如何测试社会结构是否是非随机的并且是由遗传相关性引起的——以及如何处理人口学效应

机器算法验证 r 采样 社交网络
2022-03-17 05:19:22

我正在尝试基于个人的共现来构建(无向)社交网络稍后将在此网络上应用聚类算法以找到一些不同的子组。问题是所研究的动物物种的寿命很短(或者由于捕食者而导致的死亡率很高)。这导致并非我的网络中的所有关系都可能同时存在。如果你看下图,“红色”个体在 3-4 年后几乎灭绝*,但他们有“最长”的时间“遇见”其他个体,而“蓝色”个体只有两年时间“遇见” “其他人。

在此处输入图像描述

从理论上讲,我可以假设每个人的预期寿命都不到 10 年。因此,在标记后 5 或 6 年没有捕获“红色”个体并不一定意味着它已经死亡。

如何将这种时间效应纳入社交网络?

我想回答的具体问题: 第一个问题:观察到的社交联系是否与仅通过共享空间使用解释的联系不同?即,如何测试关联是随机的还是首选的?

如果第一个问题的答案是个人之间的关联不是随机的,那么我有第二个问题......

社会结构是否与遗传相关性相关?即,密切相关的个人更经常在一起吗?(所有个体的 DNA 图谱如下)

在这里,我创建了一些结构类似于我的数据库的数据:

data <- data.frame(obs_date = c("C1","C2","C3","C4","C5","C6","C1","C2",
                                "C3","C4","C1","C2","C3","C1","C2","C3",
                                "C4","C5","C6","C7","C1","C3","C4","C5",
                                "C6","C7","C8","C3","C4","C5","C6","C7",
                                "C3","C4","C5","C6","C3","C4","C5","C3",
                                "C4","C5","C6","C5","C6","C7","C8","C5",
                                "C5","C6","C7","C8","C5","C6","C7","C7",
                                "C7","C8","C7","C8","C7","C8","C7","C8"),
                   ind_id = rep(LETTERS[1:20], times = c(6,4,3,7,1,6,5,4,
                                               3,2,2,4,1,4,3,1,2,2,2,2)),
                   obs = rep(c("seen","not_seen","seen","not_seen","seen",
                               "not_seen","seen","not_seen","seen"),
                               times = c(3,1,4,1,9,1,9,3,33)))

在这里,我添加了遗传结构。数据完全是捏造的,但它们应该反映同色个体之间密切的遗传相关性。此外, “紫色”个体是蓝色”的后代,“蓝色”绿色”的后代,“绿色”“红色”的后代。

gen.raw <- matrix(c("a","g","g","g","c","g","a","a","g","g","g","g","t","c","t","c","t","t","a","a","t","t","a","a",
                    "a","g","g","g","c","g","a","a","g","g","g","g","c","c","t","c","t","t","a","a","t","c","a","a",
                    "a","g","g","g","c","g","g","a","g","g","g","g","c","c","t","t","c","t","a","a","t","c","a","a",
                    "a","g","t","t","t","g","g","a","g","g","g","g","c","c","t","t","c","t","a","a","a","c","a","a",
                    "a","g","t","t","t","g","g","a","g","g","g","g","c","c","t","t","c","t","t","a","a","c","a","a",
                    "a","g","t","t","t","g","g","a","g","g","g","g","c","c","t","t","c","t","t","a","a","c","a","a",
                    "a","g","t","t","t","g","g","g","g","g","c","g","c","c","t","t","c","t","t","a","a","c","a","a",
                    "a","g","t","t","t","g","a","c","g","t","c","g","c","c","t","t","c","t","t","a","a","c","a","a",
                    "a","g","t","t","t","g","a","c","g","t","c","g","c","c","t","t","c","t","t","a","a","c","a","a",
                    "a","g","t","t","t","g","a","c","g","t","c","g","c","c","t","t","c","t","t","a","a","c","a","a",
                    "a","g","t","t","t","g","a","c","g","t","c","g","c","c","t","t","c","t","t","a","a","c","a","a",
                    "a","g","t","t","t","g","a","c","g","t","c","g","c","c","t","t","c","t","t","a","a","c","a","a",
                    "a","g","t","t","t","g","a","c","g","t","c","g","c","c","t","t","c","t","t","a","a","c","a","a",
                    "a","g","t","t","t","g","a","c","g","t","c","g","c","c","t","t","c","t","t","a","t","c","a","a",
                    "a","g","t","t","t","g","a","c","g","t","c","g","c","c","t","t","c","t","t","a","t","c","a","a",
                    "a","g","t","t","t","g","a","c","g","t","c","g","c","c","t","t","c","t","t","a","t","c","a","a",
                    "a","g","t","c","t","g","a","c","g","g","c","g","c","c","t","t","c","t","t","a","t","c","a","a",
                    "a","g","t","c","t","g","a","c","g","g","c","g","c","c","t","t","c","t","t","a","t","c","a","a",
                    "a","g","t","c","t","g","a","c","g","g","c","g","c","c","t","t","c","t","t","a","t","c","a","a",
                    "a","g","t","c","t","g","a","c","g","c","c","g","t","c","t","t","c","t","t","a","t","c","a","a"),
                    byrow = TRUE, ncol = 24)
rownames(gen.raw) <- LETTERS[1:20]

好的,上面给出了源数据。现在我将创建两个距离矩阵首先是从由OR-SP 索引表示的共现数据派生的关联矩阵观察到的栖息共享比例是通过将两个人一起被发现的天数除以他们可能在一起的所有可能天数来计算的(在两个人的第一次和最后一次记录之间重叠)。

# matrix of days roosting together
EG <- expand.grid(unique(data$ind_id), unique(data$ind_id))

data_seen <- subset(data, obs == "seen")

my.length.dt <- numeric(nrow(EG))
for (i in 1:nrow(EG)) {
my.length.dt[i] <- length(intersect(as.vector(data_seen$obs_date[data_seen$ind_id == EG[i, 1]]),
                                    as.vector(data_seen$obs_date[data_seen$ind_id == EG[i, 2]])))
days.together <- matrix(my.length.dt, byrow = TRUE, ncol = length(unique(data$ind_id)))
colnames(days.together) <- rownames(days.together) <- unique(data$ind_id)
}
days.together

# matrix of all possible potentional roosting days
EG <- expand.grid(unique(data$ind_id), unique(data$ind_id))
my.length.rdp <- numeric(nrow(EG))
for (i in 1:nrow(EG)) {
my.length.rdp[i] <- length(intersect(as.vector(data$obs_date[data$ind_id == EG[i, 1]]),
                                     as.vector(data$obs_date[data$ind_id == EG[i, 2]])))
roosting_days_possible <- matrix(my.length.rdp, byrow = TRUE, ncol = length(unique(data$ind_id)))
colnames(roosting_days_possible) <- rownames(roosting_days_possible) <- unique(data$ind_id)
}
roosting_days_possible

# OBSERVED ROOST-SHARING PROPORTION
OSP <- days.together/roosting_days_possible
OSP[ is.nan(OSP) ] <- 0
diag(OSP) <- 0

# So here is association matrix derived from co-occurence data
round(OSP,2)
# social distance matrix
soc_dist <- as.dist(OSP)

下一步是获取DNA序列并制作遗传相关性矩阵

# creating matrix of relatedness
library(ape)
gen.str <- as.DNAbin(gen.raw)
my.gen.dist <- dist.dna(gen.str)
fit <- hclust(my.gen.dist, method="ward")
plot(fit) # display dendogram 

最后,在这里我通过 Mantel 测试比较了社会距离和遗传距离

library(ade4)
mantel.rtest(soc_dist, my.gen.dist, nrepet = 9999)

它的结果(p > 0.05)是否意味着社会结构和遗传结构之间没有相关性?

这是回答我的问题的适当解决方案吗?有任何想法吗?

我还发现,对于社会结构,这种类型的图表可能比树状图更好。适合寻找不同的社会群体。

# Show social structure
library(igraph)
g <- graph.adjacency(OSP, weighted=TRUE, mode ="undirected")
g <- simplify(g)
# set labels and degrees of vertices
V(g)$label <- V(g)$name
V(g)$degree <- degree(g)
wc <- walktrap.community(g)
plot(wc, g)
2个回答

我认为您的问题可能与其说是方法问题,不如说是关于您试图用数据实现什么的理论问题。

如果您只对同时出现感兴趣,那么某些人比其他人有更多时间来建立联系以找到子组真的很重要吗?

现在,您可以想出一些方法来纠正一些人有更多时间与其他人“见面”的事实,因为他们更经常被抓到。您可以使用关系的强度来反映这一点。例如,您可以将平局的强度除以个人所在的观察窗口的数量。这样做的缺点是同一对中的个人的平局强度会有所不同,本质上使您的网络成为加权的有向网络,所有的联系都是互惠的。这样做的缺点是walktrap.community()函数中的算法忽略了边缘方向。这意味着您需要寻找另一种社区检测算法。

另一种减少个人“见面”时间或多或少的问题的方法是创建你的网络的几个快照,在其中你只保留在前n个时期出现的关系(你需要你对所研究物种的具体知识以及确定n的值的数据说得通)。这意味着关系会在一段时间后衰减,这将降低经常出现的个人成为最核心的趋势。缺点是您最终会获得多个反映不同时间关系状态的网络,因此您将无法为每个人获得一个稳定的社区成员资格。相反,在网络的每个快照上运行您的社区检测算法,您将更动态地了解社区成员随时间的变化。

正如我一开始所说,我认为这是一个理论问题,而不是其他任何问题。您需要问自己一些问题,例如:我为什么要将个人分类?我认为成为同一组的成员意味着什么?回答这些问题将告知您如何处理您的网络分析。

现在我将创建两个距离矩阵。首先是从由 OR-SP 索引表示的共现数据导出的关联矩阵。观察到的栖息共享比例是通过将两个人一起被发现的天数除以他们可能在一起的所有可能天数来计算的(在两个人的第一次和最后一次记录之间重叠)。

关于这一步,我认为如果您使用基于代理的建模 (ABM),您会更加成功。你描述的方法对我来说似乎很复杂,ABM 代码可能会简单——意味着更容易实现、测试、改进和验证——而且从理论和经验的角度来看也更合理您尝试创建的模型在计算社会科学领域中有些常见,其中包括 ABM 作为主要的建模/模拟方法。

我建议您使用NetLogo ( https://ccl.northwestern.edu/netlogo/ )。您的每一个人都将成为NetLogo的代理人. 每个时间步,每个代理执行一个程序,该程序确定它与环境、其他代理的交互以及其内部状态的变化。(如果您愿意,您也可以添加捕食者代理,但听起来您希望将死亡率视为每个时间步长的恒定概率,或者可能作为年龄和时间的函数。)您可以在 2D 中对代理移动进行编程物理空间(“补丁”),因此您可以模拟代理遇到其他代理并“栖息”在一起的过程。他们也可以交配和生孩子,并将他们的遗传物质作为新代理的内部状态传递。在此过程中,代理会根据您实施的任何规则形成社交网络联系。 NetLogo具有用于代理之间动态图(即社交网络)的内置功能,

对模拟进行编程后,只需在随机初始条件下运行N次,其中N选择得足够大,以使您对最终分析有足够的统计信心。您可以每T步记录数据(即您的“观察”)以模拟年度数据。 您只需要在运行结束时使用R进行统计分析。 这里有一个NetLogo扩展可以将数据导入和导出到Rhttps ://github.com/NetLogo/NetLogo/wiki/Extensions 。


您可能对这种方法有所保留,因为它涉及学习新系统和新语言(NetLogo有它自己的脚本语言)。但是,它很容易学习(许多初学者和非程序员都学习并成功使用它)。但主要的好处是您以非常直接和自然的方式对感兴趣的现象进行建模,这极大地简化了任务并大大减少了沿途出错的机会。


我通过 Mantel 测试比较了社会距离和遗传距离。

关于这一步,它认为首先确定可能的社会距离空间是一个度量空间并且它具有使其与可能基因组空间内的遗传距离相当的特征是至关重要的。在我看来,仅仅因为你有两个矩阵形式是不够的(尽管我没有这个特定测试的经验)。例如,遗传距离 = 0 表示相同的基因组,对吧?但是“社交距离=零”是什么意思?如果社交距离未定义为零,则它无法定义度量标准(参见:https ://en.wikipedia.org/wiki/Metric_space#Definition )。

其次,我认为你应该测量距离的变化你有一些初始条件,包括初始社会距离和初始遗传距离。若干年后,尽管交配、死亡和地理/社会混合,您的种群具有最终的社会距离和遗传距离。ABM 方法使这一点更加明显。


特别是关于 Mantel 检验,您还可以评估贝叶斯替代方案。来自 Wikipedia 条目:“...在存在空间自相关的情况下,Mantel 和部分 Mantel 测试可能存在缺陷并返回错误的低 p 值,参见例如 Guillot 和 Rousset,2013 [3])”贝叶斯方法可能是能够避免这个问题以及其他与零假设显着性检验 (NHST) 相关的问题。但是,我对此测试的贝叶斯方法没有具体建议。