Как создать новый столбец, который является суммой количества столбцов из определенного диапазона, которые удовлетворяют нескольким условиям - PullRequest
0 голосов
/ 22 апреля 2019

. У меня есть датафрейм, который выглядит примерно так (за исключением того, что количество столбцов Visit и Deliv достигает Visit_12 и Deliv 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, который показывает, для всех клиентов с Key_DT после 2018-01-20, но до 2018-03-25, сумму количества посещений от Visit_1 до Visit_3 что (i) идет после Key_DT в той же строке, (ii) предшествует 2018-03-25 и (iii) имеет Yes в связанном столбце Deliv (например, Deliv_1 связано с Visit_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 для каждой строки в столбце Vis_sum

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)

Ответы [ 2 ]

1 голос
/ 22 апреля 2019

Код, который вы написали, не работает, потому что он не знает, что он должен соответствовать 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)
1 голос
/ 22 апреля 2019

У меня был похожий (очень грязный, сгенерированный опросом) набор данных, который я использовал melt, merge и groupby-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

надеюсь, что сортирует подсказок и помогает вам достичь желаемого результата.

...