标记熊猫时间序列中的重复条目
Posted
技术标签:
【中文标题】标记熊猫时间序列中的重复条目【英文标题】: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 个目的地)并且所有这些目的地都被标记了。
我一直在尝试自己解决这个问题,但一直无法摆脱迭代,对于如此庞大的数据集而言,迭代计算量太大。
我将不胜感激;谢谢。
【问题讨论】:
【参考方案1】:IIUC,
我们正在做的是按id
和vacation
进行分组,并确保该年份不等于上面的年份,或者我们可以选择该组合的第一个实例。
希望这很清楚。如果您需要更多帮助,请告诉我。
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
做什么以及 ne
和 shift
单独做什么。不过,我很难理解正在比较的行。
@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+cumcount
和series.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
将返回一个系列以上是关于标记熊猫时间序列中的重复条目的主要内容,如果未能解决你的问题,请参考以下文章