2011-02-08 12 views
6

Edición de título: capitalización fija y agregado para 'pitón'.Agrupación de una serie en Python

¿Existe una manera mejor o más estándar de hacer lo que estoy describiendo? quiero entrada de la siguiente manera:

[1, 1, 1, 0, 2, 2, 0, 2, 2, 0, 0, 3, 3, 0, 1, 1, 1, 1, 1, 2, 2, 2]

a ser transformado a esto:

[0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 2, 0]

o, aún mejor, algo como esto (que describe una salida similar de manera diferente, pero ahora no se limita a enteros):

etiquetas: [1, 2, 3, 1, 2]

posiciones (donde 1 identificó la primera posición ocupable, según mi diagrama matplotlib): [2, 7, 12.5, 17, 21]

Los datos de entrada son datos categóricos que clasifican un gráfico - en la imagen siguiente, los gráficos agrupados comparten una característica categórica que me gustaría etiquetar solo una vez para el grupo. Usaré 2 ejes para dos variables diferentes, pero creo que ese es el punto por el momento.

Nota: Esta imagen no refleja ningún conjunto de datos de muestra; solo se trata de cruzar la idea de agrupar categorías. El grupo a debe etiquetarse en x = 5, ya que hay un espacio en blanco entre los dos primeros y el segundo a los grupos de datos verticales, y 0 es la línea del lado derecho.

Image demonstrating placement of tick marks in the center of a category of data

Esto es lo que tengo:

data = [1, 1, 1, 2, 2, 2, 2, 2, 3, 4, 3, 2, 2, 1, 1, 1, 1] 
last = None 
runs = [] 
labels = [] 
run = 1 
for x in data: 
    if x in (last, 0): 
     run += 1 
    else: 
     runs.append(run) 
     run = 1 
     labels.append(x) 
    last = x 
runs.append(run) 
runs.pop(0) 
labels.append(x) 
tick_positions = [0] 
last_run = 1 
for run in runs: 
    tick_positions.append(run/2.0+last_run/2.0+tick_positions[-1]) 
    last_run = run 
tick_positions.pop(0) 
print tick_positions 

Respuesta

8

Para obtener las etiquetas que se pueden utilizar itertools groupby:

>>> import itertools 
>>> numbers = [1, 1, 1, 0, 2, 2, 0, 2, 2, 0, 0, 3, 3, 0, 1, 1, 1, 1, 1, 2, 2, 2] 
>>> list(k for k, g in itertools.groupby(numbers)) 
[1, 0, 2, 0, 2, 0, 3, 0, 1, 2] 

Y para eliminar los ceros se puede utilizar una comprensión :

>>> list(k for k, g in itertools.groupby(x for x in numbers if x != 0)) 
[1, 2, 3, 1, 2] 

Si quiere obtener los puestos también, tendrá que repetir la lista usted mismo como ya lo hace. groupby no hace un seguimiento de eso para usted.

+1

Eso es exactamente lo que imaginaba que existía en alguna parte. Me recuerda que "en algún lugar" casi siempre es itertools. Gracias. – Thomas

+2

1) Las posiciones también son importantes 2) También se debe ignorar '0' entre las dos secuencias de' 2'. Supongo que no hay otra opción que generar de alguna manera ese conjunto intermedio, simplemente agrupar todos los valores repetidos no es suficiente. – rsenna

+0

rsenna tiene razón, esto no funciona para todo lo que necesito, pero espero que sea una solución como la que voy a encontrar, parece que la respuesta exacta a mi pregunta hubiera sido "no", pero eso es aburrido. – Thomas

Cuestiones relacionadas