使用SciPy Stats .fit()拟合导入数据的困惑与求助
用SciPy Stats拟合指数/Beta分布并绘图(基于导入的DataFrame数据)
前置准备
先确保导入所需库:
import pandas as pd import scipy.stats as stats import matplotlib.pyplot as plt import numpy as np from sklearn.preprocessing import MinMaxScaler # 用于Beta分布的数据标准化
从DataFrame提取目标变量(以列名var1为例),必须先剔除缺失值:
# 假设你的DataFrame名为df,目标变量列是var1 data = df['var1'].dropna().values
1. 拟合指数分布
指数分布包含loc(位置参数,通常为0)和scale(尺度参数,对应均值)两个参数,直接用fit()拟合你的数据:
# 拟合指数分布,得到参数 loc_exp, scale_exp = stats.expon.fit(data) # 生成拟合的概率密度函数(PDF)数据 x_exp = np.linspace(min(data), max(data), 1000) pdf_exp = stats.expon.pdf(x_exp, loc=loc_exp, scale=scale_exp)
绘制指数分布拟合结果
plt.figure(figsize=(10,6)) # 绘制数据直方图(密度归一化,与PDF匹配) plt.hist(data, bins=30, density=True, alpha=0.6, label='原始数据直方图') # 绘制拟合的PDF曲线 plt.plot(x_exp, pdf_exp, 'r-', linewidth=2, label=f'拟合指数分布\nloc={loc_exp:.2f}, scale={scale_exp:.2f}') plt.xlabel('变量值') plt.ylabel('密度') plt.legend() plt.title('指数分布拟合结果') plt.show()
2. 拟合Beta分布
Beta分布的定义域是**[0,1]**,如果原始数据不在该范围,需先做标准化处理:
# 标准化数据到[0,1]区间 scaler = MinMaxScaler() data_scaled = scaler.fit_transform(data.reshape(-1,1)).flatten() # 拟合Beta分布,得到参数a(alpha), b(beta), loc, scale a_beta, b_beta, loc_beta, scale_beta = stats.beta.fit(data_scaled)
绘制Beta分布拟合结果
plt.figure(figsize=(10,6)) # 绘制标准化后数据的直方图 plt.hist(data_scaled, bins=30, density=True, alpha=0.6, label='标准化后数据直方图') # 生成拟合的PDF数据 x_beta = np.linspace(0, 1, 1000) pdf_beta = stats.beta.pdf(x_beta, a_beta, b_beta, loc=loc_beta, scale=scale_beta) # 绘制拟合曲线 plt.plot(x_beta, pdf_beta, 'r-', linewidth=2, label=f'拟合Beta分布\na={a_beta:.2f}, b={b_beta:.2f}') plt.xlabel('标准化变量值') plt.ylabel('密度') plt.legend() plt.title('Beta分布拟合结果') plt.show()
批量处理4个变量
如果要一次性处理DataFrame中的4个变量,可写循环实现:
# 假设4个变量列名为['var1', 'var2', 'var3', 'var4'] var_cols = ['var1', 'var2', 'var3', 'var4'] scaler = MinMaxScaler() for col in var_cols: data = df[col].dropna().values if not len(data): print(f'变量{col}无有效数据,跳过') continue # 绘制指数+Beta拟合子图 plt.figure(figsize=(12,5)) # 指数分布拟合子图 plt.subplot(1,2,1) loc_exp, scale_exp = stats.expon.fit(data) x_exp = np.linspace(min(data), max(data), 1000) pdf_exp = stats.expon.pdf(x_exp, loc=loc_exp, scale=scale_exp) plt.hist(data, bins=30, density=True, alpha=0.6) plt.plot(x_exp, pdf_exp, 'r-', linewidth=2) plt.title(f'{col} - 指数分布拟合') # Beta分布拟合子图 plt.subplot(1,2,2) data_scaled = scaler.fit_transform(data.reshape(-1,1)).flatten() a_beta, b_beta, _, _ = stats.beta.fit(data_scaled) x_beta = np.linspace(0,1,1000) pdf_beta = stats.beta.pdf(x_beta, a_beta, b_beta) plt.hist(data_scaled, bins=30, density=True, alpha=0.6) plt.plot(x_beta, pdf_beta, 'r-', linewidth=2) plt.title(f'{col} - Beta分布拟合') plt.tight_layout() plt.show()
关键注意点
- 缺失值处理:
fit()无法处理NaN,必须用dropna()剔除无效数据 - Beta分布约束:原始数据必须标准化到[0,1]区间,否则拟合结果无意义
- 参数解读:指数分布的
scale等于数据均值(当loc=0时);Beta分布的a和b决定分布形状,数值越大分布越集中
内容的提问来源于stack exchange,提问作者Jason Word
相关产品推荐
相关产品推荐

