用另一个数据框中匹配行的值替换缺失数据
Replace missing data with values from matching rows in another dataframe
我想替换变量的值。
这是我的分贝:
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
对于所有观察。
然后我创建了几个 dB,如下所示:
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
我试过 sqldf 这样做:
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 次迭代)。
如何避免这个问题?
您可以使用 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
')
您可以简单地匹配两个数据框中的 ID,并在原始数据框中替换它们:
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")]
我们可以使用我的包 safejoin 中的 eat
,以及 "patch" 匹配项
列冲突时从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
我们也可以合并从 rhs 开始的列,以获得相同的效果:
eat(mydb, newdb, .by = "ID", .conflict = ~coalesce(.y,.x))
我想替换变量的值。
这是我的分贝:
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
对于所有观察。
然后我创建了几个 dB,如下所示:
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
我试过 sqldf 这样做:
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 次迭代)。
如何避免这个问题?
您可以使用 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
')
您可以简单地匹配两个数据框中的 ID,并在原始数据框中替换它们:
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")]
我们可以使用我的包 safejoin 中的 eat
,以及 "patch" 匹配项
列冲突时从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
我们也可以合并从 rhs 开始的列,以获得相同的效果:
eat(mydb, newdb, .by = "ID", .conflict = ~coalesce(.y,.x))