Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly generate a 3d histogram using numpy or matplotlib built in functions in python?

This is more of a general question about 3d histogram creation in python.

I have attempted to create a 3d histogram using the X and Y arrays in the following code

import matplotlib
import pylab
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib import cm

def threedhist():
    X = [1, 3, 5, 8, 6, 7, 1, 2, 4, 5]
    Y = [3, 4, 3, 6, 5, 3, 1, 2, 3, 8]
    fig = pylab.figure()
    ax = Axes3D(fig)
    ax.hist([X, Y], bins=10, range=[[0, 10], [0, 10]])
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.zlabel('Frequency')
    plt.title('Histogram')
    plt.show()

However, I am getting the following error

Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    a3dhistogram()
  File "C:/Users/ckiser/Desktop/Projects/Tom/Python Files/threedhistogram.py", line 24, in a3dhistogram
    ax.hist([X, Y], bins=10, range=[[0, 10], [0, 10]])
  File "C:\Python27\lib\site-packages\matplotlib\axes.py", line 7668, in hist
    m, bins = np.histogram(x[i], bins, weights=w[i], **hist_kwargs)
  File "C:\Python27\lib\site-packages\numpy\lib\function_base.py", line 169, in histogram
    mn, mx = [mi+0.0 for mi in range]
TypeError: can only concatenate list (not "float") to list

I have tried the code with and without the "[" in the line ax.hist([X, Y], bins=10, range=[[0, 10], [0, 10]]) I have also tried the function from numpy without success H, xedges, yedges = np.histogram2d(x, y, bins = (10, 10)) Am I missing a step or a parameter? Any advice would be greatly appreciated.

like image 767
Chris Avatar asked Dec 08 '11 21:12

Chris


People also ask

How do you make a 3D histogram in Python?

Create a new figure or activate an existing figure using figure() method. Add an axes to the cureent figure as a subplot arrangement. Create x3, y3 and z3 data points using numpy. Create dx, dy and dz data points using numpy.

How will you make a histogram using Matplotlib in Python?

In Matplotlib, we use the hist() function to create histograms. The hist() function will use an array of numbers to create a histogram, the array is sent into the function as an argument.

How do you plot a histogram using NumPy in Python?

Creating Numpy HistogramNumpy has a built-in numpy. histogram() function which represents the frequency of data distribution in the graphical form. The rectangles having equal horizontal size corresponds to class interval called bin and variable height corresponding to the frequency.


2 Answers

I posted this in a related thread about colored 3d bar plots, but I think it's also relevant here as I couldn't find a complete answer for what I needed in either thread. This code generates a histogram scatterplot for any sort of x-y data. The height represents the frequency of values in that bin. So, for example, if you had many data point where (x,y) = (20,20) it would be high and red. If you had few data points in the bin where (x,y) = (100,100) it would be low and blue.

Note: result will vary substantially depending on how much data you have and how many bins your choose for you histogram. Adjust accordingly!

xAmplitudes = #your data here
yAmplitudes = #your other data here

x = np.array(xAmplitudes)   #turn x,y data into numpy arrays
y = np.array(yAmplitudes)

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

#make histogram stuff - set bins - I choose 20x20 because I have a lot of data
hist, xedges, yedges = np.histogram2d(x, y, bins=(20,20))
xpos, ypos = np.meshgrid(xedges[:-1]+xedges[1:], yedges[:-1]+yedges[1:])

xpos = xpos.flatten()/2.
ypos = ypos.flatten()/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()

The results for about 75k data points of mine are below. Note, you can drag and drop to different perspectives and may want to save multiple views for presentations, posterity.

3d histogram side view 3d histogram perspective 2

like image 161
Ryan Dorrill Avatar answered Sep 18 '22 17:09

Ryan Dorrill


Have a look at https://matplotlib.org/stable/gallery/mplot3d/hist3d.html, this has a working example script.

I've improved the code at that link to be more of a histogram:

from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = [1, 3, 5, 8, 6, 7, 1, 2, 4, 5]
y = [3, 4, 3, 6, 5, 3, 1, 2, 3, 8]

hist, xedges, yedges = np.histogram2d(x, y, bins=(4,4))
xpos, ypos = np.meshgrid(xedges[:-1]+xedges[1:], yedges[:-1]+yedges[1:])

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

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

ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color='b', zsort='average')
plt.xlabel ("X")
plt.ylabel ("Y")

plt.show()

I'm not sure how to do it with Axes3D.hist ().

like image 42
lxop Avatar answered Sep 16 '22 17:09

lxop