如何将含起止datetime列的DataFrame转为单日期列并按天拆分数据?
嘿,这个问题我之前也碰到过!要把带时间区间的DataFrame拆成单日记录,还得按比例分配像deep这类数值对吧?别慌,用Pandas几步就能搞定,我给你一步步捋清楚:
解决思路与实现步骤
核心逻辑就是:先把每个时间区间拆成包含的所有单日,再根据区间总天数计算分配比例,最后把原数值拆分到对应的日期行里。
1. 先整个示例数据
我先构造一个和你需求匹配的DataFrame,方便演示:
import pandas as pd # 模拟你的原始数据 data = { "from": ["2015-07-06 00:00:00", "2015-07-08 00:00:00"], "to": ["2015-07-09 00:00:00", "2015-07-10 00:00:00"], "deep": [30, 20] } df = pd.DataFrame(data) # 把字符串转成datetime类型,这步必不可少 df["from"] = pd.to_datetime(df["from"]) df["to"] = pd.to_datetime(df["to"])
比如第一行的区间是2015-07-06到2015-07-09(注意这里to是次日0点,实际覆盖6、7、8号三天),deep值30,那每天就得分到10;第二行覆盖8、9号两天,deep20,每天分10。
2. 拆分时间区间,生成单日序列
我们用apply给每行生成对应的日期列表,再把行展开:
# 写个小函数,给每行生成区间内的所有日期 def get_daily_dates(row): # 重点:如果你的"to"是区间结束后的次日0点,必须减1天,不然会多算一天 return pd.date_range(start=row["from"], end=row["to"] - pd.Timedelta(days=1), freq="D") # 给每行添加上对应的日期列表 df["dates"] = df.apply(get_daily_dates, axis=1) # 把列表拆成单独的行,这步是关键! df_expanded = df.explode("dates", ignore_index=True)
执行完这步,原来的每一行已经变成了N行,N就是区间的天数。
3. 计算比例,拆分数值
接下来算每个原区间的总天数,再把deep按比例分配到每一天:
# 先给原始DF加上总天数列 df["total_days"] = (df["to"] - df["from"]).dt.days # 把总天数合并到展开后的DF里 df_expanded = df_expanded.merge(df[["from", "to", "total_days"]], on=["from", "to"], how="left") # 计算每天的deep值 df_expanded["daily_deep"] = df_expanded["deep"] / df_expanded["total_days"]
4. 整理成你要的最终格式
如果你想把日期设为索引,或者删掉没用的列,最后再调整下:
# 保留需要的列,重命名回原来的"deep" final_df = df_expanded[["dates", "daily_deep"]].rename(columns={"daily_deep": "deep"}) # 把日期设为索引(可选,看你需求) final_df = final_df.set_index("dates")
现在final_df就是你想要的结构:单个日期(或日期索引),deep列是按天拆分后的数值。
额外提一句特殊情况
如果你的时间区间不是整整天(比如from是中午12点,to是后天中午12点),那可以按小时甚至分钟来拆分,只需要把freq改成"H"或者"T",总天数换成总小时数/分钟数,逻辑完全一样~
内容的提问来源于stack exchange,提问作者BlandCorporation
相关产品推荐
相关产品推荐

