Построить гистограмму 3D-бара с питоном - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть некоторые данные x и y, с помощью которых я хотел бы сгенерировать трехмерную гистограмму с цветным градиентом (bwr или что-то еще).

Я написал скрипт, который отображает интересные значения в интервале от -2 до 2 для абсцессов x и y:

import numpy as np
import numpy.random
import matplotlib.pyplot as plt

# To generate some test data
x = np.random.randn(500)
y = np.random.randn(500)

XY = np.stack((x,y),axis=-1)

def selection(XY, limitXY=[[-2,+2],[-2,+2]]):
        XY_select = []
        for elt in XY:
            if elt[0] > limitXY[0][0] and elt[0] < limitXY[0][1] and elt[1] > limitXY[1][0] and elt[1] < limitXY[1][1]:
                XY_select.append(elt)

        return np.array(XY_select)

XY_select = selection(XY, limitXY=[[-2,+2],[-2,+2]])

heatmap, xedges, yedges = np.histogram2d(XY_select[:,0], XY_select[:,1], bins = 7, range = [[-2,2],[-2,2]])
extent = [xedges[0], xedges[-1], yedges[0], yedges[-1]]


plt.figure("Histogram")
#plt.clf()
plt.imshow(heatmap.T, extent=extent, origin='lower')
plt.show()

И даю правильный результат:

enter image description here

Теперь я хотел бы превратить это в трехмерную гистограмму.К сожалению, мне не удается правильно построить его с помощью bar3d, потому что по умолчанию он принимает длину x и y для абсциссы.

Я совершенно уверен, что есть очень простой способ построить это в 3D с помощью imshow.Как неизвестный вариант ...

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

Я наконец преуспел в этом. Я почти уверен, что есть лучший способ сделать это, но по крайней мере это работает:

import numpy as np
import numpy.random
import matplotlib.pyplot as plt

# To generate some test data
x = np.random.randn(500)
y = np.random.randn(500)

XY = np.stack((x,y),axis=-1)

def selection(XY, limitXY=[[-2,+2],[-2,+2]]):
        XY_select = []
        for elt in XY:
            if elt[0] > limitXY[0][0] and elt[0] < limitXY[0][1] and elt[1] > limitXY[1][0] and elt[1] < limitXY[1][1]:
                XY_select.append(elt)

        return np.array(XY_select)

XY_select = selection(XY, limitXY=[[-2,+2],[-2,+2]])


xAmplitudes = np.array(XY_select)[:,0]#your data here
yAmplitudes = np.array(XY_select)[:,1]#your other data here


fig = plt.figure() #create a canvas, tell matplotlib it's 3d
ax = fig.add_subplot(111, projection='3d')


hist, xedges, yedges = np.histogram2d(x, y, bins=(7,7), range = [[-2,+2],[-2,+2]]) # you can change your bins, and the range on which to take data
# hist is a 7X7 matrix, with the populations for each of the subspace parts.
xpos, ypos = np.meshgrid(xedges[:-1]+xedges[1:], yedges[:-1]+yedges[1:]) -(xedges[1]-xedges[0])


xpos = xpos.flatten()*1./2
ypos = ypos.flatten()*1./2
zpos = np.zeros_like (xpos)

dx = xedges [1] - xedges [0]
dy = yedges [1] - yedges [0]
dz = hist.flatten()

cmap = cm.get_cmap('jet') # Get desired colormap - you can change this!
max_height = np.max(dz)   # get range of colorbars so we can normalize
min_height = np.min(dz)
# scale each z to [0,1], and get their rgb values
rgba = [cmap((k-min_height)/max_height) for k in dz] 

ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color=rgba, zsort='average')
plt.title("X vs. Y Amplitudes for ____ Data")
plt.xlabel("My X data source")
plt.ylabel("My Y data source")
plt.savefig("Your_title_goes_here")
plt.show()

Я использую этот пример , но я изменил его, потому что он ввел смещение. Результат таков:

enter image description here

0 голосов
/ 18 сентября 2018

Вы можете получить тот же результат, используя что-то простое:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-2, 2, 7)
y = np.linspace(-2, 2, 7)

xx, yy = np.meshgrid(x, y)

z = xx*0+yy*0+ np.random.random(size=[7,7])

plt.imshow(z, interpolation='nearest', cmap=plt.cm.viridis, extent=[-2,2,2,2])
plt.show()

from mpl_toolkits.mplot3d import Axes3D
ax = Axes3D(plt.figure())

ax.plot_surface(xx, yy, z, cmap=plt.cm.viridis, cstride=1, rstride=1)
plt.show()

Результаты приведены ниже: enter image description here

Surface plot

...