(对于pythonistas,下面的代码是在我得到一些#hatehard之前采用R&#39格式)
这个让我感到沮丧太久了。
我有2个数据集
df1 <- data.frame(ID = c("Person.A", "Person.B", "Person.C", "Person.D", "Person.E", "Person.F"),
Aa = c(0,1,2,NA,1,1),
Ab = c(0,NA,2,1,1,1),
Ac = c(NA,NA,2,2,1,1),
no.match = c(0,1,2,2,1,2))
df2 <- data.frame(ID = c("Person.A", "Person.B", "Person.C", "Person.D", "Person.E"),
Ba = c(0,NA,2,1,1),
Bb = c(NA,1,2,2,1),
Bc = c(0,1,2,2,1))
然后我使用merge(df1, df2, all.x = T, by = "ID"
合并这两个数据集来获取:
ID Aa Ab Ac no.match Ba Bb Bc
1 Person.A 0 0 NA 0 0 NA 0
2 Person.B 1 NA NA 1 NA 1 1
3 Person.C 2 2 2 2 2 2 2
4 Person.D NA 1 2 2 1 2 2
5 Person.E 1 1 1 1 1 1 1
6 Person.F 1 1 1 2 NA NA NA
实际数据集要复杂得多,许多列在其他列中没有匹配项。所以我不认为我可以做一些取决于列的安排的事情。
列Aa
和Ba
包含相同的信息;列Ab
和Bb
也可以,等等,但列no.match
不包含匹配的列。
我想&#34; map&#34;如果 Ba
为NA,则来自Aa
到Aa
的同一行的值,并对Ab
和Bb
执行相同的操作,Ac
和Bc
等。
在这种情况下,结果DF看起来像:
ID Aa Ab Ac no.match Ba Bb Bc
1 Person.A 0 0 0 0 0 NA 0
2 Person.B 1 1 1 1 NA 1 1
3 Person.C 2 2 2 2 2 2 2
4 Person.D 1 1 2 2 1 2 NA
5 Person.E 1 1 1 1 1 1 1
6 Person.F 1 1 1 2 NA NA NA
元素[4,2]
被元素[4,6]
替换的位置
行和列需要匹配。
我尝试了大量令人尴尬的事情:apply
,ifelse
,遍历列表l1 = c('Aa','Ab','Ac'), l2 = c('Ba', 'Bb', 'Bc')
我可以一次性完成:which(is.na(mdf$Aa)) <- mdf[which(is.na(mdf$Aa)), c("Ba")]
但我怎么能迭代地做到这一点?
谢谢! (对不起啰嗦)
答案 0 :(得分:1)
此处使用data.table v1.9.5
- 安装说明here:
require(data.table) # v1.9.5+
cols1 = names(df1)[2:4]
cols2 = names(df2)[2:4]
foo <- function(x, y) {
nas = is.na(x)
x[nas] = y[nas]
x
}
setDT(df1)[df2, c(cols1, cols2) := c(Map(foo, mget(cols1),
mget(cols2)), mget(cols2)), on = "ID"]
> df1
# ID Aa Ab Ac no.match Ba Bb Bc
# 1: Person.A 0 0 0 0 0 NA 0
# 2: Person.B 1 1 1 1 NA 1 1
# 3: Person.C 2 2 2 2 2 2 2
# 4: Person.D 1 1 2 2 1 2 2
# 5: Person.E 1 1 1 1 1 1 1
# 6: Person.F 1 1 1 2 NA NA NA
setDT()
通过引用将df1
转换为 data.table 。
setDT(df1)[df2, on = "ID"]
执行加入。对于df2
的每一行,我们在df1
中找到匹配的行,并提取与匹配行对应的列。
在匹配的行上,我们<{1}}中的更新列,并通过引用添加 cols1
中的新列/ em>使用cols2
运算符。为了更新列,我们提取:=
和cols1
中指定的列,并将cols2
替换为函数NA
。要添加列,我们只需使用foo()
提取列cols2
即可。我们使用mget()
连接两个列表。
如果您有兴趣,请查看HTML vignettes了解详情。