сравнение значений в 3-х фреймах данных и добавление пропущенных значений - PullRequest
0 голосов
/ 26 апреля 2018

У меня есть 3 кадра.

Data1 -
Name_description   Numbers 
ABC                23
DEF                34
GHI                45
XYZ                43
JVK                23
LMN                21

Данные 2 имеют только список имен

Data 2- 
    Names            
    ABC                
    DEF                
    GHI                
    XYZ                
    JVK                
    LMN    
    PQR
    KJL      

Данные 3 снова имеют Имена и цифры

Data 3
Name_desc           Numbers 
    ABC                56
    DEF                67
    GHI                89
    XYZ                60
    JVK                88
    LMN                65
    PQR                100
    KJL                85

Я хочу сделать следующие вещи -

Look for all names from data 2 are present in data 1
If any names are missing then 
{
get those names
get the numbers for those missing names from data 3
append above two things (missing names & numbers) to data 1
}
else
{data1<-data1
}

Я просто думал объединить файлы, но мне также нужно убедиться, что если в данных 1 из данных 2 не пропущено ни одно имя, данные 1 должны остаться без изменений. (то же самое, что указано в коде выше)

В приведенном выше случае мой окончательный результат должен быть

Data 1- 

Name_description   Numbers 
    ABC                23
    DEF                34
    GHI                45
    XYZ                43
    JVK                23
    LMN                21
    PQR                100
    KJL                85

Спасибо

Ответы [ 5 ]

0 голосов
/ 28 апреля 2018

На самом деле нам вообще не нужно merge, вам нужно выбрать первый доступный вариант для Number, начиная с Data1, затем Data3, и я полагаю, что при Name возвращается NA. находится в Data2, а не в других.

Самый быстрый способ сделать это с помощью data.table, но я дам и другие варианты.

data.table

data.table::rbindlist по умолчанию не использует имена (use.names=FALSE), поэтому в этом случае это очень удобно.

library(data.table)
rbindlist(list(Data1,Data3,Data2))[,.SD[1,],by="Name_description"]

# 1:              ABC      23
# 2:              DEF      34
# 3:              GHI      45
# 4:              XYZ      43
# 5:              JVK      23
# 6:              LMN      21
# 7:              PQR     100
# 8:              KJL      85

Тидиверс решение

аргумент .keep_all dplyr::distinct полезен, чтобы избежать менее читабельного использования %>% filter(!duplicated(Names)) или %>% group_by(Names) %>% Slice(1).

library(tidyverse)
lst(Data1,Data3,cbind(Data2,NA)) %>%
  map(setNames,c("Names","Numbers")) %>%
  bind_rows %>%
  distinct(Names,.keep_all = TRUE) 

# Names Numbers
# 1   ABC      23
# 2   DEF      34
# 3   GHI      45
# 4   XYZ      43
# 5   JVK      23
# 6   LMN      21
# 7   PQR     100
# 8   KJL      85

базовый раствор

x <- do.call(rbind,lapply(list(Data1,Data3,cbind(Data2,NA)),setNames,c("Names","Numbers")))
x[!duplicated(x[[1]]),]  
#    Names Numbers
# 1    ABC      23
# 2    DEF      34
# 3    GHI      45
# 4    XYZ      43
# 5    JVK      23
# 6    LMN      21
# 13   PQR     100
# 14   KJL      85
0 голосов
/ 26 апреля 2018

Я нахожу dplyr::coalesce очень удобным в ситуациях, упомянутых OP. После объединения 3 фреймов данных будет доступен столбец 2 Numbers (один содержит NA), который можно объединить, используя coalesce как:

library(dplyr)

Data1 %>% full_join(Data2, by=c("Name_description" = "Names")) %>%
  inner_join(Data3, by=c("Name_description" = "Name_desc")) %>%
  mutate(Numbers = coalesce( Numbers.x, Numbers.y)) %>%
  select(Name_description, Numbers)

#    Name_description Numbers
# 1              ABC      23
# 2              DEF      34
# 3              GHI      45
# 4              XYZ      43
# 5              JVK      23
# 6              LMN      21
# 7              PQR     100
# 8              KJL      85

Данные:

Data1 <- read.table(text = 
"Name_description   Numbers 
ABC                23
DEF                34
GHI                45
XYZ                43
JVK                23
LMN                21",
header = TRUE, stringsAsFactors = FALSE)

Data2 <- read.table(text = 
"Names            
ABC                
DEF                
GHI                
XYZ                
JVK                
LMN    
PQR
KJL",
header = TRUE, stringsAsFactors = FALSE)


Data3 <- read.table(text = 
"Name_desc           Numbers 
ABC                56
DEF                67
GHI                89
XYZ                60
JVK                88
LMN                65
PQR                100
KJL                85",
header = TRUE, stringsAsFactors = FALSE)
0 голосов
/ 26 апреля 2018

С dplyr это должно выглядеть примерно так:

data1 %>% 
    bind_rows(
        data2 %>% 
        anti_join(data1) %>% 
        left_join(data3)
    )  
0 голосов
/ 26 апреля 2018

Мы можем достичь этого в dplyr с left_join и ifelse.

library(dplyr)

Data4 <- Data2 %>%
  left_join(Data1, by = c("Names" = "Name_description")) %>%
  left_join(Data3, by = c("Names" = "Name_desc")) %>%
  mutate(Numbers = ifelse(is.na(Numbers.x), Numbers.y, Numbers.x)) %>%
  select(Names, Numbers)
Data4
#    Names Numbers
# 1   ABC      23
# 2   DEF      34
# 3   GHI      45
# 4   XYZ      43
# 5   JVK      23
# 6   LMN      21
# 7   PQR     100
# 8   KJL      85

DATA

Data1 <- read.table(text = "Name_description   Numbers 
ABC                23
DEF                34
GHI                45
XYZ                43
JVK                23
LMN                21",
                    header = TRUE, stringsAsFactors = FALSE)

Data2 <- read.table(text = "Names            
    ABC                
    DEF                
    GHI                
    XYZ                
    JVK                
    LMN    
    PQR
    KJL",
                    header = TRUE, stringsAsFactors = FALSE)

Data3 <- read.table(text = "Name_desc           Numbers 
    ABC                56
    DEF                67
    GHI                89
    XYZ                60
    JVK                88
    LMN                65
    PQR                100
    KJL                85",
                    header = TRUE, stringsAsFactors = FALSE)
0 голосов
/ 26 апреля 2018

Сначала объедините Data1 и Data2, затем найдите NA в этом новом data.frame и сопоставьте их с Data3, наконец, замените их значениями Data3.

> tmp <- merge(Data1, Data2, by.x="Name_description", by.y="Names", all=TRUE)
> ind <- match(tmp$Name_description[is.na(tmp$Numbers)], Data3$Name_desc)
> tmp$Numbers[ind] <- Data3$Numbers[ind]
> tmp
  Name_description Numbers
1              ABC      23
2              DEF      34
3              GHI      45
4              JVK      23
5              LMN      21
6              XYZ      43
7              KJL     100
8              PQR      85
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...