2012-10-18 16 views
9

Używam metody matplotlib: hexbin do obliczania histogramów 2d na moich danych. Ale chciałbym uzyskać współrzędne centrów sześciokąta w celu dalszego przetwarzania wyników.pobierz współrzędne kosza z heksabinem w matplotlib

Otrzymałem wartości przy użyciu metody get_array() na wynik, ale nie mogę dowiedzieć się, jak uzyskać współrzędne kosze.

Próbowałem je obliczyć podając liczbę pojemników i zakres moich danych, ale nie znam dokładnej liczby pojemników w każdym kierunku. gridsize=(10,2) powinien załatwić sprawę, ale wygląda na to, że nie działa.

Każdy pomysł?

+0

Mogę się mylić, ale wydaje się, że nie ma sposobu na uzyskanie współrzędnych. Na szczęście wszystko to jest open source (szukaj 'hexbin' w tym pliku: https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/axes.py), abyś mógł sprawdzić, jak siatka jest obliczana i powiel go w swoim kodzie. Powodzenia! – Tobold

+0

Cześć, dziękuję Tobold, sprawdzę kod źródłowy, o którym wspomniałeś. – user1151446

Odpowiedz

16

Myślę, że to działa.

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() 

enter image description here

+1

Czy możesz podać numer wersji modułów uruchamianych tym kodem? Nie można uzyskać żadnych danych z get_offsets(): W [1]: Verts = image.get_offsets() w [2]: wierzchołków Z [2]: Tablica ([] = float64 dtype) To działa matplotlib 1.0.1, numpy 1.5.1 – Dave

+1

Mogłem edytować Twoje pytanie, aby dołączyć do niego wygenerowany obraz. Świetna odpowiedź! – Hooked

2

chciałbym, aby potwierdzić, że kod przez Hooked użyciu get_offsets() działa, ale próbowałem kilka iteracji kodu wspomniano powyżej, aby pobrać pozycje środkowe i, jak wspomniano Dave, get_offsets () pozostaje pusta. Obejściem, które znalazłem, jest użycie niepustej opcji "image.get_paths()". Mój kod ma sens, aby znaleźć centra, ale oznacza to, że jest to po prostu dłuższy kawałek, ale działa.

Opcja get_paths() zwraca zestaw wbudowanych współrzędnych x, y, które można zapętlić, a następnie uśrednić, aby zwrócić położenie środkowe każdego heksagramu.

Kod, który mam jest następujący:

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) 
0

miałem ten sam problem. Myślę, że to, co należy opracować, to framework, który ma obiekt HexagonalGrid, który można następnie zastosować do wielu różnych zestawów danych (i byłoby wspaniale zrobić to dla N wymiarów). Jest to możliwe i zaskakuje mnie to, że ani Scipy, ani Numpy nie mają dla niego nic (poza tym chyba nie ma nic podobnego poza, chyba, że ​​binify)

To powiedziawszy, zakładam, że chcesz użyć hexboksu do porównania wielu zestawów danych . Wymaga to wspólnej bazy. Mam to do pracy przy użyciu hexbin matplotlib w następujący sposób:

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 = v.T 

    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))