2009-11-23 18 views
18

में columnwise शुद्ध पायथन में आप बहुत आसानी से कॉलम के आधार पर मैट्रिक्स स्तंभ बढ़ सकता है:बढ़ते मैट्रिक्स NumPy

data = [] 
for i in something: 
    newColumn = getColumnDataAsList(i) 
    data.append(newColumn) 

NumPy की सरणी संलग्न समारोह नहीं है। hstack समारोह शून्य आकार सरणियों पर काम नहीं करता है, इस प्रकार निम्नलिखित कार्य नहीं करेगा:

data = numpy.array([]) 
for i in something: 
    newColumn = getColumnDataAsNumpyArray(i) 
    data = numpy.hstack((data, newColumn)) # ValueError: arrays must have same number of dimensions 

तो, मेरे विकल्प या तो कर रहे हैं उचित शर्त के साथ पाश iside initalization दूर करने के लिए:

data = None 
for i in something: 
    newColumn = getColumnDataAsNumpyArray(i) 
    if data is None: 
     data = newColumn 
    else: 
     data = numpy.hstack((data, newColumn)) # works 

... या एक अजगर सूची का उपयोग करें और कन्वर्ट करने के लिए सरणी के लिए बाद में है:

data = [] 
for i in something: 
    newColumn = getColumnDataAsNumpyArray(i) 
    data.append(newColumn) 
data = numpy.array(data) 

दोनों वेरिएंट एक छोटा सा होने के लिए अजीब लग रहे हैं। क्या अच्छे समाधान हैं?

उत्तर

18

NumPy वास्तव में एक संलग्न समारोह, यह तुम क्या चाहते हो सकती लगती है जो करता है, जैसे,

import numpy as NP 
my_data = NP.random.random_integers(0, 9, 9).reshape(3, 3) 
new_col = NP.array((5, 5, 5)).reshape(3, 1) 
res = NP.append(my_data, new_col, axis=1) 

अपने दूसरे स्निपेट (hstack), यदि आप एक और लाइन, जैसे जोड़ने के लिए काम करेंगे

my_data = NP.random.random_integers(0, 9, 16).reshape(4, 4) 
# the line to add--does not depend on array dimensions 
new_col = NP.zeros_like(my_data[:,-1]).reshape(-1, 1) 
res = NP.hstack((my_data, new_col)) 

hstack जी ive परिणाम concatenate((my_data, new_col), axis=1) के रूप में, मुझे यकीन नहीं है कि वे प्रदर्शन-वार की तुलना कैसे करते हैं।


है कि आपके सवाल का सबसे सीधा जवाब है, मुझे लगता है कि कोई डेटा स्रोत के माध्यम से पाशन लक्ष्य को भरने के लिए के माध्यम से संलग्न, बस अजगर में ठीक है, जबकि, मुहावरेदार NumPy नहीं है उल्लेख करना चाहिए।

एक NumPy सरणी आरंभ अपेक्षाकृत महंगे है मोटे तौर पर आरंभ की तरह है, और इस पारंपरिक अजगर पैटर्न के साथ, आप वहन करेंगे कि लागत, कम या ज्यादा, प्रत्येक पाश यात्रा पर (यानी, प्रत्येक एक NumPy सरणी को संलग्न: यहाँ क्यों है एक अलग आकार के साथ एक नई सरणी)।

कारण है कि, एक 2 डी सरणी के लिए स्तंभों की पुनरावृत्ति इसके लिए NumPy में आम पैटर्न एक खाली लक्ष्य सरणी प्रारंभ करने में है एक बार (या पूर्व आवंटित खाली कॉलम के सभी होने एक भी 2 डी NumPy सरणी) क्रमिक वांछित निर्धारित करके उन खाली कॉलम भरें स्तंभ-वार ऑफसेट (सूचकांक) - बहुत आसान दिखाने के लिए की तुलना में समझाने के लिए:

>>> # initialize your skeleton array using 'empty' for lowest-memory footprint 
>>> M = NP.empty(shape=(10, 5), dtype=float) 

>>> # create a small function to mimic step-wise populating this empty 2D array: 
>>> fnx = lambda v : NP.random.randint(0, 10, v) 

ओपी में के रूप में NumPy सरणी पॉप्युलेट, को छोड़कर प्रत्येक यात्रा बस फिर से सेट मूल्यों एम के लगातार कॉलम-वार ऑफसेट पर

>>> for index, itm in enumerate(range(5)):  
     M[:,index] = fnx(10) 

>>> M 
    array([[ 1., 7., 0., 8., 7.], 
     [ 9., 0., 6., 9., 4.], 
     [ 2., 3., 6., 3., 4.], 
     [ 3., 4., 1., 0., 5.], 
     [ 2., 3., 5., 3., 0.], 
     [ 4., 6., 5., 6., 2.], 
     [ 0., 6., 1., 6., 8.], 
     [ 3., 8., 0., 8., 0.], 
     [ 5., 2., 5., 0., 1.], 
     [ 0., 6., 5., 9., 1.]]) 

निश्चित रूप से आप पहले क्या आकार अपने सरणी सिर्फ एक बहुत बड़ा की तुलना में आप की जरूरत बना सकते हैं और 'अप्रयुक्त' भाग ट्रिम होना चाहिए में जाना जाता है नहीं है जब आप इसे

>>> M[:3,:3] 
    array([[ 9., 3., 1.], 
     [ 9., 6., 8.], 
     [ 9., 7., 5.]]) 
+0

एक नुकीली नौसिखिया के लिए बहुत उपयोगी पोस्ट। त्वरित सवाल: ऐसा कोई कारण है की गणना में तुम क्यों सूचकांक के लिए 'का उपयोग है, itm (रेंज (5)):' बल्कि सिर्फ उदाहरण के लिए, रेंज में 'एक्स के लिए की तुलना में (5):' इंडेक्स के रूप में देखते हुए और इसके समान मूल्य होता है और केवल एक का उपयोग किया जाता है। –

+0

@ जॉनबर्का प्रतिक्रिया के लिए धन्यवाद। आप सही हो सकते हैं कि मेरे कोड स्निपेट का विवरण अधिक सावधानीपूर्वक चुना जाना चाहिए - यानी, मेरे उदाहरण में, प्रत्येक पुनरावृत्ति पर 'इंडेक्स' का मान वास्तव में लूप चर के मान के समान होता है। हालांकि यह एक आर्टिफैक्ट है - इन दो चर के मान अभ्यास में बराबर नहीं होने की संभावना है (उदाहरण के लिए, पुनरावर्तनीय एक ऐसी सूची है जिसमें एक फ़ंक्शन को पास करने के लिए मान होते हैं जो 1 डी सरणी बनाता है जिसे फिर लक्षित सरणी में 'डाला जाता है')। – doug

1

आम तौर पर यह NumPy सरणी को पुन: आवंटित करना महंगा है - इसलिए आपका तीसरा समाधान वास्तव में सबसे अच्छा प्रदर्शन है।

हालांकि मुझे लगता है कि hstack तुम क्या चाहते हो जाएगा - क्यू त्रुटि संदेश में है,

ValueError: arrays must have same number of dimensions`

मेरा अनुमान है कि newColumn दो आयाम हैं कि (बजाय एक -1 डी वेक्टर की तुलना में) है, तो आप डेटा की जरूरत है दो आयाम भी हैं ... उदाहरण के लिए, data = np.array([[]]) - या वैकल्पिक रूप से नया कॉलम 1 डी वेक्टर बनाते हैं (आमतौर पर यदि चीजें 1 डी होती हैं तो उन्हें 1 डी में न्यूमपी में रखना बेहतर होता है, इसलिए प्रसारण बेहतर होता है)। इस मामले में np.squeeze(newColumn) और hstack या vstack का उपयोग डेटा की आपकी मूल परिभाषा के साथ काम करना चाहिए।

4

आमतौर पर आप इसे बनाते समय NumPy सरणी का आकार बदलना नहीं रखते हैं। आपको अपने तीसरे समाधान के बारे में क्या पसंद नहीं है? यदि यह एक बहुत बड़ी मैट्रिक्स/सरणी है, तो इससे पहले कि आप अपने मान निर्दिष्ट शुरू सरणी आवंटन के लायक हो सकता है:

x = len(something) 
y = getColumnDataAsNumpyArray.someLengthProperty 

data = numpy.zeros((x,y)) 
for i in something: 
    data[i] = getColumnDataAsNumpyArray(i) 
3

hstack पॉप्युलेट समाप्त शून्य आकार के सरणी पर काम कर सकते हैं:

import numpy as np 

N = 5 
M = 15 

a = np.ndarray(shape = (N, 0)) 
for i in range(M): 
    b = np.random.rand(N, 1) 
    a = np.hstack((a, b)) 
संबंधित मुद्दे