如何在R中将apply输出的行唯一值计数转为指定格式数据框?
问题:按ID统计数值出现次数并重塑数据框
先复现原始数据:
library(dplyr) dat <- data.frame( id = c(2341, 5849, 9085, 8570, 9918), week_1 = c("NULL", 0, 3, 5, 0), week_4 = c(0, 0, 2, 0, 3), week_8 = c(0, 1, 1, 4, 1) ) df <- dat %>% mutate_all(~replace(., lengths(.) == 0, NA)) %>% as.data.frame()
原始数据输出:
id week_1 week_4 week_8 1 2341 NULL 0 0 2 5849 0 0 1 3 9085 3 2 1 4 8570 5 0 4 5 9918 0 3 1
需求是按每个ID统计0-5的出现次数,生成r0到r5列,目标结果如下:
id r0 r1 r2 r3 r4 r5 1 2341 2 0 0 0 0 0 2 5849 2 1 0 0 0 0 3 9085 0 1 1 1 0 0 4 8570 1 0 0 0 1 1 5 9918 1 1 0 1 0 0
解决方案1:使用tidyverse工具链
这种方法逻辑直观,符合数据整理的常规流程:
library(tidyr) library(dplyr) # 1. 转成长格式,处理"NULL"为NA并过滤,将value转为数值型 long_df <- df %>% pivot_longer(cols = -id, names_to = "week", values_to = "value") %>% mutate(value = ifelse(value == "NULL", NA, as.numeric(value))) %>% filter(!is.na(value)) # 2. 按id和value计数,再转宽格式填充0,补充缺失列并排序 result_df <- long_df %>% count(id, value) %>% pivot_wider( id_cols = id, names_from = value, names_prefix = "r", values_from = n, values_fill = 0 ) %>% mutate(across(paste0("r", 0:5), ~ifelse(is.na(.), 0, .))) %>% select(id, paste0("r", 0:5)) print(result_df)
输出结果:
# A tibble: 5 × 7 id r0 r1 r2 r3 r4 r5 <dbl> <int> <int> <int> <int> <int> <int> 1 2341 2 0 0 0 0 0 2 5849 2 1 0 0 0 0 3 9085 0 1 1 1 0 0 4 8570 1 0 0 0 1 1 5 9918 1 1 0 1 0 0
解决方案2:使用base R实现
若偏好base R,可通过行循环结合因子统计完成:
# 定义需要统计的目标数值范围 target_vals <- 0:5 # 逐行处理数据 result_list <- lapply(1:nrow(df), function(i) { row_data <- df[i, -1] # 转换"NULL"为NA并过滤,转为数值型 row_data <- as.numeric(ifelse(row_data == "NULL", NA, row_data)) row_data <- row_data[!is.na(row_data)] # 用因子强制包含所有目标值,再统计次数 tab <- table(factor(row_data, levels = target_vals)) # 组合id和统计结果 c(df$id[i], as.integer(tab)) }) # 转换为数据框并命名列 result_df <- as.data.frame(do.call(rbind, result_list)) colnames(result_df) <- c("id", paste0("r", target_vals)) print(result_df)
输出结果与tidyverse方法完全一致。
内容的提问来源于stack exchange,提问作者TimF
相关产品推荐
相关产品推荐

