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

Pandas如何实现DataFrame按日索引、Topic转列并匹配对应数值

问题场景

现有包含Date、Val、Topic三列的DataFrame对象df,需要构建新DataFramedf1满足以下要求:

  • 以自然日作为行索引
  • 每个Topic的唯一取值作为单独列
  • 列中存储对应Topic在当日的数值

用户初始尝试代码如下:

import numpy as np 
import pandas as pd 
import random

rng = pd.date_range('2015-02-24', periods=50, freq='H')
TOPIC=np.random.choice(5, len(rng), replace=True)

df = pd.DataFrame({ 'Date': rng, 'Val' : np.random.randn(len(rng)),'Topic':TOPIC}) 
columns=df.Topic.unique()
df1=pd.DataFrame(columns=columns)
df1['Date']=df['Date']
df1.set_index('Date',inplace=True)
df1=df1.resample('D').ffill()
df1
实现方案

直接使用pandas透视表功能即可完成长表转宽表+按日维度聚合的逻辑,无需手动创建空表后逐列匹配。

  1. 首先将原始小时级的Date字段归一到自然日粒度,推荐使用dt.normalize()保留datetime类型,方便后续时间序列操作
  2. 调用pivot_table完成结构转换,注意如果同一天同一Topic存在多条记录,需要指定对应的聚合规则(求和、取均值、取首尾值均可,按业务需求选择)

可直接运行的参考代码:

import numpy as np 
import pandas as pd 

# 构造示例数据
rng = pd.date_range('2015-02-24', periods=50, freq='H')
TOPIC = np.random.choice(5, len(rng), replace=True)
df = pd.DataFrame({'Date': rng, 'Val': np.random.randn(len(rng)), 'Topic': TOPIC}) 

# 核心转换逻辑
# 提取自然日维度
df['day'] = df['Date'].dt.normalize()
# 透视生成目标结构
df1 = df.pivot_table(
    index='day',
    columns='Topic',
    values='Val',
    aggfunc='mean'  # 聚合规则可按需替换为sum、last、first等
).resample('D').ffill()  # 补全无数据的自然日,不需要可删除该行

df1

说明

  • 若业务上同一天同一Topic只会存在一条有效值,可将aggfunc设置为first,或直接使用df.pivot(index='day', columns='Topic', values='Val')实现,不会触发聚合计算
  • 初始代码的问题是仅创建了带列名和索引的空表,没有完成日期、Topic和Val三者的映射匹配,因此所有Topic列最终都会是空值
  • 末尾的resample('D').ffill()作用是补全时间序列中没有任何数据的自然日,用前一个最近有效值填充,不需要连续时间索引可以删除该段逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 23:27:28