新手求助:如何遍历DataFrame行生成符合日期规则的新DataFrame?
问题需求
我从来没用过循环,不清楚循环的作用,也不知道要不要用循环完成这个任务。现在我有一个包含ValueDate和MaturityDate两列的DataFrame(原始数据来自BDebt),需要生成一个新的DataFrame:
- 生成从BDebt中的最小日期到当前日期(today())的所有日期作为
ReportDate - 每个
ReportDate都要匹配所有满足ReportDate >= ValueDate且ReportDate < MaturityDate的原数据行,将ReportDate和对应的原数据行合并
输入数据示例
HSBC 500 1-Jan 5-Jan JPMO 750 2-Jan 4-Jan CITI 230 3-Jan 4-Jan
(注:列对应为「机构名、金额、ValueDate、MaturityDate」)
期望输出示例
1-Jan HSBC 500 1-Jan 5-Jan 2-Jan HSBC 500 1-Jan 5-Jan 2-Jan JPMO 750 2-Jan 4-Jan 3-Jan HSBC 500 1-Jan 5-Jan 3-Jan JPMO 750 2-Jan 4-Jan 3-Jan CITI 230 3-Jan 4-Jan 4-Jan HSBC 500 1-Jan 5-Jan
解决方案(无需循环)
用Pandas的矢量化操作就能完成,完全不需要写循环,步骤如下:
- 预处理日期列:将
ValueDate和MaturityDate转换为日期类型,确保能进行日期比较 - 生成ReportDate序列:从BDebt的最小日期到今天生成连续日期
- 交叉合并+筛选:将原DataFrame和ReportDate序列交叉合并,再筛选符合条件的行
具体代码示例
import pandas as pd from datetime import date # 模拟原始数据(实际使用时可直接读取BDebt数据) data = [ ["HSBC", 500, "1-Jan", "5-Jan"], ["JPMO", 750, "2-Jan", "4-Jan"], ["CITI", 230, "3-Jan", "4-Jan"] ] BDebt = pd.DataFrame(data, columns=["Institution", "Amount", "ValueDate", "MaturityDate"]) # 转换日期列(假设年份为当前年,可根据实际数据调整格式) current_year = date.today().year BDebt["ValueDate"] = pd.to_datetime(BDebt["ValueDate"] + f"-{current_year}", format="%d-%b-%Y") BDebt["MaturityDate"] = pd.to_datetime(BDebt["MaturityDate"] + f"-{current_year}", format="%d-%b-%Y") # 生成连续的ReportDate序列 min_date = BDebt["ValueDate"].min() today = pd.to_datetime(date.today()) report_dates = pd.DataFrame({"ReportDate": pd.date_range(start=min_date, end=today)}) # 交叉合并所有ReportDate与原数据 merged = report_dates.merge(BDebt, how="cross") # 筛选符合条件的行 result = merged[(merged["ReportDate"] >= merged["ValueDate"]) & (merged["ReportDate"] < merged["MaturityDate"])] # 格式化日期为示例中的字符串格式 result["ReportDate"] = result["ReportDate"].dt.strftime("%d-%b") result["ValueDate"] = result["ValueDate"].dt.strftime("%d-%b") result["MaturityDate"] = result["MaturityDate"].dt.strftime("%d-%b") # 按ReportDate排序后输出 result = result.sort_values("ReportDate") print(result.to_string(index=False, header=False))
代码说明
- 用
pd.date_range自动生成连续日期,无需手动循环创建日期列表 - 用
merge(how="cross")实现原数据与所有ReportDate的全组合,这是矢量化操作,比循环遍历高效得多 - 最后用布尔索引筛选符合条件的行,同样是矢量化操作,性能远优于循环
内容的提问来源于stack exchange,提问作者Matias Ochoa
相关产品推荐
相关产品推荐

