Оптимальная генерация numy ассоциативного массива с подрешетками и переменной длины - PullRequest
0 голосов
/ 13 октября 2018

У меня есть данные, сгенерированные Python, типа

fa      fb      fc
fa1     fb1     [fc01, fc02,..., fc0m]
fa2     fb2     [fc11, fc12,..., fc1m]
...     ...     ...
fan     fbn     [fcn1, fcn2,..., fcnm]

Мне нужно создать Python-совместимую структуру данных для ее хранения, максимально упростить создание и минимизировать использование памяти и время чтения / записи.,Мне нужно иметь возможность идентифицировать столбцы по именам полей (т.е. получить fa1 с чем-то вроде data['fa'][0]).fa значения являются целыми числами, а fb и fc являются числами с плавающей запятой.Ни m, ни n не известны до времени выполнения, но известны до вставки данных в структуру данных и не изменяются.m не будет превышать 1000, а n не будет превышать 10000. Данные генерируются по одной строке за раз.

До сих пор я использовал непрямой ассоциативный массив asardtype=[('f0,'i2'), ('f1','f8'), ('f2', 'f8', (m))].Однако, поскольку я не могу просто добавить новую строку в массив NumPy без удаления и повторного ее создания при каждом добавлении строки, я использую отдельную переменную подсчета ind_n, создавая asar с asar = numpy.zeroes(n, dtype=dtype),перезаписывая нули asar[ind_n] добавляемыми данными, затем увеличивая ind_n, пока не достигнет n.Это работает, но кажется, что должно быть лучшее решение (или хотя бы одно, которое позволяет мне исключить ind_n).Есть ли стандартный способ создать каркас из asar (возможно, с чем-то вроде np.zeroes()), а затем вставить каждую строку данных в первую ненулевую строку?Или способ преобразовать стандартный вложенный список Python в ассоциативный массив после того, как вложенный список будет полностью сгенерирован?(Я знаю, что это преобразование определенно можно сделать, но у меня возникают проблемы (например, ValueError: setting an array element with a sequence.) при преобразовании подмассива, когда я пытаюсь его выполнить.)

Ответы [ 2 ]

0 голосов
/ 14 октября 2018
In [39]: n, m = 5, 3
In [41]: dt=np.dtype([('f0','i2'), ('f1','f8'), ('f2', 'f8', (m))])

In [45]: asar = np.zeros(n, dt)
In [46]: asar
Out[46]: 
array([(0, 0., [0., 0., 0.]), (0, 0., [0., 0., 0.]),
       (0, 0., [0., 0., 0.]), (0, 0., [0., 0., 0.]),
       (0, 0., [0., 0., 0.])],
      dtype=[('f0', '<i2'), ('f1', '<f8'), ('f2', '<f8', (3,))])

Заполнение по полю:

In [49]: asar['f0'] = np.arange(5)
In [50]: asar['f1'] = np.random.rand(5)
In [51]: asar['f2'] = np.random.rand(5,3)
In [52]: asar
Out[52]: 
array([(0, 0.45120412, [0.86481761, 0.08861093, 0.42212446]),
       (1, 0.63926708, [0.43788684, 0.89254029, 0.90637292]),
       (2, 0.33844457, [0.80352251, 0.25411018, 0.315124  ]),
       (3, 0.24271258, [0.27849709, 0.9905879 , 0.94155558]),
       (4, 0.89239324, [0.1580938 , 0.52844036, 0.59092695])],
      dtype=[('f0', '<i2'), ('f1', '<f8'), ('f2', '<f8', (3,))])

Создание списка с соответствующей вложенностью:

In [53]: alist = [(i,i,[10]*3) for i in range(5)]
In [54]: np.array(alist, dt)
Out[54]: 
array([(0, 0., [10., 10., 10.]), (1, 1., [10., 10., 10.]),
       (2, 2., [10., 10., 10.]), (3, 3., [10., 10., 10.]),
       (4, 4., [10., 10., 10.])],
      dtype=[('f0', '<i2'), ('f1', '<f8'), ('f2', '<f8', (3,))])

Очевидно, что вы можете сделать:

for i, row in enumerate(alist):
    asar[i] = row

enumerate - хороший идиоматический способ создания индекса вместе со значением.Но тогда это так же range(n).

0 голосов
/ 13 октября 2018

Если вы знаете n во время создания первой записи, ваше решение по существу правильно.

Вы можете использовать np.empty вместо np.zeros, экономя немного (но не много) времени.

Если вам не нравится ind_n, вы можете вместо этого создать итератор массива.

>>> m = 5
>>> n = 7
>>> dt = [('col1', 'i2'), ('col2', float), ('col3', float, (m,))]
>>> data = [(np.random.randint(10), np.random.random(), np.random.random((m,))) for _ in range(n)]
>>> 
>>> rec = np.empty((n,), dt)
>>> irec = np.nditer(rec, op_flags=[['readwrite']], flags=['c_index'])
>>> 
>>> for src in data:
...     # roughly equivalent to list.append:
...     next(irec)[()] = src
...     print()
...     # getting the currently valid part:
...     print(irec.operands[0][:irec.index+1])
... 

[(9, 0.07368308, [0.44691665, 0.38875103, 0.83522137, 0.39281718, 0.62078615])]

[(9, 0.07368308, [0.44691665, 0.38875103, 0.83522137, 0.39281718, 0.62078615])
 (6, 0.82350335, [0.57971597, 0.61270304, 0.05280996, 0.03702404, 0.99159465])]

[(9, 0.07368308, [0.44691665, 0.38875103, 0.83522137, 0.39281718, 0.62078615])
 (6, 0.82350335, [0.57971597, 0.61270304, 0.05280996, 0.03702404, 0.99159465])
 (3, 0.06565234, [0.88921842, 0.21097122, 0.83276431, 0.01824657, 0.49105466])]

[(9, 0.07368308, [0.44691665, 0.38875103, 0.83522137, 0.39281718, 0.62078615])
 (6, 0.82350335, [0.57971597, 0.61270304, 0.05280996, 0.03702404, 0.99159465])
 (3, 0.06565234, [0.88921842, 0.21097122, 0.83276431, 0.01824657, 0.49105466])
 (2, 0.69806099, [0.87749632, 0.22119474, 0.25623813, 0.26587436, 0.04772489])]

[(9, 0.07368308, [0.44691665, 0.38875103, 0.83522137, 0.39281718, 0.62078615])
 (6, 0.82350335, [0.57971597, 0.61270304, 0.05280996, 0.03702404, 0.99159465])
 (3, 0.06565234, [0.88921842, 0.21097122, 0.83276431, 0.01824657, 0.49105466])
 (2, 0.69806099, [0.87749632, 0.22119474, 0.25623813, 0.26587436, 0.04772489])
 (1, 0.77573727, [0.44359522, 0.62471617, 0.65742177, 0.38889958, 0.13901824])]

[(9, 0.07368308, [0.44691665, 0.38875103, 0.83522137, 0.39281718, 0.62078615])
 (6, 0.82350335, [0.57971597, 0.61270304, 0.05280996, 0.03702404, 0.99159465])
 (3, 0.06565234, [0.88921842, 0.21097122, 0.83276431, 0.01824657, 0.49105466])
 (2, 0.69806099, [0.87749632, 0.22119474, 0.25623813, 0.26587436, 0.04772489])
 (1, 0.77573727, [0.44359522, 0.62471617, 0.65742177, 0.38889958, 0.13901824])
 (0, 0.45797521, [0.79193395, 0.69029592, 0.0541346 , 0.49603146, 0.36146384])]

[(9, 0.07368308, [0.44691665, 0.38875103, 0.83522137, 0.39281718, 0.62078615])
 (6, 0.82350335, [0.57971597, 0.61270304, 0.05280996, 0.03702404, 0.99159465])
 (3, 0.06565234, [0.88921842, 0.21097122, 0.83276431, 0.01824657, 0.49105466])
 (2, 0.69806099, [0.87749632, 0.22119474, 0.25623813, 0.26587436, 0.04772489])
 (1, 0.77573727, [0.44359522, 0.62471617, 0.65742177, 0.38889958, 0.13901824])
 (0, 0.45797521, [0.79193395, 0.69029592, 0.0541346 , 0.49603146, 0.36146384])
 (6, 0.85225039, [0.62028917, 0.4895316 , 0.00922578, 0.66836154, 0.53082779])]
...