【问题标题】:How can dplyr generate data frame for each group after the group_by operation?group_by 操作后 dplyr 如何为每个组生成数据帧?
【发布时间】:2015-01-03 23:37:16
【问题描述】:

dplyr 包在流式数据处理中的流畅性让我非常震惊。最近我急于解决一个问题,为每个组 ID 生成一个新的数据帧,并将这些小数据帧组合成一个最终更大的数据帧。一个玩具例子:

input.data.frame %>%
    group_by(gid) %>%
    {some operation to generate a new data frame for each group} ## FAILED!!!!

在dplyr中,函数mutate为每个组添加新列和summarise为每个组生成摘要,两者都不能满足我的要求。 (我错过了什么吗?)

或者,使用plyr包的ddply,dplyr之前的交互,我可以通过

ddply(input.data.frame, .(gid), function(x) {
     some operation to generate a new data frame for each group
}

但不足之处在于,当我加载 plyr 包时,dplyr 中的某些功能将被屏蔽。

【问题讨论】:

  • 在这种情况下,您必须使用do 运算符。但是,如果您向我们展示了您最终真正想做/实现的目标,那就更好了。来自帮助文件:“您可以使用 do 执行任意计算,返回数据帧或任意对象,这些对象将存储在列表中。”
  • 很好的介绍“dplyr包在流式数据处理中的流畅性让我非常震惊。” :)
  • 顺便说一下,如果您同时加载两个包(plyr 和 dplyr),建议先加载 plyr,然后再加载 dplyr,因此“标准”包例如“summarise” 将是 dplyr,但如果您需要从 plyr 获得它,只需使用 plyr::summarise 使包明确。
  • do,这就是我要找的!!很一般的操作。哥们,谢啦。 :)

标签: r dplyr


【解决方案1】:

把我的评论变成答案..

是的,dplyr 提供了一种为每个组创建 data.frames 的方法。在分组的 data.frame / tbl 上使用 do 运算符可以让您做到这一点,更准确地说,它可以让您将任意函数应用于每个组。这记录在do 的帮助文件中:

[...] 你可以使用 do 来执行任意计算,返回一个 将存储在列表中的数据框或任意对象。这 在使用模型时特别有用:您可以拟合模型 每组使用 do 然后灵活地提取组件 另一个做或总结。

到目前为止,我的经验是,只要可以使用 mutate / summarise / mutate_each / 等专用 dplyr 函数之一,就应该优先使用它们而不是 do,因为它们通常比使用do,但当然没有那么灵活。

【讨论】:

  • 能否请您回答您的问题,以显示如何使用 do 来执行此操作的代码 sn-p?谢谢
  • @user2731872,只需查看?do 帮助页面中提供的示例部分即可。或者提供一个关于您的问题的最小示例,但是如果您提出一个新问题会更好
  • 谢谢 - 我做到了,但我一点也不聪明。所示示例的结果导致 grouped_df,而不是数据帧列表,这是我认为的原始问题:` by_cyl link
  • @user2731872,dplyr 旨在处理data.frames、data.tables、tbl_dfs 等表格数据,不适用于列表。关键是由于 dplyr 中的分组功能,通常不需要像仅使用基本 R 时那样显式地执行 split。
  • 没有实际的代码 sn-p 很难理解如何完成你所说的。
【解决方案2】:

以下是 G. Grothendieck 对类似问题的回答之后的示例。 Adding rows in `dplyr` output

首先我们生成一个包含 x 和 g 的数据框。 x中有9个随机数,g中有3组a,b,c。我们想从每组中选择 2 个最大的数字。重要的是要记住 do 需要一个数据框作为返回值。

library(dplyr)
set.seed(1)
dat <- data.frame(x=runif(9),g=rep(letters[1:3],each=3))

dat
      x g
1 0.1765568 a
2 0.6870228 a
3 0.3841037 a
4 0.7698414 b
5 0.4976992 b
6 0.7176185 b
7 0.9919061 c
8 0.3800352 c
9 0.7774452 c

## this works
dat %>% dplyr::group_by( g ) %>% do( data.frame(x=tail(sort(.$x),2)) )

## this works too
dat %>% dplyr::group_by( g ) %>% do( .[tail(order(.$x),2),] )

          x      g
      (dbl) (fctr)
1 0.3841037      a
2 0.6870228      a
3 0.7176185      b
4 0.7698414      b
5 0.7774452      c
6 0.9919061      c

## no error, but x is treated as a 1x1 data frame
dat %>% dplyr::group_by( g ) %>% do( x=tail(sort(.$x),2) )
       g        x
  (fctr)    (chr)
1      a <dbl[2]>
2      b <dbl[2]>
3      c <dbl[2]>

## you need a function to do more complicated stuff 
top2x <- function(df) { df[tail(order(df$x),2),] }
dat %>% dplyr::group_by( g ) %>% do( top2x(.) )

【讨论】:

    猜你喜欢
    • 2016-07-01
    • 2015-03-18
    • 2022-08-14
    • 2014-07-09
    • 2021-10-01
    • 1970-01-01
    • 2016-03-06
    • 2023-01-18
    • 1970-01-01
    相关资源
    最近更新 更多