使用 pandas dataframe.query() 选择列
Posted
技术标签:
【中文标题】使用 pandas dataframe.query() 选择列【英文标题】:Select columns using pandas dataframe.query() 【发布时间】:2017-11-20 12:01:54 【问题描述】:dataframe.query()
上的文档非常 简洁 http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.query.html。我也无法通过网络搜索找到投影示例。
所以我尝试简单地提供列名:这给出了语法错误。同样,输入select
,然后输入列名。那么..如何做到这一点?
【问题讨论】:
我觉得这个问题很清楚。 @DaniSpringer 代码不是每个问题都需要。 【参考方案1】:在玩了一段时间并通过the source code 阅读DataFrame.query
之后,我想不出办法。
如果不是不可能的话,显然至少强烈反对。当这个问题出现在 github 上时,多产的 Pandas dev/maintainer jreback suggested using df.eval()
for selecting columns and df.query()
for filtering on rows。
更新:
javadba 指出eval
的返回值不是数据帧。例如,进一步充实 jreback 的示例......
df.eval('A')
返回 Pandas 系列,但是
df.eval(['A', 'B'])
不返回 DataFrame,它返回一个列表(熊猫系列)。
因此,最终保持对行和列进行过滤的灵活性的最佳方法似乎是使用iloc
/loc
,例如
df.loc[0:4, ['A', 'C']]
输出
A C
0 -0.497163 -0.046484
1 1.331614 0.741711
2 1.046903 -2.511548
3 0.314644 -0.526187
4 -0.061883 -0.615978
【讨论】:
但eval
不返回 DataFrame .. ret : ndarray, scalar, or pandas object
。无论如何都赞成这项努力。
嗯,好点。刚试过iris2 = iris.eval(['sepal_length', 'species'])
,但我回来的iris2
是list
...每个元素都是Pandas Series
。很奇怪。
看起来我们回到了iloc/loc
。也许玩一下,我可以在这里奖励。
更新了我的答案。不认为这是一个特别令人满意的答案,但认为这是答案。
我在性能不重要时使用它,并且更喜欢使用 postgres 后端,因为它支持分析/窗口功能。实际上和几年前一样。我经常做的另一种方法是使用 spark sql【参考方案2】:
Dataframe.query
更像是 SQL 语句中的 where 子句,而不是 select 部分。
import pandas as pd
import numpy as np
np.random.seed(123)
dates = pd.date_range('1/1/2000', periods=8)
df = pd.DataFrame(np.random.randn(8, 4), index=dates, columns=['A', 'B', 'C', 'D'])
要选择一列或多列,您可以使用以下命令:
df['A'] or df.loc[:,'A']
或
df[['A','B']] or df.loc[:,['A','B']]
要使用.query
方法,你可以这样做
df.query('A > B')
将返回 A 列中的值大于 b 列中的值的所有行。
A B C D
2000-01-03 1.265936 -0.866740 -0.678886 -0.094709
2000-01-04 1.491390 -0.638902 -0.443982 -0.434351
2000-01-05 2.205930 2.186786 1.004054 0.386186
2000-01-08 -0.140069 -0.861755 -0.255619 -2.798589
在我看来,布尔索引选择更易读
df[df['A'] > df['B']]
【讨论】:
【参考方案3】:pandasql
https://pypi.python.org/pypi/pandasql/0.1.0
这是来自以下博客http://blog.yhat.com/posts/pandasql-sql-for-pandas-dataframes.html 的示例。输入是两个 DataFrame
s meat
和 births
:这种方法给出了 sql 预期的 projections
、filtering
、aggregation
和 sorting
。
@maxpower 确实提到这个包有问题:所以让我们看看.. 至少博客中的代码和下面显示的代码可以正常工作。
pysqldf = lambda q: sqldf(q, globals())
q = """
SELECT
m.date
, m.beef
, b.births
FROM
meat m
LEFT JOIN
births b
ON m.date = b.date
WHERE
m.date > '1974-12-31';
"""
meat = load_meat()
births = load_births()
df = pysqldf(q)
根据需要,输出是熊猫DataFrame
。
它非常适合我的特定用例(评估我们的罪行)
odf = pysqldf("select %s from df where sweapons > 10 order by sweapons desc limit 10" %scols)
p('odf\n', odf)
odf
: SMURDER SRAPE SROBBERY SAGASSLT SOTHASLT SVANDLSM SWEAPONS
0 0 0 0 1 1 10 54
1 0 0 0 0 1 0 52
2 0 0 0 0 1 0 46
3 0 0 0 0 1 0 43
4 0 0 0 0 1 0 33
5 1 0 2 16 28 4 32
6 0 0 0 7 17 4 30
7 0 0 0 0 1 0 29
8 0 0 0 7 16 3 29
9 0 0 0 1 0 5 28
更新我现在用pandasql
做了很多事情:计算字段、限制、别名、级联数据帧.. 它只是如此富有成效。 p>
另一个更新(3 年后) 这有效,但警告它是 非常 慢(秒 vs 毫秒)-
【讨论】:
很高兴这对您的情况非常有效。我有几次对此感到沮丧,但也许这是因为我没有为修复它做出贡献。这是我遇到的最后一个错误 - select from multiple tables 不起作用。这是一种耻辱,因为这种操作在 SQL 中比在基本 pandas 中读起来好得多。我还担心,由于这个问题已经开放了大约 18 个月,并且没有人甚至标签分配给它,所以图书馆可能没有得到很好的维护。 @MaxPower 我现在正在使用postgresql
方言和pandasql
- 而不是默认和有限的sqlite
。到目前为止效果更好。【参考方案4】:
怎么样
df_new = df.query('col1==1 & col2=="x" ')[['col1', 'col3']]
将过滤 col1 等于 1 且 col2 等于“X”的行并仅返回第 1 列和第 3 列。
但是您需要过滤行,否则它不起作用。
对于过滤列,最好使用.loc
或.iloc
【讨论】:
【参考方案5】:只是一个更简单的示例解决方案(使用get
):
我的目标:
我希望查询结果中的 lat 和 lon 列。
我的餐桌详情:
df_city.columns
Index(['name', 'city_id', 'lat', 'lon', 'CountryName', 'ContinentName'], dtype='object')
# All columns
city_continent = df_city.get(df_city['ContinentName']=='Oceania')
# Only lat and lon
city_continent[['lat', 'lon']]
lat lon 113883 -19.12753 -169.84623 113884 -19.11667 -169.90000 113885 -19.10000 -169.91667 113886 -46.33333 168.85000 113887 -46.36667 168.55000 ... ... ... 347956 -23.14083 113.77630 347957 -31.48023 131.84242 347958 -28.29967 153.30142 347959 -35.60358 138.10548 347960 -35.02852 117.83416 3712 rows × 2 columns
【讨论】:
以上是关于使用 pandas dataframe.query() 选择列的主要内容,如果未能解决你的问题,请参考以下文章
是否可以使用 DataFrame.query() 来判断列是否存在?