如何使用 R 在数据矩阵中添加具有新列的相同字符串的总数

How to add total number of same string with new column in data matrix with R

假设我有一个矩阵,5 x 5,带有水果名称(5 class 个水果)。我想在这个现有矩阵中添加 5 个新列,每行中包含单个水果的总数,最后添加一行来显示每种相同水果的总和。数据矩阵是这样的,

    [,1]   [,2]   [,3]   [,4]   [,5]
[1,]mango        banana         mango
[2,]apple  kiwi         banana
[3,]            mango
[4,]mango       apple
[5,]                    orange

我想得到这样的输出(数据框),

    [,1]  [,2]  [,3]  [,4]  [,5] [apple] [banana] [kiwi] [mango] [orange]
[1,]mango      banana       mango   0        1       0      2        0
[2,]apple kiwi       banana         1        1       1      0        0
[3,]           mango                0        0       0      1        0
[4,]mango      apple                1        0       0      1        0   
[5,]                 orange         0        0       0      0        1
[6,]                                2        2       1      4        1

我试过grep,它正在将整个矩阵分解成一个列向量。我实际上不知道如何使用 R 对整个数据矩阵执行此操作。这是代码,

fruits <- matrix(c("mango", "", "banana", "", "mango", "apple", "kiwi", "", "banana", "","", "", "mango", "", "", "mango", "", "apple", "", "", "", "", "", "orange", ""), nrow = 5, ncol = 5, byrow = TRUE)
fruits$apple <- length(grep("apple", fruits[1:nrow(fruits), 1:ncol(fruits)]))
fruits$banana <- length(grep("banana", fruits[1:nrow(fruits), 1:ncol(fruits)]))
fruits$kiwi <- length(grep("kiwi", fruits[1:nrow(fruits), 1:ncol(fruits)]))
fruits$mango <- length(grep("mango", fruits[1:nrow(fruits), 1:ncol(fruits)]))
fruits$orange <- length(grep("orange", fruits[1:nrow(fruits), 1:ncol(fruits)]))

请帮忙。

无法使用矩阵创建您指定的输出,因为矩阵包含单一类型的值。因此,计数将转换为字符,这是一种解决方案,但可能不是您想要的。我建议您使用数据框来存储您的结果。

我提出以下四步解决方案。

  1. 创建矩阵中所有水果名称的向量。我使用额外的步骤从该向量中删除空字符串。

    all_fruits <- unique(as.vector(fruits))
    all_fruits <- all_fruits[nchar(all_fruits) > 0]
    
  2. 创建一个列表,其中包含 all_fruits 中每个水果每行的计数。

    fruit_count <- lapply(all_fruits, function(fruit)
                      rowSums(matrix(grepl(fruit, fruits), nrow = nrow(fruits))))
    names(fruit_count) <- all_fruits
    

    这部分有点棘手,所以我补充几句。您需要使用 grepl 才能 return 一个逻辑向量。不幸的是,fruits 的维数参数丢失了,并且一个简单的向量被 returned 必须转换回矩阵。 rowSums 然后用于总结在每一行中找到搜索词(即水果名称)的次数。这是有效的,因为这样做时 TRUE 被转换为 1 而 FALSE 被转换为 0。

  3. fruits 转换为数据框并添加带有空字符的附加行。将 fruit_count 转换为数据框并添加列总和。

    fruits_df <- rbind(as.data.frame(fruits), "")
    fruit_count_df <- as.data.frame(fruit_count)
    fruit_count_df[nrow(fruits) + 1, ] <- colSums(fruit_count_df)
    
  4. 将两个数据框放在一起。

    out <- data.frame(fruits_df, fruit_count_df)
    out
    ##      X1   X2     X3     X4    X5 mango apple kiwi banana orange
    ## 1 mango      banana        mango     2     0    0      1      0
    ## 2 apple kiwi        banana           0     1    1      1      0
    ## 3             mango                  1     0    0      0      0
    ## 4 mango       apple                  1     1    0      0      0
    ## 5                   orange           0     0    0      0      1
    ## 6                                    4     2    1      2      0
    

我们也可以用计数来融化和铸造数据框。然后加上一行求和:

library(reshape2)
library(tidyr)

#melt fruits matrix
g <- gather(as.data.frame(t(fruits)))

#cast data wide and bind to original matrix
d <- cbind(fruits, dcast(g, key~value)[-(1:2)])

#add row of sums
rbind(d,c(rep("", 5),colSums(d[-(1:5)])))
#       1    2      3      4     5 apple banana kiwi mango orange
# 1 mango      banana        mango     0      1    0     2      0
# 2 apple kiwi        banana           1      1    1     0      0
# 3             mango                  0      0    0     1      0
# 4 mango       apple                  1      0    0     1      0
# 5                   orange           0      0    0     0      1
# 6                                    2      2    1     4      1