上传文件至 /
This commit is contained in:
1
__init__.py
Normal file
1
__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
327
box_plot.py
Normal file
327
box_plot.py
Normal file
@ -0,0 +1,327 @@
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import seaborn as sns
|
||||
import os
|
||||
|
||||
# 设置中文字体
|
||||
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
|
||||
plt.rcParams['axes.unicode_minus'] = False
|
||||
|
||||
def plot_individual_boxplots(csv_file_path, save_dir="boxplots"):
|
||||
"""
|
||||
为每个数据列单独绘制箱型图并保存
|
||||
|
||||
参数:
|
||||
csv_file_path: CSV文件路径
|
||||
save_dir: 保存图片的目录
|
||||
"""
|
||||
try:
|
||||
# 读取CSV文件
|
||||
df = pd.read_csv(csv_file_path)
|
||||
|
||||
# 获取第五列之后的数据列(索引从0开始,第五列索引为4)
|
||||
data_columns = df.iloc[:, 4:]
|
||||
|
||||
# 检查是否有数据列
|
||||
if data_columns.empty:
|
||||
print("错误:CSV文件中没有足够的列(至少需要5列)")
|
||||
return
|
||||
|
||||
# 创建保存目录
|
||||
if not os.path.exists(save_dir):
|
||||
os.makedirs(save_dir)
|
||||
print(f"创建目录: {save_dir}")
|
||||
|
||||
# 为每个数据列单独绘制箱型图
|
||||
for column in data_columns.columns:
|
||||
# 移除空值
|
||||
clean_data = data_columns[column].dropna()
|
||||
|
||||
if len(clean_data) == 0:
|
||||
print(f"跳过列 '{column}': 没有有效数据")
|
||||
continue
|
||||
|
||||
# 创建新图形
|
||||
plt.figure(figsize=(8, 6))
|
||||
|
||||
# 绘制箱型图
|
||||
box_plot = plt.boxplot([clean_data], labels=[column], patch_artist=True,
|
||||
showfliers=False)
|
||||
|
||||
# 美化箱型图
|
||||
box_plot['boxes'][0].set_facecolor('lightblue')
|
||||
box_plot['boxes'][0].set_alpha(0.7)
|
||||
|
||||
# 添加散点
|
||||
x_pos = np.random.normal(1, 0.04, size=len(clean_data))
|
||||
plt.scatter(x_pos, clean_data, alpha=0.6, s=30, color='red',
|
||||
edgecolors='black', linewidth=0.5, zorder=3)
|
||||
|
||||
# 设置标题和标签
|
||||
plt.title(f'{column} - 箱型图', fontsize=14, fontweight='bold')
|
||||
plt.xlabel('数据列', fontsize=12)
|
||||
plt.ylabel('数值', fontsize=12)
|
||||
|
||||
# 添加统计信息到图上
|
||||
stats_text = f'数据点数: {len(clean_data)}\n均值: {clean_data.mean():.2f}\n中位数: {clean_data.median():.2f}\n标准差: {clean_data.std():.2f}'
|
||||
plt.text(0.02, 0.98, stats_text, transform=plt.gca().transAxes,
|
||||
verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8))
|
||||
|
||||
# 添加网格
|
||||
plt.grid(True, alpha=0.3, linestyle='--')
|
||||
|
||||
# 调整布局
|
||||
plt.tight_layout()
|
||||
|
||||
# 保存图片
|
||||
safe_column_name = column.replace('/', '_').replace('\\', '_').replace(':', '_')
|
||||
save_path = os.path.join(save_dir, f'{safe_column_name}_boxplot.png')
|
||||
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
||||
print(f"已保存: {save_path}")
|
||||
|
||||
# 关闭图形以释放内存
|
||||
plt.close()
|
||||
|
||||
print(f"\n所有箱型图已保存到目录: {save_dir}")
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"错误:找不到文件 {csv_file_path}")
|
||||
except Exception as e:
|
||||
print(f"错误:{str(e)}")
|
||||
|
||||
def plot_individual_boxplots_seaborn(csv_file_path, save_dir="boxplots_seaborn"):
|
||||
"""
|
||||
使用seaborn为每个数据列单独绘制箱型图并保存
|
||||
|
||||
参数:
|
||||
csv_file_path: CSV文件路径
|
||||
save_dir: 保存图片的目录
|
||||
"""
|
||||
try:
|
||||
# 读取CSV文件
|
||||
df = pd.read_csv(csv_file_path)
|
||||
|
||||
# 获取第五列之后的数据列
|
||||
data_columns = df.iloc[:, 4:]
|
||||
|
||||
if data_columns.empty:
|
||||
print("错误:CSV文件中没有足够的列(至少需要5列)")
|
||||
return
|
||||
|
||||
# 创建保存目录
|
||||
if not os.path.exists(save_dir):
|
||||
os.makedirs(save_dir)
|
||||
print(f"创建目录: {save_dir}")
|
||||
|
||||
# 为每个数据列单独绘制箱型图
|
||||
for column in data_columns.columns:
|
||||
# 移除空值
|
||||
clean_data = data_columns[column].dropna()
|
||||
|
||||
if len(clean_data) == 0:
|
||||
print(f"跳过列 '{column}': 没有有效数据")
|
||||
continue
|
||||
|
||||
# 创建新图形
|
||||
plt.figure(figsize=(8, 6))
|
||||
|
||||
# 创建数据框用于seaborn
|
||||
plot_data = pd.DataFrame({
|
||||
'列名': [column] * len(clean_data),
|
||||
'数值': clean_data
|
||||
})
|
||||
|
||||
# 使用seaborn绘制箱型图和散点
|
||||
sns.boxplot(data=plot_data, x='列名', y='数值', palette='Set2')
|
||||
sns.stripplot(data=plot_data, x='列名', y='数值',
|
||||
color='red', alpha=0.6, size=5, jitter=True)
|
||||
|
||||
# 设置标题和标签
|
||||
plt.title(f'{column} - 箱型图 (Seaborn)', fontsize=14, fontweight='bold')
|
||||
plt.xlabel('数据列', fontsize=12)
|
||||
plt.ylabel('数值', fontsize=12)
|
||||
|
||||
# 添加统计信息
|
||||
stats_text = f'数据点数: {len(clean_data)}\n均值: {clean_data.mean():.2f}\n中位数: {clean_data.median():.2f}\n标准差: {clean_data.std():.2f}'
|
||||
plt.text(0.02, 0.98, stats_text, transform=plt.gca().transAxes,
|
||||
verticalalignment='top', bbox=dict(boxstyle='round', facecolor='lightgreen', alpha=0.8))
|
||||
|
||||
# 添加网格
|
||||
plt.grid(True, alpha=0.3, linestyle='--')
|
||||
|
||||
# 调整布局
|
||||
plt.tight_layout()
|
||||
|
||||
# 保存图片
|
||||
safe_column_name = column.replace('/', '_').replace('\\', '_').replace(':', '_')
|
||||
save_path = os.path.join(save_dir, f'{safe_column_name}_boxplot_seaborn.png')
|
||||
plt.savefig(save_path, dpi=300, bbox_inches='tight')
|
||||
print(f"已保存: {save_path}")
|
||||
|
||||
# 关闭图形以释放内存
|
||||
plt.close()
|
||||
|
||||
print(f"\n所有箱型图已保存到目录: {save_dir}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"错误:{str(e)}")
|
||||
|
||||
def plot_boxplot_with_scatter(csv_file_path):
|
||||
"""
|
||||
读取CSV文件并绘制第五列之后数据列的箱型图,同时标注散点
|
||||
|
||||
参数:
|
||||
csv_file_path: CSV文件路径
|
||||
"""
|
||||
try:
|
||||
# 读取CSV文件
|
||||
df = pd.read_csv(csv_file_path)
|
||||
|
||||
# 获取第五列之后的数据列(索引从0开始,第五列索引为4)
|
||||
data_columns = df.iloc[:, 4:] # 从第五列开始的所有列
|
||||
|
||||
# 检查是否有数据列
|
||||
if data_columns.empty:
|
||||
print("错误:CSV文件中没有足够的列(至少需要5列)")
|
||||
return
|
||||
|
||||
# 设置图形大小
|
||||
plt.figure(figsize=(12, 8))
|
||||
|
||||
# 准备数据用于绘制箱型图
|
||||
box_data = []
|
||||
labels = []
|
||||
|
||||
for column in data_columns.columns:
|
||||
# 移除空值
|
||||
clean_data = data_columns[column].dropna()
|
||||
if len(clean_data) > 0:
|
||||
box_data.append(clean_data)
|
||||
labels.append(column)
|
||||
|
||||
# 绘制箱型图
|
||||
box_plot = plt.boxplot(box_data, labels=labels, patch_artist=True,
|
||||
showfliers=False) # 不显示异常值点,因为我们要自己绘制散点
|
||||
|
||||
# 美化箱型图
|
||||
colors = plt.cm.Set3(np.linspace(0, 1, len(box_data)))
|
||||
for patch, color in zip(box_plot['boxes'], colors):
|
||||
patch.set_facecolor(color)
|
||||
patch.set_alpha(0.7)
|
||||
|
||||
# 在每个箱型图上添加散点
|
||||
for i, data in enumerate(box_data):
|
||||
# 为每个数据点添加一些随机的x轴偏移,避免重叠
|
||||
x_pos = np.random.normal(i + 1, 0.04, size=len(data))
|
||||
|
||||
# 绘制散点
|
||||
plt.scatter(x_pos, data, alpha=0.6, s=20, color='red',
|
||||
edgecolors='black', linewidth=0.5, zorder=3)
|
||||
|
||||
# 设置标题和标签
|
||||
plt.title('数据列箱型图(带散点标注)', fontsize=16, fontweight='bold')
|
||||
plt.xlabel('数据列', fontsize=12)
|
||||
plt.ylabel('数值', fontsize=12)
|
||||
|
||||
# 旋转x轴标签以避免重叠
|
||||
plt.xticks(rotation=45, ha='right')
|
||||
|
||||
# 添加网格
|
||||
plt.grid(True, alpha=0.3, linestyle='--')
|
||||
|
||||
# 调整布局
|
||||
plt.tight_layout()
|
||||
|
||||
# 显示图形
|
||||
plt.show()
|
||||
|
||||
# 打印统计信息
|
||||
print(f"成功绘制了 {len(labels)} 个数据列的箱型图")
|
||||
print("数据列名称:", labels)
|
||||
|
||||
# 显示每列的基本统计信息
|
||||
print("\n各列基本统计信息:")
|
||||
for column in labels:
|
||||
data = data_columns[column].dropna()
|
||||
print(f"{column}: 数据点数={len(data)}, 均值={data.mean():.2f}, 中位数={data.median():.2f}")
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"错误:找不到文件 {csv_file_path}")
|
||||
except Exception as e:
|
||||
print(f"错误:{str(e)}")
|
||||
|
||||
def plot_boxplot_with_seaborn(csv_file_path):
|
||||
"""
|
||||
使用seaborn绘制更美观的箱型图(可选方法)
|
||||
|
||||
参数:
|
||||
csv_file_path: CSV文件路径
|
||||
"""
|
||||
try:
|
||||
# 读取CSV文件
|
||||
df = pd.read_csv(csv_file_path)
|
||||
|
||||
# 获取第五列之后的数据列
|
||||
data_columns = df.iloc[:, 4:]
|
||||
|
||||
if data_columns.empty:
|
||||
print("错误:CSV文件中没有足够的列(至少需要5列)")
|
||||
return
|
||||
|
||||
# 将数据转换为长格式用于seaborn
|
||||
melted_data = pd.melt(data_columns, var_name='列名', value_name='数值')
|
||||
melted_data = melted_data.dropna() # 移除空值
|
||||
|
||||
# 设置图形大小
|
||||
plt.figure(figsize=(12, 8))
|
||||
|
||||
# 使用seaborn绘制箱型图和散点
|
||||
sns.boxplot(data=melted_data, x='列名', y='数值', palette='Set3')
|
||||
sns.stripplot(data=melted_data, x='列名', y='数值',
|
||||
color='red', alpha=0.6, size=4, jitter=True)
|
||||
|
||||
# 设置标题和标签
|
||||
plt.title('数据列箱型图(Seaborn版本)', fontsize=16, fontweight='bold')
|
||||
plt.xlabel('数据列', fontsize=12)
|
||||
plt.ylabel('数值', fontsize=12)
|
||||
|
||||
# 旋转x轴标签
|
||||
plt.xticks(rotation=45, ha='right')
|
||||
|
||||
# 添加网格
|
||||
plt.grid(True, alpha=0.3, linestyle='--')
|
||||
|
||||
# 调整布局
|
||||
plt.tight_layout()
|
||||
|
||||
# 显示图形
|
||||
plt.show()
|
||||
|
||||
except Exception as e:
|
||||
print(f"错误:{str(e)}")
|
||||
|
||||
# 主程序
|
||||
if __name__ == "__main__":
|
||||
# 请修改为您的CSV文件路径
|
||||
csv_file_path = r"E:\code\WQ\yaobao925\output.csv" # 替换为您的CSV文件路径
|
||||
|
||||
print("请选择绘图方法:")
|
||||
print("1. 使用matplotlib绘制(所有列在一张图)")
|
||||
print("2. 使用seaborn绘制(所有列在一张图)")
|
||||
print("3. 分别绘制每列并保存(matplotlib版本)")
|
||||
print("4. 分别绘制每列并保存(seaborn版本)")
|
||||
|
||||
choice = input("请输入选择(1-4):").strip()
|
||||
|
||||
if choice == "1":
|
||||
plot_boxplot_with_scatter(csv_file_path)
|
||||
elif choice == "2":
|
||||
plot_boxplot_with_seaborn(csv_file_path)
|
||||
elif choice == "3":
|
||||
plot_individual_boxplots(csv_file_path)
|
||||
elif choice == "4":
|
||||
plot_individual_boxplots_seaborn(csv_file_path)
|
||||
else:
|
||||
print("默认使用分别绘制并保存(seaborn版本)...")
|
||||
plot_individual_boxplots_seaborn(csv_file_path)
|
||||
2561
map_beifeng.py
Normal file
2561
map_beifeng.py
Normal file
File diff suppressed because it is too large
Load Diff
184
plot_spectrum_by_parameter.py
Normal file
184
plot_spectrum_by_parameter.py
Normal file
@ -0,0 +1,184 @@
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import matplotlib.colors as mcolors
|
||||
from pathlib import Path
|
||||
|
||||
# 设置中文字体
|
||||
plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
|
||||
plt.rcParams['axes.unicode_minus'] = False
|
||||
|
||||
def load_and_plot_spectrum_by_parameters():
|
||||
"""
|
||||
加载数据并为每个水质参数绘制光谱曲线图
|
||||
"""
|
||||
try:
|
||||
# 数据文件路径
|
||||
data_file = Path(r"E:\code\WQ\yaobao925\spectral.csv")
|
||||
|
||||
if not data_file.exists():
|
||||
print(f"错误:数据文件不存在 - {data_file}")
|
||||
return
|
||||
|
||||
# 读取数据
|
||||
print("正在加载数据...")
|
||||
data = pd.read_csv(data_file)
|
||||
|
||||
print(f"数据形状: {data.shape}")
|
||||
print(f"列名: {list(data.columns[:15])}...") # 显示前15个列名
|
||||
|
||||
# 找到光谱数据的起始列(通常是数字列名)
|
||||
spectrum_start_idx = None
|
||||
for i, col in enumerate(data.columns):
|
||||
try:
|
||||
float(col)
|
||||
spectrum_start_idx = i
|
||||
break
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
if spectrum_start_idx is None:
|
||||
print("错误:未找到光谱数据列")
|
||||
return
|
||||
|
||||
print(f"光谱数据从第 {spectrum_start_idx + 1} 列开始")
|
||||
|
||||
# 分离水质参数和光谱数据
|
||||
water_quality_data = data.iloc[:, :spectrum_start_idx]
|
||||
spectrum_data = data.iloc[:, spectrum_start_idx:]
|
||||
|
||||
# 获取波长信息
|
||||
try:
|
||||
# 尝试直接转换为浮点数
|
||||
wavelengths = spectrum_data.columns.astype(float)
|
||||
except ValueError:
|
||||
# 如果包含字母,提取数字部分
|
||||
import re
|
||||
wavelengths = []
|
||||
for col in spectrum_data.columns:
|
||||
# 提取数字部分
|
||||
numbers = re.findall(r'\d+\.?\d*', str(col))
|
||||
if numbers:
|
||||
wavelengths.append(float(numbers[0]))
|
||||
else:
|
||||
# 如果没有数字,使用列索引
|
||||
wavelengths.append(float(len(wavelengths)))
|
||||
wavelengths = np.array(wavelengths)
|
||||
|
||||
print(f"波长范围: {wavelengths.min():.1f} - {wavelengths.max():.1f} nm")
|
||||
print(f"光谱数据形状: {spectrum_data.shape}")
|
||||
print(f"水质参数: {list(water_quality_data.columns)}")
|
||||
|
||||
# 过滤波长范围到374-1011nm
|
||||
wavelength_mask = (wavelengths >= 374) & (wavelengths <= 1011)
|
||||
filtered_wavelengths = wavelengths[wavelength_mask]
|
||||
filtered_spectrum_data = spectrum_data.iloc[:, wavelength_mask]
|
||||
|
||||
print(f"过滤后波长范围: {filtered_wavelengths.min():.1f} - {filtered_wavelengths.max():.1f} nm")
|
||||
print(f"过滤后光谱数据形状: {filtered_spectrum_data.shape}")
|
||||
|
||||
# 创建输出目录
|
||||
output_dir = Path(r'E:\code\WQ\yaobao925\plot')
|
||||
output_dir.mkdir(exist_ok=True)
|
||||
|
||||
# 为每个水质参数绘制光谱图
|
||||
for param_idx, parameter_name in enumerate(water_quality_data.columns):
|
||||
print(f"\n[{param_idx+1}/{len(water_quality_data.columns)}] 处理参数: {parameter_name}")
|
||||
|
||||
# 获取当前参数的数据
|
||||
parameter_values = water_quality_data[parameter_name]
|
||||
|
||||
# 过滤掉空值
|
||||
valid_mask = ~parameter_values.isna()
|
||||
if valid_mask.sum() == 0:
|
||||
print(f"参数 '{parameter_name}' 没有有效数据,跳过")
|
||||
continue
|
||||
|
||||
valid_param_values = parameter_values[valid_mask]
|
||||
valid_spectrum_data = filtered_spectrum_data[valid_mask]
|
||||
|
||||
print(f"有效样本数: {len(valid_param_values)}")
|
||||
|
||||
# 创建图形和轴
|
||||
fig, ax = plt.subplots(figsize=(12, 8))
|
||||
|
||||
# 归一化参数值到[0,1]范围,用于颜色映射
|
||||
param_min = valid_param_values.min()
|
||||
param_max = valid_param_values.max()
|
||||
|
||||
if param_max == param_min:
|
||||
# 如果所有值相同,使用中等颜色
|
||||
normalized_values = np.full(len(valid_param_values), 0.5)
|
||||
else:
|
||||
normalized_values = ((valid_param_values - param_min) / (param_max - param_min)).values
|
||||
|
||||
# 创建蓝红颜色映射(蓝色到红色)
|
||||
colormap = plt.cm.coolwarm # 蓝色(低值)到红色(高值)
|
||||
|
||||
# 绘制每条光谱曲线
|
||||
for i, (idx, spectrum) in enumerate(valid_spectrum_data.iterrows()):
|
||||
# 处理光谱数据中的空值
|
||||
spectrum_values = pd.Series(spectrum.values).fillna(0).values
|
||||
|
||||
# 根据参数值确定颜色
|
||||
color = colormap(normalized_values[i])
|
||||
alpha = 0.6 if len(valid_param_values) > 50 else 0.8 # 样本多时降低透明度
|
||||
|
||||
ax.plot(filtered_wavelengths, spectrum_values, color=color, alpha=alpha, linewidth=0.8)
|
||||
|
||||
# 设置图形属性
|
||||
ax.set_xlabel('波长 (nm)', fontsize=12)
|
||||
ax.set_ylabel('光谱强度', fontsize=12)
|
||||
ax.set_title(f'{parameter_name} 光谱曲线图\n参数范围: {param_min:.4f} - {param_max:.4f}',
|
||||
fontsize=14, fontweight='bold')
|
||||
|
||||
# 设置坐标轴范围,限制在374-1011nm
|
||||
ax.set_xlim(374, 1011)
|
||||
|
||||
# 添加网格
|
||||
ax.grid(True, alpha=0.3)
|
||||
|
||||
# 创建颜色条
|
||||
sm = plt.cm.ScalarMappable(cmap=colormap,
|
||||
norm=plt.Normalize(vmin=param_min, vmax=param_max))
|
||||
sm.set_array([])
|
||||
cbar = plt.colorbar(sm, ax=ax, shrink=0.8)
|
||||
cbar.set_label(f'{parameter_name} 数值', rotation=270, labelpad=20, fontsize=12)
|
||||
|
||||
# 添加统计信息文本框
|
||||
stats_text = f'样本数: {len(valid_param_values)}\n'
|
||||
stats_text += f'均值: {valid_param_values.mean():.4f}\n'
|
||||
stats_text += f'标准差: {valid_param_values.std():.4f}'
|
||||
|
||||
ax.text(0.02, 0.98, stats_text, transform=ax.transAxes,
|
||||
verticalalignment='top', bbox=dict(boxstyle='round',
|
||||
facecolor='wheat', alpha=0.8), fontsize=10)
|
||||
|
||||
# 优化布局
|
||||
plt.tight_layout()
|
||||
|
||||
# 保存图片
|
||||
# 清理参数名称,用于文件名
|
||||
safe_param_name = "".join(c for c in parameter_name if c.isalnum() or c in ('-', '_', '.')).rstrip()
|
||||
output_file = output_dir / f"{safe_param_name}_spectrum.png"
|
||||
plt.savefig(output_file, dpi=300, bbox_inches='tight')
|
||||
plt.close() # 关闭图形释放内存
|
||||
|
||||
print(f"图片已保存到: {output_file}")
|
||||
|
||||
print(f"\n{'='*80}")
|
||||
print(f"所有光谱图绘制完成!")
|
||||
print(f"输出目录: {output_dir}")
|
||||
print(f"{'='*80}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"处理过程中出现错误: {str(e)}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
def main():
|
||||
"""主函数"""
|
||||
load_and_plot_spectrum_by_parameters()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user