Я хочу ввести новые столбцы в df на основе значений одного столбца.
столбец категории должен быть разделен на ',' и каждая разделенная подстрока должна перейти к вновь введенному соответствующему столбцу.
Минимальный пример:
df <- data.frame(category=c('1, 2', '1, 3','3', '2, 3'),
othercolumn= c("Grealish", "Saka", "Henry", 'Jesus'))
Требуется ДФ:
finaldf <- data.frame(category=c('1, 2', '1, 3','3', '2, 3'),
category1=c('1', '1',NA, NA),
category2=c('2',NA,NA, '2'),
category3=c(NA,'3','3', '3'),
othercolumn= c("Grealish", "Saka", "Henry", 'Jesus'))
Столбцы категории1, категории2 и категории3 будут принимать значения на основе столбца категории, в противном случае нет данных.
Вы можете использовать separate
, а затем pivot_wider
:
library(tidyverse)
tibble(df) |>
separate_longer_delim(category, delim = ", ") |>
pivot_wider(names_from = category, values_from = category, names_prefix = "category") |>
select(starts_with('category'), othercolumn)
# A tibble: 4 × 4
category1 category2 category3 othercolumn
<chr> <chr> <chr> <chr>
1 1 2 NA Grealish
2 1 NA 3 Saka
3 NA NA 3 Henry
4 NA 2 3 Jesus
В базе R вы можете сделать:
Использование strsplt
для разделения чисел и преобразования их в числовые
setName
возврат в lapply
и cbind
во фрейм данных
nums <- strsplit(df$category, ",") |>
type.convert(as.is = T)
cbind(df[1], do.call(rbind, lapply(nums, \(x){
sq <- seq(max(unlist(nums)))
ifelse(sq %in% x , sq, NA ) |>
setNames(paste0("category", sq))
})), df[-1])
category category1 category2 category3 othercolumn
1 1, 2 1 2 NA Grealish
2 1, 3 1 NA 3 Saka
3 3 NA NA 3 Henry
4 2, 3 NA 2 3 Jesus
Мы можем использовать fastDummies
для создания фиктивных столбцов, а затем изменить значения
library(fastDummies)
library(dplyr)
df %>%
dummy_cols('category', split = ",\\s*") %>%
mutate(across(starts_with('category_'), ~ (NA^!.x) *
readr::parse_number(cur_column()))) %>%
relocate(othercolumn, .after = last_col())
-выход
category category_1 category_2 category_3 othercolumn
1 1, 2 1 2 NA Grealish
2 1, 3 1 NA 3 Saka
3 3 NA NA 3 Henry
4 2, 3 NA 2 3 Jesus
Вот вариант data.table
с использованием dcast
dcast(
setDT(df)[
, strsplit(category, ", "),
.(category, othercolumn)
][
,
V2 := paste0("category_", V1)
],
category + othercolumn ~ V2,
value.var = "V1"
)
который дает
category othercolumn category_1 category_2 category_3
1: 1, 2 Grealish 1 2 <NA>
2: 1, 3 Saka 1 <NA> 3
3: 2, 3 Jesus <NA> 2 3
4: 3 Henry <NA> <NA> 3