2012-10-18 32 views
9

Tôi sử dụng phương pháp matplotlib hexbin để tính toán biểu đồ 2d trên dữ liệu của tôi. Nhưng tôi muốn lấy tọa độ của các trung tâm của hình lục giác để tiếp tục xử lý các kết quả.lấy tọa độ thùng với hexbin trong matplotlib

Tôi nhận được các giá trị sử dụng phương pháp get_array() trên kết quả, nhưng tôi không thể tìm ra cách để có được tọa độ thùng.

Tôi đã cố gắng tính toán số lượng thùng và mức độ dữ liệu của tôi nhưng tôi không biết chính xác số lượng thùng trong mỗi hướng. gridsize=(10,2) nên làm các trick nhưng nó dường như không hoạt động.

Bất kỳ ý tưởng nào?

+0

Tôi có thể sai nhưng dường như không có cách nào để nhận tọa độ. May mắn đó là tất cả nguồn mở (tìm kiếm 'hexbin' trong tệp này: https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/axes.py) để bạn có thể kiểm tra cách tính lưới và sao chép nó trong mã của bạn. Chúc may mắn! – Tobold

+0

Xin chào, Cảm ơn Tobold, tôi sẽ kiểm tra mã nguồn bạn đề cập đến. – user1151446

Trả lời

16

Tôi nghĩ rằng công trình này hoạt động.

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

Bạn có thể cung cấp số phiên bản cho các mô-đun chạy với mã này không? Tôi không nhận được bất kỳ dữ liệu từ get_offsets(): Trong [1]: Verts = image.get_offsets() Trong [2]: Verts Out [2]: mảng ([], dtype = float64) Điều này đang chạy matplotlib 1.0.1, numpy 1.5.1 – Dave

+1

Tôi đã tự do chỉnh sửa câu hỏi của bạn để bao gồm hình ảnh mà nó tạo ra. Câu trả lời chính xác! – Hooked

2

Tôi rất thích để xác nhận rằng mã bởi Hooked sử dụng get_offsets() hoạt động, nhưng tôi đã cố gắng nhiều lần lặp của mã nêu trên để lấy vị trí trung tâm và, như Dave đã đề cập, get_offsets () vẫn trống. Cách giải quyết mà tôi tìm thấy là sử dụng tùy chọn 'image.get_paths()' không trống. Mã của tôi lấy trung bình để tìm các trung tâm nhưng điều đó có nghĩa là nó chỉ dài hơn một chút, nhưng nó hoạt động.

Tùy chọn get_paths() trả về một tập hợp các toạ độ x, y được nhúng có thể được lặp lại và sau đó lấy trung bình để trả về vị trí trung tâm cho mỗi quẻ.

Mã mà tôi có là như sau:

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

Tôi có vấn đề này như vậy. Tôi nghĩ rằng những gì cần phải được phát triển là một khuôn khổ để có một đối tượng HexagonalGrid mà sau đó có thể được áp dụng cho nhiều bộ dữ liệu khác nhau (và nó sẽ là tuyệt vời để làm điều đó cho N kích thước). Điều này là có thể và nó làm tôi ngạc nhiên rằng cả Scipy hay Numpy đều có bất cứ điều gì cho nó (hơn nữa có vẻ như không có gì khác giống như nó ngoại trừ có lẽ là binify)

Điều đó nói rằng, tôi giả sử bạn muốn sử dụng hexbinning để so sánh nhiều bộ dữ liệu được băm . Điều này đòi hỏi một số cơ sở chung. Tôi đã làm việc này bằng cách sử dụng hexbin của matplotlib theo cách sau:

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)) 
Các vấn đề liên quan