In [19]:
"""
IPython Notebook v4.0 para python 2.7
Librerías adicionales: Ninguna.
Contenido bajo licencia CC-BY 4.0. Código bajo licencia MIT. (c) Sebastian Flores.
"""

# Configuracion para recargar módulos y librerías 
%reload_ext autoreload
%autoreload 2

from IPython.core.display import HTML

HTML(open("style/iwi131.css", "r").read())


Out[19]:






IWI131

Programación de Computadores

Sebastián Flores

http://progra.usm.cl/

https://www.github.com/usantamaria/iwi131

Fechas

  • Actividad 05: Miércoles 6 Enero 2016 (8:00).
  • Certamen 3: Viernes 8 Enero 2016 (15:30).
  • Certamen Recuperativo: Lunes 18 Enero 2016 (8:00).

Clases

  • Mie 23 Dic 2016: Procesamiento de Texto.
  • Lun 28 Dic 2016: Escribir y leer archivos.
  • Mie 30 Dic 2016: Ejercicios tipo certamen.
  • Lun 04 Ene 2016: Ejercicios tipo certamen.
  • Mie 06 Ene 2016: Actividad 5.

Consejo: Baje el libro del curso, lea, aprenda y practique.

¿Qué contenido aprenderemos?

  • Procesamiento de texto

¿Porqué aprenderemos ese contenido?

  • Procesamiento de texto

Habilidad crucial para resolver una gran variedad de problemas.

Motivación

Queremos conocer cuales son las palabras más comunes en un idioma. Para eso, necesitamos saber cuantas veces aparece cada palabra en una frase. Desarrolle una función contar_palabras que al ser aplicada sobre un string, entregue un diccionario con las palabras y la cantidad de veces que aparece en la frase. Omita espacios y signos de puntuación y exclamación.

t = 'El sobre, en el aula, esta sobre el pupitre.'

contar_palabras(t)
{'el': 3, 'en': 1, 'esta': 1, 'aula': 1, 
'sobre': 2, 'pupitre': 1}

¿Cómo realizaría usted esta difícil tarea?

Consejos

El procesamiento de texto utiliza:

  • Reconocimiento de patrones: usted debe reconocer que patrones se repiten y puede explotar para procesar el texto.
  • Utilización de funciones específicas: el tipo de dato string posee una rica colección de métodos que debe manejar para simplificar la tarea de procesamiento de texto.
  • Recuerde que todo string es inmutable, por lo que al aplicar diversas funciones se obtiene siempre un nuevo string.

Procesamiento de texto

Salto de línea

El string \n corresponde a un único carácter, que representa el salto de línea.


In [23]:
print len("\n")

a1 = 'casa\narbol\npatio'
print a1
print len(a1)

a2 = '''casa
arbol
patio'''
print a2
print len(a2)

print a1==a2

b = 'a\nb\nc'
print b
print len(b)


1
casa
arbol
patio
16
casa
arbol
patio
16
True
a
b
c
5

Procesamiento de texto

Tabulación

El string \t corresponde a un único carácter, que representa una tabulación.


In [25]:
print len("\t")

a = 'casa\n\tarbol\n\tpatio'
print a

b = 'a\tb\tc'
print b
print len(b)


1
casa
	arbol
	patio
a	b	c
5

Procesamiento de texto

Importante: \n y \t aparecen frecuentemente cuando analicemos archivos leídos del disco duro.

Procesamiento de texto

Reemplazar secciones de un string

  • La función mi_string.replace(s1, s2) busca cada ocurrencia del substring s1 en mi_string, y lo reemplaza por s2.
  • La función mi_string.replace(s1, s2,n) busca las primeras n ocurrencias del substring s1 en mi_string, y lo reemplaza por s2.
  • La función mi_string.replace(s1, s2) regresa un nuevo string, el string original no es modificado.

In [29]:
palabra = 'cara'
palabra2 = palabra.replace('r', 's')
print palabra
print palabra2
print palabra2.replace('ca', 'pa')
print palabra2.replace('a', 'e', 1)
print palabra2.replace('c', '').replace('a', 'o') # Encadenamiento de metodos
print palabra


cara
casa
pasa
cesa
oso
cara

Procesamiento de texto

Separar un string

Para separar un string tenemos 2 opciones:

  • Separar en caracteres, utilizando list(mi_string), que genera una lista con los carácteres de mi_string en orden.
  • Separar en palabras, utilizando mi_string.split(s), que generar una lista de "palabras" que han sido separadas por el string s. El string s no estará en ninguno de los substrings de la lista. Por defecto, s es el caracter espacio " ".

In [30]:
oracion = 'taca taca'
print list(oracion)
print set(oracion)
print oracion.split()
print oracion.split("a")
print oracion.split("t")
print oracion.split("ac")


['t', 'a', 'c', 'a', ' ', 't', 'a', 'c', 'a']
set(['a', ' ', 'c', 't'])
['taca', 'taca']
['t', 'c', ' t', 'c', '']
['', 'aca ', 'aca']
['t', 'a t', 'a']

Procesamiento de texto

Unir una lista de strings

Para unir una lista de strings es necesario utilizar el método join:

s.join(lista_de_strings)

Regresa un único string donde los elementos del string han sido "pegados" utilizando el string s.


In [33]:
mi_lista = ['Ex', 'umbra', 'in', 'solem']
print ' '.join(mi_lista)
print ''.join(mi_lista)
print ' -> '.join(mi_lista)


Ex umbra in solem
Exumbrainsolem
Ex -> umbra -> in -> solem

In [34]:
mi_conjunto = {'Ex', 'umbra', 'in', 'solem'}
print mi_conjunto
print ' '.join(mi_conjunto)
print ''.join(mi_conjunto)
print ' -> '.join(mi_conjunto)


set(['Ex', 'solem', 'umbra', 'in'])
Ex solem umbra in
Exsolemumbrain
Ex -> solem -> umbra -> in

Unir una lista de strings

Observación: join funciona sólo sobre una lista de strings. Si quiere pegar números, debe convertirlos a strings antes.


In [35]:
lista_de_strings = ["1", "2", "3"]
print ", ".join(lista_de_strings)


1, 2, 3

In [36]:
lista_de_ints = [1, 2, 3]
print ", ".join(lista_de_ints)


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-36-ac88427f974d> in <module>()
      1 lista_de_ints = [1, 2, 3]
----> 2 print ", ".join(lista_de_ints)

TypeError: sequence item 0: expected string, int found

In [37]:
lista_de_ints = range(10)
lista_de_strings = []
for x in lista_de_ints:
    lista_de_strings.append(str(x))
print ", ".join(lista_de_strings)


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

Procesamiento de texto

Unir una secuencia de valores (no strings) v2

También es posible utilizar map que aplica genera una nueva lista aplicando a cada elemento de la lista original la función pasada como argumento.


In [44]:
numeros = range(10)
print numeros
def f(x):
    return 2.*x + 1./(x+1)

print map(str, numeros)
print map(float, numeros)
print map(f, numeros)

print ', '.join(map(str, numeros))

# 
print "-"join("1,2,3,4".split(","))


[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
[1.0, 2.5, 4.333333333333333, 6.25, 8.2, 10.166666666666666, 12.142857142857142, 14.125, 16.11111111111111, 18.1]
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
1-2-3-4

Procesamiento de texto

Interpolación de valores por posición


In [47]:
s = 'Soy {0} y vivo en {1} {2}'
print s.format('Perico', 'Valparaiso')
print s.format('Erika', 'Berlin')
print s.format('Wang Dawei', 'Beijing')


---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-47-36380a8ee462> in <module>()
      1 s = 'Soy {0} y vivo en {1} {2}'
----> 2 print s.format('Perico', 'Valparaiso')
      3 print s.format('Erika', 'Berlin')
      4 print s.format('Wang Dawei', 'Beijing')

IndexError: tuple index out of range

Procesamiento de texto

Interpolación de valores por nombre


In [48]:
s = '{nombre} estudia en la {u}'
# Datos pueden pasarse ordenados
print s.format(nombre='Perico', u='UTFSM')
print s.format(nombre='Fulana', u='PUCV')
# También es posible cambiar el orden
print s.format(u='UPLA', nombre='Yayita')
# O con magia (conocimiento avanzado)
d = {"nombre":"Mago Merlin", "u":"Camelot University"}
print s.format(**d)


Perico estudia en la UTFSM
Fulana estudia en la PUCV
Yayita estudia en la UPLA
Mago Merlin estudia en la Camelot University

Procesamiento de texto

Mayusculas y Minúsculas

Para cambiar la capitalización de un string, es posible utilizar los siguientes métodos:

  • .upper(): TODO EN MAYUSCULA.
  • .lower(): todo en minuscula
  • .swapcase(): cambia el order que tenia la capitalización.
  • .capitalize(): Coloca únicamente mayuscula en la primera letra del string.

In [51]:
palabra = '1. raMo de ProGra'
print palabra.upper()
print palabra.lower()
print palabra.swapcase()
print palabra.capitalize()


1. RAMO DE PROGRA
1. ramo de progra
1. RAmO DE pROgRA
1. ramo de progra

Procesamiento de texto

Ejemplo de Motivación

Queremos conocer cuales son las palabras más comunes en un idioma. Para eso, necesitamos saber cuantas veces aparece cada palabra en una frase. Desarrolle una función contar_palabras que al ser aplicada sobre un string, entregue un diccionario con las palabras y la cantidad de veces que aparece en la frase. Omita espacios y signos de puntuación y exclamación.

t = 'El sobre, en el aula, esta sobre el pupitre.'

contar_palabras(t)
{'el': 3, 'en': 1, 'esta': 1, 'aula': 1, 'sobre': 2, 'pupitre': 1}

¿Cómo realizaría ahora usted esta difícil tarea?

Procesamiento de texto

Consejos

Subdividir en tareas menores:

  • ¿Cómo sacar los simbolos indeseados?
  • ¿Cómo separar las palabras?
  • ¿Cómo contar las palabras?

In [ ]:
def contar_palabras(s):
    return s
    
t = 'El sobre, en el aula, esta sobre el pupitre.'
contar_palabras(t)

Procesamiento de texto

Motivación: Solución

INPUT:

t = 'El sobre, en el aula, esta sobre el pupitre.'
contar_palabras(t)

OUTPUT:

{'el': 3, 'en': 1, 'esta': 1, 'aula': 1, 
'sobre': 2, 'pupitre': 1}

In [53]:
def contar_palabras(s):
    s = s.lower()
    for signo in [",",".",";","!","?","'",'"']:
        s = s.replace(signo,"")
    palabras = s.split()
    contador = {}
    for palabra_sucia in palabras:
        palabra = palabra_sucia
        if palabra in contador:
            contador[palabra] += 1 # Aumentamos
        else:
            contador[palabra] = 1 # Inicializamos
    return contador
    
t = 'El sobre, en el aula, !! Esta sobre el pupitre.'
contar_palabras(t)


Out[53]:
{'aula': 1, 'el': 3, 'en': 1, 'esta': 1, 'pupitre': 1, 'sobre': 2}

Procesamiento de texto

Ejercicio 2

Escriba un programa que tenga el siguiente comportamiento:

INPUT:

Numero de alumnos: 3
Nombre alumno 1: Isaac Newton
Ingrese las notas de Isaac: 98 94 77
Nombre alumno 2: Nikola Tesla
Ingrese las notas de Nikola: 100 68 94 88
Nombre alumno 3: Albert Einstein
Ingrese las notas de Albert: 83 85

OUTPUT:

El promedio de Isaac es 89.67
El promedio de Nikola es 87.50
El promedio de Albert es 84.00

Procesamiento de texto

Ejercicio 2: Análisis

¿Cuáles son las tareas necesarias?

Procesamiento de texto

Ejercicio 1: Solución

Las tareas a realizar son:

  • Leer número de alumnos
  • Para cada alumno, leer nombre y notas.
  • Procesar notas para obtener el promedio.
  • Almacenar nombre y notas.
  • Separar nombre de apellido.
  • Imprimir resultados apropiadamente.

In [ ]:
# Solución Alumnos

In [54]:
# Solución
# Guardar datos
N = int(raw_input("Numero de alumnos: "))
notas_alumnos = []
for i in range(N):
    nombre = raw_input("Nombre alumno {0}:".format(i+1))
    nombre_pila = nombre.split(" ")[0]
    notas_str = raw_input("Ingrese las notas de {0}: ".format(nombre_pila))
    notas_int = []
    for nota in notas_str.split(" "):
        notas_int.append(int(nota))
    promedio = sum(notas_int)/float(len(notas_int))
    notas_alumnos.append( (nombre_pila, promedio) )

# Imprimir promedios
for nombre, promedio in notas_alumnos:
    print "El promedio de {0} es {1:.2f}".format(nombre, promedio)


Numero de alumnos: 2
Nombre alumno 1:Felipe Lopez Correa
Ingrese las notas de Felipe: 90 90 90 90 90 0
Nombre alumno 2:Pablo Alvarado Seguel
Ingrese las notas de Pablo: 100 0 100 0 100 0 100
El promedio de Felipe Lopez Correa es 75.00
El promedio de Pablo Alvarado Seguel es 57.14

Procesamiento de texto

Procesamiento de ADN

Una cadena de ADN es una secuencia de bases nitrogenadas llamadas adenina, citosina, timina y guanina. En un programa, una cadena se representa como un string de caracteres 'a', 'c', 't' y 'g'. A cada cadena, le corresponde una cadena complementaria, que se obtiene intercambiando las adeninas con las timinas, y las citosinas con las guaninas:

cadena = 'cagcccatgaggcagggtg'
complemento = 'gtcgggtactccgtcccac'

Procesamiento de ADN

1.1 Procesamiento de ADN: Secuencia aleatoria

Escriba la función cadena_al_azar(n) que genere una cadena aleatoria de ADN de largo n:

Ejemplo de uso:

cadena_al_azar(10) 
puede regresar 'acgtccgcct', 'tgttcgcatt', etc.

Pista:

from random import choice

choice('atcg') regresa al azar una de las letras de "atcg"

Procesamiento de ADN

1.1 Secuencia aleatoria: Análisis

¿Que tareas son necesarias?


In [57]:
# Definicion de funcion
from random import choice
def cadena_al_azar(n):
    bases_n=''
    for i in range(n):
        base=choice('atgc')
        bases_n+=base
    return bases_n

# Casos de uso
print cadena_al_azar(1)
print cadena_al_azar(1)
print cadena_al_azar(1)
print cadena_al_azar(1)
print cadena_al_azar(10)
print cadena_al_azar(10)
print cadena_al_azar(10)
print cadena_al_azar(10)


g
g
g
t
tgaccggacg
tacccacact
aagcatccga
tccattcgga

Procesamiento de ADN

1.1 Solución Secuencia aleatoria v1


In [ ]:
from random import choice

# Definicion de funcion
def cadena_al_azar(n):
    adn = ""
    for i in range(n):
        adn += choice("acgt")
    return adn

# Casos de uso
print cadena_al_azar(1)
print cadena_al_azar(1)
print cadena_al_azar(1)
print cadena_al_azar(1)
print cadena_al_azar(10)
print cadena_al_azar(10)
print cadena_al_azar(10)
print cadena_al_azar(10)

Procesamiento de ADN

1.1 Solución Secuencia aleatoria v2


In [ ]:
from random import choice

# Definicion de funcion
def cadena_al_azar(n):
    bases = []
    for i in range(n):
        bases.append(choice("acgt"))
    adn = "".join(bases)
    return adn

# Casos de uso
print cadena_al_azar(1)
print cadena_al_azar(1)
print cadena_al_azar(1)
print cadena_al_azar(1)
print cadena_al_azar(10)
print cadena_al_azar(10)
print cadena_al_azar(10)
print cadena_al_azar(10)

Procesamiento de texto

Procesamiento de ADN: Secuencia complementaria

Escriba la función complementaria(s) que regrese la cadena complementaria de c: el complementario de "a" es "t" (y viceversa), y el complementario de "c" es "g" (y viceversa).

cadena = 'cagcccatgaggcagggtg'
    print complementaria(cadena)
    'gtcgggtactccgtcccac'

Procesamiento de texto

Procesamiento de ADN: Secuencia complementaria

¿Tareas?


In [ ]:
# Solucion estudiantes
def cadena_(n):
    adn = ""
    for i in range(n):
        adn += choice("acgt")
    return adn

Procesamiento de texto

Solución Secuencia complementaria v1


In [58]:
def complementaria(adn):
    rna = ""
    for base in adn:
        if base=="a":
            rna += "t"
        elif base=="t":
            rna += "a"
        elif base=="c":
            rna += "g"
        else:
            rna += "c"
    return rna

adn = cadena_al_azar(20)
print adn
print complementaria(adn)


ttttagtgcttcagaatgtc
aaaatcacgaagtcttacag

Procesamiento de texto

Solución Secuencia complementaria v2


In [59]:
def complementaria(adn):
    pares = {"a":"t", "t":"a", "c":"g", "g":"c"}
    rna = ""
    for base in adn:
        rna += pares[base]
    return rna

adn = cadena_al_azar(20)
print adn
print complementaria(adn)


atccttcaaaaactcctagc
taggaagtttttgaggatcg

Procesamiento de texto

Solución Secuencia complementaria v3


In [60]:
def complementaria(adn):
    rna = adn.replace("a","T").replace("t","A").replace("c","G").replace("g","C")
    return rna.lower()

adn = cadena_al_azar(20)
print adn
print complementaria(adn)


caactcatagcttgtcatgg
gttgagtatcgaacagtacc

Procesamiento de texto

Digitos no presentes

Dado un string con dígitos, indique que digitos no estan presentes (en orden).

INPUT:

13579
3210

OUTPUT:

02468
456789

In [ ]: