首页 文章

在数据帧中为每组采样n个随机行

提问于
浏览
22

从这些问题 - Random sample of rows from subset of an R dataframeSample random rows in dataframe我可以很容易地看到如何从df或'n'行中随机采样(选择)'n'行,这些行来自df中特定级别的因子 .

以下是一些示例数据:

df <- data.frame(matrix(rnorm(80), nrow=40))
df$color <-  rep(c("blue", "red", "yellow", "pink"), each=10)

df[sample(nrow(df), 3), ] #samples 3 random rows from df, without replacement.

例如,只需从'pink'颜色中抽取3个随机行 - 使用 library(kimisc)

library(kimisc)
sample.rows(subset(df, color == "pink"), 3)

或编写自定义功能:

sample.df <- function(df, n) df[sample(nrow(df), n), , drop = FALSE]
sample.df(subset(df, color == "pink"), 3)

但是,我想从每个级别的因子中抽取3(或n)个随机行 . 即新的df将有12行(蓝色3个,红色3个,黄色3个,粉红色3个) . 显然可以多次运行,为每种颜色创建newdf,然后将它们绑定在一起,但我正在寻找一种更简单的解决方案 .

5 回答

  • 7

    您可以使用 ave 为具有特定因子级别的每个元素分配随机ID . 然后,您可以选择特定范围内的所有随机ID .

    rndid <- with(df, ave(X1, color, FUN=function(x) {sample.int(length(x))}))
    df[rndid<=3,]
    

    这样做的好处是可以保留原始行顺序和行名称,如果这是您感兴趣的话 . 另外,您可以相当容易地重复使用 rndid 向量来创建不同长度的子集 .

  • 5

    dplyr 0.3及更高版本中,这可以正常工作:

    df %>% group_by(color) %>% sample_n(size = 3)
    

    旧版本的dplyr(版本<= 0.2)

    我开始使用 dplyr 来回答这个问题,假设这会起作用:

    df %.% group_by(color) %.% sample_n(size = 3)
    

    但事实证明,在0.2中存在 sample_n.grouped_df S3方法,但从未派遣过't registered in the NAMESPACE file, so it' . 相反,我必须这样做:

    df %.% group_by(color) %.% dplyr:::sample_n.grouped_df(size = 3)
    Source: local data frame [12 x 3]
    Groups: color
    
                X1         X2  color
    8   0.66152710 -0.7767473   blue
    1  -0.70293752 -0.2372700   blue
    2  -0.46691793 -0.4382669   blue
    32 -0.47547565 -1.0179842   pink
    31 -0.15254540 -0.6149726   pink
    39  0.08135292 -0.2141423   pink
    15  0.47721644 -1.5033192    red
    16  1.26160230  1.1202527    red
    12 -2.18431919  0.2370912    red
    24  0.10493757  1.4065835 yellow
    21 -0.03950873 -1.1582658 yellow
    28 -2.15872261 -1.5499822 yellow
    

    据推测,这将在未来的更新中修复 .

  • 5

    我会考虑my stratified function,目前作为GitHub Gist托管 .

    得到它:

    library(devtools)  ## To download "stratified"
    source_gist("https://gist.github.com/mrdwab/6424112")
    

    并使用它:

    stratified(df, "color", 3)
    

    有几种不同的功能便于分层采样 . 例如,您也可以采取样品“即时” .

    stratified(df, "color", 3, select = list(color = c("blue", "red")))
    

    为了让您了解函数的作用,以下是 stratified 的参数:

    • df :输入 data.frame

    • group :构成"strata"的一列或多列的字符向量 .

    • size :所需的样本量 .

    • 如果 size 是小于1的值,则从每个层中取出一个比例样本 .

    • 如果 size 是1或更大的单个整数,则从每个层中获取该样本数 .

    • 如果 size 是整数向量,则为每个层获取指定数量的样本 . 建议您使用命名向量 . 例如,如果您有两个层,"A"和"B",并且您想要"A"中的5个样本和"B"中的10个样本,则应输入 size = c(A = 5, B = 10) .

    • select :这允许您在采样过程中对组进行子集化 . 这是 list . 例如,如果您的 group 变量是"Group",并且它包含三个层,"A","B"和"C",但您只想从"A"和"C"进行采样,则可以使用 select = list(Group = c("A", "C")) .

    • replace :用于替换采样 .

  • 0

    这是一个解决方案 . 我们将data.frame拆分为颜色组 . 从每个这样的组中,我们采样3行 . 结果,我们获得了data.frames列表 .

    df2 <- lapply(split(df, df$color),
       function(subdf) subdf[sample(1:nrow(subdf), 3),]
    )
    

    然后data.frames列表应合并为1 data.frame:

    do.call('rbind', df2)
    ##                    X1          X2  color
    ## blue.3    -1.22677188  1.25648082   blue
    ## blue.4    -0.54516686 -1.94342967   blue
    ## blue.1     0.44647071  0.16283326   blue
    ## pink.40    0.23520296 -0.40411906   pink
    ## pink.34    0.02033939 -0.32321309   pink
    ## pink.33   -1.01790533 -1.22618575   pink
    ## red.16     1.86545895  1.11691250    red
    ## red.11     1.35748078 -0.36044728    red
    ## red.13    -0.02425645  0.85335279    red
    ## yellow.21  1.96728782 -1.81388110 yellow
    ## yellow.25 -0.48084967  0.07865186 yellow
    ## yellow.24 -0.07056236 -0.28514125 yellow
    
  • 23

    这是一种基础方式,允许多个组和替换采样:

    n <- 3
    resample <- TRUE
    index <- 1:nrow(df)
    fun <- function(x) sample(x, n, replace = resample)
    a <- aggregate(index, by = list(group = df$color), FUN = fun )
    
    df[c(a$x),]
    

    要添加另一个组,请将其包含在“by”参数中以进行聚合 .

相关问题