tutorial tablas seleccionar recorrer graficar filtrar espaƱol documentacion datos data con columnas python pandas

python - tablas - Encontrar segmentos consecutivos en un marco de datos de pandas



seleccionar columnas de un dataframe pandas (2)

Puede usar np.diff () para probar dónde comienza / finaliza un segmento e iterar sobre esos resultados. Es una solución muy simple, por lo que probablemente no sea la de mayor rendimiento.

a = np.array([3,3,3,3,3,4,4,4,4,4,1,1,1,1,4,4,12,12,12]) prev = 0 splits = np.append(np.where(np.diff(a) != 0)[0],len(a)+1)+1 for split in splits: print np.arange(1,a.size+1,1)[prev:split] prev = split

Resultados en:

[1 2 3 4 5] [ 6 7 8 9 10] [11 12 13 14] [15 16] [17 18 19]

Tengo un pandas.DataFrame con mediciones tomadas en puntos consecutivos en el tiempo. Junto con cada medición, el sistema en observación tenía un estado distinto en cada punto en el tiempo. Por lo tanto, el DataFrame también contiene una columna con el estado del sistema en cada medición. Los cambios de estado son mucho más lentos que el intervalo de medición. Como resultado, la columna que indica los estados puede verse así (índice: estado):

1: 3 2: 3 3: 3 4: 3 5: 4 6: 4 7: 4 8: 4 9: 1 10: 1 11: 1 12: 1 13: 1

¿Hay una manera fácil de recuperar los índices de cada segmento de estados consecutivamente iguales? Eso significa que me gustaría obtener algo como esto:

[[1,2,3,4], [5,6,7,8], [9,10,11,12,13]]

El resultado también puede ser algo diferente a las listas simples.

La única solución que se me ocurre hasta ahora es iterar manualmente sobre las filas, encontrar puntos de cambio de segmento y reconstruir los índices a partir de estos puntos de cambio, pero tengo la esperanza de que haya una solución más fácil.


Un trazador de líneas:

df.reset_index().groupby(''A'')[''index''].apply(np.array)

Código por ejemplo:

In [1]: import numpy as np In [2]: from pandas import * In [3]: df = DataFrame([3]*4+[4]*4+[1]*4, columns=[''A'']) In [4]: df Out[4]: A 0 3 1 3 2 3 3 3 4 4 5 4 6 4 7 4 8 1 9 1 10 1 11 1 In [5]: df.reset_index().groupby(''A'')[''index''].apply(np.array) Out[5]: A 1 [8, 9, 10, 11] 3 [0, 1, 2, 3] 4 [4, 5, 6, 7]

También puede acceder directamente a la información del grupo por objeto:

In [1]: grp = df.groupby(''A'') In [2]: grp.indices Out[2]: {1L: array([ 8, 9, 10, 11], dtype=int64), 3L: array([0, 1, 2, 3], dtype=int64), 4L: array([4, 5, 6, 7], dtype=int64)} In [3]: grp.indices[3] Out[3]: array([0, 1, 2, 3], dtype=int64)

Para abordar la situación que mencionó DSM, podría hacer algo como:

In [1]: df[''block''] = (df.A.shift(1) != df.A).astype(int).cumsum() In [2]: df Out[2]: A block 0 3 1 1 3 1 2 3 1 3 3 1 4 4 2 5 4 2 6 4 2 7 4 2 8 1 3 9 1 3 10 1 3 11 1 3 12 3 4 13 3 4 14 3 4 15 3 4

Agrupe ahora en ambas columnas y aplique la función lambda:

In [77]: df.reset_index().groupby([''A'',''block''])[''index''].apply(np.array) Out[77]: A block 1 3 [8, 9, 10, 11] 3 1 [0, 1, 2, 3] 4 [12, 13, 14, 15] 4 2 [4, 5, 6, 7]