【问题标题】:How to create a new column that is the sum of the number of columns from a specific range that meet multiple conditions如何创建一个新列,该列是特定范围内满足多个条件的列数的总和
【发布时间】:2019-09-11 20:47:56
【问题描述】:

.我有一个看起来与此类似的数据框(除了 VisitDeliv 列的数量上升到 Visit_12Deliv 12 并且有数百个客户端 - 我在这里简化了它)

Client   Visit_1    Visit_2    Visit_3    Deliv_1  Deliv_2  Deliv_3 Key_DT
Client_1 2018-01-01 2018-01-20 2018-03-29 No       Yes      Yes     2018-01-15
Client_2 2018-01-10 2018-01-30 2018-02-10 Yes      Yes      No      2018-01-25
Client_3 2018-01-20 2018-04-01 2018-04-10 Yes      Yes      Yes     2018-04-15
Client_4 2018-01-30 2018-03-01 2018-03-10 Yes      No       Yes     2018-02-25
Client_5 2018-04-02 2018-04-07 2018-04-20 Yes      No       Yes     2018-04-01

我想创建一个名为Vis_sum 的新列,该列显示,对于在2018-01-20 之后但在2018-03-25 之前具有Key_DT 的所有客户端,从Visit_1Visit_3 的访问次数总和(i) 在同一行中位于 Key_DT 之后,(ii) 在 2018-03-25 之前,并且 (iii) 在关联的 Deliv 列中有一个 Yes(例如,Deliv_1Visit_1 相关联)。它应该是这样的

Client   Visit_1    Visit_2    Visit_3    Deliv_1  Deliv_2  Deliv_3 Key_DT     Vis_sum
Client_1 2018-01-01 2018-01-20 2018-03-29 No       Yes      Yes     2018-01-15 0
Client_2 2018-01-10 2018-01-30 2018-02-10 Yes      Yes      No      2018-01-25 1
Client_3 2018-01-20 2018-04-01 2018-04-10 Yes      Yes      Yes     2018-04-15 0
Client_4 2018-01-30 2018-03-01 2018-03-10 Yes      No       Yes     2018-02-25 1
Client_5 2018-04-02 2018-04-07 2018-04-20 Yes      No       Yes     2018-04-01 0

请注意 - 所有列中都缺少数据,因此必须考虑到这一点。

我尝试了以下方法 - 但没有奏效。虽然 (i) 和 (ii) 部分的代码在一起尝试时可以工作,而 (iii) 的代码可以单独工作,但当编写完以下所有代码后,它会为 @ 列中的每一行返回 0 987654340@:

df.loc[((df.Key_DT < '2018-03-25') & (df.Key_DT >= '2018-01-20')), 'Vis_sum'] = ((df.filter(like='Visit_').gt(df.Key_DT,axis=0)) & (df.filter(like='Visit_').lt(pd.to_datetime('2018-03-25')).fillna(0).astype(bool)) & (df.filter(like='Deliv_').eq('Yes'))).sum(1)

【问题讨论】:

  • 你不是已经问过这个问题了吗?
  • (a) 没有添加这些额外条件,并且 (b) 没有一个解决方案有效 - 很可能是由于问题不明确。我希望通过重新提出问题,这些建议更有可能奏效——有什么想法吗?
  • 你能把你迄今为止尝试过的东西也发布一下吗?
  • 好点 - 请查看已编辑的问题
  • 我个人会做的(我有一个类似的数据集)是融合我的框架并创建一个表格格式来运行分析,然后你可以使用 groupby + cumcount 来获得你想要的结果。将与您的样本一起玩

标签: python pandas datetime conditional-statements


【解决方案1】:

我有一个类似的(由调查生成的非常混乱的)数据集,我使用 meltmergegroupby-transform-cumcount 来获取我想要的数字

假设您的数据集称为 df :

#First melt the DF and the unique visits (you'll have to do this for all your value_vars)    
df1 = pd.melt(df,id_vars='Client',value_vars=['Visit_1','Visit_2','Visit_3'],var_name='Visit',value_name='Visit Date')
print(df1.head(5))
Client  Visit   Visit Date
0   Client_1    Visit_1 2018-01-01
1   Client_2    Visit_1 2018-01-10
2   Client_3    Visit_1 2018-01-20
3   Client_4    Visit_1 2018-01-30
4   Client_5    Visit_1 2018-04-02
#lets do the same for the deliveries 
df2 = pd.melt(df,id_vars='Client',value_vars=['Deliv_1','Deliv_2','Deliv_3'],var_name='Delivery',value_name='Check')

融化后,我们可以将您的值合并回表格样式 df。

# Lets merge these and then put the Key_DT back on 
res = pd.merge(df1,df2,on='Client')
res = pd.merge(res,df[['Client','Key_DT']],on='Client')
print(res.head(5))
        Client  Visit   Visit Date  Delivery    Check   Key_DT
0   Client_1    Visit_1 2018-01-01  Deliv_1 No  2018-01-15
1   Client_1    Visit_1 2018-01-01  Deliv_2 Yes 2018-01-15
2   Client_1    Visit_1 2018-01-01  Deliv_3 Yes 2018-01-15
3   Client_1    Visit_2 2018-01-20  Deliv_1 No  2018-01-15
4   Client_1    Visit_2 2018-01-20  Deliv_2 Yes 2018-01-15

让我们根据您的条件过滤并按Client 计算值

s = res.loc[(res['Key_DT'] >= '2018-01-20') & (res['Key_DT'] <= '2018-03-25') & (res.Check == 'Yes')]
res['visit_sum'] = s.groupby(['Client','Visit'])['Check'].transform('cumcount')
res['visit_sum'] = res['visit_sum'].fillna(0)
print(res.loc[res['visit_sum'] > 0])
    Client  Visit   Visit Date  Delivery    Check   Key_DT  visit_sum
27  Client_4    Visit_1 2018-01-30  Deliv_1 Yes 2018-02-25  1.0
29  Client_4    Visit_1 2018-01-30  Deliv_3 Yes 2018-02-25  1.0
30  Client_4    Visit_2 2018-03-01  Deliv_1 Yes 2018-02-25  1.0
32  Client_4    Visit_2 2018-03-01  Deliv_3 Yes 2018-02-25  1.0
33  Client_4    Visit_3 2018-03-10  Deliv_1 Yes 2018-02-25  1.0
35  Client_4    Visit_3 2018-03-10  Deliv_3 Yes 2018-02-25  1.0

希望 sort 对您有所帮助,并使您朝着获得预期结果的方向前进。

【讨论】:

  • 太棒了!我认为它可能需要对您进行一些修补,但我很高兴它起作用了。感谢您的绿色勾号。
【解决方案2】:

您编写的代码不起作用,因为它不知道应该将Visit_#Deliv_# 匹配。试试这个:

df.loc[((df.Key_DT < '2018-03-25') & (df.Key_DT >= '2018-01-20')), 'Vis_sum'] = ((df.filter(like='Visit_').gt(df.Key_DT,axis=0)) & (df.filter(like='Visit_').lt(pd.to_datetime('2018-03-25'),axis=0).fillna(0).astype(bool)) & (df.filter(like='Deliv_').rename(columns=lambda x: x.replace('Deliv','Visit')).eq('Yes'))).sum(1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-24
    • 2019-11-18
    相关资源
    最近更新 更多