Python 如何使用imshow使用Matplotlib绘制具有非线性y轴的图像?

Python 如何使用imshow使用Matplotlib绘制具有非线性y轴的图像?,python,matplotlib,Python,Matplotlib,如何将2D阵列绘制为y比例相对于y值的二次幂的图像 例如,我数组的第一行在图像中的高度为1,第二行的高度为4,等等(单位无关) 用文字解释并不简单,请看这张图片(这就是我想要的结果): 如您所见,第一行比上一行小2倍,依此类推 对于那些对我为什么要这么做感兴趣的人: 我有一个相当大的浮点数组(1070000),表示声音文件的离散小波变换系数。我试图用这些系数绘制比例图。 我可以复制数组x次,直到获得所需的图像行大小,但内存无法容纳这么多信息…您可以查看。但这只会有助于轴的不均匀性——我不认为你

如何将2D阵列绘制为y比例相对于y值的二次幂的图像

例如,我数组的第一行在图像中的高度为1,第二行的高度为4,等等(单位无关) 用文字解释并不简单,请看这张图片(这就是我想要的结果):

如您所见,第一行比上一行小2倍,依此类推

对于那些对我为什么要这么做感兴趣的人:

我有一个相当大的浮点数组(1070000),表示声音文件的离散小波变换系数。我试图用这些系数绘制比例图。
我可以复制数组x次,直到获得所需的图像行大小,但内存无法容纳这么多信息…

您可以查看。但这只会有助于轴的不均匀性——我不认为你能够像你想的那样自适应地绘制(我认为图像中的每个点总是有相同的区域——因此你必须多次拥有更宽的行)。是否有任何理由需要绘制完整阵列?很明显,所有的细节都不会出现在任何绘图中,因此我建议对原始矩阵进行大量的降采样,这样您就可以根据需要复制行,从而在不耗尽内存的情况下获得图像

您是否尝试过变换轴?例如:

ax = subplot(111)
ax.yaxis.set_ticks([0, 2, 4, 8])
imshow(data)
ax = subplot(111)
ax.yaxis.set_ticks([16, 8, 4, 2, 1, 0])
axis([-0.5, 4.5, 31.5, 0.5])
imshow(b, interpolation="nearest")
这意味着对于不存在的坐标,数据中必须存在间隙,除非有办法提供转换函数,而不仅仅是列表(从未尝试过)

编辑

我承认这只是一个线索,不是一个完整的解决方案。以下是我更详细的意思

假设您的数据在一个数组中,
a
。您可以使用这样的变换:

class arr(object):
    @staticmethod
    def mylog2(x):
        lx = 0
        while x > 1:
            x >>= 1
            lx += 1
        return lx
    def __init__(self, array):
        self.array = array
    def __getitem__(self, index):
        return self.array[arr.mylog2(index+1)]
    def __len__(self):
        return 1 << len(self.array)
现在您可以显示它,例如:

ax = subplot(111)
ax.yaxis.set_ticks([0, 2, 4, 8])
imshow(data)
ax = subplot(111)
ax.yaxis.set_ticks([16, 8, 4, 2, 1, 0])
axis([-0.5, 4.5, 31.5, 0.5])
imshow(b, interpolation="nearest")
以下是一个示例(带有包含随机值的数组):


如果您希望两者都能缩放并节省内存,您可以“手动”绘制。Matplotlib允许您绘制矩形(它们将是您的“矩形像素”):

请注意,轴的范围不是通过add_patch()设置的,但您可以自己将其设置为所需的值(axes.set_xlim,…)


PS:在我看来,thrope的响应(matplotlib.image.ununiformimage)实际上可以做你想做的事情,方法比这里描述的“手动”方法更简单

我发现使用matplotlib制作比例图的最佳方法是使用
imshow
,类似于
specgram
的实现。使用矩形很慢,因为必须为每个值创建单独的图示符。类似地,您也不希望将内容烘焙到统一的NumPy数组中,因为您可能会很快耗尽内存,因为您的最高级别大约是信号的一半

下面是一个使用SciPy和的示例:

您可能还希望按级别自适应缩放值

这对我来说很有效。我唯一的问题是matplotlib在层之间创建了一个细细的空间。我还在想办法解决这个问题


另外,尽管这个问题现在已经很老了,我想我还是在这里回答,因为当我在寻找一种使用MPL创建比例图的方法时,这个页面出现在谷歌上。

是的,我想到了降采样,但有时我不得不放大最后的细节系数,精度损失往往太高。无论如何,我会研究非均匀图像,谢谢你给我的提示,我不知道。我认为这将适用于绘制原始海报所需的图像,并且这将比通过行复制“像素”更有效。但是,获取相应的轴记号仍然是一个悬而未决的问题。-1:选择y轴上出现的记号并不能解决原始问题。使用set_ticks(),y轴保持线性,imshow()仍线性绘制阵列。原始海报需要“可变大小,矩形像素”。这就是为什么我说数据必须进行调整,对于轴本身来说仍然值得一提。@EOL:。。。现在有了正确的情节。我理解你的意思,但有时把东西拼凑起来确实有帮助;-)+1:很有意思,所有的作品都有!:)我想指出的是,此解决方案使Matplotlib绘制大量的小“像素”(比原始数组中的点的数量多得多),其中as thrope的绘制仅与数组中的点一样多的“像素”。我很想看看计时测试!:)是的,愚弄Matplotlib有点像黑客,我宁愿它是本地的(也许是,只是隐藏得很好…)。在任何情况下,都会有更多的访问阵列,正如您正确地说的那样,它不会是最优的。如果速度太慢,而thrope的解决方案最终被证明是固定大小的,那么您的想法可能就是解决方案。+1作为一个有效的替代方案,即使看起来需要更多的工作,它也会加快渲染速度(如其他解决方案中所述)。@RedGlyph谢谢!我猜thrope的解决方案确实绘制了这样的矩形(使用
nearest
neighbor选项),但直接通过Matplotlib绘制。
from pylab import *
import pywt
import scipy.io.wavfile as wavfile

# Find the highest power of two less than or equal to the input.
def lepow2(x):
    return 2 ** floor(log2(x))

# Make a scalogram given an MRA tree.
def scalogram(data):
    bottom = 0

    vmin = min(map(lambda x: min(abs(x)), data))
    vmax = max(map(lambda x: max(abs(x)), data))

    gca().set_autoscale_on(False)

    for row in range(0, len(data)):
        scale = 2.0 ** (row - len(data))

        imshow(
            array([abs(data[row])]),
            interpolation = 'nearest',
            vmin = vmin,
            vmax = vmax,
            extent = [0, 1, bottom, bottom + scale])

        bottom += scale

# Load the signal, take the first channel, limit length to a power of 2 for simplicity.
rate, signal = wavfile.read('kitten.wav')
signal = signal[0:lepow2(len(signal)),0]
tree = pywt.wavedec(signal, 'db5')

# Plotting.
gray()
scalogram(tree)
show()