首页 > 解决方案 > 如果一组行不包含特定单词,则过滤 dplyr 链中的行

问题描述

假设我有以下数据集:

df <- read.table(header=TRUE, text="name value
stranger_things_mc Stranger_Land
stranger_things_confidence 100
stranger_things_importance 1
stranger_things_answer Stranger_Things
immigrant_crime_number 140
immigrant_crime_confidence 100
immigrant_crime_importance 3
immigrant_crime_answer 50
dog_things_mc Stranger_Land
dog_things_confidence 100
dog_things_importance 1
dog_things_answer Stranger_Things
fighting_stats_number 140
fighting_stats_confidence 100
fighting_stats_answer 50")

每第四行包含三个后缀(_confidence、_importance、_answer),但有时不包含(如上面的“fighting_stats”)。一行有时有 (_mc) 后缀,有时它会显示 (_number 或 _slider)。

我想过滤掉任何包含(_number 或 _slider)以及与该 _number 或 _slider 列关联的三行的行。因此,在上面的示例中,结果输出将是:

df <- read.table(header=TRUE, text="name value
stranger_things_mc Stranger_Land
stranger_things_confidence 100
stranger_things_importance 1
stranger_things_answer Stranger_Things
dog_things_mc Stranger_Land
dog_things_confidence 100
dog_things_importance 1
dog_things_answer Stranger_Things")

我可以像这样过滤掉特定的列:

final_results <- df %>% 
  filter(!str_detect(name, "_number") & !str_detect(name, "_slider"))

但无法弄清楚如何删除所有关联的列。一般算法应该是:

首先,在名称列中找到带有“_number”或“_slider”的行,然后抓取它之前的文本。在上面的示例中,这将是“fighting_stats”和“immigrant_crime”。然后,删除任何包含该文本的行。

标签: rdplyr

解决方案


我们根据每四行是一个新块glfilterfirst_number_sliderungroup

library(dplyr)
df %>% 
    group_by(grp = as.integer(gl(n(), 4, n()))) %>% 
    filter(!str_detect(first(name), "_(number|slider)")) %>%
    ungroup %>%
    select(-grp)

更新

根据来自 OP 的注释,即块由它们的公共前缀确定,然后提取第一个word,将其用作分组变量并filter像以前一样执行

library(stringr)
df %>%
  group_by(grp = word(name, 1, sep="_")) %>% 
  filter(!str_detect(first(name), "_(number|slider)"))

并且该ungroup部分与以前相同

如果有重复的前缀,即不相邻的前缀并且需要被视为单独的块,则使用rleidfromdata.table创建分组变量

df %>%
  group_by(grp = rleid(word(name, 1, sep="_"))) %>%
  filter(!str_detect(first(name), "_(number|slider)"))

推荐阅读