Мне нужно разбить строковые значения, содержащиеся в столбце. Некоторые ячейки вообще не нуждаются в разбиении. Другим может потребоваться один, два или больше.
Я также хотел бы, чтобы разделенные значения сохранялись в параллельных столбцах.
Например, если мой исходный фрейм данных выглядит так
df2 <- data.frame(district= 1000:1003,
party= c("PartyGreen", "Coalition1(PartyRed-PartyBlue)", "PartyRed", "Coal.(PartyBlue-PartyOrange-VelvetParty)"))
Я хотел бы выглядеть так:
df.neat.2 <- data.frame(district= 1000:1003,
party= c("PartyGreen", "Coalition1(PartyRed-PartyBlue)", "PartyRed", "Coal.(PartyBlue-PartyOrange-VelvetParty)"),
party1= c("PartyGreen", "PartyRed", "PartyRed", "PartyBlue"),
party2= c(NA, "PartyBlue", NA, "PartyOrange"),
party3= c(NA, NA, NA, "VelvetParty"))
Обратите внимание, что некоторые ячейки содержат одно значение, которое не нужно разделять. Также обратите внимание, что разделение строки происходит внутри скобок ()
и разделяется тире.
library(tidyr)
library(dplyr)
library(stringr)
df2 |>
mutate(parties = str_remove_all(party, ".*\\(|\\).*"),
parties = str_split(parties, fixed("-"))) |>
unnest_wider(parties, names_sep = "_")
# district party parties_1 parties_2 parties_3
# <int> <chr> <chr> <chr> <chr>
# 1 1000 PartyGreen PartyGreen NA NA
# 2 1001 Coalition1(PartyRed-PartyBlue) PartyRed PartyBlue NA
# 3 1002 PartyRed PartyRed NA NA
# 4 1003 Coal.(PartyBlue-PartyOrange-VelvetParty) PartyBlue PartyOrange VelvetParty
Если вы хотите, чтобы имена столбцов были party_1
, party_2
и т. д. вместо parties_1
, parties_2
и т. д., вы можете передать этот вывод:
rename_with(~ str_replace(., fixed("parties"), "party"), starts_with("parties"))
Использование stringr
, dplyr
и tidyr
:
df2 |>
separate_wider_delim(party, delim = fixed('-'), names_sep = '', too_few = 'align_start') |>
mutate(across(
starts_with('party'),
\(s) str_remove(s, "^.*?\\(|\\)"))
)
Используя только базу R, мы можем gsub
удалить ненужные данные, strsplit
в "-"
и cbind
в данные.
> df2 |> cbind(
+ (s <- strsplit(gsub('.*\\(|\\).*', '', x), '-')) |>
+ lapply(`length<-`, max(lengths(s))) |>
+ do.call(what='rbind.data.frame') |>
+ setNames(paste0('party', seq_len(max(lengths(s)))))
+ )
district party party1 party2 party3
1 1000 PartyGreen PartyGreen <NA> <NA>
2 1001 Coalition1(PartyRed-PartyBlue) PartyRed PartyBlue <NA>
3 1002 PartyRed PartyRed <NA> <NA>
4 1003 Coal.(PartyBlue-PartyOrange-VelvetParty) PartyBlue PartyOrange VelvetParty