একটি NumPy অ্যারের মধ্যে স্থান ধরণের রূপান্তর


127

একটি NumPy অ্যারে দেওয়া int32, আমি কীভাবে এটি float32 জায়গায় রূপান্তর করব ? সুতরাং মূলত, আমি করতে চাই

a = a.astype(numpy.float32)

অ্যারে অনুলিপি না করে। এটা বড়.

এটি করার কারণটি হল আমার কাছে গণনার জন্য দুটি অ্যালগরিদম রয়েছে a। তাদের মধ্যে একটি অ্যারে প্রদান করে int32, অন্যটি একটি অ্যারে প্রদান করে float32(এবং এটি দুটি পৃথক পৃথক অ্যালগরিদমের সহজাত)। আরও সমস্ত গণনা aএটি একটি অ্যারে বলে ধরে নিচ্ছে float32

বর্তমানে আমি একটি সি ফাংশনে রূপান্তর করি যার মাধ্যমে ctypes। পাইথনে এটি করার কোনও উপায় আছে?


ব্যবহার ctypesকরা যতটা "পাইথনের" তেমন ব্যবহার numpy। :)
কার্ল নচেটেল

3
@ কার্ল: না, কারণ আমাকে সি ফাংশনটি নিজে কোড করতে এবং সংকলন করতে হবে।
সোভেন মারনাচ

আচ্ছা বুঝলাম. আমি মনে করি আপনি সম্ভবত এটির জন্য এসওএল।
কার্ল নচেটেল

3
@ অ্যান্ড্রু: এটির একটি অনুলিপি ফেরত দেয় কিনা তা জানানোর অনেকগুলি উপায় রয়েছে। এর মধ্যে একটি হ'ল ডকুমেন্টেশন পড়া ।
সোভেন মারনাচ

1
জায়গার সহজলভ্য অর্থ "মূল অ্যারের মতো একই মেমরি ব্যবহার করা"। গৃহীত উত্তরটি একবার দেখুন - শেষ অংশটি দেখায় যে নতুন মানগুলি একই মেমরির উপরে লিখে ফেলেছে।
সোভেন মারনাচ

উত্তর:


110

আপনি আলাদা আলাদা টাইপ দিয়ে একটি ভিউ তৈরি করতে পারেন এবং তারপরে ভিউটিতে স্থান-অনুলিপি করতে পারেন:

import numpy as np
x = np.arange(10, dtype='int32')
y = x.view('float32')
y[:] = x

print(y)

উৎপাদনের

array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.], dtype=float32)

রূপান্তর প্রদর্শনের জন্য মো ইন-স্থান, দয়া করে মনে রাখবেন কপি থেকে x থেকে yপরিবর্তিত x:

print(x)

কপি করে প্রিন্ট

array([         0, 1065353216, 1073741824, 1077936128, 1082130432,
       1084227584, 1086324736, 1088421888, 1090519040, 1091567616])

26
তাদের জন্য নোট করুন (আমার মতো) যারা বিভিন্ন বাইট-সাইজের dtype (যেমন 32 থেকে 16 বিট) এর মধ্যে রূপান্তর চান: এই পদ্ধতিটি ব্যর্থ হয় কারণ y.size <> x.size। যৌক্তিক একবার আপনি এটি সম্পর্কে চিন্তা করে :-(
জুহ_

এই সমাধানটি কি নিম্পির কিছু পুরানো সংস্করণের জন্য কাজ করছে? আমি যখন np.arange(10, dtype=np.int32).view(np.float32)নম্পি 1.8.2 এ করি তখন আমি পাই array([ 0.00000000e+00, 1.40129846e-45, ... [snip] ... 1.26116862e-44], dtype=float32)
বাস সুইঙ্কসেলস

3
@ বাসসুইনকেলস: এটি প্রত্যাশিত রূপান্তর ঘটে যখন আপনি বরাদ্দ করেন y[:] = x
unutbu

মূল উত্তর এবং @ জুহ__ দ্বারা উল্লিখিত আইটেমাইজ (বিটের সংখ্যা) সম্পর্কে করা বিন্দুটি স্পষ্ট করতে: উদাহরণস্বরূপ: a = np.arange(10, dtype='float32'); b = a[::-1]; c = np.vstack((a,b)); d = c.view('float64')এই কোডটি 10 ​​+ 10 ফ্লোট 32 নেয় এবং 20 টি ফ্লোটের পরিবর্তে 10-এ ফলাফল নেয়
ডেকানেলাস

1
এই স্থান পরিবর্তন এই স্মৃতি ব্যবহারের উপর সঞ্চয় করতে পারে তবে এটি একটি সাধারণ x.astype(float)রূপান্তর চেয়ে ধীর । আপনার স্ক্রিপ্টটি মেমোরিআরারের সাথে সীমাবদ্ধ না করা না হলে আমি এটির প্রস্তাব দেব না।
এইচপলজ

158

আপডেট: এই ফাংশনটি কেবল অনুলিপিটি এড়িয়ে চললে এড়ানো যায়, সুতরাং এটি এই প্রশ্নের সঠিক উত্তর নয়। আনটবু'র উত্তরটি সঠিক।


a = a.astype(numpy.float32, copy=False)

নম্পি অ্যাস্টাইপের একটি কপি পতাকা রয়েছে। কেন আমরা এটি ব্যবহার করব না?


14
এই প্যারামিটারটি একটি NumPy রিলিজ সমর্থিত হয়ে গেলে, আমরা অবশ্যই এটি ব্যবহার করতে পারি, তবে বর্তমানে এটি কেবলমাত্র উন্নয়ন শাখায় উপলব্ধ। এবং আমি যখন এই প্রশ্নটি জিজ্ঞাসা করেছি তখন এর অস্তিত্বই ছিল না।
সোভেন মারনাচ

2
@ স্পেনমার্নাচ এটি এখন সমর্থিত, কমপক্ষে আমার সংস্করণে (1.7.1)।
ফিলম্যাকেকে

এটি সর্বশেষতম ছদ্মবেশী সংস্করণটির সাথে পাইথন 3.3 এ পুরোপুরি কাজ করবে বলে মনে হচ্ছে।
CHM

1
আমি এটিকে a = ভিউ (700 এর চেয়ে ভাসমান (ভাসমান, লেন (a.dtype.names)) এর চেয়ে ধীরে ধীরে 700x কম বলে মনে করি
জেজে

14
অনুলিপি পতাকাটি কেবল বলেছে যে পরিবর্তনটি যদি অনুলিপি ছাড়াই করা যায় তবে এটি অনুলিপি ছাড়াই করা হবে। তবে এটির ধরনটি আলাদা এটি এখনও সর্বদা অনুলিপি করে।
কোডারফরফিল

14

আপনি এ জাতীয় রূপান্তর না করে অ্যারের প্রকার পরিবর্তন করতে পারেন:

a.dtype = numpy.float32

তবে প্রথমে আপনাকে সমস্ত পূর্ণসংখ্যাকে এমন কিছুতে পরিবর্তন করতে হবে যা সম্পর্কিত ফ্লোট হিসাবে ব্যাখ্যা করা হবে। এটি করার একটি খুব ধীর গতির উপায়টি হ'ল পাইথনের structমডিউলটি এভাবে ব্যবহার করা:

def toi(i):
    return struct.unpack('i',struct.pack('f',float(i)))[0]

... আপনার অ্যারের প্রতিটি সদস্যের জন্য প্রয়োগ করা হয়েছে।

তবে সম্ভবত একটি দ্রুততর উপায় হ'ল নম্পির সিটিপস্লিব সরঞ্জামগুলি ব্যবহার করা (যার সাথে আমি অপরিচিত)

- সম্পাদনা -

যেহেতু সিটিপ্লেসিব কাজ করে না বলে মনে হয়, ততক্ষণে আমি সাধারণ numpy.astypeপদ্ধতিতে রূপান্তরটি নিয়ে এগিয়ে যাব তবে আপনার মেমরির সীমাতে থাকা ব্লকের আকারগুলিতে এগিয়ে যাব :

a[0:10000] = a[0:10000].astype('float32').view('int32')

... কাজ শেষ হলে টাইপটি পরিবর্তন করুন।

এখানে এমন একটি ফাংশন রয়েছে যা কোনও সামঞ্জস্যপূর্ণ টাইপগুলি (কেবল একই আকারের আইটেমগুলির সাথে ডাইটিপগুলির জন্য কাজ করে) এবং ব্লক আকারের উপর ব্যবহারকারীর নিয়ন্ত্রণের সাথে নির্বিচারে আকারের অ্যারেগুলি পরিচালনা করে:

import numpy

def astype_inplace(a, dtype, blocksize=10000):
    oldtype = a.dtype
    newtype = numpy.dtype(dtype)
    assert oldtype.itemsize is newtype.itemsize
    for idx in xrange(0, a.size, blocksize):
        a.flat[idx:idx + blocksize] = \
            a.flat[idx:idx + blocksize].astype(newtype).view(oldtype)
    a.dtype = newtype

a = numpy.random.randint(100,size=100).reshape((10,10))
print a
astype_inplace(a, 'float32')
print a

1
আপনার উত্তরের জন্য ধন্যবাদ. সত্যি বলতে কী, আমি বড় বড় অ্যারেগুলির পক্ষে এটি খুব কার্যকর বলে মনে করি না - এটি উপায় খুব ধীর। অ্যারের ডেটাটিকে ভিন্ন ধরণের হিসাবে ব্যাখ্যা করা সহজ - উদাহরণস্বরূপ কল করে a.view(numpy.float32)। হার্ড অংশটি আসলে ডেটা রূপান্তর করে। numpy.ctypeslibকেবলমাত্র ডেটা পুনরায় ব্যাখ্যা করতে সহায়তা করে, বাস্তবে রূপান্তরিত করে নয়।
সোভেন মারনাচ

ঠিক আছে. আপনার স্মৃতি / প্রসেসরের সীমাবদ্ধতাগুলি কী তা আমি নিশ্চিত ছিলাম না। আমার সম্পাদনা দেখুন।
পল

আপডেটের জন্য ধন্যবাদ. ব্লকওয়াইজ করে এটি করা একটি ভাল ধারণা - বর্তমানের নুমপি ইন্টারফেসের সাথে সম্ভবত আপনি সবচেয়ে ভাল পেতে পারেন। তবে এক্ষেত্রে আমি সম্ভবত আমার বর্তমান সিটিপস সলিউশনে আটকে থাকব।
সোভেন মারনাচ

-1
import numpy as np
arr_float = np.arange(10, dtype=np.float32)
arr_int = arr_float.view(np.float32)

অ্যারে স্থানে পরিবর্তন করতে ভিউ () এবং প্যারামিটার 'dtype' ব্যবহার করুন।


প্রশ্নের লক্ষ্য হ'ল প্রকৃতপক্ষে ডেটা রূপান্তর করা । শেষ লাইনে প্রকারটি সংশোধন করার পরে int, এই উত্তরটি কেবল বিদ্যমান ডেটাটিকে ভিন্ন ধরণের হিসাবে পুনরায় ব্যাখ্যা করবে, যা আমি যা চাইছিলাম তা নয়।
সোভেন মারনাচ

আপনি কি বোঝাতে চেয়েছেন? dtype কেবল মেমরিতে ডেটার উপস্থিতি, এটি সত্যিই কার্যকরী n
蒋志强

হ্যাঁ, আমি প্রথম গৃহীত উত্তরের সাথে একমত। তবে arr_.astype (new_dtype, অনুলিপি = মিথ্যা) এখনও একটি নতুন বরাদ্দ করা অ্যারে প্রদান করে। কতটা সন্তুষ্ট করতে dtype, orderএবং subokপ্রয়োজনীয়তা অ্যারের একটি কপি ফেরত দেওয়ার জন্য? আমি এর সমাধান করি না।
蒋志强

-5

এটা ব্যবহার কর:

In [105]: a
Out[105]: 
array([[15, 30, 88, 31, 33],
       [53, 38, 54, 47, 56],
       [67,  2, 74, 10, 16],
       [86, 33, 15, 51, 32],
       [32, 47, 76, 15, 81]], dtype=int32)

In [106]: float32(a)
Out[106]: 
array([[ 15.,  30.,  88.,  31.,  33.],
       [ 53.,  38.,  54.,  47.,  56.],
       [ 67.,   2.,  74.,  10.,  16.],
       [ 86.,  33.,  15.,  51.,  32.],
       [ 32.,  47.,  76.,  15.,  81.]], dtype=float32)

5
আপনি কি নিশ্চিত যে এটি অনুলিপি নয়? আপনি এটি পরীক্ষা করে আরও কিছুটা ব্যাখ্যা করতে পারবেন?
মিশেল ডি'আমিকো

-5

a = np.subtract(a, 0., dtype=np.float32)


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

কেন এটি স্থানান্তরিত হওয়া উচিত ? numpy.subtractকপি ফিরিয়ে দিচ্ছে, তাই না? কেবলমাত্র নামটি aঅন্য একটি অংশের জন্য পুনরায় ব্যবহার করা হয়েছে ... দয়া করে ব্যাখ্যা করুন, আমি যদি এই সম্পর্কে ভুল হয়ে থাকি।
কোফফেইন

এটি নির্দেশ করার জন্য আপনাকে ধন্যবাদ, মনে হচ্ছে আপনি সঠিক আছেন - একটি অনুলিপি তৈরি করা হয়েছে।
এমআইও
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.