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
私のジレンマから私を助けてください!ありがとう
追加できる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
SeriesからDataFrameに変換し、クエリを実行してから、元に戻します。
_df["Points"] = df["Points"].to_frame().query('Points > 100')["Points"]
_
ここで、.to_frame()
はDataFrameに変換され、末尾の_["Points"]
_はSeriesに変換されます。
メソッド.query()
は、Pandasオブジェクトに1つ以上の列があるかどうかに関係なく、一貫して使用できます。
クエリの代わりにpipe
を使用できます:
s.pipe(lambda x: x[x>0]).pipe(lambda x: x[x<10])