association_data: a K x N matrix of K groups (observations, gathering events, etc.) and N individuals (all individuals that are present in at least one group) OR a K x N x N array of sampling periods.
data_format: "GBI" expect a group by individual matrix, "SP" Expect a sampling periods array
permutations: number of permutations (default = 1000)
returns: number of swaps to perform between each association matrix that is returned (default = 1)
association_index: "SRI" Simple ratio index, "HWI" Half-weight index (more to come)
association_matrix: provide a starting association matrix (see details)
identities: N vector of identifiers for each individual (column) in the group by individual matrix
which_identities: vector of identities to include in the network (subset of identities)
times: K vector of times defining the middle of each group/event
occurrences: N x S matrix with the occurrence of each individual in each sampling period (see details) containing only 0s and 1s
locations: K vector of locations defining the location of each group/event
which_locations: vector of locations to include in the network (subset of locations)
start_time: element describing the starting time for inclusion in the network (useful for temporal analysis)
end_time: element describing the ending time for inclusion in the network (useful for temporal analysis)
classes: N vector of types or class of each individual (column) in the group by individual matrix (for subsetting)
which_classes: vector of class(es)/type(s) to include in the network (subset of classes)
days: K vector of day stamp for each event (can be integer or string representing any period of time)
within_day: if TRUE then permutations will be done within the time periods
within_location: if TRUE then permutations will be done within the given locations
within_class: if TRUE then permutations will be done within the given classes
enter_time: N vector of times when each individual entered the population
exit_time: N vector of times when each individual departed the population
symmetric: Boolean to ensure that permutations maintain symmetry within sampling periods if using data_format="SP"
trialSwap: Boolean to include trial swaps (if true, then every attempted permutation is returned)
Details
Performs permutations on the group by individual matrix as given by Whitehead (2008). In order to save computing, only the recently swapped individuals are recalculated, hence why the association matrix of the original data can be provided or is recalculated.
This implementation allows permutations (swaps) to be restricted to within any of three classes. Though each class is labelled, the function is flexible. Hence, days can represent any time period (months, hours, etc.).
Swaps are implemented in a hybrid between the trial swaps proposed by Miklos and Podani (2004) and full swaps (a swap every permutation). Every permutation, a candidate edge is selected (as opposed to a dyad which could or could not have an edge, as proposed by Miklos and Podani). Then a second possible dyad is selected, from all dyads. If the selected portions of the data satisfy the baseline rules (e.g. the checkerboard pattern), then either the selection is attempted again trialSwap = FALSE or not trialSwap = TRUE. This should be set to TRUE, but the option for FALSE is provided for legacy analyses (full swap).
See get_network function for additional details on each field.
Returns
Returns a p x N x N stack of matrices with the dyadic association rates of each pair of individuals after each swap or after a number of swaps, where p = ceiling(permutations/returns)
References
Whitehead (2008) Analyzing Animal Societies
Author(s)
Damien R. Farine
Examples
### USING TIMES, ETC.data("group_by_individual")data("times")# subset GBI (to reduce run time of the example)gbi <- gbi[,1:80]## define to 2 x N x N network to hold two association matricesnetworks <- array(0, c(2, ncol(gbi), ncol(gbi)))## calculate network for first half of the timenetworks[1,,]<- get_network(gbi, data_format="GBI", association_index="SRI", times=times, start_time=0, end_time=max(times)/2)networks[2,,]<- get_network(gbi, data_format="GBI", association_index="SRI", times=times, start_time=max(times)/2, end_time=max(times))## calculate the weighted degreelibrary(sna)deg_weighted <- degree(networks,gmode="graph", g=c(1,2), ignore.eval=FALSE)## perform the permutations constricting within hour of observation## note permutations are limited to 10 to reduce runtimenetwork1_perm <- network_permutation(gbi, data_format="GBI", association_matrix=networks[1,,], times=times, start_time=0, end_time=max(times)/2, days=floor(times/3600), within_day=TRUE, permutations=10)network2_perm <- network_permutation(gbi, data_format="GBI", association_matrix=networks[2,,], times=times, start_time=max(times)/2, end_time=max(times), days=floor(times/3600), within_day=TRUE, permutations=10)## calculate the weighted degree for each permutationdeg_weighted_perm1 <- degree(network1_perm,gmode="graph", g=c(1:10), ignore.eval=FALSE)deg_weighted_perm2 <- degree(network2_perm,gmode="graph", g=c(1:10), ignore.eval=FALSE)detach(package:sna)## plot the distribution of permutations with the original data overlaidpar(mfrow=c(1,2))hist(colMeans(deg_weighted_perm1),breaks=100, main=paste("P = ", sum(mean(deg_weighted[,1])< colMeans(deg_weighted_perm1))/ncol(deg_weighted_perm1)), xlab="Weighted degree", ylab="Probability")abline(v=mean(deg_weighted[,1]), col='red')hist(colMeans(deg_weighted_perm2),breaks=100, main=paste("P = ", sum(mean(deg_weighted[,2])< colMeans(deg_weighted_perm2))/ncol(deg_weighted_perm2)), xlab="Weighted degree", ylab="Probability")abline(v=mean(deg_weighted[,2]), col='red')#### DOUBLE PERMUTATION EXAMPLE (see Farine & Carter 2021)## Load datadata("group_by_individual")data("times")# subset GBI (to reduce run time of the example)gbi <- gbi[,1:40]# Specify metricmetric <-"DEGREE"# calculate observed networknetwork <- get_network(gbi, data_format="GBI", association_index="SRI", times=times)# Calculate observed metric (degree)degrees <- rowSums(network)# Do randomisation (as above, permutations should be >=1000)networks.perm <- network_permutation(gbi, data_format="GBI", association_matrix=network, times=times, permutations=10)# Now calculate the same metric on all the random networksdegrees.rand <- apply(networks.perm,1,function(x){ rowSums(x)})# Now substract each individual's median from the observeddegree.controlled <- degrees - apply(degrees.rand,1,median)#### Now use degree.controlled for any later test. For example, to related against a trait:# Make a traittrait <- rnorm(length(degree.controlled))# get the coefficient of this:coef <- summary(lm(degree.controlled~trait))$coefficients[2,3]# Compare this to a node permutation # (here just randomising the trait values)# note this should be done >= 1000 timesn.node.perm <-10coefs.random <- rep(NA, n.node.perm)for(i in1:n.node.perm){ trait.random <- sample(trait) coefs.random[i]<- summary(lm(degree.controlled~trait.random))$coefficients[2,3]}# calculate P value (note this is only one sided)P <- sum(coef <= coefs.random)/n.node.perm