Encuentra un patrón particular en una columna de dataframe pandas

Me gustaría encontrar un patrón en particular en una columna de dataframe de pandas, y devolver los valores de índice correspondientes para subcontratar el dataframe

Aquí hay un dataframe de muestra con un posible patrón:

Fragmento para producir el dataframe:

import pandas as pd import numpy as np Observations = 10 Columns = 2 np.random.seed(123) df = pd.DataFrame(np.random.randint(90,110,size=(Observations, Columns)), columns = ['ColA','ColB']) datelist = pd.date_range(pd.datetime(2017, 7, 7).strftime('%Y-%m-%d'), periods=Observations).tolist() df['Dates'] = datelist df = df.set_index(['Dates']) pattern = [100,90,105] print(df) 

Marco de datos:

  ColA ColB Dates 2017-07-07 103 92 2017-07-08 92 96 2017-07-09 107 109 2017-07-10 100 91 2017-07-11 90 107 2017-07-12 105 99 2017-07-13 90 104 2017-07-14 90 105 2017-07-15 109 104 2017-07-16 94 90 

Aquí, el patrón de interés aparece en la Column A en las fechas 2017-07-10 a 2017-07-12 , y eso es lo que me gustaría terminar:

Salida deseada:

 2017-07-10 100 91 2017-07-11 90 107 2017-07-12 105 99 

Si ocurre el mismo patrón varias veces, me gustaría subordenar el dataframe de la misma manera, y también contar cuántas veces ocurre el patrón, pero espero que sea más directo siempre y cuando se resuelva el primer paso.

Gracias por cualquier sugerencia!

Aquí hay una solución:

Verifique si el patrón se encontró en alguna de las columnas usando balanceo . Esto le dará el último índice del grupo que coincide con el patrón

 matched = df.rolling(len(pattern)).apply(lambda x: all(np.equal(x, pattern))) matched = matched.sum(axis = 1).astype(bool) #Sum to perform boolean OR matched Out[129]: Dates 2017-07-07 False 2017-07-08 False 2017-07-09 False 2017-07-10 False 2017-07-11 False 2017-07-12 True 2017-07-13 False 2017-07-14 False 2017-07-15 False 2017-07-16 False dtype: bool 

Para cada coincidencia, agregue los índices del patrón completo:

 idx_matched = np.where(matched)[0] subset = [range(match-len(pattern)+1, match+1) for match in idx_matched] 

Consigue todos los patrones:

 result = pd.concat([df.iloc[subs,:] for subs in subset], axis = 0) result Out[128]: ColA ColB Dates 2017-07-10 100 91 2017-07-11 90 107 2017-07-12 105 99 

Usando la magia de las listas de comprensión:

 [df.index[i - len(pattern)] # Get the datetime index for i in range(len(pattern), len(df)) # For each 3 consequent elements if all(df['ColA'][i-len(pattern):i] == pattern)] # If the pattern matched # [Timestamp('2017-07-10 00:00:00')] 

La forma más corta es encontrar el índice en el que comienza el patrón. Entonces solo necesitas seleccionar las tres filas siguientes.

Para encontrar estos índices, basta con una sola línea:

 indexes=df[(df.ColA==pattern[0])&(df["ColA"].shift(-1)==pattern[1])&(df["ColA"].shift(-2)==pattern[2])].index 

Luego, haz lo que la otra respuesta dice para obtener los subconjuntos que deseas.

 for col in df: index = df[col][(df[col] == pattern[0]) & (df[col].shift(-1) == pattern[1]) & (df[col].shift(-2) == pattern[2])].index if not index.empty: print(index)