web-dev-qa-db-fra.com

Supprimer des lignes avec tous les zéros dans le cadre de données pandas

Je peux utiliser la fonctionnalité pandasdropna() pour supprimer des lignes dont certaines ou toutes les colonnes sont définies comme suit: NA '. Existe-t-il une fonction équivalente pour supprimer des lignes dont toutes les colonnes ont la valeur 0?

P   kt  b   tt  mky depth
1   0   0   0   0   0
2   0   0   0   0   0
3   0   0   0   0   0
4   0   0   0   0   0
5   1.1 3   4.5 2.3 9.0

Dans cet exemple, nous aimerions supprimer les 4 premières lignes du cadre de données.

merci!

55
user308827

Il s'avère que cela peut être joliment exprimé de manière vectorielle:

> df = pd.DataFrame({'a':[0,0,1,1], 'b':[0,1,0,1]})
> df = df[(df.T != 0).any()]
> df
   a  b
1  0  1
2  1  0
3  1  1
70
U2EF1

Bon mot. Aucune transposition nécessaire:

df.loc[~(df==0).all(axis=1)]

Et pour ceux qui aiment la symétrie, cela fonctionne aussi ...

df.loc[(df!=0).any(axis=1)]
75
8one6

Je regarde cette question environ une fois par mois et je dois toujours extraire la meilleure réponse des commentaires:

df.loc[(df!=0).any(1)]

Merci Dan Allan!

15
The Unfun Cat

Remplacez les zéros par nan, puis supprimez les lignes contenant toutes les entrées sous la forme nan . Après cela, remplacez nan par zéros.

df= df.replace(0,nan)
df=df.dropna(how='all',axis=0)
df=df.replace(nan,0)
5
stackpopped

Je pense que cette solution est la plus courte:

df= df[df['ColName'] != 0]
4

Quelques solutions que j'ai trouvées utiles, notamment pour les grands ensembles de données:

df[(df.sum(axis=1) != 0)]       # 30% faster 
df[df.values.sum(axis=1) != 0]  # 3X faster 

Continuant avec l'exemple de @ U2EF1:

In [88]: df = pd.DataFrame({'a':[0,0,1,1], 'b':[0,1,0,1]})

In [91]: %timeit df[(df.T != 0).any()]
1000 loops, best of 3: 686 µs per loop

In [92]: df[(df.sum(axis=1) != 0)]
Out[92]: 
   a  b
1  0  1
2  1  0
3  1  1

In [95]: %timeit df[(df.sum(axis=1) != 0)]
1000 loops, best of 3: 495 µs per loop

In [96]: %timeit df[df.values.sum(axis=1) != 0]
1000 loops, best of 3: 217 µs per loop

Sur un plus grand ensemble de données:

In [119]: bdf = pd.DataFrame(np.random.randint(0,2,size=(10000,4)))

In [120]: %timeit bdf[(bdf.T != 0).any()]
1000 loops, best of 3: 1.63 ms per loop

In [121]: %timeit bdf[(bdf.sum(axis=1) != 0)]
1000 loops, best of 3: 1.09 ms per loop

In [122]: %timeit bdf[bdf.values.sum(axis=1) != 0]
1000 loops, best of 3: 517 µs per loop
3
clocker
import pandas as pd

df = pd.DataFrame({'a' : [0,0,1], 'b' : [0,0,-1]})

temp = df.abs().sum(axis=1) == 0      
df = df.drop(temp)

Résultat:

>>> df
   a  b
2  1 -1
2
Akavall

Vous pouvez utiliser une fonction rapide lambda pour vérifier si toutes les valeurs d'une ligne donnée sont 0. Vous pouvez ensuite utiliser le résultat de l'application de cette lambda pour choisir uniquement les lignes correspondant ou non à cette condition:

import pandas as pd
import numpy as np

np.random.seed(0)

df = pd.DataFrame(np.random.randn(5,3), 
                  index=['one', 'two', 'three', 'four', 'five'],
                  columns=list('abc'))

df.loc[['one', 'three']] = 0

print df
print df.loc[~df.apply(lambda row: (row==0).all(), axis=1)]

Rendements:

              a         b         c
one    0.000000  0.000000  0.000000
two    2.240893  1.867558 -0.977278
three  0.000000  0.000000  0.000000
four   0.410599  0.144044  1.454274
five   0.761038  0.121675  0.443863

[5 rows x 3 columns]
             a         b         c
two   2.240893  1.867558 -0.977278
four  0.410599  0.144044  1.454274
five  0.761038  0.121675  0.443863

[3 rows x 3 columns]
2
8one6

Une autre alternative:

# Is there anything in this row non-zero?
# df != 0 --> which entries are non-zero? T/F
# (df != 0).any(axis=1) --> are there 'any' entries non-zero row-wise? T/F of rows that return true to this statement.
# df.loc[all_zero_mask,:] --> mask your rows to only show the rows which contained a non-zero entry.
# df.shape to confirm a subset.

all_zero_mask=(df != 0).any(axis=1) # Is there anything in this row non-zero?
df.loc[all_zero_mask,:].shape
1
bmc
df = df [~( df [ ['kt'  'b'   'tt'  'mky' 'depth', ] ] == 0).all(axis=1) ]

Essayez cette commande, elle fonctionne parfaitement.

0
Kumar Prasanna