Python 根据groupby条件删除行
我有以下带有(“ID”、“月份”和“状态”)的数据框。状态为“搅动”=1和“不搅动”=2 对于在观察期内状态为2但状态为1(客户处于非活动状态,然后重新激活自身)的客户,我必须删除状态为1(客户流失)的所有行 转换后的数据帧应该如下所示Python 根据groupby条件删除行,python,pandas,dataframe,Python,Pandas,Dataframe,我有以下带有(“ID”、“月份”和“状态”)的数据框。状态为“搅动”=1和“不搅动”=2 对于在观察期内状态为2但状态为1(客户处于非活动状态,然后重新激活自身)的客户,我必须删除状态为1(客户流失)的所有行 转换后的数据帧应该如下所示 ID Month Status 3863 201807 2 3863 201808 2 3863 201809 2 3863 201810 2 3863 2018
ID Month Status
3863 201807 2
3863 201808 2
3863 201809 2
3863 201810 2
3863 201811 2
3863 201812 2
3863 201901 2
3863 201902 2
3863 201903 2
3863 201904 2
3863 201905 2
3863 201906 2
3863 201907 2
3863 201908 1
用于情况1,与一起用于情况2:
case1 = df['Status'].eq(1).groupby(df['ID']).transform('all')
case2 = (df['Status'].where(df['Status'].ne(1))
.groupby(df['ID'])
.bfill()
.eq(2)
.mul(df['Status'].eq(1)))
df_filtered = df.loc[~(case1|case2)]
print(df_filtered)
ID Month Status
7 2311 201710 2
8 2311 201711 2
9 2311 201712 2
10 2312 201708 2
11 2312 201709 2
12 2312 201710 2
13 2312 201711 2
14 2312 201712 1
用于情况1,与一起用于情况2:
case1 = df['Status'].eq(1).groupby(df['ID']).transform('all')
case2 = (df['Status'].where(df['Status'].ne(1))
.groupby(df['ID'])
.bfill()
.eq(2)
.mul(df['Status'].eq(1)))
df_filtered = df.loc[~(case1|case2)]
print(df_filtered)
ID Month Status
7 2311 201710 2
8 2311 201711 2
9 2311 201712 2
10 2312 201708 2
11 2312 201709 2
12 2312 201710 2
13 2312 201711 2
14 2312 201712 1
定义以下功能:
def fn(grp):
if ~grp.Status.eq(2).any():
# No rows with Status == 2 -> return nothing
return None
srt = grp.sort_values('Month') # Sort rows
# Status == 1 after Status == 2
stat2after1 = srt.Status.shift().eq(1) & srt.Status.eq(2)
if stat2after1.any(): # Something found
cs = srt.Status.eq(2).cumsum()
# Return rows from the first with Status == 2 on
return srt[cs.gt(0)]
return srt # Return all rows (sorted)
然后,将结果应用于每组:
df.groupby('ID').apply(fn).reset_index(level=0, drop=True)
定义以下功能:
def fn(grp):
if ~grp.Status.eq(2).any():
# No rows with Status == 2 -> return nothing
return None
srt = grp.sort_values('Month') # Sort rows
# Status == 1 after Status == 2
stat2after1 = srt.Status.shift().eq(1) & srt.Status.eq(2)
if stat2after1.any(): # Something found
cs = srt.Status.eq(2).cumsum()
# Return rows from the first with Status == 2 on
return srt[cs.gt(0)]
return srt # Return all rows (sorted)
然后,将结果应用于每组:
df.groupby('ID').apply(fn).reset_index(level=0, drop=True)
正在分组的是什么?这看起来像是一个相当直接的
loc
example:)按ID和状态分组?如果您有什么想法,请发送给我,我可以尝试使用您的当前信息,这两种情况都只是状态df[df.status!=1]上的一个过滤器
我现在明白了,我没有正确解释。我添加了客户状态为2,然后更改为状态为1的情况。该行必须保留,因为这是有关客户的信息。我看到这样的问题:如果没有状态为2的行,则删除该客户状态为1的所有行如果re是状态为2的行,但状态为2的一个月大于状态为1的一个月。正在分组的是什么?这看起来是一个相当直接的loc
example:)按ID和状态分组?如果您有什么想法,请发送给我,我可以尝试使用您的当前信息,这两种情况都只是状态的一个过滤器df[df.status!=1]
我现在明白了,我没有正确解释。我添加了客户状态为2,然后更改为状态为1的情况。该行必须保留,因为这是有关客户的信息。我看到这样的问题:如果没有状态为2的行,则删除该客户状态为1的所有行如果re是状态为2的一行,但状态为2的一个月大于状态为1的一个月可能我在这里没有使用正确的示例,但在实际数据集中,此转换不起作用。我将尝试更好地解释刚刚开始的情况2。您应该在stackoverflow中问另一个新问题,因为我们已经花时间解决了前一个问题现在你改变了它你是对的,但解决问题也很重要。我本来想更好地解释这个问题的。你解释了一个与它无关的问题。如果你现在改变这个问题,人们会看到这个问题,认为这个答案是错的,当它不是错的时候,他们会投反对票。这对一开始是正确的所有问题。你可以问另一个新问题并正确地提出问题。可能我在这里没有使用正确的示例,但在实际数据集中,此转换不起作用。我将尝试更好地解释刚刚开始的案例2。你应该在stackoverflow中问另一个新问题,因为我们已经花时间解决了前一个问题,并且现在你改变了它你是对的,但解决问题也很重要。我本来想更好地解释这个问题。你解释了一个与它无关的问题。如果你现在改变了问题,人们会看到这个问题,认为这个答案是错的,当它不是错的时候,他们会投反对票。这对于最初的问题是正确的估计。您可以提出另一个新问题并正确地提出问题。当状态==1之后的状态==2->仅为状态2之前的行删除状态==1的行,而不是全部(状态2之后的状态为1的行)。是否可以为此更正函数?当状态==1之后的状态==2->仅对状态2之前的行(而不是所有的行(状态为2的行之后的状态为1的行)删除状态==1的行时,只有一件事是有效的,tnx。是否可以为此更正函数?