pydata-book高级数据分析技巧深度剖析
本文深度剖析了pydata-book中关于数据聚合分组、时间序列分析、数据可视化及建模库集成等高级数据分析技巧。文章通过丰富的代码示例和实战案例,详细介绍了使用pandas进行高效数据分组统计、时间序列处理、matplotlib和seaborn可视化,以及statsmodels和scikit-learn建模集成的完整流程,为读者提供了从数据处理到模型部署的全面指导。
数据聚合与分组操作实战
在数据分析的实际应用中,数据聚合与分组操作是最核心且最常用的技术之一。通过pandas强大的groupby功能,我们可以轻松地对数据进行分组统计、聚合计算和复杂的数据转换。本章将深入探讨数据聚合与分组操作的各种实战技巧,帮助您掌握这一关键数据分析技能。
基础分组操作
让我们从最基本的分组操作开始。假设我们有一个包含餐厅小费数据的DataFrame:
import pandas as pd
import numpy as np
# 读取小费数据集
tips = pd.read_csv('examples/tips.csv')
print(tips.head())
| total_bill | tip | smoker | day | time | size |
|---|---|---|---|---|---|
| 16.99 | 1.01 | No | Sun | Dinner | 2 |
| 10.34 | 1.66 | No | Sun | Dinner | 3 |
| 21.01 | 3.5 | No | Sun | Dinner | 3 |
| 23.68 | 3.31 | No | Sun | Dinner | 2 |
| 24.59 | 3.61 | No | Sun | Dinner | 4 |
单列分组与聚合
最基本的groupby操作是按单个列进行分组并计算聚合统计量:
# 按吸烟状态分组,计算小费的平均值
tips_grouped = tips.groupby('smoker')['tip'].mean()
print(tips_grouped)
smoker
No 2.991854
Yes 3.008710
Name: tip, dtype: float64
多列分组操作
在实际分析中,我们经常需要按多个维度进行分组:
# 按日期和吸烟状态进行分组
grouped_multiple = tips.groupby(['day', 'smoker'])
result = grouped_multiple['total_bill'].agg(['mean', 'std', 'count'])
print(result)
| day | smoker | mean | std | count |
|---|---|---|---|---|
| Fri | No | 18.42 | 4.15 | 4 |
| Fri | Yes | 16.81 | 3.76 | 15 |
| Sat | No | 19.66 | 8.33 | 45 |
| Sat | Yes | 21.28 | 8.98 | 42 |
| Sun | No | 20.51 | 9.25 | 57 |
| Sun | Yes | 24.12 | 9.68 | 19 |
| Thur | No | 17.11 | 3.91 | 45 |
| Thur | Yes | 19.19 | 4.79 | 17 |
自定义聚合函数
除了内置的聚合函数,我们还可以使用自定义函数:
# 定义自定义聚合函数:极差(最大值-最小值)
def peak_to_peak(arr):
return arr.max() - arr.min()
# 应用自定义聚合函数
custom_agg = tips.groupby('day')['total_bill'].agg(peak_to_peak)
print(custom_agg)
day
Fri 34.65
Sat 48.27
Sun 47.74
Thur 35.83
Name: total_bill, dtype: float64
多函数聚合
我们可以同时对多个列应用多个聚合函数:
# 对多个列应用多个聚合函数
multi_agg = tips.groupby(['day', 'smoker']).agg({
'total_bill': ['mean', 'max', 'min'],
'tip': ['mean', 'std'],
'size': 'sum'
})
print(multi_agg)
分组后的数据转换
groupby不仅用于聚合,还可以进行数据转换:
# 计算每个组内的小费百分比
tips['tip_pct'] = tips['tip'] / tips['total_bill']
# 按日期分组并标准化小费百分比
def standardize(group):
return (group - group.mean()) / group.std()
standardized = tips.groupby('day')['tip_pct'].transform(standardize)
tips['tip_pct_standardized'] = standardized
分组筛选操作
我们可以基于分组统计结果来筛选数据:
# 筛选出小费百分比高于组平均值的记录
def filter_high_tippers(group):
return group[group['tip_pct'] > group['tip_pct'].mean()]
high_tippers = tips.groupby('day').apply(filter_high_tippers)
print(high_tippers.head())
时间序列分组
对于时间序列数据,我们可以使用重采样进行分组:
# 创建示例时间序列数据
date_range = pd.date_range('2023-01-01', periods=100, freq='D')
time_series = pd.DataFrame({
'value': np.random.randn(100).cumsum(),
'category': np.random.choice(['A', 'B', 'C'], 100)
}, index=date_range)
# 按月份和类别分组
monthly_grouped = time_series.groupby([
pd.Grouper(freq='M'),
'category'
])['value'].mean()
高级分组技巧
# 使用字典进行列分组
column_mapping = {'total_bill': 'amount', 'tip': 'amount', 'size': 'count'}
column_grouped = tips.groupby(column_mapping, axis=1).sum()
# 使用函数进行分组
def time_of_day(time_str):
if time_str == 'Lunch':
return 'Day'
else:
return 'Night'
time_grouped = tips.groupby(time_of_day)['total_bill'].mean()
性能优化技巧
对于大数据集,分组操作可能需要优化:
# 使用categorical类型优化分组性能
tips['day'] = tips['day'].astype('category')
tips['smoker'] = tips['smoker'].astype('category')
# 使用numba加速自定义函数
import numba
@numba.jit
def fast_peak_to_peak(arr):
return arr.max() - arr.min()
# 应用优化后的函数
optimized_result = tips.groupby('day')['total_bill'].agg(fast_peak_to_peak)
实战案例:餐厅数据分析
让我们通过一个完整的案例来展示分组操作的强大功能:
# 综合分组分析
analysis_result = tips.groupby(['day', 'time', 'smoker']).agg({
'total_bill': ['count', 'mean', 'std', 'min', 'max'],
'tip': ['mean', 'median', lambda x: x.quantile(0.75)],
'size': ['mean', 'sum']
}).round(2)
# 重命名列
analysis_result.columns = [
'订单数', '平均消费', '消费标准差', '最低消费', '最高消费',
'平均小费', '小费中位数', '小费75分位数',
'平均人数', '总人数'
]
print(analysis_result)
通过掌握这些数据聚合与分组操作技巧,您将能够高效地进行复杂的数据分析任务,从简单的统计汇总到高级的数据转换,都能游刃有余。记住,熟练运用groupby是成为数据分析高手的必经之路。
时间序列数据分析方法
时间序列数据分析是数据科学中至关重要的技能,特别是在金融、物联网、商业智能等领域。pydata-book项目通过第11章全面展示了如何使用pandas进行高效的时间序列处理,涵盖了从基础操作到高级分析的完整流程。
时间序列基础操作
时间序列数据的核心在于索引的处理。pandas提供了强大的时间索引功能,能够轻松处理各种时间频率的数据:
import pandas as pd
import numpy as np
from datetime import datetime
# 创建基础时间序列
dates = [datetime(2011, 1, 2), datetime(2011, 1, 5), datetime(2011, 1, 7)]
ts = pd.Series(np.random.standard_normal(3), index=dates)
print(ts)
输出结果:
2011-01-02 -0.1724
2011-01-05 0.7658
2011-01-07 -0.0037
dtype: float64
时间索引的切片与选择
pandas的时间索引支持灵活的切片操作,可以按年、月、日等不同粒度进行数据选择:
# 创建长时间序列
longer_ts = pd.Series(np.random.standard_normal(1000),
index=pd.date_range("2000-01-01", periods=1000))
# 按年份选择
year_2001 = longer_ts["2001"]
print(f"2001年数据长度: {len(year_2001)}")
# 按年月选择
may_2001 = longer_ts["2001-05"]
print(f"2001年5月数据长度: {len(may_2001)}")
重采样与频率转换
重采样是时间序列分析中的核心技术,可以将数据从一种频率转换为另一种频率:
# 日数据重采样为月数据
monthly_data = ts.resample("M").mean()
print("月度重采样结果:")
print(monthly_data)
# 使用不同聚合方法
monthly_sum = ts.resample("M").sum()
monthly_count = ts.resample("M").count()
移动窗口操作
移动窗口统计是时间序列分析的重要技术,用于计算滚动平均值、标准差等:
# 创建示例金融时间序列
close_px = pd.DataFrame({
'AAPL': np.random.randn(1000).cumsum() + 100,
'MSFT': np.random.randn(1000).cumsum() + 50
}, index=pd.date_range('2000-01-01', periods=1000))
# 计算250日移动平均
rolling_mean = close_px['AAPL'].rolling(250).mean()
print("250日移动平均值前5个:")
print(rolling_mean.head())
# 计算滚动标准差
rolling_std = close_px['AAPL'].pct_change().rolling(250, min_periods=10).std()
时间序列数据清洗
处理时间序列数据时经常遇到缺失值和不规则频率的问题:
# 处理缺失值
frame = pd.DataFrame(np.random.standard_normal((365, 4)),
index=pd.date_range('2000-01-01', periods=365),
columns=['A', 'B', 'C', 'D'])
# 前向填充缺失值
filled_frame = frame.resample("D").ffill(limit=2)
print("前向填充后的数据形状:", filled_frame.shape)
# 使用不同填充策略
asfreq_result = frame.resample("D").asfreq()
高级时间序列操作
pandas支持更复杂的时间序列操作,包括时间偏移、周期转换等:
# 时间偏移操作
ts_shifted = ts.shift(2) # 向后移动2个周期
ts_shifted_negative = ts.shift(-2) # 向前移动2个周期
# 带频率的时间偏移
ts_shifted_freq = ts.shift(2, freq="M") # 移动2个月
# 周期索引转换
period_index = ts.resample("M", kind="period").mean()
实际应用案例
以下是一个完整的时间序列分析流程示例:
# 1. 数据准备
dates = pd.date_range('2020-01-01', periods=500, freq='D')
data = pd.Series(np.random.randn(500).cumsum(), index=dates)
# 2. 重采样为周数据
weekly_data = data.resample('W').mean()
# 3. 计算移动平均
ma_30 = data.rolling(30).mean()
ma_90 = data.rolling(90).mean()
# 4. 计算收益率
returns = data.pct_change()
# 5. 波动率分析
volatility = returns.rolling(30).std() * np.sqrt(252) # 年化波动率
性能优化技巧
处理大规模时间序列数据时,性能优化至关重要:
| 优化技巧 | 描述 | 效果 |
|---|---|---|
使用pd.to_datetime() | 批量转换时间字符串 | 大幅提升转换速度 |
| 避免重复重采样 | 预处理数据时一次性完成 | 减少计算开销 |
使用inplace=True | 原地操作减少内存使用 | 节省内存空间 |
| 选择合适的频率 | 根据分析需求选择适当频率 | 平衡精度与性能 |
# 高效的时间序列处理示例
# 批量转换时间字符串
date_strings = ['2020-01-01', '2020-01-02', '2020-01-03']
efficient_dates = pd.to_datetime(date_strings)
# 使用合适的数据类型
ts = ts.astype('float32') # 减少内存使用
时间序列数据分析是一个深度和广度都很丰富的领域,pydata-book通过实际案例和代码示例,为学习者提供了从基础到高级的完整学习路径。掌握这些技能后,你将能够处理各种复杂的时间序列分析任务,为数据驱动的决策提供有力支持。
数据可视化与图表生成
在数据分析的完整流程中,数据可视化是至关重要的一环。pydata-book项目通过matplotlib、pandas内置绘图功能以及seaborn等库,展示了丰富的数据可视化技术。本章将深入探讨这些工具的使用方法和最佳实践。
matplotlib基础绘图
matplotlib是Python中最基础且功能强大的绘图库,提供了从简单线图到复杂子图布局的完整解决方案。
import matplotlib.pyplot as plt
import numpy as np
# 创建基础线图
data = np.arange(10)
plt.plot(data)
plt.title('基础线图示例')
plt.xlabel('X轴')
plt.ylabel('Y轴')
plt.show()
matplotlib的核心概念包括Figure(画布)、Axes(坐标系)和Artist(图形元素)。通过组合这些组件,可以创建复杂的多子图布局:
# 创建2x2子图布局
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
# 在每个子图中绘制不同类型的图表
axes[0, 0].hist(np.random.standard_normal(100), bins=20, color='black', alpha=0.3)
axes[0, 1].scatter(np.arange(30), np.arange(30) + 3 * np.random.standard_normal(30))
axes[1, 0].plot(np.random.standard_normal(50).cumsum(), color='black', linestyle='dashed')
axes[1, 1].bar(['A', 'B', 'C', 'D'], [10, 20, 15, 25])
plt.tight_layout()
plt.show()
pandas内置绘图功能
pandas库为DataFrame和Series对象提供了便捷的绘图方法,大大简化了常见图表的创建过程。
import pandas as pd
import numpy as np
# 创建示例数据
s = pd.Series(np.random.standard_normal(10).cumsum(), index=np.arange(0, 100, 10))
df = pd.DataFrame({
'A': np.random.randn(100),
'B': np.random.randn(100),
'C': np.random.randn(100)
})
# Series绘图
s.plot(title='Series线图', grid=True)
# DataFrame多列绘图
df.plot(alpha=0.5, figsize=(12, 6))
pandas支持多种图表类型,通过kind参数指定:
| 图表类型 | kind参数 | 适用场景 |
|---|---|---|
| 线图 | 'line' | 时间序列数据趋势分析 |
| 柱状图 | 'bar' | 分类数据比较 |
| 水平柱状图 | 'barh' | 长类别名称的显示 |
| 直方图 | 'hist' | 数据分布分析 |
| 箱线图 | 'box' | 数据统计特征展示 |
| 面积图 | 'area' | 累积效应展示 |
| 散点图 | 'scatter' | 变量关系分析 |
| 饼图 | 'pie' | 比例分布展示 |
高级图表定制
matplotlib提供了丰富的定制选项,可以精确控制图表的每个细节:
fig, ax = plt.subplots(figsize=(12, 6))
# 绘制多条线并添加样式
x = np.linspace(0, 10, 100)
ax.plot(x, np.sin(x), color='blue', linestyle='-', linewidth=2, label='sin(x)')
ax.plot(x, np.cos(x), color='red', linestyle='--', linewidth=2, label='cos(x)')
# 设置坐标轴和标题
ax.set_xlabel('X轴', fontsize=12)
ax.set_ylabel('Y轴', fontsize=12)
ax.set_title('三角函数图像', fontsize=14)
# 添加网格和图例
ax.grid(True, alpha=0.3)
ax
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



