下面的数据集指示每个客户哪些产品处于活动状态以及在哪个月份。 月可以取几个值(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的所有客户。
答案 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种产品的情况下才有效。