Alternativa más rápida a las ventanas

Sé que este tema ha sido abordado mil veces. Pero no puedo encontrar una solución.

Estoy tratando de contar la frecuencia con la que aparece una lista (cada fila de df1.list1) en una columna de la lista (df2.list2). Todas las listas constan de valores únicos solamente. List1 incluye alrededor de 300.000 filas y list2 30.000 filas.

Tengo un código de trabajo pero es terriblemente lento (porque lo estoy utilizando). También probé itertuples () pero me dio un error (“demasiados valores para desempaquetar (esperado 2)”). Encontré una pregunta similar en línea: Pandas contando ocurrencia de lista contenida en la columna de listas . En el caso mencionado, la persona considera solo la aparición de una lista dentro de una columna de listas. Sin embargo, no puedo resolver las cosas por lo que cada fila en df1.list1 se compara con df2.list2.

Así es como se ven mis listas (simplificadas):

df1.list1 0 ["a", "b"] 1 ["a", "c"] 2 ["a", "d"] 3 ["b", "c"] 4 ["b", "d"] 5 ["c", "d"] df2.list2 0 ["a", "b" ,"c", "d"] 1 ["a", "b"] 2 ["b", "c"] 3 ["c", "d"] 4 ["b", "c"] 

Lo que me gustaría proponer:

df1

  list1 occurence 0 ["a", "b"] 2 1 ["a", "c"] 1 2 ["a", "d"] 1 3 ["b", "c"] 3 4 ["b", "d"] 1 5 ["c", "d"] 2 

Eso es lo que tengo hasta ahora:

 for index, row in df_combinations.iterrows(): df1.at[index, "occurrence"] = df2["list2"].apply(lambda x: all(i in x for i in row['list1'])).sum() 

¿Alguna sugerencia de cómo puedo acelerar las cosas? ¡Gracias por adelantado!

Esto debería ser mucho más rápido:

 df = pd.DataFrame({'list1': [["a","b"], ["a","c"], ["a","d"], ["b","c"], ["b","d"], ["c","d"]]*100}) df2 = pd.DataFrame({'list2': [["a","b","c","d"], ["a","b"], ["b","c"], ["c","d"], ["b","c"]]*100}) list2 = df2['list2'].map(set).tolist() df['occurance'] = df['list1'].apply(set).apply(lambda x: len([i for i in list2 if x.issubset(i)])) 

Usando su enfoque:

 %timeit for index, row in df.iterrows(): df.at[index, "occurrence"] = df2["list2"].apply(lambda x: all(i in x for i in row['list1'])).sum() 

1 bucle, el mejor de 3: 3,98 s por bucle Usando el mío:

 %timeit list2 = df2['list2'].map(set).tolist();df['occurance'] = df['list1'].apply(set).apply(lambda x: len([i for i in list2 if x.issubset(i)])) 

10 bucles, lo mejor de 3: 29.7 ms por bucle

Observe que he aumentado el tamaño de la lista en un factor de 100.

EDITAR

Este parece incluso más rápido:

 list2 = df2['list2'].sort_values().tolist() df['occurance'] = df['list1'].apply(lambda x: len(list(next(iter(())) if not all(i in list2 for i in x) else i for i in x))) 

Y el tiempo:

 %timeit list2 = df2['list2'].sort_values().tolist();df['occurance'] = df['list1'].apply(lambda x: len(list(next(iter(())) if not all(i in list2 for i in x) else i for i in x))) 

100 bucles, lo mejor de 3: 14.8 ms por bucle