将向量列表转换为计数数据帧

时间:2015-02-02 06:59:42

标签: r list vector dataframe

我有一个存储在列表中的字符向量列表,如下所示:

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变成一个数据框,其中每行中的每个水果的数量与它来自的篮子相匹配。我遇到的主要问题是可能会有成千上万种不同的水果&#34;在每个向量中,很多都会出现不止一次。

  

这是我想要的数据框架:

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

正如您在我当前的代码中所看到的,我必须事先知道所有可能的水果并硬编码每个水果的数量,然后将其分配给数据框中预先知道的特定列。无论如何,我意识到我在这里走的是错误的道路,所以我很感激任何关于回到正轨以获得上面所示的所需数据框架的建议。如果这是解决问题的最佳方法,请随意提供完全不同的方法,而不是试图弄清楚如何使我的工作。

4 个答案:

答案 0 :(得分:9)

我建议使用“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甚至分享您的头像。漂亮的。

答案 1 :(得分:5)

使用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

答案 2 :(得分:1)

您可以在每一行上应用函数table,然后使用gtools::smartbind

对结果进行rbind

答案 3 :(得分:1)

您可以使用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