使用pandasql处理DBF数据导出txt时出现KeyError错误如何解决
错误原因分析
- 你在将DBF表转为DataFrame时手动指定了
columns=['column1', 'column2', 'column3', 'column4'],直接覆盖了DBF原有的字段名,导致后续SQL查询用到的date、open_time、received等字段全部不存在,pandasql查询不到匹配字段会返回空DataFrame。 - 当
ps.sqldf返回空DataFrame时,你用hour1.iloc[:,0]这种方式取列,空DataFrame没有对应索引就会抛出你遇到的KeyError报错。 - 你最后导出
hour1到txt的时候,列数和顺序和你期望的输出格式不匹配,还多余添加了name列。
修复方案
首先读取DBF时不要硬编码列名,确认所有字段名正确,再添加空查询的兜底逻辑,最后调整导出逻辑即可。修正后的完整代码如下:
from dbf import Table import pandas as pd import pandasql as ps # 1. 正确读取DBF文件,保留原有字段 dfPath1 = Table('filename.dbf') dfPath1.open() df1 = pd.DataFrame(dfPath1) # 若不确定字段名可解开下面注释,打印确认有date、open_time、session_no等需要的字段 # print(df1.columns) # 替换为你实际要查询的日期、name变量值 query_date = '2020-01-01' name = '自定义name值' # 2. 封装重复的小时查询逻辑,避免冗余代码 def get_hourly_data(hour): start_time = f"{hour:02d}:00:00" end_time = f"{hour:02d}:59:59" sales_col = f'sales_for_{hour}am' if hour !=0 else 'sales_for_12am' sql = f""" Select df1.date, df1.session_no AS session_number, SUM(df1.received) AS {sales_col}, SUM(df1.taxes)+SUM(df1.auto_grat)+SUM(df1.discount) AS gross_vat_sales, SUM(df1.taxes) AS total_vat, SUM(df1.discount) AS discount, SUM(df1.auto_grat) AS service_charge From df1 Where open_time >= '{start_time}' And open_time < '{end_time}' And date = '{query_date}' """ res = ps.sqldf(sql).fillna(0) # 空查询兜底:没有匹配数据时构造一行全0默认数据,避免取列报错 if res.empty: res = pd.DataFrame([[query_date, 0, 0.0, 0.0, 0.0, 0.0, 0.0]], columns=['date','session_number',sales_col,'gross_vat_sales','total_vat','discount','service_charge']) return res # 查询0-4点共5个小时的数据 hour_data = [get_hourly_data(i) for i in range(5)] # 3. 按要求格式导出txt,不要表头、索引,用空格分隔 output_df = hour_data[0][['date', 'session_number', 'sales_for_12am', 'gross_vat_sales', 'total_vat', 'discount', 'service_charge']] output_df.to_csv('sample_output.txt', index=False, sep=' ', header=False)
补充说明
如果需要导出多个小时的结果,只需要循环hour_data列表把所有行合并后再导出即可;如果DBF里的字段名和SQL里用的不一致,把SQL里的字段名替换成df1.columns打印出来的实际字段名即可。
内容的提问来源于stack exchange,提问作者Arvin Tuzki
相关产品推荐
相关产品推荐

