python - 按列标题排列 DataFrame 列
问题描述
我有两个熊猫数据框,每个数据框的大小都不同,每条记录超过 100 万条。我希望比较这两个数据框并找出差异。
数据帧A
ID Name Age Sex
1A1 Cling 21 M
1B2 Roger 22 M
1C3 Stew 23 M
数据帧B
ID FullName Gender Age
1B2 Roger M 21
1C3 Rick M 23
1D4 Ash F 21
DataFrameB 的记录总是比 DataFrameA 多,但在 DataFrameA 中找到的记录可能不在 DataFrameB 中。DataFrameA 和 DataFrameB 中的列名不同。我将映射存储在不同的数据框中。
映射数据框
DataFrameACol DataFrameBCol
ID ID
Name FullName
Age Age
Sex Gender
我希望比较这两者并在结果旁边添加一列。
数据帧 A 的列名称加法器 = "_A_Txt"
数据帧 B 的列名称加法器 = "_B_Txt"
预期输出
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 循环来构建这个逻辑。但是 100 万条记录需要很长时间才能完成。我让程序运行了 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)
解决方案
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
推荐阅读
- python-3.x - 如何在 Kubernetes pod 中执行 python 脚本作为初始触发器
- node.js - 执行node.js脚本时如何传递参数?
- javascript - JavaScript 中的函数和字符串
- ruby-on-rails - 如何仅获取 simplecov 中指定测试的代码覆盖率报告?
- c++ - 如何从 cmake 获取宏值到 c++ 变量
- javascript - d3中地图行为的基准数据差异
- php - Magento API 抛出 500 错误,说检查异常日志但什么都没有
- javascript - 在javascript中随机化for循环
- python - 如何使用if条件在python中的列标题和行值之间查找字符串匹配(部分匹配和完全匹配)
- git - 如何使用 git diff --no-index 仅显示 dir2 FROM dir1 中的增量丢失/更改