Pandas read_csv() Python 与例子

⚡ 智能摘要

Pandas 的 read_csv() 函数只需一次调用即可将逗号分隔的本地或远程文件转换为 DataFrame。本教程将导入 UCI 成人人口普查数据集,为其十五列命名,并使用 groupby 聚合函数汇总结果。

  • 🔘 一个电话: pd.read_csv() 接受一个文件路径和一个 URL或者任何公开 read 方法的对象。
  • ☑️ 列控制: 传递名称以标记列,并将 index_col=False 保留为普通整数索引。
  • ✅ 空白: skipinitialspace=True 会删除成人数据集中每个逗号后面的空格。
  • 🧪 分组和聚合: groupby() 使用计数、最小值、最大值、平均值、中位数或标准差对帧进行汇总。
  • 🛠️ 大文件: usecols、dtype 和 chunksize 可以减少多 GB 导出数据的解析时间和内存占用。
  • ⚠️ 常见错误: 编码错误、行错误和混合数据类型错误都有相应的修复参数。

Pandas read_csv() 与示例

在 Pandas 中导入 CSV

在 TensorFlow 教程中,您将使用 成人数据集它常用于分类任务。下面使用的文件是原始数据。 adult.data 可以从 UCI 机器学习库导出数据集,数据集页面也提供压缩包下载。 ucimlrepo 如果直接路径无法解析,则打包。

数据以 CSV 格式存储。该数据集包含 8 个分类变量:

  • 工人阶级
  • 教育
  • 婚姻
  • 占用
  • 关系
  • 种族
  • 性别
  • 祖国

以及 6 个连续变量:

  • 年龄
  • 风车
  • 教育编号
  • 资本收益
  • 资本损失
  • hours_week

连同收入 label 列,这将构成你要传递给的 15 个列名。 熊猫 在下一节。

Pandas read_csv() 方法

要导入 CSV 数据集,可以使用 `pd.read_csv()` 对象。其基本签名如下:

Pandas read_csv() 语法

pandas.read_csv(filepath_or_buffer, sep=',', names=None, index_col=None, skipinitialspace=False)
  • 文件路径或缓冲区: 小路, URL或者,保存数据的类文件对象
  • 分隔符=','要使用的分隔符
  • 名称=无:为列命名。如果数据集有十列,则需要提供十个列名。
  • index_col=无:要用作行索引的列。传递 False 可强制使用新的整数索引。
  • skipinitialspace=False:跳过分隔符后的空格

完整的论点列表请查看官方文件。 pandas.read_csv() 文档.

Pandas read_csv() 示例

下面的代码片段列出了所有 15 列,指向 UCI 文件,并删除了此特定数据集中每个逗号后面的空格。

## Import csv
import pandas as pd
## Define path data
COLUMNS = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital',
           'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss',
           'hours_week', 'native_country', 'label']
PATH = "https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data"
df_train = pd.read_csv(PATH,
                       skipinitialspace=True,
                       names = COLUMNS,
                       index_col=False)
df_train.shape

输出:

(32561, 15)

该形状确认有 32,561 行和 15 列,因此 COLUMNS 中的每个名称都与文件中的一个字段匹配。

Pandas read_csv() 函数的关键参数

`read_csv()` 函数接受超过五十个参数,但其中一小部分几乎涵盖了所有实际导入操作。以下列出的默认值均来自最新的 pandas API 文档。

参数 默认 它做什么
九月 '' 用作分隔符的字符或正则表达式。对于其他格式,请使用 sep=';' 或 sep='\t'。
头 '推断' 包含列标签的行号。如果文件没有标题行,则传递 header=None。
名称 没有设置 列标签的显式列表。与 header=0 结合使用可替换现有标题。
index_col 没有 用作行索引的列。index_col=False 强制使用普通整数索引。
使用列 没有 按标签或位置加载列子集。这样可以减少解析时间和内存占用。
数据类型 没有 列数据类型,例如 {'age': 'int32'}。跳过类型推断。
na_values 没有 需要读取为 NaN 的额外字符串,例如成人数据集中的“?”占位符。
跳过行数 / 行数 没有 跳过前几行,或者只读取前 N 行数据。
解析日期 没有 读取时要转换为日期时间的列,与 date_format 配对。
编码 'utf-8' 文件文本编码。对于旧版导出文件,请使用“latin-1”或“cp1252”。
块大小 没有 返回一个迭代器,该迭代器以 N 行为单位生成文件块。
on_bad_lines '错误' 如何处理格式错误的行:引发错误、发出警告或跳过它们。

其中两点值得特别说明。 index_col=False 这与不设置该值不同:它明确地告诉 Pandas 不要提升第一列,这正是当文件每行都以一个多余的分隔符结尾时所需要的。 names 会静默覆盖文件中声明的任何内容,所以请忽略。 header=0 当 CSV 文件确实包含标题行时,它会显示出来。

Pandas groupby() 方法

查看数据的简便方法是使用 groupby 方法。此方法可以帮助您按组汇总数据。以下是 groupby() 方法可用的聚合列表:

  • 计数:计数
  • 分钟: 分钟
  • 最大:最大
  • 平均值:平均值
  • 中位数:中位数
  • 标准差:std
  • 和别的

在 groupby() 函数内部,你需要在应用聚合之前指定要分组的列。

让我们来看一个单独的组ping 使用成人数据集,您将获得所有连续变量按收入类型(高于 50 万美元或低于 50 万美元)划分的平均值:

df_train.groupby(['label']).mean()
标签 年龄 风车 教育编号 资本收益 资本损失 hours_week
<= 50K 36.783738 190340.86517 9.595065 148.752468 53.142921 38.840210
> 50K 44.249841 188005.00000 11.611657 4006.142456 195.001530 45.473026

您可以根据家庭类型获取最低年龄要求:

df_train.groupby(['label'])['age'].min()
label
<=50K    17
>50K     19
Name: age, dtype: int64

您还可以按多个列进行分组。例如,您可以根据家庭类型和婚姻状况获得最大资本收益。

df_train.groupby(['label', 'marital'])['capital_gain'].max()
label  marital
<=50K  Divorced                 34095
       Married-AF-spouse         2653
       Married-civ-spouse       41310
       Married-spouse-absent     6849
       Never-married            34095
       Separated                 7443
       Widowed                   6849
>50K   Divorced                 99999
       Married-AF-spouse         7298
       Married-civ-spouse       99999
       Married-spouse-absent    99999
       Never-married            99999
       Separated                99999
       Widowed                  99999
Name: capital_gain, dtype: int64

在进行分组后,您可以创建图表。一种方法是直接绘制分组结果。

为了生成更清晰的图表,请在调用 mean() 函数后使用 unstack() 函数,这样婚姻状况就会从索引移到列中。图表随后会分成两组,分别对应不同的收入标签,而不是像扁平的多级索引那样生成十四个(2*7)柱状图。

如果使用 Jupyter 笔记本请记住添加 %matplotlib inline,否则将不会显示任何图表。

%matplotlib inline
df_plot = df_train.groupby(['label', 'marital'])['capital_gain'].mean().unstack()
df_plot

将该未堆叠的帧绘制成柱状图,得到下图。

按收入类别和婚姻状况分组的平均资本收益条形图

如何使用 Pandas 读取大型 CSV 文件

成年数据集虽然很小,但同样的调用却可能导致导出几GB的数据时卡住。三个参数就能完成大部分工作。

  • 使用列 仅加载实际需要的列。pandas 文档指出,这可以显著加快解析速度并降低内存占用。
  • 数据类型 将每一列固定为一个类型,因此 Pandas 会跳过类型推断,并且默认情况下不会将整数扩展为 64 位。
  • 块大小 返回的是 TextFileReader 而不是 DataFrame,这样你就可以遍历 N 行的数据块并进行聚合。
import pandas as pd

# read only the columns you need, with explicit types
cols  = ['age', 'education', 'capital_gain', 'label']
types = {'age': 'int32', 'capital_gain': 'int32'}
df = pd.read_csv(PATH, names=COLUMNS, usecols=cols, dtype=types,
                 skipinitialspace=True, index_col=False)

# stream the file in fixed-size chunks instead of loading it whole
total = 0
for chunk in pd.read_csv(PATH, names=COLUMNS, chunksize=10000,
                         skipinitialspace=True, index_col=False):
    total = total + len(chunk)
print(total)

基本条件具备后,还有两种选择会有所帮助。 engine='pyarrow' 切换到多线程 Arrow 解析器,并且 dtype_backend='pyarrow' 将结果保存在带箭头的列中。 low_memory 默认值为 True,它会在内部分段解析文件,但可能会在一列中产生混合类型;请显式设置 dtype,而不是依赖于它。

最后, compression='infer' 这意味着以 .gz、.zip、.bz2、.xz 或 .zst 结尾的路径会被即时解压缩,因此无需在读取之前解压归档文件。

常见的 Pandas read_csv() 错误及其解决方法

read_csv() 函数的失败大多由以下四个原因造成,每个原因都有一个记录在案的参数可以解决。

误差 原因 固定
文件未找到错误 路径是相对于工作目录的,而不是相对于脚本的。 使用绝对路径,或确认 URL 协议可以是 http、ftp、s3、gs 或 file 之一。
Unicode解码错误 该文件不是 UTF-8 编码,而 UTF-8 是默认编码。 请传递 encoding='latin-1' 或正确的编解码器,或者 encoding_errors='replace'。
解析错误:数据标记化错误 一行数据包含的字段比表头声明的字段多。 传递 on_bad_lines='skip' 或 'warn',或设置正确的分隔符。
数据类型警告:列包含混合类型 分块类型推断在同一列中发现了不同的类型。 指定显式数据类型,或者设置 low_memory=False。
列偏移了一位 尾随分隔符会使 Pandas 将第一个字段提升到索引级别。 传递 index_col=False。

成人数据集直接显示了缺失值的情况:未知的工作类别、职业和本地国家条目存储为字面问号,因此除非您声明它们,否则它们将以字符串“?”的形式出现。

# tolerate rows with too many fields instead of raising
df = pd.read_csv(PATH, names=COLUMNS, on_bad_lines='skip')

# read a file that is not UTF-8
df = pd.read_csv('sales.csv', encoding='latin-1')

# treat the dataset's '?' placeholder as a missing value
df = pd.read_csv(PATH, names=COLUMNS, na_values='?', skipinitialspace=True)

常见问题

两者都调用同一个解析器。`read_csv()` 默认使用逗号分隔符,而 `read_table()` 读取通用分隔符文件,需要您自行设置分隔符。对于逗号分隔的文件,请使用 `read_csv()`;对于制表符或竖线分隔的文件,请使用 `read_table()`。

调用 df.to_csv('output.csv', index=False)。删除ping 该索引可避免下次读取时出现未命名的第一列。添加分隔符、编码或压缩参数,以反映导入文件时使用的设置。

传递 `parse_dates` 函数时,需要指定列名或列位置;如果布局不是 ISO 8601 格式,则需要添加 `date_format` 参数,例如 `date_format='%d/%m/%Y'`。否则,日期列将以纯字符串对象的形式传入,需要单独调用 `to_datetime` 函数。

将分隔符设置为特定字符,例如 sep=';' 或 sep='\t'。长度超过一个字符的分隔符将被视为正则表达式,并强制执行较慢的算法。 Python engine.sep=None 让该引擎从第一个有效行中嗅探分隔符。

使用 `nrows` 参数可以限制返回的数据行数,使用 `skiprows` 参数可以跳过一段开头的行。将它们结合起来,可以像翻页一样处理文件,例如,`skiprows=1000000` 和 `nrows=999999` 可以读取第二个一百万行。

是的。压缩默认设置为“推断”,因此以 .gz、.zip、.bz2、.xz 或 .zst 结尾的路径会自动解压缩。 URL使用 http、ftp、s3、gs 或文件存储都有效,并且 storage_options 将凭据传递给远程后端。

训练好的模型会标记出可能的类型错误,将近似重复的类别拼写进行聚类,并从相邻列中填充缺失值。这样就将手动清理的范围缩小到基于规则的 na_values 或 dtype 设置无法自行解决的行。

Copilot 一旦看到文件样本,就会快速生成样板代码。请将参数列表视为草稿,因为它通常会猜测数据类型和编码。运行之前,请务必对照 pandas API 文档检查每个生成的关键字。

总结一下这篇文章: