Una alternativa más rápida a la función `isin` de Pandas.

Tengo un df dataframe muy grande que se parece a:

 ID Value1 Value2 1345 3.2 332 1355 2.2 32 2346 1.0 11 3456 8.9 322 

Y tengo una lista que contiene un subconjunto de IDs ID_list . Necesito tener un subconjunto de df para el ID contenido en ID_list .

Actualmente, estoy usando df_sub=df[df.ID.isin(ID_list)] para hacerlo. Pero lleva mucho tiempo. ID contenidas en ID_list no tienen ningún patrón, por lo que no están dentro de cierto rango. (Y necesito aplicar la misma operación a muchos marcos de datos similares. Me preguntaba si hay una forma más rápida de hacerlo. ¿Ayudará mucho si el ID es el índice?

¡Gracias!

EDIT 2: aquí hay un enlace a una revisión más reciente del rendimiento de varias operaciones de pandas , aunque no parece incluir la combinación y la unión hasta la fecha.

https://github.com/mm-mansour/Fast-Pandas

EDIT 1: estos puntos de referencia eran para una versión bastante antigua de pandas y probablemente todavía no sean relevantes. Ver el comentario de Mike a continuación sobre la merge .

Depende del tamaño de sus datos, pero para grandes conjuntos de datos, DataFrame.join parece ser el camino a seguir. Esto requiere que su índice de DataFrame sea su “ID” y la Serie o el DataFrame al que se está uniendo para tener un índice que sea su “ID_list”. La Serie también debe tener un name para ser usado con join , que se introduce como un nuevo campo llamado name . También debe especificar una unión interna para obtener algo como isin porque la join predeterminada en una unión izquierda. La consulta in syntax parece tener las mismas características de velocidad que la de los grandes conjuntos de datos.

Si está trabajando con conjuntos de datos pequeños, obtiene comportamientos diferentes y, de hecho, se vuelve más rápido usar una lista de comprensión o aplicar en un diccionario que usar isin .

De lo contrario, puedes intentar obtener más velocidad con Cython .

 # I'm ignoring that the index is defaulting to a sequential number. You # would need to explicitly assign your IDs to the index here, eg: # >>> l_series.index = ID_list mil = range(1000000) l = mil l_series = pd.Series(l) df = pd.DataFrame(mil, columns=['ID']) In [247]: %timeit df[df.index.isin(l)] 1 loops, best of 3: 1.12 s per loop In [248]: %timeit df[df.index.isin(l_series)] 1 loops, best of 3: 549 ms per loop # index vs column doesn't make a difference here In [304]: %timeit df[df.ID.isin(l_series)] 1 loops, best of 3: 541 ms per loop In [305]: %timeit df[df.index.isin(l_series)] 1 loops, best of 3: 529 ms per loop # query 'in' syntax has the same performance as 'isin' In [249]: %timeit df.query('index in @l') 1 loops, best of 3: 1.14 s per loop In [250]: %timeit df.query('index in @l_series') 1 loops, best of 3: 564 ms per loop # ID must be the index for DataFrame.join and l_series must have a name. # join defaults to a left join so we need to specify inner for existence. In [251]: %timeit df.join(l_series, how='inner') 10 loops, best of 3: 93.3 ms per loop # Smaller datasets. df = pd.DataFrame([1,2,3,4], columns=['ID']) l = range(10000) l_dict = dict(zip(l, l)) l_series = pd.Series(l) l_series.name = 'ID_list' In [363]: %timeit df.join(l_series, how='inner') 1000 loops, best of 3: 733 µs per loop In [291]: %timeit df[df.ID.isin(l_dict)] 1000 loops, best of 3: 742 µs per loop In [292]: %timeit df[df.ID.isin(l)] 1000 loops, best of 3: 771 µs per loop In [294]: %timeit df[df.ID.isin(l_series)] 100 loops, best of 3: 2 ms per loop # It's actually faster to use apply or a list comprehension for these small cases. In [296]: %timeit df[[x in l_dict for x in df.ID]] 1000 loops, best of 3: 203 µs per loop In [299]: %timeit df[df.ID.apply(lambda x: x in l_dict)] 1000 loops, best of 3: 297 µs per loop