سؤال

كيف يمكنني بناء numpy مجموعة من مولد الكائن ؟

اسمحوا لي توضيح المشكلة:

>>> 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])

في هذا المثال, أعطني() هو المولد الذي خرج أود أن تتحول إلى صفيف.ومع ذلك ، فإن مجموعة منشئ ليس أكثر من تكرار المولد ، فهو ببساطة يخزن مولد نفسها.سلوك أرغب أن من numpy.مجموعة(قائمة(أعطني())), ولكن لا تريد أن تدفع الذاكرة العلوية من وجود وسيط القائمة النهائية المصفوفة في الذاكرة في نفس الوقت.هل هناك مساحة أكبر كفاءة في الطريق ؟

هل كانت مفيدة؟

المحلول

Numpy المصفوفات تتطلب طولها إلى تعيين صراحة في خلق الوقت ، على عكس الثعبان القوائم.وهذا أمر ضروري حتى أن مساحة كل عنصر يمكن أن يكون على التوالي المخصصة في الذاكرة.متتالية تخصيص الميزة الرئيسية numpy المصفوفات:هذا جنبا إلى جنب مع التعليمات البرمجية الأصلية تنفيذ السماح العمليات عليها تنفيذ أسرع بكثير من القوائم العادية.

حفظ هذا في الاعتبار, فمن المستحيل من الناحية التقنية اتخاذ مولد كائن وتحويلها إلى مجموعة إلا إذا كنت إما:

  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 هو الوقت غير فعالة (عليك أن تذهب من خلال مولد مرتين).

نصائح أخرى

واحد جوجل وراء هذه النتيجة ستاكوفيرفلوو، وجدت أن هناك <لأ href = "http://docs.scipy.org/doc/numpy/reference/generated/numpy.fromiter.html" يختلط = "noreferrer" > numpy.fromiter(data, dtype, count) . وcount=-1 الافتراضي يأخذ كل العناصر من iterable. فهو يتطلب dtype التي سيتم تحديدها بشكل واضح. في حالتي، هذا العمل:

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

وبينما يمكنك إنشاء مجموعة 1D من مولد مع numpy.fromiter()، يمكنك إنشاء مجموعة N-D من مولد مع numpy.stack:

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

وكان يعمل أيضا لالمصفوفات 1D:

>>> 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]. يمكن العثور على تنفيذ هنا .

وعرضية إلى حد ما، ولكن إذا المولدات الخاصة بك هي قائمة على الفهم، يمكنك استخدام numpy.where للحصول على نحو أكثر فعالية نتيجة الخاص بك (لقد اكتشفت هذا في التعليمات البرمجية الخاصة بي بعد رؤية هذه الوظيفة)

vstack ، hstack ، و <أ href ل = "https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.dstack.html" يختلط = "نوفولو noreferrer"> dstack يمكن ظائف تستغرق ومولدات المدخلات التي العائد المصفوفات متعددة الأبعاد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top