Pandas: Wenn Wert in einem Dataframe String aus einem anderen Dataframe enthält, Sperren anfügen

Angenommen, ich habe zwei Dataframes df1 und df2. Ich möchte einige Spalten von df2 an df1 anhängen, wenn der Wert einer bestimmten Spalte von df1 den String in einer bestimmten Spalte von df2 enthält, NaN wenn nicht.

Ein kleines Beispiel:

import pandas as pd df1 = pd.DataFrame({'col': ['abc', 'def', 'abg', 'xyz']}) df2 = pd.DataFrame({'col1': ['ab', 'ef'], 'col2': ['match1', 'match2'], 'col3': [1, 2]}) df1:    col 0  abc 1  def 2  abg 3 xyz df2:   col1    col2 col3 0   ab  match1 1 1   ef  match2 2 

Ich will:

    col col2_match col3_match 0  abc match1 1 1  def match2 2 2  abg match1 1 3 xyz NaN NaN 

Ich habe es geschafft, es in einer schmutzigen und uneffizienten Weise zu tun, aber in meinem Fall df1 enthält wie 100K Zeilen und es dauert ewig …

Danke im Voraus !

BEARBEITEN

Ein bisschen dreckig aber bekommt die Arbeit relativ schnell (ich denke immer da gibt es einen klügsten Weg aber …):

 import pandas as pd import numpy as np df1 = pd.DataFrame({'col': ['abc', 'def', 'abg']}) df2 = pd.DataFrame({'col1': ['ab', 'ef'], 'col2': ['match1', 'match2'], 'col3': [1, 2]}) def return_nan(tup): return(np.nan if len(tup[0]) == 0 else tup[0][0]) def get_indexes_match(l1, l2): return([return_nan(np.where([x in e for x in l2])) for e in l1]) def merge(df1, df2, left_on, right_on): df1.loc[:, 'idx'] = get_indexes_match(df1[left_on].values, df2[right_on].values) df2.loc[:, 'idx'] = np.arange(len(df2)) return(pd.merge(df1, df2, how='left', on='idx')) merge(df1, df2, left_on='col', right_on='col1') 

One Solution collect form web for “Pandas: Wenn Wert in einem Dataframe String aus einem anderen Dataframe enthält, Sperren anfügen”

Sie können Python-Difflib-Modul für Fuzzy-Match wie folgt verwenden

 import difflib difflib.get_close_matches df1.col = df1.col.map(lambda x: difflib.get_close_matches(x, df2.col1)[0]) 

Also jetzt dein df1 ist

  col 0 ab 1 ef 2 ab 

Sie können es df3 nennen, wenn Sie df1 unverändert halten wollen.

Jetzt können Sie fusionieren

 merged = df1.merge(df2, left_on = 'col', right_on = 'col1', how = 'outer').drop('col1', axis = 1) 

Das zusammengeführte Dataframe sieht aus wie

  col col2 col3 0 ab match1 1 1 ab match1 1 2 ef match2 2 

EDIT: Im Falle von keinem Spiel wie das neue Beispiel gegeben, müssen Sie nur eine Bedingung in Lambda setzen

 df1.col = df1.col.map(lambda x: difflib.get_close_matches(x, df2.col1)[0] if difflib.get_close_matches(x, df2.col1) else x) 

Jetzt nach dem Zusammenführen bekommst du

  col col2 col3 0 ab match1 1 1 ab match1 1 2 ef match2 2 3 xyz NaN NaN 
  • Verwenden von Formatieren, um String aus Dataframe zu erstellen
  • Pandas to_latex () entweicht mathmode
  • Lesen von großen Textdateien mit Pandas
  • Logikoperator für Boolesche Indizierung in Pandas
  • Konvertieren von Python-Tupel, Listen, Wörterbücher mit Pandas-Objekten (Serien / Dataframes) zu json
  • Python Pandas: Verwenden von Aggregate vs Apply, um neue Spalten zu definieren
  • Verwenden von groupy und subplots mit pandas dataframe
  • Fehler beim Schreiben der Pivot-Tabelle zum Excel-Datei
  • Suchen von Zeilen mit den maximalen Werten innerhalb einer Gruppe
  • Konvertieren Sie numpy Typ in Python
  • Pivot-Tabelle Probleme: Fehler 'Keine numerischen Typen zu aggregieren'
  • Python ist die beste Programmiersprache der Welt.