【发布时间】:2021-02-01 22:41:25
【问题描述】:
我的数据的简化版本如下所示:
primary_list <- list(secondary_list = list(df1 = data.frame(df_name = "hello", time = c(1,2,3,6,7,9,12,20), v1 = sample(0:1, 8, replace = T)),
df2 = data.frame(df_name = "world", time = c(1,5,6,8,9,12,15,18,19,20), v1 = sample(0:1, 10, replace = T))),
secondary_list2 = list(df1 = data.frame(df_name = "hello", time = c(1,5,6,8,9,12,15,18,19,20), v1 = sample(0:1, 10, replace = T)),
df2 = data.frame(df_name = "world", time = c(4,6,7,8,12), v1 = sample(0:1, 5, replace = T))))
我的目标是 full_joinsecondary_lists 中的所有数据帧(即具有共同元素名称和 df_name 标识符的数据帧)按“时间”分隔数据帧。目标类似于 question,但使用单独的数据框作为 full_join 的参数。
作为一个手动示例,我正在尝试实现这样的目标:
time_df <- data.frame(time = 1:25)
expected_output <- list(
secondary_list = list(time_df, primary_list$secondary_list$df1, primary_list$secondary_list2$df1) %>% reduce(full_join, by = "time"),
secondary_list2 = list(time_df, primary_list$secondary_list$df2, primary_list$secondary_list2$df2) %>% reduce(full_join, by = "time")
)
### Ideally I'm aiming for something cleaned up like this:
ideal_output <- lapply(expected_output, function(x){
x <- x %>% select(time,v1.x,v1.y)
colnames(x) <- c("time", "v1", "v2")
x
})
### I can probably handle that after
我正在尝试制作一个适用于更大列表结构并为所有 secondary_list 元素计算 full_join 的解决方案
我已尝试将列表 like this 展平,但在索引列表元素共享相同名称时遇到了一些复杂问题。还尝试rbindlist 将所有辅助列表压缩到一个数据框中,但还没有任何乐趣。
解决方案不必是dplyr,只需要适用于包含 n 个不同长度数据帧的 n 个辅助列表即可。如果输出不重复df_name.x、df_name.y,那么对于奖励点,那将是很好的,因为只需要一个标识符列,后跟变量(请参阅ideal_output),但我可以在之后很容易地清理它。
提前致谢!
更新 这个问题我得到了三个很好的答案。
-
Ronak 在 tidyverse 流水线工作流程中表现出色
-
ekoam 是一个单一的班轮,我完全赞成简洁的代码
-
neon_ninja 在微基准测试中获胜
由于我有大量数据,所以速度很重要,所以我会接受 neon_ninja 的回答。谢谢大家!
mbm = microbenchmark(
#####
ronak = primary_list %>%
purrr::transpose() %>%
map(~{
.x$time_df <- time_df
.x %>%
reduce(full_join, by = 'time') %>%
select(time, df_name.x, starts_with("v")) ### Edited select fo n dfs
}),
#####
ekoam = lapply(primary_list, compose(~select(., time, v1 = v1.x, v2 = v1.y), reduce), full_join, .init = time_df, by = "time"),
#####
neon_ninja = lapply(names(primary_list[[1]]), function(df_name) {
time_df["df_name"] = df_name ### I added this to get a column of names
time_df = data.frame(time = 1:25)
for (sec_list_name in names(primary_list)) {
time_df[sec_list_name] = NA
df = primary_list[[sec_list_name]][[df_name]]
for (i in 1:length(df$time)) {
time_df[time_df$time == df$time[i], sec_list_name] = df$v1[i]
}
}
time_df
})
)
#Unit: milliseconds
# expr min lq mean median uq max neval
# ronak 11.572526 12.507490 15.132911 13.491643 16.531374 28.11236 100
# ekoam 10.710731 11.464450 13.665370 12.450013 14.204986 26.83166 100
# neon_ninja 1.116033 1.258137 1.784428 1.345762 1.643547 13.89803 100
【问题讨论】:
标签: r list dataframe data-structures dplyr