【问题标题】:Flag repeating entries in pandas time series标记熊猫时间序列中的重复条目
【发布时间】:2020-04-24 04:24:55
【问题描述】:

我有一个采用这种形式的数据框(但有几百万行):

import pandas as pd     
dict = {'id':["A", "A", "A", "B", "B", "B", "C", "C", "C", "D", "D", "D"], 
    'year': ["2000", "2001", "2002", "2000", "2001", "2003", "1999", "2000", "2001", "2000", "2000", "2001"],
    'vacation':["France", "Morocco", "Morocco", "Germany", "Germany", "Germany", "Japan", "Australia", "Japan", "Canada", "Mexico", "China"],
    'new':[1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1]} 
df = pd.DataFrame(dict)

A   2000    France
A   2001    Morocco
A   2002    Morocco
B   2000    Germany
B   2001    Germany
B   2003    Germany
C   1999    Japan
C   2000    Australia
C   2001    Japan
D   2000    Canada       
D   2000    Mexico       
D   2001    China        

对于每一年的每个人,都会给出度假目的地;一年中可以有多个度假目的地。 当参与者去一个他们前一年没有去过的目的地(即目的地是新的)去度假时,我想标记这些行。在上述情况下,输出将是:

id  year    vacation    new
A   2000    France       1
A   2001    Morocco      1
A   2002    Morocco      0
B   2001    Germany      1
B   2002    Germany      0
B   2003    Germany      0
C   1999    Japan        1
C   1999    Australia    1
C   2000    Japan        1
D   2000    Canada       1
D   2000    Mexico       1
D   2001    China        1

对于 A、B、C 和 D,我们数据框中的第一个度假目的地被标记为新的。当 A 连续两年去摩洛哥时,没有标记第二次出现,因为 A 前一年去了那里。当 B 连续 3 次去德国时,不标记第 2 次和第 3 次。当人 C 两次去日本时,所有的事件都被标记,因为他们没有连续两年去日本 。 D 去了 3 个不同的目的地(尽管在 2000 年去了 2 个目的地)并且所有这些目的地都被标记了。

我一直在尝试自己解决这个问题,但一直无法摆脱迭代,对于如此庞大的数据集而言,迭代计算量太大。

我将不胜感激;谢谢。

【问题讨论】:

    标签: python-3.x pandas time-series


    【解决方案1】:

    IIUC,

    我们正在做的是按idvacation 进行分组,并确保该年份不等于上面的年份,或者我们可以选择该组合的第一个实例。

    希望这很清楚。如果您需要更多帮助,请告诉我。

    df["new_2"] = (
        df.groupby(["id", "vacation"])["id", "year"]
        .apply(lambda x: x.ne(x.shift()))
        .all(axis=1)
        .add(0)
    )
    

    print(df)
      id  year   vacation  new_2
    0  A  2000     France    1
    1  A  2001        USA    1
    2  A  2002     France    0
    3  B  2001    Germany    1
    4  B  2002    Germany    0
    5  B  2003    Germany    0
    6  C  1999      Japan    1
    7  C  2000  Australia    1
    8  C  2001     France    1
    

    【讨论】:

    • 这更好,+1!
    • @anky_91 大错特错 =( !
    • 谢谢。我了解 groupby 做什么以及 neshift 单独做什么。不过,我很难理解正在比较的行。
    • @Logos24 什么不清楚?你可以删除每一层并单步执行代码,首先删除.ne.shift()
    • 我现在明白了;值得补充的是,数据框必须按“年份”列升序排列才能正常工作。
    【解决方案2】:

    这是我想出的一个解决方案,使用 groupby 和 transform:

    df = df.sort_values(["id", "vacation", "year"])
    df["new"] = (
        df.groupby(["id", "vacation"])
        .transform(lambda x: x.iloc[0])
        .year.eq(df.year)
        .astype(int)
    )
    

    你会得到

      id  year   vacation  new
    0  A  2000     France    1
    1  A  2001        USA    1
    2  A  2002     France    0
    3  B  2001    Germany    1
    4  B  2002    Germany    0
    5  B  2003    Germany    0
    6  C  1999      Japan    1
    7  C  2000  Australia    1
    8  C  2001     France    1
    

    【讨论】:

    • 你不能改用transform('first') 吗?
    【解决方案3】:

    这是一种使用groupby+cumcountseries.mask的方法:

    df['new']=df.groupby(['id','vacation']).cumcount().add(1).mask(lambda x: x.gt(1),0)
    print(df)
    

      id  year   vacation  new
    0  A  2000     France    1
    1  A  2001        USA    1
    2  A  2002     France    0
    3  B  2001    Germany    1
    4  B  2002    Germany    0
    5  B  2003    Germany    0
    6  C  1999      Japan    1
    7  C  2000  Australia    1
    8  C  2001     France    1
    

    【讨论】:

    • 不知道你可以将.add() 与布尔值一起使用,你刚刚教了我一些新东西!
    • @Datanovice cumcount 将返回一系列计数 :) 但是是的,您可以将它们链接起来
    • 我总是忘记 cumcount 如何与 series 一起工作,无论如何我在使用 .any() 后无法与 groupby 一起工作
    • @Datanovice 是的,因为它只适用于 groupby 对象。 any 将返回一个系列
    猜你喜欢
    • 2021-07-21
    • 1970-01-01
    • 2017-02-20
    • 2019-04-01
    • 2016-10-18
    • 1970-01-01
    • 2021-09-08
    • 2012-04-03
    • 2017-06-07
    相关资源
    最近更新 更多