В настоящее время у меня есть фрейм данных, состоящий из столбцов с 1 и 0 в качестве значений, я хотел бы перебрать столбцы и удалить те, которые состоят только из 0. Вот что я пробовал до сих пор:
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)]
В котором годы - это список фреймов данных за разные годы, которые я анализирую, один состоит из столбцов с единицей в них, а нули - это список столбцов, содержащих все нули. Есть ли лучший способ удалить столбец на основе условия? По какой-то причине мне нужно проверить, находятся ли столбцы единиц в списке нулей, и удалить их из списка нулей, чтобы получить список всех столбцов с нулевыми значениями.
Ответы:
df.loc[:, (df != 0).any(axis=0)]
Вот подробное описание того, как это работает:
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
создает логический DataFrame, который имеет значение True, где неdf
равно нулю: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)
возвращает логическую серию, указывающую, какие столбцы имеют ненулевые записи. (any
Операция агрегирует значения по оси 0, то есть по строкам, в одно логическое значение. Следовательно, результатом является одно логическое значение для каждого столбца.)In [78]: (df != 0).any(axis=0) Out[78]: 0 True 1 False 2 True 3 False dtype: bool
И
df.loc
может использоваться для выбора этих столбцов:In [79]: df.loc[:, (df != 0).any(axis=0)] Out[79]: 0 2 0 1 0 1 0 1 [2 rows x 2 columns]
Чтобы «удалить» нулевые столбцы, переназначьте
df
:df = df.loc[:, (df != 0).any(axis=0)]
источник
df.loc[:, (~df.isin([0,1])).any(axis=0)]
тоже будет работать.df = pd.DataFrame([[np.nan]*10])
, тоdf.loc[:, df.any(axis=0)]
возвращает пустую DataFrame, аdf.loc[:, (df != 0).any(axis=0)]
возвращает DataFrame с 10 колоннами.(df == 0).all(axis=0)
это проще.Вот альтернативный способ использования:
df.replace(0,np.nan).dropna(axis=1,how="all")
По сравнению с решением unutbu этот способ явно медленнее:
%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)
источник
Если вам нужен более выразительный способ получения имен нулевых столбцов, чтобы вы могли распечатать / зарегистрировать их и поместить их на месте по их именам :
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)
Некоторые ломаются:
# 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 ]
источник