Сравнение фреймов данных с двумя разными количествами столбцов

Мне нужно сравнить два кадра данных с разными столбцами и найти различия между ними.

Хотя этот пример является числовым, мои данные — нет, я использую его как образец набора данных.

import pandas as pd

# Sample DataFrames
ProdDF = pd.DataFrame({'Project.name': ['Project A', 'Project B', 'Project C', 'Project D'],
                'Line identifier': [1, 2, 3, 4],
                'Column1': [10, 20, 30, 40],
                'Column2': [100, 200, 300, 400]})

TestDF = pd.DataFrame({'Project.name': ['Project A', 'Project B', 'Project C', 'Project E'],
                'Line identifier': [1, 2, 3, 5],
                'Column1': [10, 20, 35, 45],
                'Column2': [100, 200, 350, 450],
                'Column3': [100, 200, 350, 450]})
key_columns = ['Project.name', 'Line identifier']

# Merge DataFrames on key columns
merged_df = pd.merge(ProdDF, TestDF, on=key_columns, how='outer', suffixes=('_Prod', 
    '_Test'))

print(merged_df)

output = pd.DataFrame(columns=['Row', 'Column', 'Misaligned Data'])

for index, row in merged_df.iterrows():
    for column in merged_df.columns:
        if column not in key_columns:
            prod_column = column + '_Prod'
            test_column = column + '_Test'

            if prod_column in merged_df.columns and test_column in merged_df.columns:
                if row[prod_column] != row[test_column]:
                    output = output.append({'Row': index, 'Column': column, 'Misaligned Data': (row[prod_column], row[test_column])}, ignore_index=True)

print(output)

Это дает мне следующий результат:

Project.name  Line identifier  Column1_Prod  Column2_Prod  Column1_Test  Column2_Test  
Column3
0    Project A                1          10.0         100.0          10.0         100.0    
100.0
1    Project B                2          20.0         200.0          20.0         200.0    
200.0
2    Project C                3          30.0         300.0          35.0         350.0    
350.0

Я хотел бы, чтобы результат был:

Project.Name, Line identifier Prod Test
Project C       3              30   35
Project A       1              100   NaN
Project A       2              200   NaN
Project A       3              250   NaN

Я ищу только различия между кадрами данных.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
75
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вместо этого вы можете изменить свой цикл, сравнивая столбцы из кадра данных Prod, чтобы найти различия с merged_df.

formatted_output = []

for index, row in merged_df.iterrows():
    # compare columns from ProdDF
    for column in ProdDF.columns.difference(key_columns):
        prod_column = column + '_Prod'
        test_column = column + '_Test'

        # Check if both columns are in the merged DataFrame
        if prod_column in merged_df.columns or test_column in merged_df.columns:
            prod_value = row[prod_column] if prod_column in merged_df.columns else None
            test_value = row[test_column] if test_column in merged_df.columns else None

            # compare to find differences
            if prod_value != test_value:
                formatted_output.append({
                    'Project.Name': row['Project.name'],
                    'Line identifier': row['Line identifier'],
                    'Prod': prod_value,
                    'Test': test_value
                })

output_df = pd.DataFrame(formatted_output)

# sort by 'Project.Name' and 'Line identifier'
output_df = output_df.sort_values(by=['Project.Name', 'Line identifier'])

# print DataFrame with formatted output
print(output_df)

После добавления formatted_output = [] сверху, это потрясающе, чем вы так много

Roger i 21.06.2024 19:47

df.iterrows обычно неэффективен (см. здесь ). Вместо этого подготовьте данные для использования в df.compare:

import pandas as pd

idx = ['Project.name', 'Line identifier']
keys = ('Prod', 'Test')

comp = (pd.concat([df.set_index(idx) for df in [ProdDF, TestDF]],
                  axis=0, 
                  join='inner', 
                  keys=keys
                  )
        .unstack(0)
        .swaplevel(axis=1)
        .pipe(lambda df: df[keys[0]]
              .compare(df[keys[1]],
                       result_names=keys
                       )
              )
        )

Выход:

                             Column1       Column2       
                                Prod  Test    Prod   Test
Project.name Line identifier                             
Project C    3                  30.0  35.0   300.0  350.0
Project D    4                  40.0   NaN   400.0    NaN
Project E    5                   NaN  45.0     NaN  450.0

Чтобы соответствовать конкретному формату вашего вопроса, добавьте:

comp.stack(0).droplevel(-1).reset_index()

  Project.name  Line identifier   Prod   Test
0    Project C                3   30.0   35.0
1    Project C                3  300.0  350.0
2    Project D                4   40.0    NaN
3    Project D                4  400.0    NaN
4    Project E                5    NaN   45.0
5    Project E                5    NaN  450.0

Объяснение / Промежуточные продукты

  • Установите idx (ваш «key_columns») в качестве индекса для вашего dfs с помощью df.set_index.
  • Объедините с помощью pd.concat на axis=0.
    • join='inner' отбрасывает столбцы не общие.
    • keys=keys отслеживает источник («Prod» или «Test»).
# pd.concat(...)

                                   Column1  Column2
     Project.name Line identifier                  
Prod Project A    1                     10      100
     Project B    2                     20      200
     Project C    3                     30      300
     Project D    4                     40      400
Test Project A    1                     10      100
     Project B    2                     20      200
     Project C    3                     35      350
     Project E    5                     45      450
  • Разберите стек с помощью df.unstack , чтобы переместить keys уровень индекса (0) в столбцы, и поменяйте местами уровни с помощью df.swaplevel, чтобы сделать его верхним уровнем MultiIndex:
# pd.concat(...).unstack(0).swaplevel(axis=1)

                                Prod    Test    Prod    Test
                             Column1 Column1 Column2 Column2
Project.name Line identifier                                
Project A    1                  10.0    10.0   100.0   100.0
Project B    2                  20.0    20.0   200.0   200.0
Project C    3                  30.0    35.0   300.0   350.0
Project D    4                  40.0     NaN   400.0     NaN
Project E    5                   NaN    45.0     NaN   450.0
  • Используйте трубку для цепочки операций, применяя df.compare между «Prod» (df[keys[0]]) и «Test» (df[keys[1]]).
    • result_names=keys гарантирует, что в результате будут использоваться эти имена, а не значения по умолчанию «self» и «other».

Другие вопросы по теме