如何删除熊猫中仅包含零的列?


87

我目前有一个数据框,其中包含以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)]

在哪几年是我正在分析的各个年份的数据帧的列表,其中的数据帧由其中包含一个的列组成,而零是包含所有零的列的列表。是否有更好的方法根据条件删除列?由于某种原因,我必须检查一列是否也位于零列表中,并将它们从零列表中删除,以获得所有零列的列表。


Answers:


213
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创建一个布尔数据框,该框为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)]

我正在尝试删除包含0或1的列,并给出错误:df = df.loc [:,(df!= 0&df!= 1).any(axis = 0)]
morpheus

1
df.loc[:, (~df.isin([0,1])).any(axis=0)]也可以。
Unutbu

1
@IgorFobia:很多东西都是假的,而不是0。例如,空字符串或None或NaN。为了说明两者之间的区别,如果df = pd.DataFrame([[np.nan]*10]),则df.loc[:, df.any(axis=0)]返回一个空的DataFrame,而df.loc[:, (df != 0).any(axis=0)]返回一个包含10列的DataFrame。
Unutbu

4
我相信,如果我们检查条件是否为真,则比检查条件是否为真更容易理解。我认为(df == 0).all(axis=0)更简单。
Ryszard Cetnarski

2
感谢您的细分。这使事情很清楚。
雷吉·马修

7

这是另一种使用方式是

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)

0

如果您希望获得一种更具表现力的方式来获取零列名称,那么您可以打印/记录它们,并按其名称就地放置它们:

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 ]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.