如何用简便方法在R中实现分组行的均值变换及标准差计算?
问题描述
我有如下R语言数据框:
df<-structure(list(R1 = c(512L, 44620L, 69500L, 91120L, 98870L), R2 = c(587L, 38500L, 67370L, 94870L, 88120L), R3 = c(587L, 39370L, 57500L, 96870L, 85370L), R1.1 = c(737L, 2812L, 4050L, 6400L, 4762L), R2.1 = c(450L, 2587L, 3900L, 7287L, 5550L), R3.1 = c(712L, 2175L, 4675L, 6687L, 4125L)), class = "data.frame", row.names = c(NA, -5L))
数据展示:
R1 R2 R3 R1.1 R2.1 R3.1 1 512 587 587 737 450 712 2 44620 38500 39370 2812 2587 2175 3 69500 67370 57500 4050 3900 4675 4 91120 94870 96870 6400 7287 6687 5 98870 88120 85370 4762 5550 4125
需要完成的计算:
- 将数据分为两组列:第一组
R1、R2、R3,第二组R1.1、R2.1、R3.1 - 对每组的第2至5行,执行计算:
((该行三列均值 - 组内第一行三列均值) - 1822.9)/4167.5 - 对每组每行的三列标准差执行计算:
(标准差 - 1822.9)/4167.5
希望找到更简便的实现方式,最终得到包含变换后数据及对应标准差的结果。
优化实现方案
方案一:用tidyverse工具链(简洁易读)
先加载依赖包:
library(dplyr) library(tidyr)
执行数据处理与计算:
# 定义固定参数 const1 <- 1822.9 const2 <- 4167.5 # 转长格式并分组统计均值、标准差 df_processed <- df %>% mutate(row_id = row_number()) %>% pivot_longer(-row_id, names_to = "group", names_pattern = "(R\\d(?:\\.1)?)", values_to = "value") %>% mutate(group = ifelse(grepl("\\.1$", group), "group2", "group1")) %>% group_by(row_id, group) %>% summarise( row_mean = mean(value), row_sd = sd(value), .groups = "drop" ) # 提取每组第一行的基准均值 base_means <- df_processed %>% filter(row_id == 1) %>% select(group, base_mean = row_mean) # 合并基准值并完成最终变换 final_result <- df_processed %>% left_join(base_means, by = "group") %>% mutate( transformed_mean = ifelse(row_id >= 2, ((row_mean - base_mean) - const1)/const2, NA), transformed_sd = (row_sd - const1)/const2 ) %>% pivot_wider( names_from = group, values_from = c(transformed_mean, transformed_sd), names_glue = "{group}_{.value}" ) # 查看结果 print(final_result)
方案二:基础R实现(无额外依赖)
# 定义两组列的索引 groups <- list(group1 = 1:3, group2 = 4:6) # 批量处理每组数据 result_list <- lapply(groups, function(cols) { row_means <- rowMeans(df[, cols]) row_sds <- apply(df[, cols], 1, sd) base_mean <- row_means[1] # 计算变换后的值 trans_mean <- ifelse(1:nrow(df) >=2, ((row_means - base_mean) - 1822.9)/4167.5, NA) trans_sd <- (row_sds - 1822.9)/4167.5 data.frame(trans_mean, trans_sd) }) # 合并结果并命名列 final_result <- do.call(cbind, result_list) colnames(final_result) <- c("group1_transformed_mean", "group1_transformed_sd", "group2_transformed_mean", "group2_transformed_sd") # 查看结果 print(final_result)
内容的提问来源于stack exchange,提问作者nik
相关产品推荐
相关产品推荐

