条件替换使用来自其他数据帧的列/行名称的匹配

时间:2017-08-16 14:22:08

标签: r plyr

我有两个数据框:

id <- c("a", "b", "c")
a <- 0
b <- 0 
c <- 0
df1 <- data.frame(id, a, b, c)

  id a b c
1  a 0 0 0
2  b 0 0 0
3  c 0 0 0

num <- c("a", "c", "c")
partner <- c("b", "b", "a")
value <- c("10", "20", "30")
df2 <- data.frame(num, partner, value)

  num partner value
1   a       b    10
2   c       b    20
3   c       a    30

我希望在每个实例df1中用df2$value替换df1$id==df2$num & colnames(df1)==df2$partner中的零。所以输出应该如下:

a <- c(0, 0, 30)
b <- c(10, 0, 20)
c <- c(0, 0, 0)
df.nice <- data.frame(id, a, b, c)

  id  a  b c
1  a  0 10 0
2  b  0  0 0
3  c 30 20 0

我可以用以下内容替换单个单元格:

df1$b[df1$id=="a"] <- ifelse(df2$num=="a" & df2$partner=="b", df2$value, 0)

但是我需要循环遍历大数据帧的所有可能的df1行/列组合。我怀疑这涉及到plyr并匹配在一起,但无法弄清楚如何。

更新

感谢@MikeH。,我已经转向使用重塑。这似乎有效:

df.nice <- melt(df2, id=c("num", "partner"))
df.nice <- dcast(test.nice, num ~ partner, value.var="value")

产生这个:

  num    a  b
1   a <NA> 10
2   c   30 20

我确实需要所有可能的行/列组合,但所有行都表示为零。有没有办法让reshape从另一个数据框(例如,df1)获取行和列,或者我应该在重新整形后绑定它们吗?

1 个答案:

答案 0 :(得分:1)

如果你想要替换(而不是重塑)我认为一个简单的基本R解决方案将是:

idxs <- t(mapply(cbind, match(df2$num, df1$id), match(df2$partner, names(df1))))
df1[idxs] <- df2$value

df1
  id  a  b c
1  a  0 10 0
2  b  0  0 0
3  c 30 20 0

请注意,我使用t(mapply(...))构建要替换的行/列组合查找。当您选择df1[idxs]时,这会转换为矩阵(以选择特定的行/列组合),然后转换回data.frame

我必须使用stringsAsFactors = FALSE读取您的数据,以便值正确注册(而不是数字)。

数据:

df2 <- data.frame(num, partner, value, stringsAsFactors = F)
df1 <- data.frame(id, a, b, c, stringsAsFactors = F)