Python pandas如何将代表周数的列名转换为对应周的起始日期?
现有操作的问题
- 基础语法错误:
示例数据构造时data列表未闭合、pd.dataframe大小写错误(正确写法为pd.DataFrame)、参数括号未闭合;pd.to_datetime的format参数值未加引号,应为字符串格式。 - 周数转日期的逻辑缺失:
单独的周数无法确定唯一日期,必须结合年份、周起始规则才能计算出对应日期,仅用%U格式符缺少必要的基准信息。 - 宽转长操作不完整:
melt时仅传入id_vars=['Owner'],丢失了Index列,后续无法正确转回原始宽表结构。
实现方案
方案1:直接修改列名(更简便,无需宽长转换)
直接对周数列名做转换,不需要做melt和pivot操作,性能更好。
import pandas as pd import datetime # 修正后的示例数据构造 data = [[0,'John',1,2,3]] df = pd.DataFrame(data, columns = ['Index','Owner','32.0','33.0','34.0']) # 可自行调整配置项:年份、周起始规则(0=周一,6=周日) YEAR = 2023 WEEK_START = 0 # 拆分固定列和周数列 fixed_cols = ['Index', 'Owner'] week_cols = [col for col in df.columns if col not in fixed_cols] def week_to_start_date(week_str): # 转换32.0格式的字符串为整数周数 week_num = int(float(week_str)) first_day = datetime.datetime(YEAR, 1, 1) first_weekday = first_day.weekday() # 计算偏移天数 delta = (week_num -1)*7 + (WEEK_START - first_weekday) if delta < 0: delta +=7 return (first_day + datetime.timedelta(days=delta)).strftime('%Y-%m-%d') # 替换列名完成转换 df.columns = fixed_cols + [week_to_start_date(col) for col in week_cols]
方案2:基于melt思路的修正版
如果需要保留中间长表结构做其他处理,可以用这个方案:
import pandas as pd # 示例数据构造同上 data = [[0,'John',1,2,3]] df = pd.DataFrame(data, columns = ['Index','Owner','32.0','33.0','34.0']) YEAR = 2023 # 宽转长,保留所有标识列 df_melt = df.melt(id_vars=['Index', 'Owner']) # 提取整数周数 df_melt['week_num'] = df_melt['variable'].astype(float).astype(int) # 用ISO周格式转日期,%G=ISO年,%V=ISO周,%u=周几(1代表周一) df_melt['week_start'] = pd.to_datetime(f'{YEAR}' + df_melt['week_num'].astype(str) + '1', format='%G%V%u') # 转回宽表 df_result = df_melt.pivot(index=['Index', 'Owner'], columns='week_start', values='value').reset_index() # 格式化列名为字符串日期 df_result.columns.name = None df_result.columns = ['Index', 'Owner'] + [col.strftime('%Y-%m-%d') for col in df_result.columns[2:]]
注意事项
- 周数和年份强绑定,必须明确指定对应年份才能得到正确的日期
- 如果需要周起始为周日,方案1中将
WEEK_START改为6即可;方案2中将格式符改为%Y%U%w,拼接的周几字符改为0即可 - 跨年周建议用ISO周格式(即方案2的
%G%V%u),避免日期计算偏差
内容的提问来源于stack exchange,提问作者Kris
相关产品推荐
相关产品推荐

