创建数据框,根据列表的第一个元素进行匹配

时间:2019-02-02 16:04:07

标签: r list dataframe match

我想基于列表的第一元件上,以建立一个数据帧。具体来说,我有

  • 一个含有载体变量(names1);
  • 一个包含两个变量(一些vars1和值)的列表;
  • 最终产品应使用带有“ names1”的data.frame,其中包含与匹配的大小写一样多的行。
  • 如果特定列表和向量之间没有匹配项,则应为NA。
  • 的值也可以是因子或字符串。
  • names1 <- c("a", "b", "c")
    dat1 <- data.frame(names1 =c("a", "b", "c", "f"),values= c("val1", 13, 11, 0))
       dat1$values <- as.factor(dat1$values)
    dat2 <- data.frame(names1 =c("a", "b", "x"),values= c(12, 10, 2))
       dat2$values <- as.factor(dat2$values)
    list1 <- list(dat1, dat2)
    

    结果应该是一个新的数据框,其中包含变量“名称”以及所有与列表各部分匹配的值:

     a      b    c
     val1   13   11
     12     10   NA
    

    5 个答案:

    答案 0 :(得分:2)

    一种选择是,以循环通过list(“list1的”),filter基于“名称”载体的“名称”栏,将其转换为一个单一的数据集而创建的标识用柱.idspread从 '长' 到 '宽' 和删除 'GRP' 列

    library(tidyverse)
    map_df(list1, ~   .x %>% 
                         filter(names %in% !! names), .id = 'grp') %>%           
          spread(names, values) %>% 
          select(-grp)   
    #      a     b     c    
    #1    25    13    11
    #2    12    10    NA
    

    或者另一种选择是将数据集连同结合bind_rows,创建了一个分组ID“GRP”来指定list元件,filter的行通过只选择“名称”列与“名称” vectorspread从“长”到“宽”匹配的

    bind_rows(list1, .id = 'grp') %>%
       filter(names %in% !! names) %>% 
       spread(names, values)
    

    注意:这是最好不要使用保留关键字用于指定对象的名称(names)。另外,为避免混淆,该对象应与数据框对象的列名不同。


    也可以仅使用base R完成。创建具有组标识符Maprbind的{​​{1}}元素单一数据集,list的行通过保持仅从 '名称' 的值subset,和vector从 '长' 到 '宽'

    reshape

    答案 1 :(得分:1)

    基数R和dplyr的混合。对于每一个列表元素,我们创建1行中的数据帧。使用dplyr的{​​{1}}行将它们绑定在一起,然后使用rbind_list仅将需要的那些列作为子集。

    names

    无子集看起来像这样输出

    library(dplyr)
    
    rbind_list(lapply(list1, function(x) 
            setNames(data.frame(t(x$values)), x$names)))[names]
    
    #     a     b     c
    #   <dbl> <dbl> <dbl>
    #1    25    13    11
    #2    12    10    NA
    

    答案 2 :(得分:1)

    仅使用基础R

    body <- do.call('rbind', lapply(list1, function(list.element){
      element.vals <- list.element[['values']]
      element.names <- list.element[['names']]
      names(element.vals) <- element.names
      return.vals <- element.vals[names]
      if(all(is.na(return.vals))) NULL else return.vals
    }))
    
    df <- as.data.frame(body)
    names(df) <- names
    df
    

    答案 3 :(得分:1)

    以R为底

    t(sapply(list1, function(x) setNames(x$values, names)[match(names, x$names)]))
    #       a  b  c
    # [1,] 25 13 11
    # [2,] 12 10 NA
    

    答案 4 :(得分:0)

    为了完整起见,这是使用dcast()rowid()的{​​{3}}方法:

    library(data.table)
    nam <- names1   # avoid name conflict with column name
    rbindlist(list1)[names1 %in% nam, dcast(.SD, rowid(names1) ~ names1)][, names1 := NULL][]
    
          a  b    c
    1: val1 13   11
    2:   12 10 <NA>
    

    或更简洁地说,在重塑后选择列:

    library(data.table)
    rbindlist(list1)[, dcast(.SD, rowid(names1) ~ names1)][, .SD, .SDcols = names1]