"क्लोनिंग" पंक्ति या स्तंभ वैक्टर


155

कभी-कभी यह एक मैट्रिक्स के लिए एक पंक्ति या स्तंभ वेक्टर को "क्लोन" करने के लिए उपयोगी होता है। क्लोनिंग से मेरा मतलब है कि एक पंक्ति वेक्टर जैसे कि परिवर्तित करना

[1,2,3]

एक मैट्रिक्स में

[[1,2,3]
 [1,2,3]
 [1,2,3]
]

या एक स्तंभ वेक्टर जैसे

[1
 2
 3
]

में

[[1,1,1]
 [2,2,2]
 [3,3,3]
]

Matlab या सप्तक में यह बहुत आसानी से किया जाता है:

 x = [1,2,3]
 a = ones(3,1) * x
 a =

    1   2   3
    1   2   3
    1   2   3

 b = (x') * ones(1,3)
 b =

    1   1   1
    2   2   2
    3   3   3

मैं इसे सुन्न में दोहराना चाहता हूं, लेकिन असफल रूप से

In [14]: x = array([1,2,3])
In [14]: ones((3,1)) * x
Out[14]:
array([[ 1.,  2.,  3.],
       [ 1.,  2.,  3.],
       [ 1.,  2.,  3.]])
# so far so good
In [16]: x.transpose() * ones((1,3))
Out[16]: array([[ 1.,  2.,  3.]])
# DAMN
# I end up with 
In [17]: (ones((3,1)) * x).transpose()
Out[17]:
array([[ 1.,  1.,  1.],
       [ 2.,  2.,  2.],
       [ 3.,  3.,  3.]])

पहला तरीका ( In [16]) काम क्यों नहीं कर रहा था? क्या अजगर में इस कार्य को अधिक सुरुचिपूर्ण तरीके से प्राप्त करने का एक तरीका है?


6
मतलाब में, ध्यान दें कि यह उपयोग करने के लिए बहुत तेज़ है repmat: repmat([1 2 3],3,1)याrepmat([1 2 3].',1,3)
लुइस मेन्डो

सप्तक भी है repmat
ma11hew28

एक पांडा डेटाफ्रेम चेकआउट के साथ समान करने की तलाश करने वालों के लिए tile_df
डेटाफ्रेम चाह रखने वालों के लिए

जवाबों:


80

यहाँ यह करने के लिए एक सुंदर, Pythonic तरीका है:

>>> array([[1,2,3],]*3)
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

>>> array([[1,2,3],]*3).transpose()
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

के साथ समस्या [16] यह है कि संक्रमण एक सरणी के लिए कोई प्रभाव नहीं है लगता है। आप शायद इसके बजाय एक मैट्रिक्स चाहते हैं:

>>> x = array([1,2,3])
>>> x
array([1, 2, 3])
>>> x.transpose()
array([1, 2, 3])
>>> matrix([1,2,3])
matrix([[1, 2, 3]])
>>> matrix([1,2,3]).transpose()
matrix([[1],
        [2],
        [3]])

1
(उदाहरण के लिए वर्ग एक के लिए उदाहरण के लिए 2 डी सरणियों के लिए काम करता है, या जब (N,1)उपयोग सरणी में बदल जाता है .reshape(-1, 1))
मार्क

34
यह अत्यधिक अक्षम है। Pv. के उत्तरnumpy.tile में दिखाए अनुसार उपयोग करें ।
डेविड हेफर्नन

304

उपयोग करें numpy.tile:

>>> tile(array([1,2,3]), (3, 1))
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

या कॉलम दोहराने के लिए:

>>> tile(array([[1,2,3]]).transpose(), (1, 3))
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

16
वोट दें! मेरे सिस्टम पर, 10000 तत्वों को 1000 बार दोहराया जाने वाले वेक्टर के लिए, tileविधि वर्तमान में स्वीकृत उत्तर (गुणन-संचालक-विधि का उपयोग करके) की तुलना में 19.5 गुना तेज है।
डॉ। जन-फिलिप गेर्के

1
दूसरे खंड में ("दोहराए जाने वाले कॉलम"), क्या आप समझा सकते हैं कि वर्ग ब्रैकेट का दूसरा सेट क्या करता है, अर्थात [[1,2,3]]
चींटी

@ यह पहली अक्ष में लंबाई 1 (आपकी स्क्रीन पर लंबवत) और दूसरी अक्ष में लंबाई 3 (आपकी स्क्रीन पर क्षैतिज) के साथ 2 डी सरणी में बनाता है। ट्रांसपोज़िंग तब बनाता है जिसमें पहली धुरी में लंबाई 3 और दूसरी धुरी में लंबाई 1 है। का एक टाइल आकार(1, 3)इस स्तंभ तीन बार से अधिक है, यही वजह है कि परिणाम की पंक्तियों में प्रत्येक एक अलग तत्व होता है।
बॉलपॉइंटबैन

यह स्वीकृत उत्तर होना चाहिए क्योंकि आप किसी भी वेक्टर को पहले से ही शुरू कर सकते हैं जबकि स्वीकृत केवल तभी काम कर सकता है जब आप वेक्टर को प्रारंभ करते समय अल्पविराम जोड़ते हैं। धन्यवाद !
योहन ओबैदिया

मैं इसे 2 डी से 3 डी समाधान के लिए काम करने के लिए नहीं प्राप्त कर सकता :(
जॉन ktejik

42

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

लेकिन ऐसा करने के लिए, दोहराव और newaxis शायद सबसे अच्छा तरीका है

In [12]: x = array([1,2,3])

In [13]: repeat(x[:,newaxis], 3, 1)
Out[13]: 
array([[1, 1, 1],
       [2, 2, 2],
       [3, 3, 3]])

In [14]: repeat(x[newaxis,:], 3, 0)
Out[14]: 
array([[1, 2, 3],
       [1, 2, 3],
       [1, 2, 3]])

यह उदाहरण एक पंक्ति वेक्टर के लिए है, लेकिन इसे कॉलम वेक्टर पर लागू करना उम्मीद के मुताबिक स्पष्ट है। रिपीट यह अच्छी तरह से वर्तनी लगता है, लेकिन आप इसे अपने उदाहरण के अनुसार गुणा के माध्यम से भी कर सकते हैं

In [15]: x = array([[1, 2, 3]])  # note the double brackets

In [16]: (ones((3,1))*x).transpose()
Out[16]: 
array([[ 1.,  1.,  1.],
       [ 2.,  2.,  2.],
       [ 3.,  3.,  3.]])

5
newaxis का अतिरिक्त लाभ है कि यह वास्तव में डेटा को तब तक कॉपी नहीं करता है जब तक कि उसे इसकी आवश्यकता न हो। इसलिए यदि आप इसे गुणा करने या किसी अन्य 3x3 सरणी में जोड़ने के लिए कर रहे हैं, तो पुनरावृत्ति अनावश्यक है। विचार प्राप्त करने के लिए सुन्न प्रसारण पर पढ़ें।
AFoglia

@ सफ़ोग्लिया - अच्छी बात है। मैंने इसे इंगित करने के लिए अपना उत्तर अपडेट किया।
टमाटर

1
np.repeatबनाम का उपयोग करने के क्या फायदे हैं np.tile?
मर्गलूम

@ मर्ग्लूम: कोई नहीं, ज्यादातर, इस मामले के लिए। एक छोटे 1D सरणी के लिए, वे समान हैं और कोई महत्वपूर्ण अंतर / लाभ / लाभ / आदि नहीं है। व्यक्तिगत रूप से, मैं पंक्ति और स्तंभ क्लोनिंग के बीच समरूपता को अधिक सहजता से पाता हूं, और मुझे टाइल के लिए आवश्यक स्थानान्तरण पसंद नहीं है, लेकिन यह सिर्फ स्वाद की बात है। मतीन उलहाक का जवाब भी कहता है कि रिपीट तेजी से होता है, लेकिन यह उस सटीक उपयोग के मामले पर निर्भर हो सकता है जिसे माना जाता है, हालांकि रिपीट सी-कार्यक्षमता के बहुत करीब है, इसलिए संभवतः कुछ तेजी से रहेगा। 2 डी में उनके पास अलग-अलग व्यवहार हैं इसलिए यह वहां मायने रखता है।
टॉम 10

12

करते हैं:

>>> n = 1000
>>> x = np.arange(n)
>>> reps = 10000

शून्य-लागत आवंटन

एक दृश्य कोई अतिरिक्त मेमोरी नहीं लेता है। इस प्रकार, ये घोषणाएँ तात्कालिक हैं:

# New axis
x[np.newaxis, ...]

# Broadcast to specific shape
np.broadcast_to(x, (reps, n))

जबरन आवंटन

यदि आप सामग्री को स्मृति में निवास करने के लिए बाध्य करना चाहते हैं:

>>> %timeit np.array(np.broadcast_to(x, (reps, n)))
10.2 ms ± 62.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit np.repeat(x[np.newaxis, :], reps, axis=0)
9.88 ms ± 52.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit np.tile(x, (reps, 1))
9.97 ms ± 77.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

तीनों विधियां लगभग एक ही गति की हैं।

गणना

>>> a = np.arange(reps * n).reshape(reps, n)
>>> x_tiled = np.tile(x, (reps, 1))

>>> %timeit np.broadcast_to(x, (reps, n)) * a
17.1 ms ± 284 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit x[np.newaxis, :] * a
17.5 ms ± 300 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

>>> %timeit x_tiled * a
17.6 ms ± 240 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

तीनों विधियां लगभग एक ही गति की हैं।


निष्कर्ष

यदि आप एक गणना से पहले प्रतिकृति करना चाहते हैं, तो "शून्य-लागत आवंटन" विधियों में से एक का उपयोग करने पर विचार करें। आपको "जबरन आवंटन" के प्रदर्शन का दंड भुगतना नहीं पड़ेगा।


8

मुझे लगता है कि सुन्न में प्रसारण का उपयोग करना सबसे अच्छा, और तेज है

मैंने निम्नलिखित के रूप में एक तुलना की

import numpy as np
b = np.random.randn(1000)
In [105]: %timeit c = np.tile(b[:, newaxis], (1,100))
1000 loops, best of 3: 354 µs per loop

In [106]: %timeit c = np.repeat(b[:, newaxis], 100, axis=1)
1000 loops, best of 3: 347 µs per loop

In [107]: %timeit c = np.array([b,]*100).transpose()
100 loops, best of 3: 5.56 ms per loop

प्रसारण का उपयोग करते हुए लगभग 15 गुना तेज


आप Noneएक ही काम करने के लिए अनुक्रमण कर सकते हैं ।
डैनियलस्कैंक

न्यूआक्सिस क्या है ?!
dreab

np.newaxis कोई नहीं के लिए एक उपनाम है
जॉन ktejik

पुनरावृत्ति तेज थी: 5.56 एमएस = 5560 µ
अगस्तो फादेल

4

एक स्वच्छ समाधान के लिए एक वेक्टर के साथ NumPy के बाहरी उत्पाद फ़ंक्शन का उपयोग करना है:

np.outer(np.ones(n), x)

देता nपंक्तियों दोहरा। पुनरावृत्ति कॉलम प्राप्त करने के लिए तर्क क्रम स्विच करें। आपके द्वारा की जाने वाली पंक्तियों और स्तंभों की समान संख्या प्राप्त करने के लिए

np.outer(np.ones_like(x), x)

3

आप उपयोग कर सकते हैं

np.tile(x,3).reshape((4,3))

टाइल वेक्टर के प्रतिनिधि उत्पन्न करेगा

और जैसा आप चाहते हैं उसे आकार देगा


1

यदि आपके पास एक पांडा डेटाफ़्रेम है और dtypes, यहां तक ​​कि श्रेणीबद्ध को संरक्षित करना चाहते हैं, तो यह करने का एक तेज़ तरीका है:

import numpy as np
import pandas as pd
df = pd.DataFrame({1: [1, 2, 3], 2: [4, 5, 6]})
number_repeats = 50
new_df = df.reindex(np.tile(df.index, number_repeats))

-1
import numpy as np
x=np.array([1,2,3])
y=np.multiply(np.ones((len(x),len(x))),x).T
print(y)

पैदावार:

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