Как изменить dtype некоторых столбцов numy recarray? - PullRequest
11 голосов
/ 30 марта 2012

Предположим, у меня есть повторный массив, например:

import numpy as np

# example data from @unutbu's answer
recs = [('Bill', '31', 260.0), ('Fred', 15, '145.0')]
r = np.rec.fromrecords(recs, formats = 'S30,i2,f4', names = 'name, age, weight')

print(r)
# [('Bill', 31, 260.0) ('Fred', 15, 145.0)]

Скажем, я хочу преобразовать определенные столбцы в числа с плавающей точкой. Как мне это сделать? Должен ли я перейти на ndarray, а их обратно в recarray?

Ответы [ 3 ]

16 голосов
/ 30 марта 2012

Вот пример использования astype для выполнения преобразования:

import numpy as np
recs = [('Bill', '31', 260.0), ('Fred', 15, '145.0')]
r = np.rec.fromrecords(recs, formats = 'S30,i2,f4', names = 'name, age, weight')
print(r)
# [('Bill', 31, 260.0) ('Fred', 15, 145.0)]

age имеет тип d <i2:

print(r.dtype)
# [('name', '|S30'), ('age', '<i2'), ('weight', '<f4')]

Мы можем изменить это<f4 с использованием astype:

r = r.astype([('name', '|S30'), ('age', '<f4'), ('weight', '<f4')])
print(r)
# [('Bill', 31.0, 260.0) ('Fred', 15.0, 145.0)]
13 голосов
/ 05 апреля 2012

Есть в основном два шага. Моим камнем преткновения было найти способ изменить существующий dtype. Вот как я это сделал:

# change dtype by making a whole new array
dt = data.dtype
dt = dt.descr # this is now a modifiable list, can't modify numpy.dtype
# change the type of the first col:
dt[0] = (dt[0][0], 'float64')
dt = numpy.dtype(dt)
# data = numpy.array(data, dtype=dt) # option 1
data = data.astype(dt)
0 голосов
/ 20 сентября 2018

Это небольшое уточнение существующих ответов, а также расширение ситуаций, в которых вы хотите внести изменение на основе dtype, а не имени столбца (например, изменить все числа с плавающей точкой на целые числа).

Во-первых,Вы можете улучшить краткость и удобочитаемость, используя listcomp:

col       = 'age'
new_dtype = 'float64'

r.astype( [ (col, new_dtype) if d[0] == col else d for d in r.dtype.descr ] )

# rec.array([(b'Bill', 31.0, 260.0), (b'Fred', 15.0, 145.0)], 
#           dtype=[('name', 'S30'), ('age', '<f8'), ('weight', '<f4')])

Во-вторых, вы можете расширить этот синтаксис для обработки случаев, когда вы хотите изменить все числа с плавающей точкой на целые (или наоборот).Например, если вы хотите изменить любое 32- или 64-битное число с плавающей точкой на 64-битное целое, вы можете сделать что-то вроде:

old_dtype = ['<f4', '<f8']
new_dtype = 'int64'

r.astype( [ (d[0], new_dtype) if d[1] in old_dtype else d for d in r.dtype.descr ] )

# rec.array([(b'Bill', 31, 260), (b'Fred', 15, 145)], 
#           dtype=[('name', 'S30'), ('age', '<i2'), ('weight', '<i8')])

Обратите внимание, что astype имеет необязательный аргумент приведения, который по умолчанию равен unsafe поэтому вы можете указать casting='safe', чтобы избежать случайной потери точности при приведении чисел к числу с плавающей точкой:

r.astype( [ (d[0], new_dtype) if d[1] in old_dtype else d for d in r.dtype.descr ],
          casting='safe' )

Более подробную информацию о casting можно найти в документации numpy для astype идругие параметры.

Также обратите внимание, что для общих случаев изменения чисел с плавающей точкой на целые числа или наоборот вы можете предпочесть проверять общий тип чисел с помощью np.issubdtype, а не проверять несколько разных типов dtypes.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...