【问题标题】:dplyr 0.3.0.9000 how to use do() correctlydplyr 0.3.0.9000 如何正确使用 do()
【发布时间】:2019-06-29 00:47:42
【问题描述】:

试图重现 SO 问题的结果: dplyr: How to apply do() on result of group_by?

这是数据

person = c('Grace', 'Grace', 'Grace', 'Rob', 'Rob', 'Rob')
foods = c('apple', 'banana', 'cucumber', 'spaghetti', 'cucumber', 'banana')
eaten <- data.frame(person, foods, stringsAsFactors = FALSE)

我试图复制的结果是:

[[1]]
     [,1]     [,2]       [,3]      
[1,] "apple"  "apple"    "banana"  
[2,] "banana" "cucumber" "cucumber"

[[2]]
     [,1]        [,2]        [,3]      
[1,] "spaghetti" "spaghetti" "cucumber"
[2,] "cucumber"  "banana"    "banana" 

产生上述结果的原始代码如下,不再起作用:

> eaten %>% group_by(person) %>% do(function(x) combn(x$foods, m = 2))
Error: Results are not data frames at positions: 1, 2

尝试了几种使用do()函数的方法都没有成功。

> eaten %>% group_by(person) %>% do(combn(.$foods, m = 2))
Error: Results are not data frames at positions: 1, 2

> eaten %>% group_by(person) %>% do(.$foods, combn, m =2)
Error: Arguments to do() must either be all named or all unnamed

> eaten %>% group_by(person) %>% do((combn(.$foods, m=2)))
Error: Results are not data frames at positions: 1, 2

似乎只有下面的一个适用于警告消息:

> eaten %>% group_by(person) %>% do(as.data.frame(combn(.$foods, m = 2)))
#   person        V1        V2       V3
# 1  Grace     apple     apple   banana
# 2  Grace    banana  cucumber cucumber
# 3    Rob spaghetti spaghetti cucumber
# 4    Rob  cucumber    banana   banana
# Warning messages:
# 1: In rbind_all(out[[1]]) : Unequal factor levels: coercing to character
# 2: In rbind_all(out[[1]]) : Unequal factor levels: coercing to character

相信新版本下 do() 的行为必须有所改变。有哪些变化?使用 do() 的正确习惯用法/方式是什么?谢谢。

编辑:安装最新的 dplyr 并运行@hadley 建议的代码

packageVersion("dplyr")
[1] ‘0.3.0.2’

eaten %>% group_by(person) %>% do(x = combn(.$foods, m = 2))
# Source: local data frame [2 x 2]
# Groups: <by row>
#   
#   person          x
# 1  Grace <chr[2,3]>
# 2    Rob <chr[2,3]>

EDIT2:需要按照@hadley 的建议提取列“x”

eaten2 <- eaten %>% group_by(person) %>% do(x = combn(.$foods, m = 2))
eaten2[["x"]]
# [[1]]
# [,1]     [,2]       [,3]      
# [1,] "apple"  "apple"    "banana"  
# [2,] "banana" "cucumber" "cucumber"
# 
# [[2]]
# [,1]        [,2]        [,3]      
# [1,] "spaghetti" "spaghetti" "cucumber"
# [2,] "cucumber"  "banana"    "banana" 

【问题讨论】:

  • 我只在 dplyr 0.2 中进行了测试,并得到了关于不等因子水平的相同警告。要摆脱这些(至少在 0.2 中),您只需将您的 do 修改为:do(as.data.frame(combn(.$foods, m = 2), stringsAsFactors = FALSE )) - 希望对您有所帮助
  • 再次在 do() 中使用 stringsAsFactors 参数看起来非常不习惯和奇怪。总之,试过了。确实解决了问题。但是,想了解使用 do() 是否有合适的习惯用法以及为什么这种行为会改变(或实际上没有改变)?
  • 你需要给参数命名:eaten %&gt;% group_by(person) %&gt;% do(x = combn(.$foods, m = 2))
  • @hadley,它不起作用。
  • @KFB 提取x 列,你会得到你想要的。

标签: r dplyr


【解决方案1】:

在 Q 中移动 EDIT2 以回答以关闭问题:

对于最新的dplyr 0.3.0.2+,需要按照@hadley 的建议提取列“x”

eaten2 <- eaten %>% group_by(person) %>% do(x = combn(.$foods, m = 2))
eaten2[["x"]]
# [[1]]
# [,1]     [,2]       [,3]      
# [1,] "apple"  "apple"    "banana"  
# [2,] "banana" "cucumber" "cucumber"
# 
# [[2]]
# [,1]        [,2]        [,3]      
# [1,] "spaghetti" "spaghetti" "cucumber"
# [2,] "cucumber"  "banana"    "banana

【讨论】:

  • 使用 magrittr 1.5 你也可以做到eaten %&gt;% group_by(person) %&gt;% do(x = combn(.$foods, m = 2)) %$% x
  • @docendodiscimus,谢谢你的想法!
【解决方案2】:

显然,这是一个偏好问题/数据的用途,但我认为上述其中一种可能性对于生成可用、整洁的数据框非常聪明。使用tidyr::gather,我觉得这会返回一个对象,该对象可以明确谁在哪顿饭中吃了什么,而没有提取任何东西。

person = c( 'Grace', 'Grace', 'Grace', 'Rob', 'Rob', 'Rob' )
foods   = c( 'apple', 'banana', 'cucumber', 'spaghetti', 'cucumber', 'banana' )
eaten <- data.frame(person, foods, stringsAsFactors = FALSE)
eaten %>% group_by(person) %>% do(as.data.frame(combn(.$foods, m = 2))) %>% gather(meal, foods, -1)

返回

# Groups:   person [2]
   person meal  foods    
   <chr>  <chr> <chr>    
 1 Grace  V1    apple    
 2 Grace  V1    banana   
 3 Rob    V1    spaghetti
 4 Rob    V1    cucumber 
 5 Grace  V2    apple    
 6 Grace  V2    cucumber 
 7 Rob    V2    spaghetti
 8 Rob    V2    banana   
 9 Grace  V3    banana   
10 Grace  V3    cucumber 
11 Rob    V3    cucumber 
12 Rob    V3    banana   
> 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-15
    • 2015-10-11
    • 2018-06-19
    • 2011-12-19
    • 1970-01-01
    • 2022-06-13
    相关资源
    最近更新 更多