在数据分析流程中,“数据加载” 是第一步 —— 只有把 Excel/CSV 里的原始数据导入到 Python 中,才能进行后续的清洗、分析和可视化。而 pandas 作为 Python 数据分析的 “瑞士军刀”,提供了极简的 API 来读取 Excel/CSV 文件,同时自带强大的 “数据初探” 工具,能帮你快速摸清数据的 “底细”(比如有多少行多少列、数据类型是什么、有没有缺失值)。

今天这篇教程,从零基础视角出发,分 3 大模块讲解:环境准备读取 Excel/CSV(含踩坑指南)→数据基本信息查看(实战技巧),所有代码可直接复制运行,帮你轻松迈过数据分析的第一道坎。

一、先做准备:安装 pandas 及依赖库

pandas 本身不自带读取 Excel 的能力,需要额外安装依赖库;读取 CSV 则无需额外依赖。先确保你的环境里有这些库,新手直接用pip安装即可:

1. 安装核心库(一行命令)

打开终端(Windows 用 cmd,Mac 用终端),输入以下命令:

# 安装pandas(核心)+ openpyxl(读取Excel 2007+格式.xlsx+ xlrd(读取旧版Excel .xls格式)

pip install pandas openpyxl xlrd

2. 依赖库说明(避免踩坑)

  1. pandas:核心库,负责数据加载和处理;
  2. openpyxl:必须装!用于读取.xlsx格式的 Excel 文件(2007 及以后版本,现在主流格式);
  3. xlrd:用于读取.xls格式的旧版 Excel 文件(如果你的数据是.xls,才需要装;新版 xlrd 默认不支持.xlsx,所以必须配合 openpyxl)。

安装完成后,在 Python 中导入 pandas(惯例简写为pd):

import pandas as pd  # 导入pandas,简写为pd(行业通用)

二、读取 CSV 文件:最常用的文本数据格式

CSV(逗号分隔值)是数据分析中最常用的格式 —— 体积小、兼容性强,几乎所有工具(Excel、Python、R)都能处理。pandas 用pd.read_csv()读取,基础用法超简单,重点解决 “中文乱码”“指定列读取” 等新手常见问题。

1. 基础读取:1 行代码加载 CSV

假设有一个销售数据.csv文件,内容如下(存放在代码同一目录下,路径最简单):

日期

产品类别

销售额

销量

地区

2024-01-01

家电

5200

26

华北

2024-01-02

服装

3800

95

华东

2024-01-03

家电

6500

32

华南

2024-01-04

食品

1200

240

华北

读取代码:

# 读取CSV文件(文件和代码同一目录,直接写文件名)

df = pd.read_csv("销售数据.csv")  # dfDataFramepandas的核心数据结构(类似Excel表格)

# 打印数据类型,确认读取成功

print("数据类型:", type(df))  # 输出:数据类型: <class 'pandas.core.frame.DataFrame'>

  1. 关键概念:DataFrame(简称 “df”)是 pandas 的 “表格型数据结构”,对应 Excel 的 “工作表”—— 有行索引(左侧数字)、列名(顶部标题),每个单元格有对应的值,是后续所有分析的基础。

2. 解决新手第一坑:中文乱码(encoding 参数)

如果 CSV 文件包含中文,直接读取可能出现乱码(比如 “华北” 变成 “北区”),这是因为文件编码格式和 pandas 默认编码(utf-8)不匹配。

常见编码及解决方案:

乱码原因

编码参数

适用场景

文件是 GBK 编码(Windows 保存的 CSV 常这样)

encoding="gbk"

中文 Windows 系统保存的 CSV

文件是 UTF-8 编码(Mac/Linux 常用)

encoding="utf-8"

默认值,大部分情况适用

UTF-8 编码但带 BOM(少见)

encoding="utf-8-sig"

解决 “utf-8 编码仍乱码” 问题

代码示例(解决 GBK 编码乱码):

# 如果读取时中文乱码,加encoding="gbk"

df = pd.read_csv("销售数据.csv", encoding="gbk")

  1. 怎么判断编码?:如果不确定文件编码,先试utf-8,乱码再试gbk,90% 的中文 CSV 问题都能解决。

3. 实用参数:按需求读取(不是所有数据都要加载)

实际工作中,CSV 文件可能有几十列、几万行,我们往往只需要其中几列 —— 用read_csv()的参数筛选,避免加载无用数据,提升效率。

常用参数及案例:

参数名

作用

示例代码

效果

usecols

指定要读取的列(列名或索引)

pd.read_csv("销售数据.csv", usecols=["日期", "销售额", "地区"])

只读取 “日期、销售额、地区”3 列

index_col

指定某列为 “行索引”(代替默认数字)

pd.read_csv("销售数据.csv", index_col="日期")

用 “日期” 列作为行索引(左侧不再是 0,1,2)

skiprows

跳过前 N 行(比如跳过标题上方的注释)

pd.read_csv("销售数据.csv", skiprows=1)

跳过第 1 行,从第 2 行开始读(如果第 1 行是注释)

nrows

只读取前 N 行(快速预览大文件)

pd.read_csv("销售数据.csv", nrows=100)

只读取前 100 行(适合 GB 级大文件,避免卡死)

案例:读取指定列 + 用日期做行索引

# 只读取日期、产品类别、销售额”3列,并用日期做行索引

df = pd.read_csv(

    "销售数据.csv",

    usecols=["日期", "产品类别", "销售额"],  # 指定列

    index_col="日期"                     # 行索引

)

print(df.head())  # 打印前5行(后续会讲head()

# 输出(行索引变成日期):

#             产品类别  销售额

# 日期                 

# 2024-01-01     家电   5200

# 2024-01-02     服装   3800

# 2024-01-03     家电   6500

# 2024-01-04     食品   1200

三、读取 Excel 文件:支持多工作表、复杂格式

Excel 比 CSV 更复杂(支持多工作表、合并单元格、公式),pandas 用pd.read_excel()读取,核心解决 “指定工作表”“处理合并单元格” 等问题。

1. 基础读取:读取 Excel 默认工作表

假设有一个销售数据.xlsx文件,包含 2 个工作表:“1 月销售”(默认工作表,即打开 Excel 显示的第一个表)和 “2 月销售”,先读取默认工作表:

# 读取Excel默认工作表(需要指定engine="openpyxl",否则可能报错)

df = pd.read_excel("销售数据.xlsx", engine="openpyxl")  # engine必须加,确保读取.xlsx

print("默认工作表数据:")

print(df.head())

  1. 为什么加engine="openpyxl":pandas 默认可能调用xlrd读取 Excel,但新版xlrd不支持.xlsx格式,所以必须明确指定用openpyxl引擎(对应我们之前装的库)。如果是旧版.xls文件,引擎用engine="xlrd"

2. 指定工作表读取(sheet_name 参数)

这是读取 Excel 最常用的需求 —— 比如只读取 “2 月销售” 工作表,有 3 种指定方式:

指定方式

示例代码

说明

工作表名称(推荐)

pd.read_excel("销售数据.xlsx", engine="openpyxl", sheet_name="2月销售")

直接写工作表名,清晰不易错

工作表索引(从 0 开始)

pd.read_excel("销售数据.xlsx", engine="openpyxl", sheet_name=1)

0 是第一个表,1 是第二个表(适合表名复杂时)

读取多个工作表

pd.read_excel("销售数据.xlsx", engine="openpyxl", sheet_name=["1月销售", "2月销售"])

返回字典,key 是表名,value 是 DataFrame

案例 1:读取指定名称的工作表

# 读取“2月销售工作表

df_feb = pd.read_excel(

    "销售数据.xlsx",

    engine="openpyxl",

    sheet_name="2月销售"  # 指定工作表名

)

print("2月销售数据前5行:")

print(df_feb.head())

案例 2:一次性读取多个工作表

# 读取“1月销售“2月销售两个表,返回字典

df_dict = pd.read_excel(

    "销售数据.xlsx",

    engine="openpyxl",

    sheet_name=["1月销售", "2月销售"]

)

# 从字典中提取每个表的数据

df_jan = df_dict["1月销售"]  # 1月数据

df_feb = df_dict["2月销售"]  # 2月数据

print("1月销售数据行数:", len(df_jan))

print("2月销售数据行数:", len(df_feb))

3. 处理 Excel 特殊情况:跳过行、合并单元格

情况 1:表头不在第一行(比如前 2 行是注释)

skiprows跳过前面的行,用header指定表头所在行(从 0 开始):

# 跳过前2行(注释),表头在第3行(索引2

df = pd.read_excel(

    "销售数据.xlsx",

    engine="openpyxl",

    skiprows=2,    # 跳过前2

    header=2       # 3行(索引2)作为表头

)

情况 2:合并单元格(比如 A1-A3 合并为 “产品信息”)

pandas 读取合并单元格时,只会在 “第一个单元格” 保留值,其他合并单元格会显示NaN(缺失值),需要后续处理,但读取时可以正常加载:

# 读取包含合并单元格的Excel,合并单元格会显示NaN

df = pd.read_excel("销售数据.xlsx", engine="openpyxl")

print("包含合并单元格的数据:")

print(df)  # 合并单元格的非首格会显示NaN

四、数据基本信息查看:3 分钟摸清数据 “底细”

加载数据后,第一步不是急于分析,而是 “快速了解数据全貌”—— 比如有多少行多少列、数据类型对不对、有没有缺失值、数值列的范围是什么。pandas 提供了 6 个核心方法,覆盖 90% 的初探需求。

我们用之前的 “销售数据.csv” 加载的 DataFrame(df)为例,逐个讲解:

1. 快速预览:查看前 N 行 / 后 N 行(head ()/tail ())

  1. df.head(n):查看前 n 行(默认 n=5,适合快速看数据结构);
  2. df.tail(n):查看后 n 行(默认 n=5,适合看数据末尾是否有异常值)。

# 查看前3

print("3行数据:")

print(df.head(3))

# 输出:

#          日期 产品类别  销售额  销量  地区

# 0  2024-01-01     家电   5200   26  华北

# 1  2024-01-02     服装   3800   95  华东

# 2  2024-01-03     家电   6500   32  华南

# 查看后2

print("\n2行数据:")

print(df.tail(2))

# 输出:

#          日期 产品类别  销售额  销量  地区

# 2  2024-01-03     家电   6500   32  华南

# 3  2024-01-04     食品   1200  240  华北

2. 数据规模:行数、列数(shape)

df.shape返回一个元组(行数, 列数),快速了解数据体量:

print("数据规模(行数, 列数):", df.shape)  # 输出:数据规模(行数, 列数): (4, 5)

# 单独获取行数、列数

print("行数:", df.shape[0])  # 输出:行数:4

print("列数:", df.shape[1])  # 输出:列数:5

3. 列信息:列名、数据类型、缺失值(info ())

df.info()是 “数据初探第一神器”—— 显示列名、每列的数据类型(dtype)、非缺失值数量(Non-Null Count),帮你快速发现问题(比如数值列被识别成文本、有大量缺失值)。

print("数据基本信息:")

print(df.info())

# 输出:

# <class 'pandas.core.frame.DataFrame'>

# RangeIndex: 4 entries, 0 to 3  # 行索引:4行,03

# Data columns (total 5 columns):  # 5

#  #   Column  Non-Null Count  Dtype   # 列索引、列名、非缺失值数、数据类型

# ---  ------  --------------  ----- 

#  0   日期      4 non-null      object  # object=文本类型(日期默认是文本,后续需转成日期类型)

#  1   产品类别  4 non-null      object  # 文本类型(分类数据)

#  2   销售额    4 non-null      int64   # 整数类型(数值数据,正常)

#  3   销量      4 non-null      int64   # 整数类型(数值数据,正常)

#  4   地区      4 non-null      object  # 文本类型(分类数据)

# dtypes: int64(2), object(3)  # 数据类型统计:2个整数,3个文本

# memory usage: 288.0+ bytes  # 内存占用(很小,正常)

关键解读:
  1. 数据类型(dtype
    1. int64/float64:数值类型(可直接计算);
    2. object:文本类型(日期、分类等,需根据需求转成对应类型,比如日期转datetime64);
    3. category:分类类型(适合取值少的列,如 “地区” 只有华北 / 华东 / 华南,后续可转成 category 节省内存)。
  2. 缺失值(Non-Null Count:如果某列的 “Non-Null Count” 小于总行数(比如总行数 4,某列 3 non-null),说明该列有缺失值(1 个 NaN),后续需要处理。

4. 数值统计:均值、最值、标准差(describe ())

df.describe()数值列(int64/float64)做统计描述,返回计数、均值、标准差、最小值、四分位数、最大值,帮你快速了解数值分布(比如是否有异常值)。

print("数值列统计描述:")

print(df.describe())

# 输出(只显示数值列销售额销量):

#               销售额         销量

# count    4.000000    4.000000  # 计数:4个非缺失值

# mean   4175.000000   98.250000  # 均值:销售额平均4175,销量平均98.25

# std    2237.853883  105.985848  # 标准差:销量标准差大(说明波动大)

# min    1200.000000   26.000000  # 最小值:销售额最低1200,销量最低26

# 25%    3150.000000   29.000000  # 25分位数(下四分位)

# 50%    4500.000000   63.500000  # 50分位数(中位数)

# 75%    5525.000000  126.250000  # 75分位数(上四分位)

# max    6500.000000  240.000000  # 最大值:销售额最高6500,销量最高240

关键解读:
  1. 看 “标准差(std)”:如果某列标准差远大于均值(比如销量的 std=105,均值 = 98),说明该列数据波动大(比如销量从 26 到 240,差异大);
  2. 看 “最值”:是否有明显异常(比如销售额出现负数,或销量出现 10000 这种远超均值的值)。

5. 查看列名和行索引(columns/index)

  1. df.columns:返回所有列名(可用于遍历列、重命名列);
  2. df.index:返回行索引(可用于重置索引、修改索引)。

# 查看列名(返回Index对象,可转成列表)

print("列名:", df.columns.tolist())  # 输出:列名: ['日期', '产品类别', '销售额', '销量', '地区']

# 查看行索引

print("行索引:", df.index.tolist())  # 输出:行索引: [0, 1, 2, 3](默认数字索引)

6. 分类列唯一值:nunique ()/unique ()

对于 “产品类别”“地区” 这种分类列,用nunique()看有多少个不同值,用unique()看具体是哪些值:

# 查看每列的唯一值数量

print("各列唯一值数量:")

print(df.nunique())

# 输出:

# 日期        4  # 4个不同日期

# 产品类别    3  # 3种产品类别

# 销售额      4  # 4个不同销售额

# 销量        4  # 4个不同销量

# 地区        3  # 3个不同地区

dtype: int64

# 查看地区列的具体唯一值

print("\n地区列唯一值:", df["地区"].unique())  # 输出:地区列唯一值: ['华北' '华东' '华南']

# 查看产品类别列的唯一值计数(每个类别有多少条数据)

print("产品类别计数:")

print(df["产品类别"].value_counts())

# 输出:

# 产品类别

# 家电    2  # 家电有2条数据

# 服装    1  # 服装有1条数据

# 食品    1  # 食品有1条数据

Name: count, dtype: int64

五、实战案例:完整流程(读取→初探)

用一个 “学生成绩.xlsx” 文件,走一遍完整的 “读取→初探” 流程,巩固所学:

1. 数据背景

“学生成绩.xlsx” 包含 1 个工作表 “高一成绩”,数据如下:

学号

姓名

语文

数学

英语

班级

2024001

张三

85

92

78

1 班

2024002

李四

76

68

89

2 班

2024003

王五

90

95

92

1 班

2024004

赵六

65

58

72

2 班

2024005

孙七

88

79

85

1 班

2. 完整代码

import pandas as pd

# 1. 读取Excel文件(指定工作表高一成绩,用学号做行索引)

df_score = pd.read_excel(

    "学生成绩.xlsx",

    engine="openpyxl",

    sheet_name="高一成绩",

    index_col="学号"  # 用学号做行索引(唯一标识)

)

# 2. 数据初探

print("=" * 40)

print("1. 数据规模(行数, 列数):", df_score.shape)

print("=" * 40)

print("2. 3行数据:")

print(df_score.head(3))

print("=" * 40)

print("3. 数据类型和缺失值:")

print(df_score.info())

print("=" * 40)

print("4. 成绩统计描述(数值列):")

print(df_score.describe())

print("=" * 40)

print("5. 班级分布(分类列):")

print(df_score["班级"].value_counts())

print("=" * 40)

print("6. 语文成绩最高分:", df_score["语文"].max())

print("数学成绩最低分:", df_score["数学"].min())

print("英语成绩平均分:", df_score["英语"].mean().round(1))  # 保留1位小数

3. 运行结果解读

========================================

1. 数据规模(行数, 列数): (5, 5)

========================================

2. 3行数据:

         姓名  语文  数学  英语  班级

学号                        

2024001  张三   85   92   78  1

2024002  李四   76   68   89  2

2024003  王五   90   95   92  1

========================================

3. 数据类型和缺失值:

<class 'pandas.core.frame.DataFrame'>

Index: 5 entries, 2024001 to 2024005  # 行索引是学号

Data columns (total 5 columns):

 #   Column  Non-Null Count  Dtype

---  ------  --------------  -----

 0   姓名      5 non-null      object

 1   语文      5 non-null      int64

 2   数学      5 non-null      int64

 3   英语      5 non-null      int64

 4   班级      5 non-null      object

dtypes: int64(3), object(2)

memory usage: 240.0+ bytes

========================================

4. 成绩统计描述(数值列):

        语文        数学        英语

count   5.000000   5.000000   5.000000

mean   80.800000   78.400000   83.200000

std    10.382689   14.177446    8.508819

min    65.000000   58.000000   72.000000

25%    76.000000   68.000000   78.000000

50%    85.000000   79.000000   85.000000

75%    88.000000   92.000000   89.000000

max    90.000000   95.000000   92.000000

========================================

5. 班级分布(分类列):

班级

1    3

2    2

Name: count, dtype: int64

========================================

6. 语文成绩最高分: 90

数学成绩最低分: 58

英语成绩平均分: 83.2

通过这个流程,我们快速知道:

  1. 数据有 5 个学生,5 列信息(姓名、3 科成绩、班级);
  2. 无缺失值,成绩都是整数类型(正常);
  3. 数学成绩波动最大(std=14.2),最低分 58(可能需要关注);
  4. 1 班有 3 人,2 班有 2 人。

六、新手常见问题解决(踩坑指南)

1. 读取文件时提示 “文件不存在”

  1. 原因 1:文件路径写错(比如把 “销售数据.csv” 写成 “销售.csv”);
  2. 原因 2:文件不在代码同一目录,且没写绝对路径;
  3. 解决:

① 确认文件名和后缀(.csv/.xlsx)完全正确;

② 若文件不在代码目录,写绝对路径(比如 Windows:"C:/Users/XXX/Desktop/销售数据.csv",Mac:"/Users/XXX/Desktop/销售数据.csv");

③ 推荐:把文件和代码放在同一目录,直接写文件名(最简单,不易错)。

2. 读取 Excel 时提示 “No module named 'openpyxl'”

  1. 原因:没装 openpyxl 库,或安装失败;
  2. 解决:重新执行pip install openpyxl,确保安装成功(看到 “Successfully installed openpyxl-xxx”)。

3. 读取 CSV 中文乱码,试了 utf-8 和 gbk 都不行

  1. 原因:文件编码是其他格式(比如 gb2312、utf-16);
  2. 解决:用记事本打开 CSV 文件→点击 “文件→另存为”→查看 “编码” 选项(比如显示 “ANSI”,对应 gbk;显示 “UTF-8” 对应 utf-8),按实际编码填写encoding参数。

4. describe () 只显示部分列

  1. 原因:describe () 默认只统计数值列(int64/float64),文本列(object)不显示;
  2. 解决:若想统计文本列,加include="all"参数:df.describe(include="all"),会显示文本列的唯一值数量、最频繁值等信息。

七、总结与后续学习方向

今天我们掌握了数据分析的 “第一步核心技能”:

  1. 用 pandas 读取 CSV(解决中文乱码、指定列)和 Excel(指定工作表、处理特殊格式);
  2. 用 6 个方法快速初探数据(head ()/info ()/describe () 等),摸清数据规模、类型、缺失值、分布;

下一步可以学习:

  1. 数据清洗:处理缺失值(填充 / 删除)、异常值(识别 / 修正)、数据类型转换(比如把文本日期转成 datetime);
  2. 数据筛选与分组:用df.loc[]筛选数据,用df.groupby()按分类列分组统计(比如按班级统计平均成绩);
  3. 数据可视化:结合 matplotlib/seaborn 画柱状图、折线图(比如展示各班级成绩分布)。

如果在读取数据或初探时遇到具体问题,欢迎留言分享你的数据格式和报错信息,我会帮你针对性解决!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐