根据 R 或 python 中的条件将一个列列表中的值替换为另一个列列表中的值
Replace values from one list of columns from another list of columns based on conditions in R or python
(对于 pythonistas,在我得到一些#hatehard 之前,下面的代码是 R 的格式)
这个让我沮丧的时间太长了。
我有 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
列不包含匹配的列。
我想"map" Ba
到 Aa
同一行的值 if Aa
是 NA并对 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")]
但是我怎样才能迭代地做到这一点?
谢谢! (啰嗦抱歉)
这是一个使用 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
中找到匹配的行并提取匹配行对应的列..
在匹配的行上,我们更新列在cols1
和添加新列cols2
通过引用 使用 :=
运算符。为了更新列,我们提取了 cols1
和 cols2
中指定的列,并将 NA
s 替换为函数 foo()
。要添加列,我们只需使用 mget()
拉取列 cols2
。我们使用 c()
.
连接两个列表
如果您有兴趣,请查看 HTML vignettes 以了解更多信息。
(对于 pythonistas,在我得到一些#hatehard 之前,下面的代码是 R 的格式)
这个让我沮丧的时间太长了。
我有 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
列不包含匹配的列。
我想"map" Ba
到 Aa
同一行的值 if Aa
是 NA并对 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")]
但是我怎样才能迭代地做到这一点?
谢谢! (啰嗦抱歉)
这是一个使用 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
中找到匹配的行并提取匹配行对应的列..在匹配的行上,我们更新列在
cols1
和添加新列cols2
通过引用 使用:=
运算符。为了更新列,我们提取了cols1
和cols2
中指定的列,并将NA
s 替换为函数foo()
。要添加列,我们只需使用mget()
拉取列cols2
。我们使用c()
. 连接两个列表
如果您有兴趣,请查看 HTML vignettes 以了解更多信息。