2015-09-28 3 views
2

Я ищу какую-то парадигму или реализацию, чтобы эффективно обрабатывать множество наборов связанных N-мерных массивов (ndarray). В частности, я надеюсь на реализацию, которая позволяет мне нарезать массив целых объектов (например, someObjs = objects[100:200]) или отдельные атрибуты этих объектов (например, somePars1 = objects.par1[100:200]) --- в то же время., объединяющий функции «массив объектов» с «объектом массивов»

Для расширения на приведенном выше примере, я мог бы построить следующие подмножества двумя способами:

def subset1(objects, beg, end): 
    pars1 = [ obj.par1 for obj in objects[beg:end] ] 
    pars2 = [ obj.par2 for obj in objects[beg:end] ] 
    return pars1, pars2 

def subset2(objects, beg, end): 
    pars1 = objects.par1[beg:end] 
    pars2 = objects.par2[beg:end] 
    return pars1, pars2 

И они будут идентичны.


Edit:

Один подход был бы переопределить __getitem__ (и т.д.) методы, что-то подобное,

class Objects(object): 
    def __init__(self, p1, p2): 
     self.par1 = p1 
     self.par2 = p2 
    ... 
    def __getitem__(self, key): 
     return Objects(self.p1[key], self.p2[key]) 

Но это ужасно неэффективно, и он дублирует подмножество. Возможно, есть способ вернуть view подмножества?

+1

Я не совсем понял вопрос. Вы пытаетесь найти язык, который позволяет разместить индекс в любой из этих позиций? Это противоречит структуре большинства языков. Если у вас есть список объектов, выражение индекса * должно * быть применено непосредственно к списку, а не к элементу. Ваш код правильный в любом случае, в зависимости от того, как вы проектируете свои объекты. Однако вы не можете иметь эту двойственную природу на языке, который отличает характеристики типа. – Prune

+0

@Prune, я не думаю, что это так. См. Пример, который я добавил. Достижение этой функциональности, безусловно, возможно ... но я не могу придумать, как эффективно или эффективно делать это. – DilithiumMatrix

+0

Теперь я понимаю; Благодарю. Имейте в виду, что это по своей сути неэффективно: вы принимаете естественную структуру, но затем накладываете на нее искусственную структуру. Каждая ссылка на искусственную структуру - вид, который вы хотите - требует демонтажа и переупорядочения элементов «правильной» организации. Однако шаблон просмотра, скорее всего, будет способностью к обслуживанию. Я не знаю, говорит ли это вам что-то новое; Скорее всего, я просто подкрепляю то, чего вы боялись. – Prune

ответ

2

массив объектов и объект с подходом массива

Образец объект класса

In [56]: class MyObj(object): 
    ....:  def __init__(self, par1,par2): 
    ....:   self.par1=par1 
    ....:   self.par2=par2 

Массив из этих объектов - немного больше, чем список с массивом обертки

In [57]: objects=np.array([MyObj(1,2),MyObj(3,4),MyObj(2,3),MyObj(10,11)]) 
In [58]: objects 
Out[58]: 
array([<__main__.MyObj object at 0xb31b196c>, 
     <__main__.MyObj object at 0xb31b116c>, 
     <__main__.MyObj object at 0xb31b13cc>, 
     <__main__.MyObj object at 0xb31b130c>], dtype=object) 

`подмножество`` выбор:

In [59]: [obj.par1 for obj in objects[1:-1]] 
Out[59]: [3, 2] 

Другой класс, который может содержать такой массив. Это проще, чем определение подкласса массива:

In [60]: class MyObjs(object): 
    ....:  def __init__(self,anArray): 
    ....:   self.data=anArray 
    ....:  def par1(self): 
    ....:   return [obj.par1 for obj in self.data] 

In [61]: Obs = MyObjs(objects) 
In [62]: Obs.par1() 
Out[62]: [1, 3, 2, 10] 

subset2 тип выбора:

In [63]: Obs.par1()[1:-1] 
Out[63]: [3, 2] 

Сейчас par1 является метод, но может сделал свойство, что позволяет Obs.par1[1:-1] синтаксис.

Если par1 вернул массив вместо списка, индексирование будет более мощным.

Если MyObjs был метод __getitem__, то он может быть проиндексирован с

Obs[1:-1] 

Этот метод может быть определен различными способами, хотя проще всего применить индексирование «срез» в «данные»:

def __getitem__(self, *args): 
    # not tested 
    return MyObjs(self.data.__getitem(*args)) 

Я фокусируюсь только на синтаксисе, а не на эффективности. В общем случае массивы numpy общих объектов не очень быстрые или мощные. Такие массивы - это в основном списки указателей на объекты.

Структурированная массив и recarray версия

Другой Possiblity является np.recarray. Другой плакат просто спрашивал об их именах. Они по существу являются структурированным массивом, в котором поля могут быть доступны как атрибуты.

С структурированным определением массива:

In [64]: dt = np.dtype([('par1', int), ('par2', int)]) 
In [66]: Obj1 = np.array([(1,2),(3,4),(2,3),(10,11)], dtype=dt) 
In [67]: Obj1 
Out[67]: 
array([(1, 2), (3, 4), (2, 3), (10, 11)], 
     dtype=[('par1', '<i4'), ('par2', '<i4')]) 
In [68]: Obj1['par1'][1:-1] 
Out[68]: array([3, 2]) 
In [69]: Obj1[1:-1]['par1'] 
Out[69]: array([3, 2]) 

или recarray

In [79]: Objrec=np.rec.fromrecords(Obj1,dtype=dt) 
In [80]: Objrec.par1 
Out[80]: array([ 1, 3, 2, 10]) 
In [81]: Objrec.par1[1:-1] 
Out[81]: array([3, 2]) 
In [82]: Objrec[1:-1].par1 
Out[82]: array([3, 2]) 
+0

Решение 'recarray' выглядит фантастически! Мне нужно немного поиграть с этим, но я думаю, что это будет прекрасно. Спасибо! – DilithiumMatrix

Смежные вопросы