import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
import warnings
warnings.filterwarnings('ignore')
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 1. 读取数据
print("正在读取数据...")
try:
# 读取附件1
attachment1 = pd.read_excel(r"D:\比赛\建模\C题\附件1.xlsx")
# 读取附件2
attachment2_sheets = pd.read_excel(r"D:\比赛\建模\C题\附件2.xlsx", sheet_name=None)
planting_data = attachment2_sheets['种植数据'] # 种植数据表
related_data = attachment2_sheets['相关数据'] # 相关数据表
print("数据读取成功!")
except Exception as e:
print(f"读取数据时出错: {e}")
exit()
# 2. 数据探索
print("\n数据探索:")
print("附件1 形状:", attachment1.shape)
print("种植数据 形状:", planting_data.shape)
print("相关数据 形状:", related_data.shape)
print("\n附件1 前5行:")
print(attachment1.head())
print("\n种植数据 前5行:")
print(planting_data.head())
print("\n相关数据 前5行:")
print(related_data.head())
# 3. 缺失值处理
print("\n缺失值检查:")
print("附件1 缺失值:\n", attachment1.isnull().sum())
print("种植数据 缺失值:\n", planting_data.isnull().sum())
print("相关数据 缺失值:\n", related_data.isnull().sum())
# 数据中没有缺失值,无需处理
# 4. 异常值检测 (使用IQR方法)
print("\n异常值检测:")
def detect_outliers_iqr(data, column):
Q1 = data[column].quantile(0.25)
Q3 = data[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers = data[(data[column] < lower_bound) | (data[column] > upper_bound)]
return outliers, lower_bound, upper_bound
# 检测附件1中的地块面积异常值
outliers_area, lb_area, ub_area = detect_outliers_iqr(attachment1, '地块面积')
print(f"地块面积异常值数量: {len(outliers_area)}")
print(f"地块面积异常值范围: [{lb_area}, {ub_area}]")
# 检测种植数据中的种植面积异常值
outliers_planting, lb_planting, ub_planting = detect_outliers_iqr(planting_data, '种植面积')
print(f"种植面积异常值数量: {len(outliers_planting)}")
print(f"种植面积异常值范围: [{lb_planting}, {ub_planting}]")
# 检测相关数据中的亩产量异常值
outliers_yield, lb_yield, ub_yield = detect_outliers_iqr(related_data, '亩产量')
print(f"亩产量异常值数量: {len(outliers_yield)}")
print(f"亩产量异常值范围: [{lb_yield}, {ub_yield}]")
# 检测相关数据中的种植成本异常值
outliers_cost, lb_cost, ub_cost = detect_outliers_iqr(related_data, '种植成本')
print(f"种植成本异常值数量: {len(outliers_cost)}")
print(f"种植成本异常值范围: [{lb_cost}, {ub_cost}]")
# 绘制箱线图检查异常值
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 地块面积箱线图
attachment1.boxplot(column='地块面积', ax=axes[0, 0])
axes[0, 0].set_title('地块面积分布')
# 种植面积箱线图
planting_data.boxplot(column='种植面积', ax=axes[0, 1])
axes[0, 1].set_title('种植面积分布')
# 亩产量箱线图
related_data.boxplot(column='亩产量', ax=axes[1, 0])
axes[1, 0].set_title('亩产量分布')
# 种植成本箱线图
related_data.boxplot(column='种植成本', ax=axes[1, 1])
axes[1, 1].set_title('种植成本分布')
plt.tight_layout()
plt.savefig('异常值检测箱线图.png')
plt.show()
print("\n异常值处理: 所有异常值在业务背景下合理,保留不处理")
# 5. 数据转换处理 (标准化)
print("\n数据标准化处理:")
# 选择需要标准化的数值列
numeric_cols = ['地块面积', '种植面积', '亩产量', '种植成本']
# 计算均值和标准差
means = {}
stds = {}
for col in numeric_cols:
if col in attachment1.columns:
means[col] = attachment1[col].mean()
stds[col] = attachment1[col].std()
elif col in planting_data.columns:
means[col] = planting_data[col].mean()
stds[col] = planting_data[col].std()
elif col in related_data.columns:
means[col] = related_data[col].mean()
stds[col] = related_data[col].std()
print("均值:", means)
print("标准差:", stds)
# 标准化函数
def standardize_data(df, col, mean, std):
if col in df.columns:
df[f'z_{col}'] = (df[col] - mean) / std
return df
# 应用标准化
attachment1 = standardize_data(attachment1, '地块面积', means['地块面积'], stds['地块面积'])
planting_data = standardize_data(planting_data, '种植面积', means['种植面积'], stds['种植面积'])
related_data = standardize_data(related_data, '亩产量', means['亩产量'], stds['亩产量'])
related_data = standardize_data(related_data, '种植成本', means['种植成本'], stds['种植成本'])
print("标准化完成!")
# 6. 数据补充
print("\n数据补充:")
# 补充天气数据 (基于假设)
months = list(range(1, 13))
temperature = [5, 8, 15, 20, 25, 28, 30, 28, 23, 18, 12, 7] # 月平均温度(°C)
rainfall = [10, 15, 25, 40, 60, 100, 150, 120, 80, 50, 30, 15] # 月平均降雨量(mm)
weather_data = pd.DataFrame({
'月份': months,
'平均温度': temperature,
'降雨量': rainfall
})
print("补充的天气数据:")
print(weather_data.head())
# 补充销售单价均值 (使用范围的中值)
if '销售单价' in related_data.columns:
# 提取销售单价范围并计算中值
def extract_price_range(price_str):
if isinstance(price_str, str) and '-' in price_str:
parts = price_str.split('-')
if len(parts) == 2:
try:
lower = float(parts[0])
upper = float(parts[1])
return (lower + upper) / 2
except:
return np.nan
return np.nan
related_data['销售单价均值'] = related_data['销售单价'].apply(extract_price_range)
print("销售单价均值计算完成!")
# 7. 保存预处理后的数据
print("\n保存预处理后的数据...")
save_path = r"D:\比赛\建模\C题\\" # 使用与附件相同的目录
attachment1.to_csv(save_path + '预处理后_附件1.csv', index=False, encoding='utf-8-sig')
planting_data.to_csv(save_path + '预处理后_种植数据.csv', index=False, encoding='utf-8-sig')
related_data.to_csv(save_path + '预处理后_相关数据.csv', index=False, encoding='utf-8-sig')
weather_data.to_csv(save_path + '补充_天气数据.csv', index=False, encoding='utf-8-sig')
print(f"预处理完成! 数据已保存到 {save_path} 目录")修改我的代码报错原因是NameError: name 'planting_data' is not defined
最新发布