Pandas DataFrame中日期转datetime格式的问题及解决咨询
问题分析与解决方案
首先来说你遇到的两个核心问题:
为什么日期变成了时间戳数值?
当你用pd.to_datetime生成datetime64[ns]类型的日期对象后,直接赋值回原本是object类型的列时,pandas会自动把datetime对象转换成它底层存储的纳秒级整数(就是你看到的一串长数字)。这是因为原列的类型不支持直接存储datetime对象,发生了隐式的类型转换。你遗漏的关键步骤就是:没有把转换后的datetime对象格式化为你需要的%Y-%m-%d %H:%M:%S字符串格式,而是直接把datetime对象塞回了原列。
正确的实现方法
这里有两种方案,根据你的需求选择:
方案一:直接转换为目标格式的字符串(适合仅需要显示格式的场景)
用dt.strftime方法直接把datetime对象格式化为指定字符串,一步到位:
import pandas as pd df2 = pd.DataFrame([ ['2017-18','','','','','','','','','','','',''], ['COMPANIES', '01-APR-2017', '01-MAY-2017', '01-JUN-2017', '01-JULY-2017', '01-AUG-2017', '01-SEP-2017', '01-OCT-2017', '01-NOV-2017', '01-DEC-2017', '01-JAN-2018', '01-FEB-2018', '01-MAR-2018'] ]) # 替换JULY为JUL,匹配datetime的解析格式 df2.iloc[1, 1:] = df2.iloc[1, 1:].str.replace("JULY", "JUL") # 先转datetime,再格式化为目标字符串 df2.iloc[1, 1:] = pd.to_datetime(df2.iloc[1, 1:], format='%d-%b-%Y').dt.strftime('%Y-%m-%d %H:%M:%S')
方案二:保留datetime类型(适合后续需要日期计算的场景)
如果你之后还要对日期做加减、筛选等操作,建议保留datetime类型,只调整显示格式:
import pandas as pd df2 = pd.DataFrame([ ['2017-18','','','','','','','','','','','',''], ['COMPANIES', '01-APR-2017', '01-MAY-2017', '01-JUN-2017', '01-JULY-2017', '01-AUG-2017', '01-SEP-2017', '01-OCT-2017', '01-NOV-2017', '01-DEC-2017', '01-JAN-2018', '01-FEB-2018', '01-MAR-2018'] ]) # 替换JULY为JUL df2.iloc[1, 1:] = df2.iloc[1, 1:].str.replace("JULY", "JUL") # 将对应列转换为datetime类型 df2.loc[1, df2.columns[1:]] = pd.to_datetime(df2.loc[1, df2.columns[1:]], format='%d-%b-%Y') # 设置pandas的全局日期显示格式 pd.options.display.date_format = '%Y-%m-%d %H:%M:%S'
关于循环代码的报错原因
你用datetime.datetime.fromtimestamp(int(i))时出现ValueError,是因为i是纳秒级的时间戳(比如1491004800000000000),而fromtimestamp函数只接受秒级的时间戳。解决方法是先把纳秒数除以1e9转成秒:
import datetime # 注意不要直接遍历值,要遍历索引和值来赋值 for col_idx, val in df2.iloc[1, 1:].items(): sec_timestamp = int(val) / 10**9 df2.iloc[1, col_idx] = datetime.datetime.fromtimestamp(sec_timestamp).strftime('%Y-%m-%d %H:%M:%S')
不过这种循环方法效率很低,处理大数据集时不推荐,优先用前面的矢量化方法。
内容的提问来源于stack exchange,提问作者PratikSharma
相关产品推荐
相关产品推荐

