Отобразить один Dataframe на второй Dataframe - PullRequest
0 голосов
/ 27 декабря 2018

У меня есть два кадра данных, и я хочу отобразить оба и дать двоичное значение 1, если оно присутствует, иначе 0.

1-й DF

id       1_1   1_2   1_3   1_4   1_5   1_6   1_7   1_8   1_9   1_10  1_freq
111.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
112.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
113.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
114.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
115.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA
116.txt  NA    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA

2-йDF

id                 cats
111.cats           1,7,1
112.cats           1,1,2|1,3,2
113.cats           1,10,1|1,6,2
114.cats           1,4,2
115.cats           1,5,1
116.cats           1,1,2|1,8,1

Во 2-й DF$cats в первой строке есть 1,7,1, где 1 и 7 объединяет и создает столбец 1_7, и в этом столбце двоичное значение 1 помещается и включаетсяоставшийся столбец 0 помещается, и последний 1 номер переходит в столбец 1_freq, и, если какая-либо строка имеет более 1 категории, например, 1,10,1|1,6,2, где 1,10,1 переходит в столбец 1_10, а 1,6,2в столбец 1_6, а частота обеих категорий суммируется и переходит в столбец 1_freq.

DF Должно выглядеть так

id       1_1   1_2   1_3   1_4   1_5   1_6   1_7   1_8   1_9   1_10  1_freq
111.txt  0     0     0     0     0     0     1     0     0     0     1
112.txt  1     0     1     0     0     0     0     0     0     0     4
113.txt  0     0     0     0     0     1     0     0     0     1     3
114.txt  0     0     0     1     0     0     0     0     0     0     2
115.txt  0     0     0     0     1     0     0     0     0     0     1
116.txt  1     0     0     0     0     0     0     1     0     0     3

Надеюсь, вопрос ясен.Thankyou

Ответы [ 2 ]

0 голосов
/ 27 декабря 2018

Хотя вопрос помечен , мне было любопытно, как будет выглядеть ответ.

Поскольку df1 заполнено NA за исключением столбца id и столбцов id отличаются только в конце (txt против cats), приведенный ниже ответ предлагает создать df1 полностью из данных, содержащихся в df2:

library(data.table)
library(magrittr)
long <- setDT(df2)[, strsplit(cats, "[|]"), by = id][
  , c(.(id = id), tstrsplit(V1, ","))][
    , V3 := factor(V3, levels = 1:10)]
df1 <- dcast(long, id ~ V3, function(x) pmax(1, length(x)), 
             value.var = "V3", drop = FALSE, fill = 0)[
               long[, sum(as.integer(V4)), by = id], on = "id", freq := V1][
                 , id := stringr::str_replace(id, "cats$", "txt")][
                   , setnames(.SD, names(.SD)[-1], paste0("1_", names(.SD)[-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.table таблица df2 преобразуется из "строкового" широкого формата в форму long путем разбиенияcats столбец в "|"сначала, а затем путем разделения разделенных запятыми частей на отдельные столбцы V2 до V4.

Затем V3 поворачивается от символа к фактору, чтобы сохранить порядок столбцов при вызове dcast() дляизменить форму от длинного до широкого формата снова.Поскольку OP запросил показать 1, если хотя бы одна комбинация существует, здесь нужно использовать определение пользовательской функции function(x) pmax(1, length(x)) вместо простого lengthобновленном соединении сумма частот добавляется в столбец freq.Наконец, «cats» заменяется на «txt» в столбце id, а имена столбцов (кроме столбца id) начинаются с префикса «1 _».

Data

df2 <- data.table::fread("id                 cats
111.cats           1,7,1
112.cats           1,1,2|1,3,2
113.cats           1,10,1|1,6,2
114.cats           1,4,2
115.cats           1,5,1
116.cats           1,1,2|1,8,1", data.table = FALSE)
0 голосов
/ 27 декабря 2018

Вот опция, использующая 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))
...