объединить numy массивы, которые являются атрибутами экземпляра класса в python - PullRequest
1 голос
/ 09 февраля 2012

Я пытаюсь использовать класс, который объединяет несколько экземпляров другого класса в виде массива объектов.Я хочу иметь возможность объединять атрибуты экземпляров, которые содержатся в массиве NumPy.Я придумал неаккуратный способ сделать это с помощью множества циклов for, но я думаю, что должен быть более изящный, питонский способ сделать это.Следующий код выполняет то, что я хочу, но я хочу знать, есть ли более чистый способ сделать это:

import numpy as np


class MyClass(object):

    def __init__(self):
        self.a = 37.
        self.arr = np.arange(5)


class MyClasses(object):

    def __init__(self):
        self.N = 5 
        # number of MyClass instances to become attributes of this
    # class 

    def make_subclas_arrays(self):
        self.my_class_inst = np.empty(shape=self.N, dtype="object") 
        for i in range(self.N):
            self.my_class_inst[i] = MyClass()

    def concatenate_attributes(self):
        self.a = np.zeros(self.N)
        self.arr = np.zeros(self.N * self.my_class_inst[0].arr.size)
        for i in range(self.N):
            self.a[i] = self.my_class_inst[i].a
            slice_start = i * self.my_class_inst[i].arr.size
            slice_end = (i + 1.) * self.my_class_inst[i].arr.size
            self.arr[slice_start:slice_end] = ( 
        self.my_class_inst[i].arr )

my_inst = MyClasses()
my_inst.make_subclas_arrays()
my_inst.concatenate_attributes()

Редактировать: Основываясь на ответе HYRY, вот как методы выглядят сейчас:

def make_subclass_arrays(self):
    self.my_class_inst = np.array([MyClass() for i in range(self.N)])

def concatenate_attributes(self):
    self.a = np.hstack([i.a for i in self.my_class_inst])
    self.arr = np.hstack([i.arr for i in self.my_class_inst])

Ответы [ 2 ]

1 голос
/ 10 февраля 2012

вы можете использовать numpy.hstack () для объединения массивов:

def concatenate_attributes(self):
    self.a = np.hstack([o.a for o in self.my_class_inst])
    self.arr = np.hstack([o.arr for o in self.my_class_inst])

См. Также

vstack: укладывать массивы в последовательности по вертикали (по строкам). dstack: укладывать массивы в последовательности по глубине (вдоль третьей оси). concatenate: объединить последовательность массивов.

1 голос
/ 10 февраля 2012

Для последней функции я бы порекомендовал:

init = []
ContainerClass.arr = np.array([init + Array(myclass.arr) for myclass in self.my_class_inst])

преобразовать массив numpy в обычный массив, создать и вернуть его обратно.Предположим теперь, что у вас есть простые одномерные массивы.Я не помню наизусть, есть ли в массиве numpy функция сцепления.Вы можете использовать это вместо знака «+» и избавить от необходимости приведения типов.

Для первого у вас есть самая простая форма, которую я могу себе представить, хотя я обычно использую обычные массивы вместо пустых для объектов.

Если вы хотите быть действительно умным, вы можете создать функцию __add__ для обоих классов.Затем вы можете использовать знак «+» для добавления классов.a + b звонки a.__add__(b).Теперь вам нужно будет создать функции, которые имеют следующие свойства

  1. MyClass + MyClass возвращает новый экземпляр MyClasses с a и b внутри
  2. MyClasses + MyClass добавляет MyClass в MyClasses так, как вы хотите

Теперь, если a, b, c, d являются экземплярами myClass, a+b+c+d должен возвращать MyClasses -class, который содержит экземпляры MyClass a, b, c и d и их комбинированные массивы.Это был бы питонический способ, хотя на мой вкус он слишком сложен.

edit:

Хорошо, извините, мой плохой.У меня не было Python, когда я написал код.Это правильная версия:

init = []
my_inst.arr = np.array([init + list(myclass.arr.flat) for myclass in my_inst.my_class_inst]).flatten()

Вот что я имел в виду под __add__ (и питонским способом ... независимо от его сложности):

import numpy as np

class MyClass(object):

    def __init__(self):
        self.a = 37.
        self.arr = np.arange(5)

    def __add__(self, classToAdd):
        a = MyClasses() + self + classToAdd
        return a


class MyClasses(object):

    def __init__(self):
        self.N = 0
        self.my_class_inst = np.array([])
        self.a = np.array([])
        self.arr = np.array([])

    def __add__(self, singleClass):
        self.my_class_inst = np.hstack([self.my_class_inst, singleClass])
        self.a = np.hstack([self.a, singleClass.a])
        self.arr = np.hstack([self.arr, singleClass.arr])
        self.N = self.my_class_inst.shape[0]
        return self

#add_test = MyClass() + MyClass()
add_test = np.sum([MyClass() for i in range(5)])

print add_test.a, add_test.arr, add_test.N
print add_test.__class__, add_test.my_class_inst[0].__class__
...