2014-10-03 22 views
1

一個數據幀有條件的置換對象列值的讓我們做一個虛擬數據集中,使用R

ll = data.frame(rbind(c(2,3,5), c(3,4,6), c(9,4,9))) 
colnames(ll)<-c("b", "c", "a") 
> ll 
    b c a 
1 2 3 5 
2 3 4 6 
3 9 4 9 

P = data.frame(cbind(c(3,5), c(4,6), c(8,7))) 
colnames(P)<-c("a", "b", "c") 
> P 
    a b c 
1 3 4 8 
2 5 6 7 

我想創建一個新的數據幀,其中L1中的每一列中的值會變成0時,它小於p的第一行中的a,b,& c的對應值;換句話說,我希望看到

> new_ll 
    b c a 
1 0 0 5 
2 0 0 6 
3 9 0 9 

所以我嘗試了這種方式

nn=c("a", "b", "c") 
new_ll = sapply(nn, function(i) 
    ll[,paste0(i)][ll[,paste0(i)] < P[,paste0(i)][1]] <- 0) 

但它並不適用於某些原因!我必須在我的劇本中犯一個愚蠢的錯誤!任何想法?

> new_ll 
a b c 
0 0 0 

回答

1

您可以找到值ll是比P第一排小有apply

t(apply(ll, 1, function(x) x<P[1,][colnames(ll)])) 
     [,1] [,2] [,3] 
[1,] TRUE TRUE FALSE 
[2,] TRUE TRUE FALSE 
[3,] FALSE TRUE FALSE 

這裏,P第一行是有序的匹配ll,那麼元素進行比較。

感謝阿難Mahto,其識別apply不需要:您希望用0來代替

ll < c(P[1, names(ll)]) 
     b c  a 
[1,] TRUE TRUE FALSE 
[2,] TRUE TRUE FALSE 
[3,] FALSE TRUE FALSE 

TRUE值顯示:

ll[ ll < c(P[1, names(ll)]) ] <- 0 
ll 
    b c a 
1 0 0 5 
2 0 0 6 
3 9 0 9 

要解決你的代碼,你想要的東西像這樣:

do.call(cbind, lapply(names(ll), function(i) { 
    ll[,i][ll[,i] < P[,i][1]] <- 0 
    return(ll[i])})) 
    b c a 
1 0 0 5 
2 0 0 6 
3 9 0 9 

發生了什麼變化?首先,sapply更改爲lapply,函數爲每次迭代返回一個向量。其次,名稱以預期結果的正確順序呈現。第三,結果與cbind放在一起得到最終矩陣。作爲獎勵,對paste0的多餘呼叫已被刪除。

+0

感謝,但什麼是錯我的代碼...我的意思是,爲什麼sapply不起作用? – ToNoY 2014-10-03 16:07:39

+1

你的代碼不起作用,因爲該函數沒有返回任何有用的東西。 – 2014-10-03 16:11:08

+1

這裏我不認爲「應用」是必需的。你不能只是[ll A5C1D2H2I1M1N2O1R2T1 2014-10-03 16:34:06

0

您也可以嘗試mapply,它將函數應用於每個對應的元素。這裏,llP都是data.frames。因此,它適用於每個色譜柱的功能,並進行回收。在這裏,我匹配Pcolumn namesll(與@Matthew Lundberg相似)的column names,並且查找每列中ll的哪些元素是<比對應列(P的一行被回收)並且返回邏輯索引。然後將符合邏輯條件的元素分配給0

indx <- mapply(`<`, ll, P[1,][names(ll)]) 
new_ll <- ll 
new_ll[indx] <- 0 
new_ll 
# b c a 
#1 0 0 5 
#2 0 0 6 
#3 9 0 9 
0

如果你知道llP都是數字,你可以做到這一點也爲

llm <- as.matrix(ll) 
pv <- as.numeric(P[1, colnames(llm)]) 
llm[sweep(llm, 2, pv, `<=`)] <- 0 
data.frame(llm) 
# b c a 
# 1 0 0 5 
# 2 0 0 6 
# 3 9 0 9