使用其数据框名称重命名列表中的数据帧列

时间:2017-07-28 13:09:38

标签: r dplyr purrr

我有多个数据帧/元素具有相同的确切结构,但内容不同。他们的名字是我能区分他们的唯一方式。目标是将它们全部合并到一个数据框中,并使用因子列。原始数据帧每小时/测量有一列,所以首先我要收集所有内容。

想象一下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)
})

现在我被卡住了。我需要在mtlist_tidy中的每个dfs中重命名“temp_name”列,其名称为df,即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的解决方案,但我对这个包不熟悉。

4 个答案:

答案 0 :(得分:5)

一些想法:

首先,要解决当前问题,您可以使用map2同时遍历列表和列表名称。然后,您可以通过gather_使用列表名称命名新列(用于标准评估)。

map2(mtlist, names(mtlist), ~gather_(.x, "exp", .y, names(.x)[5:11]) )

请注意, purrr 的下一个版本将imap作为循环列表和列表名称的快捷方式。此外,下一版 tidyr 将使用tidyevalgather_将被弃用。

其次,您可以使用map_df代替lapply来保持长格式。 map_df在底层使用bind_rows,您可以通过.id参数为每个列表添加分组变量。

mtlist %>%
    map_df(~.x %>% gather("exp", "temp_name", 5:11), .id = "name" )

要从此处以宽格式放置数据集,您可以使用spread。在此示例中需要更多工作,因为某些标识变量(如hpdisp在多行中具有相同的值。

mtlist %>%
    map_df(~.x %>% gather("exp", "temp_name", 5:11), .id = "name" ) %>%
    group_by(name) %>%
    mutate( rows = 1:n() ) %>%
    spread(name, temp_name)

答案 1 :(得分:2)

你可能想要添加一些NSE魔法:

library(rlang)
mtlist_tidy %>% map2(., names(.), ~rename(.x, UQ(sym(.y)) := temp_name))

答案 2 :(得分:0)

这样做吗?

lapply(mtlist_tidy, function(i) {
  names(i)["temp_name"] <- names(mtlist)[i] } )

答案 3 :(得分:0)

我编写了一个函数来重命名特定列

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))