При объединении или объединении фреймов данных, как лучше всего обращаться с полем, которое «не имеет значения», чтобы указать, что все значения возможны? - PullRequest
1 голос
/ 29 апреля 2020

Это пример ситуации. Есть ли способ справиться с этим в R, чтобы получить желаемый результат main_df_2. Или, альтернативно, есть ли способ, которым я мог бы добавить строки в lookup_df таким образом, чтобы отсутствующие возможности, где (Division = 'd2') добавили (parent = 'P') и (parent = 'C'), добавили в виде двух строк в дополнение к одной пустой строке?

# example for the type of join 
library(tidyverse)
main_df <- data.frame( division = c('d1', 'd1', 'd2', 'd2'),
                       parent = c('P', 'C', 'P', 'C'))
main_df
# > main_df
# division parent 
# 1       d1      P
# 2       d1      C       
# 3       d2      P
# 4       d2      C
lookup_df <- data.frame( division = c('d1', 'd1', 'd2'),
                  parent = c('P', 'C', ''),
                  plant = c('A', 'B', 'B'))
lookup_df
# > lookup_df
# division parent plant
# 1       d1      P     A
# 2       d1      C     B
# 3       d2            B

# desired outcome 
# > main_df_2
# division parent plant
#    d1      P      A
#    d1      C      B
#    d2      P      B
#    d2      C      B

main_df_2 <- left_join(main_df, lookup_df,
                by = c("division" = "division",
                       "parent" = "parent"))

main_df_2
# > x1
# division parent plant
# 1       d1      P     A
# 2       d1      C     B
# 3       d2         <NA>
# 4       d2      C  <NA>

1 Ответ

1 голос
/ 29 апреля 2020

Вот 2 варианта использования data.table

1) Разделение на 2 отдельных объединения перед их связыванием строк:

library(data.table)
setDT(main_df)
setDT(lookup_df)

rbindlist(list(
    main_df[lookup_df, on=.(division, parent), nomatch=0L],
    main_df[lookup_df[parent==""], on=.(division), nomatch=0L, 
        .(division=x.division, parent=x.parent, plant=i.plant)]))

2) с использованием полного слияния перед фильтрацией (больше памяти) интенсивно, если набор данных огромен после объединения):

setnames(
    merge(lookup_df, main_df, by="division", all=TRUE)[
        parent.x==parent.y | parent.x==""][, 
            parent.x := NULL],
    "parent.y", "parent")

вывод:

   division parent plant
1:       d1      P     A
2:       d1      C     B
3:       d2      P     B
4:       d2      C     B
...