Python: заменить df1.значения col с df2.значения col2

У меня есть два фрейма данных df1 и df2.
В df1 у меня 50 столбцов, а в df2 у меня 50+ столбцов. Чего я хочу достичь, так это
В df1 у меня есть 13000 строк и тема имени столбца, где имена всех субъектов даны.
В df2 у меня есть 250 строк и вдоль 50+ у меня есть два столбца с именем subject code и subject_name.

        Here is an example of my datasets:

        df1 = 
        index     subjects
        0         Biology
        1         Physicss
        2         Chemistry
        3         Biology
        4         Physics
        5         Physics
        6         Biolgy

    df2 = 
        index     subject_name    subject_code
        0         Biology         BIO
        1         Physics         PHY
        2         Chemistry       CHE
        3         Medical         MED
        4         Programming     PRO
        5         Maths           MAT
        6         Literature      LIT 

My desired output in df1 (after replacing subject_name and fixing the spelling errors) is:
            index     subjects        subject_code
            0         Biology         BIO
            1         Physics         PHY
            2         Chemistry       CHE
            3         Biology         BIO
            4         Physics         PHY
            5         Physics         PHY
            6         Biology         BIO

Что происходит на моем конце, так это то, что я хочу объединить все значения субъекта в df1 со значениями в df2 значениях имени субъекта. В df1 есть около 500 строк, где я получаю NAN после того, как я объединяю оба столбца в один, поскольку в этих 500 строках есть некоторая разница в написании темы.
Я пробовал решение, приведенное по следующим ссылкам, но не работал для меня:
замените значения Индекса df значениями из списка, но игнорируйте пустые строки

Python pandas: замена значений нескольких столбцов, соответствующих нескольким столбцам из другого фрейма данных

            Here is my code:

            df_merged = pd.merge(df1_subject,df2_subjectname, left_on='subjects', right_on='subject_name')
        df_merged.head()

Может ли кто-нибудь сказать мне, как я могу исправить эту проблему, поскольку я уже потратил 8 часов на эту проблему, но не могу решить ее.

Овации

2 ответа

  1. Одна из проблем, которые у вас есть, — неправильное написание. Вы можете попытаться гармонизировать правописание предмета как dataframesс помощью difflibмодуля, так и его get_close_matchesметода.

    С помощью этого кода будет возвращена ближайшая тема соответствия для каждого соответствия в df1and и df2. df1'sстолбцы будут обновлены, чтобы отразить это. Таким образом, даже если имя темы написано неправильно, теперь оно будет иметь одинаковое написание в обоихdataframes.

    import pandas as pd
    import difflib
    
    df2['subject_name'] = df2.subject_name.map(lambda x: difflib.get_close_matches(x, df1.subject)[0])
    

    После этого можно попробовать слить. Это может решить вашу проблему, но было бы легче исправить, если вы предоставите воспроизводимый пример.

  2. Исправить орфографию затем объединить…

    import pandas as pd
    import operator, collections
    
    df1 = pd.DataFrame.from_items([("subjects",
                                    ["Biology","Physicss","Phsicss","Chemistry",
                                     "Biology","Physics","Physics","Biolgy","navelgazing"])])
    df2 = pd.DataFrame.from_items([("subject_name",
                                    ["Biology","Physics","Chemistry","Medical",
                                     "Programming","Maths","Literature"]),
                                   ("subject_code",
                                    ["BIO","PHY","CHE","MED","PRO","MAT","LIT"])])
    

    Найти орфографические ошибки:

    misspelled = set(df1.subjects) - set(df2.subject_name)
    

    Найдите тему, которая лучше всего соответствует неправильному написанию, и создайте словарь — > {mis_sp : subject_name}

    difference = operator.itemgetter(1)
    subject = operator.itemgetter(0)
    def foo1(word, candidates):
        '''Returns the most likely match for a misspelled word
        '''
        temp = []
        for candidate in candidates:
            count1 = collections.Counter(word)
            count2 = collections.Counter(candidate)
            diff1 = count1 - count2
            diff2 = count2 - count1
            diff = sum(diff1.values())
            diff += sum(diff2.values())
            temp.append((candidate, diff))
        return subject(min(temp, key = difference))
    
    def foo2(words):
        '''Yields (misspelled-word, corrected-word) tuples from misspelled words'''
        for word in words:
            name = foo1(word, df2.subject_name)
            if name:
                yield (word, name)
    
    d = dict(foo2(misspelled))               
    

    Исправьте все ошибки в df1

    def foo3(thing):
        return d.get(thing, thing)
    
    df3 = df1.applymap(foo3)
    

    Объединить

    df2 = df2.set_index("subject_name")
    df3 = df3.merge(df2, left_on = "subjects", right_index = True, how = 'left')
    

    foo1 возможно, этого будет достаточно для этой цели, но есть лучшие, более сложные алгоритмы для исправления орфографии. возможно, http://norvig.com/spell-correct.html

    Просто прочитайте решение @conner. Я не знал, что difflib был там, так что лучше foo1было бы,

    def foo1(word, candidates):
        try:
            return difflib.get_close_matches(word, candidates, 1)[0]
        except IndexError as e:
            # there isn't a close match
            return None