Filtre las filas del dataframe si el valor en la columna está en una lista de valores establecida

Tengo un rpt de DataFrame de los pandas de Python:

 rpt  MultiIndex: 47518 entries, ('000002', '20120331') to ('603366', '20091231') Data columns: STK_ID 47518 non-null values STK_Name 47518 non-null values RPT_Date 47518 non-null values sales 47518 non-null values 

Puedo filtrar las filas cuyo id de stock es '600809' como este: rpt[rpt['STK_ID'] == '600809']

  MultiIndex: 25 entries, ('600809', '20120331') to ('600809', '20060331') Data columns: STK_ID 25 non-null values STK_Name 25 non-null values RPT_Date 25 non-null values sales 25 non-null values 

y quiero unir todas las filas de algunas acciones, como ['600809','600141','600329'] . Eso significa que quiero una syntax como esta:

 stk_list = ['600809','600141','600329'] rst = rpt[rpt['STK_ID'] in stk_list] # this does not works in pandas 

Dado que los pandas no aceptan el comando anterior, ¿cómo lograr el objective?

Usa el método isin . rpt[rpt['STK_ID'].isin(stk_list)] .

isin() es ideal si tiene una lista de coincidencias exactas, pero si tiene una lista de coincidencias parciales o subcadenas para buscar, puede filtrar utilizando el método str.contains y las expresiones regulares.

Por ejemplo, si queremos devolver un DataFrame donde todas las ID de stock que comienzan con '600' y luego van seguidas de tres dígitos:

 >>> rpt[rpt['STK_ID'].str.contains(r'^600[0-9]{3}$')] # ^ means start of string ... STK_ID ... # [0-9]{3} means any three digits ... '600809' ... # $ means end of string ... '600141' ... ... '600329' ... ... ... ... 

Supongamos que ahora tenemos una lista de cadenas con las que queremos que 'STK_ID' los valores en 'STK_ID' , por ejemplo

 endstrings = ['01$', '02$', '05$'] 

Podemos unir estas cadenas con la expresión regular o el carácter | y pase la cadena a str.contains para filtrar el dataframe:

 >>> rpt[rpt['STK_ID'].str.contains('|'.join(endstrings)] ... STK_ID ... ... '155905' ... ... '633101' ... ... '210302' ... ... ... ... 

Finalmente, contains puede ignorar mayúsculas y minúsculas (estableciendo case=False y case=False ), lo que le permite ser más general al especificar las cadenas que desea que coincidan.

Por ejemplo,

 str.contains('pandas', case=False) 

coincidiría con PANDAS , PanDAs , paNdAs123 , y así sucesivamente.

También puedes usar rangos usando:

 b = df[(df['a'] > 1) & (df['a'] < 5)] 

También puede consultar directamente su DataFrame para esta información.

 rpt.query('STK_ID in (600809,600141,600329)') 

O buscar de manera similar los rangos:

 rpt.query('60000 < STK_ID < 70000') 

Rebanar datos con pandas

Dado un dataframe como este:

  RPT_Date STK_ID STK_Name sales 0 1980-01-01 0 Arthur 0 1 1980-01-02 1 Beate 4 2 1980-01-03 2 Cecil 2 3 1980-01-04 3 Dana 8 4 1980-01-05 4 Eric 4 5 1980-01-06 5 Fidel 5 6 1980-01-07 6 George 4 7 1980-01-08 7 Hans 7 8 1980-01-09 8 Ingrid 7 9 1980-01-10 9 Jones 4 

Hay varias formas de seleccionar o dividir los datos.

Utilizando .isin

La más obvia es la característica .isin . Puede crear una máscara que le proporcione una serie de afirmaciones True / False , que se pueden aplicar a un dataframe como este:

 mask = df['STK_ID'].isin([4, 2, 6]) mask 0 False 1 False 2 True 3 False 4 True 5 False 6 True 7 False 8 False 9 False Name: STK_ID, dtype: bool df[mask] RPT_Date STK_ID STK_Name sales 2 1980-01-03 2 Cecil 2 4 1980-01-05 4 Eric 4 6 1980-01-07 6 George 4 

El enmascaramiento es la solución ad hoc al problema, pero no siempre funciona bien en términos de velocidad y memoria.

Con indexacion

Al establecer el índice en la columna STK_ID , podemos usar el objeto de .loc pandas .loc

 df.set_index('STK_ID', inplace=True) RPT_Date STK_Name sales STK_ID 0 1980-01-01 Arthur 0 1 1980-01-02 Beate 4 2 1980-01-03 Cecil 2 3 1980-01-04 Dana 8 4 1980-01-05 Eric 4 5 1980-01-06 Fidel 5 6 1980-01-07 George 4 7 1980-01-08 Hans 7 8 1980-01-09 Ingrid 7 9 1980-01-10 Jones 4 df.loc[[4, 2, 6]] RPT_Date STK_Name sales STK_ID 4 1980-01-05 Eric 4 2 1980-01-03 Cecil 2 6 1980-01-07 George 4 

Esta es la forma más rápida de hacerlo, incluso si la indexación puede tardar un poco, ahorra tiempo si desea realizar varias consultas como esta.

Fusión de marcos de datos

Esto también se puede hacer mediante la fusión de marcos de datos. Esto se ajustaría más a un escenario en el que tiene muchos más datos que en estos ejemplos.

 stkid_df = pd.DataFrame({"STK_ID": [4,2,6]}) df.merge(stkid_df, on='STK_ID') STK_ID RPT_Date STK_Name sales 0 2 1980-01-03 Cecil 2 1 4 1980-01-05 Eric 4 2 6 1980-01-07 George 4 

Nota

Todos los métodos anteriores funcionan incluso si hay varias filas con el mismo 'STK_ID'

También puede lograr resultados similares utilizando ‘consulta’ y @:

p.ej:

 df = pd.DataFrame({'A': [1, 2, 3], 'B': ['a', 'b', 'f']}) df = pd.DataFrame({'A' : [5,6,3,4], 'B' : [1,2,3, 5]}) list_of_values = [3,6] result= df.query("A in @list_of_values") result AB 1 6 2 2 3 3 

Puede utilizar la query , es decir:

 b = df.query('a > 1 & a < 5')