如何根据Pandas中某列的值从DataFrame中选择行?

在SQL中,我会使用:

SELECT *
FROM table
WHERE column_name = some_value

当前回答

如果您想重复查询数据帧,并且速度对您很重要,最好的方法是将数据帧转换为字典,然后通过这样做,您可以将查询速度提高数千倍。

my_df = df.set_index(column_name)
my_dict = my_df.to_dict('index')

制作my_dict字典后,您可以浏览:

if some_value in my_dict.keys():
   my_result = my_dict[some_value]

如果column_name中有重复值,则无法创建字典。但您可以使用:

my_result = my_df.loc[some_value]

其他回答

我发现前面答案的语法是多余的,很难记住。Pandas在v0.13中引入了query()方法,我更喜欢它。对于您的问题,您可以使用df.query('col==val')。

转载自query()方法(实验):

In [167]: n = 10

In [168]: df = pd.DataFrame(np.random.rand(n, 3), columns=list('abc'))

In [169]: df
Out[169]:
          a         b         c
0  0.687704  0.582314  0.281645
1  0.250846  0.610021  0.420121
2  0.624328  0.401816  0.932146
3  0.011763  0.022921  0.244186
4  0.590198  0.325680  0.890392
5  0.598892  0.296424  0.007312
6  0.634625  0.803069  0.123872
7  0.924168  0.325076  0.303746
8  0.116822  0.364564  0.454607
9  0.986142  0.751953  0.561512

# pure python
In [170]: df[(df.a < df.b) & (df.b < df.c)]
Out[170]:
          a         b         c
3  0.011763  0.022921  0.244186
8  0.116822  0.364564  0.454607

# query
In [171]: df.query('(a < b) & (b < c)')
Out[171]:
          a         b         c
3  0.011763  0.022921  0.244186
8  0.116822  0.364564  0.454607

您还可以通过在环境中添加@来访问变量。

exclude = ('red', 'orange')
df.query('color not in @exclude')

在Pandas的更新版本中,受文档启发(查看数据):

df[df["colume_name"] == some_value] #Scalar, True/False..

df[df["colume_name"] == "some_value"] #String

通过将子句放在括号()中,并用&和|(和/或)组合来组合多个条件。这样地:

df[(df["colume_name"] == "some_value1") & (pd[pd["colume_name"] == "some_value2"])]

其他过滤器

pandas.notna(df["colume_name"]) == True # Not NaN
df['colume_name'].str.contains("text") # Search for "text"
df['colume_name'].str.lower().str.contains("text") # Search for "text", after converting  to lowercase

使用带有panda>=0.25.00的.query更灵活:

由于panda>=0.25.00,我们可以使用查询方法来使用panda方法过滤数据帧,甚至可以使用带有空格的列名。通常,列名中的空格会给出一个错误,但现在我们可以使用backtick(`)来解决这个问题-请参见GitHub:

# Example dataframe
df = pd.DataFrame({'Sender email':['ex@example.com', "reply@shop.com", "buy@shop.com"]})

     Sender email
0  ex@example.com
1  reply@shop.com
2    buy@shop.com

将.query与方法str.endswith一起使用:

df.query('`Sender email`.str.endswith("@shop.com")')

输出

     Sender email
1  reply@shop.com
2    buy@shop.com

此外,我们还可以通过在查询中用@前缀来使用局部变量:

domain = 'shop.com'
df.query('`Sender email`.str.endswith(@domain)')

输出

     Sender email
1  reply@shop.com
2    buy@shop.com

tl;博士

熊猫相当于

select * from table where column_name = some_value

is

table[table.column_name == some_value]

多种条件:

table[(table.column_name == some_value) | (table.column_name2 == some_value2)]

or

table.query('column_name == some_value | column_name2 == some_value2')

代码示例

import pandas as pd

# Create data set
d = {'foo':[100, 111, 222],
     'bar':[333, 444, 555]}
df = pd.DataFrame(d)

# Full dataframe:
df

# Shows:
#    bar   foo
# 0  333   100
# 1  444   111
# 2  555   222

# Output only the row(s) in df where foo is 222:
df[df.foo == 222]

# Shows:
#    bar  foo
# 2  555  222

在上面的代码中,是df[df.foo==222]行根据列值给出行,在本例中为222。

也可能出现多种情况:

df[(df.foo == 222) | (df.bar == 444)]
#    bar  foo
# 1  444  111
# 2  555  222

但在这一点上,我建议使用查询函数,因为它不那么冗长,并产生相同的结果:

df.query('foo == 222 | bar == 444')

使用numpy.where可以获得更快的结果。

例如,使用unubtu的设置-

In [76]: df.iloc[np.where(df.A.values=='foo')]
Out[76]: 
     A      B  C   D
0  foo    one  0   0
2  foo    two  2   4
4  foo    two  4   8
6  foo    one  6  12
7  foo  three  7  14

时间比较:

In [68]: %timeit df.iloc[np.where(df.A.values=='foo')]  # fastest
1000 loops, best of 3: 380 µs per loop

In [69]: %timeit df.loc[df['A'] == 'foo']
1000 loops, best of 3: 745 µs per loop

In [71]: %timeit df.loc[df['A'].isin(['foo'])]
1000 loops, best of 3: 562 µs per loop

In [72]: %timeit df[df.A=='foo']
1000 loops, best of 3: 796 µs per loop

In [74]: %timeit df.query('(A=="foo")')  # slowest
1000 loops, best of 3: 1.71 ms per loop