Ich habe derzeit einen Datenrahmen, der aus Spalten mit Einsen und Nullen als Werten besteht. Ich möchte die Spalten durchlaufen und diejenigen löschen, die nur aus Nullen bestehen. Folgendes habe ich bisher versucht:
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 welchen Jahren ist eine Liste von Datenrahmen für die verschiedenen Jahre, die ich analysiere, Einsen bestehen aus Spalten mit einer Eins und Nullen ist eine Liste von Spalten, die alle Nullen enthalten. Gibt es eine bessere Möglichkeit, eine Spalte basierend auf einer Bedingung zu löschen? Aus irgendeinem Grund muss ich prüfen, ob die Einsenspalten auch in der Nullenliste enthalten sind, und sie aus der Nullenliste entfernen, um eine Liste aller Nullspalten zu erhalten.
Antworten:
df.loc[:, (df != 0).any(axis=0)]
Hier ist eine Aufschlüsselung der Funktionsweise:
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 != 0
Erstellt einen booleschen DataFrame, der Truedf
ist, wobei er ungleich Null ist: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)
Gibt eine boolesche Reihe zurück, die angibt, welche Spalten Einträge ungleich Null haben. (Dieany
Operation aggregiert Werte entlang der 0-Achse - dh entlang der Zeilen - zu einem einzigen Booleschen Wert. Daher ist das Ergebnis ein Boolescher Wert für jede Spalte.)In [78]: (df != 0).any(axis=0) Out[78]: 0 True 1 False 2 True 3 False dtype: bool
Und
df.loc
kann verwendet werden, um diese Spalten auszuwählen:In [79]: df.loc[:, (df != 0).any(axis=0)] Out[79]: 0 2 0 1 0 1 0 1 [2 rows x 2 columns]
Um die Nullspalten zu "löschen", weisen Sie Folgendes neu zu
df
:df = df.loc[:, (df != 0).any(axis=0)]
quelle
df.loc[:, (~df.isin([0,1])).any(axis=0)]
würde auch funktionieren.df = pd.DataFrame([[np.nan]*10])
, danndf.loc[:, df.any(axis=0)]
eine leere Datenrahmen zurück, währenddf.loc[:, (df != 0).any(axis=0)]
kehrt einen Datenrahmen mit 10 Spalten.(df == 0).all(axis=0)
ist einfacher.Hier ist eine alternative Art zu verwenden ist
df.replace(0,np.nan).dropna(axis=1,how="all")
Verglichen mit der Lösung von unutbu ist dieser Weg offensichtlich langsamer:
%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)
quelle
Für den Fall, dass Sie eine aussagekräftigere Methode zum Abrufen der Nullspaltennamen wünschen, damit Sie sie drucken / protokollieren und an Ort und Stelle nach ihren Namen ablegen können :
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)
Einige brechen zusammen:
# 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 ]
quelle