当前位置: 首页 > 知识库问答 >
问题:

使用 dplyr 从数据帧中抽取子组的示例行

郑帅
2023-03-14

如果我想从不同的组中随机选择一些样本,我使用plyr包和下面的代码

require(plyr)
sampleGroup<-function(df,size) {
  df[sample(nrow(df),size=size),]
}

iris.sample<-ddply(iris,.(Species),function(df) sampleGroup(df,10))

这里从每个物种中选取10个样本。

我的一些数据帧非常大,我的问题是我可以对dplyr包使用相同的srovGroup函数吗?或者有另一种方法可以在dplyr中做同样的事情?

编辑

dplyr 包的 0.2 版引入了两个新功能,用于从表中选择随机行sample_n和sample_frac

共有3个答案

晋涛
2023-03-14

这是个好问题!对于dplyr,没有任何简单的方法可以使用文档化的语法来实现这一点,但作为一种变通方法,这又如何呢?

sampleGroup<-function(df,x=1){

  df[
    unlist(lapply(attr((df),"indices"),function(r)sample(r,min(length(r),x))))
    ,]

}

sampleGroup(iris %.% group_by(Species),3)

#Source: local data frame [9 x 5]
#Groups: Species
#
#    Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
#39           4.4         3.0          1.3         0.2     setosa
#16           5.7         4.4          1.5         0.4     setosa
#25           4.8         3.4          1.9         0.2     setosa
#51           7.0         3.2          4.7         1.4 versicolor
#62           5.9         3.0          4.2         1.5 versicolor
#59           6.6         2.9          4.6         1.3 versicolor
#148          6.5         3.0          5.2         2.0  virginica
#103          7.1         3.0          5.9         2.1  virginica
#120          6.0         2.2          5.0         1.5  virginica

编辑 - 性能比较

这是一个测试,针对1m行,26组使用data.table(本机和函数调用,如示例所示)。

本机数据.表的速度大约是 dplyr 解决方法的 2 倍,并且也比带标注的 data.table 调用快 2 倍。因此,可能 dplyr / data.table 的性能大致相同。

希望dplyr的家伙很快会给我们提供一些本地语法来进行采样!(或者更好,也许它已经在那里了)

sampleGroup.dt<-function(df,size) {
  df[sample(nrow(df),size=size),]
}

testdata<-data.frame(group=sample(letters,10e5,T),runif(10e5))

dti<-data.table(testdata)

# using the dplyr workaround with external function call
system.time(sampleGroup(testdata %.% group_by(group),10))
#user  system elapsed 
#0.07    0.00    0.06 

#using native data.table
system.time(dti[dti[,list(val=sample(.I,10)),by="group"]$val])
#user  system elapsed 
#0.04    0.00    0.03 

#using data.table with external function call
system.time(dti[, sampleGroup.dt(dti, 10), by=group])
#user  system elapsed 
#0.06    0.02    0.08 
狄旻
2023-03-14

这对于data.table来说很容易做到,对于一张大桌子也很有用。

注:正如Troy在文章中提到的,有一种更有效的方法可以使用数据来实现这一点。表,但我想尊重答案中的OP示例函数和格式。

require(data.table)
DT <- data.table(x = rnorm(10e6, 100, 50), y = letters)

sampleGroup<-function(df,size) {
  df[sample(nrow(df),size=size),]
}

result <- DT[, sampleGroup(.SD, 10), by=y]
print(result)

# y         x y
# 1: a  30.11659 m
# 2: a  57.99974 h
# 3: a  58.13634 o
# 4: a  87.28466 x
# 5: a  85.54986 j
# ---              
# 256: z 149.85817 d
# 257: z 160.24293 e
# 258: z  26.63071 j
# 259: z  17.00083 t
# 260: z 130.27796 f

system.time(DT[, sampleGroup(.SD, 10), by=y])
# user  system elapsed 
# 0.66    0.02    0.69 

Using the iris dataset:
iris <- data.table(iris)
iris[,sampleGroup(.SD, 10), by=Species]
公良照
2023-03-14

可以,您可以使用dplyr:

mtcars %>% 
    group_by(cyl) %>%
    slice_sample(n = 2))

结果是这样的

Source: local data frame [6 x 11]
Groups: cyl

   mpg cyl  disp  hp drat    wt  qsec vs am gear carb
1 24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
2 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
3 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
4 17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
5 14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
6 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8

历史注释:slice_sample()替换dplyr 1.0.0(2020年5月)中的sample_n()。dplyr的早期版本需要do(sample_n(.,2))

 类似资料:
  • 我想做的是... 但是这并不完全有效,因为colSums()的结果不是数据帧。如果我投了它,它就起作用了: 但最后做(...)比特似乎很笨拙。 我没有费心进行复制,只是使用system.time()获得了一个粗略的度量。从外观上看,dplyr和data.table在我的数据集上的表现大致相同,而且如果使用得当,两者都比我昨天提出的hack解决方案要快得多。

  • 我有数据,其中因子标签已提供在单独的文件。因此,当我读到里面的东西时,我得到的数据如下所示: 和包含factor_x标签的单独数据帧,如下所示: 我正在寻找一种有效的方法来更新数据帧'data'中的factor_x_labels'中的标签。 我一直试图使用forcats包中的fct_recode或dplyr中的recode,但遇到了麻烦,因为(例如)现有的和更新的标签需要作为字符串粘贴,但需要用=

  • 我正在生成1和0的数据帧,如下所示: 由reprex软件包(v0.1.1.9000)于2018-01-08创建。 我需要按变量的总和升序排列,然后按每个变量的降序排列。使用相当简单。然而,我想有一个更稳健的安排方法。例如,如果更改为,那么最后一行也必须更改为。我尝试使用整齐的选择器进行排列,就像使用函数一样,但出现以下错误: 由reprex软件包(v0.1.1.9000)于2018-01-08创建

  • 我有一个如下所示的数据帧: 我需要提取lat=30.75和lon 76.25的行,对于我使用的行: 但这表明了这个错误:

  • 问题内容: 我有一个如下所示的pandas数据框,并通过一列保存数据组: 现在,我想创建新的数据框(名为df_w,df_x,df_y,df_z),这些数据框仅保存其原始数据中的数据,并在一些可迭代的列表(例如列表)中进行最佳组合: 有没有使用groupby,apply和/或applymap和函数来实现此目的的智能(矢量化熊猫)方法? 我当时正在考虑对数据框进行迭代,但这似乎不是很优雅。 预先感谢您

  • 数据框是这样的 我想提取每个“名称”的前三名考试分数,并使用apply()或dplyr rowwise()函数找到它们的平均值。