我想对嵌套数据框(存储为列表列)执行计算,并使用purrr函数将计算的变量添加回每个数据框。我将使用此结果加入其他数据,并保持紧凑,这有助于我更好地组织和检查它。我可以通过几个步骤完成此操作,但似乎可能有一个我没有遇到的解决方案。如果有解决方案,我无法轻易找到它。
加载库。示例需要以下软件包(在CRAN上可用):
library(dplyr)
library(purrr)
library(RcppRoll) # to calculate rolling mean
示例数据,包含3个科目,并且随着时间的推移重复测量:
test <- data_frame(
id= rep(1:3, each=20),
time = rep(1:20, 3),
var1 = rnorm(60, mean=10, sd=3),
var2 = rnorm(60, mean=95, sd=5)
)
将数据存储为嵌套数据框:
t_nest <- test %>% nest(-id)
id data
<int> <list>
1 1 <tibble [20 x 3]>
2 2 <tibble [20 x 3]>
3 3 <tibble [20 x 3]>
执行计算。我将根据数据计算多个新变量,尽管稍后可以扩展一个解决方案。每次计算的结果都是一个数字向量,长度与输入相同(n = 20):
t1 <- t_nest %>%
mutate(var1_rollmean4 = map(data, ~RcppRoll::roll_mean(.$var1, n=4, align="right", fill=NA)),
var2_delta4 = map(data, ~(.$var2 - lag(.$var2, 3))*0.095),
var3 = map2(var1_rollmean4, var2_delta4, ~.x -.y))
id data var1_rollmean4 var2_delta4 var3
<int> <list> <list> <list> <list>
1 1 <tibble [20 x 3]> <dbl [20]> <dbl [20]> <dbl [20]>
2 2 <tibble [20 x 3]> <dbl [20]> <dbl [20]> <dbl [20]>
3 3 <tibble [20 x 3]> <dbl [20]> <dbl [20]> <dbl [20]>
我的解决方案是unnest
此数据,然后是nest
。这似乎没有任何问题,但似乎可能存在更好的解决方案。
t1 %>% unnest %>%
nest(-id)
id data
<int> <list>
1 1 <tibble [20 x 6]>
2 2 <tibble [20 x 6]>
3 3 <tibble [20 x 6]>
这个其他解决方案(from SO 42028710)很接近,但并不完全是因为它是一个列表而不是嵌套的数据帧:
map_df(t_nest$data, ~ mutate(.x, var1calc = .$var1*100))
我使用purrr Cheatsheet找到了很多有用的信息,但找不到答案。
答案 0 :(得分:9)
您可以在映射 data 列时包装另一个mutate
,并在每个嵌套的tibble中添加列:
t11 <- t_nest %>%
mutate(data = map(data,
~ mutate(.x,
var1_rollmean4 = RcppRoll::roll_mean(var1, n=4, align="right", fill=NA),
var2_delta4 = (var2 - lag(var2, 3))*0.095,
var3 = var1_rollmean4 - var2_delta4
)
))
t11
# A tibble: 3 x 2
# id data
# <int> <list>
#1 1 <tibble [20 x 6]>
#2 2 <tibble [20 x 6]>
#3 3 <tibble [20 x 6]>
unnest-nest
方法,然后重新排序内部的列:
nest_unnest <- t1 %>%
unnest %>% nest(-id) %>%
mutate(data = map(data, ~ select(.x, time, var1, var2, var1_rollmean4, var2_delta4, var3)))
identical(nest_unnest, t11)
# [1] TRUE
答案 1 :(得分:2)
似乎你正在尝试做什么,嵌套是没有必要的
library(tidyverse)
library(zoo)
test %>%
group_by(id) %>%
mutate(var1_rollmean4 = rollapplyr(var1, 4, mean, fill=NA),
var2_delta4 = (var2 - lag(var2, 3))*0.095,
var3 = (var1_rollmean4 - var2_delta4))
# A tibble: 60 x 7
# Groups: id [3]
# id time var1 var2 var1_rollmean4 var2_delta4 var3
# <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 1 1 9.865199 96.45723 NA NA NA
# 2 1 2 9.951429 92.78354 NA NA NA
# 3 1 3 12.831509 95.00553 NA NA NA
# 4 1 4 12.463664 95.37171 11.277950 -0.10312483 11.381075
# 5 1 5 11.781704 92.05240 11.757076 -0.06945881 11.826535
# 6 1 6 12.756932 92.15666 12.458452 -0.27064269 12.729095
# 7 1 7 12.346409 94.32411 12.337177 -0.09952197 12.436699
# 8 1 8 10.223695 100.89043 11.777185 0.83961377 10.937571
# 9 1 9 4.031945 87.38217 9.839745 -0.45357658 10.293322
# 10 1 10 11.859477 97.96973 9.615382 0.34633428 9.269047
# ... with 50 more rows
编辑您可以将结果嵌套到%>% nest(-id)
如果您仍然喜欢嵌套或因其他原因进行嵌套,那么它就像
t1 <- t_nest %>%
mutate(data = map(data, ~.x %>% mutate(...)))
也就是说,你在.x
语句中的map
上进行变异。这会将data
视为data.frame
,mutate
会将结果列绑定到它。