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

如何按inst分组查找满足当前与下一个val相等的swi值?

问题描述

我有一个包含3列的dataframe,代码如下:

df <- data.frame(
  "inst" = rep(c('a','b','c','d'),4),
  "swi"  = c(rep(0.05,4), rep(0.10,4), rep(0.15,4), rep(0.20,4)),
  "val"  = c(10,12,8,15,11,14,10,15,11,15,13,15,11,15,16,15)
)

该dataframe内容如下:

# A tibble: 16 x 3
# Groups:   inst [4]
   inst    swi   val
   <fct> <dbl> <dbl>
 1 a      0.05    10
 2 b      0.05    12
 3 c      0.05     8
 4 d      0.05    15
 5 a      0.1     11
 6 b      0.1     14
 7 c      0.1     10
 8 d      0.1     15
 9 a      0.15    11
10 b      0.15    15
11 c      0.15    13
12 d      0.15    15
13 a      0.2     11
14 b      0.2     15
15 c      0.2     16
16 d      0.2     15

需求:针对每个唯一的inst,找到对应的swi值,要求该swi对应的val与下一个swi对应的val相等;若不存在满足条件的swi,则返回-1。期望输出如下:

inst  swi
 a    0.1
 b    0.15
 c    -1
 d    0.05
解决方案

使用dplyr包可以高效实现这个需求,以下是具体代码:

library(dplyr)

result <- df %>%
  # 确保每个inst下的swi按升序排列,保证lead取的是下一个更大的swi对应的值
  arrange(inst, swi) %>%
  group_by(inst) %>%
  # 获取当前行的下一行val值
  mutate(next_val = lead(val)) %>%
  # 筛选当前val与下一个val相等的行
  filter(val == next_val) %>%
  # 保留inst和swi列,若有多个符合条件的swi,取第一个(最小的)
  select(inst, swi) %>%
  slice_head(n = 1) %>%
  ungroup() %>%
  # 关联所有唯一inst,确保没有符合条件的inst也被保留
  right_join(distinct(df, inst), by = "inst") %>%
  # 无符合条件的swi替换为-1
  mutate(swi = ifelse(is.na(swi), -1, swi)) %>%
  arrange(inst)

print(result)

执行代码后输出:

# A tibble: 4 x 2
  inst    swi
  <chr> <dbl>
1 a      0.1 
2 b      0.15
3 c     -1   
4 d      0.05

关键逻辑说明

  • arrange(inst, swi):保证每个inst分组内的swi是从小到大排序的,确保lead(val)获取的是下一个更高swi对应的val
  • lead(val):提取当前行的下一行val,用于比较当前和下一个swi的val是否相等
  • slice_head(n = 1):如果某个inst有多个符合条件的swi(比如d的0.05、0.1、0.15都满足),取最小的那个swi
  • right_join(distinct(df, inst)):确保所有原始inst都被包含,避免丢失没有符合条件的行
  • ifelse(is.na(swi), -1, swi):将无匹配的swi值替换为-1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:47:45