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

函数未捕获值变化:Pandas生成DataFrame日期列失败求助

问题解决:为DataFrame按周生成连续起始日期

问题描述

现有如下DataFrame:

state_territory_code    week_nbr
 CA                     WEEK 49
 CA                     WEEK 49
 FL                     WEEK 49
 CA                     WEEK 50
 TN                     WEEK 50
 HI                     WEEK 50
 GA                     WEEK 51
 FL                     WEEK 51

需求是:按行迭代时,若当前行周数与下一行周数不同,则将起始日期加7天,最终生成new_cal_date列,期望输出如下:

state_territory_code    week_nbr          new_cal_date
     CA                     WEEK 49         01/01/2024
     CA                     WEEK 49         01/01/2024
     FL                     WEEK 49         01/01/2024
     CA                     WEEK 50         01/08/2024
     TN                     WEEK 50         01/08/2024
     HI                     WEEK 50         01/08/2024
     GA                     WEEK 51         01/15/2024
     FL                     WEEK 51         01/15/2024

用户尝试了以下代码,但用apply后结果全是01/08/2024,函数外测试逻辑有效,需要修复:

def cal_week_start(some_df):
    start_dt = datetime.datetime(2024, 1, 1)
    
    for i, wk in enumerate(some_df):
        if i < (len(some_df)-1): ## Keep running as long as we haven't reached end of DF
            next_value = some_df[i+1] ## index pos of next value
            if wk != next_value: ## if value changes from one to the next do something
                new_dt = start_dt + timedelta(days = 7) ## Add 7 days.
                start_dt = new_dt ## reinitiate variable to add 7 days, 14, 21, etc.
                return start_dt 
        else:
            return start_dt

df_new['new_cal_date'] = df_new['week_nbr'].apply(cal_week_start)

问题根源

你用apply调用函数的方式完全错误:

  • apply是对Series里的每一个单独元素执行函数,而不是把整个Series传给函数。比如每次调用cal_week_start时,传入的是单个字符串(比如"WEEK 49"),不是整个week_nbr列。
  • 函数里的enumerate(some_df)其实是在枚举单个字符串的字符,逻辑彻底混乱,最后只会返回第一次满足wk != next_value的start_dt+7,所以所有行都得到01/08/2024。

高效解决方案(适配大数据集)

大数据集绝对不能用循环,要用pandas的向量化操作,速度快几个数量级。这里有两种简洁的实现方式:

方法1:用唯一周映射日期

import pandas as pd
from datetime import datetime, timedelta

# 初始化你的DataFrame
df = pd.DataFrame({
    'state_territory_code': ['CA', 'CA', 'FL', 'CA', 'TN', 'HI', 'GA', 'FL'],
    'week_nbr': ['WEEK 49', 'WEEK 49', 'WEEK 49', 'WEEK 50', 'WEEK 50', 'WEEK 50', 'WEEK 51', 'WEEK 51']
})

start_dt = datetime(2024, 1, 1)
# 获取按顺序排列的唯一周数
unique_weeks = df['week_nbr'].unique()
# 为每个周数分配对应的起始日期:第1周+0天,第2周+7天,以此类推
week_date_map = {week: start_dt + timedelta(days=7*i) for i, week in enumerate(unique_weeks)}

# 映射到原DataFrame,再格式化日期
df['new_cal_date'] = df['week_nbr'].map(week_date_map).dt.strftime('%m/%d/%Y')

print(df)

方法2:用factorize生成周组索引

import pandas as pd
from datetime import datetime, timedelta

df = pd.DataFrame({
    'state_territory_code': ['CA', 'CA', 'FL', 'CA', 'TN', 'HI', 'GA', 'FL'],
    'week_nbr': ['WEEK 49', 'WEEK 49', 'WEEK 49', 'WEEK 50', 'WEEK 50', 'WEEK 50', 'WEEK 51', 'WEEK 51']
})

start_dt = datetime(2024, 1, 1)
# factorize()会给每个唯一的周数分配一个递增的整数索引(从0开始)
df['week_group'] = df['week_nbr'].factorize()[0]
# 计算每个组对应的日期:起始日期 + 组索引*7天
df['new_cal_date'] = (start_dt + df['week_group'].apply(lambda x: timedelta(days=7*x))).dt.strftime('%m/%d/%Y')

# 可以删掉中间的week_group列(如果不需要)
df.drop('week_group', axis=1, inplace=True)

print(df)

两种方法都能得到你想要的结果,而且完全适配大数据集,不需要循环迭代每一行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 20:25:53