组合多个条件过滤R中的行

r1zk6ea1  于 2023-01-22  发布在  其他
关注(0)|答案(3)|浏览(119)

这是个新手问题。
我有一个数据框架,其中包括所有的在线调查的答复,总共在89列。
由于在线调查有时填写的人谁不真正关心,谁只是把响应值很容易填写,我想过滤掉令人难以置信的行,有人简单地击中一个极值一遍又一遍.
我想过滤掉这些列都具有值“9”或都具有值“1”的行:

  • “社交关系强”
  • “社交关系薄弱”
  • '社会_关系_二阶'
  • '社会身份生活方式'
  • “社会身份政治”
  • “社会垂直社会资本”
  • “社会垂直网络资本”

下面是我的代码(包括tidyverse和dplyr包):

data-cleaned <- data_raw %>% 
         fdaten_bereinigt <- rohdaten_basis %>% 
     filter(sociald_ties_strong == 9 & sociald_ties_weak == 9 & sociald_ties_secondorder == 9 & sociald_identity_lifestyle == 9 & sociald_identity_politics == 9 & sociald_vertical_socialcapital == 9 & sociald_vertical_networkcapital == 9)  %>%

     filter(sociald_ties_strong == 1 & sociald_ties_weak == 1 & sociald_ties_secondorder == 1 & sociald_identity_lifestyle == 1 & sociald_identity_politics == 1 & sociald_vertical_socialcapital == 1 & sociald_vertical_networkcapital == 1)

但是,我似乎在逻辑和/或语法中遗漏了一些东西,因为这会过滤掉许多行。
我的数据清理将包括更多类似上面的条件字符串,以排 debugging 误的或自动化的行,但首先我想学习如何正确处理。
可能是两个(或更多)过滤器管道在一起不是一个好主意的方式,我这样做?任何建议,欢迎!
我期望过滤掉满足所有条件的少数行,可能占总观察值的0.5%。

62lalag4

62lalag41#

你的代码有几个问题。首先,你有两个任务在你的管道中:

cleaned <- data_raw %>% 
         fdaten_bereinigt <- rohdaten_basis %>% 
    # ...

我假设这是个错误否则,你想干什么就不清楚了
第二,filter() * 保留满足条件的值,并删除其他所有值。因此,当前第一个filter() * 只保留所有值都为9的行。然后,第二个filter()只查找所有值都为1的行-其中没有行,因为这些行已在上一步中删除-因此,您将得到一个空 Dataframe 。
要获得您想要的结果,请使用!()对条件求反:

library(dplyr)

fdaten_bereinigt <- rohdaten_basis %>% 
  filter(!(sociald_ties_strong == 9 & sociald_ties_weak == 9 & sociald_ties_secondorder == 9 & sociald_identity_lifestyle == 9 & sociald_identity_politics == 9 & sociald_vertical_socialcapital == 9 & sociald_vertical_networkcapital == 9))  %>%
  # ...

第三,使用dplyr::if_all()可以更简洁地完成此操作:

fdaten_bereinigt <- rohdaten_basis %>% 
  filter(
    !if_all(sociald_ties_strong:sociald_vertical_networkcapital, \(x) x == 9),
    !if_all(sociald_ties_strong:sociald_vertical_networkcapital, \(x) x == 1)
 )
ljo96ir5

ljo96ir52#

你可以创建一个你想要检查的变量向量,然后使用filter(if_all(all_of(VECTOR), ~.x != 1) & if_all(all_of(VECTOR), ~.x != 9))

qs <- c("A", "B", "C")

dat <- data.frame("A" = 1:9,
                  "B" = 1:9,
                  "C" = 1:9)
  A B C
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
5 5 5 5
6 6 6 6
7 7 7 7
8 8 8 8
9 9 9 9

dat |> 
  filter(if_all(all_of(qs), ~.x != 1) & if_all(all_of(qs), ~.x != 9))
  A B C
1 2 2 2
2 3 3 3
3 4 4 4
4 5 5 5
5 6 6 6
6 7 7 7
7 8 8 8
7vux5j2d

7vux5j2d3#

当很难弄清楚在dplyr中要做什么时,通常将数据重新塑造成不同的形式会更容易。
可以使用pivot_longer将数据放入长格式:

dat <- data.frame("A" = 1:9,
                  "B" = 1:9,
                  "C" = 1:9)

dat_long <- 
dat %>% 
    mutate(id = row_number()) %>% 
    pivot_longer(
        cols = c(A, B, C),
        names_to = 'column',
        values_to = 'value'
    )

> dat_long
# A tibble: 27 × 3
      id column value
   <int> <chr>  <int>
 1     1 A          1
 2     1 B          1
 3     1 C          1
 4     2 A          2
 5     2 B          2
 6     2 C          2
 7     3 A          3
 8     3 B          3
 9     3 C          3
10     4 A          4
# … with 17 more rows

现在,通过group by和filter,它变得相当简单:

dat_filtered <- 
dat_long %>% 
    group_by(id) %>% 
    filter(!all(value == 1)) %>% 
    filter(!all(value == 9))

> dat_filtered
# A tibble: 21 × 3
# Groups:   id [7]
      id column value
   <int> <chr>  <int>
 1     2 A          2
 2     2 B          2
 3     2 C          2
 4     3 A          3
 5     3 B          3
 6     3 C          3
 7     4 A          4
 8     4 B          4
 9     4 C          4
10     5 A          5
# … with 11 more rows

最后,您可以将数据移回原始表单:

dat_filtered %>% 
    pivot_wider(
        names_from = column,
        values_from = value
    )

 A tibble: 7 × 4
# Groups:   id [7]
     id     A     B     C
  <int> <int> <int> <int>
1     2     2     2     2
2     3     3     3     3
3     4     4     4     4
4     5     5     5     5
5     6     6     6     6
6     7     7     7     7
7     8     8     8     8

相关问题