使用pandas读取S3存储桶CSV文件时如何保留原有数据类型
解决pandas读取CSV丢失前导0并转为float的问题
问题根因
pandas读取CSV时默认开启自动类型推断,对于带前导0的数字编码类字段,会被误识别为数值类型:
- 前导0会被直接截断
- 若字段存在空值,int类型无法存储空值,会被强制升级为float64类型,最终出现末尾带
.0的异常格式
最优解决方案
该类带前导0的字段(如账号、编码)本质为业务标识,不会用于数值计算,建议读取时强制指定为字符串类型,从根源避免类型转换异常。
修改后的代码示例
export_csv = client.get_object(Bucket = s3_bucket, Key = bo_file_name) bo_body = export_csv['Body'] csv_string = bo_body.read().decode('utf-8') # 仅需在read_csv中添加dtype参数,指定需要保留前导0的字段为字符串类型即可 bo_df = pd.read_csv( StringIO(csv_string), sep = '|', quotechar = '"', dtype={ 'actnum': str, # 可添加多个同类型字段,比如 'id_card': str } ) # 后续fillna逻辑不受影响 print('removing nulls from df') bo_df.fillna('', inplace = True) sql_server = os.getenv('DB_ENDPOINT')
扩展场景
如果所有字段都不需要自动类型推断,希望全部以原始字符串格式读取,可以直接将dtype设为全局字符串:
bo_df = pd.read_csv(StringIO(csv_string), sep = '|', quotechar = '"', dtype=str)
其他可选方案
如果确实需要保留数值类型,仅在输出/入库时补全前导0,可以在读出后格式化字段:
# 假设账号固定为9位,补前导0到9位,再转为字符串 bo_df['actnum'] = bo_df['actnum'].apply(lambda x: f'{int(x):09d}' if pd.notna(x) else '')
注:该方案仅适用于字段无异常非数值内容的场景,稳定性不如直接指定读取为字符串的方案
内容的提问来源于stack exchange,提问作者pass_the_kavasier
相关产品推荐
相关产品推荐

