Numpy.array शेप (R, 1) और (R,) के बीच का अंतर


319

में numpy, कुछ ऑपरेशन आकार में लौटते हैं (R, 1)लेकिन कुछ वापस लौटते हैं (R,)। यह स्पष्ट होने के बाद से मैट्रिक्स को अधिक थकाऊ बना देगा reshape। उदाहरण के लिए, एक मैट्रिक्स दिया जाता है M, अगर हम ऐसा करना चाहते हैं numpy.dot(M[:,0], numpy.ones((1, R)))जहां Rपंक्तियों की संख्या है (निश्चित रूप से, यही मुद्दा कॉलम-वार भी होता है)। हम matrices are not alignedत्रुटि प्राप्त करेंगे क्योंकि M[:,0]आकार में है (R,)लेकिन numpy.ones((1, R))आकार में है (1, R)

तो मेरे सवाल हैं:

  1. आकार में क्या अंतर है (R, 1)और (R,)। मुझे पता है कि यह वास्तव में संख्याओं की सूची है और उन सूचियों की सूची है जहां सभी सूची में केवल एक संख्या होती है। बस यह सोचकर कि numpyऐसा क्यों न हो कि यह आसान मैट्रिक्स गुणन के (R, 1)बजाय आकार के अनुकूल (R,)हो।

  2. क्या उपरोक्त उदाहरण के लिए बेहतर तरीके हैं? स्पष्ट रूप से इस तरह से फेरबदल के बिना:numpy.dot(M[:,0].reshape(R, 1), numpy.ones((1, R)))


3
यह मदद कर सकता है। हालांकि एक व्यावहारिक समाधान खोजने के साथ नहीं।
कीसर

1
उचित समाधान: numpy.ravel (एम [:, 0]) - से आकार में कनवर्ट करता है (आर, 1) से (आर,)
एंडी आर

जवाबों:


544

1. NumPy में आकृतियों का अर्थ

आप लिखते हैं, "मुझे पता है कि यह वास्तव में संख्याओं की सूची है और उन सूचियों की सूची है जहां सभी सूची में केवल एक संख्या होती है" लेकिन इसके बारे में सोचने के लिए एक अनछुआ तरीका है।

NumPy सरणियों के बारे में सोचने का सबसे अच्छा तरीका यह है कि वे दो भागों से मिलकर बने होते हैं, एक डेटा बफर जो सिर्फ कच्चे तत्वों का एक ब्लॉक होता है, और एक दृश्य जो डेटा बफर की व्याख्या करने का तरीका बताता है।

उदाहरण के लिए, यदि हम 12 पूर्णांक बनाते हैं:

>>> a = numpy.arange(12)
>>> a
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11])

फिर aएक डेटा बफर के होते हैं, इस तरह से कुछ व्यवस्था की:

┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

और एक दृश्य जो डेटा की व्याख्या करने का तरीका बताता है:

>>> a.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
>>> a.dtype
dtype('int64')
>>> a.itemsize
8
>>> a.strides
(8,)
>>> a.shape
(12,)

यहाँ आकृति का (12,) अर्थ है कि सरणी को एक एकल सूचकांक द्वारा अनुक्रमित किया जाता है जो 0 से 11. तक चलता है। यदि हम इस एकल सूचकांक को लेबल करते हैं i, तो सरणी aइस तरह दिखता है:

i= 0    1    2    3    4    5    6    7    8    9   10   11
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

यदि हम किसी सरणी को फिर से खोलते हैं , तो यह डेटा बफर को नहीं बदलता है। इसके बजाय, यह एक नया दृष्टिकोण बनाता है जो डेटा की व्याख्या करने का एक अलग तरीका बताता है। इतना होने के बाद:

>>> b = a.reshape((3, 4))

सरणी bमें डेटा बफ़र के समान है a, लेकिन अब इसे दो सूचकांकों द्वारा अनुक्रमित किया जाता है जो क्रमशः 0 से 2 और 0 से 3 तक चलते हैं। यदि हम दो सूचकांकों को लेबल करते हैं iऔर j, सरणी bइस तरह दिखता है:

i= 0    0    0    0    1    1    1    1    2    2    2    2
j= 0    1    2    3    0    1    2    3    0    1    2    3
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

जिसका मतलब है कि:

>>> b[2,1]
9

आप देख सकते हैं कि दूसरा सूचकांक जल्दी बदलता है और पहला सूचकांक धीरे-धीरे बदलता है। यदि आप इसे दूसरे तरीके से पसंद करते हैं, तो आप orderपैरामीटर निर्दिष्ट कर सकते हैं :

>>> c = a.reshape((3, 4), order='F')

इस तरह से अनुक्रमित सरणी में कौन से परिणाम हैं:

i= 0    1    2    0    1    2    0    1    2    0    1    2
j= 0    0    0    1    1    1    2    2    2    3    3    3
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

जिसका मतलब है कि:

>>> c[2,1]
5

यह अब स्पष्ट होना चाहिए कि किसी सरणी के लिए आकार के एक या अधिक आयामों के साथ इसका क्या अर्थ है। 1. बाद में:

>>> d = a.reshape((12, 1))

सरणी dको दो सूचकांकों द्वारा अनुक्रमित किया जाता है, जिनमें से पहला 0 से 11 तक चलता है, और दूसरा सूचकांक हमेशा 0 होता है:

i= 0    1    2    3    4    5    6    7    8    9   10   11
j= 0    0    0    0    0    0    0    0    0    0    0    0
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

इसलिए:

>>> d[10,0]
10

लंबाई 1 का आयाम "मुक्त" (कुछ अर्थों में) है, इसलिए आपको शहर जाने से कुछ भी नहीं रोक सकता है:

>>> e = a.reshape((1, 2, 1, 6, 1))

इस तरह अनुक्रमित सरणी देना:

i= 0    0    0    0    0    0    0    0    0    0    0    0
j= 0    0    0    0    0    0    1    1    1    1    1    1
k= 0    0    0    0    0    0    0    0    0    0    0    0
l= 0    1    2    3    4    5    0    1    2    3    4    5
m= 0    0    0    0    0    0    0    0    0    0    0    0
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
  0   1   2   3   4   5   6   7   8   9  10  11 
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘

इसलिए:

>>> e[0,1,0,0,0]
6

कैसे सरणियाँ कार्यान्वित की जाती हैं, इस बारे में अधिक जानकारी के लिए NumPy के आंतरिक दस्तावेज़ देखें ।

2. क्या करना है?

चूंकि numpy.reshapeबस एक नया दृश्य बनाता है, आपको जब भी आवश्यक हो इसका उपयोग करने के बारे में डर नहीं होना चाहिए। जब आप किसी सरणी को किसी भिन्न तरीके से अनुक्रमित करना चाहते हैं, तो इसका उपयोग करने का सही उपकरण है।

हालांकि, एक लंबी गणना में आमतौर पर पहली जगह में "सही" आकार के साथ सरणियों का निर्माण करना संभव होता है, और इसलिए फेरबदल और स्थानांतरित करने की संख्या को कम करता है। लेकिन वास्तविक संदर्भ को देखने के बिना, जिसे पुनर्वसन की आवश्यकता के कारण, यह कहना मुश्किल है कि क्या बदलना चाहिए।

आपके प्रश्न में उदाहरण है:

numpy.dot(M[:,0], numpy.ones((1, R)))

लेकिन यह यथार्थवादी नहीं है। सबसे पहले, यह अभिव्यक्ति:

M[:,0].sum()

परिणाम को अधिक सरल रूप से गणना करता है। दूसरा, क्या स्तंभ 0 के बारे में वास्तव में कुछ खास है? शायद आपको वास्तव में क्या चाहिए:

M.sum(axis=0)

33
यह सोचने में बेहद मददगार था कि सरणियों को कैसे संग्रहीत किया जाता है। धन्यवाद! (2-d) मैट्रिक्स के एक स्तंभ (या पंक्ति) को आगे मैट्रिक्स संगणना के लिए एक्सेस करना असुविधाजनक है, क्योंकि मुझे हमेशा स्तंभ को उचित रूप से बदलना है। हर बार मुझे आकार (n), से (n, 1) में बदलना होगा।
OfLettersAndNumbers

3
उपयोग: @SammyLee newaxisयदि आप किसी अन्य अक्ष की जरूरत है, उदाहरण के लिए a[:, j, np.newaxis]है jकी वें स्तंभ a, और a[np.newaxis, i]है iवें पंक्ति।
गारेथ रीस

मैं इस मॉडल द्वारा कागज पर एक बेहतर समझ प्राप्त करने के लिए सूचकांकों की साजिश करने की कोशिश कर रहा हूं और मुझे यह प्राप्त करने की आवश्यकता नहीं है, अगर मेरे पास 2 x 2 x 4 का आकार है, तो मैं समझता हूं कि पहले 2 को 0000000011111111 के रूप में समझा जा सकता है और अंतिम 4 हो सकता है 012301230123232323 के रूप में समझा जाता है कि मध्य में क्या होता है?
PirateApp

3
यह सोचने का एक आसान तरीका यह है कि यहाँ खसखस ​​उम्मीद के मुताबिक काम कर रहा है, लेकिन पायथन की ट्यूपल्स की छपाई गलत हो सकती है। में (R, )मामला है, के आकार ndarrayएक भी तत्वों के साथ एक टपल, तो पीछे अल्पविराम के साथ अजगर द्वारा मुद्रित किया जाता है। अतिरिक्त अल्पविराम के बिना, यह कोष्ठक में एक अभिव्यक्ति के साथ अस्पष्ट होगा । एक ndarrayएकल आयाम के साथ लंबाई के एक स्तंभ वेक्टर के रूप में हो सकता है R। में (R, 1)मामला है, टपल दो तत्व है, तो एक पंक्ति वेक्टर (या की लंबाई 1 पंक्ति के साथ एक मैट्रिक्स के रूप में सोचा जा सकता है R
माइकल यांग

1
@ एलेक्स- droidAD: यह प्रश्न और इसके उत्तर देखें ।
गैरेथ रीस

16

के बीच का अंतर (R,)और (1,R)शाब्दिक रूप से उन सूचकांकों की संख्या है जिन्हें आपको उपयोग करने की आवश्यकता है। ones((1,R))एक 2-D सरणी है जिसमें केवल एक पंक्ति होती है। ones(R)एक वेक्टर है। आम तौर पर अगर यह चर के लिए एक से अधिक पंक्ति / स्तंभ होने का कोई मतलब नहीं है, तो आपको एक वेक्टर का उपयोग करना चाहिए, न कि एक गायन आयाम के साथ एक मैट्रिक्स।

आपके विशिष्ट मामले के लिए, कुछ विकल्प हैं:

1) बस दूसरे तर्क को एक वेक्टर बनाएं। निम्नलिखित ठीक काम करता है:

    np.dot(M[:,0], np.ones(R))

2) यदि आप मैट्रिक्स ऑपरेशंस जैसे मैटलैब चाहते हैं, तो क्लास का उपयोग करें matrix इसके बजायndarray । सभी मैट्रिक को 2-डी सरणियों में मजबूर किया जाता है, और ऑपरेटर *तत्व-वार के बजाय मैट्रिक्स गुणा करता है (इसलिए आप डॉट नहीं करते हैं)। मेरे अनुभव में, यह अधिक परेशानी है कि यह लायक है, लेकिन यह अच्छा हो सकता है यदि आप matlab के लिए उपयोग किया जाता है।


हाँ। मैं और अधिक मैटलैब जैसे व्यवहार की उम्मीद कर रहा था। मैं matrixकक्षा पर एक नज़र डालूँगा। matrixक्लास BTW के लिए मुसीबत क्या है ?
clwen

2
इसके साथ समस्या matrixयह है कि यह केवल 2 डी है, और यह भी कि क्योंकि यह '*' को ओवरलोड करता है, ndarrayयदि एक पर उपयोग किया जाता है, तो इसके लिए लिखे गए कार्य विफल हो सकते हैं matrix
इवान

11

आकार एक टपल है। यदि केवल 1 आयाम है, तो आकार अल्पविराम के बाद एक नंबर और रिक्त होगा। 2+ आयामों के लिए, सभी अल्पविरामों के बाद एक संख्या होगी।

# 1 dimension with 2 elements, shape = (2,). 
# Note there's nothing after the comma.
z=np.array([  # start dimension
    10,       # not a dimension
    20        # not a dimension
])            # end dimension
print(z.shape)

(2)

# 2 dimensions, each with 1 element, shape = (2,1)
w=np.array([  # start outer dimension 
    [10],     # element is in an inner dimension
    [20]      # element is in an inner dimension
])            # end outer dimension
print(w.shape)

(2,1)


5

इसके आधार सरणी वर्ग के लिए, 2d सरणियाँ 1d या 3 डी वाले से अधिक विशेष नहीं हैं। आयामों को संरक्षित करने वाले कुछ ऑपरेशन हैं, कुछ जो उन्हें कम करते हैं, अन्य गठबंधन करते हैं या यहां तक ​​कि उनका विस्तार भी करते हैं।

M=np.arange(9).reshape(3,3)
M[:,0].shape # (3,) selects one column, returns a 1d array
M[0,:].shape # same, one row, 1d array
M[:,[0]].shape # (3,1), index with a list (or array), returns 2d
M[:,[0,1]].shape # (3,2)

In [20]: np.dot(M[:,0].reshape(3,1),np.ones((1,3)))

Out[20]: 
array([[ 0.,  0.,  0.],
       [ 3.,  3.,  3.],
       [ 6.,  6.,  6.]])

In [21]: np.dot(M[:,[0]],np.ones((1,3)))
Out[21]: 
array([[ 0.,  0.,  0.],
       [ 3.,  3.,  3.],
       [ 6.,  6.,  6.]])

अन्य अभिव्यक्तियाँ जो समान सरणी देती हैं

np.dot(M[:,0][:,np.newaxis],np.ones((1,3)))
np.dot(np.atleast_2d(M[:,0]).T,np.ones((1,3)))
np.einsum('i,j',M[:,0],np.ones((3)))
M1=M[:,0]; R=np.ones((3)); np.dot(M1[:,None], R[None,:])

MATLAB सिर्फ 2 डी सरणियों के साथ शुरू हुआ। नए संस्करण अधिक आयामों की अनुमति देते हैं, लेकिन निम्न बाउंड को बनाए रखते हैं 2. लेकिन आपको अभी भी एक पंक्ति मैट्रिक्स और कॉलम एक के बीच के अंतर पर ध्यान देना होगा, आकार (1,3)v के साथ एक(3,1) । आपने कितनी बार लिखा है [1,2,3].'? मैं लिखने जा रहा था row vectorऔर column vector, लेकिन उस 2d बाधा के साथ, MATLAB में कोई वैक्टर नहीं हैं - कम से कम वेक्टर के गणितीय अर्थ में 1d होने के नाते नहीं।

क्या आपने np.atleast_2d(_1d और _3d संस्करणों को भी) देखा है?


1

1) एक आकार से (R, 1)अधिक पसंद नहीं करने का कारण यह (R,)है कि यह अनावश्यक रूप से चीजों को जटिल करता है। इसके अलावा, (R, 1)लंबाई-आर वेक्टर के बजाय डिफ़ॉल्ट रूप से आकार देना बेहतर क्यों होगा(1, R) ? जब आप अतिरिक्त आयामों की आवश्यकता होती है, तो इसे सरल रखना और स्पष्ट होना बेहतर होता है।

2) अपने उदाहरण के लिए, आप एक बाहरी उत्पाद की गणना कर रहे हैं ताकि आप इसका reshapeउपयोग करके कॉल के बिना कर सकें np.outer:

np.outer(M[:,0], numpy.ones((1, R)))

जवाब के लिए धन्यवाद। 1) M[:,0]अनिवार्य रूप से पहले तत्व के साथ सभी पंक्तियों को प्राप्त कर रहा है, इसलिए यह होने की (R, 1)तुलना में अधिक समझ में आता है (1, R)। 2) यह हमेशा बदली करने योग्य नहीं है np.outer, उदाहरण के लिए, आकार में मैट्रिक्स के लिए डॉट (1, आर) तब (आर, 1)।
क्लेवेन

1) हां, यह सम्मेलन हो सकता है लेकिन यह अन्य परिस्थितियों में कम सुविधाजनक बनाता है। कन्वेंशन M [1, 1] के लिए एक आकृति (1, 1) सरणी को लौटाने के लिए भी हो सकता है, लेकिन यह भी आमतौर पर एक स्केलर की तुलना में कम सुविधाजनक होता है। यदि आप वास्तव में मैट्रिक्स जैसा व्यवहार चाहते हैं, तो आप एक matrixवस्तु का उपयोग करना बेहतर होगा । 2) वास्तव में, np.outerआकार हो या न काम करता है (1, R), (R, 1)या दोनों के संयोजन।
बोगट्रॉन

0

यहाँ पहले से ही बहुत सारे अच्छे उत्तर हैं। लेकिन मेरे लिए कुछ उदाहरण खोजना मुश्किल था, जहां आकार या सरणी सभी कार्यक्रम को तोड़ सकती है।

तो यहाँ एक है:

import numpy as np
a = np.array([1,2,3,4])
b = np.array([10,20,30,40])


from sklearn.linear_model import LinearRegression
regr = LinearRegression()
regr.fit(a,b)

यह त्रुटि के साथ विफल हो जाएगा:

ValueError: 2 डी सरणी की अपेक्षा, इसके बजाय 1D सरणी मिली

लेकिन हम जोड़ने reshapeके लिए a:

a = np.array([1,2,3,4]).reshape(-1,1)

यह सही ढंग से काम करता है!

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