# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import StandardScaler
import os
import matplotlib as mpl
import sys
# 设置中文字体支持
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'WenQuanYi Micro Hei'] # 支持中文的字体
plt.rcParams['axes.unicode_minus'] = False # 正确显示负号
mpl.rcParams['font.size'] = 12 # 设置全局字体大小
# 获取桌面路径
desktop = os.path.join(os.path.expanduser('~'), 'Desktop')
print(f"文件将保存到桌面: {desktop}")
# 1. 读取数据
print("读取数据...")
try:
df = pd.read_csv('sourceSet.csv')
print(f"成功读取数据,共{len(df)}行,{len(df.columns)}列")
except FileNotFoundError:
print("错误:找不到 sourceSet.csv 文件,请确保文件在当前目录")
sys.exit(1)
# 2. 识别关键特征
print("\n识别关键特征...")
# 定义必须保留的五个关键特征(中英文列名映射)
key_features = {
'点评数': ['点评数', 'review_count'],
'口味评分': ['口味', 'taste_rating'],
'环境评分': ['环境', 'environment_rating'],
'服务评分': ['服务', 'service_rating'],
'人均消费': ['人均消费', 'avg_price']
}
# 构建实际存在的特征列表
existing_key_features = {}
for feature_name, possible_names in key_features.items():
for name in possible_names:
if name in df.columns:
existing_key_features[feature_name] = name
print(f"已识别关键特征 '{feature_name}': 列名 '{name}'")
break
else:
print(f"警告:未找到关键特征 '{feature_name}' 的对应列")
if len(existing_key_features) < 5:
print(f"错误:只找到 {len(existing_key_features)} 个关键特征,需要5个")
sys.exit(1)
# 3. 去除无效特征值
print("\n去除无效特征值...")
columns_to_drop = ['lng', 'lat', '数据ID', '城市', 'ID', 'city', 'id', 'Unnamed: 0']
# 只删除实际存在的列,且不是关键特征
invalid_cols = [col for col in columns_to_drop
if col in df.columns
and col not in existing_key_features.values()]
df.drop(columns=invalid_cols, inplace=True)
print(f"已删除无效列: {invalid_cols}")
print(f"剩余列: {list(df.columns)}")
# 4. 缺失值处理
print("\n处理缺失值...")
# 确保关键特征存在
key_feature_cols = list(existing_key_features.values())
print(f"关键特征列: {key_feature_cols}")
# ① 缺失值比例高于30%的特征直接删除(仅限非关键特征)
non_key_cols = [col for col in df.columns if col not in key_feature_cols]
missing_percent = df[non_key_cols].isnull().mean()
cols_to_drop = missing_percent[missing_percent > 0.3].index.tolist()
df.drop(columns=cols_to_drop, inplace=True)
if cols_to_drop:
print(f"删除缺失值>30%的非关键特征: {cols_to_drop}")
# ② 关键特征的缺失值处理
initial_rows = len(df)
for feature_name, col_name in existing_key_features.items():
missing_count = df[col_name].isnull().sum()
if missing_count > 0:
# 关键特征缺失值使用列中位数填充
median_val = df[col_name].median()
df[col_name].fillna(median_val, inplace=True)
print(f"填充关键特征 '{feature_name}' ({col_name}) 的缺失值 (中位数: {median_val:.2f})")
# ③ 其他非关键数值特征的缺失值采取均值填充
other_cols = [col for col in df.columns
if col not in key_feature_cols
and df[col].dtype in ['int64', 'float64']]
for col in other_cols:
if df[col].isnull().sum() > 0:
mean_val = df[col].mean()
df[col].fillna(mean_val, inplace=True)
print(f"填充非关键特征 '{col}' 的缺失值 (均值: {mean_val:.2f})")
# 5. 数据可视化 - 评分排名
print("\n生成可视化图表...")
def plot_ranking(feature_name, col_name, title, color):
"""绘制评分排名的水平条形图"""
# 检查特征是否存在
if col_name not in df.columns:
print(f"错误:特征 '{col_name}' 不存在,无法生成 {title} 排名")
return None
# 取前20名
top20 = df.sort_values(col_name, ascending=False).head(20).reset_index(drop=True)
plt.figure(figsize=(14, 10))
# 使用商家名称或索引作为标签
labels = top20.index.astype(str)
if '商家名称' in df.columns:
labels = top20['商家名称'].values
elif 'shop_name' in df.columns:
labels = top20['shop_name'].values
else:
# 如果没有商家名称,使用索引
labels = [f"商家 {i+1}" for i in top20.index]
bars = plt.barh(labels, top20[col_name], color=color)
plt.title(f'{title}排名 - 前20名', fontsize=16)
plt.xlabel(title, fontsize=14)
plt.ylabel('商家名称', fontsize=14)
plt.gca().invert_yaxis() # 反转Y轴使最高分在顶部
# 在条形图上添加数值标签
for bar in bars:
width = bar.get_width()
plt.text(width + 0.01, bar.get_y() + bar.get_height() / 2,
f'{width:.2f}',
va='center', ha='left', fontsize=10)
plt.tight_layout()
save_path = os.path.join(desktop, f'{title}排名.png')
plt.savefig(save_path, dpi=100, bbox_inches='tight')
plt.close()
print(f"已保存: {save_path}")
return save_path
# 绘制三种评分排名
saved_files = []
for feature_name in ['服务评分', '口味评分', '环境评分']:
if feature_name in existing_key_features:
col_name = existing_key_features[feature_name]
color = {
'口味评分': '#55A868', # 绿色
'环境评分': '#C44E52', # 红色
'服务评分': '#4C72B0' # 蓝色
}.get(feature_name, '#888888') # 默认灰色
saved_path = plot_ranking(feature_name, col_name, feature_name, color)
if saved_path:
saved_files.append(saved_path)
else:
print(f"警告:未找到 {feature_name} 列,跳过可视化")
# 6. 特征变量选择 - 确保保留五个关键特征
print("\n特征变量选择...")
selected_features = list(existing_key_features.values())
print(f"保留的关键特征: {selected_features}")
df_selected = df[selected_features].copy()
# 7. 数据标准化 (Z-score)
print("\n数据标准化处理...")
scaler = StandardScaler()
df_selected.loc[:, selected_features] = scaler.fit_transform(df_selected[selected_features])
# 8. 保存预处理结果
output_path = os.path.join(desktop, 'processed_sourceSet.csv')
try:
df_selected.to_csv(output_path, index=False)
print(f"预处理后的数据已保存到: {output_path}")
# 验证文件是否成功生成
if os.path.exists(output_path):
print(f"文件验证成功,大小: {os.path.getsize(output_path) / 1024:.2f} KB")
else:
print("警告:文件保存失败,请检查路径权限")
except Exception as e:
print(f"文件保存错误: {str(e)}")
# 9. 生成预处理结果统计
print("\n预处理结果统计:")
stats = pd.DataFrame({
'特征': [existing_key_features[fn] for fn in existing_key_features],
'原始名称': list(existing_key_features.keys()),
'类型': df_selected.dtypes.values,
'最小值': df_selected.min().values,
'最大值': df_selected.max().values,
'取值范围': df_selected.max().values - df_selected.min().values
})
print(stats)
# 保存统计信息
stats_path = os.path.join(desktop, '预处理统计.csv')
try:
stats.to_csv(stats_path, index=False)
print(f"预处理统计已保存到: {stats_path}")
except Exception as e:
print(f"统计信息保存错误: {str(e)}")
print("\n所有处理完成!")
if saved_files:
print(f"生成的可视化文件: {saved_files}")
else:
print("警告:未生成任何可视化图表")这里面的预处理统计.csv未生成