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

如何按条件重排分组DataFrame中指定行?(优先用tidyverse)

Absolutely, you can solve this problem with the tidyverse! Let's walk through a step-by-step solution that groups your data by name, finds the correct spot for each id == "i" row, and rearranges the rows to meet your conditions.

Step 1: Load tidyverse and define a helper function

First, we'll create a custom function to handle the rearrangement logic for each name group:

library(tidyverse)

rearrange_group <- function(group_df) {
  # Split the group into the "i" row and all "s" rows
  i_row <- group_df %>% filter(id == "i")
  s_rows <- group_df %>% filter(id != "i")
  
  # If there's no "i" row in the group, return the original rows
  if (nrow(i_row) == 0) return(s_rows)
  
  # Only check middle positions (we need both lag and lead rows for your condition)
  possible_positions <- 2:(nrow(s_rows))
  
  # Find positions where the "i" row meets your criteria
  valid_positions <- possible_positions %>%
    map_lgl(function(pos) {
      # Get the surrounding rows' values
      prev_var1 <- s_rows$var1[pos - 1]
      next_var1 <- s_rows$var1[pos]
      prev_var2 <- s_rows$var2[pos - 1]
      next_var2 <- s_rows$var2[pos]
      
      # Check all four conditions
      i_row$var1 > prev_var1 && i_row$var1 < next_var1 &&
        i_row$var2 > prev_var2 && i_row$var2 < next_var2
    })
  
  # Pick the first valid position (adjust if you need a different priority)
  insert_pos <- possible_positions[valid_positions][1]
  
  # Insert the "i" row into the correct spot and recombine
  rearranged_group <- bind_rows(
    s_rows %>% slice(1:(insert_pos - 1)),
    i_row,
    s_rows %>% slice(insert_pos:nrow(s_rows))
  )
  
  return(rearranged_group)
}

Step 2: Apply the function to your data

Now we'll use group_modify to run this function on each name group:

# Your original data
df <- data.frame(
  name = c(1,1,1,1,1,2,2,2,2,2),
  id = c("s","s","s","i","s","s","i","s","s","s"),
  var1 = c(3,5,6,4,-7,2,1,-1,3,-6),
  var2 = c(2,6,-7,5,-9,7,3,2,4,-9)
)

# Rearrange the data
df_output <- df %>%
  group_by(name) %>%
  group_modify(~ rearrange_group(.x)) %>%
  ungroup()

# Check the result
df_output

Step 3: Verify the output

This will produce exactly the output you're expecting:

# A tibble: 10 × 4
    name id     var1  var2
   <dbl> <chr> <dbl> <dbl>
 1     1 s         3     2
 2     1 i         4     5
 3     1 s         5     6
 4     1 s         6    -7
 5     1 s        -7    -9
 6     2 s         2     7
 7     2 s        -1     2
 8     2 i         1     3
 9     2 s         3     4
10    2 s        -6    -9

Key notes:

  • The function handles edge cases like groups with no i rows gracefully.
  • If multiple positions meet your criteria, it picks the first one—you can adjust this to select the last or another position if needed.
  • group_modify is a tidyverse tool designed exactly for this kind of per-group custom transformation.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:22:27