如何通过pd.read_csv在读取阶段仅选取数值类型列
pd.read_csv阶段直接加载数值类型列的实现思路 首先明确:pandas的pd.read_csv本身没有内置的“按数值类型规则直接筛选列加载”的一键参数,但完全可以通过几种零依赖的工程化方案,在文件读取阶段就完成数值列的筛选,省去读完全量再跑select_dtypes的步骤,尤其在大文件场景下能大幅降低内存占用、提升处理效率。
- 方法1:样本预判+usecols参数直接加载(最常用、开销最低)
逻辑是先读取极少量的文件样本预判所有列的类型,筛选出数值列的列名后,直接传给正式加载环节的usecols参数,实现全量读取时跳过非数值列。
示例代码:
适用场景:列类型稳定的常规业务CSV,整个预判过程的额外耗时不到正式读全量的1%,处理效率远高于读完全量再筛选列的模式。import pandas as pd # 读取前100行作为样本预判列类型(常规CSV的列类型在前100行即可准确识别) sample = pd.read_csv("target.csv", nrows=100) numeric_cols = sample.select_dtypes(include="number").columns.tolist() # 正式加载全量数据时,仅读取筛选出的数值列 df_numeric = pd.read_csv("target.csv", usecols=numeric_cols) - 方法2:固定schema下的静态列指定(生产环境最高效)
如果数据源的列结构长期固定、列类型不会频繁变动,完全不需要做动态预判,直接把确认属于数值类型的列名整理成列表,传给usecols参数即可。生产环境中如果搭配dtype参数预先指定列类型,还能避免pandas自动类型推断的额外开销。
示例代码:# 预先确认的数值列列表与对应数据类型 expected_dtypes = { "user_id": "int64", "age": "float64", "purchase_amt": "float64", "visit_duration": "float64" } # 直接按指定列加载,全程不需要读取非数值列 df_numeric = pd.read_csv( "target.csv", usecols=expected_dtypes.keys(), dtype=expected_dtypes ) - 方法3:逐块读取的动态筛选(适用于列类型不确定的超大文件)
如果文件规模极大、且列类型存在前置样本无法覆盖的情况(比如前数百行是空值,后续才出现数值内容),可以用逐块读取的方式,在每个数据块的处理环节就筛掉非数值列。这种模式下非数值内容不会被保留到最终的内存对象中,和“读取阶段直接筛选”的资源消耗基本无差别,不会出现一次性读全量文件再筛列导致的内存溢出问题。
示例代码:numeric_chunk_store = [] # 每10万行作为一个独立处理块 for chunk in pd.read_csv("large_target.csv", chunksize=100000): # 每个块内仅保留数值列,非数值列处理完即丢弃 numeric_chunk_store.append(chunk.select_dtypes(include="number")) # 拼合所有保留的数值列块得到最终数据 df_numeric = pd.concat(numeric_chunk_store, ignore_index=True)
常见认知澄清
截至pandas 2.x版本,官方并未在read_csv接口中提供类似usecols="number"这类按类型规则筛选列的内置参数,上述所有实现都是基于pandas原生的usecols列指定、chunksize逐块读取两个核心能力组合实现的,不需要引入第三方库或额外依赖。
内容的提问来源于stack exchange,提问作者Bex T.
相关产品推荐
相关产品推荐

