NaNs से भरा हुआ खस्ता मैट्रिक्स बनाएं


195

मेरे पास निम्नलिखित कोड हैं:

r = numpy.zeros(shape = (width, height, 9))

यह width x height x 9शून्य से भरा एक मैट्रिक्स बनाता है । इसके बजाय, मैं यह जानना चाहूंगा कि क्या NaNआसान तरीके से एस करने के बजाय उन्हें शुरू करने का कोई कार्य या तरीका है ।


2
एक चेतावनी यह है कि NumPy का पूर्णांक NA मान (R के विपरीत) नहीं है। पांडा की सूची देखें । इसलिए np.nanइंट में परिवर्तित होने पर गलत हो जाता है।
ज़ू

सही है। NumPy के लिए ऐसा कोई NaN मान नहीं है। तो यह प्रकार पर और न्यूपी पर निर्भर करता है कि NaN के लिए कौन सा मूल्य होगा। यदि आप इसके बारे में नहीं जानते हैं, तो यह परेशानी पैदा करेगा
MasterControlProgram

जवाबों:


271

आपको शायद ही कभी सुपीरियर में वेक्टर ऑपरेशन के लिए छोरों की आवश्यकता होती है। आप एक असिंचित सरणी बना सकते हैं और एक ही बार में सभी प्रविष्टियों को असाइन कर सकते हैं:

>>> a = numpy.empty((3,3,))
>>> a[:] = numpy.nan
>>> a
array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])

मैंने a[:] = numpy.nanयहां विकल्प के a.fill(numpy.nan)रूप में समय पर और ब्लेंक द्वारा पोस्ट किया है:

$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)"
10000 loops, best of 3: 54.3 usec per loop
$ python -mtimeit "import numpy as np; a = np.empty((100,100));" "a[:] = np.nan" 
10000 loops, best of 3: 88.8 usec per loop

ndarray.fill(..)तेज विकल्प के रूप में समय के लिए वरीयता दिखाई देती है । ओटीओएच, मुझे सुपी की सुविधा कार्यान्वयन पसंद है जहां आप उस समय पूरे स्लाइस को मान असाइन कर सकते हैं, कोड का इरादा बहुत स्पष्ट है।

ध्यान दें कि ndarray.fillइसके संचालन को इन-प्लेस करता है, इसलिए numpy.empty((3,3,)).fill(numpy.nan)इसके बजाय वापस आ जाएगा None


8
मैं मानता हूं कि आपके कोड का इरादा स्पष्ट है। लेकिन निष्पक्ष समय के लिए धन्यवाद (या बल्कि, यह तथ्य कि आपने अभी भी उन्हें पोस्ट किया है), मैं इसकी सराहना करता हूं :)
जॉर्ज इज़राइल Peña

2
मुझे यह पसंद है a = numpy.empty((3, 3,)) * numpy.nan:। यह fillअसाइनमेंट विधि की तुलना में धीमी लेकिन धीमी गति से समय पर है , लेकिन यह एक oneliner है !!
हेलटोनबीकर

2
कृपया इस उत्तर को देखें: stackoverflow.com/questions/10871220/…
इवान

3
मैं .fill()विधि को पसंद करता हूं , लेकिन गति में अंतर व्यावहारिक रूप से कम हो जाता है क्योंकि सरणियां बड़ी हो जाती हैं।
n

4
... क्योंकि np.empty([2, 5])एक सरणी बनाता है, तो fill()उस सरणी को जगह में संशोधित करता है, लेकिन प्रतिलिपि या संदर्भ नहीं देता है। यदि आप np.empty(2, 5)एक नाम से कॉल करना चाहते हैं ("असाइन एक वैरिएबल के लिए है"), तो आपको ऐसा करने से पहले आपको इन-प्लेस ऑपरेशन करना होगा। यदि आप करते हैं तो एक ही तरह की बात होती है [1, 2, 3].insert(1, 4)। सूची बनाई गई है और एक 4 डाला गया है, लेकिन सूची का संदर्भ प्राप्त करना असंभव है (और इस तरह यह माना जा सकता है कि कचरा एकत्र किया गया है)। स्ट्रिंग जैसे अपरिवर्तनीय डेटा पर, एक प्रति वापस कर दी जाती है, क्योंकि आप इन-प्लेस को संचालित नहीं कर सकते। पंडों दोनों कर सकते हैं।
flutefreak7

164

एक अन्य विकल्प का उपयोग करना है numpy.full, एक विकल्प जो कि NumPy 1.8+ में उपलब्ध है

a = np.full([height, width, 9], np.nan)

यह काफी लचीला है और आप इसे किसी भी अन्य नंबर से भर सकते हैं जो आप चाहते हैं।


19
मैं इसे सबसे सही उत्तर के रूप में मानता हूँ क्योंकि यह वास्तव में क्या fullहै। np.empy((x,y))*np.nanएक अच्छा उपविजेता है (और पुराने संस्करणों के लिए अनुकूलता)।
ट्रेप सेप

यह धीमी है किfill python -mtimeit "import numpy as np; a = np.empty((100,100));" "a.fill(np.nan)" 100000 loops, best of 3: 13.3 usec per loop python -mtimeit "import numpy as np; a = np.full((100,100), np.nan);" 100000 loops, best of 3: 18.5 usec per loop
फरनाब

5
@ फ़र्नाबाज़ यदि आप समतुल्य कोड डालते हैं जो टाइमिंग लूप के बारे में बताता है कि वे उसी के बारे में हैं। दो विधियां मूल रूप से समान हैं, आपको पहले में टाइमर के बाहर "np.empty" मिला है। python -mtimeit "import numpy as np; a = np.empty((1000,1000)); a.fill(np.nan)" 1000 loops, best of 3: 381 usec per loop $ python -mtimeit "import numpy as np; a = np.full((1000,1000), np.nan);" 1000 loops, best of 3: 383 usec per loop
स्कॉट स्टैन्विकेज़

48

मैंने गति के लिए सुझाए गए विकल्पों की तुलना की और पाया कि बड़े पर्याप्त वैक्टर / मैट्रिस को भरने के लिए, सभी विकल्पों को छोड़कर val * onesऔर array(n * [val])समान रूप से तेज़ हैं।

यहां छवि विवरण दर्ज करें


प्लॉट को फिर से तैयार करने के लिए कोड:

import numpy
import perfplot

val = 42.0


def fill(n):
    a = numpy.empty(n)
    a.fill(val)
    return a


def colon(n):
    a = numpy.empty(n)
    a[:] = val
    return a


def full(n):
    return numpy.full(n, val)


def ones_times(n):
    return val * numpy.ones(n)


def list(n):
    return numpy.array(n * [val])


perfplot.show(
    setup=lambda n: n,
    kernels=[fill, colon, full, ones_times, list],
    n_range=[2 ** k for k in range(20)],
    logx=True,
    logy=True,
    xlabel="len(a)",
)

अजीब है कि numpy.full(n, val)तुलना में धीमी है a = numpy.empty(n) .. a.fill(val), क्योंकि यह एक ही बात आंतरिक रूप से करता है
endolith

26

क्या आप परिचित हैं numpy.nan?

आप अपनी खुद की विधि बना सकते हैं जैसे:

def nans(shape, dtype=float):
    a = numpy.empty(shape, dtype)
    a.fill(numpy.nan)
    return a

फिर

nans([3,4])

उत्पादन होगा

array([[ NaN,  NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN,  NaN]])

मुझे मेल कोड सूची में यह कोड मिला ।


1
ओवरकिल की तरह लगता है।
मैड फिजिसिस्ट

@MadPhysicist जो पूरी तरह से आपकी स्थिति पर निर्भर करता है। यदि आपको केवल एक एकल NaN सरणी को इनिशियलाइज़ करना है, तो हाँ, एक कस्टम फ़ंक्शन शायद ओवरकिल है। हालाँकि यदि आपको अपने कोड में दर्जनों स्थानों पर NaN सरणी को इनिशियलाइज़ करना है, तो यह फ़ंक्शन होने से यह काफी सुविधाजनक हो जाता है।
Xukrao

1
@Xukaro। वास्तव में नहीं, यह देखते हुए कि इस तरह के फ़ंक्शन का अधिक लचीला और कुशल संस्करण पहले से मौजूद है और कई अन्य उत्तरों में उल्लेख किया गया है।
मैड फिजिसिस्ट

10

यदि आप तुरंत .emptyया .fullविधियों को याद नहीं करते हैं, तो आप हमेशा गुणा का उपयोग कर सकते हैं :

>>> np.nan * np.ones(shape=(3,2))
array([[ nan,  nan],
       [ nan,  nan],
       [ nan,  nan]])

बेशक यह किसी अन्य संख्यात्मक मान के साथ भी काम करता है:

>>> 42 * np.ones(shape=(3,2))
array([[ 42,  42],
       [ 42,  42],
       [ 42, 42]])

लेकिन @ u0b34a0f6ae का स्वीकृत उत्तर 3x तेज है (सीपीयू साइकल, मस्तिष्क चक्रों को याद रखने के लिए नहीं, बल्कि साइफिक सिंटैक्स याद रखने के लिए;);

$ python -mtimeit "import numpy as np; X = np.empty((100,100));" "X[:] = np.nan;"
100000 loops, best of 3: 8.9 usec per loop
(predict)laneh@predict:~/src/predict/predict/webapp$ master
$ python -mtimeit "import numpy as np; X = np.ones((100,100));" "X *= np.nan;"
10000 loops, best of 3: 24.9 usec per loop

6

एक अन्य विकल्प है numpy.broadcast_to(val,n)जो आकार की परवाह किए बिना निरंतर समय में लौटता है और यह सबसे अधिक स्मृति कुशल भी है (यह दोहराए गए तत्व का एक दृश्य देता है)। चेतावनी यह है कि लौटाया गया मान केवल पढ़ने के लिए है।

नीचे उन सभी अन्य तरीकों के प्रदर्शन की तुलना की गई है जो कि Nico Schlömer के उत्तर में उसी बेंचमार्क का उपयोग करके प्रस्तावित किए गए हैं ।

यहां छवि विवरण दर्ज करें


5

जैसा कि कहा, numpy.empty () जाने का रास्ता है। हालाँकि, वस्तुओं के लिए, भरण () ठीक वैसा नहीं कर सकता जैसा आप सोचते हैं कि यह करता है:

In[36]: a = numpy.empty(5,dtype=object)
In[37]: a.fill([])
In[38]: a
Out[38]: array([[], [], [], [], []], dtype=object)
In[39]: a[0].append(4)
In[40]: a
Out[40]: array([[4], [4], [4], [4], [4]], dtype=object)

एक तरह से चारों ओर हो सकता है जैसे:

In[41]: a = numpy.empty(5,dtype=object)
In[42]: a[:]= [ [] for x in range(5)]
In[43]: a[0].append(4)
In[44]: a
Out[44]: array([[4], [], [], [], []], dtype=object)

मूल सवाल के साथ कुछ नहीं करने के अलावा, साफ।
मैड फिजिसिस्ट

1
खैर, यह "शून्य या एक के अलावा कुछ के लिए प्रारंभिक मैट्रिक्स को प्रारंभिक करने" के बारे में है, मामले में "कुछ और" एक वस्तु है :) (अधिक व्यावहारिक रूप से, Google ने मुझे यहां एक खाली सूची के साथ आरंभ करने के लिए नेतृत्व किया)
ntg

3

अभी तक एक और संभावना नहीं है जिसका उल्लेख यहां किया गया है, वह है NumPy टाइल का उपयोग करना:

a = numpy.tile(numpy.nan, (3, 3))

भी देता है

array([[ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN],
       [ NaN,  NaN,  NaN]])

मैं गति तुलना के बारे में नहीं जानता।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.