数据分析技术训练营
从零基础到实战 · 6大模块 · 视频+教程+代码+练习
数据清洗与预处理
1. 认识脏数据
在真实世界中,数据几乎从来不是完美的。打开一个 CSV 文件,你可能会发现缺失值(某些格子是空的)、重复行、异常值(比如年龄=200)、格式错误。使用 Pandas 的 df.info() 和 df.describe() 可以快速了解数据全貌。
import pandas as pd data = {'姓名': ['张三', '李四', '王五', '张三', '赵六'], '年龄': [25, 30, None, 25, 200], '工资': [5000, 8000, 6000, 5000, 7000]} df = pd.DataFrame(data) print("数据形状:", df.shape) print(df.isnull().sum()) print(df.describe())
2. 处理缺失值
缺失值处理有三种策略:删除、填充(均值/中位数/众数)、插值。
# 删除缺失行 df_clean = df.dropna() # 中位数填充(对异常值更鲁棒) df_filled = df.fillna({'年龄': df['年龄'].median()}) print("填充后:", df_filled)
3. 重复值与异常值
使用 df.duplicated() 检测重复行。使用 IQR 方法检测异常值。
import numpy as np print("重复行:", df.duplicated().sum()) Q1, Q3 = df['年龄'].quantile([0.25, 0.75]) IQR = Q3 - Q1 outliers = df[(df['年龄'] < Q1-1.5*IQR) | (df['年龄'] > Q3+1.5*IQR)] print("异常值:\n", outliers)
数据科学界名言:"Garbage In, Garbage Out"。数据科学家约花费 60-80% 的时间在数据清洗上。
删除:缺失 < 5% 时最简单。均值:适合正态分布。中位数:有异常值时更鲁棒。众数:适合分类数据。
特征工程实战
1. 标准化与归一化
标准化将数据转为均值0、标准差1。归一化缩放到 [0, 1]。特征量纲差异大时必须先做标准化。
import numpy as np data = np.array([[25,5000],[30,8000],[35,12000],[40,15000]]) # 标准化 data_std = (data - data.mean(axis=0)) / data.std(axis=0) print("标准化后均值:", data_std.mean(axis=0).round(4)) # 归一化 data_norm = (data - data.min(axis=0)) / (data.max(axis=0) - data.min(axis=0)) print("归一化范围:", data_norm.min(axis=0), "~", data_norm.max(axis=0))
2. 编码技术
标签编码将分类值映射为整数。独热编码为每个类别创建二进制列。
import pandas as pd colors = pd.Series(['红','绿','蓝','红','绿']) print("标签编码:", colors.map({v:i for i,v in enumerate(colors.unique())}).tolist()) print("独热编码:\n", pd.get_dummies(colors, prefix='颜色'))
3. 特征创建
从现有特征创造新特征:数学组合、日期拆分、文本提取。
import pandas as pd df = pd.DataFrame({'建造年份':[2000,1995,2010],'总面积':[120,85,150],'价格':[300,220,450]}) df['房屋年龄'] = 2024 - df['建造年份'] df['每平米价格'] = (df['价格'] / df['总面积']).round(2) print(df)
"特征决定上限,模型只是逼近上限"。好的特征能让简单模型超越复杂模型。
标准化适合 SVM、逻辑回归。归一化适合 KNN、图像处理。有异常值时优先用标准化。
数据建模与分析
1. 线性回归
用 y = wx + b 拟合数据,最小化均方误差(MSE)。
import numpy as np X = np.array([1,2,3,4,5], dtype=float) y = np.array([2.1,3.9,6.2,7.8,10.1]) w = ((X-X.mean())*(y-y.mean())).sum() / ((X-X.mean())**2).sum() b = y.mean() - w*X.mean() y_pred = w*X + b r2 = 1 - ((y-y_pred)**2).sum()/((y-y.mean())**2).sum() print(f"y = {w:.2f}x + {b:.2f}, R² = {r2:.4f}")
2. 逻辑回归(分类)
通过 Sigmoid 函数映射到 [0,1] 概率值,用于二分类。
import numpy as np def sigmoid(z): return 1/(1+np.exp(-z)) hours = np.array([1,2,3,4,5,6,7,8], dtype=float) passed = np.array([0,0,0,1,0,1,1,1]) prob = sigmoid(0.8*hours - 3.0) pred = (prob >= 0.5).astype(int) print(f"准确率: {(pred==passed).mean():.2%}")
3. 模型评估
回归看 R²/MAE/RMSE,分类看精确率/召回率/F1。
import numpy as np yt = np.array([1,0,1,1,0,1,0,0,1,1]) yp = np.array([1,0,1,0,0,1,1,0,1,1]) tp=((yp==1)&(yt==1)).sum(); fp=((yp==1)&(yt==0)).sum() fn=((yp==0)&(yt==1)).sum(); tn=((yp==0)&(yt==0)).sum() prec=tp/(tp+fp) if tp+fp else 0; rec=tp/(tp+fn) if tp+fn else 0 f1=2*prec*rec/(prec+rec) if prec+rec else 0 print(f"准确率:{(tp+tn)/len(yt):.2%} 精确率:{prec:.2%} 召回率:{rec:.2%} F1:{f1:.2%}")
K 折交叉验证将数据分成 K 份轮流测试,取平均值,结果更稳定可靠。
过拟合:训练好但测试差(死记硬背)。欠拟合:训练和测试都差(太简单)。
SQL 高级查询技巧
1. SQL 基础查询
SELECT 选择列,FROM 指定表,WHERE 过滤条件。
SELECT name, salary FROM employees WHERE salary > 5000 AND department = '技术部' ORDER BY salary DESC LIMIT 10;
2. 聚合与分组
GROUP BY 分组,HAVING 过滤组。
SELECT department, COUNT(*) AS 人数, AVG(salary) AS 平均工资 FROM employees GROUP BY department HAVING AVG(salary) > 5000;
3. 窗口函数
不折叠行,为每行计算额外值。
SELECT name, salary, ROW_NUMBER() OVER(PARTITION BY department ORDER BY salary DESC) AS 排名 FROM employees; SELECT month, revenue, LAG(revenue, 1) OVER(ORDER BY month) AS 上月 FROM sales;
WHERE 分组前过滤行。HAVING 分组后过滤组。执行顺序:FROM->WHERE->GROUP BY->HAVING->SELECT。
ROW_NUMBER:连续 1,2,3,4。RANK:并列跳号 1,2,2,4。DENSE_RANK:并列不跳 1,2,2,3。
Python 数据分析库
1. NumPy 基础
ndarray 数组,向量化运算比循环快 10-100 倍。
import numpy as np arr = np.array([1,2,3,4,5]) print("向量化:", arr * 2 + 10) print("均值:", arr.mean(), "标准差:", arr.std()) a = np.array([[1,2,3]]); b = np.array([[10],[20]]) print("广播:\n", a + b)
2. Pandas 数据操作
核心操作:筛选、分组、聚合、合并。
import pandas as pd df = pd.DataFrame({'部门':['技术','市场','技术'],'工资':[8000,6000,12000]}) print(df[df['工资'] > 7000]) print(df.groupby('部门').agg(平均工资=('工资','mean')))
3. 文本可视化
months = ['1月','2月','3月','4月','5月','6月'] sales = [100,120,115,140,135,160] for m, s in zip(months, sales): print(f" {m} | {'█' * int(s/max(sales)*30)} {s}万")
NumPy 底层用 C 语言实现,利用连续内存和 SIMD 指令集,向量化运算避免了 Python 循环开销。
df.loc[] 基于标签索引。df.iloc[] 基于位置索引。记忆:loc=label,iloc=integer location。
数据挖掘算法应用
1. K-Means 聚类
把数据分成 K 组,使组内相似、组间不同。步骤:选中心->分配->更新->重复。
import numpy as np def kmeans(X, k, max_iters=100): np.random.seed(42) centers = X[np.random.choice(len(X), k, replace=False)].copy() for _ in range(max_iters): dists = np.array([[np.sqrt(((x-c)**2).sum()) for c in centers] for x in X]) labels = dists.argmin(axis=1) new_c = np.array([X[labels==i].mean(axis=0) for i in range(k)]) if np.allclose(centers, new_c): break centers = new_c return labels, centers np.random.seed(42) X = np.vstack([np.random.normal([2,2],0.5,(30,2)), np.random.normal([8,8],0.5,(30,2)), np.random.normal([2,8],0.5,(30,2))]) labels, centers = kmeans(X, 3) for i in range(3): print(f"簇{i}: {(labels==i).sum()}个点, 中心=({centers[i][0]:.1f}, {centers[i][1]:.1f})")
2. PCA 降维
把高维数据压缩到低维,保留主要信息。
import numpy as np np.random.seed(42) X = np.random.randn(100, 5) # 手动 PCA X_centered = X - X.mean(axis=0) cov = np.cov(X_centered, rowvar=False) eigenvalues, eigenvectors = np.linalg.eigh(cov) idx = np.argsort(eigenvalues)[::-1] eigenvalues = eigenvalues[idx] eigenvectors = eigenvectors[:, idx] variance_ratio = eigenvalues / eigenvalues.sum() print("各主成分方差解释率:", variance_ratio.round(4)) print("前2个累计:", variance_ratio[:2].sum().round(4))
3. 时间序列分析
移动平均、指数平滑,用于趋势预测。
import numpy as np np.random.seed(42) sales = np.cumsum(np.random.randn(12) * 10) + 100 months = [f'{i+1}月' for i in range(12)] # 3个月移动平均 ma3 = np.convolve(sales, np.ones(3)/3, mode='valid') print("月份 | 实际 | MA3") for i in range(len(ma3)): print(f" {months[i+1]} | {sales[i+1]:.1f} | {ma3[i]:.1f}")
常用肘部法则:计算不同 K 值的簇内误差平方和(SSE),画图找"拐点"。拐点对应的 K 就是最优值。
会。方差解释率告诉我们保留了多少信息。通常保留累计解释率 > 85% 的主成分即可。