HOWTO · R
如何在 R 中计算观测值数量
使用基础 R 和 dplyr 计算 R 数据框中的每一行、符合条件的行,或按组统计出现次数。
本页内容
在 R 数据框中,一个观测值就是一行。使用 nrow() 获取观测值总数,使用带 sum() 的逻辑条件统计匹配的行,或使用 dplyr 的 count() 获取按组的频率。示例使用一个小型数据框,方便你将列名替换为自己的数据。
使用 nrow() 计算所有行
nrow(data) 返回 data 中的行数。当每一行都需要计算时,这是直接的选择。本示例有五行,nrow(students) 提供下方打印的值。
students <- data.frame(
name = c("Ada", "Ben", "Cam", "Dee", "Eli"),
passed = c(TRUE, FALSE, TRUE, TRUE, FALSE),
group = c("A", "A", "B", "B", "B")
)
total <- nrow(students)
cat("Total observations:", total, "\n")
Total observations: 5
对于行的总数,nrow() 比构造逻辑向量更清楚。特别是,with(data, 1) 求值的是标量 1;它不会为每一行创建一个值,因此 sum(with(data, 1)) 不是计算行数的方法。
在基础 R 中计算符合条件的行
若要计算符合某个条件的行,请创建一个逻辑向量并将其传递给 sum()。在 R 中,求和时 TRUE 贡献 1,FALSE 贡献 0。你可以使用 with() 引用数据框的列,而不必重复数据框名称:
sum(with(students, passed))
对于多个条件,使用 & 表示"且",或 | 表示"或"来组合它们。例如,sum(with(students, passed & group == "B")) 计算通过且属于 B 组的学生。使用括号可以让组合条件更易读。
如果条件包含 NA,除非你处理这些值,否则 sum() 会返回 NA。当未知值应从计数中排除时,使用 na.rm = TRUE,如 sum(students$passed, na.rm = TRUE)。对于像 students$score > 70 这样的表达式,这只会计算已知的大于 70 的分数;它不会将缺失的分数视为匹配。
你也可以对数据框取子集,并使用 nrow() 计算其结果行:
nrow(students[students$passed, , drop = FALSE])
drop = FALSE 参数使子集即使只包含一列也保持数据框形式。如果条件可能包含 NA,请先从逻辑索引中移除未知行,例如 students[!is.na(students$passed) & students$passed, , drop = FALSE];否则基础 R 可能会为未知条件加入一整行 NA。当你需要筛选后的行进行后续工作时使用这种方法;当你只需要数量时使用 sum()。如需在另一个示例中查看筛选后计算行数,请参阅按组计算行数。
使用 dplyr 计算行和组
dplyr 提供 filter() 来选择行,并提供 count() 来报告每个组中出现的行数。这些操作回答不同的问题:使用 filter() 再接 nrow() 获取符合条件的行数,使用 count() 获取每个值或值组合的频率。
例如,nrow(dplyr::filter(students, passed)) 计算 passed 值为 TRUE 的学生;当条件为 NA 时,filter() 会丢弃该行。若要计算每个组中的观测值,请使用 dplyr::count(students, group)。若要计算组合,请提供更多分组列,如 dplyr::count(students, group, passed)。这些调用仅供说明,此处并未执行;所提供的执行证据仅涵盖行总数的示例。
count() 会返回分组列和一个默认名为 n 的计数列。它的 wt 参数则是在每个组内对权重列求和,这是加权总计而非普通的行数。对于简单的观测值计数,请勿设置 wt。
选择符合你问题的方法
- 使用
nrow(data)计算每一行。 - 使用
sum(condition)或nrow(data[condition, , drop = FALSE])计算由条件选定的行。 - 当你想用
dplyr计算筛选后的行时,使用filter()和nrow();当你想要按组的频率时,使用count()。
这些选择使结果的含义保持明确:行总数、符合条件的行,或频率表。请检查条件或分组表达式中使用的列是否代表你打算计算的值。