【问题标题】:Select rows where column values are between a given range选择列值在给定范围之间的行
【发布时间】:2018-06-30 04:44:29
【问题描述】:

如何从 DataFrame 中查找和删除值在特定范围内的行,例如日期大于“2017-03-02”且小于“2017-03-05”

import pandas as pd                                     

d_index = pd.date_range('2018-01-01', '2018-01-06')     
d_values = pd.date_range('2017-03-01', '2017-03-06')    

s = pd.Series(d_values)                                 
s = s.rename('values')                                  

df = pd.DataFrame(s)                                    
df = df.set_index(d_index)                              

# remove rows with specific values in 'value' column                              

在上面的示例中,我将 d_values 排序为从最早到最晚的日期,因此在这种情况下,按索引切片数据帧可以完成这项工作。但是我正在寻找当 d_values 包含未排序的随机日期值时也可以使用的解决方案。有没有办法在熊猫中做到这一点?

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    选项 1
    pd.Series.between 似乎适合这项任务。

    df[~df['values'].between('2017-03-02', '2017-03-05', inclusive=False)]
    
                   values
    2018-01-01 2017-03-01
    2018-01-02 2017-03-02
    2018-01-05 2017-03-05
    2018-01-06 2017-03-06
    

    详细信息
    between 识别范围内的所有项目-

    m = df['values'].between('2017-03-02', '2017-03-05', inclusive=False)
    m
    
    2018-01-01    False
    2018-01-02    False
    2018-01-03     True
    2018-01-04     True
    2018-01-05    False
    2018-01-06    False
    Freq: D, Name: values, dtype: bool
    

    使用掩码过滤df -

    df = df[~m]
    

    选项 2
    或者,使用良好的旧逻辑 OR -

    df[~(df['values'].gt('2017-03-02') & df['values'].lt('2017-03-05'))]
    
                   values
    2018-01-01 2017-03-01
    2018-01-02 2017-03-02
    2018-01-05 2017-03-05
    2018-01-06 2017-03-06
    

    请注意,这两个选项都适用于 datetime 对象以及字符串日期列(在这种情况下,比较是按字典顺序进行的)。

    【讨论】:

    • 不错的解决方案!我已经发布了另一种方法... ;-)
    【解决方案2】:

    首先让我们洗牌你的 DF:

    In [65]: df = df.sample(frac=1)
    
    In [66]: df
    Out[66]:
                   values
    2018-01-03 2017-03-03
    2018-01-04 2017-03-04
    2018-01-01 2017-03-01
    2018-01-06 2017-03-06
    2018-01-05 2017-03-05
    2018-01-02 2017-03-02
    

    你可以使用DataFrame.eval方法(thanks @ cᴏʟᴅsᴘᴇᴇᴅ for the correction!):

    In [70]: df[~df.eval("'2017-03-02' < values < '2017-03-05'")]
    Out[70]:
                   values
    2018-01-01 2017-03-01
    2018-01-06 2017-03-06
    2018-01-05 2017-03-05
    2018-01-02 2017-03-02
    

    DataFrame.query():

    In [300]: df.query("not ('2017-03-02' < values < '2017-03-05')")
    Out[300]:
                   values
    2018-01-01 2017-03-01
    2018-01-06 2017-03-06
    2018-01-05 2017-03-05
    2018-01-02 2017-03-02
    

    【讨论】:

    • query 似乎是你最喜欢的 ;)
    • @cᴏʟᴅsᴘᴇᴇᴅ,绝对!我来自 SQL 词... ;-)
    • 实际上,您的情况与 OP 需要的相反...他们想删除您选择的行...可以反转吗?示例:df[~df.eval(...)]
    猜你喜欢
    • 1970-01-01
    • 2018-08-14
    • 2016-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-23
    相关资源
    最近更新 更多