在熊猫数据框中进行复杂选择

时间:2019-09-23 02:21:45

标签: python pandas

下面的数据集指示每个客户哪些产品处于活动状态以及在哪个月份。 月可以取几个值(1、2、3等),有很多乘积(x,y,z等),而product_active是二进制值,表示活动状态。

cust_id month product  product_active
1234    1     x        1 
1234    2     x        0 
1234    1     y        0 
1234    2     y        1   

我如何选择从第一个月到第二个月从产品x切换到产品y的所有客户?我想对此进行概括,即能够选择从m1个月到m2个月从产品a切换到产品b的所有客户。

2 个答案:

答案 0 :(得分:1)

好吧,使用.groupby()和矢量解决方案可能会有更多的Python方式,但是这里有一个解决方案可以为df提供您想要的结果。我根据您的数据做出的假设是您的产品有效期列无关紧要。

#DF Setup
_______________________
col = ['cust_id', 'month', 'product',  'product_active']
data = [
(1234,    1,     'x',        1 ),
(1234,    2,     'x',        0 ),
(1235,    1,     'y',        0 ),
(1235,    2,     'y',        1 ),
(1236,    1,     'x',        1 ),
(1236,    2,     'y',        0 )]
df = pd.DataFrame(data, columns=col)

增加了一个额外的客户(1236),以模拟产品从x1到m2的变化(x-> y)。

#Solution
______________________
result_df = pd.DataFrame()

for i,row in df.iterrows():
    if i == 0:
        pass
    elif df.loc[i-1,'cust_id'] == df.loc[i,'cust_id']:
        if (df.loc[i-1,'month'] == 1) & (df.loc[i,'month'] == 2):
            if (df.loc[i-1,'product'] == 'x') & (df.loc[i,'product'] == 'y'):
                result_df = result_df.append(df.loc[i])

这是包装在函数中的通用解决方案:

def filter_function(month,p1,p2):
    '''
    month - month you wish to check for product change.
    p1 - "From" product
    p2 - "To" product
    '''
    result_df = pd.DataFrame()

    for i,row in df.iterrows():
        if i == 0:
            pass
        elif df.loc[i-1,'cust_id'] == df.loc[i,'cust_id']:
            if (df.loc[i-1,'month'] == month-1) & (df.loc[i,'month'] == month):
                if (df.loc[i-1,'product'] == p1) & (df.loc[i,'product'] == p2):
                    result_df = result_df.append(df.loc[i])
    return result_df

filter_function(2,'x','y')

答案 1 :(得分:1)

检查是否适合您

mask = df['product_active'].ne(df['product_active'].shift(2))
a = df[~mask & df.product_active==1]['cust_id']
Cust_not_switching = list(set(df[df['cust_id'].isin(a)]['cust_id'].to_list()))
Cust_switching = list(set(df[~df['cust_id'].isin(a)]['cust_id'].to_list()))

输入

cust_id     month   product     product_active
0   1234    1   x   1
1   1234    2   x   0
2   1234    1   y   0
3   1234    2   y   1
4   1235    1   x   1
5   1235    2   x   1
6   1235    1   y   0
7   1235    2   y   0
8   1236    1   x   0
9   1236    2   x   1
10  1236    1   y   1
11  1236    2   y   0

输出

Cust_not_switching = [1235]
Cust_switching = [1234, 1236]

这只有在有2种产品的情况下才有效。