R: как отфильтровать строки, которые заканчиваются определенными символами списка?

#r #dplyr #tidyverse

#r #dplyr #аккуратная вселенная

Вопрос:

У меня есть фрейм данных, который выглядит следующим образом:

  ----------------- -------- 
| Geography       | Values |
 ----------------- -------- 
| Atlanta, GA     | 78     |
 ----------------- -------- 
| New York, NY    | 30     |
 ----------------- -------- 
| Denver, CO      | 20     |
 ----------------- -------- 
| Omaha, NE       | 178    |
 ----------------- -------- 
| Los Angeles, CA | 58     |
 ----------------- -------- 
| Providence, RI  | 100    |
 ----------------- -------- 
| Little Rock, AR | 20     |
 ----------------- -------- 
| Miami, FL       | 50     |
 ----------------- -------- 
| ...             |        |
 ----------------- -------- 
 

Я бы хотел выполнить операцию в формате tidyverse / dplyr, чтобы я мог отфильтровать любые строки из состояния GA amp; CA. Обратите внимание, что перед аббревиатурой состояния всегда стоит «, » (запятая, за которой следует пробел).

Результирующий фрейм данных должен выглядеть следующим образом:

  ----------------- -------- 
| Geography       | Values |
 ----------------- -------- 
| New York, NY    | 30     |
 ----------------- -------- 
| Denver, CO      | 20     |
 ----------------- -------- 
| Omaha, NE       | 178    |
 ----------------- -------- 
| Providence, RI  | 100    |
 ----------------- -------- 
| Little Rock, AR | 20     |
 ----------------- -------- 
| Miami, FL       | 50     |
 ----------------- -------- 
| ...             |        |
 ----------------- -------- 
 

Реальные данные намного больше, чем в этом простом примере. Он состоит из сотен городов с несколькими городами в штате, поэтому я не могу просто сделать что-то вроде:

 data %>%
filter (Geography == "Atlanta, GA" | Geography == "Los Angeles, CA")
 

Должен ли я создать новый столбец «Состояние», который удаляет последние 2 буквы столбца «География» и фильтрует по этому столбцу «Состояние», или я могу сделать что-то, связанное с регулярным выражением, например:

 exclude_list = c("GA, CA")

data %>%
filter (Geography != end_with(exclude_list))
 

Какой элегантный способ сделать это? Большое спасибо за вашу помощь!

Ответ №1:

Вы можете построить exclude_list как :

 exclude_list = c("GA", "CA")
 

Затем используйте subset как :

 subset(data, !grepl(sprintf('(%s)

Или, если вам нужен  dplyr  ответ, сделайте :

 library(dplyr)
data %>%
  filter(!grepl(sprintf('(%s)

где

 sprintf('(%s)



Если exclude_list слишком велико, ответ на регулярное выражение может завершиться неудачей, в таком случае было бы полезно предложение @thelatemail, где мы сохраняем только имя состояния и сопоставляем их с %in% :
 data[!sub("^. ,\s ", "", data$Geography) %in% exclude_list,]
 



Комментарии:

1. Чем больше я думаю об этих случаях, я не уверен, что создание гигантского регулярного выражения является хорошим масштабируемым решением, когда вы можете сделать что-то подобное dat[!sub("^. ,\s ", "", dat$Geography) %in% exclude_list,] , которое не будет падать или резко замедляться, если exclude_list станет слишком большим.

2. Хм... это правда. Я добавил обновление к ответу

Ответ №2:

Я бы рекомендовал делать это с помощью регулярных выражений. $ В регулярном выражении указывает конец строки. So grepl(" CA$", Geography) вернет true, если география заканчивается пробелом, а буквы CA.

Следовательно, я бы сделал что-то вроде:

 data %>%
  filter(!grepl(" CA$", Geography),
         !grepl(" GA$", Geography))
 

Ответ №3:

data.table Опция с grepl

 > setDT(df)[!grepl(",\s (CA|GA)$", Geography)]
         Geography Values
1:    New York, NY     30
2:      Denver, CO     20
3:       Omaha, NE    178
4:  Providence, RI    100
5: Little Rock, AR     20
6:       Miami, FL     50
 

или subset , если вы используете базовый R

 > subset(df, !grepl(",\s (CA|GA)$", Geography))
        Geography Values
2    New York, NY     30
3      Denver, CO     20
4       Omaha, NE    178
6  Providence, RI    100
7 Little Rock, AR     20
8       Miami, FL     50
 

Данные

 > dput(df)
structure(list(Geography = c("Atlanta, GA", "New York, NY", "Denver, CO", 
"Omaha, NE", "Los Angeles, CA", "Providence, RI", "Little Rock, AR",
"Miami, FL"), Values = c(78L, 30L, 20L, 178L, 58L, 100L, 20L,
50L)), class = c("data.table", "data.frame"), row.names = c(NA,
-8L))
 

,
paste0(exclude_list, collapse = '|')), Geography))
Или, если вам нужен dplyr ответ, сделайте :


где



Если exclude_list слишком велико, ответ на регулярное выражение может завершиться неудачей, в таком случае было бы полезно предложение @thelatemail, где мы сохраняем только имя состояния и сопоставляем их с %in% :


Комментарии:

1. Чем больше я думаю об этих случаях, я не уверен, что создание гигантского регулярного выражения является хорошим масштабируемым решением, когда вы можете сделать что-то подобное dat[!sub("^. ,\s ", "", dat$Geography) %in% exclude_list,] , которое не будет падать или резко замедляться, если exclude_list станет слишком большим.

2. Хм... это правда. Я добавил обновление к ответу

Ответ №2:

Я бы рекомендовал делать это с помощью регулярных выражений. $ В регулярном выражении указывает конец строки. So grepl(" CA$", Geography) вернет true, если география заканчивается пробелом, а буквы CA.

Следовательно, я бы сделал что-то вроде:


Ответ №3:

data.table Опция с grepl


или subset , если вы используете базовый R


Данные


,
paste0(exclude_list, collapse = '|')), Geography))

где



Если exclude_list слишком велико, ответ на регулярное выражение может завершиться неудачей, в таком случае было бы полезно предложение @thelatemail, где мы сохраняем только имя состояния и сопоставляем их с %in% :


Комментарии:

1. Чем больше я думаю об этих случаях, я не уверен, что создание гигантского регулярного выражения является хорошим масштабируемым решением, когда вы можете сделать что-то подобное dat[!sub("^. ,\s ", "", dat$Geography) %in% exclude_list,] , которое не будет падать или резко замедляться, если exclude_list станет слишком большим.

2. Хм… это правда. Я добавил обновление к ответу

Ответ №2:

Я бы рекомендовал делать это с помощью регулярных выражений. $ В регулярном выражении указывает конец строки. So grepl(" CA$", Geography) вернет true, если география заканчивается пробелом, а буквы CA.

Следовательно, я бы сделал что-то вроде:


Ответ №3:

data.table Опция с grepl


или subset , если вы используете базовый R


Данные


,
paste0(exclude_list, collapse = ‘|’)), Geography))

Или, если вам нужен dplyr ответ, сделайте :


где



Если exclude_list слишком велико, ответ на регулярное выражение может завершиться неудачей, в таком случае было бы полезно предложение @thelatemail, где мы сохраняем только имя состояния и сопоставляем их с %in% :


Комментарии:

1. Чем больше я думаю об этих случаях, я не уверен, что создание гигантского регулярного выражения является хорошим масштабируемым решением, когда вы можете сделать что-то подобное dat[!sub("^. ,\s ", "", dat$Geography) %in% exclude_list,] , которое не будет падать или резко замедляться, если exclude_list станет слишком большим.

2. Хм… это правда. Я добавил обновление к ответу

Ответ №2:

Я бы рекомендовал делать это с помощью регулярных выражений. $ В регулярном выражении указывает конец строки. So grepl(" CA$", Geography) вернет true, если география заканчивается пробелом, а буквы CA.

Следовательно, я бы сделал что-то вроде:


Ответ №3:

data.table Опция с grepl


или subset , если вы используете базовый R


Данные


, paste0(exclude_list, collapse = ‘|’)) #returns
#[1] «(GA|CA)$»


Если exclude_list слишком велико, ответ на регулярное выражение может завершиться неудачей, в таком случае было бы полезно предложение @thelatemail, где мы сохраняем только имя состояния и сопоставляем их с %in% :


Комментарии:

1. Чем больше я думаю об этих случаях, я не уверен, что создание гигантского регулярного выражения является хорошим масштабируемым решением, когда вы можете сделать что-то подобное dat[!sub("^. ,\s ", "", dat$Geography) %in% exclude_list,] , которое не будет падать или резко замедляться, если exclude_list станет слишком большим.

2. Хм… это правда. Я добавил обновление к ответу

Ответ №2:

Я бы рекомендовал делать это с помощью регулярных выражений. $ В регулярном выражении указывает конец строки. So grepl(" CA$", Geography) вернет true, если география заканчивается пробелом, а буквы CA.

Следовательно, я бы сделал что-то вроде:


Ответ №3:

data.table Опция с grepl


или subset , если вы используете базовый R


Данные


,
paste0(exclude_list, collapse = ‘|’)), Geography))

Или, если вам нужен dplyr ответ, сделайте :


где



Если exclude_list слишком велико, ответ на регулярное выражение может завершиться неудачей, в таком случае было бы полезно предложение @thelatemail, где мы сохраняем только имя состояния и сопоставляем их с %in% :


Комментарии:

1. Чем больше я думаю об этих случаях, я не уверен, что создание гигантского регулярного выражения является хорошим масштабируемым решением, когда вы можете сделать что-то подобное dat[!sub("^. ,\s ", "", dat$Geography) %in% exclude_list,] , которое не будет падать или резко замедляться, если exclude_list станет слишком большим.

2. Хм… это правда. Я добавил обновление к ответу

Ответ №2:

Я бы рекомендовал делать это с помощью регулярных выражений. $ В регулярном выражении указывает конец строки. So grepl(" CA$", Geography) вернет true, если география заканчивается пробелом, а буквы CA.

Следовательно, я бы сделал что-то вроде:


Ответ №3:

data.table Опция с grepl


или subset , если вы используете базовый R


Данные


,
paste0(exclude_list, collapse = ‘|’)), Geography))где



Если exclude_list слишком велико, ответ на регулярное выражение может завершиться неудачей, в таком случае было бы полезно предложение @thelatemail, где мы сохраняем только имя состояния и сопоставляем их с %in% :


Комментарии:

1. Чем больше я думаю об этих случаях, я не уверен, что создание гигантского регулярного выражения является хорошим масштабируемым решением, когда вы можете сделать что-то подобное dat[!sub("^. ,\s ", "", dat$Geography) %in% exclude_list,] , которое не будет падать или резко замедляться, если exclude_list станет слишком большим.

2. Хм… это правда. Я добавил обновление к ответу

Ответ №2:

Я бы рекомендовал делать это с помощью регулярных выражений. $ В регулярном выражении указывает конец строки. So grepl(" CA$", Geography) вернет true, если география заканчивается пробелом, а буквы CA.

Следовательно, я бы сделал что-то вроде:


Ответ №3:

data.table Опция с grepl


или subset , если вы используете базовый R


Данные


,
paste0(exclude_list, collapse = ‘|’)), Geography))Или, если вам нужен dplyr ответ, сделайте :


где



Если exclude_list слишком велико, ответ на регулярное выражение может завершиться неудачей, в таком случае было бы полезно предложение @thelatemail, где мы сохраняем только имя состояния и сопоставляем их с %in% :


Комментарии:

1. Чем больше я думаю об этих случаях, я не уверен, что создание гигантского регулярного выражения является хорошим масштабируемым решением, когда вы можете сделать что-то подобное dat[!sub("^. ,\s ", "", dat$Geography) %in% exclude_list,] , которое не будет падать или резко замедляться, если exclude_list станет слишком большим.

2. Хм… это правда. Я добавил обновление к ответу

Ответ №2:

Я бы рекомендовал делать это с помощью регулярных выражений. $ В регулярном выражении указывает конец строки. So grepl(" CA$", Geography) вернет true, если география заканчивается пробелом, а буквы CA.

Следовательно, я бы сделал что-то вроде:


Ответ №3:

data.table Опция с grepl


или subset , если вы используете базовый R


Данные