2012-01-17 52 views
8

我使用數圖,在matplotlib如下,大致如下。matplotlib問題繪圖記錄的數據和設置其X/Y界限

plt.scatter(x, y) 

# use log scales 
plt.gca().set_xscale('log') 
plt.gca().set_yscale('log') 

# set x,y limits 
plt.xlim([-1, 3]) 
plt.ylim([-1, 3]) 

的第一個問題是,如果沒有的x,y的限制,matplotlib設定尺度,使得大部分數據是不可見的 - 由於某些原因,它不使用沿x和y的最大值和最小值尺寸,所以默認情節是非常誤導。

當我使用plt.xlim,plt.ylim手動設置極限時,我認爲這是log10單位(即1/10到3000)的-1到3,我得到一個類似於附加的圖。 enter image description here

這裏的軸標籤沒有意​​義:它從10^1到10^3。這裏發生了什麼?

我包括低於一個更詳細的例子顯示了所有這些問題的數據:

import matplotlib 
import matplotlib.pyplot as plt 
from numpy import * 

x = array([58, 0, 20, 2, 2, 0, 12, 17, 16, 6, 257, 0, 0, 0, 0, 1, 0, 13, 25, 9, 13, 94, 0, 0, 2, 42, 83, 0, 0, 157, 27, 1, 80, 0, 0, 0, 0, 2, 0, 41, 0, 4, 0, 10, 1, 4, 63, 6, 0, 31, 3, 5, 0, 61, 2, 0, 0, 0, 17, 52, 46, 15, 67, 20, 0, 0, 20, 39, 0, 31, 0, 0, 0, 0, 116, 0, 0, 0, 11, 39, 0, 17, 0, 59, 1, 0, 0, 2, 7, 0, 66, 14, 1, 19, 0, 101, 104, 228, 0, 31]) 

y = array([60, 0, 9, 1, 3, 0, 13, 9, 11, 7, 177, 0, 0, 0, 0, 1, 0, 12, 31, 10, 14, 80, 0, 0, 2, 30, 70, 0, 0, 202, 26, 1, 96, 0, 0, 0, 0, 1, 0, 43, 0, 6, 0, 9, 1, 3, 32, 6, 0, 20, 1, 2, 0, 52, 1, 0, 0, 0, 26, 37, 44, 13, 74, 15, 0, 0, 24, 36, 0, 22, 0, 0, 0, 0, 75, 0, 0, 0, 9, 40, 0, 14, 0, 51, 2, 0, 0, 1, 9, 0, 59, 9, 0, 23, 0, 80, 81, 158, 0, 27]) 

c = 0.01 

plt.figure(figsize=(5,3)) 
s = plt.subplot(1, 3, 1) 
plt.scatter(x + c, y + c) 
plt.title('Unlogged') 
s = plt.subplot(1, 3, 2) 
plt.scatter(x + c, y + c) 
plt.gca().set_xscale('log', basex=2) 
plt.gca().set_yscale('log', basey=2) 
plt.title('Logged') 
s = plt.subplot(1, 3, 3) 
plt.scatter(x + c, y + c) 
plt.gca().set_xscale('log', basex=2) 
plt.gca().set_yscale('log', basey=2) 
plt.xlim([-2, 20]) 
plt.ylim([-2, 20]) 
plt.title('Logged with wrong xlim/ylim') 
plt.savefig('test.png') 

這將產生下面的情節:從左至右

enter image description here

在第一個插曲,我們擁有未記錄的原始數據。第二,我們已經記錄了數值默認視圖。第三,我們已經記錄了指定了x/y lim的值。我的問題是:

  1. 爲什麼散點圖的默認x/y邊界是錯誤的?該手冊說它應該使用數據中的最小值和最大值,但這顯然不是這種情況。它挑選出隱藏絕大多數數據的值。

  2. 那爲什麼當我設定的界限我自己,在第三散點圖從左至右,它顛倒了標籤的順序?在2^5之前顯示2^8?這很混亂。

  3. 最後,我怎樣才能得到它,這樣的地塊並不像壓扁通過使用次要情節默認?我希望這些散點圖是正方形的。

編輯:感謝喬和洪克的回覆。如果我試圖調整次要情節像這是方形:

plt.figure(figsize=(5,3), dpi=10) 
s = plt.subplot(1, 2, 1, adjustable='box', aspect='equal') 
plt.scatter(x + c, y + c) 
plt.title('Unlogged') 
s = plt.subplot(1, 2, 2, adjustable='box', aspect='equal') 
plt.scatter(x + c, y + c) 
plt.gca().set_xscale('log', basex=2) 
plt.gca().set_yscale('log', basey=2) 
plt.title('Logged') 

我得到下面的結果:

enter image description here

我怎樣才能使每一個情節是方形的,相互協調的?它應該只是爲方形的網格,所有大小相等......

編輯2:

爲了促進東西回來,這裏是一個如何把這些日誌2個地塊,使軸顯示,其非指數記數法:

import matplotlib 

from matplotlib.ticker import FuncFormatter 

def log_2_product(x, pos): 
    return "%.2f" %(x) 

c = 0.01 
plt.figure(figsize=(10,5), dpi=100) 
s1 = plt.subplot(1, 2, 1, adjustable='box', aspect='equal') 
plt.scatter(x + c, y + c) 
plt.title('Unlogged') 
plotting.axes_square(s1) 
s2 = plt.subplot(1, 2, 2, adjustable='box', aspect='equal') 
min_x, max_x = min(x + c), max(x + c) 
min_y, max_y = min(y + c), max(y + c) 
plotting.axes_square(s2) 
plt.xlim([min_x, max_x]) 
plt.ylim([min_y, max_y]) 
plt.gca().set_xscale('log', basex=2) 
plt.gca().set_yscale('log', basey=2) 
plt.scatter(x + c, y + c) 
formatter = FuncFormatter(log_2_product) 
s2.xaxis.set_major_formatter(formatter) 
s2.yaxis.set_major_formatter(formatter) 

plt.title('Logged') 
plt.savefig('test.png') 

感謝您的幫助。

+1

最奇怪的!我很想知道我自己。 – 2012-01-17 00:56:35

回答

12

@honk已經回答了您的主要問題,但對於其他人(以及您的原始問題),請閱讀幾個教程或查看一些示例。 :)

你越來越困惑,因爲你沒有看過你正在使用的函數的文檔。

爲什麼散點圖的默認x/y邊界是錯誤的?手冊 表示它應該使用數據中的最小值和最大值,但在這裏顯然不是這種情況。它挑選出隱藏大部分數據的值。

它當然不會在文檔中說。

默認情況下,matplotlib將「舍入」到最接近的「偶數」的繪圖限制。在日誌圖的情況下,這是基地的最近功率。

如果你想讓它嚴格地捕捉到數據的最小值和最大值,指定:

ax.axis('tight') 

或等價

plt.axis('tight') 

那爲什麼當我設置的界限自己,在左側的第三個散點圖中,它反轉了標籤的順序?在 2^5之前顯示2^8?這很混亂。

不是。它在2^5之前顯示2^-8。你只是擠了太多的標籤。指數中的負號被重疊的文字隱藏起來。嘗試調整的情節或調用plt.tight_layout()(或更改字體大小或dpi的。改變dpi是使所有的字體保存的圖像上的更大或更小的快捷方式。)

最後,我怎麼能得到它,以便在默認情況下使用子圖使得圖不會像 那樣凹陷?我希望這些散點圖是正方形的。

有幾種方法可以做到這一點,這取決於你的意思是「平方」。 (也就是說,你想讓劇情的長寬比變化還是限制?)

我猜你的意思是兩個,在這種情況下,你會通過adjustable='box'aspect='equal'plt.subplot。(您也可以將其設在多種不同的方式,(plt.axis('equal')等))

上述所有的例子:

import matplotlib.pyplot as plt 
import numpy as np 

x = np.array([58, 0, 20, 2, 2, 0, 12, 17, 16, 6, 257, 0, 0, 0, 0, 1, 0, 13, 25, 
       9, 13, 94, 0, 0, 2, 42, 83, 0, 0, 157, 27, 1, 80, 0, 0, 0, 0, 2, 
       0, 41, 0, 4, 0, 10, 1, 4, 63, 6, 0, 31, 3, 5, 0, 61, 2, 0, 0, 0, 
       17, 52, 46, 15, 67, 20, 0, 0, 20, 39, 0, 31, 0, 0, 0, 0, 116, 0, 
       0, 0, 11, 39, 0, 17, 0, 59, 1, 0, 0, 2, 7, 0, 66, 14, 1, 19, 0, 
       101, 104, 228, 0, 31]) 

y = np.array([60, 0, 9, 1, 3, 0, 13, 9, 11, 7, 177, 0, 0, 0, 0, 1, 0, 12, 31, 
       10, 14, 80, 0, 0, 2, 30, 70, 0, 0, 202, 26, 1, 96, 0, 0, 0, 0, 1, 
       0, 43, 0, 6, 0, 9, 1, 3, 32, 6, 0, 20, 1, 2, 0, 52, 1, 0, 0, 0, 
       26, 37, 44, 13, 74, 15, 0, 0, 24, 36, 0, 22, 0, 0, 0, 0, 75, 0, 
       0, 0, 9, 40, 0, 14, 0, 51, 2, 0, 0, 1, 9, 0, 59, 9, 0, 23, 0, 80, 
       81, 158, 0, 27]) 
c = 0.01 

# Let's make the figure a bit bigger so the text doesn't run into itself... 
# (5x3 is rather small at 100dpi. Adjust the dpi if you really want a 5x3 plot) 
fig, axes = plt.subplots(ncols=3, figsize=(10, 6), 
         subplot_kw=dict(aspect=1, adjustable='box')) 

# Don't use scatter for this. Use plot. Scatter is if you want to vary things 
# like color or size by a third or fourth variable. 
for ax in axes: 
    ax.plot(x + c, y + c, 'bo') 

for ax in axes[1:]: 
    ax.set_xscale('log', basex=2) 
    ax.set_yscale('log', basey=2) 

axes[0].set_title('Unlogged') 
axes[1].set_title('Logged') 

axes[2].axis([2**-2, 2**20, 2**-2, 2**20]) 
axes[2].set_title('Logged with wrong xlim/ylim') 

plt.tight_layout() 
plt.show() 

enter image description here

如果你希望你的劇情概述要完全相同的大小和形狀,那麼最簡單的方法是將數字大小更改爲適當的比例,然後使用adjustable='datalim'

如果您想完全概括,只需手動添加子軸而不是使用子圖。

但是,如果您不介意調整圖形大小和/或使用subplots_adjust,那麼很容易做到,仍然使用子圖。

基本上,你會做這樣的事情

# For 3 columns and one row, we'd want a 3 to 1 ratio... 
fig, axes = plt.subplots(ncols=3, figsize=(9,3), 
         subplot_kw=dict(adjustable='datalim', aspect='equal') 

# By default, the width available to make subplots in is 5% smaller than the 
# height to make them in. This is easily changable... 
# ("right" is a percentage of the total width. It will be 0.95 regardless.) 
plt.subplots_adjust(right=0.95) 

再像以前一樣繼續。

對於完整的例子:

import matplotlib.pyplot as plt 
import numpy as np 

x = np.array([58, 0, 20, 2, 2, 0, 12, 17, 16, 6, 257, 0, 0, 0, 0, 1, 0, 13, 25, 
       9, 13, 94, 0, 0, 2, 42, 83, 0, 0, 157, 27, 1, 80, 0, 0, 0, 0, 2, 
       0, 41, 0, 4, 0, 10, 1, 4, 63, 6, 0, 31, 3, 5, 0, 61, 2, 0, 0, 0, 
       17, 52, 46, 15, 67, 20, 0, 0, 20, 39, 0, 31, 0, 0, 0, 0, 116, 0, 
       0, 0, 11, 39, 0, 17, 0, 59, 1, 0, 0, 2, 7, 0, 66, 14, 1, 19, 0, 
       101, 104, 228, 0, 31]) 

y = np.array([60, 0, 9, 1, 3, 0, 13, 9, 11, 7, 177, 0, 0, 0, 0, 1, 0, 12, 31, 
       10, 14, 80, 0, 0, 2, 30, 70, 0, 0, 202, 26, 1, 96, 0, 0, 0, 0, 1, 
       0, 43, 0, 6, 0, 9, 1, 3, 32, 6, 0, 20, 1, 2, 0, 52, 1, 0, 0, 0, 
       26, 37, 44, 13, 74, 15, 0, 0, 24, 36, 0, 22, 0, 0, 0, 0, 75, 0, 
       0, 0, 9, 40, 0, 14, 0, 51, 2, 0, 0, 1, 9, 0, 59, 9, 0, 23, 0, 80, 
       81, 158, 0, 27]) 
c = 0.01 

fig, axes = plt.subplots(ncols=3, figsize=(9, 3), 
         subplot_kw=dict(adjustable='datalim', aspect='equal')) 
plt.subplots_adjust(right=0.95) 

for ax in axes: 
    ax.plot(x + c, y + c, 'bo') 

for ax in axes[1:]: 
    ax.set_xscale('log', basex=2) 
    ax.set_yscale('log', basey=2) 

axes[0].set_title('Unlogged') 
axes[1].set_title('Logged') 

axes[2].axis([2**-2, 2**20, 2**-2, 2**20]) 
axes[2].set_title('Logged with wrong xlim/ylim') 

plt.tight_layout() 
plt.show() 

enter image description here

+0

感謝您的回覆,我很感激。還有一個跟進:如果我使用可調='box'和aspect ='equal',它仍然不會以相同方式使各個子圖平方。請參閱編輯回覆。 – user248237dfsf 2012-01-17 01:41:40

+0

如果你想要完全相等的方塊大綱(請注意,在這種情況下,圖塊本身_不能是方形的(即方塊= 1,在x和y方向上有相同的限制)),那麼有幾種不同的方法可以做到這一點。給我一點,我會添加另一個例子。 – 2012-01-17 01:48:17

+0

是的,爲了澄清,我不希望它們具有相同的座標軸值 - 只是兩個座標都是「正方形」,因爲對於每個座標圖,一個維度的x個單位等於另一個座標的x個單位,並且實際的平方是在所有相同的大小...謝謝 – user248237dfsf 2012-01-17 01:59:54

4

你混淆了什麼單位給予xlimylim。他們不應該被稱爲xlim(log10(min), log10(max))但只是xlim(min, max)。它們處理軸上的最低和最高值,單位爲xy

奇怪的顯示在我看來似乎是你觸發的一些錯誤,因爲你要求在對數刻度上不能顯示的負極小值(所有xlog(x)>0)。

+0

我接受xlim/ylim,雖然它很混亂。你對其他兩個問題有什麼想法嗎? – user248237dfsf 2012-01-17 01:26:10