2012-12-22 16 views
7

avete idea, come posso bin 3 matrici per un istogramma. Le mie matrici sembranoIstogrammi di dispersione 2D e 3D da array in Python

Temperature = [4, 3, 1, 4, 6, 7, 8, 3, 1] 
Radius  = [0, 2, 3, 4, 0, 1, 2, 10, 7] 
Density  = [1, 10, 2, 24, 7, 10, 21, 102, 203] 

E la trama 1D dovrebbe guardare:

Density 

    |   X 
10^2-|    X 
    |  X 
10^1-| 
    | X 
10^0-| 
    |___|___|___|___|___ Radius 
     0 3.3 6.6 10 

E la trama 2D dovrebbero (qualitativa) simile:

Density 

    |   2  | | 
10^2-|  11249  | | 
    |  233   | | Radius 
10^1-| 12   | | 
    | 1    | | 
10^0-| 
    |___|___|___|___|___ Temperature 
     0 3 5 8 

Quindi voglio bin uno o due campi con python/numpy e poi tracciarli per analizzare la loro corrispondenza.

+0

Consiglio vivamente il pacchetto matplotlib - usando che si * * puoi scrivere il tuo codice per tracciare entrambi quegli istogrammi - (http://matplotlib.org/examples/axes_grid/scatter_hist.html) – danodonovan

risposta

11

Segue due funzioni: hist2d_bubble e hist3d_bubble; che può andare bene per il vostro scopo:

enter image description here

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


def hist2d_bubble(x_data, y_data, bins=10): 
    ax = np.histogram2d(x_data, y_data, bins=bins) 
    xs = ax[1] 
    ys = ax[2] 
    points = [] 
    for (i, j), v in np.ndenumerate(ax[0]): 
     points.append((xs[i], ys[j], v)) 

    points = np.array(points) 
    fig = pyplot.figure() 
    sub = pyplot.scatter(points[:, 0],points[:, 1], 
         color='black', marker='o', s=128*points[:, 2]) 
    sub.axes.set_xticks(xs) 
    sub.axes.set_yticks(ys) 
    pyplot.ion() 
    pyplot.grid() 
    pyplot.show() 
    return points, sub 


def hist3d_bubble(x_data, y_data, z_data, bins=10): 
    ax1 = np.histogram2d(x_data, y_data, bins=bins) 
    ax2 = np.histogram2d(x_data, z_data, bins=bins) 
    ax3 = np.histogram2d(z_data, y_data, bins=bins) 
    xs, ys, zs = ax1[1], ax1[2], ax3[1] 
    smart = np.zeros((bins, bins, bins),dtype=int) 
    for (i1, j1), v1 in np.ndenumerate(ax1[0]): 
     if v1 == 0: 
      continue 
     for k2, v2 in enumerate(ax2[0][i1]): 
      v3 = ax3[0][k2][j1] 
      if v1 == 0 or v2 == 0 or v3 == 0: 
       continue 
      num = min(v1, v2, v3) 
      smart[i1, j1, k2] += num 
      v1 -= num 
      v2 -= num 
      v3 -= num 
    points = [] 
    for (i, j, k), v in np.ndenumerate(smart): 
     points.append((xs[i], ys[j], zs[k], v)) 
    points = np.array(points) 
    fig = pyplot.figure() 
    sub = fig.add_subplot(111, projection='3d') 
    sub.scatter(points[:, 0], points[:, 1], points[:, 2], 
       color='black', marker='o', s=128*points[:, 3]) 
    sub.axes.set_xticks(xs) 
    sub.axes.set_yticks(ys) 
    sub.axes.set_zticks(zs) 
    pyplot.ion() 
    pyplot.grid() 
    pyplot.show() 
    return points, sub 

Le due figure sopra sono stati creati utilizzando:

temperature = [4, 3, 1, 4, 6, 7, 8, 3, 1] 
radius  = [0, 2, 3, 4, 0, 1, 2, 10, 7] 
density  = [1, 10, 2, 24, 7, 10, 21, 102, 203] 
import matplotlib 
matplotlib.rcParams.update({'font.size':14}) 

points, sub = hist2d_bubble(radius, density, bins=4) 
sub.axes.set_xlabel('radius') 
sub.axes.set_ylabel('density') 

points, sub = hist3d_bubble(temperature, density, radius, bins=4) 
sub.axes.set_xlabel('temperature') 
sub.axes.set_ylabel('density') 
sub.axes.set_zlabel('radius') 

correlati:

Howto bin series of float values into histogram in Python?

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

2D histogram with Python

+0

@tcaswell Vedo il tuo punto! Ho aggiornato la risposta mantenendo solo la trama della bolla! –

+2

Grazie. Ho ritirato il mio -1 e cancellato i miei commenti ora non applicabili. C'è una linea un po 'sottile di ciò che è la manipolazione dei dati accettabile e ciò che non lo è. Se tu avessi un metodo _systematic_ di spostarli (diciamo che sai che dovresti solo ottenere i dati interi e li rimodelli in una spirale) sarebbe ok, ma l'aggiunta di shift _random_ non lo è. L'uso delle scale di log è ok, non è una trasformazione arbitraria sui propri assi. Fondamentalmente, dovrebbe essere invertibile e convenzionale. – tacaswell

1

ecco una versione 2D di Castro sopra le ossa. Semplicemente traccia il valore medio a ciascuna coordinata x, y. Questo potrebbe essere tracciato usando imshow ma l'approccio di Castro rende la trama molto più ordinata.

from matplotlib import pyplot as plt 
import numpy as np 

# make some x,y points and z data that needs to be averaged and plotted 
x = [1,1,1,2,2,2,2,3,4,4,4,4] 
y = [1,1,1,2,2,2,2,3,4,4,4,4] 
z = [1,1,1,2,2,3,3,4,4,4,5,5] 
xbins, ybins = int(max(x)), int(max(y)) 
rng = [[1, xbins+1], [1, ybins+1]] 
bins = [xbins,ybins] 

# get the sum of weights and sum of occurrences (their division gives the mean) 
H, xs, ys =np.histogram2d(x, y, weights=z, bins=bins, range=rng) 
count, _, _ =np.histogram2d(x, y, bins=bins, range=rng) 

# get the mean value of each x,y point 
count = np.ma.masked_where(count==0,count) 
H = np.ma.masked_where(H==0,H) 
H/=count 

# separate the H matrix into x,y,z arrays (and discard zero values) 
points = [] 
for (i, j),v in np.ndenumerate(H): 
    if v: points.append((xs[i], ys[j], v)) 
points = np.array(points) 

# plot the data 
fig = plt.figure() 
cm = plt.cm.get_cmap('hot') 
p = plt.scatter(points[:, 0], points[:, 1], c=points[:, 2], cmap=cm) 
plt.colorbar(p).set_label('avg. z value') 
plt.grid() 
plt.show() 

Tutte le x duplicati, i punti y sono ora ridotti a un insieme unico e le loro valori z sono state in media:

averaged z value of duplicated x,y coordinates