首页 > 解决方案 > 基于删除行的多个标准子集数据框

问题描述

考虑以下由列名“id”和“x”组成的数据框,其中每个 id 重复四次。数据如下:

df<-data.frame("id"=c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4),
                "x"=c(2,2,1,1,2,3,3,3,1,2,2,3,2,2,3,3))

问题是关于如何通过以下标准对数据框进行子集化:

(1) 保留每个 id 的所有条目,如果其在 x 列中的对应值不包含 3 或它的最后一个数字为 3。

(2) 对于给定的 id,在 x 列中有多个 3,将所有数字保持在前 3 之前,并删除剩余的 3。预期的输出如下所示:

   id x
1   1 2
2   1 2
3   1 1
4   1 1
5   2 2
6   2 3
7   3 1
8   3 2
9   3 2
10  3 3
11  4 2
12  4 2
13  4 3 

我熟悉使用 dplyr 包中的“过滤器”功能来子集数据,但由于上述标准的复杂性,这种特殊情况让我感到困惑。对此的任何帮助将不胜感激。

标签: rdataframefiltersubset

解决方案


这是一种使用/创建一些新列来帮助您过滤的解决方案:

library(dplyr)

df<-data.frame("id"=c(1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4),
               "x"=c(2,2,1,1,2,3,3,3,1,2,2,3,2,2,3,3))

df %>%
  group_by(id) %>%                                    # for each id
  mutate(num_threes = sum(x == 3),                    # count number of 3s
         flag = ifelse(unique(num_threes) > 0,        # if there is a 3
                        min(row_number()[x == 3]),    # keep the row of the first 3
                        0)) %>%                       # otherwise put a 0
  filter(num_threes == 0 | row_number() <= flag) %>%  # keep ids with no 3s or up to first 3
  ungroup() %>%
  select(-num_threes, -flag)                          # remove helpful columns

# # A tibble: 13 x 2
#      id     x
#   <dbl> <dbl>
# 1     1     2
# 2     1     2
# 3     1     1
# 4     1     1
# 5     2     2
# 6     2     3
# 7     3     1
# 8     3     2
# 9     3     2
# 10    3     3
# 11    4     2
# 12    4     2
# 13    4     3

推荐阅读