在R中按组对两个DataFrame的向量执行减法运算
按分组对DataFrame进行逐行向量减法运算
需求说明
我有两个R DataFrame:
- 主数据集
df_repr:包含多列数值特征,以及标记分组的group因子列 - 分组向量集
to_subtract:行数等于主数据集的唯一分组数,每行对应一个分组的向量,需要用主数据集中对应分组的每行数据减去该分组的向量
示例数据
主数据集
df_repr <- structure(list(f1 = c(-3.9956064225704, -0.52380279948658, 0.61089389331505, -3.47273625634875, -4.486918671214, -6.1761970731672, -4.62305749757367, -4.42540643005429, -3.61613137597131, -3.29821425516253), f2 = c(-1.57918114753228, -4.10523012500727, -1.80270009366593, -0.00905317702835884, -0.899585192079915, -2.89341515186212, 0.0132542126386332, -3.32639898550135, -0.867793877742314, 0.0911950321630834), f3 = c(-6.02532301769732, -4.90073348094302, -3.73159604513274, -3.55290209472808, -6.63194560195811, 2.69409789701296, -4.17675978927128, -3.84141885970095, -1.20571283849034, 1.54287440902102), group = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L), .Label = c("A", "B"), class = "factor")), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -10L))
分组向量集
to_subtract <- structure(list(group = structure(1:2, .Label = c("A", "B"), class = "factor"), f1 = c(-2.78048744402161, -2.33583431665818), f2 = c(-2.56086962108741, -0.689157827347865), f3 = c(-3.60224982918457, -0.782365376308658)), row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame"))
尝试的代码及报错
我尝试用以下代码实现,但出现错误:
df_repr %>% group_by(group) %>% mutate(across(where(is.numeric), ~ . - to_subtract[to_subtract$group == unique(.$group), -1]))
报错信息:
Error in `mutate()`: ℹ️ In argument: `across(...)`. ℹ️ In group 1: `group = A`. Caused by error in `across()`: ! Can't compute column `f1`. Caused by error in `f1$group`: ! $ operator is invalid for atomic vectors
错误原因:to_subtract[to_subtract$group == unique(.$group), -1]返回的是DataFrame对象,而across中.指代的是当前列的原子向量,向量与DataFrame直接做减法会导致维度不兼容,触发报错。
解决方案
方法1:合并后逐列计算
先将分组向量集合并到主数据集,再对每个特征列减去对应分组的向量值:
library(dplyr) df_repr %>% left_join(to_subtract, by = "group", suffix = c("", "_sub")) %>% mutate(across(starts_with("f"), ~ . - get(paste0(cur_column(), "_sub"))), .keep = "unused")
方法2:分组后提取原子向量
分组后,从to_subtract中提取当前分组的数值向量并转成原子向量,再进行减法:
df_repr %>% group_by(group) %>% mutate(across(where(is.numeric), ~ . - unlist(to_subtract[to_subtract$group == cur_group()$group, -1]))) %>% ungroup()
方法3:矩阵索引匹配
将分组向量集转为矩阵,通过匹配分组索引提取对应向量进行减法:
sub_mat <- as.matrix(to_subtract[, -1]) idx <- match(df_repr$group, to_subtract$group) df_repr %>% mutate(across(where(is.numeric), ~ . - sub_mat[idx, cur_column()]))
期望输出
# # A tibble: 10 × 4 # f1 f2 f3 group # <dbl> <dbl> <dbl> <fct> # 1 -1.22 0.982 -2.42 A # 2 2.26 -1.54 -1.30 A # 3 3.39 0.758 -0.129 A # 4 -0.692 2.55 0.0493 A # 5 -1.71 1.66 -3.03 A # 6 -3.84 -2.20 3.48 B # 7 -2.29 0.702 -3.39 B # 8 -2.09 -2.64 -3.06 B # 9 -1.28 -0.179 -0.423 B # 10 -0.962 0.780 2.33 B
内容的提问来源于stack exchange,提问作者Arseny Sokolov
相关产品推荐
相关产品推荐

