RSS
菜单
全部文章快讯开发科技深度热点

第 5 章 数据查看与探索(EDA 入门)

内容摘要

拿到一份新数据后,第一步不是急着分析,而是**先摸清它的全貌**:有几行几列?每列是什么类型?有没有缺失值?数值分布如何?本篇文章教你用 pandas 完成一套标准的"数据体检"流程(EDA,探索性数据分析)。

拿到一份新数据后,第一步不是急着分析,而是先摸清它的全貌:有几行几列?每列是什么类型?有没有缺失值?数值分布如何?本篇文章教你用 pandas 完成一套标准的"数据体检"流程(EDA,探索性数据分析)。

目录

1. EDA 是什么

2. 宏观概览:shape / info / head / tail

3. 数值统计:describe

4. 分布探索:value_counts / unique / nunique

5. 缺失值检查

6. 相关性分析

7. 分组快速对比

8. 一套完整的 EDA 模板

9. 常见坑与注意事项

10. 本章小结与练习


1. EDA 是什么

EDA(Exploratory Data Analysis,探索性数据分析) 指在正式建模或深入分析之前,用统计和可视化的手段快速了解数据的过程。pandas 提供了大量一行式方法,让 EDA 变得非常高效。

先造一份示例数据(本文所有示例都基于它):

import pandas as pd
import numpy as np

np.random.seed(42)
df = pd.DataFrame({
    "姓名": [f"用户{i}" for i in range(1, 101)],
    "年龄": np.random.randint(18, 60, 100),
    "城市": np.random.choice(["北京", "上海", "广州", "深圳", "杭州"], 100),
    "消费金额": np.random.uniform(50, 5000, 100).round(2),
    "是否会员": np.random.choice(["是", "否"], 100, p=[0.4, 0.6]),
})
df.loc[3, "年龄"] = np.nan      # 制造一个缺失值
df.loc[7, "消费金额"] = np.nan

2. 宏观概览:shape / info / head / tail

2.1 形状

print(df.shape)      # (100, 5):100 行 5 列
print(df.size)       # 500

2.2 基本信息

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100 entries, 0 to 99
Data columns (total 5 columns):
 #   Column   Non-Null Count  Dtype
---  ------   --------------  -----
 0   姓名      100 non-null    object
 1   年龄       99 non-null    float64
 2   城市      100 non-null    object
 3   消费金额    99 non-null    float64
 4   是否会员    100 non-null    object
dtypes: float64(2), object(3)
memory usage: 4.0+ KB

一次看到:总行数、列数、每列非空个数、每列类型、内存占用。这是体检第一站。

2.3 前后几行

print(df.head())          # 前 5 行(默认)
print(df.head(10))        # 前 10 行
print(df.tail())          # 后 5 行
print(df.sample(5))       # 随机 5 行(检查数据是否乱序时好用)

2.4 列名与索引

print(df.columns)         # 列名列表
print(df.index)           # 行索引

3. 数值统计:describe

print(df.describe())
              年龄       消费金额
count   99.000000    99.000000
mean    38.737374  2625.601313
std     12.038907  1421.344919
min    18.000000    62.540000
25%    29.000000  1411.510000
50%    39.000000  2635.920000
75%    49.000000  3894.300000
max    59.000000  4981.270000

| 统计量 | 含义 |

|--------|------|

| count | 非空个数(注意可能小于行数) |

| mean | 均值 |

| std | 标准差(离散程度) |

| min / max | 最小 / 最大值 |

| 25% / 50% / 75% | 四分位数(分布位置) |

变体用法:

# 只统计部分列
df[["年龄"]].describe()

# 自定义分位数
df.describe(percentiles=[0.1, 0.9])

# 字符串列统计
df.describe(include="object")
#        姓名   城市  是否会员
# count   100   100     100
# unique  100     5       2
# top    用户1  上海      否
# freq      1    26      60

# 所有列都看
df.describe(include="all")

4. 分布探索:value_counts / unique / nunique

4.1 分类列分布

# 城市分布(按次数降序)
print(df["城市"].value_counts())

# 带百分比
print(df["城市"].value_counts(normalize=True))

# 按字母排序显示
print(df["城市"].value_counts(ascending=True))

# 只看 top3 和"其他"
print(df["城市"].value_counts().head(3))

# 缺失值也统计进来
print(df["城市"].value_counts(dropna=False))

输出示例:

上海    26
杭州    21
广州    20
北京    17
深圳    16
Name: 城市, dtype: int64

4.2 唯一值

print(df["城市"].unique())        # 去重后的数组
print(df["城市"].nunique())       # 唯一值个数 = 5
print(df.nunique())               # 每列唯一值个数

4.3 数值列分箱看分布

# 将消费金额分成 4 档,看每档有多少人
bins = pd.cut(df["消费金额"], bins=4)
print(bins.value_counts())

# 指定分箱边界
bins2 = pd.cut(df["消费金额"], bins=[0, 1000, 3000, 5000], labels=["低", "中", "高"])
print(bins2.value_counts())

5. 缺失值检查

# 每列缺失值个数
print(df.isna().sum())
# 姓名      0
# 年龄      1
# 城市      0
# 消费金额   1
# 是否会员   0

# 缺失值占比
print(df.isna().mean().round(4) * 100)

# 哪些行有缺失
print(df[df.isna().any(axis=1)])

# 缺失值总数
print(df.isna().sum().sum())
缺失值的处理办法见第 7 章。

6. 相关性分析

对数值列之间做相关性矩阵,可以快速发现"哪些列一起变化":

# 数值列相关性矩阵
print(df[["年龄", "消费金额"]].corr())

# 全部数值列
print(df.corr(numeric_only=True))

# 与某列的相关性排序
print(df.corr(numeric_only=True)["消费金额"].sort_values(ascending=False))
              年龄       消费金额
年龄      1.000000   0.051313
消费金额  0.051313   1.000000

| 相关系数 | 含义 |

|----------|------|

| 接近 1 | 正相关(同增同减) |

| 接近 -1 | 负相关(一增一减) |

| 接近 0 | 无明显线性关系 |

corr() 默认是 Pearson 相关系数。相关性 ≠ 因果性,请谨慎解读。

7. 分组快速对比

# 各城市平均消费
print(df.groupby("城市")["消费金额"].mean().sort_values(ascending=False))

# 会员 vs 非会员:消费均值、中位数、人数
print(df.groupby("是否会员")["消费金额"].agg(["count", "mean", "median", "max"]))

# 交叉表:城市 × 是否会员
print(pd.crosstab(df["城市"], df["是否会员"]))

输出示例:

           count          mean        median         max
是否会员
否             60  2588.824833  2612.555000  4952.870000
是             39  2683.211282  2719.920000  4981.270000
groupby 的完整知识见第 13 章。

8. 一套完整的 EDA 模板

把下面的函数保存起来,任何 DataFrame 都能一键体检:

import pandas as pd

def quick_eda(df, n_sample=5):
    """快速体检:结构、缺失、数值统计、分类分布、相关性"""
    print("=" * 50)
    print("1. 数据形状:", df.shape)
    print("=" * 50)
    print("\n2. 基本信息:")
    df.info()

    print("\n3. 前几行:")
    print(df.head(n_sample))

    print("\n4. 缺失值统计:")
    print(df.isna().sum())

    num_cols = df.select_dtypes(include="number").columns.tolist()
    if num_cols:
        print("\n5. 数值列统计:")
        print(df[num_cols].describe().T)

    cat_cols = df.select_dtypes(include="object").columns.tolist()
    if cat_cols:
        print("\n6. 分类列分布:")
        for col in cat_cols:
            print(f"--- {col} ---")
            print(df[col].value_counts())

    if len(num_cols) >= 2:
        print("\n7. 相关性矩阵:")
        print(df[num_cols].corr())

# 使用
quick_eda(df)

9. 常见坑与注意事项

| 坑 | 现象 | 解决办法 |

|----|------|----------|

| describe 只统计数值列 | 字符串列"消失" | 加 include="all" 或 include="object" |

| count 不等于行数 | 有缺失值 | 对比 len(df) 与 df.count() |

| corr 报错 | 有非数值列 | 用 numeric_only=True 或先筛列 |

| value_counts 忽略 NaN | 分布"看起来"不完整 | 加 dropna=False |

| 数值列被读成 object | describe 不统计它 | 用 pd.to_numeric 转换(见第 8 章) |


10. 本章小结与练习

小结

  • 宏观:shape、info()、head/tail/sample;
  • 数值:describe() 看均值、标准差、四分位数;
  • 分类:value_counts() 看分布,unique/nunique 看唯一性;
  • 缺失:isna().sum() 逐列体检;
  • 关系:corr() 看数值相关性;
  • 对比:groupby + agg 快速看分组差异。

练习题

1. 用 pd.read_csv 读入任意一份本地数据(或自己构造),执行 info() 和 describe()。

2. 检查每列缺失值个数与占比。

3. 找出唯一值最多的 3 列。

4. 用 value_counts(normalize=True) 观察分类列占比。

5. 计算两列数值的相关性并解读结果。


下一篇预告:第 6 章 数据选择与索引 —— 用 loc、iloc、布尔索引精准定位数据,这是 pandas 最常用的操作。
— 全文完 —回到顶部 ↑
下载推广海报

文章推广海报

《第 5 章 数据查看与探索(EDA 入门)》完整推广海报
DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。