如何在Pandas DataFrame中为每个Name生成前一日Value列?
如何为DataFrame添加对应姓名前一日的数值列
你的需求核心是按姓名分组,获取每组内前一天的数值,不需要额外生成Yesterday Date列再去匹配,用groupby结合shift就能高效解决,步骤如下:
最优方案:GroupBy + Shift
这种方法是向量式操作,比apply或merge效率高得多,尤其适合大数据量:
import pandas as pd # 确保Date列是datetime格式(你已经做过这步,这里再确认) df["Date"] = pd.to_datetime(df["Date"]) # 1. 先按姓名、日期排序,保证每组内日期顺序正确 df = df.sort_values(by=["Name", "Date"]) # 2. 按姓名分组,对Value列执行shift(1),得到前一行(即前一天)的数值 df["Yesterday Value"] = df.groupby("Name")["Value"].shift(1)
原理说明
sort_values(["Name", "Date"]):把同一个姓名的行按日期从小到大排列,确保shift时取到的是前一天的数据(因为Date+Name唯一,每组内日期无重复)。groupby("Name")["Value"].shift(1):对每个姓名组单独处理,shift(1)会把组内的Value向下移动一行,当前行就对应上一行的数值——也就是该姓名前一天的Value;如果某行是该姓名的最早日期,会填充NaN(符合逻辑,因为没有前一天的数据)。
保留原始行顺序的处理方式
如果不想改变原始DataFrame的行顺序,可以先保存索引,处理后再恢复:
# 保存原始索引 df = df.reset_index(drop=False) # 排序、分组、生成新列 df = df.sort_values(by=["Name", "Date"]) df["Yesterday Value"] = df.groupby("Name")["Value"].shift(1) # 恢复原始顺序并清理临时列 df = df.sort_values(by="index").drop("index", axis=1).reset_index(drop=True)
替代方案:Merge匹配(不推荐,效率低)
如果你坚持用之前生成Yesterday Date的思路,也可以通过merge实现,但数据量大时性能不如上面的方法:
from datetime import timedelta df["Date"] = pd.to_datetime(df["Date"]) df["Yesterday Date"] = df["Date"] + timedelta(days=-1) # 创建临时表,把Date映射为Yesterday Date,Value映射为Yesterday Value temp_df = df[["Name", "Date", "Value"]].rename(columns={ "Date": "Yesterday Date", "Value": "Yesterday Value" }) # 左连接匹配姓名和前一天日期 df = df.merge(temp_df, on=["Name", "Yesterday Date"], how="left")
为什么你的apply方法没成功?
apply(axis=1)是逐行遍历,需要对每行去查找对应姓名+前一天日期的行,不仅代码繁琐,而且时间复杂度是O(n²),数据量大时会非常慢。而groupby+shift是基于Pandas的向量优化操作,时间复杂度接近O(n),更简洁高效。
内容的提问来源于stack exchange,提问作者aheHkartA
相关产品推荐
相关产品推荐

