Come faccio a eliminare una colonna che contiene solo zeri in Panda?


90

Al momento ho un dataframe composto da colonne con 1 e 0 come valori, vorrei scorrere le colonne ed eliminare quelle che sono composte solo da 0. Ecco cosa ho provato finora:

ones = []
zeros = []
for year in years:
    for i in range(0,599):
        if year[str(i)].values.any() == 1:
            ones.append(i)
        if year[str(i)].values.all() == 0:
            zeros.append(i)
    for j in ones:
        if j in zeros:
            zeros.remove(j)
    for q in zeros:
        del year[str(q)]

In quali anni è un elenco di dataframe per i vari anni che sto analizzando, quelli sono costituiti da colonne con uno e zeri è un elenco di colonne che contengono tutti zeri. C'è un modo migliore per eliminare una colonna in base a una condizione? Per qualche motivo devo controllare se anche le colonne delle unità sono nell'elenco degli zeri e rimuoverle dall'elenco degli zeri per ottenere un elenco di tutte le colonne zero.


Risposte:


220
df.loc[:, (df != 0).any(axis=0)]

Ecco una ripartizione di come funziona:

In [74]: import pandas as pd

In [75]: df = pd.DataFrame([[1,0,0,0], [0,0,1,0]])

In [76]: df
Out[76]: 
   0  1  2  3
0  1  0  0  0
1  0  0  1  0

[2 rows x 4 columns]

df != 0crea un DataFrame booleano che è True dove dfè diverso da zero:

In [77]: df != 0
Out[77]: 
       0      1      2      3
0   True  False  False  False
1  False  False   True  False

[2 rows x 4 columns]

(df != 0).any(axis=0)restituisce un valore booleano Series che indica quali colonne hanno voci diverse da zero. (L' anyoperazione aggrega i valori lungo l'asse 0, ovvero lungo le righe, in un unico valore booleano. Il risultato è quindi un valore booleano per ogni colonna.)

In [78]: (df != 0).any(axis=0)
Out[78]: 
0     True
1    False
2     True
3    False
dtype: bool

E df.locpuò essere utilizzato per selezionare quelle colonne:

In [79]: df.loc[:, (df != 0).any(axis=0)]
Out[79]: 
   0  2
0  1  0
1  0  1

[2 rows x 2 columns]

Per "eliminare" le zero colonne, riassegna df:

df = df.loc[:, (df != 0).any(axis=0)]

Sto provando a eliminare una colonna se contiene 0 o 1 e dà un errore: df = df.loc [:, (df! = 0 & df! = 1) .any (axis = 0)]
morpheus

1
df.loc[:, (~df.isin([0,1])).any(axis=0)]funzionerebbe anche.
unutbu

1
@IgorFobia: Molte cose sono false senza essere 0. Ad esempio, stringhe vuote o None o NaN. Per dimostrare la differenza, if df = pd.DataFrame([[np.nan]*10]), quindi df.loc[:, df.any(axis=0)]restituisce un DataFrame vuoto, mentre df.loc[:, (df != 0).any(axis=0)]restituisce un DataFrame con 10 colonne.
unutbu

5
Credo sia più facile capire se controlliamo che una condizione sia vera, invece di controllare se la condizione non è vera non è mai non soddisfatta. Penso che (df == 0).all(axis=0)sia più semplice.
Ryszard Cetnarski

2
Grazie per il guasto. Ha reso le cose molto chiare.
Regi Mathew

7

Ecco un modo alternativo per utilizzare è

df.replace(0,np.nan).dropna(axis=1,how="all")

Rispetto alla soluzione di unutbu, questo modo è ovviamente più lento:

%timeit df.loc[:, (df != 0).any(axis=0)]
652 µs ± 5.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df.replace(0,np.nan).dropna(axis=1,how="all")
1.75 ms ± 9.49 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

0

Nel caso in cui desideri un modo più espressivo per ottenere i nomi a colonna zero in modo da poterli stampare / registrare e rilasciarli, sul posto, con i loro nomi :

zero_cols = [ col for col, is_zero in ((df == 0).sum() == df.shape[0]).items() if is_zero ]
df.drop(zero_cols, axis=1, inplace=True)

Alcuni si rompono:

# a pandas Series with {col: is_zero} items
# is_zero is True when the number of zero items in that column == num_all_rows
(df == 0).sum() == df.shape[0])

# a list comprehension of zero_col_names is built from the_series
[ col for col, is_zero in the_series.items() if is_zero ]

0

Nel caso in cui siano presenti alcuni valori NaN nelle colonne, potresti utilizzare questo approccio se desideri rimuovere le colonne che hanno sia 0 che NaN:

df.loc[:, df.sum() != 0]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.