【问题标题】:Python For Loop for Grouped Data with Interrows and Defined Function用于具有行间和定义函数的分组数据的 Python For 循环
【发布时间】:2021-10-12 19:12:16
【问题描述】:

我正在尝试计算一个指示列,以便如果给定客户在给定服务结束日期后 60 天内返回另一项服务,则它返回值 1。下面是数据表和所需的指标列。

我已按客户和服务对数据进行了分类和分组。现在,我正在尝试整理一个公式,该公式查看每一行的结束日期,并检查该给定客户(组)的任何未来服务开始日期是否在 60 天内。

到目前为止,我已经对数据进行了分组,并尝试应用 for 循环......但我不断收到错误消息。我是 Python 新手,所以我不太确定如何设置代码和语法以使其正常工作。任何帮助将不胜感激 - 谢谢!

df = pd.DataFrame({'Customer':['John','John','Deb','Sara','Sara','Sara','Sara','Sara','Mike','Mike','Mike'],
               'Service':['A','B','C','A','B','C','D','E','E','F','G'],
               'Start':['1/2/2020','3/1/2020','2/5/2020','2/6/2020','3/6/2020','8/2/2020','9/15/2020','10/2/2020','5/4/2020','6/8/2020','7/1/2020'],
               'End':['1/3/2020','3/11/2020','2/7/2020','2/9/2020','3/9/2020','8/12/2020','9/19/2020','10/12/2020','5/8/2020','6/18/2020','7/8/2020']})


df['Start'] = pd.to_datetime(df['Start'], infer_datetime_format=True, errors='coerce')
df['End'] = pd.to_datetime(df['End'], infer_datetime_format=True, errors='coerce')
df.dtypes

grp=df.groupby(['Customer','Service'])
grp.head(15)

def serv_days(Start,End):
    for row in df.iterrows():
        if (row[1].Start == row.End):
            continue
        if ((row[1].Start-row.End).days < 60):
            return 1
        else:
            return 0

for grpnm,each_grp in grp:
    for row in each_grp.iterrows():
        print(serv_days(each_grp,row[1].Start,row.loc('End')))

【问题讨论】:

    标签: python-3.x for-loop iterator pandas-groupby


    【解决方案1】:

    正如您所说,我们可以将当前行与下一行进行比较,以查看当前行客户是否等于下一行客户,并且当前行结束日期与下一行开始日期的差异小于 60 天。
    随心所欲,我们不需要groupby,我们需要:

    • 使用df[1:] 移动数据框,这意味着删除第一行并保留其他行
    • 我们需要reset_index 才能将index 与原始df 合并,所以现在我们有一个数据框将当前行和下一行合并到同一行中
    • 只需比较customercustomer_next_next 后缀由merge 函数suffixes 参数添加)和差异End Start_next
    df = pd.DataFrame({'Customer':['John','John','Deb','Sara','Sara','Sara','Sara','Sara','Mike','Mike','Mike'],
                   'Service':['A','B','C','A','B','C','D','E','E','F','G'],
                   'Start':['1/2/2020','3/1/2020','2/5/2020','2/6/2020','3/6/2020','8/2/2020','9/15/2020','10/2/2020','5/4/2020','6/8/2020','7/1/2020'],
                   'End':['1/3/2020','3/11/2020','2/7/2020','2/9/2020','3/9/2020','8/12/2020','9/19/2020','10/12/2020','5/8/2020','6/18/2020','7/8/2020']})
    
    df['Start'] = pd.to_datetime(df['Start'], infer_datetime_format=True, errors='coerce')
    df['End'] = pd.to_datetime(df['End'], infer_datetime_format=True, errors='coerce')
    
    new_df = pd.merge(df,df[1:].reset_index(drop=True),suffixes=['','_next'],left_index=True,right_index=True,how='left')
    new_df['indicator'] = (new_df['Customer'] == new_df['Customer_next']) & ((new_df['Start_next']-new_df['End'])<pd.Timedelta('60 days'))
    new_df = new_df[['Customer','Service','Start','End','indicator']]
    
        Customer    Service   Start         End         indicator
    0   John        A         2020-01-02    2020-01-03  TRUE
    1   John        B         2020-03-01    2020-03-11  FALSE
    2   Deb         C         2020-02-05    2020-02-07  FALSE
    3   Sara        A         2020-02-06    2020-02-09  TRUE
    4   Sara        B         2020-03-06    2020-03-09  FALSE
    5   Sara        C         2020-08-02    2020-08-12  TRUE
    6   Sara        D         2020-09-15    2020-09-19  TRUE
    7   Sara        E         2020-10-02    2020-10-12  FALSE
    8   Mike        E         2020-05-04    2020-05-08  TRUE
    9   Mike        F         2020-06-08    2020-06-18  TRUE
    10  Mike        G         2020-07-01    2020-07-08  FALSE
    

    【讨论】:

    • 感谢您的更正@nay,我确定了结束日期并添加了我希望获得的结果示例表。您提供的代码很有帮助,但返回全 1...我认为它只比较当前行的开始/结束日期?例如,当我们查看客户 Sara 时,我希望将服务 A 的结束日期与所有未来服务的开始日期进行比较 - 检查是否有 60 天内。然后下一行也一样。我需要将 Sara 的服务 B 的结束日期与所有未来的开始日期进行比较,看看她是否在 60 天内完成了进一步的服务,等等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-15
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    相关资源
    最近更新 更多