遍历每个客户记录以获取他们来自的首个/最后一个渠道

2 投票
4 回答
79 浏览
提问于 2025-04-12 21:23

我有一些客户访问记录,记录了他们来自哪个渠道。我想为每个客户保留一条记录,记录他们第一次和最后一次访问时的渠道。

还有一个逻辑需要加进去:如果第一次的渠道是“直接访问”,那么就不算这条记录,继续看下一条。如果下一条也是“直接访问”,那也不算,继续看下一条。直到查看完所有记录,如果客户的所有记录都是“直接访问”,那么第一次的渠道就可以标记为“直接访问”。对于最后一次的渠道也要用同样的逻辑:如果是“直接访问”,就查看前一条记录,依此类推,直到查看完所有记录。

输入的数据看起来是这样的:

客户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
  1. Date转换成日期时间格式,这样你就可以根据Date来排序。如果你的日期格式是这样的话,可以用format="%m/%d/%y"
  2. 定义condition_icondition_ii来适应你的新逻辑:你想要对每个客户ID保留: (i) 如果所有行的Channel都是Direct,就保留所有行;或者 (ii) 如果不是所有行的Channel都是Direct,就只保留那些Channel不是Direct的行
  3. 根据Customer ID进行分组,然后分别取firstlast进行汇总。
  4. 把分组后的数据框合并在一起。
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

撰写回答