【问题标题】:Assigning names to the list output of dplyr do operation为 dplyr do 操作的列表输出分配名称
【发布时间】:2014-03-26 07:36:05
【问题描述】:

dplyr 包中的do 函数通常会生成列表。有没有办法根据do 的输入为该列表分配名称?具体来说,我传递了group_by 结果,并希望列表的名称能够指示列表元素对应的组。

这是我想要实现的玩具示例:

> it = data.frame(ind=c("a","a","b","b","c"),var1=c(1,2,3,4,5), var1=c(2,3,4,2,2))
> group_by(it,ind)%.%summarise(min(var1))
Source: local data frame [3 x 2]

  ind min(var1)
1   c         5
2   b         3
3   a         1

现在使用do 执行此操作

> do(group_by(it,ind),function(x)min(x[,"var1"]))
[[1]]
[1] 5

[[2]]
[1] 3

[[3]]
[1] 1

理想情况下,名称应为c("c","b","a")

这可能吗?为什么 dplyr 会反转组的排序?请注意,在我的情况下,do 操作的结果是 lm 对象。

编辑:评论要求提供现实的例子,这就是我的想法。我根据数据(虚拟代码)拟合模型:

res <- do(group_by(data,Index),lm,formula=y~x)

现在我想做各种各样的事情,比如

sapply(res,coef)

所以我想将结果与原始数据集相关联,在这种情况下与系数对应的 Index 相关联。

编辑2:可以使用dlply函数实现所需的行为:

dlply(it,~ind,function(d)min(d[,"var1"]))

$a
[1] 1

$b
[1] 3

$c
[1] 5

attr(,"split_type")
[1] "data.frame"
attr(,"split_labels")
  ind
1   a
2   b
3   c

我正在研究是否可以使用 dplyr 复制此行为,最好是在最少干预的情况下。

【问题讨论】:

  • 你也可以使用as.list(by(it, it$ind, function(x) min(x[,'var1'])))来得到你想要的,不需要dplyr
  • 哦,我知道很多方法可以做到这一点,但我特意询问的是 dplyr。
  • @mpiktas 为什么不发布一个您想解决的问题的更现实的例子?

标签: r dplyr


【解决方案1】:

你可以在你的函数中创建一个 data.frame:

 mods <- do(group_by(it,ind),function(x)
        data.frame(it=unique(as.character(x$ind)),val=min(x$var1)))

然后:

do.call(rbind,mods)
  it val
1  a   1
2  b   3
3  c   5

编辑

 mods <- do(group_by(it,ind),
      function(x) setNames(list(min(x$var1)),unique(as.character(x$ind))))

unlist(mods,rec=FALSE)
$a
[1] 1

$b
[1] 3

$c
[1] 5

【讨论】:

  • 谢谢,但我想得到列表,因为列表的元素理论上可​​以是任何 R 对象,一般不能轻易放入 data.frame。
  • 所以将data.frame 更改为list...另外,您的示例中的数据源自数据框
  • @mpiktas 看到我的编辑。当然,列表理论上可以是任何 R 对象,但实际上很难使用按操作分组来创建不同元素长度的列表。
【解决方案2】:

试试这个标记版本的do.grouped_df

do2 <- function (.data, .f, ...) {
    if (is.null(attr(.data, "indices"))) {
        .data <- dplyr:::grouped_df_impl(.data, attr(.data, "vars"), 
            attr(.data, "drop"))
    }
    index <- attr(.data, "indices")
    out <- vector("list", length(index))
    for (i in seq_along(index)) {
        subs <- .data[index[[i]] + 1L, , drop = FALSE]
        out[[i]] <- .f(subs, ...)
    }
    nms <- as.character(attr(.data, "labels")[[1]])
    setNames(out, nms)
}

library(gusbfn)

it %.% group_by(ind) %.% do2(function(x) min(x$var1))

给出:

$a
[1] 1

$b
[1] 3

$c
[1] 5

它也可以像这样与 gsubfn 包中的fn$ 组合以稍微缩短它:

library(dplyr)
library(gsubfn)

it %.% group_by(ind) %.% fn$do2(~ min(x$var1))

给出相同的答案。

【讨论】:

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