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

在SQL中,我会使用:

SELECT *
FROM table
WHERE column_name = some_value

当前回答

您可以在函数中使用loc(方括号):

# Series
s = pd.Series([1, 2, 3, 4]) 
s.loc[lambda x: x > 1]
# s[lambda x: x > 1]

输出:

1    2
2    3
3    4
dtype: int64

or

# DataFrame
df = pd.DataFrame({'A': [1, 2, 3], 'B': [10, 20, 30]})
df.loc[lambda x: x['A'] > 1]
# df[lambda x: x['A'] > 1]

输出:

   A   B
1  2  20
2  3  30

其他回答

使用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

要选择列值等于标量some_value的行,请使用==:

df.loc[df['column_name'] == some_value]

要选择列值在可迭代的some_values中的行,请使用isin:

df.loc[df['column_name'].isin(some_values)]

将多个条件与&组合:

df.loc[(df['column_name'] >= A) & (df['column_name'] <= B)]

注意括号。由于Python的运算符优先级规则,&binding比<=和>=更紧密。因此,最后一个示例中的括号是必要的。没有括号

df['column_name'] >= A & df['column_name'] <= B

解析为

df['column_name'] >= (A & df['column_name']) <= B

这导致序列的真值是模糊错误。


要选择列值不等于some_value的行,请使用!=:

df.loc[df['column_name'] != some_value]

isin返回布尔级数,因此要选择值不在some_values中的行,请使用~:

df.loc[~df['column_name'].isin(some_values)]

例如

import pandas as pd
import numpy as np
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split(),
                   'C': np.arange(8), 'D': np.arange(8) * 2})
print(df)
#      A      B  C   D
# 0  foo    one  0   0
# 1  bar    one  1   2
# 2  foo    two  2   4
# 3  bar  three  3   6
# 4  foo    two  4   8
# 5  bar    two  5  10
# 6  foo    one  6  12
# 7  foo  three  7  14

print(df.loc[df['A'] == 'foo'])

产量

     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

如果要包含多个值,请将它们放入列出(或更一般地,任何可迭代的)并使用isin:

print(df.loc[df['B'].isin(['one','three'])])

产量

     A      B  C   D
0  foo    one  0   0
1  bar    one  1   2
3  bar  three  3   6
6  foo    one  6  12
7  foo  three  7  14

但是,请注意,如果您希望多次这样做首先创建索引,然后使用df.loc:

df = df.set_index(['B'])
print(df.loc['one'])

产量

       A  C   D
B              
one  foo  0   0
one  bar  1   2
one  foo  6  12

或者,要包含索引中的多个值,请使用df.index.isin:

df.loc[df.index.isin(['one','two'])]

产量

       A  C   D
B              
one  foo  0   0
one  bar  1   2
two  foo  2   4
two  foo  4   8
two  bar  5  10
one  foo  6  12

我发现前面答案的语法是多余的,很难记住。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')

很好的答案。只有当数据帧的大小接近百万行时,许多方法在使用df[df['col']==val]时往往需要很长时间。我希望“another_column”的所有可能值都对应于“some_column“中的特定值(在本例中是在字典中)。这起作用很快。

s=datetime.datetime.now()

my_dict={}

for i, my_key in enumerate(df['some_column'].values): 
    if i%100==0:
        print(i)  # to see the progress
    if my_key not in my_dict.keys():
        my_dict[my_key]={}
        my_dict[my_key]['values']=[df.iloc[i]['another_column']]
    else:
        my_dict[my_key]['values'].append(df.iloc[i]['another_column'])
        
e=datetime.datetime.now()

print('operation took '+str(e-s)+' seconds')```

您也可以使用.apply:

df.apply(lambda row: row[df['B'].isin(['one','three'])])

它实际上按行工作(即,将函数应用于每一行)。

输出为

   A      B  C   D
0  foo    one  0   0
1  bar    one  1   2
3  bar  three  3   6
6  foo    one  6  12
7  foo  three  7  14

结果与@unsubu提到的使用相同

df[[df['B'].isin(['one','three'])]]