如何为table()函数生成的列联表添加百分比列与总计列?
解决方案:给三维列联表添加百分比与总计列
一、直接用tidyverse管道实现(推荐)
无需拆分数据,通过tidy工具链直接生成包含频数、百分比和总计的结果表,结构与原列联表一致:
library(tidyverse) library(magrittr) result_df <- data1 %>% select(blockLabel, trial_resp.corr, participant) %>% # 生成基础频数列 count(blockLabel, trial_resp.corr, participant, name = "Freq") %>% # 按被试+实验块分组计算百分比与总计 group_by(participant, blockLabel) %>% mutate( pct = round(Freq / sum(Freq) * 100, 2), # 计算块内百分比并保留两位小数 total = sum(Freq) # 计算每个实验块的总试次数 ) %>% # 转宽表,对齐原列联表结构 pivot_wider( id_cols = c(participant, blockLabel, total), names_from = trial_resp.corr, values_from = c(Freq, pct), names_glue = "{trial_resp.corr}_{.value}" ) %>% ungroup() print(result_df)
输出示例(截取部分):
# A tibble: 15 × 7 participant blockLabel total 0_Freq 1_Freq 0_pct 1_pct <fct> <fct> <int> <int> <int> <dbl> <dbl> 1 pilot01 auditory_only 12 0 12 0 100 2 pilot01 bimodal_focus_aud… 72 1 71 1.39 98.6 3 pilot01 bimodal_focus_vis… 72 3 69 4.17 95.8 4 pilot01 divided 144 74 70 51.4 48.6 5 pilot01 visual_only 12 0 12 0 100
二、迭代实现方法
如果需要用迭代逻辑处理,以下提供三种常见方案:
1. 使用purrr::map(函数式迭代)
library(purrr) # 按被试拆分数据 participant_list <- data1 %>% select(blockLabel, trial_resp.corr, participant) %>% group_split(participant) # 定义单个被试数据的处理函数 process_single_participant <- function(df) { df %>% count(blockLabel, trial_resp.corr, name = "Freq") %>% group_by(blockLabel) %>% mutate( pct = round(Freq / sum(Freq) * 100, 2), total = sum(Freq) ) %>% pivot_wider( id_cols = c(blockLabel, total), names_from = trial_resp.corr, values_from = c(Freq, pct), names_glue = "{trial_resp.corr}_{.value}" ) %>% ungroup() %>% mutate(participant = unique(df$participant)) %>% select(participant, everything()) } # 批量处理并合并结果 map_result <- map_dfr(participant_list, process_single_participant) print(map_result)
2. 使用for循环迭代
# 获取所有被试ID participant_ids <- unique(data1$participant) # 初始化空结果框 loop_result <- tibble() for (pid in participant_ids) { # 提取单个被试数据并处理 sub_processed <- data1 %>% filter(participant == pid) %>% select(blockLabel, trial_resp.corr) %>% count(blockLabel, trial_resp.corr, name = "Freq") %>% group_by(blockLabel) %>% mutate( pct = round(Freq / sum(Freq) * 100, 2), total = sum(Freq) ) %>% pivot_wider( id_cols = c(blockLabel, total), names_from = trial_resp.corr, values_from = c(Freq, pct), names_glue = "{trial_resp.corr}_{.value}" ) %>% ungroup() %>% mutate(participant = pid) %>% select(participant, everything()) # 合并到总结果 loop_result <- bind_rows(loop_result, sub_processed) } print(loop_result)
3. 使用do.call结合lapply
# 用lapply批量处理每个被试 lapply_list <- lapply(participant_ids, function(pid) { data1 %>% filter(participant == pid) %>% select(blockLabel, trial_resp.corr) %>% count(blockLabel, trial_resp.corr, name = "Freq") %>% group_by(blockLabel) %>% mutate( pct = round(Freq / sum(Freq) * 100, 2), total = sum(Freq) ) %>% pivot_wider( id_cols = c(blockLabel, total), names_from = trial_resp.corr, values_from = c(Freq, pct), names_glue = "{trial_resp.corr}_{.value}" ) %>% ungroup() %>% mutate(participant = pid) %>% select(participant, everything()) }) # 用do.call合并结果 do.call_result <- do.call(bind_rows, lapply_list) print(do.call_result)
内容的提问来源于stack exchange,提问作者12666727b9
相关产品推荐
相关产品推荐

