Вот опция, использующая tidyverse
.Мы расширяем строки набора данных, разделяя столбец |
столбца 'cats', затем separate
'cats' на два столбца, разделяя последний элемент ,
, сгруппированный по id, и получаем * 1005.* из столбца 'freq', извлеките числа в конце 'cats', преобразуйте его в factor
с указанным levels
, создайте столбец из 1 с ('val'), spread
его в 'wide'format
library(tidyverse)
o1 <- df2 %>%
separate_rows(cats, sep = "[|]") %>%
separate(cats, into = c('cats', 'freq'),
sep=",(?=[^,]+$)", convert = TRUE) %>%
group_by(id) %>%
mutate(freq = sum(freq),
cats = factor(str_extract(cats, "\\d+$"), levels = 1:10),
val = 1) %>%
spread(cats, val, fill = 0) %>%
rename_at(-1, ~ paste0('1_', .))
Теперь мы присваиваем значения столбцам, которые являются общими с исходным набором данных (' df1 ')
df1[is.na(df1)] <- 0
df1[names(o1)[-1]] <- o1[-1]
df1
# id 1_1 1_2 1_3 1_4 1_5 1_6 1_7 1_8 1_9 1_10 1_freq
#1 111.txt 0 0 0 0 0 0 1 0 0 0 1
#2 112.txt 1 0 1 0 0 0 0 0 0 0 4
#3 113.txt 0 0 0 0 0 1 0 0 0 1 3
#4 114.txt 0 0 0 1 0 0 0 0 0 0 2
#5 115.txt 0 0 0 0 1 0 0 0 0 0 1
#6 116.txt 1 0 0 0 0 0 0 1 0 0 3
data
df1 <- structure(list(id = c("111.txt", "112.txt", "113.txt", "114.txt",
"115.txt", "116.txt"), `1_1` = c(NA, NA, NA, NA, NA, NA), `1_2` = c(NA,
NA, NA, NA, NA, NA), `1_3` = c(NA, NA, NA, NA, NA, NA), `1_4` = c(NA,
NA, NA, NA, NA, NA), `1_5` = c(NA, NA, NA, NA, NA, NA), `1_6` = c(NA,
NA, NA, NA, NA, NA), `1_7` = c(NA, NA, NA, NA, NA, NA), `1_8` = c(NA,
NA, NA, NA, NA, NA), `1_9` = c(NA, NA, NA, NA, NA, NA), `1_10` = c(NA,
NA, NA, NA, NA, NA), `1_freq` = c(NA, NA, NA, NA, NA, NA)),
class = "data.frame", row.names = c(NA,
-6L))
df2 <- structure(list(id = c("111.cats", "112.cats", "113.cats", "114.cats",
"115.cats", "116.cats"), cats = c("1,7,1", "1,1,2|1,3,2", "1,10,1|1,6,2",
"1,4,2", "1,5,1", "1,1,2|1,8,1")), class = "data.frame", row.names = c(NA,
-6L))