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 
  • Umgestaltung von Dataframes in Pandas basierend auf Spaltenbeschriftungen
  • Pandas: Speichern, um das Codierungsproblem zu übertreffen
  • Mapping einer (Lambda) -Funktion auf Listen von Strings fehlschlägt 'float' Objekt nicht iterable
  • Anpassen von Achsen in 3D hist python / matplotlib
  • Normalisierung von Daten durch Duplizierung
  • Pandas dataframe konvertiert bestimmte Spalten von string zu float
  • Python pandas: Umbenennen einer Serie in einem Dataframe?
  • Gruppenoperationen auf Pandas Spalte mit Listen
  • Pandas Stack / Groupby, um ein neues Dataframe zu machen
  • Verlieren von Zeitzone-Bewusstsein beim Speichern von hyperarchischen Pandas DatetimeIndex zu hdf5 in Python
  • Wie erstelle ich ein Pandas-Dataframe mit Spalten mit Sonderzeichen?
  • Python ist die beste Programmiersprache der Welt.