Конвертировать структурированный массив в обычный массив NumPy
Думаю, ответ будет очень очевидным, но я не вижу его сейчас.
Как я могу преобразовать массив записей обратно в обычный ndarray?
Предположим, у меня есть следующий простой структурированный массив:
x = np.array([(1.0, 4.0,), (2.0, -1.0)], dtype=[('f0', '<f8'), ('f1', '<f8')])
тогда я хочу преобразовать это в:
array([[ 1., 4.],
[ 2., -1.]])
Я старался asarray
а также astype
, но это не сработало.
ОБНОВЛЕНИЕ (решено: float32 (f4) вместо float64 (f8))
Ок, я попробовал решение Роберта (x.view(np.float64).reshape(x.shape + (-1,))
), и с простым массивом это работает отлично. Но с массивом, который я хотел преобразовать, он дает странный результат:
data = np.array([ (0.014793682843446732, 0.006681123282760382, 0.0, 0.0, 0.0, 0.0008984912419691682, 0.0, 0.013475529849529266, 0.0, 0.0),
(0.014793682843446732, 0.006681123282760382, 0.0, 0.0, 0.0, 0.0008984912419691682, 0.0, 0.013475529849529266, 0.0, 0.0),
(0.014776384457945824, 0.006656022742390633, 0.0, 0.0, 0.0, 0.0008901208057068288, 0.0, 0.013350814580917358, 0.0, 0.0),
(0.011928378604352474, 0.002819152781739831, 0.0, 0.0, 0.0, 0.0012627150863409042, 0.0, 0.018906937912106514, 0.0, 0.0),
(0.011928378604352474, 0.002819152781739831, 0.0, 0.0, 0.0, 0.001259754877537489, 0.0, 0.01886274479329586, 0.0, 0.0),
(0.011969991959631443, 0.0028706740122288465, 0.0, 0.0, 0.0, 0.0007433745195157826, 0.0, 0.011164642870426178, 0.0, 0.0)],
dtype=[('a_soil', '<f4'), ('b_soil', '<f4'), ('Ea_V', '<f4'), ('Kcc', '<f4'), ('Koc', '<f4'), ('Lmax', '<f4'), ('malfarquhar', '<f4'), ('MRN', '<f4'), ('TCc', '<f4'), ('Vcmax_3', '<f4')])
а потом:
data_array = data.view(np.float).reshape(data.shape + (-1,))
дает:
In [8]: data_array
Out[8]:
array([[ 2.28080997e-20, 0.00000000e+00, 2.78023241e-27,
6.24133580e-18, 0.00000000e+00],
[ 2.28080997e-20, 0.00000000e+00, 2.78023241e-27,
6.24133580e-18, 0.00000000e+00],
[ 2.21114197e-20, 0.00000000e+00, 2.55866881e-27,
5.79825816e-18, 0.00000000e+00],
[ 2.04776835e-23, 0.00000000e+00, 3.47457730e-26,
9.32782857e-17, 0.00000000e+00],
[ 2.04776835e-23, 0.00000000e+00, 3.41189244e-26,
9.20222417e-17, 0.00000000e+00],
[ 2.32706550e-23, 0.00000000e+00, 4.76375305e-28,
1.24257748e-18, 0.00000000e+00]])
который является массивом с другими числами и другой формой. Что я сделал не так?
3 ответа
[~]
|5> x = np.array([(1.0, 4.0,), (2.0, -1.0)], dtype=[('f0', '<f8'), ('f1', '<f8')])
[~]
|6> x.view(np.float64).reshape(x.shape + (-1,))
array([[ 1., 4.],
[ 2., -1.]])
Самый простой метод, вероятно,
x.view((float, len(x.dtype.names)))
(float
должен быть заменен типом элементов в x
: x.dtype[0]
). Это предполагает, что все элементы имеют одинаковый тип.
Этот метод дает вам регулярный numpy.ndarray
версия за один шаг (в отличие от двух шагов, требуемых view(…).reshape(…)
метод.
В сочетании с изменениями в том, как он обрабатывает многополевую индексацию numpy
предоставил две новые функции, которые могут помочь в преобразовании в / из структурированных массивов:
В numpy.lib.recfunctions
, Эти structured_to_unstructured
а также unstructured_to_structured
. repack_fields
еще одна новая функция.
Из 1.16
примечания к выпуску
представления с несколькими полями возвращают представление вместо копии
Индексирование структурированного массива с несколькими полями, например, arr[['f1', 'f3']], возвращает представление в исходный массив вместо копии. Возвращенное представление часто будет иметь дополнительные байты заполнения, соответствующие промежуточным полям в исходном массиве, в отличие от предыдущего, что повлияет на такой код, как arr[['f1', 'f3']]. View('float64'). Это изменение было запланировано с версии 1.7. С тех пор операции, попавшие в этот путь, посылают FutureWarnings. Дополнительные предупреждения FutureWarnings об этом изменении были добавлены в 1.12.
Чтобы помочь пользователям обновить свой код с учетом этих изменений, в модуль numpy.lib.recfunctions добавлен ряд функций, которые безопасно разрешают такие операции. Например, приведенный выше код можно заменить на structured_to_unstructured(arr[['f1', 'f3']], dtype='float64'). См. Раздел "Доступ к нескольким полям" в руководстве пользователя.
np.array(x.tolist())
array([[ 1., 4.],
[ 2., -1.]])
но, может быть, есть лучший метод...
Очень простое решение, используя функцию rec2array из root_numpy:
np_array = rec2array(x)
root_numpy фактически устарел, но код rec2array в любом случае полезен (источник здесь):
def rec2array(rec, fields=None):
simplify = False
if fields is None:
fields = rec.dtype.names
elif isinstance(fields, string_types):
fields = [fields]
simplify = True
# Creates a copy and casts all data to the same type
arr = np.dstack([rec[field] for field in fields])
# Check for array-type fields. If none, then remove outer dimension.
# Only need to check first field since np.dstack will anyway raise an
# exception if the shapes don't match
# np.dstack will also fail if fields is an empty list
if not rec.dtype[fields[0]].shape:
arr = arr[0]
if simplify:
# remove last dimension (will be of size 1)
arr = arr.reshape(arr.shape[:-1])
return arr