Новое семейство функций separate_*() в tidyr 1.3.0
Новое семейство функций пришло на смену функций extract(), separate(), и separate_rows(). Новые функции имеют более согласованные имена, аргументы, производительность и в целом обеспечивают новый подход к решению проблемы разделения одной текстовой ячейки на части.
Функции для разбиения текста на новые столбцы:
● separate_wider_delim() - Разделить с помощью разделителя (ex separate(sep = string))
● separate_wider_position() - Разделить по положению (ex separate(sep = integer vector))
● separate_wider_regex() - Разделить с помощью регулярного выражения (ex extract())
Функции для разбиения текста на новые строки:
● separate_longer_delim() - Разделить с помощью разделителя (ex separate_rows())
● separate_longer_position() - Разделить по положению (ранее аналога не было )
Пример:
Для примера мы будет использовать набор данных о переписи населения, получить этот набор можно с помощью пакета tidycensus.
# тестовые данные
vt_census <- tidycensus::get_decennial(
geography = "block",
state = "VT",
county = "Washington",
variables = "P1_001N",
year = 2020
)
Столбец GEOID состоит из 4ёх компонентов: 2-значного идентификатора штата, 3-значного идентификатора округа, 6-значного идентификатора участка и 4-значного идентификатора квартала.
Зная это мы можем разделить этот столбец на отдельные столбцы по позиции:
# разбиваем столбец GEOID на 4 компонента по позиции
vt_census |>
select(GEOID) |>
separate_wider_position(
GEOID,
widths = c(state = 2, county = 3, tract = 6, block = 4)
)
Столбец name содержит туже информацию но в текстовом виде, где каждый компонент разделен запятой. разделить данный столбец можно двумя способами, самый простой - использовать separate_wider_delim().
# разбиваем столбец names на компоненты по разделителю
vt_census |>
select(NAME) |>
separate_wider_delim(
NAME,
delim = ", ",
names = c("block", "block_group", "tract", "county", "state")
)
Столбец name мы разбили, но там осталось много лишней, ненужной информации, в каждой ячейке дублируются слова (Block, Block Group, Census Tract и т.д.). Этого можно избежать, если использовать не разбиение по разделителю, а извлечение с помощью регулярных выражений и функцию separate_wider_regex():
# избавляемся от мусора с помощью разбивки через регулярные выражения
vt_census |>
select(NAME) |>
separate_wider_regex(
NAME,
patterns = c(
"Block ", block = "\\d+", ", ",
"Block Group ", block_group = "\\d+", ", ",
"Census Tract ", tract = "\\d+.\\d+", ", ",
county = "[^,]+", ", ",
state = ".*"
)
)
Все приведённые выше примеры были направлены на использование wider функций, т.е. значение одного столбца разделяли на несколько новых столбцов, но иногда нам необходимо из значений одной ячейки получить несколько новых строк, разбив её каким то методом.
# тестовые данные
df_delim <- tibble(
id = 1:3,
x = c("a", "a-b", "a-b-c")
)
df <- tibble(
id = 1:3,
x = c("ab", "def", "")
)
# разбивка на строки по разделителю
df |> separate_longer_delim(x, delim = "-")
# разбивка на строки по позиции
df %>% separate_longer_position(x, 1)
Ссылки:
- Текст является частичным переводом статьи "tidyr 1.3.0"
#заметки_по_R