【问题标题】:Convert List of Vectors into Data Frame of Counts [duplicate]将向量列表转换为计数数据框
【发布时间】:2015-04-01 02:12:42
【问题描述】:

我有一个字符向量列表存储在这样的列表中:

basket1 <- c("Apple", "Orange", "Banana", "Apple", "Apple", "Grape")
basket2 <- c("Grape", "Grape", "Grape", "Grape")
basket3 <- c("Kiwi", "Apple", "Cantaloupe", "Banana")
basket4 <- c("Strawberry")
basket5 <- c("Grape", "Grape", "Grape")
FruitBasketList <- list(basket1, basket2, basket3, basket4, basket5)

我想将FruitBasketList 变成一个数据框,其中每行中每个水果的计数与它来自的篮子相匹配。我遇到的主要问题是每个向量中可能有数千个不同的“水果”,其中很多会出现不止一次。

这是我想要的结果数据框:

Basket  Apple   Orange  Banana  Grape   Kiwi    Cantaloupe  Strawberry
basket1 3       1       1       1       0       0           0
basket2 0       0       0       4       0       0           0
basket3 1       0       1       0       1       1           0
basket4 0       0       0       0       0       0           1
basket5 0       0       0       3       0       0           0

显然,这不是我的真实数据,但我认为我会简化数据的外观,以便任何人都能理解它。不,这不是家庭作业。无论如何,一个篮子里的水果数量可以是一千种不同的水果,每个水果向量的长度也不一样。也可以有数以万计的篮子(向量)。显然,一些水果可以在同一个向量(篮子)中重复多次。我一直在努力解决这个问题,但我确信它非常复杂且效率非常低。到目前为止,我的解决方案包括组合所有向量中的所有向量,然后识别所有可能的唯一水果名称。结果很好。然后我正在努力的部分是从所有这些唯一的列名中创建一个空数据框,然后为每个向量计算每个唯一的水果,然后将该值放在数据框的新行中的正确列中对于该特定篮子中不存在的水果,零。

我用来统计单个向量的代码如下所示:

GetUniqueItemCount <- function(rle, value)
{
  value <- rle$lengths[rle$values == value]
  if (identical(value, integer(0)))
  {
    value <- 0
  }
  value
}

调用它的代码如下所示:

Apple <- GetUniqueItemCount(rle, "Apple") 

正如您在我当前的代码中看到的那样,我必须事先知道所有可能的水果,并对每个水果的数量进行硬编码,然后将其分配给数据框中预先知道的特定列。无论如何,我意识到我在这里走错了路,所以我将不胜感激任何关于回到正轨以获得我想要的数据框的建议。请随意提供一种完全不同的方法,而不是试图找出如何让我的工作,如果这将是解决问题的最佳方法。

【问题讨论】:

    标签: r list vector dataframe


    【解决方案1】:

    我建议使用“qdapTools”包中的mtabulate

    library(qdapTools)
    mtabulate(FruitBasketList)
    #   Apple Banana Cantaloupe Grape Kiwi Orange Strawberry
    # 1     3      1          0     1    0      1          0
    # 2     0      0          0     4    0      0          0
    # 3     1      1          1     0    1      0          0
    # 4     0      0          0     0    0      0          1
    # 5     0      0          0     3    0      0          0
    

    package's author 甚至可以分享您的头像。漂亮。

    【讨论】:

    • 我很高兴我问了这个问题,因为它把我带到了这个包和 Tyler 的博客,到目前为止我发现它非常吸引人!感谢您向 Ananda 指出此解决方案!
    【解决方案2】:

    使用dplyr,我可能会做类似的事情

    library(dplyr)
    m <- FruitBasketList %>% lapply(table) %>% lapply(as.list) %>% 
        lapply(data.frame) %>% rbind_all()
    m
    
    # Source: local data frame [5 x 7]
    # 
    #   Apple Banana Grape Orange Cantaloupe Kiwi Strawberry
    # 1     3      1     1      1         NA   NA         NA
    # 2    NA     NA     4     NA         NA   NA         NA
    # 3     1      1    NA     NA          1    1         NA
    # 4    NA     NA    NA     NA         NA   NA          1
    # 5    NA     NA     3     NA         NA   NA         NA
    

    这会将缺失值保留为 NA。如果你想将它们设置为 0,你可以这样做

    m[is.na(m)]<-0
    m
    
    # Source: local data frame [5 x 7]
    # 
    #   Apple Banana Grape Orange Cantaloupe Kiwi Strawberry
    # 1     3      1     1      1          0    0          0
    # 2     0      0     4      0          0    0          0
    # 3     1      1     0      0          1    1          0
    # 4     0      0     0      0          0    0          1
    # 5     0      0     3      0          0    0          0
    

    【讨论】:

      【解决方案3】:

      您可以对每一行应用函数table,然后使用gtools::smartbind rbind 结果

      【讨论】:

        【解决方案4】:

        您可以melt“列表”并使用dcast从“长”重塑为“宽”

        library(reshape2)
        dcast(melt(setNames(FruitBasketList, ls(pattern='^basket'))), L1~value) 
        #      L1   Apple Banana Grape Orange Cantaloupe Kiwi Strawberry
        #1 basket1     3      1     1      1          0    0          0
        #2 basket2     0      0     4      0          0    0          0
        #3 basket3     1      1     0      0          1    1          0
        #4 basket4     0      0     0      0          0    0          1
        #5 basket5     0      0     3      0          0    0          0
        

        或者使用base R函数stacktable

        df <- stack(setNames(FruitBasketList, ls(pattern='^basket')))
        table(df[2:1])
        #          values
        #ind        Apple Banana Cantaloupe Grape Kiwi Orange Strawberry
        # basket1     3      1          0     1    0      1          0
        # basket2     0      0          0     4    0      0          0
        # basket3     1      1          1     0    1      0          0
        # basket4     0      0          0     0    0      0          1
        # basket5     0      0          0     3    0      0          0
        

        【讨论】:

          猜你喜欢
          • 2017-09-25
          • 2021-11-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-20
          • 2021-01-18
          • 1970-01-01
          相关资源
          最近更新 更多