python pandas - 通过自定义 ID 以多种方式比较两个数据帧
python pandas - compare two dataframes in multiple ways by custom ID
我需要检查两个具有不同日期的数据集随时间发生的变化:
之前的日期:
Date ID Value Category Subcategory
30-Nov 0001 100.00 A A100
30-Nov 0002 200.00 B B120
30-Nov 0003 300.00 C C300
30-Nov 0004 450.00 D D900
30-Nov 0005 500.00 D D900
当前日期:
Date ID Value Category Subcategory
31-Dec 0001 100.00 A A100
31-Dec 0002 200.00 B B101
31-Dec 0003 300.00 C C300
31-Dec 0004 400.00 E E900
31-Dec 0006 600.00 D D900
现在我需要创建 4 个数据框:
- 价值变化:
Date ID Value Category Subcategory Prior Value
31-Dec 0004 400.00 E E900 450.00
- 类别变化:
Date ID Value Category Subcategory Prior Category
31-Dec 0004 400.00 E E900 D
- 子类别的变化,但前提是类别没有变化:
Date ID Value Category Subcategory Prior Subcategory
31-Dec 0002 200.00 B B101 B120
- 项目人口变化:
Date ID Value Category Subcategory
31-Dec 0006 600.00 D D900
30-Nov 0005 500.00 D D900
我想我应该首先 运行 人口检查并排除那些中断,所以我将只有两个具有相同 ID 集的数据集。我将按照此处的示例进行操作:
Comparing two dataframes and getting the differences
为了比较 1to1 值,我找到了一段 numpy 代码,但它是通过默认索引而不是 ID 进行比较的,如何使用我的 ID 列作为记录标识符来进行比较?这将是一个大型数据集,我无法将其基于默认索引。
value_df = current_df
value_df['prior value'] = np.where(prior_df['Value'] == current_df['Value'], 'Match', prior_df['Value'])
value_df = value_df[value_df['prior value'] != 'Match']
对于多个条件,我必须逐步过滤掉它(首先过滤掉类别变化,然后过滤子类别变化)还是我可以使用 AND 连接条件?
下面是创建数据帧的代码:
prior_data = {'Date': ['30-Nov','30-Nov','30-Nov','30-Nov', '30-Nov'],
'ID': ['0001','0002','0003','0004', '0005'],
'Value' : [100.00, 200.00, 300.00, 450.00, 500.00],
'Category' : ['A','B','C','D','D'],
'Subcategory' : ['A100','B120','C300','D900','D900']}
current_data = {'Date': ['31-Dec','31-Dec','31-Dec','31-Dec','31-Dec'],
'ID': ['0001','0002','0003','0004', '0006'],
'Value' : [100.00, 200.00, 300.00, 400.00, 600.00],
'Category' : ['A','B','C','E','D'],
'Subcategory' : ['A100','B101','C300','E900','D900']}
prior_df = pd.DataFrame(prior_data)
current_df = pd.DataFrame(current_data)
我不确定这是否是最快的解决方案,但这个问题似乎需要 pd.merge
。正如您所说,让我们首先处理一个数据框中的内容,而不是另一个数据框中的内容:
def get_only_left(df1, df2):
left_merge = pd.merge(df1, df2, on='ID', suffixes=('', '_other'), how='left')
added_columns = [c + '_other' for c in df1.columns if c != 'ID']
mask = left_merge.loc[:, added_columns].isna().all(axis=1)
return left_merge[mask].drop(added_columns, axis=1)
pd.concat([get_only_left(prior_df, current_df), get_only_left(current_df, prior_df)])
这给
Date ID Value Category Subcategory
4 30-Nov 0005 500.0 D D900
4 31-Dec 0006 600.0 D D900
然后,让我们处理适当改变的值。
columns = list(current_df.columns)
df = pd.merge(current_df, prior_df, on='ID', suffixes=('', '_prior'), how='inner')
mask = df['Value'] != df['Value_prior']
df[mask].loc[:, columns + ['Value_prior']]
这给
Date ID Value Category Subcategory Value_prior
3 31-Dec 0004 400.0 E E900 450.0
然后类似地:
mask = df['Category'] != df['Category_prior']
df[mask].loc[:, columns + ['Category_prior']]
给予
Date ID Value Category Subcategory Category_prior
3 31-Dec 0004 400.0 E E900 D
最后
import numpy as np
mask = np.logical_and(df['Category'] == df['Category_prior'], df['Subcategory'] != df['Subcategory_prior'])
df[mask].loc[:, columns + ['Subcategory_prior']]
给予
Date ID Value Category Subcategory Subcategory_prior
1 31-Dec 0002 200.0 B B101 B120
我需要检查两个具有不同日期的数据集随时间发生的变化:
之前的日期:
Date ID Value Category Subcategory
30-Nov 0001 100.00 A A100
30-Nov 0002 200.00 B B120
30-Nov 0003 300.00 C C300
30-Nov 0004 450.00 D D900
30-Nov 0005 500.00 D D900
当前日期:
Date ID Value Category Subcategory
31-Dec 0001 100.00 A A100
31-Dec 0002 200.00 B B101
31-Dec 0003 300.00 C C300
31-Dec 0004 400.00 E E900
31-Dec 0006 600.00 D D900
现在我需要创建 4 个数据框:
- 价值变化:
Date ID Value Category Subcategory Prior Value
31-Dec 0004 400.00 E E900 450.00
- 类别变化:
Date ID Value Category Subcategory Prior Category
31-Dec 0004 400.00 E E900 D
- 子类别的变化,但前提是类别没有变化:
Date ID Value Category Subcategory Prior Subcategory
31-Dec 0002 200.00 B B101 B120
- 项目人口变化:
Date ID Value Category Subcategory
31-Dec 0006 600.00 D D900
30-Nov 0005 500.00 D D900
我想我应该首先 运行 人口检查并排除那些中断,所以我将只有两个具有相同 ID 集的数据集。我将按照此处的示例进行操作: Comparing two dataframes and getting the differences
为了比较 1to1 值,我找到了一段 numpy 代码,但它是通过默认索引而不是 ID 进行比较的,如何使用我的 ID 列作为记录标识符来进行比较?这将是一个大型数据集,我无法将其基于默认索引。
value_df = current_df
value_df['prior value'] = np.where(prior_df['Value'] == current_df['Value'], 'Match', prior_df['Value'])
value_df = value_df[value_df['prior value'] != 'Match']
对于多个条件,我必须逐步过滤掉它(首先过滤掉类别变化,然后过滤子类别变化)还是我可以使用 AND 连接条件?
下面是创建数据帧的代码:
prior_data = {'Date': ['30-Nov','30-Nov','30-Nov','30-Nov', '30-Nov'],
'ID': ['0001','0002','0003','0004', '0005'],
'Value' : [100.00, 200.00, 300.00, 450.00, 500.00],
'Category' : ['A','B','C','D','D'],
'Subcategory' : ['A100','B120','C300','D900','D900']}
current_data = {'Date': ['31-Dec','31-Dec','31-Dec','31-Dec','31-Dec'],
'ID': ['0001','0002','0003','0004', '0006'],
'Value' : [100.00, 200.00, 300.00, 400.00, 600.00],
'Category' : ['A','B','C','E','D'],
'Subcategory' : ['A100','B101','C300','E900','D900']}
prior_df = pd.DataFrame(prior_data)
current_df = pd.DataFrame(current_data)
我不确定这是否是最快的解决方案,但这个问题似乎需要 pd.merge
。正如您所说,让我们首先处理一个数据框中的内容,而不是另一个数据框中的内容:
def get_only_left(df1, df2):
left_merge = pd.merge(df1, df2, on='ID', suffixes=('', '_other'), how='left')
added_columns = [c + '_other' for c in df1.columns if c != 'ID']
mask = left_merge.loc[:, added_columns].isna().all(axis=1)
return left_merge[mask].drop(added_columns, axis=1)
pd.concat([get_only_left(prior_df, current_df), get_only_left(current_df, prior_df)])
这给
Date ID Value Category Subcategory
4 30-Nov 0005 500.0 D D900
4 31-Dec 0006 600.0 D D900
然后,让我们处理适当改变的值。
columns = list(current_df.columns)
df = pd.merge(current_df, prior_df, on='ID', suffixes=('', '_prior'), how='inner')
mask = df['Value'] != df['Value_prior']
df[mask].loc[:, columns + ['Value_prior']]
这给
Date ID Value Category Subcategory Value_prior
3 31-Dec 0004 400.0 E E900 450.0
然后类似地:
mask = df['Category'] != df['Category_prior']
df[mask].loc[:, columns + ['Category_prior']]
给予
Date ID Value Category Subcategory Category_prior
3 31-Dec 0004 400.0 E E900 D
最后
import numpy as np
mask = np.logical_and(df['Category'] == df['Category_prior'], df['Subcategory'] != df['Subcategory_prior'])
df[mask].loc[:, columns + ['Subcategory_prior']]
给予
Date ID Value Category Subcategory Subcategory_prior
1 31-Dec 0002 200.0 B B101 B120