Как объединить два Pandas кадра данных с NaN и дублирующиеся ключи объединения? - PullRequest
0 голосов
/ 10 апреля 2020

Не уверен, какова точная терминология для этого - но скажем, у меня есть эти два файла:

dataA.csv:

event,car,bike,bus
63175,,18,
65641,45,9,
65805,,,54
68388,,65,
68388,,,39
73041,7,,18
79336,,44,
79423,,,5

dataB.csv:

event,car,truck,bike
69834,12,,
73704,,32,
74798,,,74
77290,29,,45
79336,,55,
88795,15,,4
88979,88,,

Я хочу объединить / объединить / объединить эти таблицы со столбцом «событие» в качестве ключа объединения; однако обратите внимание, что:

  • В обеих таблицах .csv отсутствуют значения (NaN)
  • В противном случае данные, хранящиеся в обеих таблицах, представляют собой целые числа без знака
  • Некоторые имена столбцов повторяются в обеих таблицах, другие являются уникальными для таблицы
  • Столбец «событие» (который является «ключом соединения») в dataA имеет значение 68388 в двух строках (я называю это дубликатом); и значение «событие» 79336 появляется как в dataA, так и в dataB (я также называю это дубликатом)

Я пробовал этот код:

#!/usr/bin/env python3

import pandas as pd

dataA = pd.read_csv("dataA.csv", dtype='Int64')
dataB = pd.read_csv("dataB.csv", dtype='Int64')

print("dataA:")
print(dataA)
print("\ndataB:")
print(dataB)

dataMerged = pd.merge(dataA, dataB, on='event', how='outer').sort_values('event', ignore_index=True)
print("\ndataMerged:")
print(dataMerged)

... и вывод :

dataA:
   event   car  bike   bus
0  63175  <NA>    18  <NA>
1  65641    45     9  <NA>
2  65805  <NA>  <NA>    54
3  68388  <NA>    65  <NA>
4  68388  <NA>  <NA>    39
5  73041     7  <NA>    18
6  79336  <NA>    44  <NA>
7  79423  <NA>  <NA>     5

dataB:
   event   car  truck  bike
0  69834    12   <NA>  <NA>
1  73704  <NA>     32  <NA>
2  74798  <NA>   <NA>    74
3  77290    29   <NA>    45
4  79336  <NA>     55  <NA>
5  88795    15   <NA>     4
6  88979    88   <NA>  <NA>

dataMerged:
    event  car_x  bike_x   bus  car_y  truck  bike_y
0   63175   <NA>      18  <NA>   <NA>   <NA>    <NA>
1   65641     45       9  <NA>   <NA>   <NA>    <NA>
2   65805   <NA>    <NA>    54   <NA>   <NA>    <NA>
3   68388   <NA>      65  <NA>   <NA>   <NA>    <NA>
4   68388   <NA>    <NA>    39   <NA>   <NA>    <NA>
5   69834   <NA>    <NA>  <NA>     12   <NA>    <NA>
6   73041      7    <NA>    18   <NA>   <NA>    <NA>
7   73704   <NA>    <NA>  <NA>   <NA>     32    <NA>
8   74798   <NA>    <NA>  <NA>   <NA>   <NA>      74
9   77290   <NA>    <NA>  <NA>     29   <NA>      45
10  79336   <NA>      44  <NA>   <NA>     55    <NA>
11  79423   <NA>    <NA>     5   <NA>   <NA>    <NA>
12  88795   <NA>    <NA>  <NA>     15   <NA>       4
13  88979   <NA>    <NA>  <NA>     88   <NA>    <NA>

Обратите внимание, что объединение уже «сжало» значение «события» 79336 - у меня есть только одна строка с «событием» == 79336, и она содержит значения из обоих файлов; Тем не менее, все еще есть строки с «event» == 68388 - и я бы хотел только одну колонку «car» и «bike». Другими словами, я хочу, чтобы выходной результат был таким (отредактирован вручную, надеюсь, у меня нет ошибок):

    event   car  bike   bus  truck
0   63175  <NA>    18  <NA>   <NA>
1   65641    45     9  <NA>   <NA>
2   65805  <NA>  <NA>    54   <NA>
3   68388  <NA>    65    39   <NA>
4   69834    12  <NA>  <NA>   <NA>
5   73041     7  <NA>    18   <NA>
6   73704  <NA>  <NA>  <NA>     32
7   74798  <NA>    74  <NA>   <NA>
8   77290    29    45  <NA>   <NA>
9   79336  <NA>    44  <NA>     55
10  79423  <NA>  <NA>     5   <NA>
11  88795    15     4  <NA>   <NA>
12  88979    88  <NA>  <NA>   <NA>

Обратите внимание, что в моих данных, как правило, у меня нет «конфликтов», что is:

  • Либо одно значение является числом, другое - NaN (например, dataA("event"=68388,"bike")=65, dataB("event"=68388,"bike")=<NA>), и в этом случае выходные данные должны содержать число (например, out("event"=68388,"bike")=65)
  • Или оба значения являются NaN (например, dataA("event"=68388,"car")=<NA>, dataB("event"=68388,"car")=<NA>), и в этом случае выходные данные также должны содержать NaN (например, out("event"=68388,"car")=<NA>)
  • Или (очень редко) оба значения являются тот же номер (например, dataA("event"=50000,"ZZZ")=42, dataB("event"=50000,"ZZZ")=42), и в этом случае выходные данные должны также содержать тот же номер (например, out("event"=50000,"ZZZ")=42)

Как я могу добиться такого типа "сжатого слияния" с Pandas?

PS: было бы также хорошо знать, как можно справиться со случаем конфликта - то есть, есть разные числа, конкурирующие за один и тот же слот / ячейку в выходных данных (например, dataA("event"=90000,"ZZZ")=400, dataB("event"=90000,"ZZZ")=13) - в этом случае я хотел бы написать -1 в выводе, что является достаточно хорошим показателем конфликта в этом случае, дать n, что действительные данные - целое число без знака. Поскольку данные выше не содержат таких записей, просто знать это в принципе было бы здорово.

1 Ответ

1 голос
/ 10 апреля 2020

Мы можем сделать

#dfA=dfA.mask(dfA.eq('<NA>'))
#dfB=dfB.mask(dfB.eq('<NA>'))
df=pd.concat([dfA,dfB],sort=True).groupby('event').first().reset_index()
Out[61]: 
    event bike  bus  car truck
0   63175   18  NaN  NaN   NaN
1   65641    9  NaN   45   NaN
2   65805  NaN   54  NaN   NaN
3   68388   65   39  NaN   NaN
4   69834  NaN  NaN   12   NaN
5   73041  NaN   18    7   NaN
6   73704  NaN  NaN  NaN    32
7   74798   74  NaN  NaN   NaN
8   77290   45  NaN   29   NaN
9   79336   44  NaN  NaN    55
10  79423  NaN    5  NaN   NaN
11  88795    4  NaN   15   NaN
12  88979  NaN  NaN   88   NaN
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...