【问题标题】:dplyr group_by and mutate, how to access the data frame?dplyr group_by 和 mutate,如何访问数据框?
【发布时间】:2016-08-01 19:01:59
【问题描述】:

在使用 dplyr 的“group_by”和“mutate”时,如果我理解正确的话,数据帧会根据 group_by 参数拆分为不同的子数据帧。例如,使用以下代码:

 set.seed(7)
 df <- data.frame(x=runif(10),let=rep(letters[1:5],each=2))
 df %>% group_by(let) %>% mutate(mean.by.letter = mean(x))

mean() 依次应用于与 a & e 之间的一个字母相对应的 5 个 sub-dfs 的 x 列。

所以您可以操作子 dfs 的列,但您可以自己访问子 dfs 吗?令我惊讶的是,如果我尝试:

 set.seed(7)
 data <- data.frame(x=runif(10),let=rep(letters[1:5],each=2))
 data %>% group_by(let) %>% mutate(mean.by.letter = mean(.$x))

结果不同。从这个结果,可以推断出“。” df 不连续表示子 dfs,而只是“数据”之一(group_by 函数不会改变任何东西)。
原因是我想使用一个 stat 函数,该函数将数据框作为每个 sub-dfs 的参数。 谢谢!

【问题讨论】:

  • 你可以试试?do
  • do.call(rbind, lapply(split(df, df$let), myfun))
  • 我不明白这个问题,因为接受的答案与data %&gt;% group_by(let) %&gt;% mutate(mean.by.letter = mean(x)) 产生的结果相同(除非我遗漏了什么)但可能会因为额外的do-call 而变慢跨度>
  • @docendo-discimus :对不起,如果不清楚,但我不想让它太长,所以我使用了一个过于简化的例子。而且,你是对的,在这个简单的情况下,我可以有更简单的解决方案(即你重复的那个)。但是正如我在问题的最后试图解释的那样,一旦您需要将整个子数据帧作为 stat 函数的参数(而不是像 x平均()...)

标签: r group-by dplyr


【解决方案1】:

由于 dplyr 0.8 你可以使用group_mapgroup_map 调用中的. 将代表 sub-data.frame。随着时间的推移,它的行为发生了一些变化,我们可以使用 dplyr 1.0

df <- data.frame(x=runif(10),let=rep(letters[1:5],each=2))
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
df %>%   
  group_by(let) %>%
  group_map(~mutate(., mean.by.letter = mean(x)), .keep = T) %>%  
  bind_rows()
#> # A tibble: 10 x 3
#>         x let   mean.by.letter
#>     <dbl> <chr>          <dbl>
#>  1 0.442  a              0.271
#>  2 0.0999 a              0.271
#>  3 0.669  b              0.343
#>  4 0.0167 b              0.343
#>  5 0.908  c              0.575
#>  6 0.242  c              0.575
#>  7 0.685  d              0.378
#>  8 0.0716 d              0.378
#>  9 0.883  e              0.843
#> 10 0.804  e              0.843

group_map() 在那里被引入(现在已经过时了!):

https://www.tidyverse.org/articles/2019/02/dplyr-0-8-0/ https://www.tidyverse.org/articles/2018/12/dplyr-0-8-0-release-candidate/

【讨论】:

  • 谢谢!您能否在文档中添加一个链接来解释这一点?
  • @GeoffreyPoole 你是对的,行为改变了,尽管不需要使用 do.call,bind_rows 就足够了,并且自 dplyr 1.0 以来不推荐使用不加点的keep,最好使用.keep。非常感谢指正!
【解决方案2】:

我们可以在do内使用

data %>%
    group_by(let ) %>% 
    do(mutate(., mean.by.letter = mean(.$x)))

【讨论】:

  • @Franck :感谢 Akrun 和 Frank,它运行良好!我在我的解决方案中使用了函数“do”,但没有使用变异函数,并且缺少了什么!我不得不说我对“为什么”感到有些困惑。您知道有关幕后工作原理的任何高级论文/书籍吗?你有什么解释吗?
  • @godot 它需要do 中的data.frame 输出。因此,如果您不使用mutate,它需要在do 内显式调用data.frame,但它只会为每个组提供一个值,即总结..
  • 谢谢。实际上,我不明白的不是do() 部分,而是我的第一个示例的mutate() 函数中的“点”部分:为什么group_by 的输出(所以“。” mutate) 的 data.frame 与其输入相同mean() 如何“知道” var x 是子 dfs 的列而不是主要的列?
  • @godot 我猜的不同之处在于,在第一种情况下,您从“数据”中提取列“x”,即mean(.$x) 字面上类似于mean(data$x),它不需要考虑到子数据集拆分,而在do 环境中,当您执行mean(.$x) 时,. 是子数据集,.$x 是从 subdf 中提取的列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-04
  • 2014-06-04
  • 2023-02-15
  • 2019-03-13
  • 2017-08-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多