2013-09-30 156 views
1

我有一個data.frame,dim = 400行和15000列。我想申請一個條件,對於屬於每個組的行(由df$Group定義),我必須檢查組中是否有超過50%的行中的值。如果是,則保留現有值,否則全部替換爲0根據組的條件(按行)替換每列中的值data.frame

例如,對於基團的df[1:6,1]if sum(df[1:6,1] == 0)/length(df[1:6,1]) >50%,然後在df[1:6,1]所有值將被與0替換。否則現有的價值將保持不變。

樣品輸入:

df <- read.table(text= "DATA r1 r2 r3 Group 
a1 6835 256 0 a 
a2 5395 0 67 a 
a3 7746 0 30 a 
a4 7496 556 50 a 
a5 5780 255 0 a 
a6 6060 603 0 a 
b1 0 0 0 b 
b2 0 258 0 b 
b3 0 0 0 b 
b4 0 0 0 b 
b5 5099 505 0 b 
b6 0 680 0 b 
c1 8443 4900 280 c 
c2 8980 4949 0 c 
c3 7828 0 0 c 
c4 6509 3257 0 c 
c5 6563 0 49 c 
", header=TRUE, na.strings=NA,row.name=1) 
dt <- as.data.table(df) #or data.frame 

預期輸出:

>df 
DATA r1  r2 r3 Group 
a1 6835 256 0  a 
a2 5395  0 67  a 
a3 7746  0 30  a 
a4 7496 556 50  a 
a5 5780 255 0  a 
a6 6060 603 0  a 
b1  0  0 0  b 
b2  0 258 0  b 
b3  0  0 0  b 
b4  0  0 0  b 
b5  0 505 0  b 
b6  0 680 0  b 
c1 8443 4900 0  c 
c2 8980 4949 0  c 
c3 7828  0 0  c 
c4 6509 3257 0  c 
c5 6563  0 0  c 

回答

5

更新:此錯誤,#4957現在固定在v1.8.11。從NEWS

固定#5007還修復#4957,其中.N期間jlapply(.SD, function(x) ...)是不可見的。由於朱巴在這裏注意到它的SO:Replace values in each column based on conditions according to groups (by rows) data.frame


這裏是data.table方式:其中給出

dt[, lapply(.SD, function(v) { 
    len <- length(v) 
    if((sum(v==0)/len)>0.5) rep(0L,len) else v 
}), by="Group", .SDcols=c("r1","r2","r3")] 

Group r1 r2 r3 
1:  a 6835 256 0 
2:  a 5395 0 67 
3:  a 7746 0 30 
4:  a 7496 556 50 
5:  a 5780 255 0 
6:  a 6060 603 0 
7:  b 0 0 0 
8:  b 0 258 0 
9:  b 0 0 0 
10:  b 0 0 0 
11:  b 0 505 0 
12:  b 0 680 0 
13:  c 8443 4900 0 
14:  c 8980 4949 0 
15:  c 7828 0 0 
16:  c 6509 3257 0 
17:  c 6563 0 0 
+0

太好了!,謝謝@ juba。就是我在找什麼! data.table真的讓我們大量的數據集的計算時間。 – Shiv

+0

+1我編輯過使用'.N'而不是'length(v)'。希望好的。 –

+0

@MatthewDowle不能和'lapply'一起工作 - 你需要沿着'lapply(.SD,function(v,.N){...},.N)'行做(除非我'正在運行'data.table'的舊版本,並且該問題已得到解決?) – eddi

1

快速和骯髒的:

ff<-function(x){ 
    if(is.numeric(x)){ 
    b<-by(x==0,df$Group,mean) 
    x[df$Group %in% names(b)[b>0.5]]<-0 
    } 
    x 
} 

data.frame(lapply(df,ff))