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

如何基于分组大小在R语言中对DataFrame进行条件筛选?

解决分组条件筛选问题

首先明确你的需求:每个ID保留一条记录,优先按place == place1筛选;若筛选后该ID仍有多条,再按test == test1筛选,最终每个ID留一条记录。

你的原代码存在两个核心问题:

  • 条件判断逻辑偏差:if(n()>=2)是判断原分组的行数,而非place==place1筛选后的分组行数,导致筛选逻辑完全不符合预期
  • 末尾filter(n()==1)直接丢弃了筛选后仍有多行的分组,违背了你“保留一条”的核心需求

推荐解决方案(简洁版)

用优先级打分的方式标记每行的符合程度,取每个ID优先级最高的第一行:

library(dplyr)

data1 %>%
  group_by(ID) %>%
  # 标记优先级:同时满足两个条件 > 只满足place条件 > 其他情况
  mutate(
    priority = case_when(
      place == place1 & test == test1 ~ 3,
      place == place1 ~ 2,
      TRUE ~ 1
    )
  ) %>%
  # 按优先级降序排列,取第一行
  arrange(desc(priority)) %>%
  slice_head(n = 1) %>%
  # 移除辅助的优先级列
  select(-priority) %>%
  ungroup()

运行结果:

# A tibble: 4 × 6
     ID town    place place1 test  test1
  <dbl> <chr>   <chr> <chr>  <chr> <chr>
1     1 Town A  A     A      G     G    
2     3 Town A  B     B      B     B    
3     5 Town B  A     A      A     A    
4     6 Town A  B     D      B     B    

分步处理版(逻辑更直观)

如果需要严格遵循“先筛place,再筛test”的分步逻辑,用group_modify逐组处理:

library(dplyr)

data1 %>%
  group_by(ID) %>%
  group_modify(function(.x, .y) {
    # 第一步:筛选place == place1的行
    step1 <- .x %>% filter(place == place1)
    
    # 若第一步后仍有多行,执行第二步筛选
    if (nrow(step1) > 1) {
      step2 <- step1 %>% filter(test == test1)
      # 第二步有结果则取第一行,否则取第一步的第一行
      if (nrow(step2) > 0) {
        slice_head(step2, n = 1)
      } else {
        slice_head(step1, n = 1)
      }
    } else if (nrow(step1) == 0) {
      # 第一步无匹配结果时,取原组第一行(可根据需求调整规则)
      slice_head(.x, n = 1)
    } else {
      # 第一步后仅一行,直接保留
      step1
    }
  }) %>%
  ungroup()

这个版本和简洁版结果一致,更适合需要明确分步逻辑的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 11:52:29