如何让pandas的read_csv正确处理版本号字符串数据
问题:读取制表符分隔日志文件时,"9.10"被自动转换为"9.1"
问题详情
示例日志数据(制表符分隔)
163.116.197.120 2022-03-01 00:00:00.592 9.8 2493044316 3 en JPN public 10.0.19042 48 64-bit Microsoft Windows 10 Pro 2.0.50727.4927SP2-3.0.30729.4926SP2-3.5.30729.4926SP1-4.8.04084C-4.8.04084 1 181.209.195.130 2022-03-01 00:00:07.049 9.10 2540301398 2 en GTM public 10.0.19043 100 64-bit Microsoft Windows 10 Home局无法ClBBCOMAN尽快人aclDec lifeOUT最少10.0.19043 100 64-bit Microsoft Windows 10 Home Single Language 2.0.50727.4927SP2-3.0.30729.4926SP2-3.5.30729.4926SP1-4.8.04084C-4.8.04084 1 106.117.110.195 2022-03-01 00:00:11.856 9.1 3489778528 3 zh-Hans CHN public 6.1.7601 1 64-bit Microsoft Windows 7 ×0H 2.0.50727.5420SP2-3.0.30729.5420SP2-3.5.30729.5420SP1-4.7.03062C-4.7.03062 1
读取代码
df = pandas.read_csv(in_file, sep="\t", usecols=[0,1,3,6,7], dtype={"IP_Addr": str, "Date": str, "Version": str, "Lang": str, "Country": str, })
异常输出
163.116.197.120 2022-03-01 9.8 en JPN 0 181.209.195.130 2022-03-01 9.1 en GTM 1 106.117.110.195 2022-03-01 9.1 zh-Hans CHN
原数据中的9.10被自动转换为9.1,即使指定了dtype=str或dtype=object也无效。
原因分析
你忽略了read_csv的关键参数header=None:
- pandas默认会将文件第一行识别为表头列名,导致你想要的第一行数据被当成列名,后续行才是DataFrame的内容
- 你在
dtype中指定的自定义列名(如IP_Addr、Version)和DataFrame实际列名(第一行的163.116.197.120等)不匹配,dtype设置完全未生效 - pandas自动对列内容做类型推断,将
9.10识别为浮点数,丢失了末尾的0
解决方案
方法1:指定无表头+自定义列名(推荐)
明确声明文件无表头,同时给选中列指定名称,确保dtype设置生效:
import pandas as pd df = pd.read_csv( in_file, sep="\t", header=None, # 核心:声明文件无表头 usecols=[0, 1, 3, 6, 7], names=["IP_Addr", "Date", "Version", "Lang", "Country"], # 给选中列命名 dtype={ "IP_Addr": str, "Date": str, "Version": str, "Lang": str, "Country": str } )
方法2:使用converters强制转换特定列
如果仅需针对某一列(如Version列)保留字符串格式,可直接对列索引或列名做转换:
df = pd.read_csv( in_file, sep="\t", header=None, usecols=[0,1,3,6,7], names=["IP_Addr", "Date", "Version", "Lang", "Country"], converters={3: str} # 对第3列(Version)强制转为字符串 )
执行后,9.10会以字符串形式完整保留,不会被转换为9.1。
内容的提问来源于stack exchange,提问作者Gergely G
相关产品推荐
相关产品推荐

