You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter+Matplotlib绘图X轴日期时间标签与网格显示异常求助

Tkinter+Matplotlib图表X轴刻度/网格未对齐最后一条数据的问题

我编写了一个基于Tkinter的图表生成代码,需将DataFrame中的Date与Time字段合并后作为X轴,但X轴的标签和网格显示不符合预期——最后一个网格未对应DataFrame的最后一条日期时间数据。希望X轴能像Y轴一样,从第一条数据的索引位置开始,到最后一条数据的索引位置结束。

代码实现

import tkinter as tk
import os
from tkinter import filedialog
from matplotlib.figure import Figure
import pandas as pd
import numpy as np
import time
import tkinter.messagebox
from matplotlib.font_manager import FontProperties
from pathlib import Path

fontP = FontProperties()
fontP.set_size('x-small')

root= tk.Tk()
canvas1 = tk.Canvas(root, width = 800, height = 300)
canvas1.pack()

label1 = tk.Label(root, text='Data Analyser')
label1.config(font=('Arial', 20))
date1=time.strftime("%H-%M-%S,%d-%m-%Y")

def get1lineGraph ():
      global df

      import_file_path = filedialog.askopenfilename(parent=root)
      filename=Path(import_file_path).stem
      isExist = os.path.exists(filename)
      if not isExist:
          os.makedirs(filename)
      df = pd.read_excel (import_file_path)
      df['Date'] = pd.to_datetime(df['Date'])
      daytime=df['Time'].astype(str) + '\n' + df['Date'].astype(str)
      major_ticks_x1 = np.arange(0, len(df.index+1)+3.9, len(df.index+1)/4)
      minor_ticks_x1 = np.arange(0, len(df.index+1)+3.9, len(df.index+1)/8)
      if(df[clicked1.get()].max()==df[clicked1.get()].min()):
          major_ticks_y11 = np.arange(0,14,2)
          minor_ticks_y11 = np.arange(0,14,4)
      else:
          major_ticks_y11 = np.arange(df[clicked1.get()].min(), df[clicked1.get()].max()+3.9, (df[clicked1.get()].max()-df[clicked1.get()].min())/4)
          minor_ticks_y11 = np.arange(df[clicked1.get()].min(), df[clicked1.get()].max()+3.9, (df[clicked1.get()].max()-df[clicked1.get()].min())/8)
      x1 = daytime
      y11 = df[clicked1.get()].astype(float)

      figure11 = Figure(figsize=(11,4), dpi=100)
      subplot11 = figure11.add_subplot(1,1,1)
      t11, = subplot11.plot(x1, y11, color='blue', linestyle='solid', linewidth = 2, label=clicked1.get())
      subplot11.set_ylabel(clicked1.get())
      subplot11.set_xlabel('Date & Time')
      subplot11.set_xticks(major_ticks_x1)
      subplot11.set_xticks(minor_ticks_x1, minor=True)
      subplot11.set_yticks(major_ticks_y11)
      subplot11.set_yticks(minor_ticks_y11, minor=True)
      subplot11.grid(which='both')
      subplot11.grid(which='minor', alpha=0.2)
      subplot11.grid(which='major', alpha=0.5)
      subplot11.set_title(clicked1.get()+' VS Time')
      subplot11.legend(loc = 'upper left', bbox_to_anchor=(1, 1), prop=fontP)
      figure11.tight_layout()
      figure11.savefig(filename+'/Bldg1_'+clicked1.get()+'_'+date1+'.png')
      
      tkinter.messagebox.showinfo("Message from Bldg 1.",  "Graph is saved in .png file format in your PC.",parent=root)
      
options1 = [
    "P1",
    "P2",
    "P3",
    "P4"
]
clicked1 = tk.StringVar()
clicked1.set( "Select Y-axis Parameter" )
drop1 = tk.OptionMenu( root , clicked1 , *options1 )
canvas1.create_window(250, 100, window=drop1)

browseButton_Excel1line = tk.Button(root, text='Generate graph with selected Y-axis', command=get1lineGraph, bg='green', fg='white', font=('helvetica', 12, 'bold'))
canvas1.create_window(500, 100, window=browseButton_Excel1line)

button1 = tk.Button (root, text='Exit from Building 1!', command=root.destroy, bg='green', fg='white', font=('helvetica', 11, 'bold'))
canvas1.create_window(400, 180, window=button1)
root.mainloop()

测试用Excel数据

Date    Time    P1  P2  P3  P4  
1-9-2019    9:57:00 114.33  21.07   21.01   0   
1-9-2019    9:58:00 114.33  21.07   21.01   0   
1-9-2019    9:59:00 6.6 4.63    21.01   0   
1-9-2019    10:00:00    5.72    4.05    21.01   0   
1-9-2019    10:01:00    5.28    4.05    21.01   0   
1-9-2019    10:02:00    5.28    4.05    21.01   0   
1-9-2019    10:03:00    5.72    4.05    21.01   0   
1-9-2019    10:04:00    5.72    3.76    21.01   0   
1-9-2019    10:05:00    5.72    4.05    21.01   0   
1-9-2019    10:06:00    5.72    4.05    21.01   0   
1-9-2019    10:07:00    5.72    4.05    21.01   0   
1-9-2019    10:08:00    5.72    4.05    21.01   0   
1-9-2019    10:09:00    5.72    4.05    21.01   0   
1-9-2019    10:10:00    5.72    4.34    16.82   0   
1-9-2019    10:11:00    5.72    4.34    16.79   0   
1-9-2019    10:12:00    5.72    4.34    16.7    0   
1-9-2019    10:13:00    5.72    4.34    16.79   0

当前生成的图表

图表截图

解决方案

问题出在X轴刻度的计算逻辑上,原代码中len(df.index+1)的写法错误,且刻度范围没有精准覆盖到最后一条数据的索引位置。修改以下代码片段即可解决:

修改X轴刻度计算部分

将原代码中的:

major_ticks_x1 = np.arange(0, len(df.index+1)+3.9, len(df.index+1)/4)
minor_ticks_x1 = np.arange(0, len(df.index+1)+3.9, len(df.index+1)/8)

替换为:

# 获取最后一条数据的索引值
data_last_index = len(df) - 1
# 生成主刻度:从0到最后索引,均匀分成4段(共5个刻度点)
major_ticks_x1 = np.linspace(0, data_last_index, 5)
# 生成次刻度:从0到最后索引,均匀分成8段(共9个刻度点)
minor_ticks_x1 = np.linspace(0, data_last_index, 9)

代码说明

  1. len(df)-1是DataFrame最后一条数据的索引(因为索引从0开始)
  2. np.linspace会生成指定区间内均匀分布的数值,确保首尾刻度精准对应第一条和最后一条数据的位置
  3. 主刻度分成4段(5个点)、次刻度分成8段(9个点),和原代码的分段逻辑保持一致,但范围精准覆盖数据区间

修改后,X轴的网格和刻度会完全对齐到数据的首尾位置,和Y轴的显示逻辑保持一致。

内容的提问来源于stack exchange,提问作者Amit K Kushwaha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:40:44