日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

origin画图_把heatmap翻一转:imshow的origin和extent

發(fā)布時間:2024/10/8 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 origin画图_把heatmap翻一转:imshow的origin和extent 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

背景故事:

之前畫熱度圖用的seaborn,里面好像有一個inversey的選項,可以把熱度圖直接做垂直翻轉(zhuǎn)。結(jié)合numpy的histogram2d來看,這是十分實用的,因為histogram2d得到的2d heatmap直接用matplotlib.pyplot的Axes.imshow方法畫出來的圖,是上下顛倒的,如果用一次np.flip(heatmap, 0),會發(fā)現(xiàn)圖放正了,但是縱坐標的刻度還是反的,需要反著寫Axes.set_yticks與Axes.set_yticklabels來調(diào)正。很顯然,plt作為使用如此廣泛的庫,沒有理由這么搞人心態(tài)。

所以查了下np.histogram2d的文檔,發(fā)現(xiàn)范例里有用到extent,再去看了看matplotlib的文檔,發(fā)現(xiàn)了extent的具體用法,在這里記錄一下。


官方原文點上面那個“extent的具體用法”,有超鏈接的,點進去就可以看了,下面的內(nèi)容是我自己寫的范例。

首先看看背景故事里說的麻煩的情況:

import numpy as np import matplotlib.pyplot as pltx = np.random.normal(0, 1, (100,)) y = np.random.normal(0, 1, (100,)) heatmap, xedge, yedge = np.histogram2d(x, y, bins=(100, 10), range=((-4, 4), (-3, 3)))fig, ax = plt.subplots() fig.set_size_inches(4, 12) ax.set_xlabel('x') ax.set_ylabel('y') ax.imshow(heatmap) fig.savefig('./bad1.png')

這是不加任何修飾,直接畫出來的圖。該圖體現(xiàn)了一個最顯然的問題,就是我的x應該是100個bin,y應該是10個bin,應該是一個矮胖的形狀而不是一個高瘦的。

這是因為np.histogram2d的返回值就是這樣設(shè)定的,如果需要畫圖,要先轉(zhuǎn)置一下:

heatmap = heatmap.T

那么再畫一次:

fig, ax = plt.subplots() fig.set_size_inches(12, 4) ax.set_xlabel('x') ax.set_ylabel('y') ax.imshow(heatmap) fig.savefig('./bad2.png')

現(xiàn)在看上去對勁了,但是縱坐標是反的,我們希望的圖是橫縱坐標都從0開始。那么怎么解決呢?

fig, ax = plt.subplots() fig.set_size_inches(12, 4) ax.set_xlabel('x') ax.set_ylabel('y') heatmap_inverse = np.flip(heatmap, 0) ax.imshow(heatmap) ax.set_yticks([5, 9]) ax.set_yticklabels(['5', '0']) fig.savefig('./bad3.png')

這么一看效果是達到了,實際上操作很麻煩而且思路很奇怪,如果把code給別人看別人可能會疑惑。所以就需要用到imshow的origin參數(shù)。

先在一個簡單的2d heatmap上測試,產(chǎn)生一個長這樣的方陣:

test_map = np.eye(10) test_map *= np.arange(1, 11, 1)

就是對角元為1到10的對角矩陣,畫出來是這樣的:

test_fig, test_ax = plt.subplots() test_ax.imshow(test_map) test_fig.savefig('./test_default.png')

修改一下origin參數(shù)試試:

test_fig, test_ax = plt.subplots() test_ax.imshow(test_map, origin='upper') test_ax.set_title('origin = upper') test_fig.savefig('./test_upper.png') test_ax.imshow(test_map, origin='lower') test_ax.set_title('origin = lower') test_fig.savefig('./test_lower.png')

可以看出,origin默認值的就是upper,它的意思是從上往下畫;對應地,lower就是從下往上畫。不難發(fā)現(xiàn),不論怎樣規(guī)定,橫坐標都是從左往右的,這也確實比較符合人們的習慣。

那么之前的熱度圖就好畫了,指定origin為lower即可。

fig, ax = plt.subplots() fig.set_size_inches(12, 4) ax.set_xlabel('x') ax.set_ylabel('y') ax.imshow(heatmap, origin='lower') fig.savefig('./good.png')

這就不再需要自己折騰了。以上就是origin的設(shè)置。然后可能有人就想說了,我不喜歡橫坐標從左到右,我要復古一下,從右到左,怎么辦呢?那就需要用到extent了。

首先給出四個不同的extent,保存在列表里:

extent = [[0, 9, 0, 9], [0, 9, 9, 0], [9, 0, 0, 9], [9, 0, 9, 0]]

extent參數(shù)接受1個array-like的參數(shù),也就是有sequence概念的輸入(tuple、list、1darray均可)。這個array-like的參數(shù)分別代表了左右下上,也就是[橫軸最左邊的值,橫軸最右邊的值,縱軸最下面的值,縱軸最上面的值]這樣。

然后畫圖看一下效果:

for idx in range(4):test_fig, test_ax = plt.subplots()test_ax.imshow(test_map, extent=extent[idx])test_ax.set_title('extent%d'%(idx+1))test_fig.savefig('./test_extent%d.png'%(idx+1))

可以發(fā)現(xiàn),成功地調(diào)換了坐標軸的順序,但是軸變了,圖沒變,好像很離譜。這是因為,extent的作用是改變橫縱坐標展示的范圍,如果你去看官方的文檔,會發(fā)現(xiàn)它可以搭配Axes.set_xlim與Axes.set_ylim使用,來讓圖片轉(zhuǎn)起來,就像下面這樣:

for idx in range(4):test_fig, test_ax = plt.subplots()test_ax.imshow(test_map, extent=extent[idx])test_ax.set_title('extent_with_xylim%d'%(idx+1))test_ax.set_xlim([0, 9])test_ax.set_ylim([0, 9])test_fig.savefig('./test_extent%d_with_xylim.png'%(idx+1))

然而實際上你也會發(fā)現(xiàn),圖雖然轉(zhuǎn)起來了,但是圖上的點和橫縱坐標并不能對應上,以這四張圖為例,只有圖2(extent_with_xylim2)是對的,而它等價于指定origin='lower'。那么我們想要的那種,圖轉(zhuǎn)起來,坐標也對應上,應該怎么操作呢?

xylim = [[[0, 9], [0, 9]], [[0, 9], [9, 0]], [[9, 0], [0, 9]], [[9, 0], [9, 0]]] for idx in range(4):test_fig, test_ax = plt.subplots()test_ax.imshow(test_map, extent=[0, 9, 9, 0])test_ax.set_title('xylim%d'%(idx+1))test_ax.set_xlim(xylim[idx][0])test_ax.set_ylim(xylim[idx][1])test_fig.savefig('./test_xylim%d.png'%(idx+1))

其實只要設(shè)置好xlim和ylim就可以了,然后用extent來限定坐標范圍(如果不設(shè)置的話,第一行、列和最后一行、列將很窄)。一個疑問也許是,為什么這里的extent=[0, 9, 9, 0]?因為默認的origin是upper,縱坐標是倒過來的;如果設(shè)置origin為lower,就可以把extent設(shè)置為更符合直覺的[0, 9, 0, 9]。

matplotlib的水真是深啊~


(完。)

總結(jié)

以上是生活随笔為你收集整理的origin画图_把heatmap翻一转:imshow的origin和extent的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。