如何在两个值之间的 DataFrame 中选择行
- 2024-12-24 08:56:00
- admin 原创
- 83
问题描述:
我正在尝试修改 DataFramedf
以仅包含列中的值closing_price
介于 99 和 101 之间的行,并尝试使用以下代码执行此操作。
但是,我得到了错误
ValueError:Series 的真值不明确。请使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()
我想知道是否有一种不使用循环就能做到这一点的方法。
df = df[99 <= df['closing_price'] <= 101]
解决方案 1:
考虑Series.between:
df = df[df['closing_price'].between(99, 101)]
解决方案 2:
您应该使用()
对布尔向量进行分组来消除歧义。
df = df[(df['closing_price'] >= 99) & (df['closing_price'] <= 101)]
解决方案 3:
有一个更好的选择 - 使用query()方法:
In [58]: df = pd.DataFrame({'closing_price': np.random.randint(95, 105, 10)})
In [59]: df
Out[59]:
closing_price
0 104
1 99
2 98
3 95
4 103
5 101
6 101
7 99
8 95
9 96
In [60]: df.query('99 <= closing_price <= 101')
Out[60]:
closing_price
1 99
5 101
6 101
7 99
更新:回答评论(编辑以修复小错误):
我喜欢这里的语法,但是在尝试与表达式结合时失败了:
df.query('(mean - 2*sd) <= closing_price <= (mean + 2*sd)')
我的数据都在平均值的 2 个标准差之内,因此我将执行 1 来演示:
In [161]: qry = ("(closing_price.mean() - closing_price.std())" +
...: " <= closing_price <= " +
...: "(closing_price.mean() + closing_price.std())")
...:
In [162]: df.query(qry)
Out[162]:
closing_price
1 99
2 98
5 101
6 101
7 99
9 96
或者
In [163]: mean = df['closing_price'].mean()
...: sd = df['closing_price'].std()
...: df.query('(@mean - @sd) <= closing_price <= (@mean + @sd)')
...:
Out [163]:
closing_price
1 99
2 98
5 101
6 101
7 99
9 96
解决方案 4:
newdf = df.query('closing_price.mean() <= closing_price <= closing_price.std()')
或者
mean = closing_price.mean()
std = closing_price.std()
newdf = df.query('@mean <= closing_price <= @std')
解决方案 5:
如果必须反复调用(针对不同的边界和),则许多工作会不必要地重复。在这种情况下,对帧/系列进行一次排序然后使用会很有帮助。我测得的速度提高了 25 倍,见下文。pd.Series.between(l,r)
l
`r`pd.Series.searchsorted()
def between_indices(x, lower, upper, inclusive=True):
"""
Returns smallest and largest index i for which holds
lower <= x[i] <= upper, under the assumption that x is sorted.
"""
i = x.searchsorted(lower, side="left" if inclusive else "right")
j = x.searchsorted(upper, side="right" if inclusive else "left")
return i, j
# Sort x once before repeated calls of between()
x = x.sort_values().reset_index(drop=True)
# x = x.sort_values(ignore_index=True) # for pandas>=1.0
ret1 = between_indices(x, lower=0.1, upper=0.9)
ret2 = between_indices(x, lower=0.2, upper=0.8)
ret3 = ...
基准
测量对 的重复评估(n_reps=100
)pd.Series.between()
以及基于 的方法pd.Series.searchsorted()
,针对不同的参数lower
和upper
。在我的 MacBook Pro 2015 上,使用 Python v3.8.0 和 Pandas v1.0.3,以下代码产生以下输出
# pd.Series.searchsorted()
# 5.87 ms ± 321 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
# pd.Series.between(lower, upper)
# 155 ms ± 6.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# Logical expressions: (x>=lower) & (x<=upper)
# 153 ms ± 3.52 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
import numpy as np
import pandas as pd
def between_indices(x, lower, upper, inclusive=True):
# Assumption: x is sorted.
i = x.searchsorted(lower, side="left" if inclusive else "right")
j = x.searchsorted(upper, side="right" if inclusive else "left")
return i, j
def between_fast(x, lower, upper, inclusive=True):
"""
Equivalent to pd.Series.between() under the assumption that x is sorted.
"""
i, j = between_indices(x, lower, upper, inclusive)
if True:
return x.iloc[i:j]
else:
# Mask creation is slow.
mask = np.zeros_like(x, dtype=bool)
mask[i:j] = True
mask = pd.Series(mask, index=x.index)
return x[mask]
def between(x, lower, upper, inclusive=True):
mask = x.between(lower, upper, inclusive=inclusive)
return x[mask]
def between_expr(x, lower, upper, inclusive=True):
if inclusive:
mask = (x>=lower) & (x<=upper)
else:
mask = (x>lower) & (x<upper)
return x[mask]
def benchmark(func, x, lowers, uppers):
for l,u in zip(lowers, uppers):
func(x,lower=l,upper=u)
n_samples = 1000
n_reps = 100
x = pd.Series(np.random.randn(n_samples))
# Sort the Series.
# For pandas>=1.0:
# x = x.sort_values(ignore_index=True)
x = x.sort_values().reset_index(drop=True)
# Assert equivalence of different methods.
assert(between_fast(x, 0, 1, True ).equals(between(x, 0, 1, True)))
assert(between_expr(x, 0, 1, True ).equals(between(x, 0, 1, True)))
assert(between_fast(x, 0, 1, False).equals(between(x, 0, 1, False)))
assert(between_expr(x, 0, 1, False).equals(between(x, 0, 1, False)))
# Benchmark repeated evaluations of between().
uppers = np.linspace(0, 3, n_reps)
lowers = -uppers
%timeit benchmark(between_fast, x, lowers, uppers)
%timeit benchmark(between, x, lowers, uppers)
%timeit benchmark(between_expr, x, lowers, uppers)
解决方案 6:
相反
df = df[99 <= df['closing_price'] <= 101]
你应该用这个
df = df[(99 <= df['closing_price']) & (df['closing_price'] <= 101)]
我们必须使用 NumPy 的按位逻辑运算符|
, &
, ~
,^
来进行复合查询。此外,括号对于运算符优先级也很重要。
欲了解更多信息,请访问链接:比较、掩码和布尔逻辑(摘自 Jake VanderPlas 撰写的《Python 数据科学手册》)。
解决方案 7:
如果您要处理多个值和多个输入,也可以设置这样的应用函数。在这种情况下,过滤数据框中属于特定范围内的 GPS 位置。
def filter_values(lat,lon):
if abs(lat - 33.77) < .01 and abs(lon - -118.16) < .01:
return True
elif abs(lat - 37.79) < .01 and abs(lon - -122.39) < .01:
return True
else:
return False
df = df[df.apply(lambda x: filter_values(x['lat'],x['lon']),axis=1)]
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)