2014-02-13 113 views
2

我有一個名爲data.framedt,看起來像:的R - 應用和刪除列

row.names  A  B  C  D 
     1 0.1 0.2 0.5 0.3 
     2 0.2 0.3 0.4  0 
     3 10 -0.1 -0.3 0.3 # remove A cause 10/0.2 > 2 

而且我想刪除的列,使得對於列X,如果X[i]/X[i-1]>2,i>=2。 即,如果當前行除以前一行大於2(增加兩倍),請刪除該列。

我已經試過apply像這樣:

temp<-dt 
val<-apply(temp,2,function(y) { 
    y<-na.omit(y) # omit na 
    ans1 <- y[-1,]/y[-nrow(y),] - 1 # divide previous row 
    if (max(ans1,na.rm=TRUE)>2) { 
    y<-NULL # remove from temp 
    } 
}) 

但它似乎並沒有從temp刪除行。我考慮過可能會返回colnames的列表,但我無法從apply內部以他們的方式得到它們。

任何想法?

謝謝。

===編輯===
想通了與lukeA的回答修改後的版本:

val<-sapply(dt,function(y) { 
    y2<-na.omit(y) # omit NA 
    ans1 <- y2[-1]/y2[-length(y2)] - 1 # divide previous row 
    if (max(ans1,na.rm=TRUE)>1.5|min(ans1,na.rm=TRUE)< -0.5) { 
    return(NULL) # return all NULL 
    } else { 
    return(y) # return original 
    } 
}) 

回答

1

這將您的A值轉換爲NA(不適用):

dt$A[-1] <- ifelse(dt$A[-1]/head(dt$A[-1], -1) > 2, NA, dt$A[-1]) 

現在您可以決定如何處理您的A列中的NA s,例如刪除行:

dt <- dt[!is.na(dt$A), ] 

這也將爲工作的所有列這樣的:

dt[, -1] <- sapply(dt[, -1], function(x) { 
    x[-1] <- ifelse(x[-1]/head(x[-1], -1) > 2, NA, x[-1]) 
    x 
}) 
dt <- na.omit(dt) # remove NA rows 

如果你想刪除列NA,你可以做這樣的:

dt[, c(1, which(!is.na(colSums(dt[, -1]))))] 
+0

感謝您的回覆,有沒有一種方法可以像'apply'那樣爲每一列做到這一點?矩陣'dt'只是一個小例子,我會爲一個非常大的矩陣(想'300x300'及以上)做。 –

+0

@Ubobo'dt [,-1]'說*除第一個*以外的每一列,所以:是的。但是,'ifelse'不是最快的。另一方面'colSums'超快。試試看。 – lukeA

+0

謝謝,我在編輯我的評論,但超時了:哦!我用'dt [, - 1]'試過了,但是我得到錯誤'50:In x [-1]/head(x [-1],-1): 較長的對象長度不是較短的倍數對象長度'。結果'dt'是空的。 –