numpy: быстрое создание массива с разными типами столбцов - PullRequest
0 голосов
/ 09 октября 2018

Я пытаюсь создать повторный массив из серии числовых массивов с именами столбцов и смешанными типами переменных.

Следующее работает, но медленно:

    import numpy as np
    a = np.array([1,2,3,4], dtype=np.int)
    b = np.array([6,6,6,6], dtype=np.int)
    c = np.array([-1.,-2.-1.,-1.], dtype=np.float32)
    d = np.array(list(zip(a,b,c,d)),dtype = [('a',np.int),('b',np.int),('c',np.float32)])
    d = d.view(np.recarray())

Я думаю, что должен быть способ сделать это с помощью np.stack ((a, b, c), axis = -1), который быстрее, чем метод list (zip ()).Тем не менее, кажется, нет тривиального способа наложения с сохранением типов столбцов. Эта ссылка , кажется, показывает, как это сделать, но она довольно неуклюжа, и я надеюсь, что есть лучший способ.

Спасибо за помощь!

Ответы [ 2 ]

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

Вот подход «поле за полем», который я прокомментировал:

In [308]:     a = np.array([1,2,3,4], dtype=np.int)
     ...:     b = np.array([6,6,6,6], dtype=np.int)
     ...:     c = np.array([-1.,-2.,-1.,-1.], dtype=np.float32)
     ...:     dt = np.dtype([('a',np.int),('b',np.int),('c',np.float32)])
     ...: 
     ...: 

(мне пришлось исправить вашу копию n-вставлено c).

In [309]: arr = np.zeros(a.shape, dtype=dt)
In [310]: for name, x in zip(dt.names, [a,b,c]):
     ...:     arr[name] = x
     ...:     
In [311]: arr
Out[311]: 
array([(1, 6, -1.), (2, 6, -2.), (3, 6, -1.), (4, 6, -1.)],
      dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<f4')])

Так как обычномассив будет иметь гораздо больше записей (строк), чем полей, это должно быть быстрее, чем подход списка кортежей.В этом случае он, вероятно, сжимается по скорости.

In [312]: np.array(list(zip(a,b,c)), dtype=dt)
Out[312]: 
array([(1, 6, -1.), (2, 6, -2.), (3, 6, -1.), (4, 6, -1.)],
      dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<f4')])

rec.fromarrays, после некоторой настройки для определения dtype, делает:

_array = recarray(shape, descr)
# populate the record array (makes a copy)
for i in range(len(arrayList)):
    _array[_names[i]] = arrayList[i]

Единственноеспособ использования stack - сначала создать массивы:

In [315]: [np.rec.fromarrays((i,j,k), dtype=dt) for i,j,k in zip(a,b,c)]
Out[315]: 
[rec.array((1, 6, -1.),
           dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<f4')]),
 rec.array((2, 6, -2.),
           dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<f4')]),
 rec.array((3, 6, -1.),
           dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<f4')]),
 rec.array((4, 6, -1.),
           dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<f4')])]
In [316]: np.stack(_)
Out[316]: 
array([(1, 6, -1.), (2, 6, -2.), (3, 6, -1.), (4, 6, -1.)],
      dtype=(numpy.record, [('a', '<i8'), ('b', '<i8'), ('c', '<f4')]))
0 голосов
/ 09 октября 2018

np.rec.fromarrays, вероятно, то, что вы хотите:

>>> np.rec.fromarrays([a, b, c], names=['a', 'b', 'c'])
rec.array([(1, 6, -1.), (2, 6, -2.), (3, 6, -1.), (4, 6, -1.)],
          dtype=[('a', '<i8'), ('b', '<i8'), ('c', '<f4')])
...