创建的数据帧,匹配基于列表的第一元素

问题描述 投票:2回答:5

我想基于列表的第一个元素上创建一个数据帧。具体而言,我有

  • 一种含载体变量(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
    
    r list dataframe match
    5个回答
    2
    投票

    一个选择是将循环通过list(“list1的”),由“长”到filter基于“名称”载体的“名称”栏,将其转换为一个单一的数据集而创建具有.id标识列,spread'宽”和删除‘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结合在一起,创造了一个分组标识“GRP”指定list元素,通过选择具有“名称” filtervector从“长”相匹配,只有“名称”列spread行'宽'

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

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


    它只能与base R也做。创建具有Map组标识符,rbindlist元件以单个数据集,通过从“名称” subset仅保留值vector的行,以及从“长”到“宽” reshape

    df1 <- subset(do.call(rbind, Map(cbind, list1, 
              ind = seq_along(list1))), names %in% .GlobalEnv$names)   
    reshape(df1, idvar = 'ind', direction = 'wide', timevar = 'names')[-1]
    

    1
    投票

    基R和dplyr的混合。对于每一个列表元素,我们创建1行中的数据帧。使用dplyrrbind_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
    

    无子输出看起来是这样的

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

    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
    

    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
    

    0
    投票

    为了完整起见,这里是一个使用dcast()一个rowid()的方法:

    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]
    
    © www.soinside.com 2019 - 2024. All rights reserved.