web-dev-qa-db-ja.com

pandas Series(pandas.Series.query()))のクエリメソッドなどはありますか?

pandas.DataFrame.query()メソッドは、ロードまたはプロット時にデータを(事前/事後)フィルタリングするために非常に役立ちます。これは、メソッドチェーンに特に便利です。

同じロジックをpandas.Seriesに適用したいと思うことがよくあります。 df.value_countsを返すpandas.Seriesなどのメソッドを実行した後。

列がPlayer, Game, Pointsの巨大なテーブルがあり、14倍以上の3点を持つプレーヤーのヒストグラムをプロットするとします。最初に、各プレーヤーのポイント(groupby -> agg)を合計する必要があります。これにより、最大1000人のプレーヤーのシリーズとそれらの全体的なポイントが返されます。 .queryロジックを適用すると、次のようになります。

df = pd.DataFrame({
    'Points': [random.choice([1,3]) for x in range(100)], 
    'Player': [random.choice(["A","B","C"]) for x in range(100)]})

(df
     .query("Points == 3")
     .Player.values_count()
     .query("> 14")
     .hist())

私が見つけた唯一の解決策は、不必要な割り当てを行い、メソッドチェーンを解除することを余儀なくさせます。

(points_series = df
     .query("Points == 3")
     .groupby("Player").size()
points_series[points_series > 100].hist()

メソッドチェーニングとクエリメソッドはコードを読みやすくするのに役立ちますが、サブセットフィルタリングはすぐに乱雑になります。

# just to make my point :)
series_bestplayers_under_100[series_prefiltered_under_100 > 0].shape

私のジレンマから私を助けてください!ありがとう

18
dmeu

追加できるIIUC query("Points > 100")

df = pd.DataFrame({'Points':[50,20,38,90,0, np.Inf],
                   'Player':['a','a','a','s','s','s']})

print (df)
  Player     Points
0      a  50.000000
1      a  20.000000
2      a  38.000000
3      s  90.000000
4      s   0.000000
5      s        inf

points_series = df.query("Points < inf").groupby("Player").agg({"Points": "sum"})['Points']
print (points_series)     
a = points_series[points_series > 100]
print (a)     
Player
a    108.0
Name: Points, dtype: float64


points_series = df.query("Points < inf")
                  .groupby("Player")
                  .agg({"Points": "sum"})
                  .query("Points > 100")

print (points_series)     
        Points
Player        
a        108.0

別の解決策は Callableによる選択

points_series = df.query("Points < inf")
                  .groupby("Player")
                  .agg({"Points": "sum"})['Points']
                  .loc[lambda x: x > 100]

print (points_series)     
Player
a    108.0
Name: Points, dtype: float64

編集された質問による編集された回答:

np.random.seed(1234)
df = pd.DataFrame({
    'Points': [np.random.choice([1,3]) for x in range(100)], 
    'Player': [np.random.choice(["A","B","C"]) for x in range(100)]})

print (df.query("Points == 3").Player.value_counts().loc[lambda x: x > 15])
C    19
B    16
Name: Player, dtype: int64

print (df.query("Points == 3").groupby("Player").size().loc[lambda x: x > 15])
Player
B    16
C    19
dtype: int64
10
jezrael

SeriesからDataFrameに変換し、クエリを実行してから、元に戻します。

_df["Points"] = df["Points"].to_frame().query('Points > 100')["Points"]
_

ここで、.to_frame()はDataFrameに変換され、末尾の_["Points"]_はSeriesに変換されます。

メソッド.query()は、Pandasオブジェクトに1つ以上の列があるかどうかに関係なく、一貫して使用できます。

7
Martin

クエリの代わりにpipeを使用できます:

s.pipe(lambda x: x[x>0]).pipe(lambda x: x[x<10])
2
Ilya Prokin