当前位置:首页>python>从零开始学Python数据清洗(三)

从零开始学Python数据清洗(三)

  • 2026-10-11 07:43:08
从零开始学Python数据清洗(三)

数据读取与写入

数据清洗的第一步,是把数据"请进门"。听起来简单,但CSV的编码暗坑、Excel的多个工作表、中文乱码的顽固问题——这些细节能让新手卡住半天。本文将从pandas的数据读写入手。

文中涉及到的数据文件可以联系我发给你,因为我还不知道怎么在公众号插入文件


一、pd.read_csv():读取CSV文件

CSV(逗号分隔值)是最常见的数据交换格式。几乎所有系统都能导出CSV。pandas用 pd.read_csv() 读取它,这也是你以后使用频率最高的函数。

基本用法

import pandas as pd

# 最简单的调用——只指定文件路径

df = pd.read_csv('data_python/employee_data.csv')
df.head(3)

输出:

   emp_id   name department gender   age education   hire_date    salary
0  EMP0001  员工_36      市场部     女  46.0      本科  2018-07-11  22968.99
1  EMP0002  员工_62       NaN     男  24.0      大专  2023-03-29   6314.78
2  EMP0003  员工_39       NaN     女  35.0      本科  2022-02-26   3222.29

一行代码,数据已经在内存中了。但 read_csv() 的真正威力在于它的参数。

关键参数详解

# pd.read_csv() 的常用参数一览
df = pd.read_csv(
    'data_python/sales_orders.csv'
,
    encoding='utf-8',       # 文件编码
    sep=',',                # 分隔符
    header=0,               # 第几行作为列名(0表示第一行)
    nrows=100,              # 只读取前100行(预览大文件时特别有用)
    usecols=None,           # 指定要读取哪些列
    dtype=None,             # 指定列的数据类型
    parse_dates=None,       # 指定哪些列需要解析为日期
)
参数
作用
常用值
encoding
指定文件编码
'utf-8'
, 'gbk', 'gb2312'
sep
列分隔符
','
, '\t'(tsv文件)
header
列名所在行
0
(默认), None(无列名)
nrows
只读取前N行
任意整数,预览数据时使用
usecols
指定读取的列
[0, 1, 3]
 或 ['emp_id', 'name']
dtype
指定列数据类型
{'age': 'float64'}
parse_dates
将指定列解析为日期
['hire_date']
skiprows
跳过前N行
任意整数

实战:用最佳参数读取员工数据

emp = pd.read_csv(
    'data_python/employee_data.csv'
,
    encoding='utf-8',
    parse_dates=['hire_date'],   # 入职日期直接转为datetime
    dtype={'emp_id': 'string'}   # 员工编号作为字符串(不需要数学运算)
)

# 验证:hire_date现在应该是datetime类型

print
(emp.dtypes)
print
(f"数据规模: {emp.shape}")

关键习惯:读取数据时就把 parse_dates 和 dtype 设好,不要等出错了再回头修正。这在处理大批量数据时尤其重要。


二、编码问题:中文乱码的终极解决方案

中文乱码是每个Python数据分析师都会遇到的"第一课"。当你满怀期待地 read_csv,结果看到一堆 锟斤拷 或 ???,那种挫败感我们都懂。

为什么会出现乱码?

文件在保存时使用了一种编码(比如GBK),而你在读取时用了另一种编码(比如UTF-8)。编码不匹配,中文就变成了乱码。

解决方案三步走

第一步:尝试常见编码

# 中文文件最常见的三种编码,挨个试
for
 enc in ['utf-8', 'gbk', 'gb2312', 'utf-8-sig']:
    try
:
        df = pd.read_csv('data_python/sales_orders.csv', encoding=enc)
        print
(f"{enc} ✓ 读取成功")
        break

    except
 Exception as e:
        print
(f"{enc} ✗ 失败: {type(e).__name__}")

第二步:用chardet自动检测

如果手动尝试都失败了,让程序来猜:

import chardet

# 读取文件的原始字节,让chardet检测编码

with
 open('data_python/sales_orders.csv', 'rb') as f:
    raw = f.read(10000)  # 读取前10000字节就够了
    result = chardet.detect(raw)
    print
(f"检测结果: {result}")
    # 输出示例: {'encoding': 'utf-8', 'confidence': 0.99}

第三步:用检测到的编码读取

encoding = result['encoding']
df = pd.read_csv('data_python/sales_orders.csv', encoding=encoding)
print
(df.head(2))

实用经验:Windows上用Excel生成的中文CSV通常是 GBK 编码。用代码生成的CSV通常是 UTF-8。如果你不确定,优先试这两个。

保存时避免乱码

# 用 utf-8-sig 保存,Excel打开不会乱码
df.to_csv('output.csv', encoding='utf-8-sig', index=False)

utf-8-sig 在文件头部添加了BOM(字节顺序标记),Windows Excel看到这个标记就知道用UTF-8打开,完美解决中文显示问题。


三、pd.read_excel():读取Excel文件

Excel文件在企业环境中无处不在。pandas读取Excel一样简单。

基本用法

# 读取第一个工作表
df = pd.read_excel('data.xlsx')

# 读取指定工作表

df = pd.read_excel('data.xlsx', sheet_name='销售数据')

# 读取第2个工作表(索引从0开始)

df = pd.read_excel('data.xlsx', sheet_name=1)

关键参数

df = pd.read_excel(
    'data.xlsx'
,
    sheet_name='Sheet1',     # 工作表名称或索引
    header=0,                # 列名所在行
    usecols='A:D',           # 只读取A到D列(Excel列号方式)
    skiprows=2,              # 跳过前2行(比如标题行)
    nrows=500,               # 只读取500行
    dtype={'age': int},      # 指定数据类型
)

读取多个工作表

# 一次性读取所有工作表,返回一个字典
all_sheets = pd.read_excel('data.xlsx', sheet_name=None)

# 逐个访问

for
 name, sheet_df in all_sheets.items():
    print
(f"工作表 [{name}]: {sheet_df.shape}")

提示:read_excel() 依赖 openpyxl 库来读取 .xlsx 文件。如果遇到报错,先检查是否安装了它:pip install openpyxl。


四、其他数据格式简介

pandas支持的数据格式远不止CSV和Excel,以下是几个你可能遇到的格式:

JSON数据

# JSON在Web API返回中非常常见
df = pd.read_json('data.json')
# 也可以直接读取JSON字符串

df = pd.read_json('[{"name":"张三","age":28},{"name":"李四","age":35}]')

SQL数据库

from sqlalchemy import create_engine

# 创建数据库连接

engine = create_engine('sqlite:///mydata.db')
# 用SQL查询读取数据

df = pd.read_sql('SELECT * FROM employees WHERE salary > 10000', engine)

其他格式速查

格式
读取函数
写入函数
CSV
pd.read_csv()df.to_csv()
Excel
pd.read_excel()df.to_excel()
JSON
pd.read_json()df.to_json()
SQL
pd.read_sql()df.to_sql()
Stata
pd.read_stata()df.to_stata()
SPSS
pd.read_spss()
—
Clipboard
pd.read_clipboard()df.to_clipboard()

五、写入数据:to_csv() 和 to_excel()

清洗完的数据需要保存。to_csv() 和 to_excel() 是你的出口。

to_csv()

df.to_csv(
    'cleaned_data.csv'
,
    index=False,              # 不保存行索引(强烈建议)
    encoding='utf-8-sig',     # Excel友好编码
    sep=',',                  # 分隔符
    float_format='%.2f',      # 浮点数保留两位小数
    na_rep='',                # 缺失值用什么表示
)

index=False 一定要加。否则每次保存都会多出一列无意义的数字索引,累计几次文件就会变得面目全非。

to_excel()

# 保存到单个工作表
df.to_excel('cleaned_data.xlsx', sheet_name='清洗结果', index=False)

# 把多个DataFrame写入同一个Excel文件的不同工作表

with
 pd.ExcelWriter('report.xlsx', engine='openpyxl') as writer:
    emp.to_excel(writer, sheet_name='员工数据', index=False)
    sales.to_excel(writer, sheet_name='销售数据', index=False)
    cust.to_excel(writer, sheet_name='客户数据', index=False)

pd.ExcelWriter 让你可以在一个Excel文件中创建多个工作表,非常适合生成多页报告。


六、处理大文件:nrows和chunksize

当CSV文件达到几百MB甚至几GB时,一次性读入内存可能导致电脑卡死。pandas提供了两种策略。

策略一:nrows 预览

# 只读前1000行,快速预览结构和内容
df_preview = pd.read_csv('large_file.csv', nrows=1000)
print
(df_preview.shape)
print
(df_preview.dtypes)

策略二:chunksize 分块处理

# 每次读入5000行,逐块处理
chunks = []
for
 chunk in pd.read_csv('large_file.csv', chunksize=5000):
    # 每一块是一个DataFrame,在这里做清洗

    chunk = chunk.dropna()                    # 删除缺失值
    chunk['date'] = pd.to_datetime(chunk['date'])  # 转换日期
    chunks.append(chunk)

# 合并所有处理后的块

df_full = pd.concat(chunks, ignore_index=True)
print
(f"处理完成,总行数: {len(df_full)}")
策略
适用场景
参数
nrows
预览数据、调试代码
nrows=N
chunksize
大文件清洗、内存不足
chunksize=N
usecols
只关心部分列
usecols=[...]
dtype
优化内存占用
dtype={...}

七、实战:一次性读取6套数据集

让我们用一个循环,把本系列的所有练习数据全部读入:

import pandas as pd
from
 pathlib import Path

data_dir = Path('data_python')
datasets = {}

for
 file in sorted(data_dir.glob('*.csv')):
    # 从文件名提取数据集名称(去掉.csv后缀)

    name = file.stem

    # 读取,统一用utf-8编码

    df = pd.read_csv(file, encoding='utf-8')

    # 存入字典

    datasets[name] = df

    # 打印基本信息

    print
(f"{name:25s} → {df.shape[0]:>4} 行 × {df.shape[1]} 列")

print
(f"\n共加载 {len(datasets)} 套数据集,准备就绪!")

输出:

employee_data             →  500 行 × 8 列
sales_orders              →  610 行 × 6 列
customer_info             →  300 行 × 7 列
department_data           →    5 行 × 5 列
time_series_sales         →  471 行 × 4 列
survey_data               →  400 行 × 6 列

共加载 6 套数据集,准备就绪!

现在所有数据都在 datasets 字典中,随时可以按名称取出。例如:

emp = datasets['employee_data']
sales = datasets['sales_orders']

print
(emp['salary'].describe())
print
(sales['product'].value_counts())

这就是数据清洗的起点——把所有数据整齐地读入内存,为后续的探索和清洗做好准备。


小结

今天我们学会了数据的"进门"和"出门":

操作
函数
关键参数
读CSV
pd.read_csv()encoding
, parse_dates, dtype
读Excel
pd.read_excel()sheet_name
, usecols, skiprows
读JSON
pd.read_json()orient
写CSV
df.to_csv()index=False
, encoding='utf-8-sig'
写Excel
df.to_excel()sheet_name
, index=False
大文件
chunksize
分块读取,逐块处理

核心原则就三条:

  1. 1. 读数据时检查编码——用 chardet 或挨个试 utf-8、gbk
  2. 2. 读数据时解析日期——用 parse_dates,不要等后面再转换
  3. 3. 写数据时关掉索引——永远加 index=False

下一篇预告

下一篇 《数据初探与基础统计》 将进入真正的数据清洗实战。你会学到如何用 isnull() 定位缺失值、用 value_counts() 检查分类变量、用 groupby() 做分组统计——以及最重要的,如何培养"怀疑数据"的习惯。数据已经就位,准备动手清洗!


#Pandas #read_csv #中文乱码 #数据导入 #编码问题 #chardet

如果这篇文章帮你解决了中文乱码问题,点个"在看"让更多人看到。有问题欢迎留言,我们评论区见。

最新文章

随机文章