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

在SQL中,我会使用:

SELECT *
FROM table
WHERE column_name = some_value

当前回答

使用DuckDB选择行的DataFrames上的SQL语句

使用DuckDB,我们可以用SQL语句以高性能的方式查询panda DataFrames。

由于问题是如何根据列值从DataFrame中选择行?,问题中的示例是一个SQL查询,这个答案在本主题中看起来很合理。

例子:

In [1]: import duckdb

In [2]: import pandas as pd

In [3]: con = duckdb.connect()

In [4]: df = pd.DataFrame({"A": range(11), "B": range(11, 22)})

In [5]: df
Out[5]:
     A   B
0    0  11
1    1  12
2    2  13
3    3  14
4    4  15
5    5  16
6    6  17
7    7  18
8    8  19
9    9  20
10  10  21

In [6]: results = con.execute("SELECT * FROM df where A > 2").df()

In [7]: results
Out[7]:
    A   B
0   3  14
1   4  15
2   5  16
3   6  17
4   7  18
5   8  19
6   9  20
7  10  21

其他回答

使用DuckDB选择行的DataFrames上的SQL语句

使用DuckDB,我们可以用SQL语句以高性能的方式查询panda DataFrames。

由于问题是如何根据列值从DataFrame中选择行?,问题中的示例是一个SQL查询,这个答案在本主题中看起来很合理。

例子:

In [1]: import duckdb

In [2]: import pandas as pd

In [3]: con = duckdb.connect()

In [4]: df = pd.DataFrame({"A": range(11), "B": range(11, 22)})

In [5]: df
Out[5]:
     A   B
0    0  11
1    1  12
2    2  13
3    3  14
4    4  15
5    5  16
6    6  17
7    7  18
8    8  19
9    9  20
10  10  21

In [6]: results = con.execute("SELECT * FROM df where A > 2").df()

In [7]: results
Out[7]:
    A   B
0   3  14
1   4  15
2   5  16
3   6  17
4   7  18
5   8  19
6   9  20
7  10  21

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

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

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

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中给定值的多个列中仅选择特定列:

select col_name1, col_name2 from table where column_name = some_value.

选项位置:

df.loc[df['column_name'] == some_value, [col_name1, col_name2]]

或查询:

df.query('column_name == some_value')[[col_name1, col_name2]]