Тактика для сравнения фреймов данных, когда имена столбцов отличаются, а последовательность неизвестна - PullRequest
0 голосов
/ 22 октября 2019

Мне нужно сравнить два DataFrames одновременно, чтобы выяснить, совпадают ли значения или нет. Один DataFrame взят из рабочей книги Excel, а другой - из SQL-запроса. Проблема в том, что не только столбцы могут быть не последовательными, но и заголовки столбцов могут иметь другое имя. Это помешало бы мне просто получить заголовки столбцов Excel и использовать их для перестановки столбцов в SQL DataFrame. Кроме того, я буду делать это на нескольких вкладках в рабочей книге Excel и по различным запросам. Мало того, что имена столбцов отличаются от Excel к SQL, но они также могут отличаться от Excel к Excel и SQL к SQL.

Я создал решение, но оно не только очень изменчиво, но яобеспокоен тем, что он начнет занимать значительное количество памяти для запуска.

Решение заключается в использовании списков в списке. Если значение excel находится в том же списке, что и значение SQL, они считаются совпадающими, и функция возвращает окончательный порядок, который должен изменить SQL DataFrame, чтобы соответствовать тому же порядку, который используется Excel DataFrame. В случае, если я упустил некоторые возможности, и вновь созданный список заказов имеет длину, отличную от необходимой, я просто возвращаю исходный список заголовков SQL в исходном порядке.

Приведенный ниже пример - лишь малая часть того, чтоЯ на самом деле буду работать с. Фактическое количество вариантов и имен столбцов намного выше, чем в примере ниже. Будем благодарны за любые предложения по улучшению этой функции или по лучшему решению этой проблемы.

Вот пример:

#Example data
exceltab1 = {'ColA':[1,2,3],
        'ColB':[3,4,1],
        'ColC':[4,1,2]}

exceltab2 = {'cColumn':[10,15,17],
         'aColumn':[5,7,8],
        'bColumn':[9,8,7]}

sqltab1 = {'Col/A':[1,2,3],
        'Col/C':[4,1,2],
        'Col/B':[3,4,1]}

sqltab2 = {'col_banana':[9,8,7],
         'col_apple':[5,7,8],
        'col_carrot':[10,15,17]}

#Code
import pandas as pd
ec1 = pd.DataFrame(exceltab1)
ec2 = pd.DataFrame(exceltab2)

sq1 = pd.DataFrame(sqltab1)
sq2 = pd.DataFrame(sqltab2)


#This will fail because the columns are out of order
result1 = (ec1.values == sq1.values).all()


def translate(excel_headers ,sql_headers):
    translator = [["ColA", "aColumn", "Col/A", "col_apple"],
    ["ColB", "bColumn", "Col/B", "col_banana"],
    ["ColC", "cColumn", "Col/C", "col_carrot"]]
    order = []
for i in range(len(excel_headers)):
        for list in translator:
            for item in sql_headers:
                if excel_headers[i] in list and item in list:
                    order.append(item)
                    break
    if len(order) != len(sql_headers):
        return sql_headers
    else:
        return order


sq1 =sq1[translate(list(ec1.columns), list(sq1.columns))]


#This will pass because the columns now line up
result2 = (ec1.values == sq1.values).all()

print(f"Result 1: {result1} , Result 2: {result2}")

Результат: Результат 1: Ложь, Результат 2: Правда

1 Ответ

0 голосов
/ 22 октября 2019

Нет кода, но есть алгоритм.

У нас есть набор столбцов A и другого B. Мы можем сравнить столбец из A и другой из B и посмотреть, равны ли они. Мы делаем это для всех комбинаций столбцов.

Это можно рассматривать как двудольный граф, в котором есть две группы вершин A и B (одна вершина для каждого столбца), и существует ребро между двумя вершинами, если этидва столбца равны. Тогда проблема перевода имен столбцов эквивалентна нахождению идеального соответствия в этом двудольном графе.

Алгоритм, с которым это делается, - это Хопкрофт-Карп, который имеет реализацию Python здесь . Это находит максимальное совпадение, поэтому вам все равно нужно проверить, найдено ли оно идеального соответствия (то есть каждый столбец из A имеет связанный столбец из B).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...