Obecnie mam ramkę danych składającą się z kolumn z 1 i 0 jako wartościami, chciałbym iterować przez kolumny i usuwać te, które składają się tylko z 0. Oto, czego próbowałem do tej pory:
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)]
W których latach jest lista ramek danych z różnych lat, które analizuję, jedynki to kolumny zawierające jedynkę, a zera to lista kolumn zawierających same zera. Czy istnieje lepszy sposób na usunięcie kolumny na podstawie warunku? Z jakiegoś powodu muszę sprawdzić, czy kolumny jedynek również znajdują się na liście zer i usunąć je z listy zer, aby uzyskać listę wszystkich kolumn zerowych.
Odpowiedzi:
df.loc[:, (df != 0).any(axis=0)]
Oto zestawienie tego, jak to działa:
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
tworzy wartość logiczną DataFrame, która ma wartość True, gdziedf
jest różna od zera: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)
zwraca serię logiczną wskazującą, które kolumny mają niezerowe wpisy. (any
Operacja agreguje wartości wzdłuż osi 0 - tj. Wzdłuż wierszy - w jedną wartość logiczną. Dlatego wynikiem jest jedna wartość logiczna dla każdej kolumny).In [78]: (df != 0).any(axis=0) Out[78]: 0 True 1 False 2 True 3 False dtype: bool
I
df.loc
można ich użyć do wybrania tych kolumn:In [79]: df.loc[:, (df != 0).any(axis=0)] Out[79]: 0 2 0 1 0 1 0 1 [2 rows x 2 columns]
Aby „usunąć” kolumny zerowe, przypisz ponownie
df
:df = df.loc[:, (df != 0).any(axis=0)]
źródło
df.loc[:, (~df.isin([0,1])).any(axis=0)]
również zadziała.df = pd.DataFrame([[np.nan]*10])
,df.loc[:, df.any(axis=0)]
zwraca wtedy pustą ramkę DataFrame, adf.loc[:, (df != 0).any(axis=0)]
zwraca ramkę DataFrame z 10 kolumnami.(df == 0).all(axis=0)
jest to prostsze.Oto alternatywny sposób użycia is
df.replace(0,np.nan).dropna(axis=1,how="all")
W porównaniu z rozwiązaniem unutbu ten sposób jest oczywiście wolniejszy:
%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)
źródło
Jeśli chcesz uzyskać bardziej wyrazisty sposób uzyskiwania nazw kolumn zerowych, abyś mógł je wydrukować / zarejestrować i upuścić je na miejscu według ich nazw :
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)
Niektóre załamują się:
# 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 ]
źródło