Упорядочить столбцы DataFrame по заголовкам столбцов - PullRequest
0 голосов
/ 18 января 2019

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

DataFrameA

ID   Name    Age  Sex
1A1  Cling   21    M
1B2  Roger   22    M
1C3  Stew    23    M

DataFrameB

ID   FullName   Gender  Age
1B2  Roger       M       21
1C3  Rick        M       23
1D4  Ash         F       21

DataFrameB всегда будет иметь больше записей, чем DataFrameA, но записи, найденные в DataFrameA, могут все еще не находиться в DataFrameB. Имена столбцов в DataFrameA и DataFrameB различны. У меня отображение хранится в другом фрейме данных.

MappingDataFrame

DataFrameACol   DataFrameBCol
ID               ID
Name             FullName
Age              Age
Sex              Gender

Я хочу сравнить эти два и добавить рядом столбец с результатом.

Сумматор имени столбца для фрейма данных A = "_A_Txt"

Сумматор имени столбца для фрейма данных B = "_B_Txt"

ExpectedOutput

ID   Name_A_Txt FullName_B_Text   Result_Name   Age_A_Txt  Age_B_Txt   Result_Age     
1B2  Roger           Roger          Match        ...        ...
1C3  Stew            Rick           No Match     ...        ...

Перед именами столбцов должен быть добавлен текст.

В данный момент я использую цикл For для построения этой логики. Но на 1 миллион записей уходит много времени. Я оставил программу работающей более 50 минут, и она не была завершена, как в режиме реального времени, я создаю ее для более чем 100 столбцов.

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

Чтобы начать с DataFrameA и DataFrameB, используйте следующий код,

import pandas as pd

d = {
     'ID':['1A1', '1B2', '1C3'], 
     'Name':['Cling', 'Roger', 'Stew'],
     'Age':[21, 22, 23], 
     'Sex':['M', 'M', 'M']
     }

DataFrameA = pd.DataFrame(d)

d = {
     'ID':['1B2', '1C3', '1D4'], 
     'FullName':['Roger', 'Rick', 'Ash'],
     'Gender':['M', 'M', 'F'], 
     'Age':[21, 23, 21]
     }

DataFrameB = pd.DataFrame(d)

Я полагаю, что этот вопрос немного отличается от предложения (определения объединений), предоставленного Coldspeed, поскольку это также включает поиск различных имен столбцов и добавление нового столбца результатов вместе с ним. Кроме того, имена столбцов необходимо преобразовать на стороне результата.

OutputDataFrame выглядит как показано ниже,

Для лучшего понимания читателей я ставлю колонку имена в строке в порядке

Col 1 -  ID (Coming from DataFrameA)
Col 2 -  Name_X (Coming from DataFrameA)
Col 3 -  FullName_Y (Coming from DataFrameB)
Col 4 -  Result_Name (Name is what is there in DataFrameA and this is a comparison between Name_X and FullName_Y)
Col 5 -  Age_X (Coming from DataFrameA)
Col 6 -  Age_Y (Coming From DataFrameB)
Col 7 -  Result_Age (Age is what is there in DataFrameA and this is a result between Age_X and Age_Y)
Col 8 -  Sex_X (Coming from DataFrameA)
Col 9 -  Gender_Y (Coming from DataFrameB)
Col 10 - Result_Sex (Sex is what is there in DataFrameA and this is a result between Sex_X and Gender_Y)

1 Ответ

0 голосов
/ 18 января 2019
m = list(mapping_df.set_index('DataFrameACol')['DataFrameBCol']
                   .drop('ID')
                   .iteritems())
m[m.index(('Age', 'Age'))] = ('Age_x', 'Age_y')
m 
# [('Name', 'FullName'), ('Age_x', 'Age_y'), ('Sex', 'Gender')]

Начните с внутреннего merge:

df3 = (df1.merge(df2, how='inner', on=['ID'])
          .reindex(columns=['ID', *(v for V in m for v in V)]))

df3
    ID   Name FullName  Age_x  Age_y Sex Gender
0  1B2  Roger    Roger     22     21   M      M
1  1C3   Stew     Rick     23     23   M      M

Теперь сравните столбцы и установите значения с np.where:

l, r = map(list, zip(*m))
matches = (df3[l].eq(df3[r].rename(dict(zip(r, l)), axis=1))
                 .add_prefix('Result_')
                 .replace({True: 'Match', False: 'No Match'}))

for k, v in m:
    name = f'Result_{k}'
    df3.insert(df3.columns.get_loc(v)+1, name, matches[name])

df3.columns
# Index(['ID', 'Name', 'FullName', 'Result_Name', 'Age_x', 'Age_y',
#        'Result_Age_x', 'Sex', 'Gender', 'Result_Sex'],
#       dtype='object')

df3.filter(like='Result_')

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