如何将DataFrame的日期索引转换为字符串?及批量获取商品历史API数据的优化问询
解决API批量获取商品历史价格的两个核心问题
一、获取并转换DataFrame最后一行的索引日期
你之前用df.iloc[-1,0]拿到商品代码是因为iloc是按位置取行列值,而你要的是作为索引的日期,得换个方式操作:
正确步骤:
- 提取最后一行的索引:直接取索引的最后一个元素,这会返回对应的日期对象(如果你的索引是
datetime类型):last_date_obj = df.index[-1] - 转换为
YYYY-MM-DD格式的字符串:- 如果索引是
datetime64类型,用strftime方法格式化:last_date_str = last_date_obj.strftime('%Y-%m-%d') - 如果索引本身就是字符串类型,直接赋值即可:
last_date_str = df.index[-1]
- 如果索引是
- 删除该日期的所有行:
df = df.drop(last_date_str)
现在last_date_str就是你需要传入下一次API调用的endDate参数了。
二、更优的批量获取+去重方案
你当前删除不完整日期的思路是对的,这里给你优化流程,让批量获取更自动化且避免重复:
1. 先验证日期完整性(避免误删完整数据)
在删除最后一天前,先判断这一天的数据是否完整——比如假设每个完整日期应该包含所有商品(symbol)的数据,你可以统计每日商品数量对比基准值:
# 获取完整日期应有的商品数量(取第一个完整日期的数量作为基准) full_symbol_count = df.groupby(level=0).count().iloc[0, 0] # 统计最后一天的商品数量 last_day_count = df.groupby(level=0).count().iloc[-1, 0] if last_day_count < full_symbol_count: # 最后一天数据不完整,删除并记录该日期为下一次的endDate last_date_str = df.index[-1].strftime('%Y-%m-%d') df = df.drop(last_date_str) next_end_date = last_date_str else: # 最后一天数据完整,下一次取前一天作为endDate(避免重复获取) from datetime import timedelta next_end_date = (df.index[-1] - timedelta(days=1)).strftime('%Y-%m-%d')
2. 批量追加数据时的去重保障
每次获取新数据后,直接和总数据合并即可(因为是从新到旧获取,日期范围天然不重叠),但为了保险,可以基于「日期+商品代码」去重:
# 假设total_df是存储所有历史数据的总DataFrame new_df = fetchData(initDate='1975-01-01', endDate=next_end_date, output_type='df') # 先处理new_df的不完整日期(同上验证步骤) # 合并数据 total_df = pd.concat([total_df, new_df]) # 去重:保留最新的重复记录(这里是较早的日期数据) total_df = total_df.reset_index().drop_duplicates(subset=['index', 'symbol'], keep='last').set_index('index')
3. 完整自动循环获取示例
import pandas as pd from datetime import timedelta # 初始化总数据和起始参数 total_df = pd.DataFrame() current_end_date = None # 第一次调用无需传入endDate while True: # 调用API获取数据 if current_end_date: df = fetchData(initDate='1975-01-01', endDate=current_end_date, output_type='df') else: df = fetchData(initDate='1975-01-01', output_type='df') # 空DataFrame说明没有更多数据,退出循环 if df.empty: break # 验证最后一天数据完整性 full_symbol_count = df.groupby(level=0).count().iloc[0, 0] last_day_count = df.groupby(level=0).count().iloc[-1, 0] if last_day_count < full_symbol_count: current_end_date = df.index[-1].strftime('%Y-%m-%d') df = df.drop(current_end_date) else: current_end_date = (df.index[-1] - timedelta(days=1)).strftime('%Y-%m-%d') # 追加到总数据并去重 total_df = pd.concat([total_df, df]) total_df = total_df.reset_index().drop_duplicates(subset=['index', 'symbol'], keep='last').set_index('index') # 打印进度(可选) print(f"已获取至日期: {current_end_date}")
这个流程会自动循环获取所有完整的历史数据,无需手动干预,也不会产生重复记录。
内容的提问来源于stack exchange,提问作者Charles Leblanc
相关产品推荐
相关产品推荐

