国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Python【Matplotlib】交互式時間序列繪圖,將x軸設(shè)置為日期時間格式并和鼠標拖動縮放相結(jié)合

這篇具有很好參考價值的文章主要介紹了Python【Matplotlib】交互式時間序列繪圖,將x軸設(shè)置為日期時間格式并和鼠標拖動縮放相結(jié)合。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

背景

上篇博客:python【matplotlib】鼠標拖動滾動縮放坐標范圍和拖動圖例共存,得到啟發(fā),我們已經(jīng)可以通過鼠標拖動縮放坐標范圍和移動圖例,來實現(xiàn)動態(tài)交互式繪圖了,對于x軸是時間序列的繪圖需求,能否也實現(xiàn)動態(tài)交互式繪圖呢?
答案是肯定的,接下來我將詳細描述其實現(xiàn)的方式。

效果

python plot x軸日期跳變,Python,python,matplotlib

實現(xiàn)步驟

準備工作

首先,我們需要導(dǎo)入必要的庫,包括datetime、timedelta、matplotlib.pyplot等。同時,我們設(shè)置中文顯示字體為"Microsoft YaHei",并準備一些時間序列數(shù)據(jù)。

from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import matplotlib.dates as mdate
from matplotlib.ticker import MaxNLocator

plt.rcParams["font.family"] = "Microsoft YaHei"

x = ['2023/12/20  15:23:01', '2023/12/20  15:23:02', '2023/12/20  15:23:03', ]

接下來,我們定義一個函數(shù)get_time,用于將時間字符串列表轉(zhuǎn)換為datetime對象。

def  get_time(time_list):
    date_object = []
    for time in time_list:
        date_object.append(datetime.strptime(time, "%Y/%m/%d  %H:%M:%S"))   # TODO 重點,把字符串轉(zhuǎn)換成時間對象
    return date_object

然后,我們調(diào)用這個函數(shù)將時間字符串列表轉(zhuǎn)換為datetime對象,并打印結(jié)果。

date_object = get_time(x)
print(date_object)

創(chuàng)建時間序列圖

現(xiàn)在,我們開始創(chuàng)建一個示例時間序列圖。在這個例子中,我們將時間序列數(shù)據(jù)與位移數(shù)據(jù)繪制在同一張圖上。

# 創(chuàng)建一個示例圖形
fig, ax = plt.subplots()
ax.plot(date_object, [2, 0, 6, ], label=f'位移', ls='-')  # TODO 重點,直接把datetime類型的時間賦值為x軸即可
ax.xaxis.set_major_formatter(mdate.DateFormatter('%H:%M:%S'))#設(shè)置時間標簽顯示格式

為了更好地交互,我們設(shè)置了x軸的日期格式為"%H:%M:%S",并打印出一些關(guān)于時間范圍的信息。

one_minutes = timedelta(minutes=1)
one_second = timedelta(seconds=1)
dates = mdate.drange(date_object[-1], date_object[-1] + one_minutes, one_second)    # TODO 取某個時間范圍,類似range()
print([mdate.num2date(t).strftime("%Y-%m-%d %H:%M:%S") for t in dates])

x_min, x_max = ax.get_xlim()    # 這里獲取到的x軸的范圍是時間的float格式,用mdate.num2date()可以轉(zhuǎn)為日期類型
print(x_min, x_max)
print("==============")
print(mdate.num2date(x_min), mdate.num2date(x_max))     # float 轉(zhuǎn) 日期
print("=============")
print(mdate.datestr2num(x[0]), mdate.datestr2num(x[2]))     # 日期轉(zhuǎn) float
print(date_object[0].timestamp(), date_object[2].timestamp())   #  日期轉(zhuǎn) float 和ax.get_xlim()獲取到的不一樣

調(diào)整坐標軸范圍和刻度

我們接下來進行一些坐標軸的調(diào)整,包括去除坐標軸兩端的空白、設(shè)置整數(shù)刻度、旋轉(zhuǎn)x軸標簽等。

xticks = ax.get_xticks()
yticks = ax.get_yticks()
# 計算相鄰刻度位置之間的差異
xtick_size = xticks[1] - xticks[0]
ytick_size = yticks[1] - yticks[0]
print(">>>>>>>")
print(xticks)
print(xtick_size)
print(type(mdate.num2date(x_min)))

ax.margins(0)     # 調(diào)整坐標軸兩端的空白為0
# ax.xaxis.set_major_locator(MaxNLocator(integer=True))     # (integer=True) 只有整數(shù)刻度才會顯示

# 重新設(shè)置x軸的范圍,這里不能直接用x_min, x_max,因為x_min, x_max是float類型,需要用mdate.num2date()轉(zhuǎn)為日期類型
one_second = timedelta(seconds=1)   # 1秒的時間
ax.set(xlim=(mdate.num2date(x_min)-one_second, mdate.num2date(x_max) + one_second))  # 左右分別增大1秒
plt.xticks(rotation=30)     #  設(shè)置x軸的刻度標簽 旋轉(zhuǎn)30度,防止標簽重疊
print(ax.get_xticks())

添加交互功能

現(xiàn)在,我們?yōu)閳D表添加鼠標拖動和滾輪滾動的交互功能。這部分代碼包括處理鼠標事件的函數(shù)和連接事件的操作。

startx = 0
starty = 0
mPress = False

# 鼠標拖動 處理事件
def call_move(event):
    # print(event.name)
    global mPress
    global startx
    global starty
    mouse_x = event.x
    mouse_y = event.y
    axtemp = event.inaxes
    if event.name == 'button_press_event':
        if axtemp and event.button == 1:
            if axtemp.get_legend():
                legend_bbox = axtemp.get_legend().get_window_extent()
                left_bottom = legend_bbox.get_points()[0]
                right_top = legend_bbox.get_points()[1]

                if left_bottom[0] <= mouse_x <= right_top[0] and left_bottom[1] <= mouse_y <= right_top[1]:
                    # print("在圖例上按下鼠標")
                    # 在圖例上按下鼠標
                    mPress = False
                    return
            # 沒有圖例的情況
            # print("在 Axes 上按下鼠標")
            # 在 Axes 上按下鼠標
            mPress = True
            startx = event.xdata
            starty = event.ydata
            return
    elif event.name == 'button_release_event':
        if axtemp and event.button == 1:
            mPress = False
    elif event.name == 'motion_notify_event':
        if axtemp and event.button == 1 and mPress:
            if axtemp.get_legend():
                legend_bbox = axtemp.get_legend().get_window_extent()
                left_bottom = legend_bbox.get_points()[0]
                right_top = legend_bbox.get_points()[1]

                if left_bottom[0] <= mouse_x <= right_top[0] and left_bottom[1] <= mouse_y <= right_top[1]:
                    print("在圖例上移動鼠標")
                    # 在圖例上按下鼠標
                    mPress = False
                    return

            # 沒有圖例的情況
            # print("在Axes上移動鼠標")
            x_min, x_max = axtemp.get_xlim()
            y_min, y_max = axtemp.get_ylim()
            w = x_max - x_min
            h = y_max - y_min
            # print(event)
            # 移動
            mx = event.xdata - startx
            my = event.ydata - starty
            # 注意這里, -mx,  因為下一次 motion事件的坐標,已經(jīng)是在本次做了移動之后的坐標系了,所以要體現(xiàn)出來
            # startx=event.xdata-mx  startx=event.xdata-(event.xdata-startx)=startx, 沒必要再賦值了
            # starty=event.ydata-my
            # print(mx,my,x_min,y_min,w,h)
            axtemp.set(xlim=(x_min - mx, x_min - mx + w))
            axtemp.set(ylim=(y_min - my, y_min - my + h))
            fig.canvas.draw_idle()  # 繪圖動作實時反映在圖像上

    return

# 滾輪滾動 處理事件
def call_scroll(event):
    # print(event.name)
    axtemp = event.inaxes
    # print('event:', event)
    # print(event.xdata, event.ydata)
    # 計算放大縮小后, xlim 和ylim
    if axtemp:
        x_min, x_max = axtemp.get_xlim()
        y_min, y_max = axtemp.get_ylim()
        print(x_min, x_max)
        w = x_max - x_min
        h = y_max - y_min
        curx = event.xdata
        cury = event.ydata
        curXposition = (curx - x_min) / w
        curYposition = (cury - y_min) / h


        if event.button == 'down':
            # print('befor:', w, h)
            w = w * 1.1   # 1.1
            h = h * 1.1
            # print('down', w, h)
        elif event.button == 'up':
            # print('befor:', w, h)
            w = w / 1.1
            h = h / 1.1
            # print('up', w, h)
        # print(curXposition, curYposition)
        newx = curx - w * curXposition
        newy = cury - h * curYposition
        axtemp.set(xlim=(newx, newx + w))
        axtemp.set(ylim=(newy, newy + h))
        # axtemp.margins(0)  # 調(diào)整坐標軸兩端的空白
        fig.canvas.draw_idle()  # 繪圖動作實時反映在圖像上


fig.canvas.mpl_connect('scroll_event', call_scroll)
fig.canvas.mpl_connect('button_press_event', call_move)
fig.canvas.mpl_connect('button_release_event', call_move)
# fig.canvas.mpl_connect('draw_event', call_move)
fig.canvas.mpl_connect('motion_notify_event', call_move)

最后,通過plt.show()展示交互式時間序列圖。

plt.show()

通過以上步驟,我們成功創(chuàng)建了一個交互式的時間序列圖,支持鼠標拖動和滾輪滾動操作,方便用戶查看不同時間范圍的數(shù)據(jù)。希望這篇博客對你理解Matplotlib的交互功能有所幫助。文章來源地址http://www.zghlxwxcb.cn/news/detail-839411.html

全部代碼

from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import matplotlib.dates as mdate
from matplotlib.ticker import MaxNLocator

plt.rcParams["font.family"] = "Microsoft YaHei"

x = ['2023/10/24  15:23:01', '2023/10/24  15:23:02', '2023/10/24  15:23:03', ]

def  get_time(time_list):
    date_object = []
    for time in time_list:
        date_object.append(datetime.strptime(time, "%Y/%m/%d  %H:%M:%S"))   # TODO 重點,把字符串轉(zhuǎn)換成時間對象
    return date_object


date_object = get_time(x)
# 從字符串到時間對象
# date_string = "2023-01-01 12:30:00"
# date_object = datetime.strptime(date_string, "%Y-%m-%d %H:%M:%S")

print(date_object)

# 創(chuàng)建一個示例圖形
fig, ax = plt.subplots()
ax.plot(date_object, [2, 0, 6, ], label=f'位移', ls='-')  # TODO 重點,直接把datetime類型的時間賦值為x軸即可
ax.xaxis.set_major_formatter(mdate.DateFormatter('%H:%M:%S'))#設(shè)置時間標簽顯示格式


one_minutes = timedelta(minutes=1)
one_second = timedelta(seconds=1)
dates = mdate.drange(date_object[-1], date_object[-1] + one_minutes, one_second)    # TODO 取某個時間范圍,類似range()
print([mdate.num2date(t).strftime("%Y-%m-%d %H:%M:%S") for t in dates])

x_min, x_max = ax.get_xlim()    # 這里獲取到的x軸的范圍是時間的float格式,用mdate.num2date()可以轉(zhuǎn)為日期類型
print(x_min, x_max)
print("==============")
print(mdate.num2date(x_min), mdate.num2date(x_max))     # float 轉(zhuǎn) 日期
print("=============")
print(mdate.datestr2num(x[0]), mdate.datestr2num(x[2]))     # 日期轉(zhuǎn) float
print(date_object[0].timestamp(), date_object[2].timestamp())   #  日期轉(zhuǎn) float 和ax.get_xlim()獲取到的不一樣

xticks = ax.get_xticks()
yticks = ax.get_yticks()
# 計算相鄰刻度位置之間的差異
xtick_size = xticks[1] - xticks[0]
ytick_size = yticks[1] - yticks[0]
print(">>>>>>>")
print(xticks)
print(xtick_size)
print(type(mdate.num2date(x_min)))

ax.margins(0)     # 調(diào)整坐標軸兩端的空白為0
# ax.xaxis.set_major_locator(MaxNLocator(integer=True))     # (integer=True) 只有整數(shù)刻度才會顯示

# 重新設(shè)置x軸的范圍,這里不能直接用x_min, x_max,因為x_min, x_max是float類型,需要用mdate.num2date()轉(zhuǎn)為日期類型
one_second = timedelta(seconds=1)   # 1秒的時間
ax.set(xlim=(mdate.num2date(x_min)-one_second, mdate.num2date(x_max) + one_second))  # 左右分別增大1秒
plt.xticks(rotation=30)     #  設(shè)置x軸的刻度標簽 旋轉(zhuǎn)30度,防止標簽重疊
print(ax.get_xticks())


startx = 0
starty = 0
mPress = False

# 鼠標拖動 處理事件
def call_move(event):
    # print(event.name)
    global mPress
    global startx
    global starty
    mouse_x = event.x
    mouse_y = event.y
    axtemp = event.inaxes
    if event.name == 'button_press_event':
        if axtemp and event.button == 1:
            if axtemp.get_legend():
                legend_bbox = axtemp.get_legend().get_window_extent()
                left_bottom = legend_bbox.get_points()[0]
                right_top = legend_bbox.get_points()[1]

                if left_bottom[0] <= mouse_x <= right_top[0] and left_bottom[1] <= mouse_y <= right_top[1]:
                    # print("在圖例上按下鼠標")
                    # 在圖例上按下鼠標
                    mPress = False
                    return
            # 沒有圖例的情況
            # print("在 Axes 上按下鼠標")
            # 在 Axes 上按下鼠標
            mPress = True
            startx = event.xdata
            starty = event.ydata
            return
    elif event.name == 'button_release_event':
        if axtemp and event.button == 1:
            mPress = False
    elif event.name == 'motion_notify_event':
        if axtemp and event.button == 1 and mPress:
            if axtemp.get_legend():
                legend_bbox = axtemp.get_legend().get_window_extent()
                left_bottom = legend_bbox.get_points()[0]
                right_top = legend_bbox.get_points()[1]

                if left_bottom[0] <= mouse_x <= right_top[0] and left_bottom[1] <= mouse_y <= right_top[1]:
                    print("在圖例上移動鼠標")
                    # 在圖例上按下鼠標
                    mPress = False
                    return

            # 沒有圖例的情況
            # print("在Axes上移動鼠標")
            x_min, x_max = axtemp.get_xlim()
            y_min, y_max = axtemp.get_ylim()
            w = x_max - x_min
            h = y_max - y_min
            # print(event)
            # 移動
            mx = event.xdata - startx
            my = event.ydata - starty
            # 注意這里, -mx,  因為下一次 motion事件的坐標,已經(jīng)是在本次做了移動之后的坐標系了,所以要體現(xiàn)出來
            # startx=event.xdata-mx  startx=event.xdata-(event.xdata-startx)=startx, 沒必要再賦值了
            # starty=event.ydata-my
            # print(mx,my,x_min,y_min,w,h)
            axtemp.set(xlim=(x_min - mx, x_min - mx + w))
            axtemp.set(ylim=(y_min - my, y_min - my + h))
            fig.canvas.draw_idle()  # 繪圖動作實時反映在圖像上

    return

# 滾輪滾動 處理事件
def call_scroll(event):
    # print(event.name)
    axtemp = event.inaxes
    # print('event:', event)
    # print(event.xdata, event.ydata)
    # 計算放大縮小后, xlim 和ylim
    if axtemp:
        x_min, x_max = axtemp.get_xlim()
        y_min, y_max = axtemp.get_ylim()
        print(x_min, x_max)
        w = x_max - x_min
        h = y_max - y_min
        curx = event.xdata
        cury = event.ydata
        curXposition = (curx - x_min) / w
        curYposition = (cury - y_min) / h


        if event.button == 'down':
            # print('befor:', w, h)
            w = w * 1.1   # 1.1
            h = h * 1.1
            # print('down', w, h)
        elif event.button == 'up':
            # print('befor:', w, h)
            w = w / 1.1
            h = h / 1.1
            # print('up', w, h)
        # print(curXposition, curYposition)
        newx = curx - w * curXposition
        newy = cury - h * curYposition
        axtemp.set(xlim=(newx, newx + w))
        axtemp.set(ylim=(newy, newy + h))
        # axtemp.margins(0)  # 調(diào)整坐標軸兩端的空白
        fig.canvas.draw_idle()  # 繪圖動作實時反映在圖像上


fig.canvas.mpl_connect('scroll_event', call_scroll)
fig.canvas.mpl_connect('button_press_event', call_move)
fig.canvas.mpl_connect('button_release_event', call_move)
# fig.canvas.mpl_connect('draw_event', call_move)
fig.canvas.mpl_connect('motion_notify_event', call_move)


plt.show()

到了這里,關(guān)于Python【Matplotlib】交互式時間序列繪圖,將x軸設(shè)置為日期時間格式并和鼠標拖動縮放相結(jié)合的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • Python-OpenCV中的圖像處理-GrabCut算法交互式前景提取

    Python-OpenCV中的圖像處理-GrabCut算法交互式前景提取

    cv2.grabCut(img: Mat, mask: typing.Optional[Mat], rect, bgdModel, fgdModel, iterCount, mode=…) img:輸入圖像 mask:掩模圖像,用來確定那些區(qū)域是背景,前景,可能是前景/背景等。 可以設(shè)置為: cv2.GC_BGD,cv2.GC_FGD,cv2.GC_PR_BGD,cv2.GC_PR_FGD,或者直接輸入 0,1,2,3 也行。 rect :包含前景的矩形,格式為

    2024年02月13日
    瀏覽(104)
  • python:基于GeoPandas和GeoViews庫將GEDI激光高程數(shù)據(jù)映射到交互式地圖

    python:基于GeoPandas和GeoViews庫將GEDI激光高程數(shù)據(jù)映射到交互式地圖

    作者:CSDN @ _養(yǎng)樂多_ 本文將介紹 GEDI(Global Ecosystem Dynamics Investigation)激光雷達數(shù)據(jù)某數(shù)據(jù)點波形數(shù)據(jù)提取,并繪制圖表,添加其他圖表元素并使圖表具有交互性。 在本文中,我們將探索如何打開、讀取和處理GEDI數(shù)據(jù),并利用地理信息處理庫GeoPandas和地理空間數(shù)據(jù)可視化庫

    2024年02月15日
    瀏覽(33)
  • 基于python下selenium庫實現(xiàn)交互式圖片保存操作(批量保存瀏覽器中的圖片)

    基于python下selenium庫實現(xiàn)交互式圖片保存操作(批量保存瀏覽器中的圖片)

    Selenium是最廣泛使用的開源Web UI(用戶界面)自動化測試套件之一,可以通過編程與瀏覽量的交互式操作對網(wǎng)頁進行自動化控制?;谶@種操作進行數(shù)據(jù)保存操作,尤其是在圖像數(shù)據(jù)的批量保存上占據(jù)優(yōu)勢。本博文基于selenium 與jupyterlab實現(xiàn)批量保存瀏覽器搜索到的圖片。 Se

    2024年01月24日
    瀏覽(57)
  • 交互式shell與非交互式shell,反彈shell

    交互shell就是shell等待你的輸入,并且立即執(zhí)行你提交的命令。 這種模式被稱作交互式是因為shell與用戶進行交互。 這種模式也是大多數(shù)用戶非常熟悉的:登錄、執(zhí)行一些命令、簽退。當簽退后,shell也終止了。 需要進行信息交互,例如輸入某個信息 會返回信息 你需要對其輸

    2024年02月02日
    瀏覽(28)
  • Selenium4+Python3 - Iframe、Select控件、交互式彈出框、執(zhí)行JS、Cookie操作

    Selenium4+Python3 - Iframe、Select控件、交互式彈出框、執(zhí)行JS、Cookie操作

    iframe識別: 語法: driver.switch_to.frame(‘方式’) 1、常見處理方法三種 index:下標 name:id或name屬性的值 webelement:元素 2、通過下標進入 進入第一個iframe: 3、通過id或name屬性的值進入 通過id或name屬性的值進入指定的iframe: 4、通過iframe元素進入iframe 通過iframe元素進入指定i

    2024年02月04日
    瀏覽(95)
  • 【OpenCV-Python】——單/多模板匹配&分水嶺算法圖像分割&圖像金字塔&交互式前景提取

    目錄 前言: 1、模板匹配 1.1 單目標匹配 1.2 多目標匹配 2、圖像分割

    2024年02月07日
    瀏覽(40)
  • 人機交互學習-6 交互式系統(tǒng)的設(shè)計

    人機交互學習-6 交互式系統(tǒng)的設(shè)計

    Allan Cooper建議不要過早地把重點放在小細節(jié)、小部件和精細的交互上會妨礙產(chǎn)品的設(shè)計,應(yīng)先站在一個高層次上關(guān)注用戶界面和相關(guān)行為的整體結(jié)構(gòu) Allan Cooper提出的交互框架不僅 定義了高層次的屏幕布局 ,同時定義了 產(chǎn)品的工作流、行為和組織 。它包括了6個主要步驟:

    2024年02月09日
    瀏覽(20)
  • 人機交互學習-5 交互式系統(tǒng)的需求

    人機交互學習-5 交互式系統(tǒng)的需求

    關(guān)于目標產(chǎn)品的一種陳述,它指定了產(chǎn)品應(yīng)做什么,或者應(yīng)如何工作 應(yīng)該是具體、明確和無歧義的 搜集數(shù)據(jù) 解釋數(shù)據(jù) 提取需求 注:了解 功能不同 智能冰箱:應(yīng)能夠提示黃油已用完 字處理器:系統(tǒng)應(yīng)支持多種格式 物理條件不同 移動設(shè)備運行的系統(tǒng)應(yīng)盡可能小,屏幕顯示限

    2024年02月09日
    瀏覽(27)
  • Pyspark交互式編程

    Pyspark交互式編程 有該數(shù)據(jù)集Data01.txt 該數(shù)據(jù)集包含了某大學計算機系的成績,數(shù)據(jù)格式如下所示: 根據(jù)給定的數(shù)據(jù)集,在pyspark中通過編程來完成以下內(nèi)容: 該系總共有多少學生; (提前啟動好pyspark) 該系共開設(shè)了多少門課程; Tom同學的總成績平均分是多少; 求每名同學的

    2023年04月08日
    瀏覽(33)
  • 交互式shell

    交互式shell

    交互式模式就是shell等待用戶的輸入,并且執(zhí)行用戶提交的命令。這種模式被稱作交互式是因為shell與用戶進行交互。這種模式也是大多數(shù)用戶非常熟悉的:登錄、執(zhí)行一些命令、簽退。當用戶簽退后,shell也終止了。 shell也可以運行在另外一種模式:非交互式模式。在這種模

    2024年02月02日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包