python 画柱状图和折线图【转载】

import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.ticker import FuncFormatter
from tkinter import Tk, filedialog, messagebox

# 使用Tkinter创建文件选择对话框并显示提示信息
def select_file(file_type):
    root = Tk()
    root.withdraw()  # 隐藏主窗口
    if file_type == 'csv':
        messagebox.showinfo("选择CSV文件", "请选择监控数据的CSV文件")
        file_path = filedialog.askopenfilename(title="选择CSV文件", filetypes=[("CSV files", "*.csv")])
    elif file_type == 'excel':
        messagebox.showinfo("选择Excel文件", "请选择主机数据的Excel文件")
        file_path = filedialog.askopenfilename(title="选择Excel文件", filetypes=[("Excel files", "*.xls *.xlsx")])
    root.destroy()
    return file_path

# 选择文件路径
csv_file_path = select_file('csv')
xls_file_path = select_file('excel')

# 文件列名变量
csv_columns = {
    'datetime': '数据时间',
    'instance_id': '实例ID',
    'monitor_value': '监控值'
}

xls_columns = {
    'name': '名称',
    'instance_id': '云主机ID'
}

# 读取CSV文件,尝试不同的编码
try:
    data = pd.read_csv(csv_file_path, encoding='utf-8')
except UnicodeDecodeError:
    data = pd.read_csv(csv_file_path, encoding='gbk')

# 读取Excel主机列表文件,并重命名列名以匹配
host_list = pd.read_excel(xls_file_path, usecols=[xls_columns['name'], xls_columns['instance_id']])
host_list = host_list.rename(columns={xls_columns['instance_id']: csv_columns['instance_id']})

# 将数据时间列转换为datetime格式
data[csv_columns['datetime']] = pd.to_datetime(data[csv_columns['datetime']])

# 提取日期部分
data['日期'] = data[csv_columns['datetime']].dt.date

# 与主机列表合并,以获取主机名称
data = data.merge(host_list, on=csv_columns['instance_id'], how='left')

# 计算每日最高监控值
daily_max = data.groupby([xls_columns['name'], '日期'])[csv_columns['monitor_value']].max().reset_index()

# 计算每日最高峰值的总和并求平均值
daily_max_sum = daily_max.groupby(xls_columns['name'])[csv_columns['monitor_value']].sum().reset_index()
daily_max_avg = daily_max_sum.copy()
daily_max_avg[csv_columns['monitor_value']] = daily_max_sum[csv_columns['monitor_value']] / daily_max['日期'].nunique()

# 找出TOP10的主机
top10_hosts = daily_max_avg.nlargest(10, csv_columns['monitor_value'])

# 设置Seaborn样式
sns.set(style="whitegrid")

# 自定义颜色
custom_color = (51 / 255, 152 / 255, 219 / 255)

# 设置字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False  # 正常显示负号

# 修改figsize以减小图像尺寸
smaller_figsize = (10, 5)

# 生成TOP10主机的每日最高峰值平均值柱状图
plt.figure(figsize=smaller_figsize)
bars = sns.barplot(x=xls_columns['name'], y=csv_columns['monitor_value'], data=top10_hosts, color=custom_color, width=0.5)
plt.xlabel('', fontsize=12)  # 主机名称设置为空标签
plt.ylabel('', fontsize=12)  # 平均监控值设置为空标签
plt.title('', fontsize=15)  # TOP10主机每日最高峰值平均值设置为空标签
plt.xticks(rotation=45)

# 在每个柱子上显示数值
for bar in bars.patches:
    height = bar.get_height()
    plt.text(bar.get_x() + bar.get_width() / 2.,
             height,
             f'{height:.2f}',
             ha='center', va='bottom',
             fontsize=10)  # 这里设置字体大小

# 自定义Y轴刻度标签为百分比格式
def percent_formatter(x, pos):
    return f'{x:.0f}%'

ax = plt.gca()
ax.yaxis.set_major_formatter(FuncFormatter(percent_formatter))

# 设置Y轴范围为0到100
ax.set_ylim(0, 100)

# 取消柱状图的边框
for spine in ax.spines.values():
    spine.set_visible(False)

# 取消竖线
ax.xaxis.grid(False)

plt.tight_layout()
plt.savefig('top10_daily_max_avg_bar_with_values.png', bbox_inches='tight')
plt.show()

# 计算每日最高监控值并绘图
fig = plt.figure(figsize=smaller_figsize)  # 这里调整线形图的尺寸
ax = fig.add_subplot(1, 1, 1)

for host in top10_hosts[xls_columns['name']]:
    host_data = daily_max[daily_max[xls_columns['name']] == host]
    sns.lineplot(x='日期', y=csv_columns['monitor_value'], data=host_data, marker='o', label=host, ax=ax)

plt.xlabel('', fontsize=12)  # 日期标签设置为空
plt.ylabel('', fontsize=12)  # 最高监控值标签设置为空
# plt.title('TOP10主机每日最高监控值', fontsize=15)

# 隐藏图形的边框
for spine in ax.spines.values():
    spine.set_visible(False)

# 设置x轴范围为数据的最小和最大日期
min_date = daily_max['日期'].min()
max_date = daily_max['日期'].max()
ax.set_xlim([min_date, max_date])

# 自定义Y轴刻度标签为百分比格式
ax.yaxis.set_major_formatter(FuncFormatter(percent_formatter))

# 设置Y轴范围为0到100
ax.set_ylim(0, 100)

# 取消竖线
ax.xaxis.grid(False)
# 显示x轴的下边框
ax.spines['bottom'].set_visible(True)

# 正确处理图例位置,将其移到图像上方,并设置frameon=False使其透明
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels, loc='lower center', bbox_to_anchor=(0.5, 1.02), fancybox=True, shadow=False, ncol=5, frameon=False)

plt.xticks(rotation=45)
plt.tight_layout(rect=[0, 0, 1, 0.95])  # 调整布局以适应图例
plt.savefig('top10_daily_max_line.png', bbox_inches='tight')
plt.show()

备注:云主机ID需要调整下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值