R语言中使用mutate()计算差异倍数时出错的解决咨询
问题与解决:计算分组差异倍数时的长度不匹配错误
问题背景
构造数据的代码:
barcode <- c("barcode1", "barcode1", "barcode2", "barcode2", "barcode3","barcode3","barcode1","barcode1","barcode2","barcode2","barcode3","barcode3") sampleID <- rep(paste0("sampleID_", 1:12)) bc_rel_abun <- runif(length(sampleID), min = 0, max = 1) Nature <- rep(c("Control", "Case"), each = 6) df <- data.frame(barcode, sampleID, bc_rel_abun,Nature)
先通过分组计算均值:
df<- df %>% group_by(barcode,Nature) %>% mutate(bc_rel_abun_repli_comb = mean(bc_rel_abun))
随后尝试计算每个barcode的Control与Case组差异倍数时出错:
df %>% group_by(barcode) %>% mutate(foldchange = (bc_rel_abun_repli_comb[Nature == "Control"] - bc_rel_abun_repli_comb[Nature == "Case"]) / bc_rel_abun_repli_comb[Nature == "Control"])
错误信息:
Error in `mutate()`: ℹ In argument: `foldchange = ... / bc_rel_abun[Nature == "Control"]`. ℹ In group 1: `barcode = "AAAAAAAAAGATAATTTACATTAGG"`. Caused by error: ! `foldchange` must be size 4 or 1, not 2.
期望输出:
barcode Nature Foldchange barcode1 Controlvscase 2.7 barcode2 Controlvscase -0.3 barcode3 Controlvscase 0.2
错误原因
按barcode分组后,每个组包含4行数据(2个Control样本、2个Case样本)。当执行bc_rel_abun_repli_comb[Nature == "Control"]时,会返回2个完全相同的均值(因为同一barcode的Control组均值已通过mutate统一赋值),同理bc_rel_abun_repli_comb[Nature == "Case"]也返回2个相同值。两者计算后得到长度为2的向量,但mutate要求新列的长度要么与组内行数(4)一致,要么为1(自动广播到所有行),因此出现长度不匹配的错误。
解决方法
方法1:生成期望的汇总格式(每个barcode一行)
直接先按barcode和Nature汇总均值,再转宽格式计算差异倍数,最后整理成目标结构:
library(dplyr) library(tidyr) # 汇总均值并计算差异倍数 summary_result <- df %>% # 先得到每个barcode+Nature的均值,替代原mutate步骤(更高效) group_by(barcode, Nature) %>% summarize(bc_mean = mean(bc_rel_abun), .groups = "drop") %>% # 转宽格式,将Control和Case转为列 pivot_wider(names_from = Nature, values_from = bc_mean) %>% # 计算差异倍数并添加Nature列 mutate( Foldchange = (Control - Case) / Control, Nature = "Controlvscase" ) %>% # 调整列顺序到目标格式 select(barcode, Nature, Foldchange) print(summary_result)
方法2:在原数据框中添加差异倍数列
如果需要保留原数据的所有行,同时为每个barcode添加统一的差异倍数列,可通过first()提取单值避免长度问题:
df_with_foldchange <- df %>% group_by(barcode) %>% mutate( # 提取Control组的均值(取第一个值即可,同组内所有Control行的均值相同) ctrl_mean = first(bc_rel_abun_repli_comb[Nature == "Control"]), # 提取Case组的均值 case_mean = first(bc_rel_abun_repli_comb[Nature == "Case"]), # 计算差异倍数 foldchange = (ctrl_mean - case_mean) / ctrl_mean ) %>% ungroup() print(df_with_foldchange)
内容的提问来源于stack exchange,提问作者Steffi Ma
相关产品推荐
相关产品推荐

