如果75%的列值等于0,如何从数据框中删除行

时间:2016-06-23 13:07:35

标签: python r numpy pandas

我有一个44列和60,000行的数据框。如果它有0到75%的列,我想删除这些行。这个75%:例如在我的情况下,44列中的33列。所以我在R中尝试了以下功能 如,

filter <- apply(df, 1,function(x) any(x[1:33]!=0) && any(x[34:44]!=0) )
df = df[filter,]

它非常适合我要求的那些专栏。但问题是我的数据框有很多行,其值如此,对于某些行,在备用模型中有零,即一列其数值则为零,依此类推。这有时超过33列,上面的函数避免了这些行。

到目前为止,我在R中尝试过,我可以在熊猫中尝试的任何解决方案也都很棒..我知道当pandas中的所有值都不等于零时

 df[(df != 0).all(1)]

以下是我的数据框架的样子,

dim(df)
[1] 57905    44
head(df)

     ID Pe_1    Pe_2    Pe_3    Pe_4    Pe_5    Pe_6    Pe_7    Pe_8    Pe_9    Pe_10   Pe_11   Pe_12   Pe_13   Pe_14   Pe_15   Pe_16   Pe_17   Pe_18   Pe_19   Pe_20   Pe_21   Pe_22   Pe_23   Pe_24   Pe_25   Pe_26   Pe_27   Pe_28   Pe_29   Pe_30   Pe_31   Pe_32   Pe_33   Pe_34   Pe_35   Pe_36   Pe_37   Pe_38   Pe_39   Pe_40   Pe_41   Pe_42   Pe_43   Pe_44
ENSG1   0   0   1   0   0   2   2   1   0   0   0   1   0   3   3   0   1   0   2   0   2   3   1   2   0   2   0   0   0   0   0   2   0   0   0   0   2   0   0   2   0   3   1   3
ENSG2   274 293 300 273 229 124 427 291 274 561 128 506 342 540 376 422 411 190 723 224 303 316 766 697 251 167 271 361 325 133 215 274 217 366 227 579 337 254 570 188 143 363 250 359
ENSG3   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
ENSG4   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
ENSG5   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
ENSG6   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
ENSG7   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
ENSG8   0   1   0   1   1   1   0   2   0   0   0   1   1   1   0   1   0   0   0   0   0   1   1   1   2   1   0   3   0   1   1   2   0   0   0   0   0   0   1   1   0   0   1   1
ENSG9   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
ENSG10  3   2   4   6   21  6   6   13  3   1   1   6   10  4   2   0   1   0   0   0   4   2   5   3   25  9   7   10  7   5   3   0   0   5   1   8   4   5   0   4   1   3   2   4
ENSG11  277 43  79  216 1170    174 213 1303    564 14  53  76  170 1016    32  19  69  69  50  21  75  31  560 86  2668    604 513 303 1378    109 219 172 10  1031    276 242 1587    217 76  43  450 81  502 99

任何建议/帮助都会很棒

6 个答案:

答案 0 :(得分:7)

似乎您要删除超过75%0的行。例如,保留至少有25%非零值的行。

R

df = data.frame(a=c(1,8,0), b=c(0,2,0), c=c(0,0,1), d=c(4,4,0))

df[rowMeans(df!=0)>0.25, ]  # or df[rowMeans(df==0)<0.75, ]
#  a b c d
#1 1 0 0 4
#2 8 2 0 4

Pandas

df = pd.DataFrame({'a':[1,8,0],'b':[0,2,0],'c':[0,0,1], 'd':[4,4,0]})

# In [198]: df
# Out[198]:
#   a  b  c  d
#0  1  0  0  4
#1  8  2  0  4
#2  0  0  1  0

df[df.astype('bool').mean(axis=1)>=0.25] # or df[(~df.astype('bool')).mean(axis=1)<0.75]

#Out[199]:
#   a  b  c  d
#0  1  0  0  4
#1  8  2  0  4

答案 1 :(得分:3)

试试这个(熊猫):

df[(df==0).sum(axis=1)/len(df.columns) <= 0.75]

答案 2 :(得分:3)

Pandas方法,这里我们使用0将df与sumaxis=1行进行比较,这将生成一个Series,其中包含0个值的计数,我们将其与行长度的75%进行比较并过滤df:

In [14]:
df[(df == 0).sum(axis=1) < df.shape[1] * 0.75]

Out[14]:
        ID  Pe_1  Pe_2  Pe_3  Pe_4  Pe_5  Pe_6  Pe_7  Pe_8  Pe_9  ...    \
0    ENSG1     0     0     1     0     0     2     2     1     0  ...     
1    ENSG2   274   293   300   273   229   124   427   291   274  ...     
7    ENSG8     0     1     0     1     1     1     0     2     0  ...     
9   ENSG10     3     2     4     6    21     6     6    13     3  ...     
10  ENSG11   277    43    79   216  1170   174   213  1303   564  ...     

    Pe_35  Pe_36  Pe_37  Pe_38  Pe_39  Pe_40  Pe_41  Pe_42  Pe_43  Pe_44  
0       0      0      2      0      0      2      0      3      1      3  
1     227    579    337    254    570    188    143    363    250    359  
7       0      0      0      0      1      1      0      0      1      1  
9       1      8      4      5      0      4      1      3      2      4  
10    276    242   1587    217     76     43    450     81    502     99  

[5 rows x 45 columns]

答案 3 :(得分:1)

或者@ colonel-beauvel使用rowMeans,你可以使用rowSums

df[rowSums(df[, -1] > 0) / (ncol(df)-1) >= 0.75,]
  • df [, - 1]&gt; 0取得除ID列之外的data.frame,df,并返回逻辑矩阵,无论每个元素。
  • rowSums将所有行添加到一起(它和rowMeans非常快)。
  • ncol返回df的列数(从中减去1)。
  • rowSumsncol的比率与0.75进行比较,返回逻辑。

此逻辑用于对行进行子集化。

答案 4 :(得分:0)

简单的代码,它应该工作:

for i in df:
    iLength = 0
    countZeros = 0

    for j in df:
        iLength += 1
        if i[j] == 0:
            countZeros += 1

    zeroRate = countZeros / iLength
    if zeroRate >= 0.75:
        #DeleteRow

答案 5 :(得分:-2)

R解决方案(希望如此)

我想我得到了这个,跳过你想要的一块。这里和那里之间的代码都是在上下文中的所有代码,并且可以在R中工作。

MakeDF.R <- function(CustomVector,n){
  #just a function to make a sample df
  NewDF <- data.frame(matrix(nrow=n,ncol=length(CustomVector)))
  colnames(NewDF) <- CustomVector
  return(NewDF)
}

制作数据框

DF<-MakeDF.R(c(1:44),10)
#sample df with 44 rows

添加一些带零的行

DF[c(5,6,7),] <- c(1:44)*0
#add sample zero rows

现在你需要的位。

RemoveRows <- lapply(1:nrow(DF),function(i){
  RemoveRow_i = 0
  if(
    length(which(DF[i,] == 0)) > (ncol(DF) * 0.75)  ){
    #above is the "more than 75% zero columns step
    RemoveRow_i = i #select this row as one to be removed
  }
  RemoveRow_i
  #return either the row number or zero
})

这为我们提供了要删除的行列表。现在我们需要清理该列表(删除零)

RemoveRows = RemoveRows[RemoveRows > 0]
#Leaves no zeroes in the list

清理清单后,我们可以删除数据

CleanedDF <- DF[-do.call(rbind,RemoveRows)[,1],]
#the do.call(rbind....) is returning a 1 column dataframe. 
#So the first column is the vector of rows we want to remove.
#the -c(row numbers) removes rows. df[-1,] would delete the first row
#df[-c(1,2),] would delete the first two rows