আমি কীভাবে জেনারেটর থেকে একটি নম্পি অ্যারে তৈরি করব?


166

আমি কীভাবে জেনারেটরের অবজেক্টের বাইরে আঙ্কুল অ্যারে তৈরি করতে পারি?

আমাকে সমস্যাটি বর্ণনা করি:

>>> import numpy
>>> def gimme():
...   for x in xrange(10):
...     yield x
...
>>> gimme()
<generator object at 0x28a1758>
>>> list(gimme())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> numpy.array(xrange(10))
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> numpy.array(gimme())
array(<generator object at 0x28a1758>, dtype=object)
>>> numpy.array(list(gimme()))
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

এই উদাহরণস্বরূপ, gimme()সেই জেনারেটরটি যার আউটপুটটি আমি একটি অ্যারেতে রূপান্তর করতে চাই। তবে অ্যারে কনস্ট্রাক্টর জেনারেটরের উপরে পুনরাবৃত্তি করে না, এটি কেবল জেনারেটরটি নিজেই সঞ্চয় করে। আমি যে আচরণটি করতে চাই তা হ'ল numpy.array(list(gimme()))তবে আমি একই সাথে মধ্যবর্তী তালিকা এবং চূড়ান্ত অ্যারে স্মৃতিতে মেমরির ওভারহেড দিতে চাই না। আরও কোনও স্থান-দক্ষ উপায় আছে?


6
এটি একটি আকর্ষণীয় বিষয়। আমি এটি পেরিয়ে এসেছি from numpy import *; print any(False for i in range(1))- যা বিল্ট- ইনকে ছায়া দেয় any()এবং বিপরীত ফলাফল তৈরি করে (যেমনটি আমি এখন জানি)।
moooeeeep

4
পছন্দ করেছেন যদি numpyনা করতে পারেন (অথবা করতে চায় না) আচরণ জেনারেটর হিসেবে পাইথন না, অন্তত এটা ব্যতিক্রম যখন এটি একটি আর্গুমেন্ট হিসাবে একটি জেনারেটর পায় বাড়াতে হবে।
সর্বোচ্চ

1
@ ম্যাক্স আমি ঠিক একই খনিতে পা রেখেছি। স্পষ্টতই এটি NumPy তালিকায় উত্থাপিত হয়েছিল (এবং এর আগে ) এই সিদ্ধান্তে এসেছিল যে ব্যতিক্রম বাড়াতে এটি পরিবর্তন করা হবে না এবং সর্বদা নেমস্পেস ব্যবহার করা উচিত।
আলেক্সেই

উত্তর:


128

অদ্ভুত অ্যারেগুলির জন্য দৈর্ঘ্যের তালিকাগুলির বিপরীতে তাদের দৈর্ঘ্য স্পষ্টভাবে নির্ধারণ করা দরকার। এটি প্রয়োজনীয় কারণ যাতে প্রতিটি আইটেমের জন্য স্থান ক্রমাগত মেমরিতে বরাদ্দ করা যায়। ক্রমাগত বরাদ্দ হ'ল নাম্পার অ্যারেগুলির মূল বৈশিষ্ট্য: এটি স্থানীয় কোড প্রয়োগের সাথে মিলিত হয়ে তাদের উপর নিয়মিত তালিকার চেয়ে দ্রুত কাজ সম্পাদন করে।

এটি মাথায় রেখে, জেনারেটরের কোনও জিনিস নেওয়া এবং এটিতে অ্যারেতে পরিণত করা প্রযুক্তিগতভাবে অসম্ভব: যদি না হয় আপনি:

  1. চালানোর সময় এটি কতটি উপাদান উপার্জন করবে তা অনুমান করতে পারে:

    my_array = numpy.empty(predict_length())
    for i, el in enumerate(gimme()): my_array[i] = el
  2. মধ্যবর্তী তালিকায় এর উপাদানগুলি সংরক্ষণ করতে ইচ্ছুক:

    my_array = numpy.array(list(gimme()))
  3. দুটি অভিন্ন জেনারেটর তৈরি করতে পারে, মোট দৈর্ঘ্য সন্ধান করার জন্য প্রথমটির মধ্য দিয়ে চালানো, অ্যারের সূচনা করতে এবং তারপরে প্রতিটি উপাদান খুঁজে পেতে আবার জেনারেটরের মাধ্যমে চালানো যেতে পারে:

    length = sum(1 for el in gimme())
    my_array = numpy.empty(length)
    for i, el in enumerate(gimme()): my_array[i] = el

1 সম্ভবত আপনি যা খুঁজছেন তা। 2 স্থান অদক্ষ, এবং 3 সময় অদক্ষ (আপনাকে দুবার জেনারেটরের মধ্য দিয়ে যেতে হবে)।


11
অন্তর্নির্মিত array.arrayএকটি সংযোগহীন লিঙ্কযুক্ত তালিকা, এবং আপনি সহজভাবে করতে পারেন array.array('f', generator)। বলা অসম্ভব বলে বিভ্রান্তিকর। এটি কেবল গতিশীল বরাদ্দ।
কুয়াডু

1
নুপি.আরে কেন মেমোরি বরাদ্দ ঠিক তেমনভাবে বিল্টিন অ্যারে.আরে হিসাবে করেন না, যেমন কুয়াদু বলেছে। বাণিজ্য কি? আমি জিজ্ঞাসা করি কারণ উভয় উদাহরণে স্থির বরাদ্দ মেমরি রয়েছে। অথবা না?
jgomo3

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

2
খালি ব্যবহার করা কিছুটা দ্রুত। যেহেতু আপনি মানগুলি যে কোনও উপায়ে শুরু করতে চলেছেন, তাই এটি দুবার করার দরকার নেই।
কৌশিক ঘোষ

নীচে @ hillিলের উত্তরটি দেখুন যা 1 এর চেয়ে দ্রুততর
বিল

206

এই স্ট্যাকওভারফ্লো ফলাফলের পিছনে একটি গুগল, আমি দেখতে পেলাম যে একটি numpy.fromiter(data, dtype, count)। ডিফল্টটি count=-1পুনরাবৃত্তযোগ্য থেকে সমস্ত উপাদান নেয়। এটি একটি dtypeস্পষ্টভাবে সেট করা প্রয়োজন । আমার ক্ষেত্রে, এটি কাজ করেছে:

numpy.fromiter(something.generate(from_this_input), float)


আপনি কিভাবে এই প্রশ্নের প্রয়োগ করবেন? numpy.fromiter(gimme(), float, count=-1)কাজ করে না. কি somethingদাঁড়াবে?
ম্যাথিয়াস 009

1
@ ম্যাথিয়াস009 numpy.fromiter(gimme(), float, count=-1)আমার পক্ষে কাজ করে।
moooeeeep

14
fromiterকেবল 1D অ্যারেগুলিতে কেন কাজ করে তা বোঝানো একটি থ্রেড : mail.scipy.org/pipermail/numpy-discussion/2007-August/…
সর্বাধিক

2
fwiw, count=-1এটি ডিফল্ট হিসাবে নির্দিষ্ট করার দরকার নেই।
জিজ্ঞাসাবাচান

5
যদি আপনি আগে থেকে পুনরাবৃত্তের দৈর্ঘ্যটি জানেন তবে countপারফরম্যান্সটি উন্নত করতে নির্দিষ্ট করুন । এইভাবে চাহিদা পূরণের পরিবর্তে মানগুলি পূরণ করার আগে মেমোরিটিকে বরাদ্দ দেয় (এর ডকুমেন্টেশন দেখুন numpy.fromiter)
এডি

15

আপনি এর সাহায্যে জেনারেটর থেকে 1D অ্যারে numpy.fromiter()তৈরি করতে পারবেন, তবে আপনি এখানে জেনারেটর থেকে একটি এনডি অ্যারে তৈরি করতে পারেন numpy.stack:

>>> mygen = (np.ones((5, 3)) for _ in range(10))
>>> x = numpy.stack(mygen)
>>> x.shape
(10, 5, 3)

এটি 1 ডি অ্যারেগুলির জন্যও কাজ করে:

>>> numpy.stack(2*i for i in range(10))
array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])

নোট যেটি numpy.stackঅভ্যন্তরীণভাবে জেনারেটর গ্রাস করছে এবং এর সাথে একটি মধ্যবর্তী তালিকা তৈরি করছে arrays = [asanyarray(arr) for arr in arrays]। বাস্তবায়ন এখানে পাওয়া যাবে


1
এটি একটি ঝরঝরে সমাধান, নির্দেশ করার জন্য ধন্যবাদ। তবে এটি ব্যবহার করার চেয়ে কিছুটা ধীর (আমার অ্যাপ্লিকেশনটিতে) বলে মনে হচ্ছে np.array(tuple(mygen))। পরীক্ষার ফলাফলগুলি এখানে: %timeit np.stack(permutations(range(10), 7)) 1 loop, best of 3: 1.9 s per loopতুলনায়%timeit np.array(tuple(permutations(range(10), 7))) 1 loop, best of 3: 427 ms per loop
বিল

13
এটি দুর্দান্ত বলে মনে হচ্ছে এবং আমার জন্য কাজ করে। তবে নম্পি 1.16.1 এর সাথে আমি এই সতর্কতাটি পেয়েছি:FutureWarning: arrays to stack must be passed as a "sequence" type such as list or tuple. Support for non-sequence iterables such as generators is deprecated as of NumPy 1.16 and will raise an error in the future.
জোসেফ শেডি

6

কিছুটা স্পর্শকাতর, তবে যদি আপনার জেনারেটর একটি তালিকা উপলব্ধি হয় তবে numpy.whereআপনি আরও কার্যকরভাবে আপনার ফলাফল পেতে ব্যবহার করতে পারেন (আমি এই পোস্টটি দেখার পরে এটি আমার নিজের কোডে আবিষ্কার করেছি)


0

Vstack , hstack এবং dstack ফাংশন ইনপুট জেনারেটর যে উত্পাদ বহু মাত্রিক অ্যারে হিসাবে গ্রহণ করতে পারেন।


3
লিঙ্কগুলি পরিবর্তিত হওয়ার বা কোনও কিছুর ক্ষেত্রে আপনি উদাহরণ দিতে পারেন? :)
এরি কুপার-ডেভিস

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