R语言分组数据处理:如何筛选每组的中间行?
Hey there! Let's figure out how to grab the middle row for each group in your data frame.
First, let's recap your setup to make sure we're on the same page:
Your original data frame is defined as:
df <- data.frame(id=c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3), x=c(1,2,3,3,5,1,4,3,1,2,8,9,3,1,0))
And you already know how to get the first row per group with:
df %>% group_by(id) %>% filter(row_number()==1)
Getting the middle row per group
The key here is to calculate the middle position using the total number of rows in each group (we can get that with n() in dplyr).
1. For groups with an odd number of rows (like your example, 5 rows per group)
Since each of your groups has 5 rows, the middle row is the 3rd one. We can calculate this position with ceiling(n()/2) (or floor(n()/2) + 1—both give the same result for odd counts).
You can use either filter() or the more concise slice() function:
library(dplyr) # Using filter() df %>% group_by(id) %>% filter(row_number() == ceiling(n()/2)) # Or using slice() (cleaner for row selection) df %>% group_by(id) %>% slice(ceiling(n()/2))
Running either of these will return the 3rd row for each group:
# A tibble: 3 × 2 # Groups: id [3] id x <dbl> <dbl> 1 1 3 2 2 3 3 3 3
2. Handling groups with even numbers of rows
If your data had groups with even row counts (e.g., 4 rows), you might want to choose either the upper-middle or lower-middle row:
- To get the lower-middle row (2nd row in a 4-row group): use
floor(n()/2) - To get the upper-middle row (3rd row in a 4-row group): use
floor(n()/2) + 1 - To get both middle rows: use
row_number() %in% c(floor(n()/2), floor(n()/2)+1)
Example for even-row groups:
# Sample data with a 4-row group df_even <- data.frame(id=c(1,1,1,1,2,2,2,2,2), x=c(10,20,30,40,5,6,7,8,9)) # Get upper-middle row for each group df_even %>% group_by(id) %>% slice(floor(n()/2) + 1)
Why this works
n()returns the total number of rows in the current groupceiling()andfloor()adjust the division result to get the correct integer row positionslice()is designed for selecting rows by position, making the code more readable than usingfilter()withrow_number()
内容的提问来源于stack exchange,提问作者89_Simple

