2017-08-15 49 views
-1

使用這個DF:查找單元中的數據幀中並替換其價值沒有循環[R

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。


編輯。 作爲測試所有的答案,我意識到我的問題是非常基本的,並不代表我的問題。我試圖做到沒有循環,但失敗並最終使用它。

所以,我想將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),但不知道是否可以完成沒有循環或不使用列名稱。

謝謝。

+3

'df $ A [df $ m == 2&df $ y == 1999] < - 72' –

回答

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 
+0

太好了。如何使用索引而不是列名?我應該做'DF%>%mutate(。[3] = replace(。[3],m == 2&y == 1999,72))? – noriega

+0

您可以使用'mutate_at'並將列位置傳遞給'.var'變量。 'DF%>%mutate_at(.vars = 3,funs(替換(。,m == 2&y == 1999,72)))'。 – Psidom

+0

不錯。如果需要使用多個列,該怎麼辦?我的意思是:將m = 2,y = 1999,col ='A'替換​​爲72 **和** m = 1,y = 1998,col ='B'替換爲100 – noriega

0

在基地-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進行更改。