如何在 R 中执行嵌套重采样 - 多样性指数不确定性

How to perform nested resampling in R - Diversity index uncertainty

提问人:CaptainKrabs 提问时间:8/29/2023 最后编辑:CaptainKrabs 更新时间:8/30/2023 访问量:60

问:

我目前正在尝试应用 Herrmann 等人 (2022) 中描述的重采样方法,其中包含外部和内部重采样循环:enter image description here我的数据集由 100 行 x 60 列组成。行对应于尝试 ID(每行一次尝试),列对应于物种(每列一个物种)。每个单元格表示每个物种 i 中每个尝试的个体计数 K = NiK

NiK 可能随重采样而变化,但给定尝试中所有混杂物种的个体总数(称为 NK,对应于行和)需要恒定。

让我们生成一个类似的数据帧:

df <- matrix(sample(0:15, 6000, replace = T), ncol = 60)
df

这是我用于外部循环的代码:

#Outer loop
#Resampling among the 100 tries 1000 times
seed(1234)
outer = matrix(replicate(1000, sample(1:nrow(df), nrow(df), replace = T)), ncol = 100)

现在添加内部循环,我被卡住了。 内循环在每次尝试中对给定物种的个体数量进行重采样,而外循环在内循环生成的新数据集中重新采样尝试:

i = 物种数

r = 外部重采样 ID

inner <- NULL
complete <- NULL
for (r in 1:1000) {
  for (i in 1:ncol(df)) {
    inner = cbind(inner,sample(df[,i], nrow(df), replace = T))
  }
  complete = rbind(complete, inner[outer[r,],])
  inner <- NULL
}
complete

循环工作正常,可以通过内部和外部循环生成 100 次尝试的 1000 次重采样,但我目前不知道如何将每行限制为总和 N K,这可以针对给定的尝试 K 计算

rowSums(df[K,])

有谁知道一种函数或方法,可以允许在使用内循环在每列中重新采样时保持 NK 常数?

提前感谢您的帮助,并希望我的英语和我的解释可以理解。

r 嵌套 约束 采样重采样

评论


答:

1赞 jblood94 8/29/2023 #1

使用 和 ,我们可以对一行进行重采样,并最终得到相同的总数。展示:rowSums(df)rmultinom

rs <- rowSums(df)
all(replicate(100, sum(rmultinom(1, rs[1], df[1,])) == rs[1]))
#> [1] TRUE

由于要对内部样本求和,因此对于每个外部样本,我们可以对多个行重采样进行行求和。

set.seed(1234)
K <- 100L # "tries"
N <- 60L # species
R <- 1e3L # resamples
df <- matrix(sample(0:15, N*K, replace = 1), K, N)
rs <- rowSums(df)

outer <- mapply( # outer sampling
  \(x) rowSums(
    # inner sampling
    mapply(\(i) rmultinom(1, rs[i], df[i,]), sample(nrow(df), K, 1))
  ),
  1:R
)

dim(outer)
#> [1]   60 1000

现在的每一列都对应一个外部重采样。outer

0赞 CaptainKrabs 8/29/2023 #2

感谢 jblood94 的快速回答!也许我误解了你的答案,但我的目标是用常量行和对列进行重采样,而不是用常量行和对行进行重采样。

我终于找到了解决问题的方法。我正在用错误的数据帧解决问题。

事实上,我的原始数据集看起来更像是:

ID <- sort(rep(1:100,times=c(sample(1:10, 100, replace = T))))
df <- data.frame(ID, Species.name= sample(letters[1:26], length(ID), replace = T))
df

with ID = 尝试 ID 并 Species.name 物种的识别。

使用我获得了一个类似的数据帧,如我原来的帖子中所述:acast()

 library(reshape2)
 acast(df, ID~Species.name)

适用于计算多样性指数。

尽管如此,使用 df,在保持每次尝试的个体数的同时执行嵌套采样更容易,因为个体等于一行!

工作代码:

 library(reshape2)
   library(dplyr)
#Get species complete list
sptot <- unique(df$Species.name)
length(sptot)

#Get try ID
nID <- unique((df$ID))
length(nID)

#Extract number of individuals per try to keep it constant
groupsize = df %>%
  group_by(ID)%>%
  summarise(n = n())
groupsize

#Test suitability of the inner resampling
outer = data.frame(ID = as.integer(sample(nID, length(nID), replace = T)), Ntry = 
seq(1,length(nID),1))
outerdata = left_join(outer, df, by = "ID", relationship = "many-to- 
many")

df2 = outerdata %>%
  group_by(Ntry, ID)%>%
  summarise(n = n())%>%
  left_join(groupsize, by = "ID")%>%
  mutate(diff = n.x - n.y)
mean(df2$diff) #Same number of row (individuals) per try

df3 = outerdata %>%  
  left_join(groupsize, by = "ID") %>%
  group_by(Ntry) %>%
  mutate(Sp = sample(Species.name, replace = T)) %>%
  filter(length(Sp) == n) %>%
  ungroup()
df3

check = df3 %>%
  group_by(ID, Ntry)%>%
  summarise(nfacor = length(unique(Species.name)),
            nfacsamp = length(unique(Sp)))

check$V = ifelse(check$nfacsamp <= check$nfacor, "OK", "FALSE")
check #no more unique species in resampling than in observed


#Create the loop
inner <- NULL
outer <- NULL
complete <- NULL
for (i in 1:1000) {
  #Outer resampling
  outer = data.frame(ID = as.integer(sample(nID, length(nID), replace = T), Ntry = seq(1,length(nID),1))
  outerdata = left_join(outer, df, by = "ID", relationship = "many-to-many")
  
  
  #Inner resampling
  inner = outerdata %>%  
    left_join(groupsize, by = "ID") %>%
    group_by(Ntry) %>%
    mutate(Sp = sample(Species.name, replace = T)) %>%
    filter(length(Sp) == n) %>%
    ungroup()
  inner = inner[,c("Ntry", "Sp")]
  
  #Adding missing column (i.e missing species since it is possible that 
  #some species are not resampled in a given iteration)
  sampcol <- colnames(acast(inner, Ntry ~ Sp, fun.aggregate = length))
  misscol = sub(" ", "\\.", setdiff(as.character(sptot), sampcol))
  complete = data.frame(Ntry= rownames(acast(inner, Ntry ~ Sp, fun.aggregate = length)), acast(inner, Ntry ~ Sp, fun.aggregate = length), bloc = i)
  complete[,misscol] <- 0
}
complete

然后,我们得到一个 1000 x 100 行的数据帧,其列数对应于物种,非常适合计算多样性指数。 令人讨厌的是错误消息,但它不会影响结果。acast()

根据 Herrmann 等人 (2022),我们现在需要:1) 对每个区块的列求和以获得 1000 行,每个集合物种计数在重新采样尝试中,2) 然后计算每个多样性指数的 1000 个值,并得到 Efron 95% CI。

希望这个线程能帮助某人进行类似的分析!