パンダでゼロのみを含む列を削除するにはどうすればよいですか?


90

現在、値が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)]

分析しているさまざまな年のデータフレームのリストは年であり、1は1を含む列で構成され、ゼロはすべてゼロを含む列のリストです。条件に基づいて列を削除するより良い方法はありますか?何らかの理由で、1の列がゼロのリストにも含まれているかどうかを確認し、それらをゼロのリストから削除して、すべてのゼロの列のリストを取得する必要があります。


回答:


220
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 != 0dfがゼロ以外の場合にTrueであるブールDataFrameを作成します。

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軸に沿った値(つまり、行に沿った値)が1つのブール値に集約されます。したがって、結果は各列に1つのブール値になります。)

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 2016年

1
df.loc[:, (~df.isin([0,1])).any(axis=0)]また動作します。
unutbu 2016年

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 2018

5
条件が真でないかどうかをチェックするよりも、条件が真であるかどうかをチェックする方が理解しやすいと思います。(df == 0).all(axis=0)もっと簡単だと思います。
Ryszard Cetnarski 2018

2
故障ありがとうございます。それは物事を非常に明確にしました。
RegiMathew19年

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 ]

0

列にいくつかのNaN値がある場合、0とNaNの両方を持つ列を削除する場合は、このアプローチを使用することをお勧めします。

df.loc[:, df.sum() != 0]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.