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. for multilayer networks, supply one name per layer.

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 (or original_weight_<layer> for each layer of a multilayer network).

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

  • multilayer networks: transforms each layer separately

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
#> log_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"
)