Аккуратный способ фильтрации, но добавление дополнения в таблицу

Допустим, я фильтрую табличку, выполняю некоторую обработку, фильтрую и затем выполняю еще некоторую обработку, но я хочу сохранить дополнение данных, которые я отфильтровал на каждом этапе.

Например. вместо

library(tidyverse)
data(mtcars)
mtcars %>%
  filter(cyl<5) %>%
  filter(gear>3 & wt>3) %>%
  filter(mpg>23)

Я мог бы захотеть что-то подобное, не делая отдельных шагов, когда я сохраняю табличку, делаю еще один шаг, чтобы сохранить дополнение, а затем делаю еще один шаг и т. д.

library(tidyverse)
data(mtcars)
mtcars1 = mtcars %>%
  filter(cyl<5, keep_complement = "mtcars2") %>%
  filter(gear>3 & wt>3, keep_complement = "mtcars3") %>%
  filter(mpg>23, keep_complement = "mtcars4")
# Desired outcome: 4 tibbles mtcars1 to 4

mtcars_final = bind_rows(mtcars1, mtcars2, mtcars3, mtcars4)

Если вам интересно, зачем мне это: у меня есть несколько все более сложных строковых операций для решения проблемы, сначала простое прямое сравнение, затем некоторое регулярное/нечеткое сопоставление строк, а затем что-то, для чего мне, возможно, придется использовать нейронную сеть. Кажется, должен быть какой-то аккуратный способ выполнять дорогостоящие операции только с подмножеством без необходимости писать код в несколько шагов.

т.е. чего я пытаюсь избежать, так это что-то действительно неуклюжее, похожее на это (что также требует, чтобы я сам инвертировал любые операции фильтрации - на практике также необходимо учитывать значения NA и т. д.):

mtcars_tmp <- mtcars %>%
    filter(cyl<5)

mtcars2 <- mtcars %>%
    filter(cyl>=5)

mtcars_tmp2 <- mtcars_tmp %>%
    filter(gear>3 & wt>3)

mtcars3 <- mtcars_tmp %>%
    filter(gear<=3 | wt<=3)

mtcars1 <- mtcars_tmp2 %>%
    filter(mpg>23)

mtcars4 <- mtcars_tmp2 %>%
    filter(mpg<=23)

mtcars_final = bind_rows(mtcars1, mtcars2, mtcars3, mtcars4)

Вы можете сохранить результат фильтрации, а затем использовать его для анти-соединения с оригиналом.

Allan Cameron 06.05.2022 09:07

Вы имеете в виду что-то вроде редактирования, которое я добавил внизу, как я знаю, как это сделать (чего я пытаюсь избежать)?

Björn 06.05.2022 09:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
42
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это создаст дополнение с помощью anti_join и назначит его новому объекту и вернет отфильтрованные результаты, чтобы его можно было использовать как обычное dplyr::filter в конвейере:

library(tidyverse)

#' Filters a data.frame and saves the complement
#' @param keep_complement charachter to name the object the complement is saved to. NULL to not save it.
filter_complement <- function(.data, ..., keep_complement = NULL) {
  res <- dplyr::filter(.data = .data, ...)
  
  if (! is.null(keep_complement)) {
    complement <- dplyr::anti_join(.data, res)
    assign(keep_complement, complement, envir = globalenv())  
  }
  
  res
}

mtcars %>%
  filter(cyl < 5) %>%
  filter(gear > 3 & wt > 3) %>%
  filter(mpg > 23)
#>            mpg cyl  disp hp drat   wt qsec vs am gear carb
#> Merc 240D 24.4   4 146.7 62 3.69 3.19   20  1  0    4    2

mtcars %>%
  filter_complement(cyl < 5, keep_complement = "mtcars2") %>%
  filter_complement(gear > 3 & wt > 3, keep_complement = "mtcars3") %>%
  filter_complement(mpg > 23, keep_complement = "mtcars4")
#> Joining, by = c("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am",
#> "gear", "carb")
#> Joining, by = c("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am",
#> "gear", "carb")
#> Joining, by = c("mpg", "cyl", "disp", "hp", "drat", "wt", "qsec", "vs", "am",
#> "gear", "carb")
#>            mpg cyl  disp hp drat   wt qsec vs am gear carb
#> Merc 240D 24.4   4 146.7 62 3.69 3.19   20  1  0    4    2

mtcars4
#>           mpg cyl  disp hp drat   wt qsec vs am gear carb
#> Merc 230 22.8   4 140.8 95 3.92 3.15 22.9  1  0    4    2
mtcars3
#>                 mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> Datsun 710     22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> Fiat 128       32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
#> Honda Civic    30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
#> Toyota Corolla 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
#> Toyota Corona  21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
#> Fiat X1-9      27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
#> Porsche 914-2  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
#> Lotus Europa   30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
#> Volvo 142E     21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2

Created on 2022-05-06 by the reprex package (v2.0.0)

Спасибо, это действительно делает то, что я хочу. Я предполагаю, что нет встроенного способа сделать это по умолчанию?

Björn 06.05.2022 09:33

Это слишком специфический вариант использования. Пакеты содержат только повторно используемые общие функции, которые можно использовать в качестве строительных блоков для вашего собственного кода.

danlooo 06.05.2022 09:36

Другие вопросы по теме