这是一个非常类似问题的后续问题,我已经在这里得到了很大的帮助,但我未能根据新要求修改解决方案。
我有一个数据框列表,每个数据框的行数不同。我想使用每个数据框的名称来重命名每个数据框中的所有(不仅仅是第一列)列。然后我想在每个数据框中添加一个带有行号的列,以便使用合并来绑定所有数据框。
我的小例子又创建了一个简短的数据框列表:
# Create dummy list of data frames
df1 <- data.frame(border=c(1,2,3), value=c(4,5,6))
df2 <- data.frame(border=as.factor(c("A","B")), value=c(3,5.7))
df_lst <- list(df1, df2)
names(df_lst) <- c("df1","df2")
这次所需的输出应该如下所示:
df1 border df1 value df2 border df2 value
1 1 4 A 3.0
2 2 5 B 5.7
3 3 6 <NA> NA
我可以通过访问各个数据帧来描述如何在代码中到达这个小玩具示例,但我希望有一个像 @Maël 在我上一个问题中所建议的那样优雅的解决方案,该解决方案是
applies
直接到数据框列表:
# Append the list names hard coded to all column names
# but this should be dynamic within the list not using the data frames
names(df1) <- c("df1 border", "df1 value")
names(df2) <- c("df2 border", "df2 value")
# Add a column which can be used in merge
df1$row_id <- row.names(df1)
df2$row_id <- row.names(df2)
# Merge all dataframes adding rows w/ <NA> where required
# but this should use the list not the individual data frames
df <- merge(df1, df2, all.x=T, all.y=T)
我们可以这样做: 主要任务是 cbind 需要相同数量的行。 在此示例中,我们在绑定到数据框后使用
reframe(cur_data()[seq(3),], .by=id) %>%
。这里它是用 3
硬编码的,但我们可以通过 max_rows <- max(map_int(df_lst, nrow))
轻松克服。之后我们需要一些旋转技巧:
library(tidyverse)
df_lst %>%
map(~mutate_all(.x, as.character)) %>%
bind_rows(.id = 'id') %>%
reframe(cur_data()[seq(3),], .by=id) %>%
group_by(id) %>%
mutate(row = row_number()) %>%
pivot_wider(names_from = id, values_from = c(border, value)) %>%
select(-row)
border_df1 border_df2 value_df1 value_df2
<chr> <chr> <chr> <chr>
1 1 A 4 3
2 2 B 5 5.7
3 3 NA 6 NA