Лучший способ сравнить 2 DFS, получить имя разных col & before + after vals? - PullRequest
0 голосов
/ 18 сентября 2018

Как лучше всего сравнивать 2 кадра данных с одинаковыми именами столбцов, строка за строкой, если ячейка отличается, имеет значение До и После и какая ячейка отличается в этом кадре данных.

Я знаю, что этот вопрос задавали много, но ни одно из приложений не подходит для моего варианта использования.Скорость важна.Существует пакет под названием datacompy, но это не хорошо, если мне нужно сравнить 5000 циклов данных в цикле (я сравниваю только 2 за раз, но всего около 10000 и 5000 раз).

Я не знаюне хочу объединять кадры данных в столбцеЯ хочу сравнить их построчно.Строка 1 со строкой 1. И т. Д. Если столбец в строке 1 отличается, мне нужно знать только имя столбца, до и после.Возможно, если он числовой, я мог бы также добавить столбец с abs val.диф.

Проблема в том, что иногда существует крайний случай, когда строки не в порядке (только на 1 запись), и не хотят, чтобы они выдавались как ложные срабатывания.

Пример:

Эти кадры данных будут созданы при прохождении гонки # (имеется 5000 номеров гонки)

df1

+-----+-------+--+------+--+----------+----------+-------------+--+
| Id  | Speed |  | Name |  | Distance |  |          Location   |  |
+-----+-------+--+------+--+----------+----------+-------------+--+
| 181 |  10.3 |  | Joe  |  |        2 |          | New York    |  |
| 192 |   9.1 |  | Rob  |  |        1 |          | Chicago     |  |
| 910 |   1.0 |  | Fred |  |        5 |          | Los Angeles |  |
|  97 |   1.8 |  | Bob  |  |        8 |          | New York    |  |
|  88 |   1.2 |  | Ken  |  |        7 |          | Miami       |  |
|  99 |   1.1 |  | Mark |  |        6 |          | Austin      |  |
+-----+-------+--+------+--+----------+----------+-------------+--+

df2:

+-----+-------+--+------+--+----------+----------+-------------+--+
| Id  | Speed |  | Name |  | Distance | |             |  Location |
+-----+-------+--+------+--+----------+----------+-------------+--+
| 181 |  10.3 |  | Joe  |  |        2 |          | New York    |  |
| 192 |   9.4 |  | Rob  |  |        1 |          | Chicago     |  |
| 910 |   1.0 |  | Fred |  |        5 |          | Los Angeles |  |
|  97 |   1.5 |  | Bob  |  |        8 |          | New York    |  |
|  99 |   1.1 |  | Mark |  |        6 |          | Austin      |  |
|  88 |   1.2 |  | Ken  |  |        7 |          | Miami       |  |
+-----+-------+--+------+--+----------+----------+-------------+--+

diff:

+-------+----------+--------+-------+
| Race# | Diff_col | Before | After |
+-------+----------+--------+-------+
|   123 | Speed    |    9.1 |   9.4 |
|   123 | Speed    |    1.8 |   1.5 |

Пример ложного срабатывания - последние 2 строки, Кен + Марк.Я мог бы суммировать различия в одной строке на гонку, но если в кадре данных есть 3000 записей и есть 1000 различий (маловероятно, но возможно), то у меня будет множество столбцов.Я подумал, что это было проще, так как я мог экспортировать в Excel, а затем отсортировать по расе #, увидеть все различия или по diff_col, посмотреть, какие столбцы разные.

            def DiffCol2(df1, df2, race_num):
is_diff = False
diff_cols_list = []
row_coords, col_coords = np.where(df1 != df2)
diffDf = []
alldiffDf = []
for y in set(col_coords): 
    col_df1 = df1.iloc[:,y].name
    col_df2 = df2.iloc[:,y].name
    for index, row in df1.iterrows(): 
        if df1.loc[index, col_df1] != df2.loc[index, col_df2]:
            col_name = col_df1 
            if col_df1 != col_df2: col_name = (col_df1, col_df2)
            diffDf.append({‘Race #’: race_num,'Column Name': col_name, 'Before: df2.loc[index, col_df2], ‘After’: df1.loc[index, col_df1]})

            try: 
                check_edge_case = df1.loc[index, col_df1] == df2.loc[index+1, col_df1]
            except: 
                check_edge_case = False
            try: 
                check_edge_case_two = df1.loc[index, col_df1] == df2.loc[index-1, col_df1]
            except: 
                check_edge_case_two = False
            if not (check_edge_case or check_edge_case_two):
                col_name = col_df1
                if col_df1 != col_df2:
                    col_name = (col_df1, col_df2) #if for some reason column name isn’t the same, which should never happen but in case, I want to know both col names
                is_diff = True
                diffDf.append({‘Race #’: race_num,'Column Name': col_name, 'Before: df2.loc[index, col_df2], ‘After’: df1.loc[index, col_df1]})
return diffDf, alldiffDf, is_diff

[заранее извиняюсь за странно отформатированные таблицы, я приложил все усилия, учитывая, как раздражает вставка таблиц в s / o]

1 Ответ

0 голосов
/ 18 сентября 2018

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

df1 = pd.DataFrame(np.random.randn(10, 4), columns=list('ABCD'))
df2 = df1.copy(deep=True)
df2['B'][5] = 100 # Creating difference
df2['C'][6] = 100 # Creating difference
dif=[]
for col in df1.columns:
    for bef, aft in zip(df1[col], df2[col]):
        if bef!=aft:
            dif.append([col, bef, aft])
print(dif)

Результаты ниже

enter image description here

enter image description here

enter image description here

Альтернативное решение без петель

df = df1.melt()
df.columns=['Column', 'Before']
df.insert(2, 'After', df2.melt().value)
df[df.Before!=df.After]

enter image description here

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