导入引入
import os
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.optimize import curve_fit
读取数据
需要自己更改的地方,详间注释中的3点
# 1、文件路径替换为自己的文件路径和自己的文件名
folder_path = r'D:/'
file_path1 = os.path.join(folder_path, 'yourfilename.xlsx')
# 2、要读取数据的sheet
sheet_name = 'Sheet1'
# 读取xlsx文件
df = pd.read_excel(file_path1, sheet_name=sheet_name)
# 3、获取列名为x, y,flag的数据,x为要拟合的输入数据,y为要拟合的输出数据,flag为数据的分类,比如flag为男性、女性,意思分别拟合男性和女性数据
x = df['x].values
y = df['y'].values
flag = df['flag'].values
拟合关系
# 定义线性函数(线性拟合模型)
def linear_func(x, a, b):
return a * x + b
# 定义指数函数(非线性拟合模型)
def nonlinear_func(x, c, d):
return c * np.exp(d * x)
# 定义多项式函数(非线性拟合模型)
def polynomial_func(x, *params):
return sum(p * x**i for i, p in enumerate(params))
# 定义 sigmoid 函数作为非线性拟合模型
def sigmoid_func(x, a, b, c):
return a / (1 + np.exp(-b * (x - c)))
开始拟合
根据自己需要从拟合关系中选择需要拟合的数据关系,这里选sigmoid_func
# 针对不同的 flag 分别绘制在不同的子图中
unique_flags = np.unique(flag)
fig, axs = plt.subplots(len(unique_flags), 1, figsize=(8, 6 * len(unique_flags)), sharex=True)
for i, unique_flag in enumerate(unique_flags):
ax = axs[i]
flag_indices = np.where(flag == unique_flag)[0]
# 提取对应 flag 的数据
x_flag = x[flag_indices]
y_flag = y[flag_indices]
# # 如果x,y数据差异过大,可能需要归一化处理
# scaler = MinMaxScaler()
# x_normalized = scaler.fit_transform(x_flag.reshape(-1, 1)).flatten()
# y_normalized = scaler.fit_transform(y_flag.reshape(-1, 1)).flatten()
# 将数据按照 x 的顺序排序
sorted_indices = np.argsort(x_flag)
x_sorted = x_flag[sorted_indices]
y_sorted = y_flag[sorted_indices]
# 利用 curve_fit 进行非线性拟合
params_nonlinear, covariance_nonlinear = curve_fit(sigmoid_func, x_sorted, y_sorted, p0=[1, 1, 1], method='lm')
# 生成非线性拟合后的数据
fit_y_nonlinear_normalized = sigmoid_func(x_sorted, *params_nonlinear)
# 反归一化
# x_reverse = scaler.inverse_transform(x_flag.reshape(-1, 1)).flatten()
# y_reverse = scaler.inverse_transform(y_flag.reshape(-1, 1)).flatten()
ax.scatter(x_sorted, y_sorted, label=f'Original Data (Flag {unique_flag})')
ax.plot(x_sorted, fit_y_nonlinear_normalized, label=f'Nonlinear Fit: Sigmoid (Flag {unique_flag})\nParameters: a={params_nonlinear[0]:.3f}, b={params_nonlinear[1]:.3f}, c={params_nonlinear[2]:.3f}', color='red')
ax.legend()
ax.set_ylabel(f'ydata (Original Scale) (Flag {unique_flag})')
plt.xlabel('xdata')
plt.suptitle('Nonlinear Fit Example with Sigmoid Function for Different Flags')
plt.show()