knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

Within experimental designs, sampling via a given method is considered similarly to other "building blocks" manipulations. Conceptually, they also:

  1. take a theoretical scanList as an input
  2. alter it in some way:
    • group-scan sampling can lead to missing some edges: they are turned into NA in the scanList regardless of them being 1 or 0 originally
    • focal(-scan) sampling allows to sample all edges involving the focal, but misses all the others: they are also turned to NAs
  3. and return an empirical scanList

Designin a sampling method

Designing a sampling method - or creating a expDesign object in SimuNet - relies on design_sampling():

See below to see how to specify varied sampling designs. Sampling can be only part of the overall experimental design, and for instance follow a sequence of other manipulations. See them in action in the following examples!

Group-scan sampling

Group-scan sampling is the act of looking at the whole group during scans, and seeing who is associated/interacting with whom.

library(SimuNet)
design_sampling(method = "group",sampling = "random")

The returned expDesign can be passed to design_exp() to make it a component of a larger experimental design:

group.rand <- design_sampling(method = "group",sampling = "random")
design_exp(remove_mostPeripheral,group.rand)
# or 
design_exp(remove_mostPeripheral,design_sampling(method = "group",sampling = "random"))

Let's apply it to a scanList:

set.seed(42)
n <- 5L
samp.effort <- 100L
Adj <- sample(1:samp.effort,n * n) |>
  matrix(nrow = 5,dimnames = list(letters[1:n],letters[1:n]))
Adj[lower.tri(Adj,diag = TRUE)] <- 0L
Adj

sL.group <- simunet(Adj,samp.effort,"upper",10,group.rand)
sL.group

sL <- simunet(Adj,samp.effort,"upper",10)
sL |> perform_exp(group.rand)

We can for instance compare the second scan before and after group-scan sampling:

sL.group$theoretical.scanList[,,2]
sL.group[,,2]

As you can see, the edge present between nodes b and e has been missed, but not the ones between a and b.

Types of group-scan sampling

obs.P can be defined via several routines

Random probabilities

Like in the previous example, observation probabilities can be determined at random. Input sampling as the character string "random"

design_sampling("group",sampling = "random")

Note that with sampling = "random", obs.P is randomly drawn before being applied to a scanList, but that for all scans the same obs.P is used to mask edges.

sL |> perform_exp(group.rand) |> attrs("obs.P")  # Retrieve the obs.P drawn and applied to the same
sL |> perform_exp(group.rand) |> attrs("obs.P")  # scanList.

Constant probability

All probabilities can be set to a constant probability. Input this constant as the sampling argument:

group.cst <- design_sampling("group",sampling = 0.8)  # an edge has 80% chances of being observed

group.cst
sL.cst <- sL |> perform_exp(group.cst)
sL.cst
sL.cst |> count_nonNA()

# Inputting `sampling` as the string "constant" returns an error leading to inputting the constant
# sL |> perform_exp(design_sampling("group",sampling = "constant"))

Determined from a user-defined function

By inputting a function of Adj returning a similarly-dimensioned probability matrix, you can design several routines. To do so, pass the function as the samplingargument

central.bias_fun <- function(Adj) {
  str <- 
    Adj |>
    igraph::graph.adjacency(mode = "upper",weighted = TRUE) |> 
    igraph::strength()
  obs.P <- str %o% str
  diag(obs.P) <- 0
  obs.P / (max(obs.P) + 1)
}
central.bias_fun(Adj) # each edge presence probability is the product of the nodes' strength

group.bias <- design_sampling("group",sampling = central.bias_fun)

sL.bias <- sL |> perform_exp(group.bias)
sL.bias
sL.bias |> count_nonNA()
sL.bias$obs.P  # you can note that obs.P is internally a triangular matrix like Adj

sL |> scale_scans()
sL.bias |> scale_scans()

Focal(-scan) sampling

Focal(-scan) sampling is the act of following a focal individual, and record all associations/interactions involving it.

A focal-scan sampling would be recording data "on the tick", but focal scans can also be defined as continuous.

We argue that by dividing a continuous focal sampling into segments and observing association within each segments, one can "binarize" a continuous sampling into a scan equivalent, should it require dividing the continuous scan into the smallest segments sampling resolution allows (e.g. each minute).

## randomly select focals
focal.rand <- design_sampling(method = "focal",sampling = "random")

sL.foc <- sL |> perform_exp(focal.rand)
sL.foc
sL.foc |> attrs("focalList")

We can again compare for instance the fifth scan before and after focal-scan sampling:

sL.foc$theoretical.scanList[,,5]
sL.foc[,,5]

Types of focal-scan sampling

focalList can be defined via several routines

Random probabilities

Like in the previous example, focals can be selected at random. Input sampling as the character string "random"

## randomly select focals
design_sampling(method = "focal",sampling = "random")

Again, note that with sampling = "random", focalList is randomly drawn before being applied to a scanList.

sL |> perform_exp(focal.rand) |> attrs("focalList")  # Retrieve the focalList drawn and applied to 
sL |> perform_exp(focal.rand) |> attrs("focalList")  # the same scanList.

Even focal list

Efforts can be made to draw a focal list as evenly as possible (each node is sampled almost as many time). Input sampling as the character string "even" (the default).

## randomly select focals
focal.even <- design_sampling(method = "focal",sampling = "even")

sL.even <- sL |> perform_exp(focal.even)
sL.even
sL.even$focalList

Determined from a user-defined function

By inputting a function of Adj returning a probability vector (which length is the number of nodes), you can design several focal selection routines. To do so, pass the function as the samplingargument

trait_bias <- function(Adj) {
  n <- nrow(Adj)
  1:n # imagine the node index to be a trait that biases (favors) the selection of the node as focal
}
trait_bias(Adj) # 

focal.bias <- design_sampling("focal",sampling = trait_bias)

sL.bias <- sL |> perform_exp(focal.bias)
sL.bias
sL.bias |> count_nonNA()
sL.bias$focalList

sL |> scale_scans()
sL.bias |> scale_scans()


R-KenK/SimuNet documentation built on Oct. 22, 2021, 1:27 a.m.