Re: Presentación y probabilidades

Chema Cortes pych3m4 en gmail.com
Vie Abr 25 14:08:18 CEST 2008


El día 25 de abril de 2008 10:52, Víctor <victorpernand en gmail.com> escribió:
> Hola, un saludo a todos los de la lista. Soy novato en python. Tengo algunas
>  ideas sencillas que me gustaría llevar a la práctica, pero antes tengo que
>  aprender y practicar.
>
>  Para empezar, estoy intentando hacer una función de permita elegir entre los
>  elementos de una lista, según una lista de probabilidades. Por ejemplo, si
>  le doy la lista ['azul','rojo','verde'] y la lista de probabilidades en
>  tantos por cientos [50,25,25] o en cualquier otra relación como [ 2,1,1]
>  (que sería igual que el anterior), me devuelve uno de los tres colores,
>  según las probabilidades de apararición.
>
>  Esto es lo que he hecho hasta ahora:
>
>  from random import randint
>
>  def sumalista(lista):
>     "suma los elementos de una lista de numeros"
>     return reduce (lambda x,y: x+y, lista)

Esta función es equivalente a la función 'sum' se python.

>  def decide(lista, probab):
>     tmp=[0]
>     for x in range(len(probab)):
>         tmp.append(probab[x]+tmp[x])
>     #normaliza a 1000
>     normaliza= [x*1000/sumalista(probab) for x in tmp]

Lo veo un poco complejo, con ese 'append' con "autoreferencia". Lo que
sí que deberías tener cuidado es con las divisiones, ya que, de
momento (hasta que se cambie en alguna versión futura de python), las
divisiones de enteros dan números enteros. Todo este trozo de código
lo haría así:

    normaliza=[x*1000.0/sum(probab) for x in probab]

Fíjate en que he puesto 1000.0, que es un float.

>     num=randint(0,999)
>     elemento= len([x for x in normaliza if x<=num])-1
>     return lista[elemento]

Una forma elegante, aunque ineficiente, de hacer lo mismo:

    def decide(lista,probab):
      L=sum( [[x]*p for (x,p) in zip(lista,probab)] , [])
      return L[randint(0,sum(probab))]

Una forma mucho más eficiente y directa (sin usar compresión de listas):

  def decide(lista,probab):
    num=randint(0,sum(probab))
    for i,n in enumerate(probab):
        if n>=num:
            break
        num-=n
    return lista[i]


Supongo que se puede hacer de muchas otras formas.
_______________________________________________
Lista de correo Python-es 
http://listas.aditel.org/listinfo/python-es
FAQ: http://listas.aditel.org/faqpyes





Más información sobre la lista de distribución Python-es