【问题标题】:Pandas row analysis for consecutive dates连续日期的 Pandas 行分析
【发布时间】:2015-09-16 15:15:45
【问题描述】:

按照行的“链”并从 CSV 文件中计算连续月份。

目前我正在阅读一个包含 5 列感兴趣的 CSV 文件(基于保险单):

CONTRACT_ID   START-DATE           END-DATE        CANCEL_FLAG    OLD_CON_ID
123456        2015-05-30           2016-05-30       0             8788
123457        2014-03-20           2015-03-20       0             12000
123458        2009-12-20           2010-12-20       0             NaN
...

我想计算一个合约链连续运行的月数。

示例:从链“前端”的合约(最旧的合约)获取START-DATE,从链的末端(最新的合约)获取END-DATE。最旧的合约由链中被取消的合约之前定义,或者由没有OLD_CON_ID 值的合约定义。

每一行代表一个合约,prev_Con_ID 指向前一个合约 ID。期望的输出是合约链可以追溯到多少个月直到出现间隙(即客户在一段时间内没有合约)。如果该列中没有任何内容,则这是该链中的第一个合约。

CANCEL_FLAG 也应该切断链,因为值为 1 表示合约被取消。

当前代码通过像这样编辑数据框来计算每年的活跃合约数量:

df_contract = df_contract[
(df_contract['START_DATE'] <= pd.to_datetime('2015-05-31')) & 
(df_contract['END_DATE'] >= pd.to_datetime('2015-05-31')) & (df_contract['CANCEL_FLAG'] == 0 )
]
df_contract = df_contract[df_contract['CANCEL_FLAG'] == 0
]
activecount = df_contract.count()
print activecount['CONTRACT_ID']

这里是我创建数据框和调整日期时间值的前 6 行代码:

file_name = 'EXAMPLENAME.csv'
df = pd.read_csv(file_name)
df_contract = pd.read_csv(file_name)
df_CUSTOMERS = pd.read_csv(file_name)

df_contract['START_DATE'] = pd.to_datetime(df_contract['START_DATE'])
df_contract['END_DATE'] = pd.to_datetime(df_contract['END_DATE'])

理想的输出是这样的:

FIRST_CONTRACT_ID       CHAIN_LENGTH       CON_MONTHS
1234567                 5                  60
1500001                 1                  4
800                     10                 180

然后将这些数据点绘制成图表。

EDIT2:CSV 文件已更改,现在可能更容易。问题已更新。

【问题讨论】:

    标签: python date csv pandas


    【解决方案1】:

    不确定我是否完全理解您的要求,但这样的工作是否有效?:

    df_contract['TOTAL_YEARS'] = (df_contract['END_DATE'] - df_contract['START_DATE']
                                 )/np.timedelta64(1,'Y')
    
    df_contract['TOTAL_YEARS'][(df['CANCEL_FLAG'] == 1) && (df['TOTAL_YEARS'] > 1)] = 1
    

    【讨论】:

    • 验证的时间太长了,但它正确计算了成为客户的年数,尽管不是连续的。举例说明。 Client1 的合同从 2006 年到 2008 年,然后是 2010 年到 2015 年。代码应该返回 5,而不是 9。
    • 由于原始 CSV 文件的更改,我还编辑了原始问题。希望这能让它更容易理解(和执行)。
    【解决方案2】:

    经过多次反复试验,我终于成功了!

    这会找到链中第一个和最后一个合约之间的时间差并且找到链的长度。

    目前不是最干净的代码,但它可以工作:

    test = 'START_DATE'
    
    
    df_short = df_policy[['OLD_CON_ID',test,'CONTRACT_ID']]
    df_short.rename(columns={'OLD_CON_ID':'PID','CONTRACT_ID':'CID'}, 
    
    inplace = True)
    df_test = df_policy[['CONTRACT_ID','END_DATE']]
    df_test.rename(columns={'CONTRACT_ID':'CID','END_DATE': 'PED'}, inplace = True)
    
    
    df_copy1 = df_short.copy()
    df_copy2 = df_short.copy()
    df_copy2.rename(columns={'PID':'PPID','CID':'PID'}, inplace = True)
    
    df_merge1 = pd.merge(df_short, df_copy2,
        how='left',
        on=['PID'])
    
    df_merge1['START_DATE_y'].fillna(df_merge1['START_DATE_x'], inplace = True)
    df_merge1.rename(columns={'START_DATE_x':'1_EFF','START_DATE_y':'2_EFF'}, inplace=True)
    

    复制、合并、填充和重命名代码对 5 个合并的数据帧重复然后:

    df_merged = pd.merge(df_merge5, df_test,
        how='right',
        on=['CID'])
    
    df_merged['TOTAL_MONTHS'] = ((df_merged['PED'] - df_merged['6_EFF']
                                 )/np.timedelta64(1,'M'))
    
    df_merged4 = df_merged[
        (df_merged['PED'] >= pd.to_datetime('2015-07-06')) 
    df_merged4['CHAIN_LENGTH'] = df_merged4.drop(['PED','1_EFF','2_EFF','3_EFF','4_EFF','5_EFF'], axis=1).apply(lambda row: len(pd.unique(row)), axis=1) -3
    

    希望我的代码能被理解,并能在未来帮助到别人。

    【讨论】:

      猜你喜欢
      • 2021-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 2021-12-09
      • 2015-02-25
      • 1970-01-01
      相关资源
      最近更新 更多