matplotlib问题绘图记录的数据和设置其X/Y界限
我使用数图,在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,我得到一个类似于附加的图。
这里的轴标签没有意义:它从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')
这将产生下面的情节:从左至右
在第一个插曲,我们拥有未记录的原始数据。第二,我们已经记录了数值默认视图。第三,我们已经记录了指定了x/y lim的值。我的问题是:
为什么散点图的默认x/y边界是错误的?该手册说它应该使用数据中的最小值和最大值,但这显然不是这种情况。它挑选出隐藏绝大多数数据的值。
那为什么当我设定的界限我自己,在第三散点图从左至右,它颠倒了标签的顺序?在2^5之前显示2^8?这很混乱。
最后,我怎样才能得到它,这样的地块并不像压扁通过使用次要情节默认?我希望这些散点图是正方形的。
编辑:感谢乔和洪克的回复。如果我试图调整次要情节像这是方形:
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')
我得到下面的结果:
我怎样才能使每一个情节是方形的,相互协调的?它应该只是为方形的网格,所有大小相等......
编辑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')
感谢您的帮助。
@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()
如果你希望你的剧情概述要完全相同的大小和形状,那么最简单的方法是将数字大小更改为适当的比例,然后使用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()
感谢您的回复,我很感激。还有一个跟进:如果我使用可调='box'和aspect ='equal',它仍然不会以相同方式使各个子图平方。请参阅编辑回复。 – user248237dfsf 2012-01-17 01:41:40
如果你想要完全相等的方块大纲(请注意,在这种情况下,图块本身_不能是方形的(即方块= 1,在x和y方向上有相同的限制)),那么有几种不同的方法可以做到这一点。给我一点,我会添加另一个例子。 – 2012-01-17 01:48:17
是的,为了澄清,我不希望它们具有相同的坐标轴值 - 只是两个坐标都是“正方形”,因为对于每个坐标图,一个维度的x个单位等于另一个坐标的x个单位,并且实际的平方是在所有相同的大小...谢谢 – user248237dfsf 2012-01-17 01:59:54
你混淆了什么单位给予xlim
和ylim
。他们不应该被称为xlim(log10(min), log10(max))
但只是xlim(min, max)
。它们处理轴上的最低和最高值,单位为x
和y
。
奇怪的显示在我看来似乎是你触发的一些错误,因为你要求在对数刻度上不能显示的负极小值(所有x
的log(x)>0
)。
我接受xlim/ylim,虽然它很混乱。你对其他两个问题有什么想法吗? – user248237dfsf 2012-01-17 01:26:10
最奇怪的!我很想知道我自己。 – 2012-01-17 00:56:35