【问题标题】:Python pandas column filtering substringPython pandas 列过滤子字符串
【发布时间】:2020-08-28 03:44:50
【问题描述】:

我在 python3 中有一个使用 pandas 的数据框,其中有一列包含一个带日期的字符串。

这是列的子集

ColA
"2021-04-03"
"2021-04-08"
"2020-04-12"
"2020-04-08"
"2020-04-12"

我想删除两次具有相同月份和日期的行,并保留最新年份的行。

这将是我期望从这个子集得到的结果

ColA
"2021-04-03"
"2021-04-08"
"2020-04-12"

最后两行被删除,因为 2020-04-12 和 2020-04-08 的日期已经是 2021 年。

我曾想过使用 apply 和 lambda 来执行此操作,但我的真实数据框有数百行和数十列,因此效率不高。有没有更有效的方法来做到这一点?

【问题讨论】:

    标签: python python-3.x pandas dataframe


    【解决方案1】:

    有几种方法可以做到这一点。其中之一是提取年份,按年份排序,然后删除具有重复月日对的行。

    # separate year and month-day pairs
    df['year'] = df['ColA'].apply(lambda x: x[:4])
    df['mo-day'] = df['ColA'].apply(lambda x: x[5:])
    df.sort_values('year', inplace=True)
    print(df)
    

    这是分离和排序后的样子:

             ColA  year mo-day
    2  2020-04-12  2020  04-12
    3  2020-04-08  2020  04-08
    4  2020-04-12  2020  04-12
    0  2021-04-03  2021  04-03
    1  2021-04-08  2021  04-08
    

    之后,我们可以简单地删除重复的列并删除额外的列:

    # drop duplicate month-day pairs
    df.drop_duplicates('mo-day', keep='first', inplace=True)
    
    # get rid of the two columns
    df.drop(['year','mo-day'], axis=1, inplace=True)
    
    # since we dropped duplicate, reset the index
    df.reset_index(drop=True, inplace=True)
    print(df)
    

    最终结果:

             ColA
    0  2020-04-12
    1  2020-04-08
    2  2021-04-03
    

    这比将整个列转换为日期时间并提取日期要快得多,因为您按原样处理字符串。

    【讨论】:

    • 您的预期结果似乎也不正确;您想保留最旧的年份,因此您应该保留 2020-04-08 而不是 2021-04-08 等。
    • 是的,你是对的,我更新了问题,对此感到抱歉......
    【解决方案2】:

    我不确定您是否可以避免使用“应用”来提取日期的相关部分以进行分组,但如果您首先将该列转换为 pandas 日期时间类型,这会容易得多:

    df = pd.DataFrame({'colA':
    ["2021-04-03",
    "2021-04-08",
    "2020-04-12",
    "2020-04-08",
    "2020-04-12"]})
    
    df['colA'] = df.colA.apply(pd.to_datetime)
    

    然后您可以按(日,月)分组并保持最高值,如下所示:

    df.groupby(df.colA.apply(lambda x: (x.day, x.month))).max()
    

    【讨论】:

    • 是的,这就是我一直在寻找的,但不幸的是,当我将您的答案应用于我的数据框时,只有 2020 年的日期会出现,我希望优先考虑 2021 年的日期,然后如果它不存在取必须存在的 2020 年日期
    • 您的答案是正确的,只是应该是 max() 而不是 first()。也许您可以编辑您的帖子,以便我可以接受您的回答
    猜你喜欢
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    • 2020-06-07
    • 1970-01-01
    相关资源
    最近更新 更多