我对Pandas DataFrame关于Dtype检测的行为感到非常困扰。
我使用' read_sql_query'从数据库中检索数据以构建DataFrame,然后将其转储到csv文件中。
我不需要任何改造。只需将其转储到csv文件中并更改表单中的日期字段:'%d /%m /%Y'
但是:
self.dataframe.to_csv(self.fic,
index=False,
header=False,
sep='|',
mode='a',
encoding='utf-8',
line_terminator='\n',
date_format='%d/%m/%Y
)
会错过转换/格式化某些日期字段...
我试图用另一种方式做到:
l = list(self.dataframe.select_dtypes(include=['datetime64']).columns)
for i in l:
self.dataframe[i] = self.dataframe[i].dt.strftime('%d/%m/%Y')
我很满意,但是更多的测试显示出一种奇怪的行为:
如果我的sql请求只选择了两个nuplet:
requete = 'select * from DOMMAGE_INTERET where doi_id in (176433, 181564)'
无论在csv或DataFrame中形成什么,一切都有效。
它正确检测日期字段:
df.dtypes
doi_id int64
aff_id int64
pdo_id int64
doi_date_decision datetime64[ns]
doi_date_mod datetime64[ns]
doi_montant float64
doi_reste_a_payer object
doi_appliquer_taux int64
doi_date_update datetime64[ns]
afg_id int64
dtype: object
但使用其他选择时
requete = 'select * from DOMMAGE_INTERET where rownum < 100'
再次错过了。实际上,字段类型的检测方式不同:
doi_id int64
aff_id int64
pdo_id int64
doi_date_decision object
doi_date_mod datetime64[ns]
doi_montant float64
doi_reste_a_payer object
doi_appliquer_taux int64
doi_date_update datetime64[ns]
afg_id int64
dtype: object
正如您所看到的:&#39; doi_date_decision&#39;类型确实根据请求选择而改变但当然,这是一组相同的数据!!!
难道不奇怪吗?
您对这种行为有解释吗?
答案 0 :(得分:2)
您的to-csv
操作未转换所有指定的日期字段,因为正如您所提到的,并非所有日期时间列都以日期时间格式读入,而是在当前数据框中显示为字符串( object dtype) 。这是从外部源读取的不幸副作用,因为导入的系统 - 包括Python,SAS,Stata,R,Excel等 - 除非另外明确定义,否则尝试通过前几行定义列。
幸运的是,pandas的read_sql_query()
维护了parse_dates
的参数。因此,请考虑在读取操作期间定义日期,因为此参数采用列表或字典:
df = read_sql_query('select * from DOMMAGE_INTERET where rownum < 100', engine,
parse_dates = ['doi_date_decision', 'doi_date_mod', 'doi_date_update'])
或者,在阅读之前和to_csv
之前使用pd.to_datetime()
进行转化:
df['doi_date_decision'] = pd.to_datetime(df['doi_date_decision'])
大多数RDMS都以YYYY-MM-DD HH:MM:SS
格式维护日期时间,与pandas格式保持一致。
答案 1 :(得分:1)
如果没有一些数据样本,很难深入研究您的问题。但是,您可能会遇到以下两种情况之一:
NULL
值,这会阻止pandas将您的列自动解释为日期时间答案 2 :(得分:0)
感谢Boud和Parfait。他们的答案是正确的:
我的所有测试都显示缺少日期字段会使Dtype检测失败。
read_sql_query()有一个参数来定义具有日期类型的字段。我想要解决这个问题。
可悲的是,从现在开始,我一直在使用完整的通用处理来处理数百个表格。 使用'read_sql_query'参数'parse_dates'意味着先做元数据定义工作(比如描述每个表的json文件)。
实际上,我还发现当列中有NaN字段时,整数会更改为浮点数...
如果我要阅读csv平面文件,我可以理解数据类型很难检测......但是来自数据库(read_sql_query)!熊猫有SqlAlchelmy作为依赖。而SqlAlchemy(甚至任何较低级别的Python数据库驱动程序(cx_Oracle,DB API))都具有检测数据类型的反射机制。 Pandas可能一直在使用这些元数据来保持数据类型的完整性。