You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为包含card_id与num_week的DataFrame添加多列,标记卡片ID在过去4周内的使用状态

解决卡片周使用历史标记问题

嘿,我来帮你搞定这个需求!你之前用循环没成功,大概率是因为没先处理重复记录,或者没高效地按卡片分组去查询历史周数。其实用Pandas的内置方法就能轻松实现,而且比循环高效很多,我给你两种可行的方案:

方案一:利用集合查询(直观易读)

这个方法先把每个卡片的所有使用周数存成集合,然后直接检查当前周的前n周是否在集合里,逻辑非常清晰:

import pandas as pd

# 构造你的示例数据
data = {
    'card_id': [123234, 124531, 345124, 451433, 512453, 123234, 124531, 235467, 145246, 134353, 512453, 123234],
    'num_week': [1,1,1,1,2,2,2,2,3,3,3,3]
}
df = pd.DataFrame(data)

# 第一步:先去重,得到每个卡片在哪些周有使用记录(避免重复计算)
unique_usage = df.drop_duplicates(subset=['card_id', 'num_week'])

# 第二步:为每个卡片建立使用周数的集合,方便快速查询
card_week_sets = unique_usage.groupby('card_id')['num_week'].apply(set)

# 第三步:定义函数,判断当前卡片在n周前是否被使用
def has_used_prior(row, n):
    target_week = row['num_week'] - n
    # 如果目标周数小于1(比如第1周的前1周是0,不存在),直接返回0
    if target_week < 1:
        return 0
    # 检查目标周是否在该卡片的使用集合里
    return 1 if target_week in card_week_sets.get(row['card_id'], set()) else 0

# 第四步:生成前1到4周的标记列
for n in range(1, 5):
    # 列名处理:第1周用used_week_prior,其余用used_n_weeks_prior
    col_name = 'used_week_prior' if n == 1 else f'used_{n}_weeks_prior'
    df[col_name] = df.apply(lambda x: has_used_prior(x, n), axis=1)

# 查看结果
print(df.sort_values(by=['num_week', 'card_id']).reset_index(drop=True))

方案二:利用Merge连接(高效,适合大数据量)

如果你的数据集很大,apply可能会有点慢,这时候用Pandas的merge操作更高效,因为它是向量化的:

import pandas as pd

# 同样先构造示例数据
data = {
    'card_id': [123234, 124531, 345124, 451433, 512453, 123234, 124531, 235467, 145246, 134353, 512453, 123234],
    'num_week': [1,1,1,1,2,2,2,2,3,3,3,3]
}
df = pd.DataFrame(data)

# 第一步:去重得到唯一的卡片-周数组合
unique_usage = df.drop_duplicates(subset=['card_id', 'num_week'])

# 第二步:循环生成前1到4周的标记列
for n in range(1, 5):
    col_name = 'used_week_prior' if n == 1 else f'used_{n}_weeks_prior'
    # 构造临时表:把每个卡片的使用周数加上n,得到"哪些卡片在X周的n周前有使用"
    temp = unique_usage.copy()
    temp['current_week'] = temp['num_week'] + n
    # 只保留需要的列,避免冗余
    temp = temp[['card_id', 'current_week']]
    # 左连接到原始表,匹配卡片ID和当前周数
    df = df.merge(temp, left_on=['card_id', 'num_week'], right_on=['card_id', 'current_week'], how='left')
    # 能匹配到说明n周前有使用,标记为1,否则0
    df[col_name] = df['current_week'].notna().astype(int)
    # 删除临时列
    df = df.drop(columns=['current_week'])

# 查看结果
print(df.sort_values(by=['num_week', 'card_id']).reset_index(drop=True))

结果说明

两种方案都会生成你需要的4列,比如对于card_id=123234、num_week=3的记录:

  • used_week_prior是1(因为它在第2周有使用)
  • used_2_weeks_prior是1(因为它在第1周有使用)
  • used_3_weeks_prior和used_4_weeks_prior都是0(没有更早的记录)

这完全符合你给出的期望结果,而且自动处理了周数小于1的情况(比如第1周的前1周不存在,直接返回0)。

内容的提问来源于stack exchange,提问作者TomasC8

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 17:17:42