使用do

时间:2017-06-08 09:02:05

标签: r dplyr

代码

假设我有以下代码(我知道,而不是第二个do,我可以在这种情况下使用简单的mutate(并跳过rowwise()),但这是不是重点,因为在我的真实代码中,第二个do有点复杂并且计算模型):

library(dplyr)
set.seed(1)
d <- data_frame(n = c(5, 1, 3))
e <- d %>% group_by(n) %>% 
    do(data_frame(y = rnorm(.$n), dat = list(data.frame(a = 1)))) 
e %>% rowwise() %>% do(data_frame(sum = .$y + .$n))

# Source: local data frame [9 x 1]
# Groups: <by row>

# # A tibble: 9 x 1
#         sum
# *     <dbl>
# 1 0.3735462
# 2 3.1836433
# 3 2.1643714
# 4 4.5952808
# 5 5.3295078
# 6 4.1795316
# 7 5.4874291
# 8 5.7383247
# 9 5.5757814

问题

如您所见,结果仅包含列sum

问题

有没有办法保持来自e 的原始列,而需要明确指定它们(例如e %>% do(data_frame(n = .$n, y = .$y, dat = .$dat, sum = .$y + .$n)) dplyr或者我是否必须使用purrrlyr::by_row?(不是我不喜欢purrrlyr *,我只是想知道是否有一种直接的dplyr方式可以做到这一点我可以过度了):

e %>% purrrlyr::by_row(function(x) x$y + x$n, .collate = "cols", .to = "sum")

*)好吧,实际上有一个purrrlyr::by_row

e %>% purrrlyr::by_row(function(x) data_frame(sum = x$y + x$n, diff = x$y - x$n), 
                       .collate ="cols")

将生成列sum1diff1,我需要再次重命名以获取sumdiff,这会添加另一行代码。

1 个答案:

答案 0 :(得分:4)

我几乎从不使用do,而是组合使用nestmutatemap

在你的情况下,这有点难以理解,因为你的例子似乎没有完全说明你的需求。

在最简单的情况下,您可以指定所需的变量(例如,如果它们是S3对象的列表):

mutate(e, sum = map2_dbl(y, n, `+`))

或者,您可以嵌套所需的数据,然后映射整个数据。 E.g:

f <- e
f$r <- 1:nrow(e) # i.e. add some other variable, not necessarily row indices

f %>%
  ungroup() %>%                               # e was still grouped
  nest(n:dat) %>%                               # specify what you variables you need
  mutate(sum = map_dbl(data, ~.$y + .$n)) %>% # map to data, use the same formula as in do
  unnest()                                    # unnest to get original columns back

两者都保持原始列不受影响。

对于建模示例,例如:

mtcars %>% 
  group_by(cyl) %>% 
  nest() %>% 
  mutate(model = map(data, ~lm(qsec ~ hp, .)),
         coef  = map_dbl(model, ~coef(.)[2])) %>% 
  unnest(data)

这将为您提供所有原始数据,但每组添加回归系数。在取消之前,整个模型都在data.frame中作为列表列。