একটি NumPy 2d অ্যারের কাটা, বা আমি কীভাবে একটি এনএক্সএন অ্যারে (এন> মি) থেকে এমএক্সএম সাবম্যাট্রিক্স বের করব?


174

আমি একটি NumPy nxn অ্যারে টুকরা করতে চাই। আমি একটি নির্বিচারে নিষ্কাশন করতে চান অ্যারের এম সারি এবং কলামগুলির সংগ্রহটি (অর্থাত সারি / কলামগুলির সংখ্যায় কোনও বিন্যাস ছাড়াই), এটি একটি নতুন, এমএক্সএম অ্যারে তৈরি করে। এই উদাহরণের জন্য আসুন আমরা অ্যারেটি 4x4 বলে থাকি এবং আমি এটি থেকে 2x2 অ্যারেটি বের করতে চাই।

আমাদের অ্যারে এখানে:

from numpy import *
x = range(16)
x = reshape(x,(4,4))

print x
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]
 [12 13 14 15]]

সরানোর জন্য লাইন এবং কলামগুলি একই। সবচেয়ে সহজ কেসটি যখন আমি 2x2 সাবমেট্রিক্সটি শুরু করতে বা শেষে দেখতে পারি, অর্থাত:

In [33]: x[0:2,0:2]
Out[33]: 
array([[0, 1],
       [4, 5]])

In [34]: x[2:,2:]
Out[34]: 
array([[10, 11],
       [14, 15]])

তবে আমার কী সারি / কলামগুলির অন্য মিশ্রণটি সরিয়ে ফেলতে হবে? আমার যদি প্রথম এবং তৃতীয় লাইন / সারিগুলি সরানোর প্রয়োজন হয়, এভাবে সাবম্যাট্রিক্সটি বের করা যায় [[5,7],[13,15]]? সারি / রেখার যে কোনও রচনা থাকতে পারে। আমি কোথাও পড়েছি যে সারি এবং কলাম উভয়ের জন্য সূচি তালিকাগুলির অ্যারে / তালিকা ব্যবহার করে আমার কেবল অ্যারে সূচী করা দরকার, তবে এটি কার্যকর বলে মনে হচ্ছে না:

In [35]: x[[1,3],[1,3]]
Out[35]: array([ 5, 15])

আমি একটি উপায় পেয়েছি, যা:

    In [61]: x[[1,3]][:,[1,3]]
Out[61]: 
array([[ 5,  7],
       [13, 15]])

এটির সাথে প্রথম বিষয়টি হ'ল এটি খুব কমই পঠনযোগ্য, যদিও আমি এটির সাথে থাকতে পারি। কারও যদি এর থেকে আরও ভাল সমাধান হয় তবে আমি অবশ্যই এটি শুনতে চাই।

অন্য জিনিসটি আমি একটি ফোরামে পড়েছি যে অ্যারেগুলির সাথে অ্যারেগুলি সূচনা করা NumPy কে পছন্দসই অ্যারের একটি অনুলিপি তৈরি করতে বাধ্য করে, সুতরাং বড় অ্যারেগুলির সাথে চিকিত্সা করার সময় এটি একটি সমস্যা হতে পারে। কেন / কেন এই প্রক্রিয়াটি কাজ করে?

উত্তর:


62

সোভেন উল্লিখিত হিসাবে, x[[[0],[2]],[1,3]]1 এবং 3 টি কলামের সাথে মেলে এমন 0 এবং 2 টি সারি ফিরিয়ে দেবে যখন x[[0,2],[1,3]]একটি অ্যারেতে [[0,1] এবং x [2,3] মানগুলি ফিরিয়ে দেবে।

আমি যে প্রথম উদাহরণটি দিয়েছি তা করার জন্য একটি সহায়ক ফাংশন রয়েছে numpy.ix_। আপনি আমার প্রথম উদাহরণ হিসাবে একই জিনিস করতে পারেন x[numpy.ix_([0,2],[1,3])]। এটি আপনাকে অতিরিক্ত সমস্ত বন্ধনীতে প্রবেশ করা থেকে বাঁচাতে পারে।


111

এই প্রশ্নের উত্তর দিতে, আমাদের দেখতে হবে যে একটি বহুমাত্রিক অ্যারে সূচকে নিম্পিতে কীভাবে কাজ করে। প্রথমে বলি xআপনার প্রশ্ন থেকে আপনার অ্যারে রয়েছে । নির্ধারিত xবাফারটিতে 0 থেকে 15 পর্যন্ত 16 টি আরোহণের পূর্ণসংখ্যা থাকবে x[i,j]you এটি কার্যকর হিসাবে গণনা করে করা হয় i*x.shape[1]+j(এবং প্রকৃত মেমরি অফসেট পেতে কোনও int এর আকারের সাথে গুণ করে)।

আপনি যদি বেসিক স্লাইসিংয়ের মাধ্যমে সাববারি বের করেন y = x[0:2,0:2] তবে ফলস্বরূপ অবজেক্টটি এর সাথে অন্তর্নিহিত বাফারটি ভাগ করবে x। তবে অ্যাক্সেস করলে কী হয় y[i,j]? NumPy i*y.shape[1]+jঅ্যারেতে অফসেট গণনা করতে ব্যবহার করতে পারে না , কারণ ডেটা সম্পর্কিতy মেমরিতে ক্রমাগত নয়।

পদক্ষেপ প্রবর্তন করে নুমপি এই সমস্যাটি সমাধান করে । অ্যাক্সেসের জন্য অফসেট মেমরি গণনা করার সময়x[i,j] , আসলে যা গণনা করা হয় তা হ'ল i*x.strides[0]+j*x.strides[1](এবং এর মধ্যে ইতিমধ্যে কোনও int এর আকারের ফ্যাক্টরটি অন্তর্ভুক্ত রয়েছে):

x.strides
(16, 4)

yউপরের মতো যখন বের করা হয়, নুমপি একটি নতুন বাফার তৈরি করে না, তবে এটি একই বাফারকে উল্লেখ করে একটি নতুন অ্যারে অবজেক্ট তৈরি করে (অন্যথায় yএটি কেবল সমান হবে x)) নতুন অ্যারে অবজেক্টটির আলাদা আকৃতি থাকবেx এবং সম্ভবত অন্যরকম শুরু হবে বাফারে অফসেট করা হয়েছে তবে এর সাথে ধাপগুলি ভাগ করা হবে x(এই ক্ষেত্রে অন্তত):

y.shape
(2,2)
y.strides
(16, 4)

এইভাবে, অফসেটের জন্য মেমরির গণনা করা y[i,j]সঠিক ফলাফল করবে।

তবে NumPy এর মতো কিছু করার জন্য কী করা উচিত z=x[[1,3]]? মূল বাফারটির জন্য ব্যবহার করা হলে স্ট্রাইডস মেকানিজম সঠিক ইনডেক্সিংয়ের অনুমতি দেয় না z। তাত্ত্বিকভাবে NumPy চেয়ে আরও কিছু পরিশীলিত ব্যবস্থা যুক্ত করতে পারে তবে এটি উপাদানকে অ্যাক্সেস তুলনামূলকভাবে ব্যয়বহুল করে তুলবে, কোনওভাবে অ্যারের পুরো ধারণাটিকে অস্বীকার করবে। তদ্ব্যতীত, দৃশ্যটি আর কোনও সত্যই হালকা ওজনের জিনিস হবে না।

এটি সূচকের নম্পপি ডকুমেন্টেশনে গভীরভাবে আচ্ছাদিত

ওহ, এবং আপনার আসল প্রশ্ন সম্পর্কে প্রায় ভুলে গেছেন: একাধিক তালিকাগুলি অনুমান অনুযায়ী কাজ করে কীভাবে তৈরি করা যায় তা এখানে:

x[[[1],[3]],[1,3]]

এর কারণ সূচক অ্যারেগুলি একটি সাধারণ আকারে সম্প্রচারিত হয়। অবশ্যই, এই নির্দিষ্ট উদাহরণের জন্য, আপনি বেসিক কাটা দিয়েও করতে পারেন:

x[1::2, 1::2]

সাব ক্লাস অ্যারেগুলি উচ্চস্বরে সম্ভব হবে যাতে একটিতে "স্লাই-ভিউ" অবজেক্ট থাকতে পারে মূল সূচিতে সূচিগুলি পুনরায় তৈরি করতে পারে। এটি সম্ভবত ওপি এর প্রয়োজনীয়তা পূরণ করতে পারে
jsbueno

@ জসবুউনো: এটি পাইথন কোডের জন্য কাজ করবে তবে স্কিপি / নম্পি চারপাশে জড়িয়ে থাকা সি / ফোর্টরান রুটিনগুলির জন্য নয়। এই মোড়ানো রুটিনগুলিই যেখানে নম্পির শক্তি নিহিত।
ডেটা চু

সু .. এক্স [[[1], [3]], [1,3]] এবং এক্স [[1,3],:] [:, [1,3]] এর মধ্যে পার্থক্য কী? আমি বলতে চাইছি এমন কোনও রূপ রয়েছে যা অন্যের চেয়ে ভাল ব্যবহার করা উচিত?
লেভেস্ক

1
@ জেসি: x[[[1],[3]],[1,3]]কেবলমাত্র একটি নতুন অ্যারে তৈরি করে, যখন x[[1,3],:][:,[1,3]]দুটি বার অনুলিপি করে, তাই প্রথমটি ব্যবহার করুন।
সোভেন মারনাচ

@ জেসি: অথবা জাস্টিনের উত্তর থেকে পদ্ধতিটি ব্যবহার করুন।
সোভেন মারনাচ

13

আমি মনে করি না যে x[[1,3]][:,[1,3]]এটি খুব সহজেই পঠনযোগ্য। আপনি যদি নিজের অভিপ্রায় সম্পর্কে আরও পরিষ্কার হতে চান তবে আপনি এটি করতে পারেন:

a[[1,3],:][:,[1,3]]

আমি টুকরো টুকরো করার ক্ষেত্রে বিশেষজ্ঞ নই তবে সাধারণত, আপনি যদি অ্যারেগুলিতে টুকরো টুকরো করার চেষ্টা করেন এবং মানগুলি অবিচ্ছিন্ন থাকে, আপনি যেখানে স্ট্রাইডের মান পরিবর্তন করা হয়েছে সেখানে ফিরে আসুন।

উদাহরণস্বরূপ আপনার ইনপুটগুলি 33 এবং 34 এ, যদিও আপনি 2x2 অ্যারে পান তবে স্ট্রাইডটি 4 হয় Thus সুতরাং, আপনি যখন পরবর্তী সারিতে সূচী করেন তখন পয়েন্টারটি মেমরিতে সঠিক অবস্থানে চলে যায়।

স্পষ্টতই, এই পদ্ধতিটি সূচকের অ্যারের ক্ষেত্রে ভালভাবে বহন করে না। সুতরাং, নম্পিদের অনুলিপিটি তৈরি করতে হবে। সর্বোপরি, আরও অনেক ম্যাট্রিক্স গণিতের ফাংশন আকার, স্ট্রাইড এবং ক্রমাগত মেমরির বরাদ্দের উপর নির্ভর করে।


10

আপনি যদি প্রতিটি অন্যান্য সারি এবং প্রতিটি অন্যান্য কলাম বাদ দিতে চান তবে আপনি এটি বেসিক স্লাইসিংয়ের মাধ্যমে করতে পারেন:

In [49]: x=np.arange(16).reshape((4,4))
In [50]: x[1:4:2,1:4:2]
Out[50]: 
array([[ 5,  7],
       [13, 15]])

এটি আপনার অ্যারের অনুলিপি নয়, একটি দর্শন ফিরিয়ে দেয়।

In [51]: y=x[1:4:2,1:4:2]

In [52]: y[0,0]=100

In [53]: x   # <---- Notice x[1,1] has changed
Out[53]: 
array([[  0,   1,   2,   3],
       [  4, 100,   6,   7],
       [  8,   9,  10,  11],
       [ 12,  13,  14,  15]])

z=x[(1,3),:][:,(1,3)]উন্নত সূচিকাগুলি ব্যবহার করার সময় এবং একটি অনুলিপি প্রদান করে:

In [58]: x=np.arange(16).reshape((4,4))
In [59]: z=x[(1,3),:][:,(1,3)]

In [60]: z
Out[60]: 
array([[ 5,  7],
       [13, 15]])

In [61]: z[0,0]=0

নোট যে xঅপরিবর্তিত:

In [62]: x
Out[62]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

আপনি যদি স্বেচ্ছাচারী সারি এবং কলামগুলি নির্বাচন করতে চান তবে আপনি বেসিক স্লাইসিং ব্যবহার করতে পারবেন না। আপনি ভালো কিছু ব্যবহার, উন্নত ইন্ডেক্স ব্যবহার করতে হবে x[rows,:][:,columns], যেখানে rowsএবং columnsসিকোয়েন্স আছে। এটি অবশ্যই আপনাকে আপনার মূল অ্যারের একটি অনুলিপি দিচ্ছে না। এটি যেমনটি প্রত্যাশা করা উচিত, যেহেতু একটি ন্যালি অ্যারে সংবিধ মেমরি ব্যবহার করে (ধ্রুবক পদক্ষেপ সহ), এবং স্বেচ্ছাসেবী সারি এবং কলামগুলির সাথে কোনও ভিউ তৈরি করার উপায় নেই (যেহেতু এটির জন্য অ-ধ্রুব পদক্ষেপ প্রয়োজন)।


5

নপি দিয়ে আপনি সূচকের প্রতিটি উপাদানগুলির জন্য একটি স্লাইস পাস করতে পারেন - সুতরাং, আপনার x[0:2,0:2] উপরে উদাহরণ কাজ করে।

আপনি যদি কলাম বা সারিগুলি সমানভাবে এড়িয়ে যেতে চান তবে আপনি তিনটি উপাদান (যেমন শুরু, থামান, পদক্ষেপ) দিয়ে স্লাইসগুলি পাস করতে পারেন।

আবার, উপরে আপনার উদাহরণের জন্য:

>>> x[1:4:2, 1:4:2]
array([[ 5,  7],
       [13, 15]])

যা মূলত: সূচক 1 এ শুরু হওয়ার সাথে প্রথম মাত্রায় টুকরো টুকরো, সূচক সমান বা 4 এর চেয়ে বেশি হলে বন্ধ করুন এবং প্রতিটি পাসের সূচকে 2 যোগ করুন। দ্বিতীয় মাত্রা জন্য একই। আবার: এটি কেবল ধ্রুব পদক্ষেপের জন্য কাজ করে।

অভ্যন্তরীণভাবে আপনি বেশ আলাদা কিছু করতে চেয়েছিলেন - x[[1,3]][:,[1,3]]প্রকৃতপক্ষে যা ঘটে তা হল মূল অ্যারে ( x[[1,3]]অংশ দিয়ে সম্পন্ন ) থেকে কেবল 1 এবং 3 সারি সহ একটি নতুন অ্যারে তৈরি করা , এবং তারপরে পুনরায় টুকরো টুকরো - একটি তৃতীয় অ্যারে তৈরি করা - কেবলমাত্র পূর্ববর্তী অ্যারের 1 এবং 3 কলাম।


1
আমি যে সারি / কলামগুলি বের করার চেষ্টা করেছি তার সাথে সুনির্দিষ্ট হওয়ায় এই সমাধানটি কাজ করে না। 50x50 ম্যাট্রিক্সে একইটি কল্পনা করুন, যখন আমি 5,11,12,32,39,45 সারি / কলামগুলি বের করতে চাই, সাধারণ টুকরা দিয়ে এটি করার উপায় নেই। আমি যদি আমার প্রশ্নে পরিষ্কার না হত তবে দুঃখিত।
লেভেস্ক

3

আমার এখানে একটি অনুরূপ প্রশ্ন রয়েছে: সর্বাধিক পাইথোনীয় উপায়ে একটি নাদারের সাব-নাদারে লেখা। পাইথন 2

আপনার কেসটির জন্য আগের পোস্টের সমাধান অনুসরণ করে সমাধানটি দেখতে দেখতে:

columns_to_keep = [1,3] 
rows_to_keep = [1,3]

একটি ix_ ব্যবহার করে:

x[np.ix_(rows_to_keep, columns_to_keep)] 

যা হলো:

array([[ 5,  7],
       [13, 15]])

0

এটি কতটা দক্ষ তা আমি নিশ্চিত নই তবে আপনি উভয় অক্ষকেই কাটতে রেঞ্জ () ব্যবহার করতে পারেন

 x=np.arange(16).reshape((4,4))
 x[range(1,3), :][:,range(1,3)] 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.