pandas系列(pandas.Series.query())是否有查询方法或类似方法?
Is there a query method or similar for pandas Series (pandas.Series.query())?
pandas.DataFrame.query()
方法非常适用于 (pre/post) - 在加载或绘图时过滤数据。它对方法链接特别方便。
我发现自己经常想将相同的逻辑应用于 pandas.Series
,例如在完成了诸如 df.value_counts
之类的方法之后 return 是 pandas.Series
.
例子
让我们假设有一个巨大的 table 列 Player, Game, Points
,我想绘制得分超过 14 乘以 3 的球员的直方图。我首先必须对每个玩家 (groupby -> agg
) 的积分求和,这将 return 一系列约 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
请帮我走出困境!谢谢
如果我没理解错你可以加上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
另一个解决方案是Selection By 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。
无论 Pandas 对象是否有 1 列或多列,都可以一致地使用方法 .query()
。
您可以使用 pipe
:
而不是查询
s.pipe(lambda x: x[x>0]).pipe(lambda x: x[x<10])
pandas.DataFrame.query()
方法非常适用于 (pre/post) - 在加载或绘图时过滤数据。它对方法链接特别方便。
我发现自己经常想将相同的逻辑应用于 pandas.Series
,例如在完成了诸如 df.value_counts
之类的方法之后 return 是 pandas.Series
.
例子
让我们假设有一个巨大的 table 列 Player, Game, Points
,我想绘制得分超过 14 乘以 3 的球员的直方图。我首先必须对每个玩家 (groupby -> agg
) 的积分求和,这将 return 一系列约 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
请帮我走出困境!谢谢
如果我没理解错你可以加上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
另一个解决方案是Selection By 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。
无论 Pandas 对象是否有 1 列或多列,都可以一致地使用方法 .query()
。
您可以使用 pipe
:
s.pipe(lambda x: x[x>0]).pipe(lambda x: x[x<10])