Python Pandas - получить совпадающие и не совпадающие записи между двумя кадрами данных - PullRequest
0 голосов
/ 21 октября 2018

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

У меня есть два фрейма данных, из которых я должен получить совпадающие и несоответствующие записи в новые данныекадров.

Пример:

DF1:

ID Name Number    DOB     Salary
1  AAA  1234   12-05-1996 100000
2  BBB  1235   16-08-1997 200000
3  CCC  1236   24-04-1998 389999
4  DDD  1237   05-09-2000 450000

DF2:

ID Name Number    DOB     Salary
1  AAA  1234   12-05-1996 100000
2  BBB  1235   16-08-1997 200000
3  CCC  1236   24-04-1998 389999
4  DDD  1237   05-09-2000 540000

И с первичными ключами, которые являются здесь ID и именем (вна самом деле количество ключей может варьироваться), мне нужно получить

Match_df:

ID Name Number    DOB     Salary
1  AAA  1234   12-05-1996 100000
2  BBB  1235   16-08-1997 200000
3  CCC  1236   24-04-1998 389999

Mismatch_df:

ID Name Number    DOB     Salary
4  DDD  1237   05-09-2000 540000

Я перепробовал все возможные способы, такие как

pd.merge(df1, df2, left_on=[ID,Name],right_on=[ID,Name], how='inner')

, и это создает все уникальные ключи в обоих фреймах данныхНо это также приводит к несовпадающим записям.

Но я получаю это как результат:

ID Name Number    DOB     Salary
1  AAA  1234   12-05-1996 100000
2  BBB  1235   16-08-1997 200000
3  CCC  1236   24-04-1998 389999
4  DDD  1237   05-09-2000 540000

, где также включается 4-я запись.

Здесь меняется только col col зарплаты, но в реальном времени, это может быть список столбцов для сравнения.

Из этого я должен получить только совпадающие записи в matched_df и несоответствующие записи в mismatch_df.

Пожалуйста, помогите мне в этом.

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

Заранее спасибо.

Ответы [ 4 ]

0 голосов
/ 21 октября 2018
# pick index keys and compare column(s)
keys = ['ID', 'Name']
# if comparing all columns:
col_list = [col for col in df1.columns if col not in keys]
# # if comparing specific columns:
# col_list = ['Salary', 'DOB']

# extend keys with col_list for next step
sel_cols = keys.copy()
sel_cols.extend(col_list)

# set a multi-index with keys
# to dataframes with col_list columns
dfa = df1[sel_cols].set_index(keys)
dfb = df2[sel_cols].set_index(keys)

# make an equivalency boolean mask
dfa.update(dfb)
mask = np.equal(df1[col_list].values, dfa.values).all(axis=1)

# slice df1 with mask
Match_df = df1[mask]
Mismatch_df = df1[~mask]
0 голосов
/ 21 октября 2018

Упрощенный Ответ на ваш вопрос с помощью df1.where:

Примечание: Полученные ячейки с NaN не удовлетворяют условиям, т.е. они не равныв двух кадрах данных.Те, которые имеют реальное значение, равны тем, которые равны в двух фреймах данных

>>> df1.where(df1.Salary==df2.Salary)
          DoB   ID  Name    Salary
0  12-05-1996  1    AAA  100000.0
1  16-08-1997  2    BBB  200000.0
2  24-04-1998  3    CCC  389999.0
3         NaN  NaN  NaN       NaN

При работе с pd.merge: если вы просто хотите объединить df1 & df1 без уровня столбца или индекса, тогда онпо умолчанию принимает пересечение столбцов в обоих фреймах данных.

>>> pd.merge(df1, df2)
          DoB  ID Name  Salary
0  12-05-1996   1  AAA  100000
1  16-08-1997   2  BBB  200000
2  24-04-1998   3  CCC  389999

Если вы хотите присоединиться к столбцу или уровню индекса, используйте on.

 >>> pd.merge(df1, df2, on="Salary")
        DoB_x  ID_x Name_x  Salary       DoB_y  ID_y Name_y
0  12-05-1996     1    AAA  100000  12-05-1996     1    AAA
1  16-08-1997     2    BBB  200000  16-08-1997     2    BBB
2  24-04-1998     3    CCC  389999  24-04-1998     3    CCC

Для несоответствия в df2: вы можете выбрать isin (dict) метод:

>>> df2[~df2.isin(df1.to_dict('l')).all(1)]
          DoB  ID Name  Salary
3  05-09-2000   4  DDD  540000

другим способом, как Мейблдано.

df2[~df2.isin(df1).all(axis=1)]
0 голосов
/ 21 октября 2018

Чтобы получить соответствие:

>> df1.merge(df2)

ID Name  Number         DOB  Salary
0   1  AAA    1234  12-05-1996  100000
1   2  BBB    1235  16-08-1997  200000
2   3  CCC    1236  24-04-1998  389999

И для несоответствия выберите строку в df2:

>> df2[~df2.isin(df1).all(axis=1)]

   Name  Number         DOB  Salary
ID                                 
4   DDD    1237  05-09-2000  540000
0 голосов
/ 21 октября 2018

Мое решение было бы немного другим и включало бы простое копирование зарплаты из другого набора данных.

Например:

DF1["Salary2"] = DF2["Salary"]

MatchDF = DF1[DF1["Salary"] == DF1["Salary2"]]
MisMatchDF = DF1[DF1["Salary"] != DF1["Salary2"]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...