2013-04-03 32 views
6

Tôi sử dụng Python với numpy.numpy: Làm thế nào để tham gia mảng? (để có được sự kết hợp của một số phạm vi)

Tôi có một mảng NumPy các chỉ số a:

>>> a 
array([[5, 7], 
     [12, 18], 
     [20, 29]]) 
>>> type(a) 
<type 'numpy.ndarray'> 

Tôi có một mảng NumPy các chỉ số b:

>>> b 
array([[2, 4], 
     [8, 11], 
     [33, 35]]) 
>>> type(b) 
<type 'numpy.ndarray'> 

tôi cần phải tham gia vào một mảng a với một mảng b:

a + b =>[2, 4] [5, 7] [8, 11] [12, 18] [20, 29] [33, 35]

=>ab có mảng các chỉ số =>[2, 18] [20, 29] [33, 35]

(chỉ số ([2, 4][5, 7][8, 11][12, 18]) đi tuần tự

=>2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18 =>[2, 18])

Ví dụ này:

>>> out_c 
array([[2, 18], 
     [20, 29], 
     [33, 35]]) 

Có thể ai đó vui lòng đề xuất, ho Tôi có được out_c không?

Cập nhật: @Geoff giải pháp được đề xuất python union of multiple ranges. Liệu giải pháp này nhanh nhất và tốt nhất trong mảng dữ liệu lớn?

+0

Bạn có ý nghĩa gì khi 'tích hợp' hai mảng? – StuGrey

+0

Có lẽ tôi chỉ dày đặc, nhưng tôi không thể tìm ra cách bạn đã đi từ 'a' và' b' sang 'out_c'. – mgilson

+0

@StuGrey Tôi đã cập nhật câu hỏi – Olga

Trả lời

4

(New trả lời) Sử dụng NumPy

ranges = np.vstack((a,b)) 
ranges.sort(0) 

# List of non-overlapping ranges 
nonoverlapping = (ranges[1:,0] - ranges[:-1,1] > 1).nonzero()[0] 

# Starts are 0, and all the starts not overlapped by their predecessor 
starts = np.hstack(([0], nonoverlapping + 1)) 

# Ends are -1 and all the ends who aren't overlapped by their successor 
ends = np.hstack((nonoverlapping, [-1])) 

# Result 
result = np.vstack((ranges[starts, 0], ranges[ends, 1])).T 

(Cũ câu trả lời) Sử dụng danh sách và đặt

import numpy as np 
import itertools 

def ranges(s): 
    """ Converts a list of integers into start, end pairs """ 
    for a, b in itertools.groupby(enumerate(s), lambda(x, y): y - x): 
     b = list(b) 
     yield b[0][1], b[-1][1] 

def intersect(*args): 
    """ Converts any number of numpy arrays containing start, end pairs 
     into a set of indexes """ 
    s = set() 
    for start, end in np.vstack(args): 
     s = s | set(range(start,end+1)) 
    return s 

a = np.array([[5,7],[12, 18],[20,29]]) 
b = np.array([[2,4],[8,11],[33,35]]) 

result = np.array(list(ranges(intersect(a,b)))) 

Tài liệu tham khảo

+0

cảm ơn giải pháp được đề xuất – Olga

+0

Bạn đã tìm thấy gì để không hoạt động với giải pháp mới của mình? Tôi đã poking tại nó ngay bây giờ ... – Jaime

+0

Với caveat "không chồng chéo", tôi muốn nói nó hoạt động tốt, phải không? – Jaime

1

có lẽ bạn có thể thử sử dụng numpy.concatenate() để nối các mảng với nhau, sau đó tìm mininum và tối đa của mỗi hàng ... sau đó tạo c làm ma trận min và max của mỗi hàng.

cách khác, np.minimum và np.maximum so sánh hai mảng và tìm giá trị tối thiểu và tối đa, vì vậy bạn có thể tìm tối thiểu và tối đa cho mỗi hàng, sau đó gán cho ma trận c.

+0

Tôi nghĩ rằng đó là một sự trùng hợp ngẫu nhiên rằng hai mảng 'a' và' b' đều có ba hàng. Đây là một điểm tốt mặc dù, nếu tôi sai. – Geoff

+0

@mtigger cảm ơn vì lời mời – Olga

3

Không đẹp, nhưng nó hoạt động. Tôi không thích vòng lặp cuối cùng, mua không thể nghĩ ra một cách để làm mà không có nó:

ab = np.vstack((a,b)) 
ab.sort(axis=0) 

join_with_next = ab[1:, 0] - ab[:-1, 1] <= 1 
endpoints = np.concatenate(([0], 
          np.where(np.diff(join_with_next) == True)[0] + 2, 
          [len(ab,)])) 
lengths = np.diff(endpoints) 
new_lengths = lengths.copy() 
if join_with_next[0] == True: 
    new_lengths[::2] = 1 
else: 
    new_lengths[1::2] = 1 
new_endpoints = np.concatenate(([0], np.cumsum(new_lengths))) 
print endpoints, lengths 
print new_endpoints, new_lengths 

starts = endpoints[:-1] 
ends = endpoints[1:] 
new_starts = new_endpoints[:-1] 
new_ends = new_endpoints[1:] 
c = np.empty((new_endpoints[-1], 2), dtype=ab.dtype) 

for j, (s,e,ns,ne) in enumerate(zip(starts, ends, new_starts, new_ends)): 
    if e-s != ne-ns: 
     c[ns:ne] = np.array([np.min(ab[s:e, 0]), np.max(ab[s:e, 1])]) 
    else: 
     c[ns:ne] = ab[s:e] 

>>> c 
array([[ 2, 18], 
     [20, 29], 
     [33, 35]]) 
+0

cảm ơn giải pháp được đề xuất – Olga

+0

Bạn đã truyền cảm hứng cho tôi để tiếp tục thử. Nếu bạn vẫn còn quan tâm đến vấn đề này, bạn sẽ kiểm tra câu trả lời của tôi? Có vẻ quá đơn giản để đúng. – Geoff

+0

... đừng bận tâm. – Geoff

Các vấn đề liên quan