Заменить отсутствующие данные значениями из соответствующих строк в другом кадре данных - PullRequest
0 голосов
/ 11 декабря 2018

Я хочу заменить значения переменной.

Это мой дБ:

head(mydb)

ID   V1     V2     V3     V4 
1    value  value  0    0
2    value  value  0    0  
3    value  value  0    0
4    value  value  0    0  
5    value  value  0    0
6    value  value  0    0  

V3 и V4 имеют 0 длявсе наблюдения.

Затем я создал несколько дБ, как показано ниже:

head(newdb)
ID   V3     V4 
2    5      4  
4    8      5  
6    9      6  

Я хочу получить что-то вроде этого:

ID   V1     V2     V3     V4 
1    value  value  0    0
2    value  value  5    4  
3    value  value  0    0
4    value  value  8    5  
5    value  value  0    0
6    value  value  9    6

Я пытался с сделать это так:

mydf <- sqldf('SELECT mydf.*, newdb.v3, newdb.v4              
               FROM mydf
               LEFT JOIN newdb 
               ON  mydf.ID = newdb.id')

Код, который я создал, работает хорошо и выполняет свою работу;но проблема в том, что я нахожусь внутри цикла for, и для каждого из моих newDB код sql генерирует другие V3 и V4 и прикрепляет его близко к предыдущему, создавая что-то вроде этого:

ID   V1     V2     V3   V4   V3   V4   V3  V4
1    value  value  0    0    1    5    0   0
2    value  value  5    4    0    0    0   0
3    value  value  0    0    0    0    7   8
4    value  value  8    5    0    0    0   0
5    value  value  0    0    2    2    0   0 
6    value  value  9    6    0    0    0   0

Я добавил еще один столбец V3 и V4 для каждой итерации моего цикла (в данном случае 3 итерации).

Как я могу избежать этой проблемы?

Ответы [ 3 ]

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

Вы можете просто сопоставить идентификаторы в двух фреймах данных и заменить их на исходные:

mydf[,c("V3","V4")] <- newdf[match(mydf$ID, newdf$ID),c("V3","V4")]

mydf
#   ID  V1    V2   V3 V4
# 1  1 value value NA NA
# 2  2 value value  5  4
# 3  3 value value NA NA
# 4  4 value value  8  5
# 5  5 value value NA NA
# 6  6 value value  9  6

Позже вы можете заменить NA s на 0 s.

Обновление:

Вместо того, чтобы for-loop объединить все newdf вместе, а затем запустить код для этого;посмотрите на псевдокод ниже:

newdf_concat <- rbind(newdf1, newdf2)

mydf[,c("V3","V4")] <- newdf_concat[match(mydf$ID, newdf_concat$ID),c("V3","V4")]
0 голосов
/ 26 февраля 2019

Мы могли бы использовать eat из моего пакета safejoin и "пропатчить" совпадения из rhs в rhs при конфликте столбцов.

# devtools::install_github("moodymudskipper/safejoin")
library(safejoin)
library(dplyr)

eat(mydb, newdb, .by = "ID", .conflict = "patch")
#   ID    V1    V2 V3 V4
# 1  1 value value  0  0
# 2  2 value value  5  4
# 3  3 value value  0  0
# 4  4 value value  8  5
# 5  5 value value  0  0
# 6  6 value value  9  6

Мы также можем объединить столбцы, начиная с правой части, для того же эффекта:

eat(mydb, newdb, .by = "ID", .conflict = ~coalesce(.y,.x))
0 голосов
/ 11 декабря 2018

Вы можете легко обновить объединения с помощью data.table

library(data.table)
setDT(mydb)
setDT(newdb)

mydb[newdb, on = 'ID', c('V3', 'V4') := .(i.V3, i.V4)]

mydb
#    ID    V1    V2 V3 V4
# 1:  1 value value  0  0
# 2:  2 value value  5  4
# 3:  3 value value  0  0
# 4:  4 value value  8  5
# 5:  5 value value  0  0
# 6:  6 value value  9  6

Вы также можете использовать sqldf, но вы должны использовать coalesce (тот же результат, что и выше)

library(sqldf)
sqldf('
SELECT  mydb.ID
        , mydb.V1
        , mydb.V2
        , coalesce(newdb.v3, mydb.V3) as V3
        , coalesce(newdb.v4, mydb.V4) as V4
FROM    mydb
        LEFT JOIN newdb 
          using(id)
')

Используемые данные:

mydb <- fread('
ID   V1     V2     V3     V4 
1    value  value  0    0
2    value  value  0    0  
3    value  value  0    0
4    value  value  0    0  
5    value  value  0    0
6    value  value  0    0  
')
newdb <- fread('
ID   V3     V4 
2    5      4  
4    8      5  
6    9      6  
')
...