【问题标题】:Select variables from list of tibbles using names in each tibble使用每个小标题中的名称从小标题列表中选择变量
【发布时间】:2018-11-25 04:49:47
【问题描述】:

我有一个小标题或数据框的列表(每个列表中都有一个名称),我想:(1)在每个小标题中从具有不同名称的变量创建具有相同名称long.col 的新列; (2) 通过从另一个 tibble 与每个 tibble 中连接 tibble 名称和列名称的键进行匹配,最后; (3) 在每个 tibble 中为所有新创建的具有相同名称 long.col 的列绑定行,并标识它们来自的原始 tibble。

我想最好使用 tidyverse 函数来做到这一点。以下是两者的示例: a) 小标题列表; b) 关键 tibble 标识 tibble 名称和要在每个中选择的变量

df1 <- tibble(v1 = c(rep("A", 5), rep("B", 5)),
          v2 = 1:10)
df2 <- tibble(v1 = c(rep("C", 6), rep("D", 6)),
          v3 = 11:22)
df3 <- tibble(v1 = c(rep("E", 4), rep("F", 4)),
          v4 = 23:30)

list.df <- list(df1, df2, df3)
names(list.df) <- c("data1", "data2", "data3")

key <- tibble(data = c("data1", "data2", "data3"),
          vars = c("v2", "v3", "v4"))

最终输出应如下所示:

 final.df <- tibble(data = c(rep("data1", 10), rep("data2", 12), rep("data3", 8)),
               long.col = 1:30)

我需要使用多个列在更长的列表中执行此操作,因此为每个 tibble 中的每个列单独执行此操作是不可行的。

【问题讨论】:

    标签: r list select data-binding tibble


    【解决方案1】:

    你可以在这里使用map2

    library(purrr)
    library(tibble)
    out <- map2_df(.x = list.df,
                   .y = names(list.df),
                   .f = ~ {
                     temp <- key[["vars"]][key[['data']] == .y]
                     tibble(data = .y, long.col = .x[[temp]])
                     })
    

    检查输出

    identical(final.df, out)
    #[1] TRUE
    

    【讨论】:

    • 我实际上发现你的第一个答案(pmap())更加优雅(因为更紧凑并且不需要分配临时对象)。请问您为什么决定改用map2()?谢谢
    • @prosoitos 感谢您的评论。我改变了答案,因为pmap——你可能知道——我们并行迭代了list.dfnames(list.df)key[['vars']]。我们得到了正确的输出,因为key[['vars']] 中的元素顺序正确。 ...
    • 谢谢!我怀疑您已对其进行了更改以使其更通用,但我不确定。昨天当您发布您的答案时,我正准备使用 purrr 发布答案,但我的并没有那么优雅,并且首先涉及创建一个函数。所以你的两个答案对我来说都很有教育意义:)
    • ...如果我们要更改key 中的行顺序,我们会收到错误消息:“调用rlang::last_error() 以查看回溯”。最佳
    【解决方案2】:

    您所说的问题的第一步是从键表中动态选择变量名称,并在相应的数据框中分配值。这可以通过首先定义一个函数来完成,该函数根据数据框返回基本变量名称(对于long.col)。

    getBaseVar <- function(dfName, keyTibble){
      varToBeTransformed <- keyTibble %>% dplyr::filter(data == (!!dfName)) %>% 
                           dplyr::select(vars) %>% dplyr::first() %>% 
                             rlang::sym(.)
      return(varToBeTransformed)
    
    }
    

    此函数将所需的变量名称作为符号返回。然后可以将其传递给dplyr::mutate 函数。为了对列表中存在的所有数据框动态执行此操作,我们将命名的数据框列表传递给 purrr::imap 函数,通过该函数可以访问列表元素(在您的情况下为数据框)和列表元素的名称.

    list.df.transformed <- purrr::imap(list.df, function(df, name){
       df %>% dplyr::mutate( long.col := !!getBaseVar(name, key))
    })
    

    最后,您可以通过再次通过purrr::imap 传递转换后的数据帧列表并提取必要的数据(即long.col 列和具有重复值的变量)来创建所需的输出数据框)。提取后,将其传递给dplyr::bind_rows 函数会返回所需的数据帧。

    final.df <- tibble(data = character(), long.col = numeric()) 
    purrr::imap(list.df.transformed, function(df, name){
        repeatedNameCol <- tibble(data = rep(name, nrow(df)))
        dataToBind <- df %>% dplyr::select(long.col) %>% 
                         dplyr::bind_cols(repeatedNameCol)
        return(dataToBind)
    }) %>% dplyr::bind_rows(.) -> final.df
    

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-04
      • 2021-12-13
      • 1970-01-01
      相关资源
      最近更新 更多