【问题标题】:How to compare consecutive rows and add a column based on the condition如何比较连续行并根据条件添加列
【发布时间】:2018-08-30 04:08:35
【问题描述】:

我正在尝试计算 pandas 数据帧中两个连续行之间的差异,并根据我想用某个值填充一列的结果。

例如:

以下是示例数据

ID Date
1   2/2/2018
2   2/3/2018
3   2/18/2018
3   2/19/2018
3   2/27/2018
4   5/5/2018
4   6/9/2018
5   6/10/2018
6   7/1/2018
6   7/2/2018
6   7/10/2018
6   7/30/2018
6   8/1/2018
6   8/3/2018
7   8/10/2018

数据按 ID 分组。

以下是示例输出数据

因此,每当 ID 发生变化时,“代码”列都会显示“I”。对于相同的 ID,如果两个连续日期之间的差异小于 30,则“代码”列具有“R1”,对于相同的 ID,如果下一个日期在前一个日期的 30 天内,“代码”将具有“R2”,对于如果下一个数据在前一个“代码”的 30 天内,则相同的 ID 将具有“R4”。例如,以 case ID--"4" 为例,“Code”的两行都是“I”,因为即使 ID = 4,这两个日期也相距 30 天以上。 2018 年 6 月 9 日 - 2018 年 5 月 5 日 = 34。

sorted_data["Code"] = "I"
def conditions(data):
    if data['Completed Date'].diff() <=30:
        val = "R1"
    elif  data['Completed Date'].diff() <=30:
        val = "R2"
    elif  data['Completed Date'].diff() <=30:
        val = "R3"
    elif data['Completed Date'].diff() <=30:
        val = "R4"
    elif data['Completed Date'].diff() <=30:
        val = "R5"
    elif data['Completed Date'].diff() <=30:
        val = "R6"
    elif data['Completed Date'].diff() <=30:
        val = "R7"
    elif data['Completed Date'].diff() <=30:
        val = "R8"
    return val
for groups, data in sorted_data.groupby("Cust_No"):
    print(conditions(sorted_data))

我不知道如何获取下一行值来比较日期。上面的代码不起作用并给我错误。

【问题讨论】:

  • 研究使用np.select
  • @Deya,请发布可以复制的文本以创建示例数据集,图像不好。
  • @HaleemurAli,我重新格式化了它。如果您有更多信息,请告诉我

标签: python-3.x pandas-groupby


【解决方案1】:

ID 分组,查找与前一个日期的日期差小于或等于30 的所有行。

然后再次按ID分组,得到累积和并设置I,其中值等于0 else前缀R

x = df.groupby('ID').apply(lambda x: x.Date-x.Date.shift() <= pd.Timedelta(days=30)).astype(int) 
df['out'] = x.groupby('ID').cumsum().apply(lambda x: 'I' if x == 0 else f'R{x}').reset_index(drop=True)  

# output:

    ID       Date out
0    1 2018-02-02   I
1    2 2018-02-03   I
2    3 2018-02-18   I
3    3 2018-02-19  R1
4    3 2018-02-27  R2
5    4 2018-05-05   I
6    4 2018-06-09   I
7    5 2018-06-10   I
8    6 2018-07-01   I
9    6 2018-07-02  R1
10   6 2018-07-10  R2
11   6 2018-07-30  R3
12   6 2018-08-01  R4
13   6 2018-08-03  R5
14   7 2018-08-10   I

【讨论】:

    【解决方案2】:

    可能不是最优的,但正在使用 iterrows:

    prev_id = 'x' 
    prev_date = pd.to_datetime('1/1/1900')
    prev_rpt = 0
    for idx,ser in df.iterrows():
        if ser.ID == prev_id and (ser.Date - prev_date).days < 30:
            prev_rpt += 1
            df.loc[idx,'Code'] = 'R' + str(prev_rpt)
        else:
            df.loc[idx,'Code'] = 'I'
            prev_rpt = 0
        prev_id = ser.ID
        prev_date = ser.Date  
    

    【讨论】:

    • 感谢您的快速回复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-22
    • 1970-01-01
    • 2020-11-11
    • 2022-01-23
    相关资源
    最近更新 更多