1

假设我有一个 5 x 5 的矩阵,带有水果名称(5 类水果)。我想在这个现有矩阵中添加 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)]))

请帮忙。

4

2 回答 2

2

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

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

  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才能返回逻辑向量。不幸的是, 的维度参数fruits丢失了,并且返回了一个简单的向量,必须将其转换回矩阵。rowSums然后用于总结在每一行中找到搜索词(即水果的名称)的次数。这有效,因为在执行此操作时TRUE转换为 1 和FALSE0。

  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
    
于 2016-02-20T14:56:54.067 回答
2

我们还可以使用计数来熔化和投射数据框。然后添加一行总和:

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
于 2016-02-20T15:31:40.917 回答