pandas合并CSV时Date Time列自定义日期格式导出异常
问题背景
需求为合并代码运行目录下的所有CSV文件,要求所有文件的Date Time列统一采用 m/d/yyyy h:mm:ss.0 格式,日期格式调整逻辑位于代码末尾。
当前代码运行时,控制台通过print打印的Date Time列结果完全符合预期格式,但导出的CSV文件打开后显示异常:
- 格式化规则末尾保留
.0时,文件内该列格式显示为 mm:ss.0 - 移除格式化规则末尾的
.0时,文件内列格式显示正常,但仅记录到分钟位,秒数部分被完全截断
现有实现代码
import os import pandas as pd import glob # returns all data after header in panda DataFrame def skip_to(fle, line): if os.stat(fle).st_size == 0: raise ValueError("File is empty") with open(fle, 'r') as f: if check(fle, line): pos = 0 cur_line = f.readline() while not cur_line.startswith(line): pos = f.tell() # add current line to header dataframe cur_line = f.readline() f.seek(pos) return pd.read_csv(f, parse_dates=[line], na_values=['Unknown']) else: return "" def check(myfile, myline): with open(myfile, 'r') as f: datafile = f.readlines() for line in datafile: if myline in line: return True return False # finished the search without finding # getting all csv files for concatenation current_dir = os.getcwd() files = [fn for fn in glob.glob(current_dir + '\**\\' + 'cdlog*.csv', recursive=True)] df = pd.DataFrame() for file in files: if file.endswith('.csv'): dp_data = skip_to(file, "Date Time") if type(dp_data) != str: dp_data.drop(0, axis=0, inplace=True) df = pd.concat([df, dp_data], ignore_index=True, axis=0) df['Date Time'] = pd.to_datetime(df['Date Time']) df['Date Time'] = df['Date Time'].dt.strftime('%m/%d/%Y %H:%M:%S.0') print(df['Date Time']) # export to .csv df.to_csv("test_output.csv")
异常效果示例
- 格式化规则带
.0时的显示效果:
- 格式化规则不带
.0时的显示效果:
问题原因
这个问题和pandas导出逻辑无关,是Excel打开CSV时的自动格式识别机制导致的显示异常:CSV是纯文本格式,本身不存储单元格格式信息,Excel打开时会自动对内容做类型判断,将符合日期规则的字符串自动转换为Excel内置的日期类型,再套用默认的日期显示格式,最终出现显示错乱。用纯文本编辑器(比如记事本、VS Code)打开导出的test_output.csv就能验证,文件里存储的日期字符串完全是设置的正确格式。
解决方案
根据使用场景选对应方案即可:
- 如果导出的CSV只用于程序读取、不需要用Excel人工查看:不需要做任何修改,当前导出的文件内容完全正确,程序读取时可以正常解析。
- 如果需要用Excel打开查看且不需要后续二次处理:给日期字符串前加一个单引号,强制Excel将其识别为纯文本,不会自动做日期转换,修改对应格式化代码行即可:
df['Date Time'] = "'" + df['Date Time'].dt.strftime('%m/%d/%Y %H:%M:%S.0') - 如果需要兼顾Excel查看和格式正确性:不要导出为CSV格式,改为导出xlsx格式,直接在导出时指定单元格的日期显示格式,从根源避免Excel自动识别乱改格式。注意用这个方案时不要提前把
Date Time列转成字符串,保留其datetime类型即可,用以下代码替换原有的格式化+导出逻辑:# 保留datetime类型,不要转字符串 df['Date Time'] = pd.to_datetime(df['Date Time']) # 导出为xlsx时指定日期格式 with pd.ExcelWriter("test_output.xlsx", engine='openpyxl', datetime_format='m/d/yyyy h:mm:ss.0') as writer: df.to_excel(writer, index=False)
额外提示:原代码里用dir作为变量名是不推荐的写法,dir是Python内置函数,直接赋值覆盖容易引发意料之外的问题,建议改成current_dir这类自定义名称。
内容的提问来源于stack exchange,提问作者jakewags01
相关产品推荐
相关产品推荐

