Слияние, когда один из столбцов является списком, создание нового столбца, который является списком - PullRequest
1 голос
/ 18 марта 2019

У меня есть два набора данных, которые я хочу объединить.Один из столбцов, который я хочу использовать в качестве ключа для слияния, имеет значения в списке.Если какое-либо из этих значений появится в столбце второго набора данных, я хочу, чтобы значение в другом столбце было объединено с первым набором данных - это может означать, что существует несколько значений, которые должны быть представлены в виде списка.

Это довольно сложно объяснить, но, надеюсь, данные этого примера проясняют ситуацию.

Пример данных

library(data.table)
mother_dt <- data.table(mother = c("Penny", "Penny", "Anya", "Sam", "Sam", "Sam"), 
                 child = c("Violet", "Prudence", "Erika", "Jake", "Wolf", "Red"))
mother_dt [, children := .(list(unique(child))), by = mother]
mother_dt [, child := NULL]
mother_dt <- unique(mother_dt , by = "mother")

child_dt <- data.table(child = c("Violet", "Prudence", "Erika", "Jake", "Wolf", "Red"), 
                             age = c(10, 8, 9, 6, 5, 2))

Так, например, первая строка в моем новом наборе данных будет иметь «Пенни» в столбце mother, список, содержащий «Фиолетовый »и« Благоразумие »в столбце children, а также список, содержащий 10 и 8 в столбце age.

Я пробовал следующее:

combined_dt <- mother_dt[, child_age := ifelse(child_dt$child %in% children, 
                                                      .(list(unique(child_dt$age))), NA)

Но это просто содержит список всех возрастов в последней строке.

Я ценю, что это, вероятно, довольно необычное поведение, но есть ли способ достичь этого?

Редактировать: Окончательная таблица данных будет выглядеть так:

final_dt <- data.table(mother = c("Penny", "Anya", "Sam"), 
                      children = c(list(c("Violet", "Prudence")), list(c("Erika")), list(c("Jake", "Wolf", "Red"))),
                      age = c(list(c(10, 8)), list(c(9)), list(c(6, 5, 2))))

Ответы [ 3 ]

1 голос
/ 18 марта 2019

Вы можете сделать что-то вроде этого -

  library(splitstackshape)
  newm <- mother_dt[,.(children=unlist(children)),by=mother]
  final_dt <- merge(newm,child_dt,by.x = "children",by.y = "child")

> aggregate(. ~ mother, data = cv, toString)
      mother         children     age
    1   Anya            Erika       9
    2  Penny Prudence, Violet   8, 10
    3    Sam  Jake, Red, Wolf 6, 2, 5
1 голос
/ 18 марта 2019

Самый простой способ, который я могу придумать, - сначала вычеркнуть список детей, затем объединить, а затем снова перечислить:

mother1 <- mother_dt[,.(children=unlist(children)),by=mother]
mother1[child_dt,on=c(children='child')][,.(children=list(children),age=list(age)),by=mother]
0 голосов
/ 19 марта 2019

Вы можете сделать это следующим образом, что дает преимущество в сохранении дубликатов в столбце mother, когда они существуют.

mother_dt$age <- lapply(
  mother_dt$children, 
  function(x,y) y[x], 
   y = setNames(child_dt$age, child_dt$child))

mother_dt
#    mother        children   age
# 1:  Penny Violet,Prudence 10, 8
# 2:   Anya           Erika     9
# 3:    Sam   Jake,Wolf,Red 6,5,2

Я хорошо транслирую в синтаксис tidyverse:

library(tidyverse)
mutate(mother_dt, age = map(children,~.y[.], deframe(child_dt)))
#   mother         children     age
# 1  Penny Violet, Prudence   10, 8
# 2   Anya            Erika       9
# 3    Sam  Jake, Wolf, Red 6, 5, 2
...