使用 Pandas 和 R 创建序列和

Creating Sequence Sum using Pandas and R

大家好,我想使用 ID、月份和值来计算序列和标志。 对于每个唯一 ID,如果值更改为零,则序列为 1,如果连续几个月持续为零,则序列将如上所示添加。

当序列加到6时,标志位为1

请帮助我使用 Pandas 和 R

R中,我们可以使用data.table创建'Sequence'和'Flag'。将 'data.frame' 转换为 'data.table' (setDT(df1)),按 'Id' 分组,我们用 Value == 0 指定 'i',创建 'Sequence' 作为基于 'i' 中的 TRUE 值的序列 (1:.N)。然后,通过为 'Sequence' 为 1 的那些元素分配 (:=) 1 来创建 'Flag'。如果 'Id' 没有 1 或 all 'Flag' 值为 NA,则在顶部连接 0,同时从 'Flag' 中删除一个元素(Flag[-1] ) 或 else return 'Flag'

library(data.table)
setDT(df1)[Value == 0, Sequence := 1:.N , by = Id]
df1[Sequence ==1, Flag := 1][, Flag := if(all(is.na(Flag))) 
                     c(0, Flag[-1]) else Flag, by = Id]
df1
#        Id  Month Value Sequence Flag
# 1: SCSR1 Jan-16   400       NA   NA
# 2: SCSR1 Feb-16     0        1    1
# 3: SCSR1 Mar-16     0        2   NA
# 4: SCSR1 Apr-16     0        3   NA
# 5: SCSR1 May-16     0        4   NA
# 6: SCSR1 Jun-16     0        5   NA
# 7: SCSR1 Jul-16     0        6   NA
# 8: SCCS9 Jan-16   440       NA    0
# 9: SCCS9 Feb-16  3000       NA   NA
#10: SCCS9 Mar-16   400       NA   NA
#11: SCCS9 Apr-16   100       NA   NA
#12: SCCS9 May-16   300       NA   NA
#13: SCCS9 Jun-16   400       NA   NA
#14: SCCS9 Jul-16   100       NA   NA
#15: SKHH1 Jan-16  1000       NA   NA
#16: SKHH1 Feb-16     0        1    1
#17: SKHH1 Mar-16     0        2   NA
#18: SKHH1 Apr-16     0        3   NA
#19: SKHH1 May-16     0        4   NA
#20: SKHH1 Jun-16     0        5   NA
#21: SKHH1 Jul-16     0        6   NA

注意:最好将 NA 作为缺失值而不是空白 ("") 以保留列的 class。

数据

df1 <- data.frame(Id = rep(c("SCSR1", "SCCS9", "SKHH1"), each = 7),
    Month = rep(c('Jan-16', 'Feb-16', 'Mar-16', 'Apr-16', 'May-16', 'Jun-16',
   'Jul-16'), 3), Value = c(400, rep(0, 6), 440, 3000, 400, 100, 300, 400,
   100, 1000, rep(0,6)))

Pandas解决方案如下。

请注意,如果某个 ID 中的值切换回非零值,下面的序列列将通过复制最后一个值(例如 1,2,3,4,5,6,6,6,6, ...)。这可以通过移动 Value 列来清理,就像我们对 Id 列进行移动并在 Id 内进行比较一样。但是,如果值可以在 Id 中在 0 和非零之间振荡,则累积和方法会失效。如果那没有发生,这种方法应该没问题。我很好奇是否有其他解决方案可以解决这个问题。

import pandas as pd

df = pd.DataFrame({'Id':['SCSR1']*7+['SCCS9']*7+['SKHH1']*7, 'Value':[400]+[0]*6+[440,3000,400,100,300,400,100,1000]+[0]*6})
df['flag'] = 0

# create a shifted column to ensure that comparisons are made within an Id
df['Id2'] = df['Id'].shift()

# set the appropriate flag values to 1 and define the sequences
df.loc[(df['Id'] == df['Id2']) & (df['Value'] == 0), 'flag'] = 1
df['Sequence'] = df.groupby('Id')['flag'].cumsum()

@akrun 已经为您提供了一个漂亮的 R 解决方案。另一种方法是使用 rleid 函数。但我更喜欢@akrun 的解决方案。