Tipos de datos y formatos
Última actualización: 2023-02-07 | Mejora esta página
Tiempo estimado: 45 minutos
El formato de columnas y filas individuales afectará el análisis realizado en un dataset leído en Python. Por ejemplo, no se pueden realizar cálculos matemáticos sobre una secuencia de caracteres (datos con formato de texto). Esto puede parecer obvio, sin embargo, a veces en Python los valores numéricos son leídos como secuencias de caracteres. En esta situación, cuando intentas realizar cálculos con datos numéricos sobre datos formateados como secuencias de caracteres, obtienes un error.
Hoja de ruta
Preguntas
- ¿Qué tipos de datos pueden estar contenidos en un DataFrame?
- ¿Por qué es importante el tipo de datos?
Objetivos
- Describir cómo se almacena la información en un DataFrame de Python.
- Examinar la estructura de un DataFrame.
- Modificar el formato de los valores en un DataFrame.
- Describir cómo los tipos de datos afectan a las operaciones.
- Definir, manipular e interconvertir integers y floats en Python.
- Analizar datasets que tienen valores faltantes/nulos (valores NaN).
- Escribir datos manipulados a un archivo.
En esta lección repasaremos maneras de explorar y comprender mejor la estructura y formato de nuestros datos.
Tipos de Datos
La forma en que se almacena la información en un DataFrame u objeto Python afecta a lo que podemos hacer con él y también a los resultados de los cálculos. Hay dos tipos principales de datos que estaremos explorando en esta lección: tipos de datos numéricos y de texto.
Tipos de Datos Numéricos
Los tipos de datos numéricos incluyen enteros
(integer) y números de punto flotante
(float). Un número de punto flotante tiene puntos
decimales incluso si el valor del punto decimal es 0. Por ejemplo: 1.13,
2.0, 1234.345. Si tenemos una columna que contiene tanto enteros como
números de punto flotante, Pandas asignará el tipo de dato
float
a toda la columna, de modo tal que los puntos
decimales no se pierdan.
Un integer nunca tendrá un punto decimal. Así que,
si quisiéramos almacenar 1.13 como un entero de tipo
integer se almacenará como 1. Del mismo modo, 1234.345
se almacenará como 1234. A menudo, en Python verás el tipo de dato
Int64
que representa un entero de 64 bits. El 64
simplemente se refiere a la memoria asignada para almacenar datos en
cada celda; eso se refiere a la cantidad de dígitos que puede
efectivamente almacenar cada “celda”. Asignar espacio antes de tiempo
permite a las computadoras optimizar el almacenamiento y hacer más
eficiente el procesamiento.
Tipo de Datos de Texto
En Python, el tipo de datos de texto se conoce como secuencia de caracteres (string). En Pandas se los conoce como objetos (object). Las secuencias de caracteres pueden contener números y / o caracteres. Por ejemplo, una secuencia de caracteres puede ser una palabra, una oración, o varias oraciones. Un objeto Pandas también podría ser un nombre de gráfico como ‘plot1’. Una secuencia de caracteres también puede contener o consistir en números. Por ejemplo, ‘1234’ podría ser almacenado como una secuencia de caracteres. También ‘10.23’ podría ser almacenado como secuencia de caracteres. Sin embargo, ¡las las secuencias de caracteres que contienen números no se pueden utilizar en operaciones matemáticas!
Pandas y Python básico utilizan nombres ligeramente diferentes para los tipos de datos. Más sobre esto en la tabla de abajo:
Tipo en Pandas | Tipo en Python Nativo | Descripción |
---|---|---|
object | string | El dtype más general. Será asignado a tu columna si la columna contiene tipos mixtos (números y secuencias de caracteres). |
int64 | int | Caracteres numéricos. 64 se refiere a la memoria asignada para almacenar el caracter. |
float64 | float | Caracteres numéricos con decimales. Si una columna contiene números y NaNs (ver más abajo), Pandas usará float64 por defecto, en caso de que los datos faltantes contengan decimales. |
datetime64, timedelta[ns] | N/D (ver el módulo datetime en la biblioteca estandar de Python) | Valores destinados a contener datos de tiempo. Mira en estos para experimentos con series de tiempo. |
Comprobando el formato de nuestros datos
Ahora que tenemos una comprensión básica de los tipos de datos
numéricos y de texto, exploremos el formato de los datos de nuestra
encuesta. Estaremos trabajando con el mismo dataset
surveys.csv
que hemos usado en lecciones anteriores.
PYTHON
# Ten en cuenta que se usa `pd.read_csv` porque importamos pandas con el alias `pd`
surveys_df = pd.read_csv ("data/surveys.csv")
Recuerda que podemos comprobar el tipo de un objeto de la siguiente manera:
OUTPUT: pandas.core.frame.DataFrame
A continuación, veamos la estructura de datos de nuestras encuestas.
En pandas, podemos comprobar el tipo de datos de una columna en un
DataFrame usando la sintaxis
dataFrameName[column_name].dtype
:
OUTPUT: dtype('O')
Un tipo ‘O’ solo significa “objeto” que en el mundo de Pandas es una secuencia de caracteres (texto).
OUTPUT: dtype('int64')
El tipo int64
nos dice que Python está almacenando cada
valor dentro de esta columna como un entero de 64 bits. Podemos usar el
comando dat.dtypes
para ver el tipo de datos de cada
columna de un DataFrame (todos a la vez).
which returns:
PYTHON
record_id int64
month int64
day int64
year int64
plot_id int64
species_id object
sex object
hindfoot_length float64
weight float64
dtype: object
Ten en cuenta que la mayoría de las columnas en nuestros datos de
encuesta son del tipo int64
. Esto significa que son enteros
de 64 bits. Pero la columna de peso (weight) es un valor de punto
flotante o float
, lo que significa que contiene decimales.
Las columnas species_id
y sex
son objetos, lo
cual significa que contienen secuencias de caracteres
string
.
Trabajando con integers y floats
Así que hemos aprendido que las computadoras almacenan los números de
una de dos maneras: como enteros integer
o como números de
punto flotante float
. Los integers son los
números que usualmente usamos para contar. Los float
tienen parte fraccionaria (decimal). Consideremos ahora cómo el tipo de
datos puede impactar en las operaciones matemáticas entre nuestros
datos. La suma, la resta, la división y la multiplicación funcionan en
float e integer como es de
esperar.
Si dividimos un integer por otro, obtenemos un float. El resultado en Python 3 es diferente al de Python 2, donde el resultado es un integer (porque Python 2 hace una división entera).
También podemos convertir un número de punto flotante en un entero, o un entero en un número de punto flotante. Ten en cuenta que Python redondea por defecto cuando convierte de float a integer.
Trabajando con los datos de nuestra encuesta
Volviendo a nuestros datos, si lo deseamos, podemos modificar el
formato de los valores dentro de nuestros datos. Por ejemplo, podríamos
convertir el campo record_id
a float
PYTHON
# Convertir el campo record_id de integer a float
surveys_df['record_id'] = surveys_df['record_id'].astype('float64')
surveys_df['record_id'].dtype
OUTPUT: dtype('float64')
Desafío - Cambiando tipos
Intenta convertir la columna
plot_id
a float usandoA continuación, intenta convertir
weight
(peso) en un integer. ¿Qué te dice Pandas? ¿Qué es lo que va mal ahí? Más adelante, hablaremos acerca de algunas soluciones a esto.
Valores de datos faltantes o nulos - NaN
¿Qué ocurrió en en el desafío? Ten en cuenta que esto arroja un error de valor:
ValueError: Cannot convert NA to integer
.
Si observamos la columna weight
(peso) de los datos de
las encuestas, notamos que hay valores NaN (Not
a Number) (no es número). Los valores
**NaN ** son valores que no están definidos y que no se pueden
representar matemáticamente. Pandas, por ejemplo, leerá como NaN
aquellas celdas vacías de una hoja CSV o Excel. Los valores NaN tienen
algunas propiedades deseables: si tuviéramos que promediar la columna
weight
(peso) sin reemplazar los valores NaN, Python sabría
saltarse las celdas vacías.
Tratar con valores de datos faltantes siempre es un desafío. A veces es dificil saber por qué faltan valores. ¿Fue debido a un error de entrada de datos? ¿O son datos que alguien no pudo recoger? ¿Debe considerarse el valor como 0? Para tomar buenas decisiones, necesitamos saber qué representan los valores faltantes del dataset. Si tenemos suerte, tendremos algunos metadatos que nos dirán más acerca de cómo fueron manejados los valores nulos.
Por ejemplo, en algunas disciplinas, como el sensado remoto, los valores de datos faltantes suelen definirse como -9999. Tener un montón de valores -9999 en tus datos podría realmente alterar los cálculos numéricos. A menudo, en las hojas de cálculo, las celdas se dejan vacías cuando no hay datos disponibles. Por defecto, Pandas reemplazará esos valores nulos con NaN. Sin embargo, es una buena práctica adquirir el hábito de marcar intencionalmente aquellas celdas que no tienen datos con un valor que represente “sin datos”! De esa manera, en el futuro, no habrá preguntas cuando tu (o alguna otra persona) explore los datos.
¿Dónde están los NaN’s?
Exploremos un poco más los valores NaN en nuestros datos. Usando las herramientas que hemos aprendido en la lección 02, podemos averiguar cuántas filas contienen valores NaN en la columna weight (peso). También, partiendo de nuestros datos, podemos crear un nuevo subconjunto que contenga solamente aquellas filas con peso mayor a cero (es decir, seleccionar valores significativos de peso):
PYTHON
len(surveys_df[pd.isnull(surveys_df.weight)])
# How many rows have weight values?
len(surveys_df[surveys_df.weight> 0])
Usando el método .fillna ()
podemos reemplazar todos los
valores NaN por ceros (después de hacer una copia de
los datos de modo tal de no perder nuestro trabajo):
PYTHON
df1 = surveys_df.copy()
# Completar todos los valores NaN con ceros
df1['weight'] = df1['weight'].fillna(0)
Sin embargo, NaN y cero arrojan diferentes resultados en el análisis. El valor promedio resulta diferente cuando los valores NaN se reemplazan con cero, comparando cuando los valores de NaN son descartados o ignorados.
Podemos completar los valores NaN con cualquier valor que elijamos. El código de abajo completa todos los Valores NaN con un promedio de los pesos.
También podríamos elegir crear un subconjunto de datos, manteniendo solamente aquellas filas que no contienen valores NaN.
La clave es tomar decisiones conscientes acerca de cómo administrar los datos faltantes. Aquí es donde pensamos cómo se utilizarán nuestros datos y cómo estos valores afectarán las conclusiones científicas que se obtengan de los datos.
Python nos brinda todas las herramientas que necesitamos para dar cuenta de estos problemas. Solo debemos ser cautelosos acerca de cómo nuestras decisiones impactan en los resultados científicos.
Desafío - Contando
Cuenta el número de valores perdidos por columna. Sugerencia: el
método .count()
te proporciona el número de observaciones
que no son NA por columna. Examina el método .isnull()
.
Escribiendo datos a CSV
Hemos aprendido a manipular datos para obtener los resultados deseados. Pero también hemos discutido acerca de mantener los datos que han sido manipulados separados de los datos sin procesar. Algo que podríamos estar interesados en hacer es trabajar solo con las columnas que tienen datos completos. Primero, recarguemos los datos para no mezclar todas nuestras manipulaciones anteriores.
A continuación, vamos a eliminar todas las filas que contienen
valores nulos. Usaremos el comando dropna
. De forma
predeterminada, dropna
elimina las columnas que contienen
valores nulos incluso para una sola fila.
Si ahora escribes df_na
, deberías observar que el
DataFrame resultante tiene 30676 filas y 9 columnas,
mucho menos que las 35549 filas originales.
Ahora podemos usar el comando to_csv
para exportar un
DataFrame a formato CSV. Ten en cuenta que el código
que se muestra a continuación por defector guardará los datos en el
directorio de trabajo en el que estamos parados. Podemos guardarlo en
otra carpeta agregando el nombre de la carpeta y una barra inclinada
antes del nombre del archivo:
df.to_csv('foldername/out.csv')
. Usamos
index = False
para que Pandas no incluya el número de
índice para cada fila.
Usaremos este archivo de datos más adelante en el taller. Revisa tu directorio de trabajo para asegurarte de que el CSV se haya guardado correctamente y que puedas abrirlo. Si lo deseas, intenta recuperarlo con Python para asegurarte de que se importa correctamente.
Resumen
Hemos aprendido:
- Cómo explorar los tipos de dato de las colummnas de un DataFrame
- Cómo cambiar el tipo de dato
- Qué son los valores NaN, cómo deberían representarse, y lo que eso significa para tu trabajo
- Cómo reemplazar los valores NaN si así lo quisieras
- Como usar
to_csv
para guardar en un archivo los datos manipulados.
Puntos Clave
- Pandas usa otros nombres para tipos de datos que Python, por
ejemplo:
object
para datos textuales. - Una columna en un DataFrame sólo puede tener un tipo de datos.
- El tipo de datos de la columna de un DataFrame puede ser comprobado
usando
dtype
. - Es necesario tomar decisiones conscientes sobre cómo manejar los datos faltantes.
- Un DataFrame puede ser guardado en un archivo CSV usando la función
to_csv
.