目录
[如何读取 csv、excel?如何指定编码、索引?](#如何读取 csv、excel?如何指定编码、索引?)
[拿到一个 DataFrame,你第一步会看什么?](#拿到一个 DataFrame,你第一步会看什么?)
[多表合并用什么?和 SQL 的 JOIN 对应什么?](#多表合并用什么?和 SQL 的 JOIN 对应什么?)
[用 Pandas 做 Excel 透视表](#用 Pandas 做 Excel 透视表)
[根据分数新增等级列(优秀 / 良好 / 及格)](#根据分数新增等级列(优秀 / 良好 / 及格))
[行转列、列转行(melt /pivot)](#行转列、列转行(melt /pivot))
[apply/map/applymap 区别](#apply/map/applymap 区别)
为什么会出现SettingWithCopyWarning这个警告?怎么解决?
[如何实现 SQL 的 group by having?](#如何实现 SQL 的 group by having?)
[导出 Excel / CSV](#导出 Excel / CSV)
[NumPy 数组(ndarray)和 Python 列表 list 的区别?](#NumPy 数组(ndarray)和 Python 列表 list 的区别?)
[数据归一化 / 标准化](#数据归一化 / 标准化)
[用 NumPy 实现 3σ 异常值筛选](#用 NumPy 实现 3σ 异常值筛选)
[np.where 用法](#np.where 用法)
[为什么要设置 dtype?](#为什么要设置 dtype?)
[Matplotlib + Seaborn](#Matplotlib + Seaborn)
[Matplotlib 是什么?Seaborn 是什么?关系?](#Matplotlib 是什么?Seaborn 是什么?关系?)
[Matplotlib 两张图:figure /axes 是什么?](#Matplotlib 两张图:figure /axes 是什么?)
[Seaborn-绘制柱状图(带误差棒 / 分组)](#Seaborn-绘制柱状图(带误差棒 / 分组))
[Matplotlib vs Seaborn 区别?](#Matplotlib vs Seaborn 区别?)
[SciPy 是什么,在数据分析里用来干什么?](#SciPy 是什么,在数据分析里用来干什么?)
[什么是 p 值?](#什么是 p 值?)
[独立样本 t 检验](#独立样本 t 检验)
[配对样本 t 检验](#配对样本 t 检验)
[单样本 t 检验](#单样本 t 检验)
[方差分析 ANOVA(多组比较)](#方差分析 ANOVA(多组比较))
[秩和检验(非参数替代 t 检验)](#秩和检验(非参数替代 t 检验))
[t 检验和方差分析的区别?](#t 检验和方差分析的区别?)
[相关系数 ≠ 因果关系?](#相关系数 ≠ 因果关系?)
[p 值很小代表什么?](#p 值很小代表什么?)
[Statsmodels 是什么?和 Sklearn 有什么区别?](#Statsmodels 是什么?和 Sklearn 有什么区别?)
[如何看回归结果 summary?](#如何看回归结果 summary?)
[异常值 / 强影响点怎么检测?](#异常值 / 强影响点怎么检测?)
[Statsmodels 时间序列能干什么?](#Statsmodels 时间序列能干什么?)
[ADF 平稳性检验](#ADF 平稳性检验)
[什么时候用 Statsmodels,什么时候用 Sklearn?](#什么时候用 Statsmodels,什么时候用 Sklearn?)
[p < 0.05 代表什么?](#p < 0.05 代表什么?)
[R² 是什么意思?太低怎么办?](#R² 是什么意思?太低怎么办?)
[用 Statsmodels 做过什么业务分析?](#用 Statsmodels 做过什么业务分析?)
[Scikit-learn 是什么,在数据分析里用来干什么?](#Scikit-learn 是什么,在数据分析里用来干什么?)
[数值特征归一化 / 标准化](#数值特征归一化 / 标准化)
[缺失值处理 SimpleImputer](#缺失值处理 SimpleImputer)
[决策树 / 随机森林(最常用、最强业务解释性)](#决策树 / 随机森林(最常用、最强业务解释性))
[K-Means 聚类(用户分层、生源分层)](#K-Means 聚类(用户分层、生源分层))
[PCA 降维](#PCA 降维)
[网格搜索 GridSearchCV](#网格搜索 GridSearchCV)
[用 sklearn 做过什么实际分析?](#用 sklearn 做过什么实际分析?)
[逻辑回归 / 决策树 / 随机森林怎么选?](#逻辑回归 / 决策树 / 随机森林怎么选?)
[K-Means 是什么?](#K-Means 是什么?)
[K-Means 的执行过程?](#K-Means 的执行过程?)
[K 怎么确定?](#K 怎么确定?)
[K-Means 优缺点?](#K-Means 优缺点?)
[K-Means 为什么要标准化 / 归一化?](#K-Means 为什么要标准化 / 归一化?)
[K-Means 遇到异常值怎么办?](#K-Means 遇到异常值怎么办?)
[用 K-Means 做过什么?](#用 K-Means 做过什么?)
Pandas
Pandas作用?
主要用 Pandas 做数据读取、清洗、分组聚合、多表关联和特征工程,是日常最核心的库。
如何读取 csv、excel?如何指定编码、索引?
注释:编码常用 utf-8 / gbk,中文乱码常用 encoding='gbk' 或 encoding='gb2312'。
读取 CSV
python
import pandas as pd
df = pd.read_csv("data.csv", encoding="utf-8")
读取 Excel
python
import pandas as pd
df = pd.read_excel("data.xlsx", sheet_name="Sheet1")
读取时指定索引列
python
import pandas as pd
df = pd.read_csv("data.csv", index_col="id")
拿到一个 DataFrame,你第一步会看什么?
先看结构、类型、空值、重复、异常值。
前5行,看数据结构
python
df.head()
字段类型、是否有空值、占用内存
python
df.info()
数值列统计(均值、分位数、最大最小)
python
df.describe()
行数, 列数
python
df.shape
每列空值数量(最重要)
python
df.isnull().sum()
如何按条件筛选行?如何选取列?
- 条件筛选(最常用)
python
df[df["age"] > 18]
- 多条件 & 且 | 或
& | 两边必须加括号,否则报错。
python
df[(df["score"] >= 60) & (df["province"] == "河南")]
- loc:按标签(行名+列名)
python
df.loc[df["score"] > 90, ["name", "score"]]
- iloc:按位置(第0行到第5行,前2列)
python
df.iloc[0:5, 0:2]
如何查看、处理缺失值?
- 数值列:均值 / 中位数 / 分位数
- 分类列:众数
- 空值很少:直接删
- 空值有规律:前向填充 ffill / 后向填充 bfill
查看空值
python
df.isnull().sum()
删除含空值的行
python
df = df.dropna()
填充 0
python
df = df.fillna(0)
连续数值用均值填充
python
df["score"] = df["score"].fillna(df["score"].mean())
分类字段用众数填充
python
df["province"] = df["province"].fillna(df["province"].mode()[0])
如何查看重复行、删除重复?
查看重复行数
python
df.duplicated().sum()
删除全部重复行
python
df = df.drop_duplicates()
按某一列去重(如按id去重,保留第一条)
python
df = df.drop_duplicates(subset=["id"], keep="first")
如何把字符串转时间?转整数?
转时间类型(非常常用)
python
df["date"] = pd.to_datetime(df["date"])
转整型
python
df["age"] = df["age"].astype(int)
查看类型
python
df.dtypes
按专业分组,统计分数的均值、最大值、人数
单指标
python
df.groupby("major")["score"].mean()
多分组 + 多聚合函数
reset_index() 非常常用,否则分组字段是索引,不方便后续处理。
python
df.groupby(["college", "major"])["score"].agg(
mean_score="mean",
max_score="max",
count="count"
).reset_index() # 把索引变回列
多表合并用什么?和 SQL 的 JOIN 对应什么?
- 按共同字段关联 → merge
- 上下堆叠数据 → concat
- 按行号 / 索引合并 → join
- merge:按列关联(对应 SQL JOIN)
python
df3 = pd.merge(df1, df2, on="id", how="left") # left join
- concat:上下拼接(追加数据)
python
df_all = pd.concat([df1, df2], axis=0)
- join:按索引合并
python
df1.join(df2)
用 Pandas 做 Excel 透视表
python
pd.pivot_table(
data=df,
index="college", # 行
columns="major", # 列
values="score", # 值
aggfunc="mean" # 聚合方式
)
根据分数新增等级列(优秀 / 良好 / 及格)
方法1:np.where(简单二分类)
python
import numpy as np
df["is_pass"] = np.where(df["score"] >= 60, 1, 0)
方法2:apply(多分类)
python
df["level"] = df["score"].apply(lambda x:
"优秀" if x >= 90 else
"良好" if x >= 70 else
"及格" if x >= 60 else "不及格"
)
方法3:pd.cut(分桶,最规范)
python
df["level"] = pd.cut(
df["score"],
bins=[0, 60, 70, 90, 100],
labels=["不及格", "及格", "良好", "优秀"]
)
如何提取年、月、日?如何按月求和?
python
df["date"] = pd.to_datetime(df["date"])
df["year"] = df["date"].dt.year
df["month"] = df["date"].dt.month
df["day"] = df["date"].dt.day
按月重采样统计
python
df.resample("M", on="date")["amount"].sum()
如何识别并剔除异常值?
超出 ±3σ 视为异常,是数据分析标准做法。
python
mean = df["score"].mean()
std = df["score"].std()
upper = mean + 3 * std
lower = mean - 3 * std
df = df[(df["score"] >= lower) & (df["score"] <= upper)]
行转列、列转行(melt /pivot)
宽表 → 长表
python
df_long = df.melt(id_vars="id", var_name="type", value_name="value")
长表 → 宽表
python
df_wide = df_long.pivot(index="id", columns="type", values="value")
apply/map/applymap 区别
map:只用于 Series,元素映射apply:可用于 Series / DataFrame,支持复杂函数applymap:对 DataFrame 每个单元格 操作(现已逐渐被map替代)
为什么会出现SettingWithCopyWarning这个警告?怎么解决?
对切片 DataFrame 直接修改,Pandas 不确定你改原表还是副本。
解决 :加上 .copy() 即可。
python
df = df[df["score"]>60].copy()
如何实现 SQL 的 group by having?
例子:筛选平均分 > 60 的专业
python
df.groupby("major").filter(lambda x: x["score"].mean() > 60)
导出 Excel / CSV
python
df.to_csv("out.csv", index=False, encoding="utf-8-sig")
df.to_excel("out.xlsx", index=False, sheet_name="结果")
NumPy
NumPy作用?
用 NumPy 做数值计算、异常值判断、数据归一化,配合 Pandas 做向量化操作。
NumPy 数组(ndarray)和 Python 列表 list 的区别?
- 数组元素类型必须统一,列表可以混放任意类型。
- 数组支持矢量化运算,不用循环,速度极快。
- 数组支持多维结构(矩阵),更适合数值计算。
- 数组占用内存更小,底层连续存储。
- 提供大量数学 / 统计函数,适合数据分析、建模。
创建数组的常用方式有哪些?
python
import numpy as np
从列表创建
python
arr = np.array([1,2,3,4])
全0/全1数组
python
arr = np.zeros((3,4))
arr = np.ones((2,2))
固定值
python
arr = np.full((2,3), 5)
等差序列
python
arr = np.arange(0, 10, 2) # 0,2,4,6,8
arr = np.linspace(0,10,5) # 均分5个点
单位矩阵
python
arr = np.eye(3)
查看数组属性
python
arr = np.array([[1,2],[3,4]])
形状 (行数,列数)
python
arr.shape
维度数
python
arr.ndim
总元素个数
python
arr.size
数据类型
python
arr.dtype
转置
python
arr.T
数组索引与切片
python
arr = np.array([[1,2,3],
[4,5,6],
[7,8,9]])
取某行
python
arr[0]
取某行某列
python
arr[0, 1]
切片:所有行,前2列
python
arr[:, :2]
布尔索引 arr[arr > 5]
python
arr[arr > 5]
什么是广播(broadcasting)?为什么重要?
- 不同形状的数组在运算时,NumPy 会自动扩展维度对齐,不需要手动循环。
- 优点:代码简洁、速度极快、内存高效。
- 是 Pandas、Matplotlib、机器学习库高效的基础。
示例:
python
a = np.array([[1,2],[3,4]])
b = np.array([10, 20])
# b 自动广播成 [[10,20],[10,20]]
print(a + b)
常用数学 / 统计函数
python
arr = np.array([1,2,3,4,5])
求和
python
np.sum(arr)
均值
python
np.mean(arr)
标准差
python
np.std(arr)
方差
python
np.var(arr)
最大值
python
np.max(arr)
最小值
python
np.min(arr)
中位数
python
np.median(arr)
最大值下标
python
np.argmax(arr)
最小值下标
python
np.argmin(arr)
累计求和
python
np.cumsum(arr)
数据归一化 / 标准化
题目:把数组缩放到 [0,1] 之间
python
arr = np.array([1,2,3,4,5])
arr_min = arr.min()
arr_max = arr.max()
# 最小-最大归一化
arr_norm = (arr - arr_min) / (arr_max - arr_min)
题目:Z-score 标准化(均值 0,方差 1)
python
arr_std = (arr - np.mean(arr)) / np.std(arr)
用 NumPy 实现 3σ 异常值筛选
python
arr = np.array([1,2,3,4,100])
mean = arr.mean()
std = arr.std()
upper = mean + 3 * std
lower = mean - 3 * std
# 保留正常范围内数据
arr_clean = arr[(arr >= lower) & (arr <= upper)]
数组形状修改
python
arr = np.arange(12)
改为3行4列
python
arr.reshape(3,4)
展平成一维
python
arr.flatten()
转置
python
arr.reshape(3,4).T
拼接与分割
python
a = np.array([[1,2],[3,4]])
b = np.array([[5,6],[7,8]])
垂直拼接(上下)
python
np.vstack([a, b])
水平拼接(左右)
python
np.hstack([a, b])
均等分割
python
np.vsplit(a, 2)
np.hsplit(a, 2)
np.where 用法
python
arr = np.array([1,2,3,4,5])
满足条件返回x,否则y
python
new_arr = np.where(arr > 3, 100, 0)
只返回满足条件的下标
python
idx = np.where(arr > 3)
去重、唯一值
python
arr = np.array([1,2,2,3,3,3])
去重
python
np.unique(arr)
去重 + 计数
python
vals, counts = np.unique(arr, return_counts=True)
空值(NaN)相关问题
python
arr = np.array([1, 2, np.nan, 4])
判断是否 NaN
python
np.isnan(arr)
注意:np.nan == np.nan 是 False,正确删除 NaN
python
arr[~np.isnan(arr)]
算时自动跳过 NaN
python
np.nanmean(arr)
np.nansum(arr)
np.nanstd(arr)
为什么要设置 dtype?
- 控制内存占用(int8/int32/float64)
- 避免溢出、计算错误
- 提升运算速度
python
arr = np.array([1,2,3], dtype=np.float32)
随机数生成
0~1 均匀分布
python
np.random.rand(3,3)
标准正态分布
python
np.random.randn(3,3)
整数随机
python
np.random.randint(0,10, size=(2,2))
打乱顺序
python
np.random.shuffle(arr)
设置随机种子,保证可复现
python
np.random.seed(42)
Matplotlib + Seaborn
Matplotlib 是什么?Seaborn 是什么?关系?
- Matplotlib:Python 最基础的绘图库,可以画几乎所有静态图表,自由度极高。
- Seaborn:基于 Matplotlib 封装的统计可视化库,语法更简洁、图更美观,专门用于数据分析。
- 关系:Seaborn 底层是 Matplotlib,可以互相配合使用。
数据分析常用哪些图表?分别用于什么场景?
- 折线图:看趋势、时间变化
- 柱状图 / 条形图:类别对比
- 直方图 / 核密度图:看数据分布
- 箱线图:看异常值、分位数、分布范围
- 散点图:看变量相关性
- 热力图:看相关系数矩阵
- 饼图:看占比
Matplotlib 两张图:figure /axes 是什么?
figure:画布,整张图的容器axes:子图,真正画图的区域- 现在推荐用 OO 风格 :
fig, ax = plt.subplots()
Matplotlib-绘制最简单的折线图
python
import matplotlib.pyplot as plt
import numpy as np
x = [1,2,3,4,5]
y = [2,4,6,8,10]
# 创建画布
fig, ax = plt.subplots(figsize=(8,4))
# 画折线
ax.plot(x, y, color='red', linewidth=2, marker='o', label='y=2x')
# 标题、标签
ax.set_title('折线图示例', fontsize=14)
ax.set_xlabel('X轴')
ax.set_ylabel('Y轴')
# 图例
ax.legend()
# 网格
ax.grid(True, alpha=0.3)
plt.show()
Matplotlib-画柱状图
python
x = ['A','B','C','D']
y = [10,25,18,32]
fig, ax = plt.subplots()
ax.bar(x, y, color='steelblue')
ax.set_title('柱状图')
plt.show()
Matplotlib-画直方图(看分布)
python
data = np.random.randn(1000)
fig, ax = plt.subplots()
ax.hist(data, bins=30, alpha=0.7)
ax.set_title('数据分布')
plt.show()
Matplotlib-画散点图(看相关性)
python
x = np.random.randn(100)
y = x * 2 + np.random.randn(100)
fig, ax = plt.subplots()
ax.scatter(x, y, s=20, alpha=0.6)
ax.set_title('散点图')
plt.show()
Matplotlib-画子图(多图并排)
python
fig, (ax1, ax2) = plt.subplots(1,2, figsize=(10,4))
ax1.plot([1,2,3],[4,5,6])
ax2.bar(['a','b'],[10,20])
plt.tight_layout() # 自动调整间距
plt.show()
Matplotlib-如何保存图片?
dpi=300高清bbox_inches='tight'防止标题被截断
python
plt.savefig('test.png', dpi=300, bbox_inches='tight')
Matplotlib-中文乱码怎么解决?
python
plt.rcParams['font.sans-serif'] = ['SimHei'] # 黑体
plt.rcParams['axes.unicode_minus'] = False # 负号正常显示
Seaborn-绘制柱状图(带误差棒 / 分组)
python
import seaborn as sns
import pandas as pd
df = pd.DataFrame({
'major':['工','工','理','理'],
'score':[80,85,75,78]
})
sns.barplot(data=df, x='major', y='score', palette='viridis')
plt.title('各专业平均分')
plt.show()
Seaborn-箱线图(识别异常值)
python
# 单变量箱线图
sns.boxplot(y=df['score'])
# 分组箱线图
sns.boxplot(data=df, x='major', y='score')
plt.show()
Seaborn-热力图(相关系数矩阵)
用途 :看变量之间相关性,常用于生源、分数、深造率分析。
python
# 构造相关矩阵
corr = df.corr()
# 画热力图
sns.heatmap(corr, annot=True, cmap='coolwarm', fmt='.2f')
plt.title('相关性热力图')
plt.show()
Seaborn-散点图 + 拟合线(看线性关系)
python
sns.regplot(data=df, x='score', y='advance_rate')
plt.title('分数与深造率关系')
plt.show()
Seaborn-核密度图 / 分布对比
python
sns.kdeplot(df['score'], fill=True)
plt.title('分数分布')
plt.show()
Seaborn-分面图 FacetGrid(按类别分别画图)
python
g = sns.FacetGrid(df, col='major')
g.map(plt.hist, 'score')
plt.show()
Matplotlib vs Seaborn 区别?
- Matplotlib:底层、灵活、代码多、适合自定义
- Seaborn:高层、简洁、美观、适合统计分析、快速出图
- 数据分析日常:Seaborn 快速画图 + Matplotlib 微调细节
箱线图、直方图、散点图分别用来干什么?
- 箱线图:异常值 + 分位数 + 分组对比
- 直方图:数据分布(是否正态、偏态)
- 散点图:两个变量相关性、趋势
什么时候用热力图?
- 展示相关系数矩阵
- 展示交叉表、频次表
- 常用于多维度指标相关性分析(如生源分数、毕业率、深造率)
如何让图表更专业、更适合汇报?
python
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.figure(figsize=(10,5))
sns.barplot(...)
plt.title('...', fontsize=14)
plt.xlabel(...)
plt.ylabel(...)
plt.tight_layout()
plt.savefig('xxx.png', dpi=300)
做数据分析时可视化流程是什么?
- 先看数据整体:直方图 / 核密度图看分布
- 看异常值:箱线图
- 看对比:柱状图 / 条形图
- 看趋势:折线图
- 看相关性:散点图 + 热力图
- 最后用 Matplotlib 统一调整字体、标题、尺寸,导出高清图用于报告。
SciPy
SciPy 是什么,在数据分析里用来干什么?
SciPy 是基于 NumPy 的科学计算库,最常用在统计检验。
数据分析中主要用于:A/B 测试、差异显著性检验、相关性分析。
常见场景:
- 不同专业深造率是否有显著差异
- 不同生源分数是否存在真实差别
- 政策 / 干预前后效果是否显著
- 两个变量是否相关
什么是 p 值?
p 值是假设检验成立的概率。
常用显著性水平 α = 0.05
- p < 0.05:差异显著,拒绝原假设
- p > 0.05:差异不显著,不能认为有真实差别
常见统计检验怎么选?
- 两组连续数据比较 → t 检验
- 多组连续数据比较 → 方差分析 ANOVA
- 两个分类变量关系 → 卡方检验
- 两个连续变量相关性 → 皮尔逊 / 斯皮尔曼相关
- 非正态分布数据 → 秩和检验(Mann-Whitney U)
导入scipy
python
from scipy import stats
import numpy as np
正态性检验,如何检验一组数据是否符合正态分布?
t 检验前提是数据正态,否则要用秩和检验。
python
# 生成测试数据
data = np.random.normal(0, 1, 1000)
# Shapiro-Wilk 检验(小样本)
stat, p = stats.shapiro(data)
# Kolmogorov-Smirnov 检验
stat, p = stats.kstest(data, 'norm', args=(np.mean(data), np.std(data)))
print(f'p值={p:.3f}')
# p>0.05 → 符合正态
# p<0.05 → 非正态
独立样本 t 检验
比较 A/B 两组均值是否有显著差异
python
group1 = np.array([80,82,85,87,81])
group2 = np.array([75,77,72,76,74])
# 独立样本 t 检验
stat, p = stats.ttest_ind(group1, group2)
print(f't统计量={stat:.3f}, p值={p:.3f}')
# 判断
if p < 0.05:
print("差异显著")
else:
print("差异不显著")
配对样本 t 检验
同一批学生干预前 vs 干预后成绩是否显著提高
用途:政策效果、教学干预、活动效果评估。
python
before = [70,72,75,68,73]
after = [76,78,82,74,79]
stat, p = stats.ttest_rel(before, after)
单样本 t 检验
样本均值是否显著不等于某个理论值
例如:本校平均分是否显著高于全省平均分
python
data = [82,81,85,83,80]
pop_mean = 75 # 全省均值
stat, p = stats.ttest_1samp(data, pop_mean)
方差分析 ANOVA(多组比较)
3 个及以上专业的分数是否存在显著差异
python
g1 = [80,82,85]
g2 = [75,77,79]
g3 = [70,72,71]
stat, p = stats.f_oneway(g1, g2, g3)
# p<0.05 → 至少一组有差异
卡方检验(分类变量关联性)
高频场景:
- 性别 vs 升学
- 生源地 vs 毕业情况
- 专业 vs 就业类型
输入是列联表(交叉表)
python
# 列联表:行=性别,列=是否深造
table = [[50, 100],
[30, 120]]
chi2, p, dof, expected = stats.chi2_contingency(table)
# p<0.05 → 两个分类变量显著相关
皮尔逊相关系数(线性相关)
- corr 接近 1 → 强正相关
- corr 接近 -1 → 强负相关
- p<0.05 → 相关显著
python
x = [1,2,3,4,5]
y = [2,4,5,7,8]
corr, p = stats.pearsonr(x, y)
斯皮尔曼等级相关(非参数,不要求正态)
数据不符合正态时用斯皮尔曼。
python
corr, p = stats.spearmanr(x, y)
秩和检验(非参数替代 t 检验)
数据非正态时,不能用 t 检验,用 Mann-Whitney U
python
stat, p = stats.mannwhitneyu(group1, group2)
t 检验和方差分析的区别?
- t 检验:两组比较
- ANOVA:三组及以上
什么时候用非参数检验?
- 样本量小
- 数据明显不符合正态分布
- 存在极端异常值
相关系数 ≠ 因果关系?
相关只能说明一起变化,不能判断谁影响谁,也可能是第三方因素导致。
p 值很小代表什么?
代表两组差异极不可能是随机误差造成的,可以认为存在真实差异。
数据分析完整统计检验流程?
- 看数据分布 → 正态检验
- 正态 → t 检验 / ANOVA
- 非正态 → 秩和检验
- 分类变量 → 卡方检验
- 看相关性 → 皮尔逊 / 斯皮尔曼
- 看 p 值判断是否显著
Statsmodels
Statsmodels 是什么?和 Sklearn 有什么区别?
Statsmodels 是 Python 用于统计建模、统计推断 的库,侧重假设检验、p 值、置信区间、R²、残差分析等统计结果。
Sklearn 侧重预测、机器学习,不重视统计指标。
数据分析常用场景:
- 线性回归 / 逻辑回归
- 时间序列(ARIMA)
- 方差分析
- 拟合后看影响因素是否显著
总结
- 想解释因素影响、看显著性 → Statsmodels
- 想预测结果、准确率 → Sklearn
线性回归用来干什么?
分析哪些变量对目标有显著影响
量化影响大小(回归系数)
控制其他变量后,看某个因素的净影响
常用于:
- 分数 / 深造率受哪些因素影响
- 生源、性别、专业对毕业的影响
- 政策效果评估
最小二乘线性回归代码
python
import statsmodels.api as sm
import pandas as pd
import numpy as np
# 构造数据
df = pd.DataFrame({
'score': [80,85,77,79,82,83], # 因变量 Y
'study_hour': [5, 7, 4, 5, 6, 5], # 自变量 X1
'age': [19,20,19,18,20,19] # X2
})
# 1. 自变量 X 必须加常数项(截距)
X = df[['study_hour', 'age']]
X = sm.add_constant(X) # 必须加!
y = df['score']
# 2. 拟合模型
model = sm.OLS(y, X).fit()
# 3. 输出完整统计结果
print(model.summary())
注释:
add_constant不加会没有截距,结果错误.summary()是面试亮点:能看懂统计报表
如何看回归结果 summary?
1. R-squared(R²)
模型解释力,越接近 1 越好。
2. coef(系数)
变量每增加 1,y 变化多少。正 = 正向影响,负 = 负向影响。
3. P>|t|(p 值)
- p < 0.05 :变量显著
- p > 0.05:不显著,可剔除
4. std err / t
系数的统计显著性。
5. 残差诊断(JB、Prob (JB))
看残差是否正态,模型是否合理。
总结
先看 R² 判断解释力度,再看每个变量的 coef 方向与大小,最后看 p 值判断是否显著,同时观察残差是否满足正态假设。
逻辑回归(分类问题)
用于二分类问题:是否毕业、是否深造、是否就业、是否报到等。
python
# 因变量是 0/1
y = np.array([1,1,0,1,0,1])
# 建模
model = sm.Logit(y, X).fit()
print(model.summary())
输出看:
- coef:影响方向
- P>|z|:是否显著
- 预测概率:
model.predict(X)
线性回归有哪些基本假设?
- 线性:X 与 Y 线性关系
- 独立:样本相互独立
- 正态:残差近似正态分布
- 同方差:残差方差恒定
- 无多重共线性:自变量之间不高度相关
多重共线性怎么判断、怎么处理?
判断
- 看系数符号反常、p 值不显著
- 计算VIF(方差膨胀因子)
python
from statsmodels.stats.outliers_influence import variance_inflation_factor
vif = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
判断标准
- VIF > 10:严重共线性
- VIF > 5:轻度共线性
处理
- 删除其中一个变量
- 合并变量
- 正则化(ridge/lasso)
异常值 / 强影响点怎么检测?
python
# Cook 距离
infl = model.get_influence()
cook = infl.cooks_distance[0]
Cook 距离大 → 强影响点,需要检查。
Statsmodels 时间序列能干什么?
- ARIMA / SARIMA 预测
- 平稳性检验(ADF)
- 白噪声检验
- 趋势、季节性分析
ADF 平稳性检验
python
from statsmodels.tsa.stattools import adfuller
stat, p, _, _, _, _ = adfuller(ts)
# p < 0.05 → 序列平稳
什么时候用 Statsmodels,什么时候用 Sklearn?
- 做统计推断、看显著性、解释影响因素、写分析报告 → Statsmodels
- 做预测、分类、模型准确率 → Sklearn
回归系数(coef)代表什么?
控制其他变量不变的情况下,该变量每增加 1,因变量平均变化多少。
p < 0.05 代表什么?
该变量对 Y 有显著影响,不是随机误差造成的。
R² 是什么意思?太低怎么办?
R² 表示模型能解释 Y 的方差比例。
太低说明:
- 缺失重要变量
- 关系不是线性
- 噪声太大
用 Statsmodels 做过什么业务分析?
用 Statsmodels 做过影响因素分析 ,比如分析生源分数、学习时长、专业等变量对深造率 / 毕业率的影响,通过回归系数和 p 值判断哪些因素显著,最终给出可解释的分析结论,而不只是预测
Scikit-learn(sklearn)
Scikit-learn 是什么,在数据分析里用来干什么?
Python 里最通用的机器学习库,封装了几乎所有经典算法。
数据分析里主要用于:
- 分类 / 预测(是否升学、是否报到、是否流失)
- 特征重要性分析
- 聚类(用户分群、生源分群)
- 数据预处理(归一化、编码、降维)
和 Statsmodels 区别:
- sklearn:重预测、重准确率
- Statsmodels:重统计推断、重显著性、重解释
机器学习四大类
- 分类:预测类别(0/1,是否深造)
- 回归:预测连续值(分数、收入、升学概率)
- 聚类:无标签分组(用户分层、生源分层)
- 降维:PCA 等,简化特征、可视化
模型构建标准流程
- 数据读取与探索
- 特征工程(缺失值、编码、归一化)
- 划分训练集/测试集 train_test_split
- 模型初始化
- 训练 model.fit(X_train, y_train)
- 预测 model.predict(X_test)
- 评估指标(准确率、MAE、AUC 等)
- 模型优化与特征重要性
分类特征编码:OneHot、LabelEncoder
性别、专业等离散特征 → OneHotEncoder
有序类别(低/中/高)→ LabelEncoder
python
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
数值特征归一化 / 标准化
标准化(均值0方差1)→ 大多数模型首选
归一化(0~1)→ 神经网络、距离模型
python
from sklearn.preprocessing import StandardScaler, MinMaxScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
缺失值处理 SimpleImputer
均值/中位数/众数填充
python
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy='median')
数据集划分
python
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
线性回归(预测连续值,如分数)
python
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X_train, y_train)
pred = model.predict(X_test)
逻辑回归(二分类,如是否升学、是否就业)
python
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_train, y_train)
pred = model.predict(X_test)
pred_prob = model.predict_proba(X_test)[:,1]
决策树 / 随机森林(最常用、最强业务解释性)
- 能输出特征重要性 feature_importances_
- 不需要强特征标准化
- 擅长非线性关系
python
from sklearn.ensemble import RandomForestClassifier
rf = RandomForestClassifier(n_estimators=100)
rf.fit(X_train, y_train)
K-Means 聚类(用户分层、生源分层)
用途:
- 把学生分成:高分稳定型、潜力型、待关注型
- 做精细化运营 / 培养策略
python
from sklearn.cluster import KMeans
km = KMeans(n_clusters=3, random_state=42)
labels = km.fit_predict(X_scaled)
PCA 降维
python
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
分类模型指标有哪些?
- 准确率 Accuracy:总体预测对的比例
- 精确率 Precision:预测为 1 的里面真的是 1
- 召回率 Recall:真实 1 里被预测出来的比例
- F1:精确率与召回率平衡
- AUC / ROC:二分类最常用、最靠谱
python
from sklearn.metrics import accuracy_score, precision_score, recall_score, roc_auc_score
回归模型指标有哪些?
- MAE 平均绝对误差
- MSE/RMSE 均方误差 / 平方根误差
- R² 解释程度(越接近 1 越好)
python
from sklearn.metrics import mean_absolute_error, r2_score
聚类评估有哪些?
- 轮廓系数
- Calinski-Harabasz 指数
过拟合是什么?怎么解决?
模型在训练集上表现特别好,但在测试集 / 新数据上表现很差。
原因:模型把噪声、偶然规律也学会了,没有学到真正通用的模式。
表现:
- 训练集准确率 / 误差很优秀
- 测试集准确率骤降、误差飙升
- 模型太复杂,泛化能力差
解决方案:
1. 增加数据
- 数据越多,噪声影响越小,模型越容易学到真实规律。
2. 降低模型复杂度
- 线性模型:减少特征
- 决策树:减小深度、减少叶子节点
- 少用复杂模型(如深度树、复杂神经网络)
3. 正则化(最常用)
- L1 正则:让部分特征系数变为 0,自动做特征选择
- L2 正则:压缩系数大小,防止极端权重
- 逻辑回归、线性回归常用:
LogisticRegression(C=0.1)C 越小,正则越强
4. 剪枝(树模型专用)
- 限制树深度
max_depth - 限制叶子节点最小样本数
min_samples_leaf - 提前停止生长
5. 特征选择 / 降维
- 删除无关、冗余、噪声特征
- 使用 PCA、方差筛选、相关性筛选
6. 早停 Early Stopping
- 训练时监控验证集误差,不再提升就停止,防止过度学习。
7. 集成模型(简单有效)
- 随机森林、XGBoost 自带抗过拟合能力,比单棵树稳得多。
总结
过拟合就是模型在训练集表现很好,但泛化能力差,在新数据上表现差。
解决方法主要有:增加数据、降低模型复杂度、使用正则化、特征选择、剪枝,以及用随机森林这类集成模型。
欠拟合是什么?怎么解决?
模型在训练集上表现就很差,测试集也很差
原因:模型太简单、学习能力不足,连数据里的基本规律都没学会
表现:
- 训练集误差大、准确率低
- 测试集同样差
- 模型偏差(Bias)过高
解决方案:
1. 增加更有用的特征
- 手工构造特征(组合特征、交叉特征、时间特征等)
- 引入更多维度信息
2. 提高模型复杂度
- 换成更复杂的模型:线性 → 树模型 / 集成模型
- 加深树深度、增加叶子节点
3. 减少正则化
- 减小正则化强度
- 线性模型调大
C值 - 树模型减少剪枝
4. 去掉不必要的降维、特征筛选
- 别把有用信息过滤掉了
5. 训练更充分
- 增加迭代次数
- 调整学习率
| 欠拟合 Underfitting | 过拟合 Overfitting | |
|---|---|---|
| 训练集效果 | 差 | 很好 |
| 测试集效果 | 差 | 很差 |
| 模型复杂度 | 太简单 | 太复杂 |
| 核心问题 | 高偏差,没学会规律 | 高方差,学了噪声 |
| 解决思路 | 加特征、加复杂度 | 降复杂度、正则、剪枝、加数据 |
总结
欠拟合是模型太简单,在训练集上都学不好,偏差过高。
解决方法主要是:增加有效特征、提高模型复杂度、减少正则化。
而过拟合是模型太复杂,学了噪声,泛化差,需要降复杂度、正则化、剪枝、增加数据等方式解决。
什么是交叉验证?
交叉验证(Cross Validation)就是:把数据集分成多份,轮流用其中一部分当验证集,多次训练评估,最后取平均结果,让模型评估更可靠。
为什么要用交叉验证?
- 只分一次 train/test,结果容易碰巧好 / 碰巧差,不稳定。
- 交叉验证能避免运气成分,更真实地反映模型泛化能力。
- 防止你因为单次划分运气好,高估或低估模型效果。
最常用的:K 折交叉验证(K-Fold)
流程(以 5 折 为例):
- 把数据平均分成 5 份
- 第 1 次:用 1,2,3,4 份训练,第 5 份验证
- 第 2 次:用 1,2,3,5 份训练,第 4 份验证
- ...... 依次轮换
- 最后得到 5 个分数,取平均值 作为最终评估结果
python
from sklearn.model_selection import cross_val_score
# cv=5 就是 5 折交叉验证
scores = cross_val_score(model, X, y, cv=5)
# 平均分数
print(scores.mean())
总结
交叉验证是把数据集分成若干份,轮流作为验证集来多次评估模型,最后取平均结果。目的是让模型评估更稳定、可靠,避免单次划分带来的偶然性,更准确地反映模型的泛化能力。
扩展
- K 一般取多少? 常用 5 折 或 10 折
- **什么时候用留一法(LOOCV)?**数据特别少的时候
- 交叉验证的作用?
- 评估模型效果
- 调参(网格搜索)
- 对比不同模型
网格搜索 GridSearchCV
GridSearchCV = 穷举所有参数组合 + 交叉验证(CV)自动选出最好的参数。
- 模型里有很多超参数:比如随机森林的
max_depth、n_estimators逻辑回归的C(正则强度) - 人工一个个试太慢、不准
- GridSearchCV 自动遍历所有参数组合,用交叉验证打分,选出最优一组
基本流程
- 定义一个参数网格(字典):要试哪些值都列出来
- 遍历每一种参数组合
- 每组参数都做 K 折交叉验证
- 记录平均分数
- 最终输出:最优参数 + 最优分数
python
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
# 模型
rf = RandomForestClassifier()
# 定义要搜索的参数网格
param_grid = {
'max_depth': [3, 5, 7], # 树深度
'n_estimators': [50, 100, 200] # 树数量
}
# 网格搜索 + 5折交叉验证
grid = GridSearchCV(
estimator=rf,
param_grid=param_grid,
cv=5, # 5折交叉验证
scoring='roc_auc'
)
grid.fit(X_train, y_train)
# 结果
print("最优参数:", grid.best_params_)
print("最优分数:", grid.best_score_)
# 用最优模型预测
best_model = grid.best_estimator_
- 优点:结果客观、自动、可靠
- 缺点 :参数多的时候非常慢(暴力穷举)
- 更快的替代 :
RandomizedSearchCV(随机搜索,不遍历全部)
总结
GridSearchCV 是一种自动调参方法 ,它会穷举我们指定的所有参数组合,并通过交叉验证 评估每组参数的效果,最终自动选出泛化能力最好的参数组合,让模型效果更稳定、避免人工调参的主观性。
特征重要性怎么看?
特征重要性 = 这个特征对模型预测贡献有多大,值越大,说明这个特征越关键。
1. 树模型(最常用)
- 随机森林 Random Forest
- 决策树
- GBDT / XGBoost / LightGBM
2. 线性模型
- 线性回归
- 逻辑回归(看系数绝对值大小,但要先标准化)
3. 不推荐
KNN、SVM、神经网络 → 很难直接看重要性
树模型代码
python
from sklearn.ensemble import RandomForestRegressor
model = RandomForestRegressor()
model.fit(X_train, y_train)
# 查看特征重要性
importances = model.feature_importances_
# 转成DataFrame方便看
import pandas as pd
fi = pd.DataFrame({
'feature': X_train.columns,
'importance': importances
}).sort_values('importance', ascending=False)
print(fi)
原理
- 树在分裂时,用这个特征减少了多少误差(基尼系数 / 方差)
- 减少越多 → 越重要
线性模型代码
- 必须先标准化,否则量纲不同不能比
- 系数绝对值越大 → 越重要
- 正负代表影响方向
python
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X_train_scaled, y_train) # 必须先标准化!
coef = pd.DataFrame({
'feature': X_train.columns,
'coef': model.coef_
}).sort_values('coef', key=abs, ascending=False)
总结
树模型(如随机森林)可以直接通过 feature_importances_ 查看特征重要性,值越大表示该特征对预测贡献越大。线性模型需要先做标准化,再看系数的绝对值大小。在分析中常用它来识别关键影响因素。
注意
- 特征重要性高 ≠ 因果关系,只是相关性
- 多重共线性会让重要性失真
- 树模型容易偏好高基数特征(如 ID、类别多的特征)
- 数据分析里最常用:随机森林看特征重要性 ,用来做因素分析
分类模型评估指标
4 个基础指标
- TP(真正例):真 1,预测 1
- FN(假反例):真 1,预测 0
- FP(假正例):真 0,预测 1
- TN(真反例):真 0,预测 0
5 大核心指标
1. 准确率 Accuracy
公式:(TP + TN) / 全部
- 所有样本里预测对的比例
- 缺点:类别不平衡时完全没用(比如 99% 是 0,瞎猜都能 99% 准确率)
2. 精确率 Precision(查准率)
预测为 1 的里面,有多少是真 1
- TP / (TP + FP)
- 场景:宁可少抓,不能抓错例如:垃圾邮件识别、推荐系统
3. 召回率 Recall(查全率)
真实为 1 的里面,有多少被找出来
- TP / (TP + FN)
- 场景:宁可错抓,不能漏掉例如:金融欺诈、疾病检测、风险识别
4. F1 分数
精确率与召回率的调和平均
- 2 * (Precision * Recall) / (Precision + Recall)
- 两者都要兼顾时用
5. AUC(最常用、最重要)
- 衡量模型整体区分能力
- 范围 0.5 ~ 1
- 0.5 = 瞎猜
- 0.7~0.8 = 可用
- 0.8~0.9 = 很好
- 0.9+ = 极强
- 优点:不受类别不平衡影响
- 数据分析面试必说 AUC
总结
分类模型常用的评估指标有:准确率、精确率、召回率、F1 和 AUC 。准确率在不平衡数据下不可靠,所以我一般优先看 AUC。业务需要少误判时看精确率,需要不漏掉目标时看召回率,两者兼顾用 F1。
标准化和归一化区别?
| 归一化 MinMaxScaler | 标准化 StandardScaler | |
|---|---|---|
| 范围 | 0~1 | 均值 0,方差 1 |
| 受异常值影响 | 很大 | 较小 |
| 数据分布要求 | 无 | 近似正态更稳 |
| 适用场景 | 固定范围、距离模型 | 大多数机器学习模型 |
- StandardScaler:均值 0 方差 1 → 通用
- MinMaxScaler:0~1 → 距离类模型(KNN、KMeans、神经网络)
用 归一化 的场景:
- KNN、K-Means、SVM 等距离 - based 模型
- 神经网络
- 需要把值限定在 0~1 之间
用 标准化 的场景:
- 线性回归、逻辑回归
- 随机森林、树模型也可以用(不强制)
- 数据存在异常值时更稳
- 日常建模默认优先用标准化
树模型不需要标准化?树模型按大小排序分裂,和数值绝对大小无关。
总结
归一化是把数据缩放到 0~1 ,标准化是把数据变成 均值 0 方差 1 。归一化受异常值影响大,适合距离类模型;标准化更稳健,日常建模一般优先用标准化。
类别特征用什么编码?
一、无序分类特征(性别、专业、城市、省份)
1. One-Hot 编码(独热编码)
最常用、默认首选
- 一列变多列,只有 0/1
- 不引入大小关系
- 类别不多时用
适用:性别、专业、省份、学历等
二、有序分类特征(低 / 中 / 高、小 / 大、差 / 良 / 优)
2. 标签编码 / 有序编码 LabelEncoder / OrdinalEncoder
- 按顺序映射成 0,1,2...
- 保留大小关系
适用:成绩等级、风险等级、教育阶段
三、高基数类别(用户 ID、手机号、学校编号、超多省份)
3. 频率编码(计数编码)
用出现次数代替类别
4. 目标编码(均值编码)
用该类别对应的目标均值编码(比如:某专业深造率 = 编码)
适用:类别特别多、one-hot 会爆炸的场景
四、树模型 vs 线性模型怎么选?
树模型(随机森林、XGBoost)
- 可以直接用标签编码
- 也可以用 目标编码
- 一般不用 one-hot(会影响效果)
线性模型 / 逻辑回归 / KNN / 神经网络
- 必须用 One-Hot
- 不能直接用标签编码(会引入虚假大小关系)
总结
类别不多的无序特征用 One-Hot 编码 ;有序特征用 标签编码或有序编码 ;类别特别多的高基数特征用 频率编码或目标编码;线性模型必须用 One-Hot,树模型可以直接用标签编码或目标编码。
用 sklearn 做过什么实际分析?
用 sklearn 做过学生升学概率预测模型,用随机森林看特征重要性,识别出影响深造的关键因素,并用聚类做学生分层,辅助制定针对性培养策略。
类别不平衡(比如很少人违约、很少人辍学)怎么办?
1. 更换评估指标(最简单、第一步必做)
- 不用 Accuracy 准确率(会骗人)
- 改用:
- AUC
- F1 分数
- Recall 召回率
2. 调整样本(最常用)
(1)过采样 Oversampling
- 对少数类重复采样、生成样本
- 优点:用足少量信息
- 缺点:容易过拟合
(2)欠采样 Undersampling
- 对多数类随机删掉一些
- 优点:快、简单
- 缺点:丢信息
(3)SMOTE 算法
- 在少数类样本之间插值生成新样本
- 比简单过采样更不容易过拟合
- 最常用、最推荐
3. 类别权重 Class Weight
直接在模型里给少数类更高的权重,惩罚错分。
代码示例:
python
# 逻辑回归
LogisticRegression(class_weight='balanced')
# 随机森林
RandomForestClassifier(class_weight='balanced')
不用改数据,效果往往很好。
4. 阈值移动 Threshold Moving
模型默认阈值 0.5,我们调低阈值(如 0.2、0.3),让模型更容易预测为少数类,提高召回率。
5. 集成方法
- 对多数类多次欠采样
- 训练多个模型
- 最后投票不容易过拟合,效果稳定。
总结
类别不平衡时,首先不使用准确率 ,改用 AUC、F1、召回率。然后可以用SMOTE 过采样 或欠采样 平衡数据。最简单有效的是直接设置 class_weight='balanced' 调整类别权重。也可以通过降低阈值提高少数类的识别率。
逻辑回归 / 决策树 / 随机森林怎么选?
- 逻辑回归 :线性模型,可解释性极强,速度快
- 决策树 :非线性,可解释,但容易过拟合
- 随机森林 :多棵树集成,效果最好、最稳,泛化能力强
1. 逻辑回归 Logistic Regression
- 类型:线性模型
- 优点 :
- 速度极快
- 可解释性最强(能看系数、显著性、概率)
- 不容易过拟合
- 输出是概率,方便业务理解
- 缺点 :
- 只能学线性关系
- 无法处理复杂交互
- 适合场景 :
- 需要清晰解释因素影响(如:哪些因素影响升学 / 违约)
- 数据量很大、要求快
- 线上简单预测
2. 决策树 Decision Tree
- 类型:非线性、规则模型
- 优点 :
- 可解释(能画树、能读规则)
- 不用标准化
- 能处理非线性、特征交互
- 缺点 :
- 非常容易过拟合
- 不稳定,数据一变树就大变
- 适合场景 :
- 小数据、需要白盒规则
- 做初步探索分析
- 一般不直接用于最终建模
3. 随机森林 Random Forest
- 类型:集成模型(多棵决策树投票)
- 优点 :
- 效果通常最好
- 抗过拟合、稳定性强
- 能处理非线性、异常值、多重共线性
- 能输出特征重要性(数据分析神器)
- 缺点 :
- 比逻辑回归慢一点
- 可解释性比逻辑回归差(黑盒)
- 适合场景 :
- 通用首选模型
- 效果优先、不知道用啥时就用它
- 找关键影响因素(特征重要性)
- 分类 / 回归都强
怎么选?
1. 优先选 逻辑回归
- 需要强可解释性
- 要报告系数、显著性、影响方向
- 数据大、要求速度
2. 优先选 随机森林
- 追求预测效果
- 存在非线性、特征交互
- 想看特征重要性
- 不知道用啥模型时的默认首选
3. 一般不单独用决策树
- 容易过拟合、不稳定
- 要用也用剪枝,或直接升级成随机森林
总结
逻辑回归线性、可解释性最强 ,适合需要清晰说明因素影响的场景;决策树能处理非线性,但容易过拟合;随机森林是集成模型,效果最稳定、泛化能力最强 ,还能输出特征重要性,是我做数据分析时的通用首选模型。
K-Means
K-Means 是什么?
K-means 属于 Scikit-learn,是无监督聚类算法,把相似的样本自动分成 K 个簇。不需要标签 y,只需要特征 X。
python
from sklearn.cluster import KMeans
K-Means 的执行过程?
- 随机选 K 个点作为初始质心
- 每个样本计算到质心距离,归到最近的簇
- 重新计算每个簇的新质心(均值)
- 重复 2、3,直到质心不再变化
归类 → 求中心 → 再归类
K 怎么确定?
- **手肘法(Elbow Method)**看簇内误差平方和 SSE 下降趋势,拐弯点就是 K
- **轮廓系数(Silhouette Score)**越大聚类效果越好
- 结合业务:比如分 3 类:高价值 / 中等 / 普通
K-Means 优缺点?
优点
- 简单、快、好用
- 大数据集也能跑
- 客户分群、用户分层神器
缺点
- 需要手动指定 K
- 对异常值极敏感
- 对量纲敏感(必须标准化)
- 只能发现凸、球形簇,不规则形状不行
- 初始质心影响结果(要设 random_state)
K-Means 为什么要标准化 / 归一化?
因为 K-Means 基于距离(欧氏距离)。如果特征量纲不一样(比如年龄 0-100,收入 0-100 万),收入会直接主导距离,结果失真。
必须用 StandardScaler 或 MinMaxScaler。
K-Means 遇到异常值怎么办?
- 先删异常值
- 或用 K-Medians(更稳,但 sklearn 没有)
- 或用 DBSCAN 密度聚类替代
用 K-Means 做过什么?
做用户 / 学生分层,比如根据成绩、活跃度、消费等特征聚类,分成高潜力、普通、待关注群体,用于精细化运营和策略分析。