Python en Español

Tutorial de loadtxt de NumPy( cargar datos de los archivos)

En un tutorial anterior, hablamos sobre los arreglos NumPy, y vimos cómo hace que el proceso de lectura, análisis y operaciones de datos numéricos sea pan comido. En este tutorial, discutiremos el método de loadtxt NumPy que se utiliza para analizar los datos de los archivos de texto y almacenarlos en una matriz NumPy de n dimensiones.

Entonces podemos realizar todo tipo de operaciones sobre él que son posibles en una matriz NumPy.

np.loadtxt ofrece mucha flexibilidad en la forma en que leemos los datos de un archivo especificando opciones como el tipo de datos de la matriz resultante, cómo distinguir una entrada de datos de las demás mediante delimitadores, omitiendo/incluyendo filas específicas, etc. Examinaremos cada una de esas formas en el siguiente tutorial.

 

 

Especificar el camino del archivo

Veamos cómo podemos especificar la ruta del archivo del que queremos leer los datos.

Usaremos un archivo de texto de muestra para nuestros ejemplos de códigos, que enumera los pesos (en kg) y alturas (en cm) de 100 individuos, cada uno en una fila.

Utilizaré varias variantes de este archivo para explicar las diferentes características de la función loadtxt.

Comencemos con la representación más simple de los datos en un archivo de texto. Tenemos 100 líneas (o filas) de datos en nuestro archivo de texto, cada una de las cuales comprende dos números de punto flotante separados por un espacio.

El primer número de cada fila representa el peso, y el segundo número representa la altura de un individuo.

Aquí hay un pequeño vistazo del archivo:

110.90 146.03
44.83 211.82
97.13 209.30
105.64 164.21

Este archivo es almacenado como `weight_height_1.txt`.
Nuestra tarea es leer el archivo y analizar los datos de manera que podamos representarlos en una matriz NumPy.

Importaremos el paquete NumPy y llamaremos al método loadtxt, pasando la ruta del archivo como valor al primer parámetro filePath.

import numpy as np

data = np.loadtxt("./weight_height_1.txt")

Aquí estamos asumiendo que el archivo está almacenado en la misma ubicación desde donde nuestro código Python se ejecutará (‘./’ represents current directory). Si no es así, necesitamos especificar la ruta completa del archivo (Ex: “C://Users/John/Desktop/weight_height_1.txt”)

También tenemos que asegurarnos de que cada fila del archivo tenga el mismo número de valores.

La extensión del archivo puede ser cualquier otra que no sea .txt siempre y cuando el archivo contenga texto, también podemos pasar un generador en lugar de una ruta de archivo (más sobre eso más adelante)

La función devuelve una matriz n-dimensional NumPy de valores encontrados en el texto.

Aquí nuestro texto tenía 100 filas con cada una de ellas con dos valores de flotación, por lo que los datos de objeto devueltos serán una matriz NumPy de forma (100, 2) con el tipo de datos de flotación.

Puedes verificarlo comprobando los atributos “shape” y “dtype” de los datos devueltos:

print("shape of data:",data.shape)

print("datatype of data:",data.dtype)

Salida:
Especificar el camino del archivo

Especificar delimitadores

Un delimitador es un carácter o una cadena de caracteres que separa valores individuales en una línea.

Por ejemplo, en nuestro archivo anterior, teníamos los valores separados por un espacio, por lo que, en ese caso, el delimitador era un carácter de espacio (“”).

Sin embargo, algunos otros archivos pueden tener un delimitador diferente; por ejemplo, los archivos CSV suelen utilizar la coma (“,”) como delimitador. Otro archivo puede tener un punto y coma como delimitador.

Por lo tanto, necesitamos que nuestro cargador de datos sea lo suficientemente flexible como para identificar esos delimitadores en cada fila y extraer de ellos los valores correctos.

Esto puede lograrse pasando nuestro delimitador como parámetro a la función np.loadtxt.

Vamos a considerar otro archivo ‘weight_height_2.txt’, tiene el mismo contenido de datos que el anterior, pero esta vez los valores en cada fila están separados por una coma:

110.90, 146.03
44.83, 211.82
97.13, 209.30

Llamaremos a la función np.loadtxt de la misma manera que antes, excepto que ahora pasamos un parámetro adicional – “delimitador:

import numpy as np

data = np.loadtxt("./weight_height_2.txt", delimiter = ",")

Esta función devolverá la misma matriz que antes.

  • En la sección anterior, no pasamos el valor del parámetro delimitador porque np.loadtxt() espera que el espacio “”sea el delimitador por defecto””.
  • Si los valores de cada fila estuvieran separados por una pestaña, en ese caso, el delimitador se especificaría utilizando el carácter de escape “\t”.

Puede verificar los resultados de nuevo comprobando la forma de la matriz de datos y también imprimiendo las primeras filas:

print("shape of array", data.shape)

print("First 5 rows:\n", data[:5])

Salida:
Especificar delimitadores

Trabajando con dos delimitadores

Ahora podría haber situaciones donde existen más de un delimitador en un archivo.

Por ejemplo, imaginemos que cada una de nuestras líneas contiene un 3er valor que representa la fecha de nacimiento del individuo en formato dd-mm-aaaa

110.90, 146.03, 3-7-1981
44.83, 211.82, 1-2-1986
97.13, 209.30, 14-2-1989

Ahora supongamos que queremos extraer las fechas, meses y años como tres valores diferentes en tres columnas diferentes de nuestra matriz NumPy. Entonces, ¿deberíamos pasar “,” como el delimitador o deberíamos pasar “-”?

Sólo podemos pasar un valor al parámetro delimitador en el método np.loadtxt!

No hay necesidad de preocuparse, siempre hay una solución. Usemos un tercer archivo ‘./weight_height_3.txt’ para este ejemplo.

Primero usaremos un enfoque ingenuo, que tiene los siguientes pasos:

  1. Leer el archivo
  2. Eliminar uno de los delimitadores en cada línea y reemplazarlo con un delimitador común (aquí la coma)
  3. Agregar la línea a la lista de ejecución
  4. Pasar esta lista de cadenas a la función np.loadtxt en lugar de pasar una ruta de archivo.

Vamos a escribir el código:

#reading each line from file and replacing "-" by ","
with open("./weight_height_3.txt") as f_input:

    text = [l.replace("-", ",") for l in f_input]

#calling the loadtxt method with “,“ as delimiter
data = np.loadtxt(text, delimiter=",")
  • Fíjate que estamos pasando una lista de cadenas como entrada y no una ruta de archivo.
  • Al llamar la función, todavía pasamos el parámetro del delimitador con el valor “,” ya que hemos reemplazado todas las instancias del segundo delimitador “-” por una coma.
  • La matriz NumPy devuelta debería tener ahora cinco columnas.

Puedes validar los resultados una vez más imprimiendo la forma y las primeras cinco líneas:

print("Shape of data:", data.shape)

print("First five rows:\n",data[:5])

Salida:
Trabajando con dos delimitadores

Fíjese como tenemos tres columnas adicionales en cada fila indicando la fecha, el mes y el año de nacimiento

También, noten que los nuevos valores son todos valores de punto flotante; sin embargo, la fecha, ¡el mes o el año tienen más sentido como números enteros!

Veremos cómo manejar tales inconsistencias de tipo de datos en la próxima sección.

 

Un enfoque general para delimitadores múltiples

En esta sección, veremos un enfoque general para trabajar con múltiples delimitadores.

También aprenderemos cómo podemos usar generadores en lugar de rutas de archivo, una solución más eficiente para los delimitadores múltiples, que la que discutimos en la sección anterior.

El problema de leer todo el archivo de una vez y almacenarlo como una lista de cadenas es que no se escala bien. Por ejemplo, si hay un archivo con un millón de líneas, almacenarlos en una lista de una sola vez va a consumir memoria adicional innecesaria.

Por lo tanto, usaremos generadores para deshacernos de cualquier delimitador adicional.

Un generador nos “rinde” una secuencia de valores sobre la marcha, es decir, leerá las líneas de un archivo según se requiera en lugar de leerlas todas a la vez

Así que primero definamos una función generadora que tome una ruta de archivo y una lista de delimitadores como parámetro.

def generate_lines(filePath, delimiters=[]):
    
    with open(filePath) as f:
        
        for line in f:
            
            line = line.strip() #removes newline character from end
            
        for d in delimiters:
            
            line =line.replace(d, " ")
            
            yield line

Aquí estamos revisando cada uno de los delimitadores uno por uno en cada línea y reemplazándolos por un espacio en blanco” “que es el delimitador por defecto en la función np.loadtxt.

Ahora llamaremos a esta función generadora y pasaremos el objeto generador devuelto al método np. loadtxt en lugar de la ruta del archivo.

gen = generate_lines("./weight_height_3.txt", ["-",","])

data = np.loadtxt(gen)

Obsérvese que no hemos tenido que pasar ningún parámetro delimitador adicional, ya que nuestra función generadora ha sustituido todas las instancias de los delimitadores de la lista pasada por un espacio, que es el delimitador por defecto.

Podemos ampliar esta idea y especificar tantos delimitadores como sean necesarios.

Especificar el tipo de datos

A menos que se especifique lo contrario, la función np.loadtxt del paquete NumPy asume que los valores del archivo de texto pasado son valores de punto flotante por defecto.

Por lo tanto, si se pasa un archivo de texto que tiene caracteres distintos de los números, la función arrojará un error, indicando que esperaba valores en coma flotante.

Podemos superar esto especificando el tipo de datos de los valores en el archivo de texto utilizando el parámetro de tipo de datos.

En el ejemplo anterior, vimos que la fecha, el mes y el año se interpretaban como valores en coma flotante. Sin embargo, sabemos que estos valores nunca pueden existir en forma decimal.

Veamos in nuevo archivo ‘/weight_height_4.txt’, que tiene solo 1 columna para la fecha de Nacimiento de individuos en el formato dd-mm-yyyy:

13-2-1991
17-12-1990
18-12-1986

Así que llamaremos al método loadtxt con “-” como delimitador:

data = np.loadtxt("./weight_height_4.txt", delimiter="-")

print(data[:3])

print("datatype =",data.dtype)

Si miramos la salida de las líneas de código anteriores, veremos que cada uno de los tres valores se ha almacenado como valores de punto flotante por defecto, y el tipo de datos de la matriz es “float64”.

Podemos alterar este comportamiento pasando el valor ‘int’ al parámetro ‘dtype’. Esto le pedirá a la función que almacene los valores extraídos como enteros, y por lo tanto el tipo de datos del array también será ‘int’.

data = np.loadtxt("./weight_height_4.txt", delimiter="-", dtype="int")

print(data[:3])

print("datatype =",data.dtype)

Salida:
Especificar el tipo de datos

¿Pero qué pasa si hay columnas con diferentes tipos de datos?

Digamos que tenemos las dos primeras columnas con valores de flotación y la última columna con valores enteros.

En ese caso, podemos pasar una cadena de tipo de datos separada por comas que especifique el tipo de datos de cada columna (en orden de existencia) al parámetro dtype.

Sin embargo, en tal caso, la función devolverá una matriz NumPy de tuplas de valores, ya que una matriz NumPy en su conjunto sólo puede tener un tipo de datos.

Vamos a intentar eso en el archive ‘weight_height_3.txt’donde las dos primeras columnas (peso, altura tienen valores flotantes y los últimos tres valores (fecha, mes, año) eran enteros:

Salida:
Especificar el tipo de datos para columnas

 

Ignorar encabezados

En algunos casos (especialmente en los archivos CSV), la primera línea del archivo de texto puede tener “encabezados” que describen lo que representa cada columna de las siguientes filas. Mientras leemos los datos de tales archivos de texto, es posible que queramos ignorar la primera línea porque no podemos (y no debemos) almacenarlos en nuestra matriz NumPy.

En tal caso, podemos usar el parámetro ‘skiprows’ y pasarle el valor 1, pidiéndole a la función que ignore la primera 1 línea(s) del archivo de texto.

Vamos a intentar esto en un archivo CSV – ‘weight_height.csv’:

Weight (in Kg), height (in cm)
73.847017017515,241.893563180437
68.7819040458903,162.310472521300
74.1101053917849,212.7408555565

Ahora queremos ignorar la línea del encabezado, es decir, la primera línea del archivo:

data = np.loadtxt("./weight_height.csv", delimiter=",", skiprows=1)

print(data[:3])

Salida:
Ignorar encabezados

De la misma manera, podemos pasar cualquier número entero positivo n al parámetro skiprows pidiendo que se ignoren las primeras n líneas del archivo.

 

Ignorar la primera columna

A veces, también podemos querer saltarnos la primera columna porque no nos interesa. Por ejemplo, si nuestro archivo de texto tuviera la primera columna como “género”, y si no necesitamos incluir los valores de esta columna al extraer los datos, necesitamos una forma de pedir a la función que haga lo mismo.

No tenemos un parámetro de “skipcols” como las “skiprows” en la función np.loadtxt, con el cual, podríamos expresar esta necesidad. Sin embargo, np.loadtxt tiene otro parámetro llamado ‘usecols’ donde especificamos los índices de las columnas a retener.

Así que, si queremos saltarnos la primera columna, podemos simplemente suministrar los índices de todas las columnas excepto la primera (recuerde que la indexación comienza en cero)

Basta de hablar, ¡vamos a trabajar!

Vamos a ver el contenido de un nuevo archivo ‘weight_height_5.txt’, el cual tiene una columna adicional de género que queremos ignorar.

Male, 110.90, 146.03
Male, 44.83, 211.82


Female, 78.67, 158.74
Male, 105.64, 164.21

Primero determinaremos el número de columnas desde la primera línea y luego pasaremos un ranco de índices de columnas excluyendo la primera:

with open("./weight_height_5.txt") as f:
    #determining number of columns from the first line of text

    n_cols = len(f.readline().split(","))

data = np.loadtxt("./weight_height_5.txt", delimiter=",",usecols=np.arange(1, n_cols))

print("First five rows:\n",data[:5])

Aquí estamos suministrando un rango de valores comenzando desde 1 (segunda columna) y extendiéndolo hasta la columna n (la última columna)
Salida:
Ignorar la primera columna

Podemos generalizar el uso del parámetro usecols al pasar una lista de índices de solo aquellas columnas que queremos incluir.

 

Cargar las primeras n filas

Podemos cargar solo las primeras filas y saltarnos el resto. Esto se puede lograr utilizando el parámetro max_rows del método np.loadtext.

Vamos a suponer que queremos leer solo las primeras diez filas del archivo de texto ‘eigth_heigth_2.txt’. llamaremos al método np.loadtext junto con el parámetro max_rows y pasaremos el valor de 10.

data = np.loadtxt("./weight_height_2.txt", delimiter=",",max_rows = 10)

print("Shape of data:",data.shape)

Salida:
Saltar filas

Como Podemos ver, el arreglo NumPy devuelto tiene solo diez filas, las cuales son las primeras diez filas del archivo de texto.

Si utilizamos el parámetro maw_rows junto con el parámetro skiprows, entonces el número especificado de filas será saltado, y las próximas n filas serán extraídas, donde n es el valor que pasamos a max_rows.

 

Cargar filas especificas

Si queremos que la función np.loadtxt dolo cargue filas específicas del archivo de texto, ningún parámetro soporta esta característica.

Sin embargo, Podemos lograr esto al definir un generador que acepte índices de filas y retorne líneas en esos índices. Entonces le pasaremos este objeto generador a nuestro método np.loadtxt.

Vamos primero a definir el generador:

def generate_specific_rows(filePath, row_indices=[]):

    with open(filePath) as f:

        # using enumerate to track line no.
        for i, line in enumerate(f):

            #if line no. is in the row index list, then return that line
            if i in row_indices:
 
               yield line

Ahora vamos a utilizar la función np.loadtxt para leer la 2da, 4ta y 100esima fila en el archivo ‘weight_height_2.txt

gen = generate_specific_rows("./weight_height_2.txt",row_indices = [1, 3, 99])

data = np.loadtxt(gen, delimiter=",")

print(data)

Esto debería retornar un arreglo NumPy que tenga tres filas y dos columnas:

Salida:
Cargar filas especificas

 

Saltar la última fila

Si quieres excluir la última fila del archivo de texto, podemos lograrlo de varias formas. Puedes definir otro generador que entregue las líneas una por una y se detenga justo antes de la última, o puedes utilizar enfoque incluso más simple, averigua el número de líneas en el archivo y pasa uno número menos al parámetro max_rows.

¿Pero cómo averiguaras el número de líneas?
Síguenos!!

with open("./weight_height_2.txt") as f:

    n = len(list(f))

print("n =", n)

Ahora n contiene el número de líneas presentes en el archivo `weight_height_2.txt`, ese valor debería ser 100.

Ahora leeremos el archivo de texto como soliamos hacerlo, utilizando el método np.loadtxt junto con el parámetro max_rows con valor de n-1.

data = np.loadtxt("./weight_height_2.txt", delimiter=",",max_rows=n - 1)

print("data shape =",data.shape)

Salida:
Saltar la última fila

Como Podemos ver, el archivo de texto original tenía 100 filas, pero cuando leemos los datos del archivo su forma es (99, 2) ya que se saltó la última fila del archivo.

 

Saltar columnas especificas

Supongamos que quiere ignorar algunas de las columnas mientras carga los datos de un archivo de texto especificando los índices de dichas columnas.

Si bien el método np.loadtxt proporciona un parámetro para especificar qué columnas retener (usecols), no ofrece una forma de hacer lo contrario, es decir, especificar qué columnas saltarse. Sin embargo, ¡siempre podemos encontrar una solución!

Primero definiremos los índices de las columnas a ignorar, y luego, utilizándolos, derivaremos la lista de índices a retener ya que los dos conjuntos serían mutuamente excluyentes.

Luego pasaremos esta lista de índices derivados al parámetro usecols.

Aquí está el pseudocódigo de todo el proceso:

  1. Encuentra el número de columnas en el archivo n_cols (explicado en una sección anterior)
  2. Definir la lista de los índices a ser ignorados
  3. Crear un rango de índices desde 0 a n_cols, y eliminar los índices del paso 2 de este rango
  4. Pasar esta nueva lista al parámetro usecols en el método np.loadtxt

Vamos a crear una función de envoltura loadtext_without_columns que implemente todos los pasos anteriores:

def loadtext_without_columns(filePath, skipcols=[], delimiter=","):

    with open(filePath) as f:
 
       n_cols = len(f.readline().split(delimiter))

    #define a range from 0 to n_cols
    usecols = np.arange(0, n_cols)

    #remove the indices found in skipcols
    usecols = set(usecols) - set(skipcols)

    #sort the new indices in ascending order
    usecols = sorted(usecols)

    #load the file and retain indices found in usecols
    data = np.loadtxt(filePath, delimiter = delimiter, usecols = usecols)

    return data

Para probar nuestro código, trabajaremos con un nuevo archivo `weight_height_6.txt`, que tiene cinco columnas – las dos primeras columnas indican el ancho y la altura, y las tres restantes indican la fecha, el mes y el año de nacimiento de los individuos.

Todos los valores están separados por un único delimitador – la coma:

110.90, 146.03, 3,7,1981
44.83, 211.82, 1,2,1986
97.13, 209.30, 14,2,1989


105.64, 164.21, 3,6,2000

Supongamos que no nos interesan la altura y la fecha de nacimiento del individuo, y por lo tanto queremos saltarnos las columnas de las posiciones 1 y 2.

Llamemos a nuestra función de envoltura especificando nuestros requisitos:

data = loadtext_without_columns("./weight_height_6.txt",skipcols = [1, 2], delimiter = ",")

# print first 5 rows
print(data[:5])

Salida:
Saltar columnas especificas

Podemos ver que nuestra función de envoltura sólo devuelve tres columnas: peso, mes y año. ¡Se ha asegurado de que las columnas que especificamos se han saltado!

 

Cargar arreglos 3D

Hasta ahora, hemos estado leyendo el contenido del archivo como una matriz 2D NumPy. Este es el comportamiento por defecto del método np.loadtxt, y no hay ningún parámetro adicional que podamos especificar para interpretar los datos leídos como una matriz 3D.

Así que el enfoque más simple para resolver este problema sería leer los datos como una matriz NumPy y usar el método de remodelación de NumPy para remodelar los datos en cualquier forma de cualquier dimensión que deseemos.

Sólo tenemos que tener cuidado de que, si queremos interpretarlo como una matriz multidimensional, debemos asegurarnos de que se almacena en el archivo de texto de manera adecuada y que después de remodelar la matriz, obtendríamos lo que realmente deseamos.

Tomemos un archive de ejemplo – ‘weight_height_7.txt’.

Este es el mismo archivo que ‘weight_height_2.txt’. La única diferencia es que este archivo tiene 90 filas, y cada bloque de 30 filas representa una sección o clase diferente a la que pertenecen los individuos.

Así que hay un total de 3 secciones (A, B y C), cada una de las cuales tiene 30 individuos cuyos pesos y alturas se enumeran en una nueva fila.

Los nombres de las secciones se indican con un comentario justo antes del comienzo de cada sección (puede comprobarlo en las líneas 1, 32 y 63).

Los comentarios comienzan con ‘#’ y estas líneas son ignoradas por np.loadtxt cuando se leen los datos. También podemos especificar cualquier otro identificador para las líneas de comentarios utilizando el parámetro ‘comments’.

Ahora bien, cuando se lee este archivo y se imprime su forma, se mostraría (90,2) porque así es como np.loadtxt lee los datos – organiza los datos de varias filas en matrices 2D.

Pero sabemos que hay una separación lógica entre cada grupo de 30 individuos, y querríamos que la forma fuera (3, 30, 2) – donde la primera dimensión indica las secciones, la segunda representa a cada uno de los individuos de esa sección, y la última dimensión indica el número de valores asociados a cada uno de estos individuos (aquí 2 para peso y altura).

Utilizar el método de remodelado de NumPy

Así que queremos que nuestros datos sean representados como una matriz 3D.

Podemos lograrlo simplemente reformando los datos devueltos usando el método de reformulación de NumPy.

data = np.loadtxt("./weight_height_7.txt",delimiter=",")

print("Current shape = ",data.shape)

data = data.reshape(3,30,2)

print("Modified shape = ",data.shape)

print("fifth individual of section B - weight, height =",data[1,4,:])

Salida:
Obtén matrices 3d

Fíjense en cómo imprimimos los detalles de un individuo específico usando tres índices

El resultado devuelto pertenece al 5º individuo de la sección B – esto se puede validar a partir del texto:


#section B
100.91, 155.55
72.93, 150.38
116.68, 137.15
86.51, 172.15
59.85, 155.53

 

Comparación con alternativas

Aunque numpy.loadtxt es una utilidad extremadamente útil para leer datos de archivos de texto, ¡no es la única!

Existen muchas alternativas que pueden hacer la misma tarea que np.loadtxt; muchas de ellas son mejores que np.loadtxt en muchos aspectos. Veamos brevemente tres de estas funciones alternativas.

numpy.genfromtxt

  1. Este es el método más discutido y el más utilizado junto con np.loadtxt
  2. No hay una gran diferencia entre los dos; la única que destaca es la capacidad de np.genfromtxt para manejar sin problemas los valores perdidos.
  3. De hecho, la documentación de NumPy describe np.loadtxt como “una función equivalente (a np.genfromtxt) cuando no falta ningún dato.
  4. Así que los dos son métodos casi similares, excepto que np.genfromtxt puede hacer un procesamiento más sofisticado de los datos en un archivo de texto.

numpy.fromfile

  1. np.fromfile se utiliza comúnmente cuando se trabaja con datos almacenados en archivos binarios, sin delimitadores.
  2. Puede leer archivos de texto plano, pero lo hace con muchos problemas (adelante y trata de leer los archivos que discutimos usando np.fromfile)
  3. Aunque es más rápido en tiempo de ejecución que np.loadtxt, pero generalmente no es una opción preferida cuando se trabaja con datos bien estructurados en un archivo de texto.
  4. Además, la documentación de NumPy menciona np.loadtxt como una forma más flexible (que np.fromfile) de cargar datos de un archivo de texto.

pandas.read_csv

  1. pandas.read_csv es la elección más popular de los científicos de datos, ingenieros de ML, analistas de datos, etc. para leer los datos de los archivos de texto.
  2. Ofrece mucha más flexibilidad que np.loadtxt o np.genfromtxt.
  3. No puedes pasar un generador a pandas.read_csv como hicimos nosotros.
  4. En términos de velocidad de ejecución, sin embargo, pandas.read_csv lo hace mejor que np.loadtxt

 

Manejando Valores Faltantes

Como se discutió en nuestra sección comparando np.loadtxt con otras opciones, np.genfromtxt maneja los valores perdidos por defecto. No tenemos ninguna forma directa de manejar los valores perdidos en np.loadtxt

Aquí veremos una forma indirecta (y ligeramente sofisticada) de manejar los valores perdidos con el método np.loadtxt.

El parámetro de los convertidores:

  • np.loadtxt tiene un parámetro convertidor que se utiliza para especificar el preprocesamiento (si lo hay) necesario para cada una de las columnas del archivo.
  • Por ejemplo, si el archivo de texto almacena la columna de altura en centímetros y queremos almacenarlos en pulgadas, podemos definir un convertidor para la columna de altura.
  • El parámetro convertidor acepta un diccionario donde las claves son índices de columna, y los valores son métodos que aceptan el valor de la columna, lo ‘convierten’ y devuelven el valor modificado.

¿Como Podemos utilizar los convertidores para manejar valores faltantes?

  • Tenemos que decidir primero el tipo de datos por defecto, es decir, el valor que se utilizará para rellenar las posiciones en las que faltan los valores reales. Digamos que queremos rellenar los valores de altura y peso que faltan con 0, así que nuestro valor_de_llenado será 0.
  • A continuación, podemos definir un convertidor para cada columna del archivo, que comprueba si hay algún valor o una cadena vacía en esa columna, y si es una cadena vacía, la llenará con nuestro valor_de_llenado.
  • Para ello, tendremos que encontrar el número de columnas en el archivo de texto, y ya hemos discutido cómo lograrlo en una sección anterior.

Utilizaremos el archive ‘weight_height_8.txt’, que es lo mismo que ‘weight_height_2.txt’ pero tiene varios valores perdidos.

, 146.03
44.83, 211.82
97.13,
69.87, 207.73
, 158.87
99.25, 195.41

Escribamos el código para rellenar las posiciones de estos valores perdidos con un 0.

# finding number of columns in the file
with open("./weight_height_8.txt") as f:

    n_cols = len(f.readline().split(","))

print("Number of columns", n_cols)

# defining converters for each of the column (using 'dictionary
# comprehension') to fill each missing value with fill_value

fill_value = 0

converters = {i: lambda s: float(s.strip() or fill_value) for i in range(2)}

data = np.loadtxt("./weight_height_8.txt", delimiter=",",converters = converters)

print("data shape =",data.shape)

print("First 5 rows:\n",data[:5])

Salida:
Manejando Valores Faltantes

Los valores de altura y peso que faltan han sido correctamente reemplazados con un 0. ¡No hay magia!!

 

Conclusión

numpy.loadtxt es, sin duda, una de las opciones más estándar para leer un dato bien estructurado almacenado en un archivo de texto. Nos ofrece una gran flexibilidad para elegir varias opciones para especificar la forma en que queremos leer los datos, y dondequiera que no lo haga – ¡recuerde que siempre hay una solución!

Mokhtar Ebrahim
Fundadora de LikeGeeks. Estoy trabajando como administrador de sistemas Linux desde 2010. Soy responsable de mantener, proteger y solucionar problemas de servidores Linux para múltiples clientes de todo el mundo. Me encanta escribir guiones de shell y Python para automatizar mi trabajo.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *