اذهب إلى المحتوى

السؤال

نشر (معدل)

لدي بيانات في شكل اثنان dataframes كالتالي:

df1 = DataFrame([[10],[20],[30],[40],[50]], index=['one','two','three','four','five'], columns=['number'])

       number
one       10
two       20
three     30
four      40
five      50

df2 = DataFrame([['a'],['b'],['c'],['d'],['e']], index=['two','four','one','three','five'], columns=['letter'])

      letter
two       a
four      b
one       c
three     d
five      e

وأريد انشاء dataframe جديدة تقوم بدمجهم معا عن طريق المقارنة بين ال index وجمع ما هو متشابه سويا بحيث يكون الخرج كالتالي:

      number letter
one         1      a
two         2      b
three       3      c
four        4      d
five        5      e

مع ملاحظة أن العناصر ليست مرتبة سوياً حتى أستطيع دمجهم مباشرة وانما يجب البحث عن التشابهة أولا قبل الدمج. كيف يمكنني فعل هذا؟

تم التعديل في بواسطة Mohamed Elnemr

Recommended Posts

  • 0
نشر

يمكنك استخدام الدالة get_close_matches للمقارنة بين العناصر وربط العناصر المتشابهة سويا ثم استخدام الدالة join لجمعهم سويا مثل الكود التالي:

In [1]: import difflib 

In [2]: difflib.get_close_matches
Out[3]: <function difflib.get_close_matches>

In [4]: df2.index = df2.index.map(lambda x: difflib.get_close_matches(x, df1.index)[0])

In [5]: df2
Out[5]: 
      letter
one        a
two        b
three      c
four       d
five       e

In [6]: df1.join(df2)
Out[6]: 
       number letter
one        10      a
two        20      b
three      30      c
four       40      d
five       50      e

كذلك يمكنك استخدام الدالة merge اذا كانت الdataframes علي هيئة أعمدة كالتالي:

df1 = DataFrame([[10,'one'],[20,'two'],[30,'three'],[40,'four'],[50,'five']], columns=['number', 'name'])
df2 = DataFrame([['a','one'],['b','two'],['c','three'],['d','four'],['e','five']], columns=['letter', 'name'])

df2['name'] = df2['name'].apply(lambda x: difflib.get_close_matches(x, df1['name'])[0])
df1.merge(df2)

أو استخدام المكتبة fuzzywuzzy لجمعهم سويا كالتالي:

from fuzzywuzzy import fuzz
from fuzzywuzzy import process

fuzzy_merge(df1, df2, 'index', 'index', threshold=80)
  • 0
نشر

يوجد عدة طرق لتنفيذ المطلوب كما شرح أحمد في التعليق السابق ولكن في بعض الأحيان تحتاج لمكتبة لتسهيل الأمر وإضافة بعض المميزات ويمكنك استخدام المكتبة fuzzymatcher لتنفيذ المطلوب

قم بتثبيتها كالتالي

pip install fuzzymatcher

لاحظ المثال التالي

from fuzzymatcher import link_table, fuzzy_left_join

left_on = ["fname", "mname", "lname",  "dob"]

right_on = ["name", "middlename", "surname", "date"]

fuzzymatcher.link_table(df_left, df_right, left_on, right_on)

 

  • 0
نشر

إضافة للطرق أعلاه.. فلأداء أعلى يفضل استخدام خوارزمية مطابقة السلاسل Jaro-Winkle للقيام بهكذا عمليات، فهي الأفضل من ناحية الأداء والأكثر دقة :


import pandas as pd
import jellyfish
df1 = pd.DataFrame([[1],[2],[3],[4],[5]], index=['one','two','three','four','five'], columns=['number'])
df1
"""
    number
one   	1
two 	  2
three 	3
four 	  4
five 	  5
"""
df2 = pd.DataFrame([['a'],['b'],['c'],['d'],['e']], index=['one','too','three','fours','five'], columns=['letter'])
df2
"""
  letter
one   	a
too   	b
three 	c
fours 	d
five  	e
"""
def get_closest_match(x, list_strings):
  best_match = None
  highest_jw = 0
  for current_string in list_strings:
    current_score = jellyfish.jaro_winkler(x, current_string)
    if(current_score > highest_jw):
      highest_jw = current_score
      best_match = current_string
  return best_match
df2.index = df2.index.map(lambda x: get_closest_match(x, df1.index))
df1.join(df2)
"""
    number 	letter
one   	1 	a
two   	2 	b
three 	3 	c
four 	  4 	d
five 	  5 	e
"""

 

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...