使用其数据框名称重命名列表中的数据框列
Rename column of dataframes inside a list with its dataframe name
我有多个 dataframes/tibbles 结构完全相同,但内容不同。他们的名字是我区分他们的唯一方式。 objective 是将它们全部合并到一个数据框中,带有一个因子列。原始数据帧每个 hour/measurement 一列,所以首先我想收集所有内容。
假设 mtcars df 的第 5 到 11 列是我的小时列。
mt1 <- mtcars
mt2 <- mtcars
mt3 <- mtcars
mt4 <- mtcars
mtlist <- list(m1 = mt1,
m2 = mt2,
m3 = mt3,
m4 = mt4)
require(tidyverse)
mtlist_tidy <- lapply(mtlist, function(x){
df <- x %>%
gather(exp, temp_name, 5:11)
return(df)
})
现在我卡住了。我需要使用该 df 的名称重命名 mtlist_tidy 内每个 dfs 中的 "temp_name" 列,即 m1、m2 等:
> head(mtlist_tidy$m1)
mpg cyl disp hp exp temp_name
1 21.0 6 160 110 drat 3.90
2 21.0 6 160 110 drat 3.90
3 22.8 4 108 93 drat 3.85
4 21.4 6 258 110 drat 3.08
5 18.7 8 360 175 drat 3.15
6 18.1 6 225 105 drat 2.76
应该变成
> head(mtlist_tidy$m1)
mpg cyl disp hp exp m1
1 21.0 6 160 110 drat 3.90
2 21.0 6 160 110 drat 3.90
3 22.8 4 108 93 drat 3.85
4 21.4 6 258 110 drat 3.08
5 18.7 8 360 175 drat 3.15
6 18.1 6 225 105 drat 2.76
那么purrr::reduce(mtlist_tidy, full_join)
就可以了,完成我的任务。
我想一定有一个只使用 purrr
并跳过 lapply 的解决方案,但我对这个包还不是很熟悉。
这个可以吗?
lapply(mtlist_tidy, function(i) {
names(i)["temp_name"] <- names(mtlist)[i] } )
几个想法:
首先,要解决当前问题,您可以使用 map2
同时遍历列表和列表名称。然后,您可以通过 gather_
(用于标准评估)按照列表名称命名新列。
map2(mtlist, names(mtlist), ~gather_(.x, "exp", .y, names(.x)[5:11]) )
请注意 purrr 的下一版本将使用 imap
作为循环遍历列表和列表名称的快捷方式。此外,下一版本的 tidyr 将使用 tidyeval
并且 gather_
将被弃用。
其次,您可以通过使用 map_df
而不是 lapply
进行循环来保持长格式。 map_df
在后台使用 bind_rows
,您可以通过 .id
参数为每个列表包含一个分组变量。
mtlist %>%
map_df(~.x %>% gather("exp", "temp_name", 5:11), .id = "name" )
要从此处将数据集放入宽格式,您可以使用 spread
。在这个例子中需要做更多的工作,因为一些识别变量,如 hp
和 disp
在多行中具有相同的值。
mtlist %>%
map_df(~.x %>% gather("exp", "temp_name", 5:11), .id = "name" ) %>%
group_by(name) %>%
mutate( rows = 1:n() ) %>%
spread(name, temp_name)
您可能想要添加一些 NSE 魔法:
library(rlang)
mtlist_tidy %>% map2(., names(.), ~rename(.x, UQ(sym(.y)) := temp_name))
我写了一个函数来重命名特定的列
rename_fn <- function(df, col_ind, new_names) {
names(df)[col_ind] <- new_names
return(df)
}
然后简单地使用来自 purrr
的 map2
mtlist_tidy<-mtlist_tidy %>% map2(.,names(mtlist_tidy),
~rename_fn(.x,col_ind = 6,new_names = .y))
我有多个 dataframes/tibbles 结构完全相同,但内容不同。他们的名字是我区分他们的唯一方式。 objective 是将它们全部合并到一个数据框中,带有一个因子列。原始数据帧每个 hour/measurement 一列,所以首先我想收集所有内容。
假设 mtcars df 的第 5 到 11 列是我的小时列。
mt1 <- mtcars
mt2 <- mtcars
mt3 <- mtcars
mt4 <- mtcars
mtlist <- list(m1 = mt1,
m2 = mt2,
m3 = mt3,
m4 = mt4)
require(tidyverse)
mtlist_tidy <- lapply(mtlist, function(x){
df <- x %>%
gather(exp, temp_name, 5:11)
return(df)
})
现在我卡住了。我需要使用该 df 的名称重命名 mtlist_tidy 内每个 dfs 中的 "temp_name" 列,即 m1、m2 等:
> head(mtlist_tidy$m1)
mpg cyl disp hp exp temp_name
1 21.0 6 160 110 drat 3.90
2 21.0 6 160 110 drat 3.90
3 22.8 4 108 93 drat 3.85
4 21.4 6 258 110 drat 3.08
5 18.7 8 360 175 drat 3.15
6 18.1 6 225 105 drat 2.76
应该变成
> head(mtlist_tidy$m1)
mpg cyl disp hp exp m1
1 21.0 6 160 110 drat 3.90
2 21.0 6 160 110 drat 3.90
3 22.8 4 108 93 drat 3.85
4 21.4 6 258 110 drat 3.08
5 18.7 8 360 175 drat 3.15
6 18.1 6 225 105 drat 2.76
那么purrr::reduce(mtlist_tidy, full_join)
就可以了,完成我的任务。
我想一定有一个只使用 purrr
并跳过 lapply 的解决方案,但我对这个包还不是很熟悉。
这个可以吗?
lapply(mtlist_tidy, function(i) {
names(i)["temp_name"] <- names(mtlist)[i] } )
几个想法:
首先,要解决当前问题,您可以使用 map2
同时遍历列表和列表名称。然后,您可以通过 gather_
(用于标准评估)按照列表名称命名新列。
map2(mtlist, names(mtlist), ~gather_(.x, "exp", .y, names(.x)[5:11]) )
请注意 purrr 的下一版本将使用 imap
作为循环遍历列表和列表名称的快捷方式。此外,下一版本的 tidyr 将使用 tidyeval
并且 gather_
将被弃用。
其次,您可以通过使用 map_df
而不是 lapply
进行循环来保持长格式。 map_df
在后台使用 bind_rows
,您可以通过 .id
参数为每个列表包含一个分组变量。
mtlist %>%
map_df(~.x %>% gather("exp", "temp_name", 5:11), .id = "name" )
要从此处将数据集放入宽格式,您可以使用 spread
。在这个例子中需要做更多的工作,因为一些识别变量,如 hp
和 disp
在多行中具有相同的值。
mtlist %>%
map_df(~.x %>% gather("exp", "temp_name", 5:11), .id = "name" ) %>%
group_by(name) %>%
mutate( rows = 1:n() ) %>%
spread(name, temp_name)
您可能想要添加一些 NSE 魔法:
library(rlang)
mtlist_tidy %>% map2(., names(.), ~rename(.x, UQ(sym(.y)) := temp_name))
我写了一个函数来重命名特定的列
rename_fn <- function(df, col_ind, new_names) {
names(df)[col_ind] <- new_names
return(df)
}
然后简单地使用来自 purrr
的 map2mtlist_tidy<-mtlist_tidy %>% map2(.,names(mtlist_tidy),
~rename_fn(.x,col_ind = 6,new_names = .y))