回答:
するとlen(df['column name'])
、1つの数値、つまりDataFrameの行数(つまり、列自体の長さ)が取得されます。len
列の各要素に適用する場合は、を使用しますdf['column name'].map(len)
。だから試して
df[df['column name'].map(len) < 2]
df[df['column name'].map(lambda x: str(x)!=".")]
pandas 0.23.4
python 3.6を使用しています
.copy()
引き上げる新しい列を割り当て、例えば(後で編集をしたい場合には、最後にこのデータフレームを警告「A値をデータフレームからのスライスのコピーに設定されしようとしている」。
この質問の元のタイトル「条件式に基づいてpandas DataFrameから行を削除する方法」に直接答えるには(これは必ずしもOPの問題ではないが、この質問に遭遇した他のユーザーを助けることができる)、これを行う1つの方法は、ドロップ方法:
df = df.drop(some labels)
df = df.drop(df[<some boolean condition>].index)
例
列 'score'が<50であるすべての行を削除するには:
df = df.drop(df[df.score < 50].index)
インプレースバージョン(コメントで指摘されているとおり)
df.drop(df[df.score < 50].index, inplace=True)
複数の条件
(ブール索引付けを参照)
演算子は、for 、
|
foror
、&
for です。これらは括弧を使用してグループ化する必要があります。and
~
not
列 'score'が<50および> 20であるすべての行を削除するには
df = df.drop(df[(df.score < 50) & (df.score > 20)].index)
reset_index()
)。多くの行への道が私のデータフレームから削除されたとき、私はこれを難しい方法で見つけました。
test = df.drop(df[df['col1'].dtype == str].index)
が、私はエラーを取得KeyError: False
私も試してみましたdf.drop(df[df.col1.dtype == str].index)
し、df.drop(df[type(df.cleaned_norm_email) == str].index)
しかし何も動いていないようにみえましたか?誰もがアドバイスできますか?ありがとう!@ユーザー
df[(df.score < 50) & (df.score > 20)]
答えの一部として計算することに注意してください。これを逆にdf = df[(df.score >= 50) | (df.score <= 20)]
すると、答えがはるかに速くなります。
をDataFrame
フィルタリングされたバージョン自体に割り当てることができます。
df = df[df.score > 50]
これは以下より高速ですdrop
。
%%timeit
test = pd.DataFrame({'x': np.random.randn(int(1e6))})
test = test[test.x < 0]
# 54.5 ms ± 2.02 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
test = pd.DataFrame({'x': np.random.randn(int(1e6))})
test.drop(test[test.x > 0].index, inplace=True)
# 201 ms ± 17.9 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
test = pd.DataFrame({'x': np.random.randn(int(1e6))})
test = test.drop(test[test.x > 0].index)
# 194 ms ± 7.03 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
@Userの汎用ソリューションを拡張して、drop
無料の代替案を提供します。これは、質問のタイトル(OPの問題ではない)に基づいてここで指示された人々向けです
負の値を持つすべての行を削除したいとします。1つのライナーソリューションは次のとおりです。
df = df[(df > 0).all(axis=1)]
ステップバイステップの説明:-
5x5のランダム正規分布データフレームを生成しましょう
np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,5), columns=list('ABCDE'))
A B C D E
0 1.764052 0.400157 0.978738 2.240893 1.867558
1 -0.977278 0.950088 -0.151357 -0.103219 0.410599
2 0.144044 1.454274 0.761038 0.121675 0.443863
3 0.333674 1.494079 -0.205158 0.313068 -0.854096
4 -2.552990 0.653619 0.864436 -0.742165 2.269755
条件がネガを削除しているとします。条件を満たすブールdf:-
df > 0
A B C D E
0 True True True True True
1 False True False False True
2 True True True True True
3 True True False True False
4 False True True False True
条件を満たすすべての行のブールシリーズ。行の いずれかの要素が条件に失敗した場合、その行はfalseとマークされます。
(df > 0).all(axis=1)
0 True
1 False
2 True
3 False
4 False
dtype: bool
最後に、条件に基づいてデータフレームから行を除外します
df[(df > 0).all(axis=1)]
A B C D E
0 1.764052 0.400157 0.978738 2.240893 1.867558
2 0.144044 1.454274 0.761038 0.121675 0.443863
あなたが実際に戻ってDFに割り当てることができ、削除対フィルター上で行わingが
df = df[(df > 0).all(axis=1)]
これは、NaN(非数値エントリ)を含む行を除外するように簡単に拡張できます。
df = df[(~df.isnull()).all(axis=1)]
これは、次のような場合にも簡略化できます。列Eが負であるすべての行を削除します
df = df[(df.E>0)]
@Userのdrop
ソリューションが未加工のカラムベースのろ過よりも遅い理由に関するいくつかのプロファイリング統計で終わりたいと思います。
%timeit df_new = df[(df.E>0)]
345 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit dft.drop(dft[dft.E < 0].index, inplace=True)
890 µs ± 94.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
カラムは、基本的にSeries
、すなわちA NumPy
配列は、任意のコストをかけずにインデックスを付けることができます。基礎となるメモリ組織が実行速度にどのように影響するかに興味がある人のために、ここでパンダの高速化に関する素晴らしいリンクがあります:
列値の複雑な条件に基づいてデータフレームの行を削除する場合は、上記の方法でそれを書き込むことは複雑になる可能性があります。私は常に機能する次のより簡単な解決策を持っています。「ヘッダー」を使用して列をドロップすると想定し、その列をリストに最初に取得します。
text_data = df['name'].tolist()
リストのすべての要素に関数を適用し、それをパンダシリーズに配置します。
text_length = pd.Series([func(t) for t in text_data])
私の場合、私はトークンの数を取得しようとしていました:
text_length = pd.Series([len(t.split()) for t in text_data])
次に、データフレームに上記のシリーズを含む列を1つ追加します。
df = df.assign(text_length = text_length .values)
これで、次のような新しい列に条件を適用できます。
df = df[df.text_length > 10]
def pass_filter(df, label, length, pass_type):
text_data = df[label].tolist()
text_length = pd.Series([len(t.split()) for t in text_data])
df = df.assign(text_length = text_length .values)
if pass_type == 'high':
df = df[df.text_length > length]
if pass_type == 'low':
df = df[df.text_length < length]
df = df.drop(columns=['text_length'])
return df
df[[(len(x) < 2) for x in df['column name']]]
が、あなたの方がはるかに優れています。ご協力いただきありがとうございます!