2010-07-15 30 views
5

के बीच गड़बड़ी इंटरकवर्जन मैं नम्पी में रैखिक और बहुआयामी अनुक्रमण के बीच इंटरकॉन्टर करने का एक तेज़ तरीका ढूंढ रहा हूं।बहुआयामी और रैखिक अनुक्रमण

मेरा उपयोग कंक्रीट बनाने के लिए, मेरे पास एन कणों का एक बड़ा संग्रह है, प्रत्येक ने 5 फ्लोट मान (आयाम) को एनएक्स 5 सरणी दिया है। मैं तब प्रत्येक आयाम को प्रत्येक आयाम को 5 आयामी अंतरिक्ष में एक बिन असाइन करने के लिए बिन सीमाओं के उचित विकल्प के साथ numpy.digitize का उपयोग करके बिन करता हूं।

N = 10 
ndims = 5 
p = numpy.random.normal(size=(N,ndims)) 
for idim in xrange(ndims): 
    bbnds[idim] = numpy.array([-float('inf')]+[-2.,-1.,0.,1.,2.]+[float('inf')]) 

binassign = ndims*[None] 
for idim in xrange(ndims): 
    binassign[idim] = numpy.digitize(p[:,idim],bbnds[idim]) - 1 

दूतावास में पंक्तियां होती हैं जो बहुआयामी सूचकांक से मेल खाते हैं। मैं तो एक रेखीय सूचकांक करने के लिए बहुआयामी सूचकांक में परिवर्तित करना चाहते हैं, तो मुझे लगता है कि मैं कुछ ऐसा करना चाहते हैं जाएगा:

linind = numpy.arange(6**5).reshape(6,6,6,6,6) 

यह प्रत्येक बहुआयामी सूचकांक एक रेखीय अनुक्रमणिका से मैप करने के लिए के लिए एक लुक-अप देना होगा। इसके बाद आप का उपयोग कर वापस जा सकते हैं:

mindx = numpy.unravel_index(x,linind.shape) 

मैं कहां से कठिनाइयां आ रही हूँ कैसे binassign लेने के लिए (Nx5 सरणी) लगाना है प्रत्येक पंक्ति में बहुआयामी सूचकांक युक्त, और coverting है कि एक 1 दिन रैखिक सूचकांक करने के लिए, द्वारा रैखिक अनुक्रमण सरणी linind टुकड़ा करने के लिए इसका उपयोग कर।

यदि किसी के पास बहु-आयामी सूचकांक और रैखिक सूचकांक के बीच आगे और आगे जाने के लिए एक (या कई) लाइन इंडेक्सिंग चाल है जो सभी एन कणों के लिए ऑपरेशन को सदिश बनाती है, तो मैं आपकी अंतर्दृष्टि की सराहना करता हूं।

उत्तर

3

हालांकि मुझे ईओएल के जवाब की तरह बहुत कुछ है, लेकिन मैं इसे प्रत्येक दिशा के साथ गैर-समान संख्या में डिब्बे के लिए थोड़ा सा सामान्य बनाना चाहता था, और आदेश के सी और एफ शैलियों के बीच अंतर को हाइलाइट करना चाहता था।

ndims = 5 
N = 10 

# Define bin boundaries 
binbnds = ndims*[None] 
nbins = [] 
for idim in xrange(ndims): 
    binbnds[idim] = numpy.linspace(-10.0,10.0,numpy.random.randint(2,15)) 
    binbnds[idim][0] = -float('inf') 
    binbnds[idim][-1] = float('inf') 
    nbins.append(binbnds[idim].shape[0]-1) 

nstates = numpy.cumprod(nbins)[-1] 

# Define variable values for N particles in ndims dimensions 
p = numpy.random.normal(size=(N,ndims)) 

# Assign to bins along each dimension 
binassign = ndims*[None] 
for idim in xrange(ndims): 
    binassign[idim] = numpy.digitize(p[:,idim],binbnds[idim]) - 1 

binassign = numpy.array(binassign) 

# multidimensional array with elements mapping from multidim to linear index 
# Two different arrays for C vs F ordering 
linind_C = numpy.arange(nstates).reshape(nbins,order='C') 
linind_F = numpy.arange(nstates).reshape(nbins,order='F') 

और अब रूपांतरण

# Fast conversion to linear index 
b_F = numpy.cumprod([1] + nbins)[:-1] 
b_C = numpy.cumprod([1] + nbins[::-1])[:-1][::-1] 

box_index_F = numpy.dot(b_F,binassign) 
box_index_C = numpy.dot(b_C,binassign) 

बनाने के लिए और शुद्धता के लिए जाँच करने के लिए: यहाँ एक उदाहरण हल है

# Check 
print 'Checking correct mapping for each particle F order' 
for k in xrange(N): 
    ii = box_index_F[k] 
    jj = linind_F[tuple(binassign[:,k])] 
    print 'particle %d %s (%d %d)' % (k,ii == jj,ii,jj) 

print 'Checking correct mapping for each particle C order' 
for k in xrange(N): 
    ii = box_index_C[k] 
    jj = linind_C[tuple(binassign[:,k])] 
    print 'particle %d %s (%d %d)' % (k,ii == jj,ii,jj) 

और संपूर्णता के लिए, आप से वापस जाने के लिए चाहते हैं, तो एक तेज़, वेक्टरीकृत शैली शैली में बहुआयामी सूचकांक के लिए 1 डी इंडेक्स:

print 'Convert C-style from linear to multi' 
x = box_index_C.reshape(-1,1) 
bassign_rev_C = x/b_C % nbins 

print 'Convert F-style from linear to multi' 
x = box_index_F.reshape(-1,1) 
bassign_rev_F = x/b_F % nbins 

और फिर से जांच करने के लिए:

print 'Check C-order' 
for k in xrange(N): 
    ii = tuple(binassign[:,k]) 
    jj = tuple(bassign_rev_C[k,:]) 
    print ii==jj,ii,jj 

print 'Check F-order' 
for k in xrange(N): 
    ii = tuple(binassign[:,k]) 
    jj = tuple(bassign_rev_F[k,:]) 
    print ii==jj,ii,jj 
4

आप बस प्रत्येक बिन के सूचकांक की गणना कर सकते हैं:

box_indices = numpy.dot(ndims**numpy.arange(ndims), binassign) 

अदिश उत्पाद बस करता है 1 * x0 + 5 * x 1 + 5 * 5 * x2 + ... यह NumPy के dot() के माध्यम से बहुत कुशलता से किया जाता है।

+0

धन्यवाद, मैं अपने खुद के समाधान में अपने सुझाव सामान्यीकृत। – JoshAdel

संबंधित मुद्दे