如何在 R 中随机采样数据帧的多个连续行?

How to randomly sample multiple consecutive rows of a dataframe in R?

我有一个包含 100 行和 20 列的数据框,我想随机抽样 5 次 10 个连续的行,例如10:19、25:34 等。使用:sample_n( df, 5 ) 我能够提取 5 个唯一的、随机抽样的行,但不知道如何对连续的行进行抽样。有什么帮助吗?谢谢!

你没有提到这是否可以包括替换(即,如果你采样 10:19,你是否也可以采样 15:24?)。您也没有提及是否可以对第 91 行以上的任何内容进行采样,这意味着 10 个样本被截断(即 98,99,100 只会是连续的 3 行,除非您希望它循环回到第 1 行)。假设您可以通过替换对任何值进行采样,解决方案可以在一行中完成:

sapply(sample(1:100,5),function(x){seq(x,x+9)})

这会将序列函数应用于 5 个单独采样的数字中的每一个。输出将是一个矩阵,其中每一列都是 10 个连续行的样本,但如前所述,这些可能会重叠或超过 100。

如果你想要一个行完全不重叠的解决方案,并避免超过 100 的值,而不使高于 91 的值不太可能被采样,这实际上有点技巧,但我认为下面的代码应该工作。您不能只从 1:91 中采样而不影响随机样本的概率,因为这意味着像 100 这样的值实际上只有 1/91 的概率被采样(样本值必须为 91),而其他值不要涉及相同的约束。此解决方案使得所有行都同样可能被采样。

Rows=c(1:100,1:100)


SampleRows=matrix(0,nrow=10,ncol=5)


for(i in 1:ncol(SampleRows)){
  SampledValue=sample(Rows,1)
  RowsIndex=min(which(Rows==SampledValue))
  Sequence=Rows[RowsIndex:(RowsIndex+9)]
  SampleRows[,i]=Sequence
  Rows=Rows[!(Rows %in% Sequence)]
}

这种方法创建了一个向量,该向量从 1:100 开始排序,重复两次(可变行),稍后您会明白为什么这很重要。对于 5 次迭代(对应 5 个样本)中的每一次,我们从 Rows 中取一个采样值,它将是一个数字 1:100,然后我们找出该数字在 Rows 中的位置,并取其旁边的所有 9 个值.在第一个示例中,这将始终是 10 个连续的数字(例如 20:29)。但随后我们从 Rows 中删除这些采样值。如果我们碰巧将下一个样本作为会导致重叠的值(如 18),那么它会取而代之的样本是 (18,19,30,31,32,33,34...),因为 20:29 有被删除。我们需要在 Rows 中执行两次 1:100,这样如果我们采样一个像 99 这样的值,它会从 100 重置为 1。

如果你想在一个向量中输出,把这个放在最后

sort(as.vector(SampleRows))

让我知道这是否能解决您的问题。

df <- mtcars
df$row_nm <- seq(nrow(df))

set.seed(7)

sample_seq <- function(n, N) {
  i <- sample(seq(N), size = 1)
  
  ifelse(
    test = i + (seq(n) - 1) <= N,
    yes = i + (seq(n) - 1),
    no = i + (seq(n) - 1) - N
  )
}

replica <- replicate(n = 5, sample_seq(n = 10, N = nrow(df)))

# result
lapply(seq(ncol(replica)), function(x) df[replica[, x], ])
#> [[1]]
#>                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb row_nm
#> Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4     10
#> Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4     11
#> Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3     12
#> Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3     13
#> Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3     14
#> Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4     15
#> Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4     16
#> Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4     17
#> Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1     18
#> Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2     19
#> 
#> [[2]]
#>                   mpg cyl  disp  hp drat    wt  qsec vs am gear carb row_nm
#> Honda Civic      30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2     19
#> Toyota Corolla   33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1     20
#> Toyota Corona    21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1     21
#> Dodge Challenger 15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2     22
#> AMC Javelin      15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2     23
#> Camaro Z28       13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4     24
#> Pontiac Firebird 19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2     25
#> Fiat X1-9        27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1     26
#> Porsche 914-2    26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2     27
#> Lotus Europa     30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2     28
#> 
#> [[3]]
#>                    mpg cyl  disp  hp drat    wt  qsec vs am gear carb row_nm
#> Maserati Bora     15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8     31
#> Volvo 142E        21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2     32
#> Mazda RX4         21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4      1
#> Mazda RX4 Wag     21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4      2
#> Datsun 710        22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1      3
#> Hornet 4 Drive    21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1      4
#> Hornet Sportabout 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2      5
#> Valiant           18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1      6
#> Duster 360        14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4      7
#> Merc 240D         24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2      8
#> 
#> [[4]]
#>                    mpg cyl  disp  hp drat    wt  qsec vs am gear carb row_nm
#> Lotus Europa      30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2     28
#> Ford Pantera L    15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4     29
#> Ferrari Dino      19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6     30
#> Maserati Bora     15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8     31
#> Volvo 142E        21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2     32
#> Mazda RX4         21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4      1
#> Mazda RX4 Wag     21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4      2
#> Datsun 710        22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1      3
#> Hornet 4 Drive    21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1      4
#> Hornet Sportabout 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2      5
#> 
#> [[5]]
#>                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb row_nm
#> Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4      7
#> Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2      8
#> Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2      9
#> Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4     10
#> Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4     11
#> Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3     12
#> Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3     13
#> Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3     14
#> Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4     15
#> Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4     16

reprex package (v2.0.1)

创建于 2022-01-24

你可以这样:

#sample data
df <- data.table(value = 1:100000)

#function which sampled consecutive rows (x = dataframe, rows = nr of consecutive rows, nr = amount of times you want to sample consecutive rows)
sample_fun <- function(x, rows, nr){
  #maximum number which can be sampled
  numbers <- 1:(nrow(x) - rows)

  #randomly sample 5 numbers
  sampled.numbers <- sample(numbers, nr)
    
  #convert to vector (5 consecutive)
  sampled.rows <- lapply(sampled.numbers, function(x){seq(x, (x+rows-1), 1)})
  sampled.rows <- do.call(c, sampled.rows)
  
  #sample and return
  result <- x[sampled.rows,]
  return(result)
}  

sample_fun(x = df, rows = 5, nr = 2)