在数据帧中查找单元格并在没有循环R的情况下替换其值

时间:2017-08-15 22:44:17

标签: r dplyr

使用此df:

  DF = data.frame(m=rep(1:2,2), y=rep(1998:1999,each=2), A=c(2:5), B=c(4,NA,6,7))

> DF
  m    y A  B
1 1 1998 2  4
2 2 1998 3 NA
3 1 1999 4  6
4 2 1999 5  7

如何使用此值作为坐标替换单个单元格:

m = 2 ; y = 1999 ; col = 'A' ; val = 72

按照这些值,我想用72替换5。

修改 在测试所有答案时,我意识到我的问题非常基本,并不能代表我的问题。我试图在没有for循环的情况下这样做但失败并最终使用它。

所以,我想替换DF数据框中的值,但使用其他数据框:

repl = data.frame(m=c(2,1), y=c(1999,1998), col=c('A','B'), val=c(72,100))
> repl
  m    y col val
1 2 1999   A  72
2 1 1998   B 100

这意味着repl数据框的每一行都是DF中要替换的值。

我一直在尝试为每一行使用Psidom回答mutate(A = replace(A, m == 2 & y == 1999, 72),但想知道是否可以在没有循环或没有使用列名的情况下完成。

谢谢。

2 个答案:

答案 0 :(得分:2)

dplyr方式为mutate + if_else

DF %>% mutate(A = if_else(m == 2 & y == 1999, 72L, A))

#  m    y  A  B
#1 1 1998  2  4
#2 2 1998  3 NA
#3 1 1999  4  6
#4 2 1999 72  7

mutate + replace

DF %>% mutate(A = replace(A, m == 2 & y == 1999, 72))

#  m    y  A  B
#1 1 1998  2  4
#2 2 1998  3 NA
#3 1 1999  4  6
#4 2 1999 72  7

取决于条件,返回一个替换了预期值的新向量。

更新如果您需要同时进行多项更新,您可以:

1)重塑DF,以便将要更新的列收集到一个列中;

2)加入两个条件列my以及列标题列;

3)更新值;

4)重新塑造数据帧;

tidyr一起,您可以这样做:

library(dplyr); library(tidyr)

DF %>% 
    gather(col, vals, -m, -y) %>% 
    left_join(repl, by = c("m", "y", "col")) %>% 
    mutate(vals = coalesce(val, vals)) %>% 
    select(-val) %>% 
    spread(col, vals)

#  m    y  A   B
#1 1 1998  2 100
#2 1 1999  4   6
#3 2 1998  3  NA
#4 2 1999 72   7

答案 1 :(得分:0)

对于你的后续问题,base-R中的单行方法将是

lapply(1:nrow(repl), function(i) 
       DF[DF$m==repl$m[i] & DF$y==repl$y[i], repl$col[i]] <<- repl$val[i])

DF
  m    y  A   B
1 1 1998  2 100
2 2 1998  3  NA
3 1 1999  4   6
4 2 1999 72   7

这会遍历repl的每一行并对DF进行更改。 <<-强制它对全局环境中的原始DF进行更改。