Manejo de arrays y matrices en python

He leído constantemente que python es un lenguaje muy poderoso con el cual se puede hacer prácticamente lo que uno desee. Recientemente, me adentré en su mundo tratando de programar algunas aplicaciones para GRASS, sin embargo, esa “zambullida” fue prácticamente sin conocer muchos detalles del lenguaje y eso me ha traído algunos problemas. Por esta razón me propuse identificar algunos aspectos que tenía que aprender mejor y ese correspondía al de arrays y matrices.

Para sistematizar las operaciones que se pueden lograr con éstos se cuenta con el módulo numpy. Como también es tedioso el hecho de tener que digitar en cónsola los arreglos y matrices, especialmente cuando estos son muy grandes, me propuse a averiguar como se puede realizar esta tarea de manera expedita. Para ello, decidí crear un archivo de texto plano (archivo2) que contiene dos matrices de 3×3 (la primera es real simétrica porque se sabe que su inversa está definida) con la siguiente configuración:

1 2 3
2 1 4
3 4 1
1 2 3
4 5 6
7 8 9

Para leer ese archivo e imprimirlo por pantalla tendríamos suficiente con:

#! /usr/bin/env python

pfile=open('archivo2','r')

data=pfile.read()

pfile.close()

print data

y es simplemente texto. Con el código siguiente ya se imprime con un formato de array:

#! /usr/bin/env python

#Librerias
import numpy as np
from StringIO import StringIO 

pfile=open('archivo2','r')

data=pfile.read()

pfile.close()

data=np.genfromtxt(StringIO(data)) #Se sobre entiende que los 
                                   #delimitadores son espacios

print data

donde la salida es la siguiente:

[[ 1.  2.  3.]
 [ 2.  1.  4.]
 [ 3.  4.  1.]
 [ 1.  2.  3.]
 [ 4.  5.  6.]
 [ 7.  8.  9.]]

Para individualizar las matrices y “multiplicarlas”:

#! /usr/bin/env python

#Librerias
import numpy as np
from StringIO import StringIO 

pfile=open('archivo2','r')

data=pfile.read()

pfile.close()

data=np.genfromtxt(StringIO(data)) #Se sobre entiende que los 
                                   #delimitadores son espacios


matriz1 = data[0:3]
matriz2 = data[3:6]

matriz3 = matriz1 * matriz2

print matriz3

se tiene que la salida es la siguiente:

[[  1.   4.   9.]
 [  8.   5.  24.]
 [ 21.  32.   9.]]

Sin embargo, esta salida no corresponde a una multiplicación de matrices propiamente dicha porque, hasta ahora, genfromtxt lo que hizo fue simplemente transformar el texto en un array de arrays. Para transformar en matriz y obtener el resultado esperado hay que incluir una instrucción adicional:

#! /usr/bin/env python

#Librerias
import numpy as np
from StringIO import StringIO 

pfile=open('archivo2','r')

data=pfile.read()

pfile.close()

data=np.genfromtxt(StringIO(data)) #Se sobre entiende que los 
                                   #delimitadores son espacios

data=np.matrix(data) #Transformar array de arrays en matriz

matriz1 = data[0:3]
matriz2 = data[3:6]

matriz3 = matriz1 * matriz2

print matriz3

donde ahora la salida si es la esperada para una multiplicación de matrices:

[[ 30.  36.  42.]
 [ 34.  41.  48.]
 [ 26.  34.  42.]]

Por otra parte, si se quiere determinar, por ejemplo, la inversa de una matriz entonces hay que importar el módulo linalg de scipy. El código sería el siguiente:

#! /usr/bin/env python

#Librerias
import numpy as np
from StringIO import StringIO 
from scipy.linalg import *

pfile=open('archivo2','r')

data=pfile.read()

pfile.close()

data=np.genfromtxt(StringIO(data)) #Se sobre entiende que los 
                                   #delimitadores son espacios

#data=np.matrix(data) #Transformar array de arrays en matriz

matriz1 = data[0:3]
matriz2 = data[3:6]

matriz3 = matriz1 * matriz2

matriz4=inv(matriz1) #inv determina la inversa

print matriz4 #matriz inversa de matriz1

cuya salida para la inversa es:

[[-0.75  0.5   0.25]
 [ 0.5  -0.4   0.1 ]
 [ 0.25  0.1  -0.15]]

Con estos conocimientos básicos de manejo de arrays y matrices la parte que se detalla del script siguiente:

#! /usr/bin/python
import os
import grass.script as grass

os.system("clear")

#numero de puntos

n = 15

#Obtencion de las coordenadas x,y,z para todos los puntos
puntos = grass.read_command("v.to.db", flags="p", map="cuenca_puntos", type="point", option="coor", units="meters", quiet="True")

#Definicion de la matriz
matriz = []

for i in range(n):
	matriz.append([])
	for j in range(3):
		matriz[i].append(None)

#Algoritmo para la individualizacion de las coordenadas
z=1
h=0
for i in range(n):
	h=h+3
	for j in range(3):
		matriz[i][j]=(puntos.split("|")[z])
		if (j==2):
			temp=(puntos.split("|")[h])
			matriz[i][j]=float(temp.split("\n")[0])
		z=z+1

#Impresion, por verificacion, de la matriz
for i in range(n):
	for j in range(3):
		print matriz[i][j],
	print 	
.
.
.

quedaría entonces de manera más concisa como:

#! /usr/bin/python
import os
import grass.script as grass
import numpy as np
from StringIO import StringIO

os.system("clear")

#numero de puntos

n = 15

#Obtencion de las coordenadas x,y,z para todos los puntos
puntos = grass.read_command("v.to.db", flags="p", map="cuenca_puntos", type="point", option="coor", units="meters", quiet="True")

puntos=np.genfromtxt(StringIO(puntos), delimiter="|")

puntos=puntos[0:15,1:4]

print puntos
.
.
.
About these ads
Esta entrada fue publicada en Código Python. Guarda el enlace permanente.

6 respuestas a Manejo de arrays y matrices en python

  1. Pingback: Script de python para generar y rotar rectángulos a partir de puntos en QGIS-GRASS |

  2. Juanlu001 dijo:

    Hola Jose! Acabo de descubrir tu blog y está muy bien, pero en este artículo creo que te has complicado en exceso. Para cargar un array desde un archivo externo no hace falta usar un StringIO, ni siquiera crear un objeto file: precisamente ayer publicamos un artículo sobre cómo leer datos con NumPy. En nuestro blog nos dedicamos a hablar de Python aplicado a la ciencia y la ingeniería, ¡tal vez te interese!

    Un saludo!

    • Gracias por tu comentario. Veré tus sugerencias porque en realidad apenas lo que tengo son 2 meses aprendiendo python pero, analizando rápidamente lo que tu me señalas, parece que no me he “complicado en exceso” en un caso particular. La razón está en que yo no soy el que “hace las salidas” sino el comando v.to.db de GRASS y esa es la razón del uso de StringIO; que fue la manera más eficiente que encontré en el manual de numpy para eliminar los delimitadores “|” que se producen por default (ahora pensándolo mejor también es posible manipular las flags del comando para que en lugar de “|” genere simplemente espacios y evitar el uso posterior de StringIO). Para los otros casos veré como modificar el código.

      Saludos

      Nota: Ya vi porque no hace falta StringIO. Gracias por la sugerencia.

  3. Pingback: Matrices en Python usando numpy | VTirapegui Elementos de Algebra para la Computacion | Scoop.it

  4. Juanlu001 dijo:

    Si pudieras actualizar la URL en mi comentario (y borrar este) te lo agradecería :)

    http://pybonacci.org/2012/08/17/como-leer-y-escribir-datos-en-archivos-con-numpy/

    Aparentemente me llegan muchas visitas de tu blog :) ¡Un saludo!

Deja un comentario

Por favor, inicia sesión con uno de estos métodos para publicar tu comentario:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s