原始模版
Python (Matplotlib 和 Seaborn) 的模板,用于展示蒙特卡洛模拟数据的折线图和分布图。这个模板将包含:
- 将所有模拟路径的图分离为单独的图表,确保更清晰地展示每条路径。
- 均值和置信区间的折线图,添加统计指标(均值、偏度、峰度)。
- 最终年份值的分布直方图。
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from scipy.stats import skew, kurtosis
import os
# 设置 Seaborn 样式和调色板
sns.set_style("darkgrid")
sns.set_palette("husl")
def plot_monte_carlo_simulation(data, years, title="Monte Carlo Simulation", save_dir="output"):
"""
绘制蒙特卡洛模拟可视化图并保存为 PNG 和 PDF 格式
data: shape (n_simulations, n_years) 的数组
years: 年份列表
title: 图表标题
save_dir: 保存图片的文件夹路径
"""
# 确保保存文件夹存在
os.makedirs(save_dir, exist_ok=True)
# 图1: 所有模拟路径(单独图表)
plt.figure(figsize=(10, 6))
for i in range(data.shape[0]):
plt.plot(years, data[i, :], alpha=0.3, linewidth=0.5, label=f'Simulation {i+1}' if i < 5 else None)
plt.title('All Simulation Paths')
plt.xlabel('Year')
plt.ylabel('Value')
plt.grid(True, alpha=0.3)
# plt.legend(loc='upper left', fontsize=8, ncol=2) # 只显示前5条路径的图例,避免过于拥挤
# 保存图1
plt.savefig(os.path.join(save_dir, "simulation_paths.png"), dpi=300, bbox_inches='tight')
plt.savefig(os.path.join(save_dir, "simulation_paths.pdf"), bbox_inches='tight')
plt.tight_layout()
plt.show()
# 图2: 均值和置信区间
fig, (ax2, ax3) = plt.subplots(1, 2, figsize=(15, 5))
# 计算统计指标
mean_values = np.mean(data, axis=0)
std_values = np.std(data, axis=0)
ci_upper = mean_values + 1.96 * std_values
ci_lower = mean_values - 1.96 * std_values
# 最终年份的统计指标
final_values = data[:, -1]
mean_final = np.mean(final_values)
skew_final = skew(final_values)
kurt_final = kurtosis(final_values)
# 均值和置信区间图
ax2.plot(years, mean_values, label='Mean', linewidth=2)
ax2.fill_between(years, ci_lower, ci_upper, alpha=0.2, label='95% CI')
ax2.set_title('Mean and 95% Confidence Interval')
ax2.set_xlabel('Year')
ax2.set_ylabel('Value')
ax2.grid(True, alpha=0.3)
ax2.legend()
# 添加统计指标文本
stats_text = f'Mean (Final Year): {mean_final:.2f}\nSkewness (Final Year): {skew_final:.2f}\nKurtosis (Final Year): {kurt_final:.2f}'
ax2.text(0.02, 0.98, stats_text, transform=ax2.transAxes, verticalalignment='top',
bbox=dict(boxstyle='round', facecolor='white', alpha=0.8))
# 图3: 最终年份分布
sns.histplot(final_values, kde=True, ax=ax3)
ax3.set_title(f'Distribution at Year {years[-1]}')
ax3.set_xlabel('Value')
ax3.set_ylabel('Frequency')
plt.suptitle(title, fontsize=16)
# 保存图2
plt.savefig(os.path.join(save_dir, "mean_and_distribution.png"), dpi=300, bbox_inches='tight')
plt.savefig(os.path.join(save_dir, "mean_and_distribution.pdf"), bbox_inches='tight')
plt.tight_layout()
plt.show()
# 示例数据生成
if __name__ == "__main__":
# 生成示例数据
np.random.seed(42)
n_simulations = 1000
n_years = 100
years = np.arange(2001, 2101)
# 模拟数据 (这里用随机游走作为示例)
data = np.zeros((n_simulations, n_years))
for i in range(n_simulations):
data[i, :] = np.cumsum(np.random.normal(0, 1, n_years))
# 调用可视化函数,指定保存文件夹
plot_monte_carlo_simulation(data, years, "Example Monte Carlo Simulation", save_dir="monte_carlo_output")
代码说明
- 包含三个子图:
- 左上:所有1000条模拟路径(半透明显示)
- 左下:均值线和95%置信区间
- 右下:2100年值的分布直方图(带核密度估计)
- 需要安装的库:numpy, matplotlib, seaborn, pandas, scipy
- 数据格式:输入数据为 shape
(1000, 100)的 numpy 数组,代表1000条模拟路径,每条路径包含2001到2100年的值。 - 可通过修改 title 参数自定义图表标题
- 在均值与置信区间图和最终年份分布图中,添加了最终年份(2100年)数据的统计指标:均值、偏度、峰度。
- 保存功能:
- 图表将自动保存到指定的
save_dir文件夹(默认值为"output")。- 确保
save_dir是有效的文件夹路径(如"C:/Users/YourName/Output"或"./results"),建议使用原始字符串(r"C:\path\to\folder")。 - 如果文件夹不存在,代码会自动创建。
- PNG 文件使用高分辨率(
dpi=300),PDF 文件为矢量格式,适合出版。
- 确保
- 图表将自动保存到指定的
注意事项
- 传入
plot_monte_carlo_simulation函数 - 确保 years 参数与目标数据的年份范围匹配
- 可根据需要调整图表大小、颜色等参数
- 修改
dpi参数调整 PNG 文件的分辨率
修改方案一
修改计划
-
图1(All Simulation Paths):
- 保留所有1000条模拟路径。
- 添加一条重要的分界线(新模拟数据),以醒目方式(例如粗线、不同颜色)显示。
- 保存为 PNG 和 PDF 格式。
-
图2(Mean and Boundary Lines):
- 修改为只显示:
- 所有模拟路径的上边界线(最大值)。
- 所有模拟路径的下边界线(最小值)。
- 所有模拟路径的均值线。
- 新添加的分界线。
- 移除置信区间和其他统计指标。
- 保存为 PNG 和 PDF 格式。
- 修改为只显示:
-
图3(Final Year Scatter Plot):
- 修改为2100年所有1000条模拟数据的散点图。
- 将突出显示的分界线值为一条水平线,
- 保存为 PNG 和 PDF 格式。
-
表格(与图3一起显示在PDF中):
- 均值(
np.mean(final_values)) - 标准差(
np.std(final_values)) - 偏度(
scipy.stats.skew) - 峰度(
scipy.stats.kurtosis) - 分界线值(
boundary_data[-1]) - 大于分界线值的模拟数量
- 小于或等于分界线值的模拟数量
- 使用
plt.table绘制,与图3一起保存
- 均值(
方案假设
- 新分界线数据(
boundary_data)为一条与原有模拟数据相同长度(100年)的数组,格式为 numpy 数组或列表。 - 保存文件夹仍使用
save_dir参数,默认值为monte_carlo_output。
更新后的代码
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from scipy.stats import skew, kurtosis
import os
from matplotlib.backends.backend_pdf import PdfPages
# 设置 Seaborn 样式和调色板
sns.set_style("darkgrid")
sns.set_palette("husl")
def plot_monte_carlo_simulation(data, years, boundary_data, title="Monte Carlo Simulation", save_dir="output"):
"""
绘制蒙特卡洛模拟可视化图并保存为 PNG 和 PDF 格式
data: shape (n_simulations, n_years) 的数组
years: 年份列表
boundary_data: 新增的分界线数据,shape (n_years,)
title: 图表标题
save_dir: 保存图片的文件夹路径
"""
# 确保保存文件夹存在
os.makedirs(save_dir, exist_ok=True)
# 图1: 所有模拟路径 + 分界线
plt.figure(figsize=(10, 6))
for i in range(data.shape[0]):
plt.plot(years, data[i, :], alpha=0.3, linewidth=0.5, label=f'Simulation {i+1}' if i < 5 else None)
plt.plot(years, boundary_data, color='red', linewidth=2, label='Boundary Line')
plt.title('All Simulation Paths')
plt.xlabel('Year')
plt.ylabel('Value')
plt.grid(True, alpha=0.3)
plt.legend(loc='upper left', fontsize=8, ncol=2)
# 保存图1
plt.savefig(os.path.join(save_dir, "simulation_paths.png"), dpi=300, bbox_inches='tight')
plt.savefig(os.path.join(save_dir, "simulation_paths.pdf"), bbox_inches='tight')
plt.tight_layout()
plt.show()
plt.close()
# 图2: 均值线 + 上下边界线 + 分界线
plt.figure(figsize=(10, 6))
mean_values = np.mean(data, axis=0)
upper_bound = np.max(data, axis=0)
lower_bound = np.min(data, axis=0)
plt.plot(years, mean_values, label='Mean', linewidth=2, color='blue')
plt.plot(years, upper_bound, label='Upper Bound', linewidth=1.5, color='green', linestyle='--')
plt.plot(years, lower_bound, label='Lower Bound', linewidth=1.5, color='purple', linestyle='--')
plt.plot(years, boundary_data, label='Boundary Line', linewidth=2, color='red')
plt.title('Mean and Boundary Lines')
plt.xlabel('Year')
plt.ylabel('Value')
plt.grid(True, alpha=0.3)
plt.legend(loc='upper left', fontsize=8)
# 保存图2
plt.savefig(os.path.join(save_dir, "mean_and_boundaries.png"), dpi=300, bbox_inches='tight')
plt.savefig(os.path.join(save_dir, "mean_and_boundaries.pdf"), bbox_inches='tight')
plt.tight_layout()
plt.show()
plt.close()
# 图3: 最终年份散点图 + 水平分界线 + 表格
final_values = data[:, -1]
boundary_final = boundary_data[-1]
# 计算统计指标
mean_final = np.mean(final_values)
std_final = np.std(final_values)
skew_final = skew(final_values)
kurt_final = kurtosis(final_values)
count_above = np.sum(final_values > boundary_final)
count_below_or_equal = np.sum(final_values <= boundary_final)
# 创建 PDF 文件保存图3和表格
pdf_path = os.path.join(save_dir, "final_year_scatter_and_stats.pdf")
with PdfPages(pdf_path) as pdf:
# 图3: 散点图 + 水平分界线
plt.figure(figsize=(10, 6))
plt.scatter(range(1, len(final_values) + 1), final_values, alpha=0.5, s=10, label='Simulations')
plt.axhline(y=boundary_final, color='red', linewidth=2, label='Boundary Line')
plt.title(f'Final Year ({years[-1]}) Values')
plt.xlabel('Simulation Index')
plt.ylabel('Value')
plt.grid(True, alpha=0.3)
plt.legend(loc='upper left', fontsize=8)
# 保存到 PDF
pdf.savefig(bbox_inches='tight')
plt.savefig(os.path.join(save_dir, "final_year_scatter.png"), dpi=300, bbox_inches='tight')
plt.tight_layout()
plt.show()
plt.close()
# 表格
stats_data = {
'Statistic': ['Mean', 'Standard Deviation', 'Skewness', 'Kurtosis', 'Boundary Value',
'Count > Boundary', 'Count ≤ Boundary'],
'Value': [f'{mean_final:.2f}', f'{std_final:.2f}', f'{skew_final:.2f}', f'{kurt_final:.2f}',
f'{boundary_final:.2f}', f'{count_above}', f'{count_below_or_equal}']
}
stats_df = pd.DataFrame(stats_data)
plt.figure(figsize=(6, 4))
plt.axis('off')
table = plt.table(cellText=stats_df.values, colLabels=stats_df.columns, loc='center', cellLoc='center')
table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1.2, 1.2)
plt.title('Final Year Statistics')
# 保存到 PDF
pdf.savefig(bbox_inches='tight')
plt.close()
# 示例数据生成
if __name__ == "__main__":
# 生成示例数据
np.random.seed(42)
n_simulations = 1000
n_years = 100
years = np.arange(2001, 2101)
# 模拟数据 (随机游走)
data = np.zeros((n_simulations, n_years))
for i in range(n_simulations):
data[i, :] = np.cumsum(np.random.normal(0, 1, n_years))
# 示例分界线数据 (线性增长加噪声)
boundary_data = np.linspace(0, 10, n_years) + np.random.normal(0, 0.5, n_years)
# 调用可视化函数
plot_monte_carlo_simulation(data, years, boundary_data, "Example Monte Carlo Simulation", save_dir="monte_carlo_output")
代码说明
-
图1(All Simulation Paths):
- 保留1000条模拟路径(透明度
alpha=0.3)。 - 添加分界线(
boundary_data),使用红色粗线(color='red', linewidth=2)突出显示。 - 保存为
simulation_paths.png和simulation_paths.pdf。
- 保留1000条模拟路径(透明度
-
图2(Mean and Boundary Lines):
- 显示:
- 均值线(蓝色实线)。
- 上边界线(绿色虚线,
np.max(data, axis=0))。 - 下边界线(紫色虚线,
np.min(data, axis=0))。 - 分界线(红色实线)。
- 保存为
mean_and_boundaries.png和mean_and_boundaries.pdf。
- 显示:
-
图3(Final Year Scatter Plot):
- 使用
plt.scatter绘制2100年所有模拟值的散点图(s=10, alpha=0.5)。 - 将分界线值的突出显示(红色星形标记)改为水平线,使用
plt.axhline(y=boundary_final, color='red', linewidth=2)。 - 保留1000条模拟数据的散点图(
s=10, alpha=0.5)。 - 保存为
final_year_scatter.png和final_year_scatter_and_stats.pdf(包含散点图和表格)。
- 使用
-
表格:
- 表格与图3一起保存到
final_year_scatter_and_stats.pdf中,使用PdfPages实现多页 PDF。
- 表格与图3一起保存到
使用说明
-
输入数据:
data:shape 为(1000, 100)的 numpy 数组,代表1000条模拟路径。years:年份数组(如np.arange(2001, 2101))。boundary_data:新分界线数据,shape 为(100,)的 numpy 数组或列表。- 示例中,
boundary_data为线性增长加噪声的数据,您需要替换为您的实际分界线数据。
-
保存路径:
- 默认保存到
monte_carlo_output文件夹。 - 可自定义,例如:
plot_monte_carlo_simulation(data, years, boundary_data, save_dir="custom_folder") - 输出文件:
simulation_paths.png,simulation_paths.pdfmean_and_boundaries.png,mean_and_boundaries.pdffinal_year_scatter.png,final_year_scatter_and_stats.pdf(包含散点图和表格)
- 默认保存到
-
依赖库:
numpy,matplotlib,seaborn,pandas,scipy- 安装:
pip install numpy matplotlib seaborn pandas scipy
-
注意事项:
- 分界线数据:确保
boundary_data的长度与years一致(100年)。 - 文件覆盖:同名文件会被覆盖,建议使用唯一的
save_dir。 - PDF 多页:
final_year_scatter_and_stats.pdf包含两页(散点图和表格)。 - 表格格式:表格字体大小和缩放已优化(
fontsize=10,scale=1.2)。
- 分界线数据:确保
修改方案二
只修改了输出方式,从分散输出到合并输出。
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
from scipy.stats import skew, kurtosis
import os
from matplotlib.backends.backend_pdf import PdfPages
# 设置 Seaborn 样式和调色板
sns.set_style("darkgrid")
sns.set_palette("husl")
def plot_monte_carlo_simulation(data, years, boundary_data, title="Monte Carlo Simulation", save_dir="output", scenario="monte_carlo_results"):
"""
绘制蒙特卡洛模拟可视化图并保存为 PNG 和合并的 PDF 格式
data: shape (n_simulations, n_years) 的数组
years: 年份列表
boundary_data: 新增的分界线数据,shape (n_years,)
title: 图表标题
save_dir: 保存图片的文件夹路径
scenario: 合并 PDF 文件的名称
"""
# 确保保存文件夹存在
os.makedirs(save_dir, exist_ok=True)
# 创建合并的 PDF 文件
pdf_path = os.path.join(save_dir, f"{scenario}.pdf")
with PdfPages(pdf_path) as pdf:
# 图1: 所有模拟路径 + 分界线
plt.figure(figsize=(10, 6))
for i in range(data.shape[0]):
plt.plot(years, data[i, :], alpha=0.3, linewidth=0.5, label=f'Simulation {i+1}' if i < 5 else None)
plt.plot(years, boundary_data, color='red', linewidth=2, label='Boundary Line')
plt.title('All Simulation Paths')
plt.xlabel('Year')
plt.ylabel('Value')
plt.grid(True, alpha=0.3)
plt.legend(loc='upper left', fontsize=8, ncol=2)
# 保存图1为 PNG 和 PDF
plt.savefig(os.path.join(save_dir, "simulation_paths.png"), dpi=300, bbox_inches='tight')
pdf.savefig(bbox_inches='tight')
plt.tight_layout()
plt.show()
plt.close()
# 图2: 均值线 + 上下边界线 + 分界线
plt.figure(figsize=(10, 6))
mean_values = np.mean(data, axis=0)
upper_bound = np.max(data, axis=0)
lower_bound = np.min(data, axis=0)
plt.plot(years, mean_values, label='Mean', linewidth=2, color='blue')
plt.plot(years, upper_bound, label='Upper Bound', linewidth=1.5, color='green', linestyle='--')
plt.plot(years, lower_bound, label='Lower Bound', linewidth=1.5, color='purple', linestyle='--')
plt.plot(years, boundary_data, label='Boundary Line', linewidth=2, color='red')
plt.title('Mean and Boundary Lines')
plt.xlabel('Year')
plt.ylabel('Value')
plt.grid(True, alpha=0.3)
plt.legend(loc='upper left', fontsize=8)
# 保存图2为 PNG 和 PDF
plt.savefig(os.path.join(save_dir, "mean_and_boundaries.png"), dpi=300, bbox_inches='tight')
pdf.savefig(bbox_inches='tight')
plt.tight_layout()
plt.show()
plt.close()
# 图3: 最终年份散点图 + 水平分界线
final_values = data[:, -1]
boundary_final = boundary_data[-1]
# 计算统计指标
mean_final = np.mean(final_values)
std_final = np.std(final_values)
skew_final = skew(final_values)
kurt_final = kurtosis(final_values)
count_above = np.sum(final_values > boundary_final)
count_below_or_equal = np.sum(final_values <= boundary_final)
plt.figure(figsize=(10, 6))
plt.scatter(range(1, len(final_values) + 1), final_values, alpha=0.5, s=10, label='Simulations')
plt.axhline(y=boundary_final, color='red', linewidth=2, label='Boundary Line')
plt.title(f'Final Year ({years[-1]}) Values')
plt.xlabel('Simulation Index')
plt.ylabel('Value')
plt.grid(True, alpha=0.3)
plt.legend(loc='upper left', fontsize=8)
# 保存图3为 PNG 和 PDF
plt.savefig(os.path.join(save_dir, "final_year_scatter.png"), dpi=300, bbox_inches='tight')
pdf.savefig(bbox_inches='tight')
plt.tight_layout()
plt.show()
plt.close()
# 表格
stats_data = {
'Statistic': ['Mean', 'Standard Deviation', 'Skewness', 'Kurtosis', 'Boundary Value',
'Count > Boundary', 'Count ≤ Boundary'],
'Value': [f'{mean_final:.2f}', f'{std_final:.2f}', f'{skew_final:.2f}', f'{kurt_final:.2f}',
f'{boundary_final:.2f}', f'{count_above}', f'{count_below_or_equal}']
}
stats_df = pd.DataFrame(stats_data)
plt.figure(figsize=(6, 4))
plt.axis('off')
table = plt.table(cellText=stats_df.values, colLabels=stats_df.columns, loc='center', cellLoc='center')
table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1.2, 1.2)
plt.title('Final Year Statistics')
# 保存表格到 PDF
pdf.savefig(bbox_inches='tight')
plt.close()
# 示例数据生成
if __name__ == "__main__":
# 生成示例数据
np.random.seed(42)
n_simulations = 1000
n_years = 100
years = np.arange(2001, 2101)
# 模拟数据 (随机游走)
data = np.zeros((n_simulations, n_years))
for i in range(n_simulations):
data[i, :] = np.cumsum(np.random.normal(0, 1, n_years))
# 示例分界线数据 (线性增长加噪声)
boundary_data = np.linspace(0, 10, n_years) + np.random.normal(0, 0.5, n_years)
# 调用可视化函数,指定 scenario
plot_monte_carlo_simulation(data, years, boundary_data, "Example Monte Carlo Simulation",
save_dir="monte_carlo_output", scenario="example_scenario")
1075

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



