Python 如何基于列值从数据帧中选择行?

Python 如何基于列值从数据帧中选择行?,python,pandas,dataframe,Python,Pandas,Dataframe,如何根据Pandas中某列中的值从数据框中选择行 在SQL中,我将使用: 选择* 从桌子上 其中colume\u name=某个值 我试图查看Pandas的文档,但没有立即找到答案。要选择列值等于标量的行,请使用=: df.loc[df['column_name'] == some_value] 要选择列值在iterable中的行,某些值,请使用isin: df.loc[df['column_name'].isin(some_values)] print(df.loc[df['B'].is

如何根据Pandas中某列中的值从数据框中选择行

在SQL中,我将使用:

选择*
从桌子上
其中colume\u name=某个值

我试图查看Pandas的文档,但没有立即找到答案。

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

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

要选择列值在iterable中的行,
某些值
,请使用
isin

df.loc[df['column_name'].isin(some_values)]
print(df.loc[df['B'].isin(['one','three'])])
df.loc[df.index.isin(['one','two'])]
将多个条件与
组合:

df.loc[(df['column_name'] >= A) & (df['column_name'] <= B)]
被解析为

df['column_name'] >= (A & df['column_name']) <= B
isin
返回一个布尔序列,因此要选择其值不在
某些值中的行,请使用
~
对布尔序列求反:

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
     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
       A  C   D
B              
one  foo  0   0
one  bar  1   2
one  foo  6  12
       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

如果要包含多个值,请将它们放在 列出(或更一般地说,任何iterable)并使用
isin

df.loc[df['column_name'].isin(some_values)]
print(df.loc[df['B'].isin(['one','three'])])
df.loc[df.index.isin(['one','two'])]
屈服

     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
     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
       A  C   D
B              
one  foo  0   0
one  bar  1   2
one  foo  6  12
       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

但是,请注意,如果您希望多次执行此操作,则 首先制作索引,然后使用
df.loc

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

     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
     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
       A  C   D
B              
one  foo  0   0
one  bar  1   2
one  foo  6  12
       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
或者,要包含索引中的多个值,请使用
df.index.isin

df.loc[df['column_name'].isin(some_values)]
print(df.loc[df['B'].isin(['one','three'])])
df.loc[df.index.isin(['one','two'])]
屈服

     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
     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
       A  C   D
B              
one  foo  0   0
one  bar  1   2
one  foo  6  12
       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

下面是一个简单的例子

from pandas import DataFrame

# Create data set
d = {'Revenue':[100,111,222], 
     'Cost':[333,444,555]}
df = DataFrame(d)


# mask = Return True when the value in column "Revenue" is equal to 111
mask = df['Revenue'] == 111

print mask

# Result:
# 0    False
# 1     True
# 2    False
# Name: Revenue, dtype: bool


# Select * FROM df WHERE Revenue = 111
df[mask]

# Result:
#    Cost    Revenue
# 1  444     111
tl;博士 熊猫相当于

select * from table where column_name = some_value

多个条件:

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

代码示例 在上面的代码中,
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')

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

复制自


要附加到这个著名的问题(虽然有点晚了):您还可以执行
df.groupby('column\u name')、get\u group('column\u desired\u value')、reset\u index()
来创建一个具有特定值的指定列的新数据帧。例如

import pandas as pd
df = pd.DataFrame({'A': 'foo bar foo bar foo bar foo foo'.split(),
                   'B': 'one one two three two two one three'.split()})
print("Original dataframe:")
print(df)

b_is_two_dataframe = pd.DataFrame(df.groupby('B').get_group('two').reset_index()).drop('index', axis = 1) 
#NOTE: the final drop is to remove the extra index column returned by groupby object
print('Sub dataframe where B is two:')
print(b_is_two_dataframe)
运行此命令可提供:

Original dataframe:
     A      B
0  foo    one
1  bar    one
2  foo    two
3  bar  three
4  foo    two
5  bar    two
6  foo    one
7  foo  three
Sub dataframe where B is two:
     A    B
0  foo  two
1  foo  two
2  bar  two

使用以下方法可以获得更快的结果

例如,与-

时间比较:

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

有几种方法可以从数据帧中选择行:

  • 布尔索引(
    df[df['col']==value
    ])
  • 位置索引(
    df.iloc[…])
  • 标签索引(
    df.xs(…)
  • df.query(…)
    API
  • 下面我将向您展示每种方法的示例,以及何时使用某些技术的建议。假设我们的标准是列
    'A'
    ==
    'foo'

    (关于性能的注意:对于每种基本类型,我们可以通过使用Pandas API保持简单,或者我们可以在API之外冒险,通常是进入NumPy,并加快速度。)


    设置

    我们首先需要确定一个条件,它将作为我们选择行的标准。我们将从OP的case
    column\u name==some\u value
    开始,并包括一些其他常见用例

    从@unutbu借款:

    import pandas as pd, 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})
    

    1。布尔索引 。。。布尔索引需要找到每行
    'A'
    列的真值等于
    'foo'
    ,然后使用这些真值来标识要保留的行。通常,我们将这个系列命名为真值数组,
    mask
    。我们在这里也会这样做

    mask = df['A'] == 'foo'
    
    然后,我们可以使用此掩码对数据帧进行切片或索引

    df[mask]
    
         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
    
    这是完成这项任务最简单的方法之一,如果性能或直觉不是问题,这应该是您选择的方法。但是,如果性能是一个问题,那么您可能需要考虑创建<代码>掩码< /代码>的另一种方式。


    2。位置索引 位置索引(
    df.iloc[…]
    )有它的用例,但这不是其中之一。为了确定切片的位置,我们首先需要执行与上面相同的布尔分析。这就让我们多做一步来完成同样的任务

    mask = df['A'] == 'foo'
    pos = np.flatnonzero(mask)
    df.iloc[pos]
    
         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
    
    3。标签索引 标签索引可能非常方便,但在这种情况下,我们再次做了更多的工作,但没有任何好处

    df.set_index('A', append=True, drop=False).xs('foo', level=1)
    
         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
    
    4
    df.query()
    API
    pd.DataFrame.query
    是执行此任务的一种非常优雅/直观的方法,但通常速度较慢但是,如果您注意下面的计时,对于大数据,查询是非常有效的。这比标准方法更重要,与我的最佳建议类似

    df.query('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
    

    我的首选是使用
    布尔值
    掩码

    %timeit mask = df['A'].values == 'foo'
    %timeit mask = df['A'] == 'foo'
    
    5.84 µs ± 195 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    166 µs ± 4.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    通过修改如何创建
    布尔值
    掩码
    ,可以实现实际的改进

    mask
    备选方案1
    使用底层NumPy数组,放弃创建另一个
    pd.Series

    最后,我将展示更多完整的时间测试,但请看一下使用示例数据帧获得的性能提升。首先,我们看一下创建
    掩码

    %timeit mask = df['A'].values == 'foo'
    %timeit mask = df['A'] == 'foo'
    
    5.84 µs ± 195 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
    166 µs ± 4.45 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    
    使用NumPy阵列评估
    掩码
    ,速度快约30倍。这部分是由于NumPy评估通常更快。部分原因还在于缺少构建索引和相应的
    pd.Series
    对象所需的开销

    接下来,我们将查看使用一个
    掩码与另一个
    进行切片的时间

    mask = df['A'].values == 'foo'
    %timeit df[mask]
    mask = df['A'] == 'foo'
    %timeit df[mask]
    
    219 µs ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    239 µs ± 7.03 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    性能的提升并不明显。我们将看看这是否能支持更健壮的测试


    mask
    备选方案2
    我们也可以重建数据帧。重建datafram时有一个很大的警告
    res = pd.DataFrame(
        index=[
            'mask_standard', 'mask_standard_loc', 'mask_with_values', 'mask_with_values_loc',
            'query', 'xs_label', 'mask_with_isin', 'mask_with_in1d'
        ],
        columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
        dtype=float
    )
    
    for j in res.columns:
        d = pd.concat([df] * j, ignore_index=True)
        for i in res.index:a
            stmt = '{}(d)'.format(i)
            setp = 'from __main__ import d, {}'.format(i)
            res.at[i, j] = timeit(stmt, setp, number=50)
    
    spec.div(spec.min())
    
                         10        30        100       300       1000      3000      10000     30000
    mask_with_values  1.009030  1.000000  1.194276  1.000000  1.236892  1.095343  1.000000  1.000000
    mask_with_in1d    1.104638  1.094524  1.156930  1.072094  1.000000  1.000000  1.040043  1.027100
    reconstruct       1.000000  1.142838  1.000000  1.355440  1.650270  2.222181  2.294913  3.406735
    
    spec.T.plot(loglog=True)
    
    np.random.seed([3,1415])
    d1 = pd.DataFrame(np.random.randint(10, size=(10, 5)), columns=list('ABCDE'))
    
    def mask_with_values(df):
        mask = df['A'].values == 'foo'
        return df[mask]
    
    def mask_with_in1d(df):
        mask = np.in1d(df['A'].values, ['foo'])
        return df[mask]
    
    def reconstruct(df):
        v = df.values
        mask = np.in1d(df['A'].values, ['foo'])
        return pd.DataFrame(v[mask], df.index[mask], df.columns)
    
    spec = pd.DataFrame(
        index=['mask_with_values', 'mask_with_in1d', 'reconstruct'],
        columns=[10, 30, 100, 300, 1000, 3000, 10000, 30000],
        dtype=float
    )
    
    for j in spec.columns:
        d = pd.concat([df] * j, ignore_index=True)
        for i in spec.index:
            stmt = '{}(d)'.format(i)
            setp = 'from __main__ import d, {}'.format(i)
            spec.at[i, j] = timeit(stmt, setp, number=50)
    
    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]]
    
    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
    
    df[[df['B'].isin(['one','three'])]]
    
    # 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
    
    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
    
    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