看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
pandas 的 query() 方法是对 DataFrame 进行数据查询,函数的简洁、实用、直观值得我们认真学习,熟练掌握它可以快速、随心地筛选数据。准确说,query 是使用布尔表达式查询数 DataFrame 的列,这个布尔表达式支持一个文本字符串。
query() 方法的语法十分简单,它作用于 DataFrame 上:
DataFrame.query(expr, inplace=False, **kwargs)
其中的参数:
**kwargs
:pandas.eval() 支持的关键字参数,可用于查询,完整详细信息,请参阅 pandas.eval()。返回:
在 query 方法中最重要的参数就是 expr,它是一个字符串,这个字符串是合法的 Python 逻辑表达式语句,变量会认为是 DataFrame 的列名。支持的功能点有:
Area (cm^2)
此方法使用顶级 pd.eval()
函数计算传递的查询,表达式的计算结果首先传递给 DataFrame.loc
,如果由于多维键(例如 DataFrame)而失败,则结果将传递给DataFrame.__getitem__()
。
默认情况下,query() 方法使用略微修改的 Python语 法。例如,& 和 |(按位)运算符近似表达 and 和 or,这在语法上是有效的 Python,但是语义不同。可以通过传递关键字参数 parser='python' (这是 pd.eval 的参数,默认是 parser='pandas' )来更改表达式的语义。这将强制执行与 Python 中相同的语义。同样,您可以传递 engine='python' 以使用 python 本身作为后端计算表达式。不建议这样做,因为与使用 numexpr 作为引擎相比,这样做效率低下。
默认情况下,DataFrame.index 和 DataFrame.columns 属性放置在查询命名空间中,这允许您将框架的索引和列视为框架中的一列。标识符索引(index)用于框架索引,您还可以使用索引的名称在查询中标识它。请注意,Python 关键字不能用作标识符。
支持以下算术运算:+
, -
, *
,/
, **
, %
, //
(仅限 python 引擎)以及以下布尔运算: |
(or), &
(and), 和 ~
(not)。此外,“pandas”解析器允许使用 and、or 和 not,其语义与相应的位运算符不同。详情 pandas.eval()。
更多细节可以参考 Python 的词法分析 (https://docs.python.org/3/reference/lexical_analysis.html) 同时结合 pandas.core.computation.parsing
的源码。
根据以上的功能描述,以下是一些用法的示例:
# pure python
df[(df['a'] < df['b']) & (df['b'] < df['c'])]
# query
df.query('(a < b) & (b < c)')
# 索引取名后可直接用于表达式
df.index.name = 'x'
df.query('x < b and b < c')
# 不命名,可用 index
df.query('index < b < c')
# 列名的命名空间下的方法(需返回布尔序列)可以使用
df.query('col.str.contains("am")') # 包含 am 字符
df.query('col.str.len() > 2') # 长度大于 2
注:如果索引的名称与列名重叠,则列名优先,这时可以使用 index 代表索引,如果不幸列名有个也叫 index,这时可以用 ilevel_0
:
df.query('ilevel_0 == "2022-01-01"')
对于多层索引:
# 索引名的命名空间,color 是其中一层索引的名称
df.query('color == "red"')
# 如果索引没有名字,可用 ilevel_<n> 指示索级别
df.query('ilevel_0 == "red"')
约定为 ilevel_0,表示索引第 0 级的 “索引级别0”。
当您拥有一个 DataFrame 对象集合时,这些对象有一个共同的列名子集(或索引级别/名称)。您可以将相同的查询传递给两个 DataFrame:
expr = '0.0 <= a <= c <= 0.5'
map(lambda frame: frame.query(expr), [df, df2])
pandas 和 Python 表达式的对比:
df.query('(a < b) & (b < c)')
df[(df['a'] < df['b']) & (df['b'] < df['c'])]
# 通过删除括号(比较运算符绑定得比&和|)稍微好一些:
df.query('a < b & b < c')
# 用英语单词代替
df.query('a < b and b < c')
# 继续简化,更加自然
df.query('a < b < c')
in 和not in 运算:
# a 列中有 b 列内容的
df.query('a in b')
# Python 方法,同上
df[df['a'].isin(df['b'])]
df.query('a not in b')
# Python 方法
df[~df['a'].isin(df['b'])]
您可以将其与其他表达式结合使用,以实现非常简洁的查询:
# 列 a 和列 b 具有重叠值的行并且c列的值小于d列的值
df.query('a in b and c < d')
# 纯Python
df[df['b'].isin(df['a']) & (df['c'] < df['d'])]
请注意,in 和 not in 是在 Python 中计算的,因为 numexpr 没有此操作的等效项。但是,只有 in/not-in 表达式本身在普通 Python 中进行计算。例如,在表达式中 df.query('a in b + c + d')
(b+c+d)由 numexpr 计算,然后在普通 Python 中计算 in 操作。通常,任何可以使用 numexpr 进行评估的操作都将被删除。
==
运算符在列表对象中的特殊用法(使用 ==/!= 将值列表与列进行比较工作原理与 in/not in 类似):
df.query('b == ["a", "b", "c"]')
# pure Python
df[df['b'].isin(["a", "b", "c"])]
df.query('c == [1, 2]')
df.query('c != [1, 2]')
# using in/not in
df.query('[1, 2] in c')
df.query('[1, 2] not in c')
# pure Python
df[df['c'].isin([1, 2])]
布尔运算,同时可以使用 not 或~运算符对布尔表达式求反:
df['bools'] = ser > 0.5
df.query('~bools')
df.query('not bools')
df.query('not bools') == df[~df['bools']]
当然,表达式也可以任意复杂:
# 短查询语法
shorter = df.query('a < b < c and (not bools) or bools > 2')
# 纯 Python 中的相同的操作
longer = df[(df['a'] < df['b'])
& (df['b'] < df['c'])
& (~df['bools'])
| (df['bools'] > 2)]
总之,字符串表达式最终的计算结果需要是一个原同长度数据索引的布尔序列,如果是一个聚合值则会报错,如:
# 正确,查询 b 列为偶数的行
df.query('b % 2 == 0')
# 筛选出 b 列大于该列平均值的行
df.query('b > b.mean()')
# 公式计算结果为标量 True,报错:KeyError: True
df.query('b.any()')
关于 query() 的性能。
DataFrame.query() 对于大的 DataFrame,使用 numexpr 比 Python 稍微快一点。如果帧的行数超过大约200000行,则使用 query() 我们可以看到将 numexpr 引擎与 DataFrame 一起使用的性能优势。
此绘图是使用 DataFrame 创建的,DataFrame 有3列,每列包含使用numpy生成的浮点值,使用 numpy.random.randn() 生成。
df.query() 与 df.eval() 都可以用字符串表达式来对原数据做计算,区别主要有:
另外 df.eval() 和 pd.eval() 的命名空间不同, pd.eval() 可以做任何事情,包括对数据的修改、非 pandas 数据的操作。如果要对 pandas 数据进行操作,要指定数据变量(如 df.col)。
关于 df.eval() 和 pd.eval() 可以查看:pd.eval()。
更新时间:2023-09-03 09:41:14 标签:pandas 查询 query