¿Cómo cambiar el dtype de ciertas columnas de un recarray numpy?

Supongamos que tengo una revisión como la siguiente:

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)] 

Digamos que quiero convertir ciertas columnas a flotadores. ¿Cómo hago esto? ¿Debo cambiar a un ndarray y volver a un recarray?

Aquí hay un ejemplo que usa astype para realizar la conversión:

 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)] 

La age es de dtype :

 print(r.dtype) # [('name', '|S30'), ('age', ' 

Podemos cambiar eso a usando astype :

 r = r.astype([('name', '|S30'), ('age', ' 

Básicamente hay dos pasos. Mi obstáculo fue encontrar la forma de modificar un dtype existente. Así es como lo hice:

 # 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) 

Aquí hay un pequeño refinamiento de las respuestas existentes, más una extensión para situaciones en las que desea realizar un cambio basado en el tipo de dtype en lugar del nombre de la columna (por ejemplo, cambiar todos los flotantes a números enteros).

Primero, puede mejorar la concisión y la legibilidad utilizando una lista comp:

 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', ' 

En segundo lugar, puede ampliar esta syntax para controlar los casos en los que desea cambiar todos los flotantes a enteros (o viceversa). Por ejemplo, si desea cambiar cualquier flotante de 32 o 64 bits a un entero de 64 bits, podría hacer algo como:

 old_dtype = [' 

Tenga en cuenta que astype tiene un argumento de conversión opcional que por defecto es unsafe por lo que es posible que desee especificar casting='safe' para evitar perder accidentalmente la precisión cuando la conversión de casillas a enteros:

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

Consulte la documentación de números en astype para obtener más información sobre el casting y otras opciones.

También tenga en cuenta que para los casos generales de cambio de flotadores a enteros o viceversa, es posible que prefiera verificar el tipo de número general con np.issubdtype lugar de verificar contra múltiples tipos de dipo específicos.