用于从每个类别中一次随机删除一个数据点的 R 函数?

R function for randomly removing one data point at a time from each category?

我正在尝试分析估算珊瑚礁覆盖率百分比如何随着用于分析珊瑚礁变化的点数而变化。我的实际数据集包含 150 张照片,每张照片有 50 个点。这个想法是让 R 估计所有这些点的覆盖百分比,然后从每张照片中删除 1 个点并重新分析,然后删除另一个点并重新分析等

欢迎任何有关我如何编写或查找或在哪里可以找到这样的函数的帮助,因为我对这一切都很陌生!下面是一个样本数据集,只有 3 个图,每个图有 5 个点。因此,如前所述,想法是分析所有点,然后随机每个图中删除一个点,重新分析并重复。基本上这个样本第一次分析将是 15 个点,下一次分析将是总共 12 个地块等

示例数据集:

Plot ID
1    S
1    S
1    S
1    T
1    T
2    S
2    C
2    C
2    SP
2    S
3    S
3    T
3    T
3    C
3    T

谢谢!

基础 R

set.seed(42)
dat[ave(rep(TRUE, nrow(dat)), dat$Plot, 
        FUN = function(z) length(z) > 1 & !seq_along(z) %in% sample(length(z), 1)),]
#    Plot ID
# 2     1  S
# 3     1  S
# 4     1  T
# 5     1  T
# 6     2  S
# 7     2  C
# 8     2  C
# 9     2 SP
# 12    3  T
# 13    3  T
# 14    3  C
# 15    3  T

我添加了确保最小大小为 1 (length(z) > 1) 的逻辑,如果您有不同的需求,您可能希望提高这一点,或者如果您不关心删除一个,则删除该条件Plot 当它只有一行时。

dplyr

library(dplyr)
set.seed(42)
dat %>%
  group_by(Plot) %>%
  sample_n(n() - 1) %>%
  ungroup()
# # A tibble: 12 x 2
#     Plot ID   
#    <int> <chr>
#  1     1 S    
#  2     1 T    
#  3     1 T    
#  4     1 S    
#  5     2 C    
#  6     2 SP   
#  7     2 S    
#  8     2 C    
#  9     3 S    
# 10     3 C    
# 11     3 T    
# 12     3 T    

这是一个基础 R 函数 tapply/sample
它的参数是 data.frame 和分组列。

sample_rows <- function(data, group){
  group <- as.character(substitute(group))
  tapply(seq_len(nrow(data)), data[[group]], \(x) sample(x, 1))
}

set.seed(2021)

i <- sample_rows(df1, Plot)
df2 <- df1[-i, ]
nrow(df2)
#[1] 12

i <- sample_rows(df2, Plot)
df2 <- df2[-i, ]
nrow(df2)
#[1] 9

数据

df1 <-
structure(list(Plot = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 
3L, 3L, 3L, 3L, 3L), ID = c("S", "S", "S", "T", "T", "S", "C", 
"C", "SP", "S", "S", "T", "T", "C", "T")), class = "data.frame", 
row.names = c(NA, -15L))