3. 数据概览与基础统计:快速摸清数据全貌

在开始任何数据清洗工作之前,第一步永远是“摸清家底”。面对催收触达的原始数据,我们需要快速回答三个核心问题:数据有多大?、哪些字段有缺失?、字段类型是否合理?。Pandas 提供了三个最基础、最高效的方法:shape、info() 和 describe()。

3.1 数据规模:shape 与 len

使用 df.shape 可以立即获取 DataFrame 的行数和列数,这是对数据体量的第一印象。

import pandas as pd

# 假设已加载原始催收数据
df = pd.read_csv('collection_contact_raw.csv')

# 查看数据规模
rows, cols = df.shape
print(f"数据集包含 {rows} 行记录,{cols} 列字段。")
💡 实战提示: 催收数据通常按天或按批次导出,行数在几万到几十万之间。如果行数异常少(如 0 行),需立即检查上游数据源是否为空或导出失败。

3.2 数据类型与缺失值:info() 全景扫描

df.info() 是数据清洗中最常用的“体检报告”。它会一次性输出:列名、非空计数、数据类型(Dtype)以及内存占用。

# 打印数据集的完整信息
df.info()

输出示例(模拟):

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 50000 entries, 0 to 49999
Data columns (total 12 columns):
 #   Column              Non-Null Count  Dtype  
---  ------              --------------  -----  
 0   客户ID               50000 non-null  int64  
 1   催收员ID             49800 non-null  float64
 2   触达时间             50000 non-null  object 
 3   触达方式             50000 non-null  object 
 4   通话时长(秒)         42000 non-null  float64
 5   是否接通             50000 non-null  object 
 6   承诺还款金额         15000 non-null  float64
 7   承诺还款日期         12000 non-null  object 
 8   客户标签             30000 non-null  object 
 9   案件金额             50000 non-null  int64  
 10  逾期天数             50000 non-null  int64  
 11  催收结果备注         25000 non-null  object 
dtypes: float64(3), int64(3), object(6)
memory usage: 4.6+ MB

3.3 关键字段解读:从 info() 中发现的异常

通过上述 info() 输出,我们可以快速定位以下潜在问题:

字段名 问题类型 异常描述 清洗优先级
催收员ID 缺失值 + 类型错误 有 200 个缺失值;应为字符串(object),但显示为 float64 高
通话时长(秒) 缺失值 缺失 8000 条(16%),需判断是未接通还是数据丢失 高
承诺还款金额 高缺失率 仅 30% 有值,需评估是否用于建模 中
触达时间 类型错误 显示为 object,实际应为 datetime 类型 高
⚠️ 常见陷阱: 催收员ID、案件ID 等标识字段,如果被 Pandas 自动识别为 float64,说明该列存在缺失值(NaN)。必须将其转换为字符串类型,否则后续关联分析会出错。

3.4 数值分布概览:describe() 快速统计

df.describe() 对数值型列自动计算:计数、均值、标准差、最小值、四分位数和最大值。这是发现异常值的“雷达”。

# 查看数值列的统计摘要
df.describe()

输出示例(模拟):

        案件金额      逾期天数    通话时长(秒)
count   50000.00   50000.00   42000.00
mean     8500.50      45.30     120.50
std      3200.20      30.10      98.40
min       500.00       1.00       0.00
25%      6200.00      20.00      30.00
50%      7800.00      38.00      95.00
75%     10200.00      65.00     180.00
max     50000.00     180.00     600.00

3.5 从 describe() 中识别异常信号

  • 通话时长(秒): 最小值为 0,但催收通话不可能为 0 秒。这通常代表未接通或挂断记录,需要结合“是否接通”字段进行过滤或填充。
  • 案件金额: 最大值 50000 远高于 75% 分位数的 10200,可能存在极端大额案件,需确认是否为数据录入错误或真实高额案件。
  • 逾期天数: 最大值 180 天,需确认是否超过业务定义的催收周期上限。
📌 清洗行动清单:
  1. 将“催收员ID”转为字符串,并处理缺失值。
  2. 将“触达时间”转为 datetime 格式。
  3. 对“通话时长”为 0 的记录,标记为“未接通”或填充为 NaN。
  4. 检查“案件金额”和“逾期天数”的极端值是否合理。

3.6 数据概览流程总图

以下 SVG 图展示了从加载数据到生成清洗清单的完整概览流程:

数据概览与基础统计流程 加载原始数据 shape:查看行数/列数 info():类型与缺失值 describe():数值分布 输出:清洗行动清单

3.7 非数值列的快速探查

对于 object 类型的列(如“触达方式”、“催收结果备注”),describe() 默认不统计。我们可以使用 value_counts() 来查看分类分布:

# 查看触达方式的分布
print(df['触达方式'].value_counts())

# 查看是否接通的分布
print(df['是否接通'].value_counts())

输出示例:

触达方式
电话外呼    35000
短信通知    10000
AI外呼      5000
Name: count, dtype: int64

是否接通
是    28000
否    22000
Name: count, dtype: int64
💡 业务洞察: 电话外呼占比 70%,但接通率仅 56%(28000/50000)。这提示我们需要重点关注“未接通”记录的清洗策略,例如是否保留、如何标记原因。