lunes, 9 de julio de 2018

Frecuencias en Python

Reto: Frecuencias

Construir una lista que contenga el código de 6 aeropuertos internacionales: MAD, JFK, LHR, CDG, AMS, FRA. Generar un dado de seis caras, con las siguientes probabilidades 25%, 22%, 18%, 14%, 11%, 10%, que corresponden a cada uno de los aeropuertos respectivamente. Generar un listado de 100 aeropuertos extraídos entre los seis del array y que aparezcan de forma aleatoria cada uno según su probabilidad. Finalmente mostramos los aeropuertos y el número de veces que aparece cada uno de ellos.




Los elementos de la lista (aeropuertos) no son equiprobables. Tenemos que conseguir que salgan de forma aleatoria pero cada uno con el peso que se le ha asignado. Generamos un listado con cien aeropuertos y luego calculamos la frecuencia con la que aparece cada uno de ellos. Esas frecuencias no necesariamente han de coincidir exactamente con los pesos asignados ya que estamos trabajando en el campo de la incertidumbre.

Método 1

Importamos la libreria random para trabajar con números aleatorios. Importamos la libreria numpy para poder luego usar cumsum que nos dará las probabilidades acumuladas. Inicializamos la lista F con seis ceros. Esta lista contendrá al final las frecuencias con las que aparece cada aeropuerto. Imprimimos la lista L de aeropuertos disponibles y la lista P con las probabilidades o pesos de cada uno de ellos. Con cumsum construimos la lista A que contendrá el acumulado de las probabilidades individuales de cada aeropuerto. Imprimimos la lista de pesos acumulados A.
Definimos la función intervalo que recibe como argumentos r (un número random entre cero y uno) y A que es la lista de pesos acumulados.
Nos metemos en un bucle for para generar los cien aeropuertos. Dentro del bucle generamos un número aleatorio r  y llamamos a la función intervalo que nos devolverá un número aleatorio entre 0 y 5, pero este número ya no será equiprobable sino que estará cargado con los pesos definidos para cada aeropuerto. Ese número se llamará z y se usará como índice para obtener el aeropuerto usándolo con la lista L, así L[z]. Construiremos la lista de frecuencias con la expresión F[z]+=1 que acumulará un 1 cada vez que aparezca el aeropuerto de índice z.
Imprimimos un separador para las FRECUENCIAS. Nos metemos en un bucle for que recorre los valores 0 a 5 que es el índice que usaremos para imprimir las listas F (frecuencias), L (abreviatura del aeropuerto), C (ciudad del aeropuerto).




import random
import numpy as np
random.seed()
L=['MAD','JFK','LHR','CDG','AMS','FRA']
P=[.25,.22,.18,.14,.11,.10]
C=['Madrid','New York','London','Paris','Amsterdam','Frankfurt']
F=[0]*6 #frecuencia de cada aeropuerto
print(L)
print('probabilidad:',P)
A=np.cumsum(P) #acumulado
print('acumulada: ',A)
def intervalo(r,A):
  for i in range(len(A)):
    if r<=A[i]:
      return(i)
for j in range(100):
  r=random.random()
  z=intervalo(r,A)
  F[z]+=1
  print(L[z])
print('--- F R E C U E N C I A S ---')
for k in range(6):
  print(F[k],L[k],C[k])

También podríamos haber calculado la lista A con las probabilidades acumuladas usando las siguientes línea de código en sustitución de la expresión A=np.cumsum(P). Esto nos permitiría ahorrarnos importar la librería numpy.

A=[P[0]]*6 #probabilidad acumulada
for i in range(1,len(P)):
  A[i]=round(A[i-1]+P[i],4)


Método 2

Este método usa menos líneas de código que el anterior. Importamos de la librería random el elemento choices. Inicializamos las listas L, P y F. Esta última la inicializamos con seis valores todos ellos iguales a cero, y finalmente contendrá las frecuencias de aparción de cada aeropuerto. Nos metemos en un bucle for de cien elementos para generar todos los aeropuertos de forma aleatoria no uniforme. Con range(6) generamos una lista con los números 0 a 5. Con choices(range(6),P) lo que hacemos es elegir de forma aleatoria uno de esos seis valores numéricos de la primera lista según la probabilidad P dada por la segunda lista. Esas probabilidades actúan como los pesos o importancia relativa que tiene cada uno de los elementos a la hora de ser elegidos. La variable que obtenemos es x que contiene el elemento elegido en forma de lista. Por ejemplo, x puede resultar ser [5] que significaría que ha sido elegido el último elemento de la lista que va entre 0 y 5. Como necesitamos que ese valor no venga dado en forma de lista, sino que lo necesitamos en formato de número entero, lo consguimos con la variable y definida como y=x[0] que lo que hace es obtener el primer y único elemento de la lista x.
Imprimimos el aeropuerto usando L[y] y en el print añadimos end=' '. Eso lo que hace es evitar que se impriman los aeropuertos en vertical y deja un espacio en blanco entre ellos.
Contruimos la lista F con las frecuencias con las que se presentan cada uno de los aeropuertos. Finalmente imprimimos la lista de aeropuertos y las frecuencias asociadas. Esto se consigue usando zip que fusiona las dos listas en una sucesión de tuplas. Si intentamos imprimir el objeto zip no veríamos el resultado esperado ya que es necesario encapsularlo con alguno de estos elementos.

  • list --> lista, se ven los corchetes []. Es el sistema que hemos utilizado
  • tuple --> tupla, se vería contenido entre paréntesis ()
  • dict --> diccionario, se vería contenido entre llaves {}





from random import choices
L=['MAD','JFK','LHR','CDG','AMS','FRA']
P=[.25,.22,.18,.14,.11,.10]
F=[0]*6 #frecuencia de cada aeropuerto
print(L)
print('probabilidad:',P)
for i in range(100):
  x=choices(range(6),P)
  y=x[0]
  print(L[y], end=' ')
  F[y]+=1
print('\n','-'*25,' F R E C U E N C I A S ','-'*26)
print(list(zip(L,F)))


Método 3

Importamos el elemento choice de numpy.random. Observe que no se trata del mismo elemento que en el caso anterior. Este va en singular choice y el anterior estaba en plural choices. Incluso pertenecen a librerías diferentes. En este método y gracias al uso de choice nos ahorramos tener que construir la lista con las probabilidades acumuladas ya que ahora lo único que tenemos que hacer es proporcionar a esta función la lista L (relación de aeropuertos) y la lista P (probabilidadades individuales). La función choice nos devuelve uno de los seis aeropuertos elegido de forma aleatoria según los pesos proporcionados por la lista P de probabilidades. Con el aeropuerto z elegido vamos contruyendo una lista a con append. Como estamos dentro del bucle for la lista a finalmente contendrá cien aeropuertos que imprimiremos.
Para hacer el análisis de frecuencias usamos collections.Counter(a) que nos dará un diccionario que contiene como clave cada uno de los aeropuertos y como valor su frecuencia de aprición. Este diccionario viene ordenado de mayor a menor frecuencia de acaecimiento, por lo que no siempre veremos primero el aeropuerto de Madrid que es el más probable.




from numpy.random import choice
import collections
L=['MAD','JFK','LHR','CDG','AMS','FRA']
P=[.25,.22,.18,.14,.11,.10]
a=[] #lista que contendrá los 100 aeropuertos
for i in range(100):
  z=choice(L, p=P) #elige de una lista según pesos
  a.append(z)
print(a)
print(collections.Counter(a)) #dict con las frecuencias

No hay comentarios:

Publicar un comentario