2016-04-30 87 views
2

我想基於與行變量匹配的列名稱替換數據框單元格中的值,如示例代碼中所示。我知道足夠的知道,嵌套循環不是這樣做的首選方式(並且更有效的解決方案可能非常簡單),但還沒有找到一個乾淨的矢量化方法。我一直在搞嵌套應用,也就是說,在一個被apply調用的函數內部應用,但沒有成功,也沒有看起來像是最好的方式。根據列名和變量匹配替換數據框中的單元格值

輸入:

test.df 
    Group   G1  G2   G3 
1 G1 0.63910462 0.5738143 0.97428347 
2 G2 0.62578294 0.4653417 0.92010090 
3 G3 0.01136336 0.3163722 0.20266664 
4 G1 0.09054996 0.1984567 0.17488220 
5 G2 0.74865266 0.9862222 0.80725355 
6 G3 0.82855980 0.2668529 0.06786335 
7 G1 0.74310410 0.8861169 0.44801963 
8 G2 0.97329786 0.6682355 0.69658779 
9 G3 0.68696020 0.7362139 0.77452962 

輸出:

test.df 
    Group   G1  G2  G3 
1 G1   NA 0.5738143 0.9742835 
2 G2 0.62578294  NA 0.9201009 
3 G3 0.01136336 0.3163722  NA 
4 G1   NA 0.1984567 0.1748822 
5 G2 0.74865266  NA 0.8072535 
6 G3 0.82855980 0.2668529  NA 
7 G1   NA 0.8861169 0.4480196 
8 G2 0.97329786  NA 0.6965878 
9 G3 0.68696020 0.7362139  NA 

代碼:

test.df <- data.frame("Group"=rep(c("G1", "G2", "G3"), 3), "G1"=runif(9, 0, 1), "G2"=runif(9, 0, 1), "G3" = runif(9,0,1)) 

for (j in 1:ncol(test.df)) { 
    for(i in 1:nrow(test.df)) { 
    if(colnames(test.df)[j] == test.df$Group[i]) { 
     test.df[i,j] <- NA 
    } 
    } 
} 

我想我可以用dplyr過濾器來獲得需要被替換的值,替換它們,然後重新組裝數據框,但我有興趣學習其他選項。

+0

只是爲了確定我正確理解你的代碼:例如,你想要做的是消除行列名相等的所有值? –

回答

3

向量化爲match()

idx <- cbind(seq_len(nrow(test.df)), match(test.df$Group, names(test.df)[-1])) 
test.df[-1][idx] <- NA 

idx創建索引矩陣用於收集我們想要轉換爲NA的值。第一部分只是一個序列長度的行數。第二部分將Group列與其他列的名稱匹配。然後我們替換。

這導致更新test.df

Group   G1  G2  G3 
1 G1   NA 0.5738143 0.9742835 
2 G2 0.62578294  NA 0.9201009 
3 G3 0.01136336 0.3163722  NA 
4 G1   NA 0.1984567 0.1748822 
5 G2 0.74865266  NA 0.8072535 
6 G3 0.82855980 0.2668529  NA 
7 G1   NA 0.8861169 0.4480196 
8 G2 0.97329786  NA 0.6965878 
9 G3 0.68696020 0.7362139  NA 

注:我在創作的test.dfstringsAsFactors = FALSE,所以在你的,你將不得不使用test.df$Group <- as.character(test.df$Group)第一,因爲你的例子有它的因素。

+1

我已經足夠重新排列和收集的小組這樣做:'test.df < - test.df [order(test.df $ Group),]',並不知道如何去下一級。現在,它是完全意義上的。事實上,我甚至不需要訂購它。哇。 – Gopala

+0

非常好。謝謝! – Nat

2

你可以拆分行,然後子分配:

s = split(seq_len(nrow(test.df)), test.df$Group) 
for (k in names(s)) test.df[s[[k]], k] <- NA_real_ 

或者與data.table:

library(data.table) 
for (k in names(s)) set(test.df, i = s[[k]], j = k, v = NA_real_) 

注意,你實際上並不在這裏使用一個data.table;我們在數據框上使用setset在這種情況下的優點是通過引用對其進行修改。

+0

我懷疑這是一個愚蠢的問題,但無法找到目標。 – Frank

0

路過巴吞魯:

test.df %>% mutate(G1 = ifelse(Group == "G1", NA, G1)) 

# Group   G1  G2  G3 
# 1 G1   NA 0.3337749 0.3999944 
# 2 G2 0.25801678 0.4763512 0.3253522 
# 3 G3 0.47854525 0.8921983 0.7570871 
# 4 G1   NA 0.8643395 0.2026923 
# 5 G2 0.08424691 0.3899895 0.7111212 
# 6 G3 0.87532133 0.7773207 0.1216919 
# 7 G1   NA 0.9606180 0.2454885 
# 8 G2 0.83944035 0.4346595 0.1433044 
# 9 G3 0.34668349 0.7125147 0.2396294 

現在,我怎麼了發生變異通過所有列掃?

相關問題