大家好,我想使用 ID、月份和值来计算序列和标志。对于每个唯一的 id,如果值更改为零,则序列为 1,如果连续几个月继续为零,则序列将添加,如上所示。
当序列加到 6 时,标志将为 1。
请帮助我想用 Pandas 和 R 来做
大家好,我想使用 ID、月份和值来计算序列和标志。对于每个唯一的 id,如果值更改为零,则序列为 1,如果连续几个月继续为零,则序列将添加,如上所示。
当序列加到 6 时,标志将为 1。
请帮助我想用 Pandas 和 R 来做
在R
中,我们可以使用 来创建“序列”和“标志” data.table
。将 'data.frame' 转换为 'data.table' ( setDT(df1)
),按 'Id' 分组,我们用 指定 'i' ,根据 'i' 中的 TRUE 值Value == 0
创建 'Sequence' 作为序列 ( )。然后,通过为那些为“序列”为 1 的元素1:.N
分配 ( ) 1 来创建“标志”。:=
如果有没有 1 的 'Id' 或all
'Flag' 值为 NA,则在顶部连接 0,同时从 'Flag' ( Flag[-1]
) 中删除一个元素或else
返回 '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 作为缺失值而不是空格 ( ""
) 以保留列的类别。
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)))
熊猫解决方案如下。
请注意,如果值在 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 的解决方案。