несколько операций над двумя фреймами данных с использованием R - PullRequest
1 голос
/ 06 мая 2020

У меня есть два фрейма данных df1 и df2 разной длины и два столбца в качестве ключевых столбцов. Я хотел бы выполнить несколько операций с этими фреймами данных следующим образом:

  1. Замена только пустых ячеек (NAs) в df1 соответствующими значениями из df2 на основе ключевых столбцов
  2. для каждого пары ключевых столбцов, ячейки из обоих фреймов данных, значения которых противоречат друг другу, должны быть представлены в новом фрейме данных

df1

id_col1   id_col2   name    age    sex
---------------------------------------
101         1M              21  
101         3M              21      M
102         1M      Mark    25  

df2

id_col1    id_col2    name     age     sex
-------------------------------------------
101          1M       Steve             M
101          2M                         M
101          3M       Steve    25   
102          1M       Ria      25       M
102          2M       Anie     22       F

После выполнения операции 1, т.е. замены NA в df1 соответствующими значениями из df2, я должен получить следующее:

result_1

id_col1    id_col2    name     age     sex
-------------------------------------------
101         1M        Steve    21      M
101         3M        Steve    25      M
102         1M        Mark     25      M

После выполнения операции 2, т.е. конфликтующих ячеек в df1 и df2 для тех же ключевых столбцов, я должен получить следующее:

result_2

id_col1    id_col2    name     age     sex
-------------------------------------------
101          3M                21   
101          3M                25   
102          1M        Mark     
102          1M        Ria      

Может ли кто-нибудь помочь в их решении?

1 Ответ

1 голос
/ 06 мая 2020

Для result_1 вы можете использовать left_join и case_when после преобразования в длинную форму:

library(dplyr)
library(tidyr)

left_join(pivot_longer(df1, -starts_with('id_col'),  
                            values_ptypes=list(value='character')),
          pivot_longer(df2, -starts_with('id_col'), values_to="value2", 
                            values_ptypes=list(value2='character'))) %>%
  mutate(value = case_when(value == '' ~ value2,
                            TRUE ~ value)) %>%
  select(-value2) %>%
  pivot_wider() %>%
  type.convert()

#   id_col1 id_col2 name    age sex  
#     <int> <fct>   <fct> <int> <fct>
# 1     101 1M      Steve    21 M    
# 2     101 3M      Steve    21 M    
# 3     102 1M      Mark     25 M

Для result_2 код аналогичен, за исключением мутации, мы фильтруем и добавляем дополнительную форму.

left_join(pivot_longer(df1, -starts_with('id_'), values_to="value1", 
                            values_ptypes=list(value1='character')),
          pivot_longer(df2, -starts_with('id_'), values_to="value2", 
                            values_ptypes=list(value2='character'))) %>%
  filter(value1 != '' & value2 != '' & value1 != value2) %>%
  pivot_longer(cols=value1:value2, names_prefix="value", names_to="df") %>%
  pivot_wider() %>%
  type.convert() %>% 
  select(intersect(names(df1), names(.))) # to retain original colname ordering

#   id_col1 id_col2 name    age
#     <int> <fct>   <fct> <int>
# 1     101 3M      NA       21
# 2     101 3M      NA       25
# 3     102 1M      Mark     NA
# 4     102 1M      Ria      NA

Data :

df1 <- structure(list(id_col1 = c(101L, 101L, 102L), id_col2 = c("1M", 
"3M", "1M"), name = c("", "", "Mark"), age = c(21L, 21L, 25L), 
    sex = c("", "M", "")), class = "data.frame", row.names = c(NA, -3L))

df2 <- structure(list(id_col1 = c(101L, 101L, 101L, 102L, 102L), id_col2 = c("1M", 
"2M", "3M", "1M", "2M"), name = c("Steve", "", "Steve", "Ria", 
"Anie"), age = c(NA, NA, 25L, 25L, 22L), sex = c("M", "M", "", 
"M", "F")), class = "data.frame", row.names = c(NA, -5L))
...