使用具有条件的另一个数据框替换一个数据帧中的多个列的值

时间:2017-12-08 01:04:19

标签: r dataframe

您好我有两个数据框如下:

df1: 
ID   x    y     z     
1    a    b     c     
2    a    b     c
3    a    b     c 
4    a    b     c

和df2:

ID   x    y     
 2   d    NA
 3   NA   e

我正在追查这样的结果:

df1:

    ID   x    y     z     
    1    a    b     c     
    2    d    b     c
    3    a    e     c 
    4    a    b     c

我一直在尝试使用其他帖子建议的匹配功能,但我一直遇到问题,我的df1数据帧被替换为来自df2的NA值。 这是我一直在使用的代码

for (i in names(df2)[2:length(names(df2))]) {
  df1[i] <- df2[match(df1$ID, df2$ID)]
}

由于

3 个答案:

答案 0 :(得分:0)

你的代码对我不起作用,所以我稍微改了一下但是有效。如果您正在阅读外部文件中的数据,请在阅读时使用stringAsFactor = FALSE,这样您就不会遇到问题。

df1 = data.frame("ID" = 1:4,"x" = rep("a",4), "y" =rep("b",4),"z" = rep("c",4),
                 stringsAsFactors=FALSE)
df2 = data.frame("ID" = 2:3,"x" = c("d",NA), "y" = c(NA,"e"),stringsAsFactors=FALSE)

for(i in 1:nrow(df2)){
  new_data = df2[i,-which(apply(df2[i,],2,is.na))]
  pos = as.numeric(new_data[1])
  col_replace = intersect(colnames(new_data),colnames(df1))
  df1[pos,col_replace] = new_data
}

答案 1 :(得分:0)

使用dplyr的解决方案。我们的想法是将两个数据帧转换为长格式,进行连接和替换值,并将格式转换回宽格式。 df5是最终输出。

library(dplyr)
library(tidyr)

df3 <- df1 %>% gather(Col, Value, -ID) 
df4 <- df2 %>% gather(Col, Value, -ID, na.rm = TRUE)
df5 <- df3 %>%
  left_join(df4, by = c("ID", "Col")) %>%
  mutate(Value.x = ifelse(!is.na(Value.y), Value.y, Value.x)) %>%
  select(ID, Col, Value.x) %>%
  spread(Col, Value.x)
df5
#   ID x y z
# 1  1 a b c
# 2  2 d b c
# 3  3 a e c
# 4  4 a b c

数据

df1 <- read.table(text = "ID   x    y     z     
1    a    b     c     
                  2    a    b     c
                  3    a    b     c 
                  4    a    b     c",
                  header = TRUE, stringsAsFactors = FALSE)

df2 <- read.table(text = "ID   x    y     
 2   d    NA
 3   NA   e",
                  header = TRUE, stringsAsFactors = FALSE)

答案 2 :(得分:0)

As mentioned by alistaire,这是更新联接。它与data.table软件包一起提供:

library(data.table)
setDT(df1)
setDT(df2)
df1[df2, on = "ID", x := ifelse(is.na(i.x), x, i.x)]
df1[df2, on = "ID", y := ifelse(is.na(i.y), y, i.y)]
df1
   ID x y z
1:  1 a b c
2:  2 d b c
3:  3 a e c
4:  4 a b c

如果有很多具有替换值的列,那么在将列名视为数据重整为长格式之后,可能值得跟随www's suggestion进行替换:

library(data.table)
melt(setDT(df1), "ID")[
  melt(setDT(df2), "ID", na.rm = TRUE), on = .(ID, variable), value := i.value][
    , dcast(.SD, ID ~ variable)]
   ID x y z
1:  1 a b c
2:  2 d b c
3:  3 a e c
4:  4 a b c

数据

df1 <- fread(
"ID   x    y     z     
1    a    b     c     
2    a    b     c
3    a    b     c 
4    a    b     c")

df2 <- fread(
"ID   x    y     
 2   d    NA
 3   NA   e")