パンダシリーズをフィルタリングする方法


98

groupby( 'name')を実行し、他の列でmean()関数を使用した後、このようなシリーズがあります

name
383      3.000000
663      1.000000
726      1.000000
737      9.000000
833      8.166667

1.000000の平均値で行を除外する方法を教えてもらえますか?ありがとう、そして私はあなたの助けに大いに感謝します。


さて、与えられた条件でシリーズをどのようにフィルタリングしますか?

回答:


132
In [5]:

import pandas as pd

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

s = pd.Series(test)
s = s[s != 1]
s
Out[0]:
383    3.000000
737    9.000000
833    8.166667
dtype: float64

11
以下の答えは連鎖できるので(つまり、定義sしてから式で2回使用する必要がない)私は好みます。ただし、パンダ0.18からのみ機能します。
ianS 2017年

piRSquaredの回答のタイミング比較も参照してください。
ianS 2017年

67

パンダバージョン0.18+から、シリーズのフィルタリングも以下のように実行できます

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

pd.Series(test).where(lambda x : x!=1).dropna()

チェックアウト:http//pandas.pydata.org/pandas-docs/version/0.18.1/whatsnew.html#method-chaininng-improvements


3
メソッドチェーンの方がはるかに優れています(そしてSparkを思い出させます)
Dylan Hogg 2017

本当ですが、この場合、Sparkはより直感的なことを行います。つまり、述語と一致しない行を削除するだけです。つまり、ドキュメントを読むまでは明らかに不要に思えた「.dropna()」部分を使用しないということです。それに噛まれた:D
FlorentMoiny20年

46

以下のようDACWが指摘し、ある方法チェインの改善あなたは非常にうまく探しているものを行うパンダ0.18.1では。

を使用する代わりに.where、関数を.locインデクサーまたはシリーズインデクサーのいずれかに渡して[]、次の呼び出しを回避できます.dropna

test = pd.Series({
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
})

test.loc[lambda x : x!=1]

test[lambda x: x!=1]

同様の動作がDataFrameクラスとNDFrameクラスでサポートされています。


2
これは私のお気に入りの答えであり、numpyに陥ることなく最速のようです(タイミングの比較を参照)。
ianS 2017年

22

これを行う簡単な方法は、を使用numpyして再構築し、基になる配列をスライスすることです。以下のタイミングを参照してください。

mask = s.values != 1
pd.Series(s.values[mask], s.index[mask])

0
383    3.000000
737    9.000000
833    8.166667
dtype: float64

ナイーブなタイミング

ここに画像の説明を入力してください


、私はあなたの方法が好きです、私がマルチマスクを持っているかどうか知りたいです。Thx
Menglong Li

1
@MenglongLiによって異なりますが、質問する必要があります。ほとんどの場合、それらを&と組み合わせます。mask = mask1&mask2
piRSquared 2017

6

もう1つの方法は、最初にDataFrameに変換し、クエリメソッドを使用することです(numexprがインストールされていると仮定します)。

import pandas as pd

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

s = pd.Series(test)
s.to_frame(name='x').query("x != 1")

条件を文字列として渡すのは良い考えではないと思います
SzymonPajzert 2017

1
これにより、データフレームのすべてのオーバーヘッドが追加され、非常に遅くなります。
幻想的な

5

連鎖操作が好きな場合は、次のcompress関数を使用することもできます。

test = pd.Series({
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
})

test.compress(lambda x: x != 1)

# 383    3.000000
# 737    9.000000
# 833    8.166667
# dtype: float64

1

私の場合、値が文字のタプルであるパンダシリーズがありました

Out[67]
0    (H, H, H, H)
1    (H, H, H, T)
2    (H, H, T, H)
3    (H, H, T, T)
4    (H, T, H, H)

したがって、インデックスを使用して系列をフィルタリングできますが、必要なインデックスを作成するために必要ですapply。私の条件は、「「H」が1つだけあるすべてのタプルを検索する」です。

series_of_tuples[series_of_tuples.apply(lambda x: x.count('H')==1)]

私はそれが「連鎖可能」ではないことを認めます(つまり、series_of_tuples2回繰り返すことに注意してください。一時的な級数を変数に格納して、apply(...)を呼び出すことができるようにする必要があります)。

ブールインデックスを生成するために要素ごとに動作できる他のメソッド(以外.apply(...))もあります。

次のような連鎖可能な関数を使用した他の多くの回答(承認された回答を含む):

  • .compress()
  • .where()
  • .loc[]
  • []

これらは、シリーズの個々のではなく、シリーズ適用される呼び出し可能オブジェクト(ラムダ)受け入れます

したがって、上記の条件/呼び出し可能/ラムダを次のようなチェーン可能な関数のいずれかで使用しようとすると、一連のタプルが奇妙に動作しました.loc[]

series_of_tuples.loc[lambda x: x.count('H')==1]

エラーが発生します:

KeyError: 'レベルHは名前と同じである必要があります(なし)'

非常に混乱していましたが、Series.countseries_of_tuples.count(...)関数を使用しているようです。これは私が望んでいたものではありません。

別のデータ構造の方が良いかもしれないことを認めます。

  • カテゴリデータ型?
  • データフレーム(タプルの各要素が列になります)
  • 一連の文字列(タプルを連結するだけ):

これにより、一連の文字列が作成されます(つまり、タプルを連結し、タプル内の文字を1つの文字列に結合します)。

series_of_tuples.apply(''.join)

だから私はチェーン可能なものを使うことができますSeries.str.count

series_of_tuples.apply(''.join).str.count('H')==1
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.