Skip to contents

mutate_weights applies mathematical transformations to edge weights in a netify object. this is useful for normalizing data, handling skewed distributions, creating binary networks, or applying any custom mathematical transformation to network weights.

Usage

mutate_weights(
  netlet,
  transform_fn = NULL,
  add_constant = 0,
  new_name = NULL,
  keep_original = TRUE
)

Arguments

netlet

a netify object with edge weights to transform

transform_fn

a function to apply to the weights. can be any function that takes a matrix and returns a matrix (e.g., log, sqrt, function(x) x^2). if NULL, only the add_constant operation is performed.

add_constant

numeric value to add to weights before applying transform_fn. useful for log transformations (e.g., add_constant = 1 for log(x + 1)) or shifting distributions.

new_name

optional new name for the weight variable. if provided, updates the weight attribute and descriptive labels. if NULL, keeps the original name.

keep_original

logical. if TRUE (default), preserves the original weights as a dyadic variable. if FALSE, discards original weights to save memory.

Value

a netify object with transformed weights. the original weights are optionally preserved as a dyadic variable named "original_weight".

Details

the function handles all netify object types:

  • cross-sectional: transforms the single network matrix

  • longitudinal arrays: transforms each time slice

  • longitudinal lists: transforms each time period matrix

the function automatically updates network attributes:

  • updates is_binary if transformation results in 0/1 values

  • updates detail_weight with transformation description

  • preserves all other network and nodal attributes

for longitudinal arrays, original weight preservation is not yet implemented and will show an informational message.

Author

cassy dorff, shahryar minhas

Examples

# load example data
data(icews)
icews_2010 <- icews[icews$year == 2010, ]

# create a weighted network
net <- netify(
    icews_2010,
    actor1 = "i", actor2 = "j",
    symmetric = FALSE,
    weight = "verbCoop"
)

# example 1: log transformation (common for skewed data)
net_log <- mutate_weights(
    net,
    transform_fn = log,
    add_constant = 1, # log(x + 1) to handle zeros
    new_name = "log_verbCoop"
)
print(net_log)
#>  Network data created.
#> • Unipartite
#> • Asymmetric
#> • log_verbCoop (transformed)
#> • Cross-Sectional
#> • # Unique Actors: 152
#> Network Summary Statistics:
#>           dens miss  mean recip trans
#> verbCoop 0.435    0 2.243 0.966 0.639
#> • Nodal Features: None
#> • Dyad Features: original_weight

# example 2: square root transformation (moderate skewness)
net_sqrt <- mutate_weights(
    net,
    transform_fn = sqrt,
    new_name = "sqrt_verbCoop"
)

# example 3: binarization (convert to presence/absence)
net_binary <- mutate_weights(
    net,
    transform_fn = function(x) ifelse(x > 0, 1, 0),
    new_name = "verbCoop_binary"
)
#>  network has been binarized through transformation

# example 4: standardization (z-scores)
net_std <- mutate_weights(
    net,
    transform_fn = function(x) {
        mean_x <- mean(x, na.rm = TRUE)
        sd_x <- sd(x, na.rm = TRUE)
        return((x - mean_x) / sd_x)
    },
    new_name = "verbCoop_standardized"
)

# example 5: rank transformation
net_rank <- mutate_weights(
    net,
    transform_fn = function(x) rank(x, na.last = "keep"),
    new_name = "verbCoop_ranked"
)

# example 6: power transformation
net_power <- mutate_weights(
    net,
    transform_fn = function(x) x^0.5, # square root as power
    new_name = "verbCoop_power"
)

# example 7: min-max normalization (scale to 0-1)
net_norm <- mutate_weights(
    net,
    transform_fn = function(x) {
        min_x <- min(x, na.rm = TRUE)
        max_x <- max(x, na.rm = TRUE)
        return((x - min_x) / (max_x - min_x))
    },
    new_name = "verbCoop_normalized"
)

# example 8: winsorization (cap extreme values)
net_winsor <- mutate_weights(
    net,
    transform_fn = function(x) {
        q95 <- quantile(x, 0.95, na.rm = TRUE)
        return(pmin(x, q95)) # cap at 95th percentile
    },
    new_name = "verbCoop_winsorized"
)

# example 9: only add constant (no transformation function)
net_shifted <- mutate_weights(
    net,
    add_constant = 10,
    new_name = "verbCoop_shifted"
)

# example 10: don't keep original weights to save memory
net_log_compact <- mutate_weights(
    net,
    transform_fn = log1p, # log(1 + x), handles zeros automatically
    new_name = "log1p_verbCoop",
    keep_original = FALSE
)

# example 11: longitudinal network transformation
# \donttest{
# create longitudinal network
net_longit <- netify(
    icews,
    actor1 = "i", actor2 = "j", time = "year",
    symmetric = FALSE,
    weight = "verbCoop",
    actor_time_uniform = FALSE
)

# transform across all time periods
net_longit_log <- mutate_weights(
    net_longit,
    transform_fn = log1p,
    new_name = "log_verbCoop"
)
# }

# example 12: custom transformation with multiple operations
net_custom <- mutate_weights(
    net,
    transform_fn = function(x) {
        # complex transformation: log, then standardize
        x_log <- log(x + 1)
        x_std <- (x_log - mean(x_log, na.rm = TRUE)) / sd(x_log, na.rm = TRUE)
        return(x_std)
    },
    new_name = "verbCoop_log_std"
)