2013-09-30 119 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))