2012-10-12 28 views
10

Tôi muốn tạo danh sách các điểm tương ứng với lưới. Vì vậy, nếu tôi muốn tạo một mạng lưới của khu vực từ (0,0) đến (1,1), nó sẽ chứa các điểm (0,0), (0,1), (1,0), (1, 0).Điểm meshgrid một nửa

Tôi biết rằng điều này có thể được thực hiện với đoạn mã sau:

g = np.meshgrid([0,1],[0,1]) 
np.append(g[0].reshape(-1,1),g[1].reshape(-1,1),axis=1) 

yielding kết quả:

array([[0, 0], 
     [1, 0], 
     [0, 1], 
     [1, 1]]) 

Câu hỏi của tôi là hai khía cạnh:

  1. Có một tốt hơn cách làm điều này?
  2. Có cách nào để khái quát hóa điều này với kích thước cao hơn không?

Trả lời

24

Tôi chỉ nhận thấy rằng các tài liệu trong NumPy cung cấp một cách nhanh hơn để làm điều này:

X, Y = np.mgrid[xmin:xmax:100j, ymin:ymax:100j] 
positions = np.vstack([X.ravel(), Y.ravel()]) 

này một cách dễ dàng có thể được khái quát hóa để hơn kích thước bằng cách sử dụng chức năng meshgrid2 liên kết và lập bản đồ 'Ravel' cho lưới điện dẫn .

g = meshgrid2(x, y, z) 
positions = np.vstack(map(np.ravel, g)) 

Kết quả nhanh hơn khoảng 35 lần so với phương pháp zip cho mảng 3D với 1000 lần đánh dấu trên mỗi trục.

Nguồn: http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.gaussian_kde.html#scipy.stats.gaussian_kde

Để so sánh hai phương pháp xem xét các phần mã sau đây:

Tạo dấu tick ngôn rằng sẽ giúp tạo lưới điện.

In [23]: import numpy as np 

In [34]: from numpy import asarray 

In [35]: x = np.random.rand(100,1) 

In [36]: y = np.random.rand(100,1) 

In [37]: z = np.random.rand(100,1) 

Xác định hàm mgilson liên quan đến cho meshgrid:

In [38]: def meshgrid2(*arrs): 
    ....:  arrs = tuple(reversed(arrs)) 
    ....:  lens = map(len, arrs) 
    ....:  dim = len(arrs) 
    ....:  sz = 1 
    ....:  for s in lens: 
    ....:  sz *= s 
    ....:  ans = [] 
    ....:  for i, arr in enumerate(arrs): 
    ....:   slc = [1]*dim 
    ....:   slc[i] = lens[i] 
    ....:   arr2 = asarray(arr).reshape(slc) 
    ....:   for j, sz in enumerate(lens): 
    ....:    if j != i: 
    ....:     arr2 = arr2.repeat(sz, axis=j) 
    ....:   ans.append(arr2) 
    ....:  return tuple(ans) 

Tạo lưới điện và thời gian hai chức năng.

In [39]: g = meshgrid2(x, y, z) 

In [40]: %timeit pos = np.vstack(map(np.ravel, g)).T 
100 loops, best of 3: 7.26 ms per loop 

In [41]: %timeit zip(*(x.flat for x in g)) 
1 loops, best of 3: 264 ms per loop 
+0

Tôi nhận được thông báo lỗi: 'Traceback (cuộc gọi gần đây nhất): Tệp" ", dòng 1, trong Tệp". \ Xxx.py ", dòng 816, trong meshgrid2 slc [i] = lens [ i] LoạiError: đối tượng 'map' không phải là subscriptable' file 'xxx.py' là nơi tôi đặt hàm của bạn vào. –

+0

Bạn có thể sử dụng python3 nơi map trả về một iterator chứ không phải là một danh sách. Điều dễ nhất cần làm là bọc 'map' trong 'list':' lens = list (map (len, arrs)) '. –

+0

Trên Numpy 1.8 không cần hàm 'meshgrid2', vì tiêu chuẩn' meshgrid' hỗ trợ các chiều cao hơn. – fhchl

9

Các điểm lưới của bạn có luôn tách rời không? Nếu vậy, bạn có thể sử dụng numpy.ndindex

print list(np.ndindex(2,2)) 

kích thước cao hơn:

print list(np.ndindex(2,2,2)) 

Thật không may, điều này không đáp ứng các yêu cầu của OP từ giả thiết không thể thiếu (bắt đầu với 0) không được đáp ứng . Tôi sẽ để lại câu trả lời này chỉ trong trường hợp người khác đang tìm kiếm cùng một điều mà những giả định đó là đúng sự thật.


Một cách khác để làm điều này dựa vào zip:

g = np.meshgrid([0,1],[0,1]) 
zip(*(x.flat for x in g)) 

phần này quy mô này để thỏa mãn kích thước tùy ý. Thật không may, np.meshgrid không chia tỷ lệ tốt thành nhiều kích thước, do đó phần đó sẽ cần được giải quyết hoặc giả sử nó hoạt động, bạn có thể sử dụng SO answer này để tạo hàm ndmeshgrid của riêng bạn.

+0

Gợi ý tốt, nhưng tiếc là họ không. Chỉnh sửa ... cũng phạm vi sẽ không nhất thiết phải bắt đầu với điểm (0,0, ...). –

+0

@juniper - Quá tệ. Tôi đã thêm một giải pháp khác có thể quan tâm ... – mgilson

+0

Điều đó sẽ thực hiện. Cảm ơn! –

1

Tuy nhiên, một cách khác để làm điều đó là:

np.indices((2,2)).T.reshape(-1,2) 

Mà có thể được khái quát hóa để kích thước cao hơn, ví dụ .:

In [60]: np.indices((2,2,2)).T.reshape(-1,3) 
Out[60]: 
array([[0, 0, 0], 
     [1, 0, 0], 
     [0, 1, 0], 
     [1, 1, 0], 
     [0, 0, 1], 
     [1, 0, 1], 
     [0, 1, 1], 
     [1, 1, 1]]) 
Các vấn đề liên quan