【问题标题】:Return a list in dplyr mutate()在 dplyr mutate() 中返回一个列表
【发布时间】:2014-03-05 00:31:18
【问题描述】:

在我的实际问题中,我有一个返回列表的函数。有没有办法将它与 dplyr mutate() 一起使用?这个玩具示例不起作用-:

it = data.table(c("a","a","b","b","c"),c(1,2,3,4,5), c(2,3,4,2,2))

myfun = function(arg1,arg2) {

temp1 = arg1 + arg2
temp2 = arg1 - arg2
list(temp1,temp2)

}

myfun(1,2)

it%.%mutate(new = myfun(V2,V3))

我看到它在 new 变量的第一个“列”中循环函数的输出,但不明白为什么。

谢谢!

【问题讨论】:

  • 目前不支持,下一个版本的dplyr会支持。 (至少对于 data.frames,鉴于 Arun 的 cmets,尚不清楚 data.table 是否允许您将列表用作列)
  • @hadley,data.tablehomepage 上的第一行是:“快速子集、快速分组、快速分配、快速有序连接和 list columns,语法简短灵活”。它确实支持。鉴于他提到输出正在“循环”,我猜布罗迪的回答是他所期待的。 RonRich,请告诉我们输出应该是什么样子。
  • brodie 的输出是正确的。我将发布一个带有 data.table 方向的新问题,以更清楚地说明我的现实问题。
  • @Arun 明白了——我只是很困惑,因为 data.table 通常会将列表变成列

标签: r data.table dplyr


【解决方案1】:

使用data.table 执行此操作的惯用方法是使用:=(通过引用赋值)运算符。这是一个插图:

it[, c(paste0("V", 4:5)) := myfun(V2, V3)]

如果你真的想要一份清单,何乐而不为:

as.list(it[, myfun(V2, V3)])

或者,也许这就是你想要的,但你为什么不直接使用data.table 功能:

it[, c(.SD, myfun(V2, V3))]
#    V1 V2 V3 V4 V5
# 1:  a  1  2  3 -1
# 2:  a  2  3  5 -1
# 3:  b  3  4  7 -1
# 4:  b  4  2  6  2
# 5:  c  5  2  7  3    

请注意,如果 myfun 为其输出命名,则名称将显示在最终结果列中:

#    V1 V2 V3 new.1 new.2
# 1:  a  1  2     3    -1
# 2:  a  2  3     5    -1
# 3:  b  3  4     7    -1
# 4:  b  4  2     6     2
# 5:  c  5  2     7     3    

【讨论】:

  • @Arun,喘不过气来!何时实施多变量就地修改?我一直在为此而苦恼。
  • @BrodieG Looong 很久以前 :) 也许是 1.8.6 或更早版本?
  • 我不确定这是 OP 想要的。如果myfun 返回一个线性模型怎么办?
  • @hadley,试试:data.table(a=1:3, b=list(1, list("hello", "goodbye"), 3)),但我还没有测试过这会表现得多么优雅......此外,完全不清楚 OP 想要什么,但基于他给出的具体示例看起来他正在返回与原始列长度相同的向量,所以我怀疑他是否正在考虑返回不符合要求的对象。
  • @hadley,更直接:it[, list(list(myfun(V2, V3))), by=rep(1, nrow(it))] 其中myfun 返回一个lm 对象。
【解决方案2】:

鉴于这个问题的标题,我想我会发布一个使用dplyr::mutatetidyverse 解决方案。注意myfun 需要输出data.frame 才能工作。


library(tidyverse)

it = data.frame(
  v1 = c("a","a","b","b","c"),
  v2 = c(1,2,3,4,5), 
  v3 = c(2,3,4,2,2))

myfun = function(arg1,arg2) {

  temp1 = arg1 + arg2
  temp2 = arg1 - arg2
  data.frame(temp1, temp2)

}

it %>% 
  nest(data = c(v2, v3)) %>% 
  mutate(out = map(data, ~myfun(.$v2, .$v3))) %>% 
  unnest(cols = c(data, out))
#> # A tibble: 5 x 5
#>   v1       v2    v3 temp1 temp2
#>   <fct> <dbl> <dbl> <dbl> <dbl>
#> 1 a         1     2     3    -1
#> 2 a         2     3     5    -1
#> 3 b         3     4     7    -1
#> 4 b         4     2     6     2
#> 5 c         5     2     7     3

reprex package (v0.3.0) 于 2020 年 2 月 4 日创建

【讨论】:

    【解决方案3】:

    mutate() 函数旨在将新列添加到现有数据框中。数据框是相同长度的向量列表。因此,您不能将列表添加为新列,因为列表不是向量。

    您可以将函数重写为两个函数,每个函数都返回一个向量。然后使用 mutate() 分别应用它们中的每一个,它应该可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多