Conseguir las coordenadas de los contenedores con hexbin en matplotlib.

Uso el método hexbin de hexbin para calcular los histogtwigs 2d de mis datos. Pero me gustaría obtener las coordenadas de los centros de los hexágonos para seguir procesando los resultados.

get_array() los valores utilizando el método get_array() en el resultado, pero no puedo averiguar cómo obtener las coordenadas de los contenedores.

Traté de calcularlos dado el número de contenedores y la extensión de mis datos, pero no sé el número exacto de contenedores en cada dirección. gridsize=(10,2) debería hacer el truco pero no parece funcionar.

¿Alguna idea?

Creo que esto funciona.

 from __future__ import division import numpy as np import math import matplotlib.pyplot as plt def generate_data(n): """Make random, correlated x & y arrays""" points = np.random.multivariate_normal(mean=(0,0), cov=[[0.4,9],[9,10]],size=int(n)) return points if __name__ =='__main__': color_map = plt.cm.Spectral_r n = 1e4 points = generate_data(n) xbnds = np.array([-20.0,20.0]) ybnds = np.array([-20.0,20.0]) extent = [xbnds[0],xbnds[1],ybnds[0],ybnds[1]] fig=plt.figure(figsize=(10,9)) ax = fig.add_subplot(111) x, y = points.T # Set gridsize just to make them visually large image = plt.hexbin(x,y,cmap=color_map,gridsize=20,extent=extent,mincnt=1,bins='log') # Note that mincnt=1 adds 1 to each count counts = image.get_array() ncnts = np.count_nonzero(np.power(10,counts)) verts = image.get_offsets() for offc in xrange(verts.shape[0]): binx,biny = verts[offc][0],verts[offc][1] if counts[offc]: plt.plot(binx,biny,'k.',zorder=100) ax.set_xlim(xbnds) ax.set_ylim(ybnds) plt.grid(True) cb = plt.colorbar(image,spacing='uniform',extend='max') plt.show() 

introduzca la descripción de la imagen aquí

Me encantaría confirmar que el código de Hooked utilizando get_offsets () funciona, pero probé varias iteraciones del código mencionado anteriormente para recuperar las posiciones centrales y, como mencionó Dave, get_offsets () permanece vacío. La solución que encontré es usar la opción ‘image.get_paths ()’ no vacía. Mi código toma el medio para encontrar centros, pero lo que significa que es solo un poco más, pero funciona.

La opción get_paths () devuelve un conjunto de coordenadas x, y incrustadas que se pueden repartir y luego promediar para devolver la posición central para cada hexagtwig.

El código que tengo es el siguiente:

 counts=image.get_array() #counts in each hexagon, works great verts=image.get_offsets() #empty, don't use this b=image.get_paths() #this does work, gives Path([[]][]) which can be plotted for x in xrange(len(b)): xav=np.mean(b[x].vertices[0:6,0]) #center in x (RA) yav=np.mean(b[x].vertices[0:6,1]) #center in y (DEC) plt.plot(xav,yav,'k.',zorder=100) 

Yo tuve el mísmo problema. Creo que lo que se necesita desarrollar es un marco para tener un objeto HexagonalGrid que luego pueda aplicarse a muchos conjuntos de datos diferentes (y sería increíble hacerlo para N dimensiones). Esto es posible y me sorprende que ni Scipy ni Numpy tengan nada para él (además, parece que no hay nada igual, excepto tal vez binify )

Dicho esto, asumo que desea utilizar el hexbinning para comparar varios conjuntos de datos agrupados. Esto requiere alguna base común. Conseguí que esto funcionara usando el hexbin de matplotlib de la siguiente manera:

 import numpy as np import matplotlib.pyplot as plt def get_data (mean,cov,n=1e3): """ Quick fake data builder """ np.random.seed(101) points = np.random.multivariate_normal(mean=mean,cov=cov,size=int(n)) x, y = points.T return x,y def get_centers (hexbin_output): """ about 40% faster than previous post only cause you're not calculating the min/max every time """ paths = hexbin_output.get_paths() v = paths[0].vertices[:-1] # adds a value [0,0] to the end vx,vy = vT idx = [3,0,5,2] # index for [xmin,xmax,ymin,ymax] xmin,xmax,ymin,ymax = vx[idx[0]],vx[idx[1]],vy[idx[2]],vy[idx[3]] half_width_x = abs(xmax-xmin)/2.0 half_width_y = abs(ymax-ymin)/2.0 centers = [] for i in xrange(len(paths)): cx = paths[i].vertices[idx[0],0]+half_width_x cy = paths[i].vertices[idx[2],1]+half_width_y centers.append((cx,cy)) return np.asarray(centers) # important parts ==> class Hexagonal2DGrid (object): """ Used to fix the gridsize, extent, and bins """ def __init__ (self,gridsize,extent,bins=None): self.gridsize = gridsize self.extent = extent self.bins = bins def hexbin (x,y,hexgrid): """ To hexagonally bin the data in 2 dimensions """ fig = plt.figure() ax = fig.add_subplot(111) # Note mincnt=0 so that it will return a value for every point in the # hexgrid, not just those with count>mincnt # Basically you fix the gridsize, extent, and bins to keep them the same # then the resulting count array is the same hexbin = plt.hexbin(x,y, mincnt=0, gridsize=hexgrid.gridsize, extent=hexgrid.extent, bins=hexgrid.bins) # you could close the figure if you don't want it # plt.close(fig.number) counts = hexbin.get_array().copy() return counts, hexbin # Example ===> if __name__ == "__main__": hexgrid = Hexagonal2DGrid((21,5),[-70,70,-20,20]) x_data,y_data = get_data((0,0),[[-40,95],[90,10]]) x_model,y_model = get_data((0,10),[[100,30],[3,30]]) counts_data, hexbin_data = hexbin(x_data,y_data,hexgrid) counts_model, hexbin_model = hexbin(x_model,y_model,hexgrid) # if you want the centers, they will be the same for both centers = get_centers(hexbin_data) # if you want to ignore the cells with zeros then use the following mask. # But if want zeros for some bins and not others I'm not sure an elegant way # to do this without using the centers nonzero = counts_data != 0 # now you can compare the two data sets variance_data = counts_data[nonzero] square_diffs = (counts_data[nonzero]-counts_model[nonzero])**2 chi2 = np.sum(square_diffs/variance_data) print(" chi2={}".format(chi2))