针对问题一,我们的目标是分析古代玻璃文物的表面风化与其玻璃类型、纹饰和颜色之间的关系,并预测风化前的化学成分含量。
步骤 1: 数据预处理
处理缺失值:对化学成分数据中的缺失值进行处理,可以选择填充(例如使用成分的平均值)或者删除含有过多缺失值的样本。
import pandas as pd
import numpy as np
def read_excel_to_dataframe(file_path):
"""
读取 Excel 文件并将其转换为 Pandas DataFrame。
参数:
file_path (str): Excel 文件的路径。
返回:
DataFrame: 从 Excel 文件中读取的数据。
"""
try:
df = pd.read_excel(file_path,header=0)
return df
except Exception as e:
print(f"读取文件时发生错误: {e}")
return None
我们对数据进行预览查看数据是否有空缺值:
我们发现文物颜色这一特征是存在缺失值的,基于数据来看最好的方式可以通过一些机器学习算法进行填充,能够保证填充的数据具有一定的准确性,这里采用使用随机森林进行缺失值填充:使用没有缺失值的数据来训练一个随机森林模型,其中,预测变量是除了要填充缺失值的列以外的其他列,目标变量是需要填充缺失值的列。
ef full_RF(df):
# 假设df是你的DataFrame,首先创建一个副本以避免修改原始DataFrame
df_copy = df.copy()
# 首先,对非数值列进行编码
encoder = LabelEncoder()
for column in df_copy.columns.drop('颜色'):
df_copy[column] = encoder.fit_transform(df_copy[column])
# 分离出有缺失值和没有缺失值的数据
df_missing = df_copy[df_copy['颜色'].isnull()]
df_no_missing = df_copy.dropna()
# 准备训练数据
X_train = df_no_missing.drop('颜色', axis=1)
y_train = df_no_missing['颜色']
# 训练随机森林模型
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
# 对缺失值进行预测
X_missing = df_missing.drop('颜色', axis=1)
predicted_colors = model.predict(X_missing)
# 填充缺失值
df_copy.loc[df_copy['颜色'].isnull(), '颜色'] = predicted_colors
return df_copy
关于表单2我们需要明白我们的是空白处表示未检测到该成分,因此我们不需要填充空缺数据,需要判断每行的总和是否在85%到105%之间,并将结果添加为新的一列“有效性”:
sums = df_filled.drop(columns=['文物采样点']).sum(axis=1)
df_filled['总和']=sums
# 判断每行的总和是否在85%到105%之间,并将结果添加为新的一列“有效性”
df_filled['有效性'] = sums.apply(lambda x: '有效' if 85 <= x <= 105 else '无效')
df_filled
数据整合:将化学成分数据与文物的基本信息(如类型、纹饰、颜色)整合在一起,为后续分析做准备。
其中我们分别要提取出未风化和风化的数据,需要注意的是,表面风化特征中带有风化这一属性时,文物采样点会存在采样未风化这一情况,所以要过滤调,也就是存在着风化点中测量未风化点的情况,需要分析的更加具体一点,将这种情况剔除干净再来分析,从而得到一张完整的分析表格:
同理清洗无风化数据也是如此:
现在基于这份数据我们可以进行数据可视化来帮助我们分析每个化学元素的波动和是否存在明显特征规律,
def plot_scatter(df):
# 绘制散点图
plt.figure(figsize=(14, 6))
# 遍历每个样本绘制散点图
for column in df.columns[1:]: # 跳过'化学成分'列,从'样本1'开始
plt.scatter(df['化学成分'], df[column], label=column, s=100) # s控制点的大小
# 添加图例、标题和轴标签
plt.legend()
plt.title('化学成分含量')
plt.xlabel('化学成分')
plt.ylabel('含量')
plt.xticks(rotation=45) # 旋转x轴标签,以便更容易阅读
plt.grid(True) # 添加网格线
plt.tight_layout() # 调整布局以适应标签
plt.show()
我们要根据样本的纹理类型和颜色,三者分组分类:
来看具体效果:
很明显可以看到风化和未风化化学成分不同之处,可根据未风化的文物化学成分的平均含量去预测拟合,也可以用KNN这类算法去匹配最接近的进行拟合,那么第一问我们就做完了,我们马上开始第二问建模。
希望大家支持一下!到这里第一问建模就结束了,想要了解更多的欢迎联系博主再向大家推荐一下笔者精心打造的专栏。此专栏的目的就是为了让零基础快速使用各类数学模型以及代码,每一篇文章都包含实战项目以及可运行代码。博主紧跟各类数模比赛,每场数模竞赛博主都会将最新的思路: