Pandas: compruebe si una columna de cadena en un dataframe contiene un par de cadenas de otro dataframe

Esta pregunta se basa en otra pregunta que hice, donde no cubrí el problema por completo: Pandas: compruebe si una columna de cadena contiene un par de cadenas

Esta es una versión modificada de la pregunta.

Tengo dos marcos de datos:

df1 = pd.DataFrame({'consumption':['squirrel ate apple', 'monkey likes apple', 'monkey banana gets', 'badger gets banana', 'giraffe eats grass', 'badger apple loves', 'elephant is huge', 'elephant eats banana tree', 'squirrel digs in grass']}) df2 = pd.DataFrame({'food':['apple', 'apple', 'banana', 'banana'], 'creature':['squirrel', 'badger', 'monkey', 'elephant']}) 

El objective es probar si df.food:df.creature pares están presentes en df1.consumptions.

La respuesta esperada para esta prueba en el ejemplo anterior sería:

 ['True', 'False', 'True', 'False', 'False', 'True', 'False', 'True', 'False'] 

El patrón es:

squirrel ate apple = True ya que ardilla y manzana son un par. a mono le gusta la manzana = Falso ya que el mono y la manzana no son un par que estamos buscando.

Estaba pensando en construir un diccionario de marcos de datos de los valores de los pares donde cada dataframe sería para una criatura para, por ejemplo, una ardilla, un mono, etc., y luego usar np.where para crear una expresión booleana y realizar un str.contains.

No estoy seguro si esa es la forma más fácil.

Considere este enfoque vectorizado:

 from sklearn.feature_extraction.text import CountVectorizer vect = CountVectorizer() X = vect.fit_transform(df1.consumption) Y = vect.transform(df2.creature + ' ' + df2.food) res = np.ravel(np.any((X.dot(YT) > 1).todense(), axis=1)) 

Resultado:

 In [67]: res Out[67]: array([ True, False, True, False, False, True, False, True, False], dtype=bool) 

Explicación:

 In [68]: pd.DataFrame(X.toarray(), columns=vect.get_feature_names()) Out[68]: apple ate badger banana digs eats elephant gets giraffe grass huge in is likes loves monkey squirrel tree 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 2 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 3 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 4 0 0 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 5 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 6 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 7 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 1 8 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 0 1 0 In [69]: pd.DataFrame(Y.toarray(), columns=vect.get_feature_names()) Out[69]: apple ate badger banana digs eats elephant gets giraffe grass huge in is likes loves monkey squirrel tree 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 3 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 

ACTUALIZAR:

 In [92]: df1['match'] = np.ravel(np.any((X.dot(YT) > 1).todense(), axis=1)) In [93]: df1 Out[93]: consumption match 0 squirrel ate apple True 1 monkey likes apple False 2 monkey banana gets True 3 badger gets banana False 4 giraffe eats grass False 5 badger apple loves True 6 elephant is huge False 7 elephant eats banana tree True 8 squirrel digs in grass False 9 squirrel.eats/apple True # <----- NOTE 

Esta es mi respuesta usando comprensiones y zip
Tenga en cuenta, esto comprueba subcadenas en df1

 c = df1.consumption.values.tolist() f = df2.food.values.tolist() a = df2.creature.values.tolist() check = np.array([[fd in cs and cr in cs for fd, cr in zip(f, a)] for cs in c]) check.any(1) array([ True, False, True, False, False, True, False, True, False], dtype=bool) 

Esta es una versión de pandas de lo que hizo @MaxU. Respeta lo que hizo … ¡es genial!

 X = df1.consumption.str.get_dummies(' ') Y = (df2.creature + ' ' + df2.food).str.get_dummies(' ') \ .reindex_axis(X.columns, 1, fill_value=0) # This is where you can see which rows from `df2` (columns) # matched with which rows from `df1` (rows) XY = X.dot(YT) print(XY) 0 1 2 3 0 2 1 0 0 1 1 1 1 0 2 0 0 2 1 3 0 1 1 1 4 0 0 0 0 5 1 2 0 0 6 0 0 0 1 7 0 0 1 2 8 1 0 0 0 # return the desired `True`s and `False`s XY.gt(1).any(1) 0 True 1 False 2 True 3 False 4 False 5 True 6 False 7 True 8 False dtype: bool 

pruebas ingenuas

introduzca la descripción de la imagen aquí