使用matplotlib绘制对数2D直方图
这是我写的第一个Python程序,所以可能会有一些“奇怪”的地方。这个程序会从指定文件夹里读取3列数据,然后为每个文件计算直方图,最后把结果放到一个二维矩阵里,目的是为了创建一个类似于2D直方图的东西。
我遇到的困难是在我的第三个图表中,我希望y轴的数据使用对数刻度,并且数据能够按照这个刻度来展示。此外,我还想把输入数据中的“零”值去掉。我尝试使用numpy.where(matrix)
来实现这个功能,但我不确定这样做是否真的能达到我的目的……
这是我的代码:
#!/usr/bin/python
# Filename: untitled.py
# encoding: utf-8
from __future__ import division
from matplotlib.colors import LogNorm
import matplotlib
import numpy as np
import matplotlib.pylab as plt
import os
import matplotlib.cm as cm
def main():
dataFiles = [filename for filename in os.listdir(".") if (filename[-4:]==".log" and filename[0]!='.')]
dataFiles.sort()
p = []
matrix1 = []
matrix2 = []
matrix3 = []
for dataFile in dataFiles:
p += [ eval(dataFile[11:16]) ]
data = np.loadtxt(dataFile, skiprows=7)[:,1:4]
matrix1 += [ data[:,0] ]
matrix2 += [ data[:,1] ]
matrix3 += [ data[:,2] ]
matrixList = [matrix1, matrix2, matrix3]
#make histograms out of the matrices
matrix1Hist = [ np.histogram( matrixColumn, bins=30, range=(np.min(np.where(matrix1 != 0)), np.max(matrix1)))[0] for matrixColumn in matrix1 ]
matrix2Hist = [ np.histogram( matrixColumn, bins=200, range=(np.min(np.where(matrix2 != 0)), np.max(matrix2)))[0] for matrixColumn in matrix2 ]
matrix3Hist = [ np.histogram( matrixColumn, bins=50, range=(np.min(np.where(matrix3 != 0)), np.max(matrix3)))[0] for matrixColumn in matrix3 ]
# convert the matrixHistogramsto numpy arrays and swap axes
matrix1Hist = np.array(matrix1Hist).transpose()
matrix2Hist = np.array(matrix2Hist).transpose()
matrix3Hist = np.array(matrix3Hist).transpose()
matrixHistList = [matrix1Hist, matrix2Hist, matrix3Hist]
fig = plt.figure(0)
fig.clf()
for i,matrixHist in enumerate( [matrix1Hist, matrix2Hist, matrix3Hist] ):
ax = fig.add_subplot(2, 2, i+1)
ax.grid(True)
ax.set_title('matrix'+str(i+1))
if i < 2:
result = ax.imshow(matrixHist,
cmap=cm.gist_yarg,
origin='lower',
aspect='auto', #automatically span matrix to available space
interpolation='hanning',
extent= [ p[0], p[-1], np.floor( np.min( matrixList[i])), np.ceil( np.max( matrixList[i])) ] ,
)
elif i == 2:
result = ax.imshow(matrixHist,
cmap=cm.gist_yarg,
origin='lower',
aspect='auto', #automatically span matrix to available space
interpolation='hanning',
extent= [ p[0], p[-1], 1, np.log10(np.max( matrixList[i])) ] ,
)
ticks_at = [ 0 , abs(matrixHist).max()]
fig.colorbar(result, ticks=ticks_at,format='%1.2g')
plt.show()
if __name__ == '__main__':
main()
1 个回答
4
关于你问题的第一部分,你可以选择以下几种方法:
- 在绘图之前,先对结果使用
np.log(my_array)
。 - 通过查看这个之前的问题来调整坐标轴的比例:在Python中使用matplotlib绘制对数坐标轴。
- 在像
pcolor
和imshow
这样的二维颜色图中,通过使用 matplotlib.colors.LogNorm 实例,并通过norm
关键字来调整比例。比如:imshow(my_array, cmap=mpl.cm.jet, norm=mpl.colors.LogNorm)
关于你问题的第二部分 - 如何从数组中过滤掉零值 - 你可以试试:
my_array = my_array[my_array != 0]
my_array != 0
这段代码会创建一个由 True
和 False
组成的逻辑数组,然后用这个数组来进行切片。不过,这样会返回一个一维数组,可能不是你想要的。如果你想把这些值改成其他的(并保持二维的形状),可以使用下面的代码(这里的值被设置为 NaN
)……
my_array[my_array != 0] = np.NaN