xticks barplot python dictionary functional-programming

python - barplot - pandas plot



Usando el mapa de python y otras herramientas funcionales (9)

Esto es bastante simple, pero estoy tratando de aprender / entender la programación funcional en Python. El siguiente código:

foos = [1.0,2.0,3.0,4.0,5.0] bars = [1,2,3] def maptest(foo, bar): print foo, bar map(maptest, foos, bars)

produce:

1.0 1 2.0 2 3.0 3 4.0 None 5.0 None

P. ¿Hay alguna manera de usar el mapa o cualquier otra herramienta funcional en Python para producir lo siguiente sin bucles, etc.

1.0 [1,2,3] 2.0 [1,2,3] 3.0 [1,2,3] 4.0 [1,2,3] 5.0 [1,2,3]

Como nota al margen, ¿cómo cambiaría la implementación si existe una dependencia entre foo y bar? p.ej

foos = [1.0,2.0,3.0,4.0,5.0] bars = [1,2,3,4,5]

e imprimir:

1.0 [2,3,4,5] 2.0 [1,3,4,5] 3.0 [1,2,4,5] ...

PD: Sé cómo hacerlo ingenuamente usando if, loops y / o generadores, pero me gustaría aprender cómo lograr lo mismo usando herramientas funcionales. ¿Es solo un caso de agregar una instrucción if a maptest o aplicar otro mapa de filtro a barras internamente en maptest?


¿Estás familiarizado con otros lenguajes funcionales? es decir, ¿estás tratando de aprender cómo funciona Python la programación funcional, o estás tratando de aprender sobre la programación funcional y el uso de Python como el vehículo?

Además, ¿entiendes las comprensiones de la lista?

map(f, sequence)

es directamente equivalente (*) a:

[f(x) for x in sequence]

De hecho, creo que map() se programó una vez para su eliminación de Python 3.0 como redundante (eso no sucedió).

map(f, sequence1, sequence2)

es mayormente equivalente a:

[f(x1, x2) for x1, x2 in zip(sequence1, sequence2)]

(hay una diferencia en cómo maneja el caso donde las secuencias son de diferente longitud. Como viste, map() rellena None cuando se acaba una de las secuencias, mientras que zip() detiene cuando se detiene la secuencia más corta)

Por lo tanto, para abordar su pregunta específica, está tratando de producir el resultado:

foos[0], bars foos[1], bars foos[2], bars # etc.

Puede hacer esto escribiendo una función que toma un solo argumento y lo imprime, seguido de barras:

def maptest(x): print x, bars map(maptest, foos)

Alternativamente, puede crear una lista que se vea así:

[bars, bars, bars, ] # etc.

y usa tu prueba de mapa original:

def maptest(x, y): print x, y

Una forma de hacerlo sería crear explícitamente la lista de antemano:

barses = [bars] * len(foos) map(maptest, foos, barses)

Alternativamente, puede obtener el módulo itertools . itertools contiene muchas funciones inteligentes que te ayudan a hacer una programación de evaluación perezosa de estilo funcional en python. En este caso, queremos itertools.repeat , que generará su argumento indefinidamente a medida que iteramos sobre él. Este último hecho significa que si lo haces:

map(maptest, foos, itertools.repeat(bars))

obtendrá un resultado infinito, ya que map() continúa mientras uno de los argumentos siga produciendo resultados. Sin embargo, itertools.imap es como map() , pero se detiene tan pronto como se detiene el iterable más corto.

itertools.imap(maptest, foos, itertools.repeat(bars))

Espero que esto ayude :-)

(*) Es un poco diferente en Python 3.0. Allí, map () esencialmente devuelve una expresión de generador.


¿Esto lo haría?

foos = [1.0,2.0,3.0,4.0,5.0] bars = [1,2,3] def maptest2(bar): print bar def maptest(foo): print foo map(maptest2, bars) map(maptest, foos)


Aquí está la solución que está buscando:

>>> foos = [1.0, 2.0, 3.0, 4.0, 5.0] >>> bars = [1, 2, 3] >>> [(x, bars) for x in foos] [(1.0, [1, 2, 3]), (2.0, [1, 2, 3]), (3.0, [1, 2, 3]), (4.0, [1, 2, 3]), (5.0, [ 1, 2, 3])]

Recomiendo usar una lista de comprensión (la parte [(x, bars) for x in foos] sobre el uso del mapa ya que evita la sobrecarga de una llamada a función en cada iteración (que puede ser muy significativa). Si vas a usarlo en un ciclo for, obtendrás mejores velocidades al usar una comprensión de generador:

>>> y = ((x, bars) for x in foos) >>> for z in y: ... print z ... (1.0, [1, 2, 3]) (2.0, [1, 2, 3]) (3.0, [1, 2, 3]) (4.0, [1, 2, 3]) (5.0, [1, 2, 3])

La diferencia es que la comprensión del generador está flojamente cargada .

ACTUALIZACIÓN En respuesta a este comentario:

Por supuesto, usted sabe, que no copia barras, todas las entradas son la misma lista de barras. Por lo tanto, si modifica alguno de ellos (incluidas las barras originales), los modificará a todos.

Supongo que este es un punto válido. Hay dos soluciones a esto que puedo pensar. El más eficiente es probablemente algo como esto:

tbars = tuple(bars) [(x, tbars) for x in foos]

Dado que las tuplas son inmutables, esto evitará que las barras se modifiquen a través de los resultados de esta lista de comprensión (o la comprensión del generador si sigue esa ruta). Si realmente necesita modificar todos y cada uno de los resultados, puede hacer esto:

from copy import copy [(x, copy(bars)) for x in foos]

Sin embargo, esto puede ser un poco caro tanto en términos de uso de la memoria como en velocidad, por lo que recomendaría que no lo haga a menos que realmente necesite agregar a cada uno de ellos.


Aquí hay una descripción general de los parámetros de la map(function, *sequences) :

  • function es el nombre de tu función.
  • sequences es cualquier cantidad de secuencias, que generalmente son listas o tuplas. map repetirá sobre ellos simultáneamente y dará los valores actuales para function . Es por eso que el número de secuencias debe ser igual a la cantidad de parámetros para su función.

Parece que estás intentando iterar para algunos de los parámetros de la function , pero mantienes constantes a los demás, y desafortunadamente el map no es compatible. Encontré una vieja propuesta para agregar tal característica a Python, pero la construcción del mapa es tan limpia y está bien establecida que dudo que algo así se implemente.

Utilice una solución alternativa como las variables globales o enumere las comprensiones, como otros han sugerido.


La manera más fácil sería no pasar las bars través de las diferentes funciones, sino acceder directamente desde maptest :

foos = [1.0,2.0,3.0,4.0,5.0] bars = [1,2,3] def maptest(foo): print foo, bars map(maptest, foos)

Con su función original maptest también podría usar una función lambda en el map :

map((lambda foo: maptest(foo, bars)), foos)


La programación funcional se trata de crear código libre de efectos secundarios.

map es una abstracción de transformación de lista funcional. Lo usas para tomar una secuencia de algo y convertirlo en una secuencia de otra cosa.

Está intentando usarlo como un iterador. No hagas eso. :)

Aquí hay un ejemplo de cómo puede usar el mapa para compilar la lista que desea. Hay soluciones más cortas (yo solo usaría las comprensiones), pero esto te ayudará a entender qué mapa funciona un poco mejor:

def my_transform_function(input): return [input, [1, 2, 3]] new_list = map(my_transform, input_list)

Observe que en este punto, solo ha realizado una manipulación de datos. Ahora puedes imprimirlo:

for n,l in new_list: print n, ll

- No estoy seguro de lo que quieres decir con "sin bucles". fp no se trata de evitar bucles (no puede examinar cada elemento de una lista sin visitar cada uno). Se trata de evitar los efectos secundarios, por lo tanto, escribir menos errores.


Qué tal esto:

foos = [1.0,2.0,3.0,4.0,5.0] bars = [1,2,3] def maptest(foo, bar): print foo, bar map(maptest, foos, [bars]*len(foos))


>>> from itertools import repeat >>> for foo, bars in zip(foos, repeat(bars)): ... print foo, bars ... 1.0 [1, 2, 3] 2.0 [1, 2, 3] 3.0 [1, 2, 3] 4.0 [1, 2, 3] 5.0 [1, 2, 3]


import itertools foos=[1.0, 2.0, 3.0, 4.0, 5.0] bars=[1, 2, 3] print zip(foos, itertools.cycle([bars]))