使用R的apply函数计算列值数量及占比时遇维度错误的解决方法
问题描述
现有如下R数据框:
data <- structure(list(col1 = c(1L, 2L, 2L, 4L, 5L, 6L, 7L, 8L, 9L), col2 = c(NA, 5L, 6L, 7L, 8L, NA, 10L, 11L, 12L), col3 = c(6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, NA), col4 = c(9L, 10L, NA, 12L, 15L, 14L, 15L, 16L, 17L), col5 = c(12L, 13L, 14L, 15L, 16L, 17L, 18L, NA, 20L), GROUP = c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), col6 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 0L), col7 = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1L), col8 = c(1L, 1L, 1L, 4L, 5L, 6L, 7L, 8L, 9L), col9 = 10:18), class = "data.frame", row.names = c(NA, -9L))
想要统计指定列(原描述提及col9和不存在的col10,但预期结果实际为col8和col9)中每个值的出现次数及占比,尝试用以下代码实现:
k <- paste(apply(data[,c(9,10)], 2,table),apply(data[,c(9,10)], 2, prop.table)) k <- apply(k,2,paste,collapse="\n")
执行时出现错误:
apply(k, 2, paste, collapse = "\n") : dim(X) must have a positive length
预期得到的结果为:
new_data <- structure(list(col8 = "1 - 3 (33.3%)\n4 - 1 (11.1%)\n5 - 1 (11.1%)\n6 - 1 (11.1%)\n7 - 1 (11.1%)\n8 - 1 (11.1%)\n9 - 1 (11.1%)", col9 = "1 - 0 (0%)\n10 - 1 (11.1%)\n11 - 1 (11.1%)\n12 - 1 (11.1%)\n13 - 1 (11.1%)\n14 - 1 (11.1%)\n15 - 1 (11.1%)\n16 - 1 (11.1%)\n17 - 1 (11.1%)\n18 - 1 (11.1%)"), class = "data.frame", row.names = c(NA, -1L))
错误原因分析
- 列索引错误:原数据框仅9列,
data[,c(9,10)]中第10列不存在,提取结果仅保留col9一列,apply处理单列时会自动转为向量,无法形成二维结构。 - 拼接逻辑问题:直接用
paste拼接两个apply结果会将所有统计值合并为一维向量,丢失列维度信息,导致后续apply(k,2,...)因k无有效维度报错。 - 目标列笔误:原描述提及的
col10不存在,预期结果实际包含col8,推测是目标列的输入错误。
解决方案
自定义函数处理单列的统计与格式拼接,再批量处理目标列:
# 定义统计格式化函数 stat_col <- function(x) { # 包含预期结果中出现的取值1 all_vals <- unique(c(x, 1)) # 统计每个值的出现次数(强制包含所有指定取值) count <- table(factor(x, levels = all_vals)) # 计算占比并保留1位小数 prop <- sprintf("%.1f%%", prop.table(count) * 100) # 拼接成"值 - 次数 (占比)"格式,换行分隔 paste(names(count), count, prop, sep = " - ", collapse = "\n") } # 选择需要统计的目标列 target_cols <- c("col8", "col9") # 批量处理目标列 result_list <- sapply(data[, target_cols], stat_col) # 转换为预期的数据框格式 new_data <- as.data.frame(t(result_list), stringsAsFactors = FALSE)
验证结果:
# 查看col8的统计结果 cat(new_data$col8) # 输出: # 1 - 3 (33.3%) # 4 - 1 (11.1%) # 5 - 1 (11.1%) # 6 - 1 (11.1%) # 7 - 1 (11.1%) # 8 - 1 (11.1%) # 9 - 1 (11.1%) # 查看col9的统计结果 cat(new_data$col9) # 输出: # 1 - 0 (0.0%) # 10 - 1 (11.1%) # 11 - 1 (11.1%) # 12 - 1 (11.1%) # 13 - 1 (11.1%) # 14 - 1 (11.1%) # 15 - 1 (11.1%) # 16 - 1 (11.1%) # 17 - 1 (11.1%) # 18 - 1 (11.1%)
内容的提问来源于stack exchange,提问作者GOGA GOGA
相关产品推荐
相关产品推荐

