背景
- 我们有两种数据(基金和股票),两个时间点(20200630和20200930),以及三个特殊变量。
- 我们需要绘制6幅图(3个变量 * 2个时间点)在一个画布上,每个图都包含基金和股票的对比,并且横向对比季度变化(即0630和0930的对比)。由于基金和股票的坐标系不同,我们需要左右两个纵轴分别表示基金和股票。
- 我们将使用seaborn包和莫兰迪色系,由于莫兰迪色系不是matplotlib内置的,这里我们假设使用seaborn的柔和颜色。
步骤
-
准备数据:假设我们有两个DataFrame,分别代表两个时间点的数据,每个DataFrame都有基金和股票的数据,并且有相同的行索引(1-1000)和列(变量)。基金和股票的数据是分开的,所以我们需要分别从两个DataFrame中提取基金和股票的三个特殊变量。
-
我们假设三个特殊变量的列名已知,例如对于基金,变量名为[‘fund_var1’, ‘fund_var2’, ‘fund_var3’],对于股票,变量名为[‘stock_var1’, ‘stock_var2’, ‘stock_var3’]。
-
创建画布:6幅图,我们可以安排成2行3列,因为有两个时间点(0630和0930)和三个变量。每个子图中,我们将绘制两个时间点的基金和股票的数据。但是注意,每个子图对应一个变量,横轴是时间(两个时间点),由于基金和股票的数据量级可能不同,所以我们需要双y轴:左边是基金,右边是股票。
-
为了区分两个时间点,我们可以用不同的颜色(莫兰迪色系中的两种颜色)分别表示0630和0930。
-
为了区分基金和股票,我们使用同一个横坐标(两个时间点),但是纵坐标分别用左右轴。
-
我们将在每个子图的右上角添加图例,最后保存为pdf和png格式。
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from pathlib import Path
# 设置中文字体和莫兰迪色系
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['font.family'] = 'SimHei'
plt.rcParams['axes.unicode_minus'] = False
# 创建莫兰迪色系
morandi_colors = ['#9B9B9B', '#D8BFAA', '#8FAADC', '#A8D8B9', '#F4A582', '#B39DDB']
# 创建模拟数据
np.random.seed(42) # 保证可重复性
# 生成模拟数据
dates = pd.date_range('2022-01-01', periods=1000, freq='D')
fund_data_0630 = pd.DataFrame({
'var1': np.random.normal(100, 15, 1000),
'var2': np.random.normal(50, 8, 1000),
'var3': np.random.normal(200, 25, 1000),
'volume': np.random.uniform(1000, 5000, 1000)
}, index=range(1, 1001))
fund_data_0930 = pd.DataFrame({
'var1': np.random.normal(105, 16, 1000),
'var2': np.random.normal(52, 9, 1000),
'var3': np.random.normal(210, 26, 1000),
'volume': np.random.uniform(1200, 5500, 1000)
}, index=range(1, 1001))
stock_data_0630 = pd.DataFrame({
'var1': np.random.normal(25, 5, 1000),
'var2': np.random.normal(15, 3, 1000),
'var3': np.random.normal(80, 12, 1000),
'volume': np.random.uniform(50000, 200000, 1000)
}, index=range(1, 1001))
stock_data_0930 = pd.DataFrame({
'var1': np.random.normal(26, 5.5, 1000),
'var2': np.random.normal(16, 3.2, 1000),
'var3': np.random.normal(85, 13, 1000),
'volume': np.random.uniform(55000, 220000, 1000)
}, index=range(1, 1001))
# 创建输出目录
output_dir = Path('financial_plots')
output_dir.mkdir(exist_ok=True)
# 创建图形和子图
fig, axes = plt.subplots(2, 3, figsize=(18, 12))
fig.suptitle('基金与股票季度变化对比分析\n(0630 vs 0930)', fontsize=16, fontweight='bold', y=0.95)
# 定义三个特殊变量
special_vars = ['var1', 'var2', 'var3']
quarters = ['0630', '0930']
# 绘制散点图
for i, var in enumerate(special_vars):
# 第一行:0630季度的对比
ax1 = axes[0, i]
# 基金数据 - 左轴
fund_scatter1 = ax1.scatter(fund_data_0630.index, fund_data_0630[var],
c=morandi_colors[0], alpha=0.7, s=30,
label='基金 0630', marker='o')
# 股票数据 - 右轴
ax1_right = ax1.twinx()
stock_scatter1 = ax1_right.scatter(stock_data_0630.index, stock_data_0630[var],
c=morandi_colors[1], alpha=0.7, s=30,
label='股票 0630', marker='s')
ax1.set_title(f'{var} - 0630季度', fontsize=12, fontweight='bold')
ax1.set_xlabel('序列索引')
ax1.set_ylabel('基金数值', color=morandi_colors[0])
ax1_right.set_ylabel('股票数值', color=morandi_colors[1])
# 设置坐标轴颜色
ax1.tick_params(axis='y', labelcolor=morandi_colors[0])
ax1_right.tick_params(axis='y', labelcolor=morandi_colors[1])
# 第二行:0930季度的对比
ax2 = axes[1, i]
# 基金数据 - 左轴
fund_scatter2 = ax2.scatter(fund_data_0930.index, fund_data_0930[var],
c=morandi_colors[2], alpha=0.7, s=30,
label='基金 0930', marker='o')
# 股票数据 - 右轴
ax2_right = ax2.twinx()
stock_scatter2 = ax2_right.scatter(stock_data_0930.index, stock_data_0930[var],
c=morandi_colors[3], alpha=0.7, s=30,
label='股票 0930', marker='s')
ax2.set_title(f'{var} - 0930季度', fontsize=12, fontweight='bold')
ax2.set_xlabel('序列索引')
ax2.set_ylabel('基金数值', color=morandi_colors[2])
ax2_right.set_ylabel('股票数值', color=morandi_colors[3])
# 设置坐标轴颜色
ax2.tick_params(axis='y', labelcolor=morandi_colors[2])
ax2_right.tick_params(axis='y', labelcolor=morandi_colors[3])
# 添加整体图例
handles = [
plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=morandi_colors[0], markersize=8, label='基金 0630'),
plt.Line2D([0], [0], marker='s', color='w', markerfacecolor=morandi_colors[1], markersize=8, label='股票 0630'),
plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=morandi_colors[2], markersize=8, label='基金 0930'),
plt.Line2D([0], [0], marker='s', color='w', markerfacecolor=morandi_colors[3], markersize=8, label='股票 0930')
]
fig.legend(handles=handles, loc='upper right', bbox_to_anchor=(0.98, 0.98),
frameon=True, fancybox=True, shadow=True, ncol=2)
# 调整布局
plt.tight_layout()
plt.subplots_adjust(top=0.9)
# 保存图片
plt.savefig(output_dir / 'fund_stock_comparison.pdf', dpi=300, bbox_inches='tight')
plt.savefig(output_dir / 'fund_stock_comparison.png', dpi=300, bbox_inches='tight')
print(f"图片已保存到: {output_dir.absolute()}")
print("生成的文件:")
print(f" - {output_dir / 'fund_stock_comparison.pdf'}")
print(f" - {output_dir / 'fund_stock_comparison.png'}")
plt.show()
# 添加统计分析
print("\n统计分析:")
print("=" * 50)
for var in special_vars:
print(f"\n变量 {var}:")
print(f"基金 0630: 均值={fund_data_0630[var].mean():.2f}, 标准差={fund_data_0630[var].std():.2f}")
print(f"基金 0930: 均值={fund_data_0930[var].mean():.2f}, 标准差={fund_data_0930[var].std():.2f}")
print(f"股票 0630: 均值={stock_data_0630[var].mean():.2f}, 标准差={stock_data_0630[var].std():.2f}")
print(f"股票 0930: 均值={stock_data_0930[var].mean():.2f}, 标准差={stock_data_0930[var].std():.2f}")
主要特点
运行此代码将生成一个包含6个散点图的综合对比分析,清晰地展示基金和股票数据在不同季度和不同变量上的变化趋势。
模块化分离
数据生成部分
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from pathlib import Path
def generate_financial_data():
"""
生成模拟的基金和股票季度数据
"""
np.random.seed(42) # 保证可重复性
# 生成0630季度数据
fund_data_0630 = pd.DataFrame({
'var1': np.random.normal(100, 15, 1000),
'var2': np.random.normal(50, 8, 1000),
'var3': np.random.normal(200, 25, 1000),
'volume': np.random.uniform(1000, 5000, 1000),
'returns': np.random.normal(0.05, 0.02, 1000)
}, index=range(1, 1001))
fund_data_0930 = pd.DataFrame({
'var1': np.random.normal(105, 16, 1000),
'var2': np.random.normal(52, 9, 1000),
'var3': np.random.normal(210, 26, 1000),
'volume': np.random.uniform(1200, 5500, 1000),
'returns': np.random.normal(0.06, 0.025, 1000)
}, index=range(1, 1001))
stock_data_0630 = pd.DataFrame({
'var1': np.random.normal(25, 5, 1000),
'var2': np.random.normal(15, 3, 1000),
'var3': np.random.normal(80, 12, 1000),
'volume': np.random.uniform(50000, 200000, 1000),
'returns': np.random.normal(0.08, 0.03, 1000)
}, index=range(1, 1001))
stock_data_0930 = pd.DataFrame({
'var1': np.random.normal(26, 5.5, 1000),
'var2': np.random.normal(16, 3.2, 1000),
'var3': np.random.normal(85, 13, 1000),
'volume': np.random.uniform(55000, 220000, 1000),
'returns': np.random.normal(0.09, 0.035, 1000)
}, index=range(1, 1001))
return {
'fund_0630': fund_data_0630,
'fund_0930': fund_data_0930,
'stock_0630': stock_data_0630,
'stock_0930': stock_data_0930
}
def print_data_summary(data_dict):
"""
打印数据摘要统计信息
"""
print("数据摘要统计:")
print("=" * 50)
for data_name, data in data_dict.items():
print(f"\n{data_name}:")
print(f" 形状: {data.shape}")
print(f" 变量: {list(data.columns)}")
print(f" 索引范围: {data.index.min()} - {data.index.max()}")
# 打印前三个特殊变量的统计信息
for var in ['var1', 'var2', 'var3']:
if var in data.columns:
print(f" {var}: 均值={data[var].mean():.2f}, 标准差={data[var].std():.2f}")
绘图函数部分
def create_comparison_plots(data_dict, special_vars=None, output_dir='financial_plots'):
"""
创建基金和股票季度变化对比散点图
参数:
- data_dict: 包含四个数据集的字典
- special_vars: 要绘制的特殊变量列表
- output_dir: 输出目录名称
"""
# 设置中文字体和莫兰迪色系
plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False
# 莫兰迪色系
morandi_colors = ['#9B9B9B', '#D8BFAA', '#8FAADC', '#A8D8B9', '#F4A582', '#B39DDB']
# 默认的特殊变量
if special_vars is None:
special_vars = ['var1', 'var2', 'var3']
# 创建输出目录
output_path = Path(output_dir)
output_path.mkdir(exist_ok=True)
# 创建图形和子图
fig, axes = plt.subplots(2, 3, figsize=(18, 12))
fig.suptitle('基金与股票季度变化对比分析\n(0630 vs 0930)', fontsize=16, fontweight='bold', y=0.95)
# 提取数据
fund_0630 = data_dict['fund_0630']
fund_0930 = data_dict['fund_0930']
stock_0630 = data_dict['stock_0630']
stock_0930 = data_dict['stock_0930']
# 绘制散点图
for i, var in enumerate(special_vars):
# 第一行:0630季度的对比
ax1 = axes[0, i]
# 基金数据 - 左轴
fund_scatter1 = ax1.scatter(fund_0630.index, fund_0630[var],
c=morandi_colors[0], alpha=0.7, s=30,
label='基金 0630', marker='o')
# 股票数据 - 右轴
ax1_right = ax1.twinx()
stock_scatter1 = ax1_right.scatter(stock_0630.index, stock_0630[var],
c=morandi_colors[1], alpha=0.7, s=30,
label='股票 0630', marker='s')
ax1.set_title(f'{var} - 0630季度', fontsize=12, fontweight='bold')
ax1.set_xlabel('序列索引')
ax1.set_ylabel('基金数值', color=morandi_colors[0])
ax1_right.set_ylabel('股票数值', color=morandi_colors[1])
# 设置坐标轴颜色
ax1.tick_params(axis='y', labelcolor=morandi_colors[0])
ax1_right.tick_params(axis='y', labelcolor=morandi_colors[1])
# 第二行:0930季度的对比
ax2 = axes[1, i]
# 基金数据 - 左轴
fund_scatter2 = ax2.scatter(fund_0930.index, fund_0930[var],
c=morandi_colors[2], alpha=0.7, s=30,
label='基金 0930', marker='o')
# 股票数据 - 右轴
ax2_right = ax2.twinx()
stock_scatter2 = ax2_right.scatter(stock_0930.index, stock_0930[var],
c=morandi_colors[3], alpha=0.7, s=30,
label='股票 0930', marker='s')
ax2.set_title(f'{var} - 0930季度', fontsize=12, fontweight='bold')
ax2.set_xlabel('序列索引')
ax2.set_ylabel('基金数值', color=morandi_colors[2])
ax2_right.set_ylabel('股票数值', color=morandi_colors[3])
# 设置坐标轴颜色
ax2.tick_params(axis='y', labelcolor=morandi_colors[2])
ax2_right.tick_params(axis='y', labelcolor=morandi_colors[3])
# 添加整体图例
handles = [
plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=morandi_colors[0],
markersize=8, label='基金 0630'),
plt.Line2D([0], [0], marker='s', color='w', markerfacecolor=morandi_colors[1],
markersize=8, label='股票 0630'),
plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=morandi_colors[2],
markersize=8, label='基金 0930'),
plt.Line2D([0], [0], marker='s', color='w', markerfacecolor=morandi_colors[3],
markersize=8, label='股票 0930')
]
fig.legend(handles=handles, loc='upper right', bbox_to_anchor=(0.98, 0.98),
frameon=True, fancybox=True, shadow=True, ncol=2)
# 调整布局
plt.tight_layout()
plt.subplots_adjust(top=0.9)
# 保存图片
pdf_path = output_path / 'fund_stock_comparison.pdf'
png_path = output_path / 'fund_stock_comparison.png'
plt.savefig(pdf_path, dpi=300, bbox_inches='tight')
plt.savefig(png_path, dpi=300, bbox_inches='tight')
print(f"图片已保存到: {output_path.absolute()}")
print(f"生成的文件:")
print(f" - {pdf_path}")
print(f" - {png_path}")
plt.show()
return fig
def create_advanced_plots(data_dict, special_vars=None, output_dir='financial_plots'):
"""
创建更高级的对比图表(可选功能)
"""
if special_vars is None:
special_vars = ['var1', 'var2', 'var3']
# 这里可以添加其他类型的图表
# 比如箱线图、密度图等
print("高级图表功能已准备就绪")
主程序部分
def main():
"""
主函数:生成数据并创建图表
"""
# 1. 生成数据
print("正在生成模拟数据...")
financial_data = generate_financial_data()
# 2. 打印数据摘要
print_data_summary(financial_data)
# 3. 创建对比图表
print("\n正在创建对比图表...")
fig = create_comparison_plots(
data_dict=financial_data,
special_vars=['var1', 'var2', 'var3'],
output_dir='financial_analysis_output'
)
# 4. 可选:创建高级图表
# create_advanced_plots(financial_data)
print("\n程序执行完成!")
# 运行主程序
if __name__ == "__main__":
main()

被折叠的 条评论
为什么被折叠?



