如何按一列分组计算多列中因子的出现次数?

6

我有一个看似简单的问题,但我无法弄清如何得到我想要的精确结果。

我的数据长这样:

      Job     C/C++     Java     Python
  Student     FALSE     TRUE      FALSE
Developer      TRUE     TRUE       TRUE
Developer      TRUE     TRUE      FALSE
 Sysadmin      TRUE    FALSE      FALSE
  Student     FALSE     TRUE       TRUE

我希望按“工作”列分组,并计算每列中 TRUE 的数量。我的期望输出如下:

      Job     C/C++     Java     Python
  Student         0        2          1
Developer         2        2          1 
 Sysadmin         1        0          0

非常感谢您的帮助。


1
你能描述一下你在问题中尝试过的内容吗? - Caramiriel
2个回答

9
假设你的数据框叫作“temp”,只需使用 aggregate 函数即可:
aggregate(. ~ Job, temp, sum)
#         Job C.C.. Java Python
# 1 Developer     2    2      1
# 2   Student     0    2      1
# 3  Sysadmin     1    0      0

这里的逻辑是TRUEFALSE分别等于数值"1"和"0",因此在聚合时可以直接使用sum


为了完整性,还有一种使用"tidyverse"的解决方案:

library(tidyverse)
temp %>% 
  group_by(Job) %>% 
  summarise_all(sum)
# # A tibble: 3 x 4
#   Job       C.C..  Java Python
#   <chr>     <int> <int>  <int>
# 1 Developer     2     2      1
# 2 Student       0     2      1
# 3 Sysadmin      1     0      0

这里是易于复制和粘贴的数据格式。此格式通过使用dput(您的实际数据框名称)获取,当您将R相关问题发布到Stack Overflow时,应使用此格式。

temp <- structure(list(Job = c("Student", "Developer", "Developer", "Sysadmin", 
          "Student"), C.C.. = c(FALSE, TRUE, TRUE, TRUE, FALSE), Java = c(TRUE, 
          TRUE, TRUE, FALSE, TRUE), Python = c(FALSE, TRUE, FALSE, FALSE, TRUE)),
          .Names = c("Job", "C.C..", "Java", "Python"), class = "data.frame", 
          row.names = c(NA, -5L))

7

替代方案plyrdata.table

data.table:

require(data.table)
tmp.dt <- data.table(temp, key="Job")
tmp.dt[, lapply(.SD, sum), by=Job]

#         Job C.C.. Java Python
# 1: Developer     2    2      1
# 2:   Student     0    2      1
# 3:  Sysadmin     1    0      0

plyr:

require(plyr)
ddply(temp, .(Job), function(x) colSums(x[-1]))

#         Job C.C.. Java Python
# 1 Developer     2    2      1
# 2   Student     0    2      1
# 3  Sysadmin     1    0      0

编辑:如果你需要计算Newbie的数量而不是TRUE/FALSE,则可以使用以下方法:

使用data.table:

require(data.table)
tmp.dt <- data.table(temp, key="Job")
tmp.dt[, lapply(.SD, function(x) sum(x == "Newbie")), by=Job]

使用 Plyr:

require(plyr)
ddply(temp, .(Job), function(x) colSums(x[-1] == "Newbie"))

我更喜欢data.table的答案,但有备选方案也很好。 - A5C1D2H2I1M1N2O1R2T1
这非常好,我认为我会使用这个解决方案。不过还有一个问题:如果数据不是TRUE/FALSE,而是任意字符串,你会怎么做呢?比如说,如果我想要计算Python中"Newbie"的数量? - user2145843
1
@user2145843,欢迎来到Stack Overflow。请注意您点击的“提问”按钮,以便您可以提出第一个问题。您在此评论中的后续问题与之前的问题不同,因此应被视为不同的问题。但是,在提出新问题之前,请务必搜索任何类似的问题。 - A5C1D2H2I1M1N2O1R2T1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接