2011-03-01 18 views
9

मैं numpy ndarray subclass करना चाहता हूँ। हालांकि, मैं सरणी नहीं बदल सकता। क्यों self = ... सरणी नहीं बदलता है? धन्यवाद।उप-वर्गीकरण numpy ndarray समस्या

import numpy as np 

class Data(np.ndarray): 

    def __new__(cls, inputarr): 
     obj = np.asarray(inputarr).view(cls) 
     return obj 

    def remove_some(self, t): 
     test_cols, test_vals = zip(*t) 
     test_cols = self[list(test_cols)] 
     test_vals = np.array(test_vals, test_cols.dtype) 

     self = self[test_cols != test_vals] # Is this part correct? 

     print len(self) # correct result 

z = np.array([(1,2,3), (4,5,6), (7,8,9)], 
    dtype=[('a', int), ('b', int), ('c', int)]) 
d = Data(z) 
d.remove_some([('a',4)]) 

print len(d) # output the same size as original. Why? 
+0

कृपया अपने अपेक्षित आउटपुट प्रदान करें, यह स्पष्ट नहीं है कि आप क्या हासिल करना चाहते हैं। –

+0

मैं डेटा उदाहरण से पंक्तियों को हटाना चाहता हूं। – riza

+0

ठीक है, आप एक मुखौटा का उपयोग कर सकते हैं, लेकिन अगर आप एक और सवाल पूछते हैं तो बेहतर है क्योंकि इसे ndarray –

उत्तर

4

शायद बल्कि एक विधि की तुलना में इस एक समारोह बनाने के लिए,:

import numpy as np 

def remove_row(arr,col,val): 
    return arr[arr[col]!=val] 

z = np.array([(1,2,3), (4,5,6), (7,8,9)], 
    dtype=[('a', int), ('b', int), ('c', int)]) 

z=remove_row(z,'a',4) 
print(repr(z)) 

# array([(1, 2, 3), (7, 8, 9)], 
#  dtype=[('a', '<i4'), ('b', '<i4'), ('c', '<i4')]) 

या, यदि आप यह एक विधि के रूप चाहते हैं,

import numpy as np 

class Data(np.ndarray): 

    def __new__(cls, inputarr): 
     obj = np.asarray(inputarr).view(cls) 
     return obj 

    def remove_some(self, col, val): 
     return self[self[col] != val] 

z = np.array([(1,2,3), (4,5,6), (7,8,9)], 
    dtype=[('a', int), ('b', int), ('c', int)]) 
d = Data(z) 
d = d.remove_some('a', 4) 
print(d) 

मुख्य अंतर यह यहाँ है remove_someself को संशोधित करने का प्रयास नहीं करता है, यह केवल Data का एक नया उदाहरण देता है।

+0

यह शायद प्रश्न के लिए एक उपयोगी प्रतिक्रिया है, लेकिन एक जवाब नहीं है। स्वयं = ... मूल्य क्यों नहीं बदलता है? शायद जवाब नीचे है? मैं अन्यथा दोबारा पोस्ट करूंगा। – mathtick

+0

कल्पना करें 'डी', आपका' डेटा' उदाहरण। यह स्मृति के एक ब्लॉक को इंगित कर रहा है जिसमें अंतर्निहित डेटा है। कॉलम * इन-प्लेस * को निकालने के लिए, आपको अन्य कॉलम एक साथ ले जाना होगा और फिर सरणी का आकार बदलना होगा। जब आप 'self = some_other_array' कहते हैं तो आप चर नाम' self' को स्मृति के किसी अन्य ब्लॉक पर रीडायरेक्ट कर रहे हैं। 'Remove_row' विधि के बाहर, हालांकि, परिवर्तनीय नाम' d' अभी भी स्मृति के मूल ब्लॉक को इंगित कर रहा है। तो यह 'डी' को संशोधित करने में विफल रहता है। – unutbu

+0

मैंने जो भी सलाह कभी भी numpy के बारे में पढ़ी है, कहती है कि किसी को numpy arrays का आकार बदलने का प्रयास नहीं करना चाहिए। ऐसा करना संभव है, लेकिन सभी प्रतिलिपि इसे धीमा कर देती है। वांछित डेटा के साथ नए सरणी बनाने के लिए दृश्य बनाने के लिए स्लाइस का उपयोग करना, या फैंसी इंडेक्सिंग करना बेहतर है। हां, एक नई सरणी बनाने में भी प्रतिलिपि शामिल है, लेकिन कम से कम आप जगह के चारों ओर डेटा स्थानांतरित करने की जटिलता से बचाए गए हैं। – unutbu

6

कारण आप परिणाम आप उम्मीद नहीं मिल रहे हैं क्योंकि आप कर रहे हैं पद्धति remove_some भीतर फिर से बताए self है। आप बस एक नया स्थानीय चर self बना रहे हैं। यदि आपके सरणी आकार को बदलने के लिए नहीं थे, तो आप बस स्वयं [:] = ... कर सकते हैं और आप संदर्भ को self पर रख सकते हैं और सभी ठीक होंगे, लेकिन आप self के आकार को बदलने की कोशिश कर रहे हैं। जिसका अर्थ है कि हमें कुछ नई मेमोरी फिर से आवंटित करने की आवश्यकता है और जब हम self देखेंगे तो हम कहां इंगित करते हैं।

मैं ऐसा करने के तरीके पता नहीं है। मैंने सोचा कि इसे __array_finalize__ या __array__ या __array_wrap__ द्वारा हासिल किया जा सकता है। लेकिन मैंने जो भी कोशिश की है वह कम हो रही है।

अब, इस बारे में जाने का एक और तरीका है जो ndarray उपखंड नहीं करता है।

Class Data(object): 
    def __init__(self, inarr): 
     self._array = np.array(inarr) 
    def remove_some(x): 
     self._array = self._array[x] 
    def __add__(self, other): 
     return np.add(self._array, other) 

ठीक है, आप चित्र प्राप्त: आप एक नया वर्ग है कि एक विशेषता एक ndarray है और उसके बाद इस तरह सभी सामान्य __add__, __mul__, आदि .. कुछ ओवरराइड कि रहता है बना सकते हैं। यह सभी ऑपरेटरों को ओवरराइड करने का दर्द है, लेकिन लंबे समय तक, मुझे लगता है कि अधिक लचीला लगता है।

आपको इसे सही करने के लिए this को पढ़ना होगा। __array_finalize__ जैसी विधियां हैं जिन्हें "क्लीनअप" करने का सही समय कहा जाना चाहिए।

+0

मैंने सोचा कि '__array_finalize__' का उपयोग तब किया जाता है जब एक नया उदाहरण शुरू किया जा रहा है, उदाहरण के लिए अतिरिक्त विशेषताओं को जोड़ने में। – riza

+0

मैंने सोचा था कि इसे किसी भी समय बुलाया जाना था जब आप ओपी की तरह सरणी आवंटित कर रहे थे। लेकिन ईमानदार होने के लिए, यह मेरे सिर पर है।'__array_wrap__' शायद जो चाहता था उसके करीब आता है, लेकिन केवल ufunc द्वारा कॉल किए जाने पर ही लौटाता है। – Paul

3

मैंने ऐसा करने की कोशिश की, लेकिन यह वास्तव में subclass ndarray के लिए बहुत जटिल है।

यदि आपको केवल कुछ कार्यक्षमता जोड़नी है, तो मैं एक वर्ग बनाने का सुझाव दूंगा जो सरणी को विशेषता के रूप में संग्रहीत करता है।

class Data(object): 

    def __init__(self, array): 
     self.array = array 

    def remove_some(self, t): 
     //operate on self.array 
     pass 

d = Data(z) 
print(d.array) 
+0

[सब वर्ग ndarray कैसे करें पर प्रलेखन] (https://docs.scipy.org/doc/numpy/user/basics.subclassing.html) इसे आसान बनाने में मदद कर सकता है। – Sardathrion

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

  • कोई संबंधित समस्या नहीं^_^