遍历每个客户记录以获取他们来自的首个/最后一个渠道
我有一些客户访问记录,记录了他们来自哪个渠道。我想为每个客户保留一条记录,记录他们第一次和最后一次访问时的渠道。
还有一个逻辑需要加进去:如果第一次的渠道是“直接访问”,那么就不算这条记录,继续看下一条。如果下一条也是“直接访问”,那也不算,继续看下一条。直到查看完所有记录,如果客户的所有记录都是“直接访问”,那么第一次的渠道就可以标记为“直接访问”。对于最后一次的渠道也要用同样的逻辑:如果是“直接访问”,就查看前一条记录,依此类推,直到查看完所有记录。
输入的数据看起来是这样的:
客户ID | 日期 | 渠道 |
---|---|---|
1 | 1/1/24 | 邮件 |
1 | 1/2/24 | 搜索 |
1 | 1/3/24 | 直接访问 |
2 | 1/5/24 | 直接访问 |
2 | 1/6/24 | 付费 |
2 | 1/7/24 | 邮件 |
3 | 1/8/24 | 直接访问 |
3 | 1/9/24 | 直接访问 |
3 | 1/10/24 | 直接访问 |
3 | 1/11/24 | 直接访问 |
我需要的输出结果是这样的:
客户ID | 第一次渠道 | 最后一次渠道 |
---|---|---|
1 | 邮件 | 搜索 |
2 | 付费 | 邮件 |
3 | 直接访问 | 直接访问 |
我该如何在我的数据框中实现这个呢?
可能我需要创建两个循环,一个循环遍历所有记录,里面再嵌套一个循环来处理每个客户的记录。它先记录第一次渠道,然后检查是否是“直接访问”,如果是,就继续查看下一条记录,直到循环结束。
4 个回答
0
你可以使用 sort_values
来排序数据,然后用自定义的 groupby.agg
方法,选择 'first'
或 'last'
来处理数据:
df['Date'] = pd.to_datetime(df['Date'], dayfirst=False)
out = (df
.sort_values(by='Date')
.groupby('Customer ID', as_index=False)
.agg(**{'First Channel': ('Channel', 'first'),
'Last Channel': ('Channel', 'last')
})
)
输出结果:
Customer ID First Channel Last Channel
0 1 Email Direct
1 2 Direct Email
2 3 Direct Direct
0
在我开始之前,你的输出应该根据你的输入值看起来像这样。如果你再检查一下你的输入和输出,就会明白了。
Customer ID, First Channel, Last Channel
1 Email Direct
2 Direct Email
3 Direct Direct
首先,把你的日期列转换成日期时间格式。
df['Date'] = pd.to_datetime(df['Date'])
接下来,按照客户ID和日期对你的数据进行排序。
df = df.sort_values(by=['Customer ID', 'Date'])
找到你的第一个渠道。
first_channel = df.groupby('Customer ID')['Channel'].first().reset_index()
找到你的最后一个渠道。
last_channel = df.groupby('Customer ID')['Channel'].last().reset_index()
把第一个渠道和最后一个渠道根据客户ID合并在一起。
final= pd.merge(first_channel, last_channel, on='Customer ID')
最终的结果会包含“客户ID, Channel_x, Channel_y”,所以需要更改列名。你需要使用这个。
final.columns = ['Customer ID', 'First Channel', 'Last Channel']
1
- 把
Date
转换成日期时间格式,这样你就可以根据Date
来排序。如果你的日期格式是这样的话,可以用format="%m/%d/%y"
。 - 定义
condition_i
和condition_ii
来适应你的新逻辑:你想要对每个客户ID保留: (i) 如果所有行的Channel
都是Direct
,就保留所有行;或者 (ii) 如果不是所有行的Channel
都是Direct
,就只保留那些Channel
不是Direct
的行。 - 根据
Customer ID
进行分组,然后分别取first
和last
进行汇总。 - 把分组后的数据框合并在一起。
df["Date"] = pd.to_datetime(df["Date"], format="%d/%m/%y")
df = df.sort_values(by="Date")
condition_i = df.groupby("Customer ID")["Channel"].transform(
lambda x: all(x == "Direct")
)
condition_ii = (
df.groupby("Customer ID")["Channel"]
.transform(lambda x: any(x != "Direct"))
.loc[df["Channel"] != "Direct"]
)
first = (
df[(condition_i) | (condition_ii)]
.groupby("Customer ID", as_index=False)
.first()
.rename(columns={"Channel": "Fist Channel"})
)
last = (
df[(condition_i) | (condition_ii)]
.groupby("Customer ID", as_index=False)
.last()
.rename(columns={"Channel": "Last Channel"})
)
out = pd.merge(
first[["Customer ID", "Fist Channel"]], last[["Customer ID", "Last Channel"]]
)
Customer ID Fist Channel Last Channel
0 1 Email Search
1 2 Paid Email
2 3 Direct Direct