根据R或python中的条件,从另一列列中替换一列列中的值

时间:2015-07-29 22:36:23

标签: python r data-analysis data-cleansing

(对于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

实际数据集要复杂得多,许多列在其他列中没有匹配项。所以我不认为我可以做一些取决于列的安排的事情。

AaBa包含相同的信息;列AbBb也可以,等等,但列no.match不包含匹配的列。

我想&#34; map&#34;如果 Ba为NA,则来自AaAa 的同一行的值,并对AbBb执行相同的操作,AcBc等。

在这种情况下,结果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]替换的位置 行和列需要匹配。

我尝试了大量令人尴尬的事情:applyifelse,遍历列表l1 = c('Aa','Ab','Ac'), l2 = c('Ba', 'Bb', 'Bc')

我可以一次性完成:which(is.na(mdf$Aa)) <- mdf[which(is.na(mdf$Aa)), c("Ba")]

但我怎么能迭代地做到这一点?

谢谢! (对不起啰嗦)

1 个答案:

答案 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了解详情。