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

如何在R中按ID汇总多行状态?(对标SAS BY语句实现)

在R中按ID汇总多行状态(对应SAS的BY/first.last逻辑)

需求:按每个ID判断colour列的状态,分为"red only"、"blue only"或"both",已知SAS可通过BY语句结合first.和last.实现,以下是R中的实现方案。

示例数据

生成数据框的代码:

example <- data.frame(id = c("A1", "A1", "A1", "A2", "A3", "A3", "A4", "A4", "A4", "A5", "A5", "A6"), 
                      colour = c("red", "red", "blue", "red", "blue", "blue", "red", "red", "red", "red", "blue", "red"))

原始数据输出:

id colour
1  A1    red
2  A1    red
3  A1   blue
4  A2    red
5  A3   blue
6  A3   blue
7  A4    red
8  A4    red
9  A4    red
10 A5    red
11 A5   blue
12 A6    red

期望结果

id    status
1 A1      both
2 A2  red only
3 A3 blue only
4 A4  red only
5 A5      both
6 A6  red only

SAS实现参考代码

data table1 (keep=id status);
set example;
by id;
retain red_count blue_count;

if first.id then do;
  red_count = 0;
  blue_count = 0;
end;

if colour = "red" then red_count+1;
if colour = "blue" then blue_count+1;

if last.id then do;
  if red_count > 0 and blue_count > 0 then status = "both";
  else if red_count > 0  then status = "red only";
  else if blue_count > 0 then status = "blue only";
  output;
end;

run;

R实现方案

方法一:使用dplyr包(tidyverse生态)

这是最常用的 tidy 风格实现,逻辑清晰直观:

library(dplyr)

# 处理数据
result <- example %>%
  # 按ID分组
  group_by(id) %>%
  # 计算组内是否存在red和blue
  summarise(
    has_red = any(colour == "red"),
    has_blue = any(colour == "blue"),
    .groups = "drop" # 取消分组状态
  ) %>%
  # 根据存在情况生成状态
  mutate(
    status = case_when(
      has_red & has_blue ~ "both",
      has_red ~ "red only",
      has_blue ~ "blue only",
      TRUE ~ "none" # 处理无颜色的边缘情况
    )
  ) %>%
  # 保留需要的列
  select(id, status)

print(result)

方法二:Base R实现

无需加载额外包,用原生函数完成:

# 按ID分组,提取每个ID的唯一colour值
colour_groups <- tapply(example$colour, example$id, unique)

# 生成结果数据框
result_base <- data.frame(
  id = names(colour_groups),
  status = sapply(colour_groups, function(cols) {
    has_red <- "red" %in% cols
    has_blue <- "blue" %in% cols
    if (has_red & has_blue) "both"
    else if (has_red) "red only"
    else if (has_blue) "blue only"
    else "none"
  })
)

# 按ID排序,和示例结果顺序一致
result_base <- result_base[order(result_base$id), ]
# 重置行名
rownames(result_base) <- NULL

print(result_base)

逻辑对比

SAS中需要手动用retain维护计数变量,通过first.id初始化、last.id触发输出;而R的分组聚合操作直接封装了组内逻辑,无需手动处理组的起始/结束标识,只需关注组内需要判断的条件即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 04:55:37