You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用dplyr按class分组计算行间多列绝对差并生成差异列?

用dplyr实现分组计算分数绝对差并生成对应ID列

给定包含class、学生id及q1-q4科目分数的数据框,需完成以下操作:

  • 按class分组
  • 计算每行与同组其他行的q1-q4列绝对差之和
  • 基于该差值生成diff0、diff1、diff2、diff3列,分别记录同组内与当前行差值为0、1、2、3的其他学生id(无匹配则填NA)

输入数据

class   id  q1  q2  q3  q4
Ali     12  1   2   3   3
Tom     16  1   2   4   2
Tom     18  1   2   3   4
Ali     24  2   2   4   3
Ali     35  2   2   4   3
Tom     36  1   2   4   2

数据的dput结构:

structure(list(class = 
c("Ali", "Tom", "Tom", "Ali", "Ali", "Tom"), 
id = c(12L, 16L, 18L, 24L, 35L, 36L), 
q1 = c(1L, 1L, 1L, 2L, 2L, 1L), 
q2 = c(2L, 2L, 2L, 2L, 2L, 2L), 
q3 = c(3L, 4L, 3L, 4L, 4L, 4L), 
q4 = c(3L, 2L, 4L, 3L, 3L, 2L)), row.names = c(NA, -6L), class = "data.frame")

dplyr实现方案

library(dplyr)
library(tidyr)

df <- structure(list(class = c("Ali", "Tom", "Tom", "Ali", "Ali", "Tom"), 
                     id = c(12L, 16L, 18L, 24L, 35L, 36L), 
                     q1 = c(1L, 1L, 1L, 2L, 2L, 1L), 
                     q2 = c(2L, 2L, 2L, 2L, 2L, 2L), 
                     q3 = c(3L, 4L, 3L, 4L, 4L, 4L), 
                     q4 = c(3L, 2L, 4L, 3L, 3L, 2L)), row.names = c(NA, -6L), class = "data.frame")

result <- df %>%
  group_by(class) %>%
  # 为每组内的每行生成同组所有数据的列表并展开
  mutate(temp = list(cur_data())) %>%
  unnest(temp) %>%
  # 排除行与自身的匹配
  filter(id != temp.id) %>%
  # 计算四科分数的绝对差之和
  mutate(diff_sum = abs(q1 - temp.q1) + abs(q2 - temp.q2) + abs(q3 - temp.q3) + abs(q4 - temp.q4)) %>%
  # 按原行的class和id分组,整理不同差值对应的id字符串
  group_by(class, id, q1, q2, q3, q4) %>%
  summarise(
    diff0 = ifelse(any(diff_sum == 0), paste0(temp.id[diff_sum == 0], collapse = ","), NA),
    diff1 = ifelse(any(diff_sum == 1), paste0(temp.id[diff_sum == 1], collapse = ","), NA),
    diff2 = ifelse(any(diff_sum == 2), paste0(temp.id[diff_sum == 2], collapse = ","), NA),
    diff3 = ifelse(any(diff_sum == 3), paste0(temp.id[diff_sum == 3], collapse = ","), NA),
    .groups = "drop"
  )

print(result)

代码说明

  1. 分组匹配同组数据:通过mutate(temp = list(cur_data()))为每组内的每行生成包含同组所有数据的列表,再用unnest展开,实现每行与同组其他行的全量匹配。
  2. 过滤自身匹配:用filter(id != temp.id)剔除行与自身的无效匹配。
  3. 计算绝对差总和:对q1-q4四列分别计算绝对差后求和,得到每行与同组其他行的分数差异值diff_sum。
  4. 生成目标列:按原行的class和id分组,分别筛选出diff_sum为0、1、2、3的学生id,用paste0合并为字符串,无匹配项则设为NA。

输出结果

# A tibble: 6 × 10
  class    id    q1    q2    q3    q4 diff0 diff1 diff2 diff3
  <chr> <int> <int> <int> <int> <int> <chr> <chr> <chr> <chr>
1 Ali      12     1     2     3     3 NA    NA    24,35 NA   
2 Ali      24     2     2     4     3 35    NA    12    NA   
3 Ali      35     2     2     4     3 24    NA    12    NA   
4 Tom      16     1     2     4     2 36    NA    NA    18   
5 Tom      18     1     2     3     4 NA    NA    NA    16,36
6 Tom      36     1     2     4     2 16    NA    NA    18   

内容的提问来源于stack exchange,提问作者Sandy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 00:40:30