Python 比较两个不重复的数据帧
我有两个类似的结构化数据帧,分别代表两个时间段,比如2020年7月和2020年8月。其中的数据是来自多个公司来源(如CRM和会计应用程序)的预测和/或实现收入数据。这些列包含关于客户、产品、数量、价格、收入、期限等的数据。现在,我想通过比较两个数据框来了解这两个月到几个月之间发生了什么 我试图通过重命名一些列(如quantity、price和revenue)来实现这一点,然后合并客户端、产品和期间的两个数据帧。然后我计算了数量、价格和收入的差额 但是我遇到了一个问题。。。假设一个特定客户与我们签订了合同,在未来两年内每月购买两种特定产品(abc和xyz)。这意味着在我们7月份的预测中,我们可以将这两项作为收入。实际上,与其他合同以及加权管道中的预期收入相比,该列表要长得多 这是从我们特定客户的总预测中提取的一小部分Python 比较两个不重复的数据帧,python,pandas,Python,Pandas,我有两个类似的结构化数据帧,分别代表两个时间段,比如2020年7月和2020年8月。其中的数据是来自多个公司来源(如CRM和会计应用程序)的预测和/或实现收入数据。这些列包含关于客户、产品、数量、价格、收入、期限等的数据。现在,我想通过比较两个数据框来了解这两个月到几个月之间发生了什么 我试图通过重命名一些列(如quantity、price和revenue)来实现这一点,然后合并客户端、产品和期间的两个数据帧。然后我计算了数量、价格和收入的差额 但是我遇到了一个问题。。。假设一个特定客户与我们签
Client Product Period Stage Qty Price Rev
0 A abc 2020-07 contracted 1 100 100
1 A xyz 2020-07 contracted 1 50 50
现在假设这个客户要求购买第二个产品xyz,我们得到了另一个合同。而7月份的情况是这样的:
Client Product Period Stage Qty Price Rev
0 A abc 2020-07 contracted 1 100 100
1 A xyz 2020-07 contracted 1 50 50
2 A xyz 2020-07 contracted 1 50 50
现在假设一个月后,我们从我们的会计系统中得出了如下的实际收入(因此我们的预测变成了现实):
现在我想通过在重命名一些列后合并两个df来比较它们
def rename_column(df_name, col_name, first_forecast_period):
col_name = df_name.rename(columns={col_name: col_name + '_' + first_forecast_period}, inplace=True)
return df_name
rename_column(df_1, 'Stage', '1')
rename_column(df_1, 'Price', '1')
rename_column(df_1, 'Qty', '1')
rename_column(df_1, 'Rev', '1')
rename_column(df_2, 'Stage', '2')
rename_column(df_2, 'Price', '2')
rename_column(df_2, 'Qty', '2')
rename_column(df_2, 'Rev', '2')
result_1 = pd.merge(df_1, df_2, how ='outer')
然后通过一些数学计算得出差异:
result_1['Qty_diff'] = result1['Quantity_2'] - result1['Quantity_1']
result_1['Price_diff'] = result1['Price_2'] - result1['Price_1']
result_1['Rev_diff'] = result1['Rev_2'] - result1['Rev_1']
这导致:
Client Product Period Stage_1 Qty_1 Price_1 Rev_1 Stage_2 Qty_2 Price_2 Rev_2 Qty_diff Price_diff Rev_diff
0 A abc 2020-07 contracted 1 100 100 realised 1 100 100 0 0 0
1 A xyz 2020-07 contracted 1 50 50 realised 2 50 100 1 0 50
2 A xyz 2020-07 contracted 1 50 50 realised 2 50 100 1 0 50
因此,问题在于,在第三行中,实现的部分被第二次包含。由于预测和现实是一样的,结果应该是:
Client Product Period Stage_1 Qty_1 Price_1 Rev_1 Stage_2 Qty_2 Price_2 Rev_2 Qty_diff Price_diff Rev_diff
0 A abc 2020-07 contracted 1 100 100 realised 1 100 100 0 0 0
1 A xyz 2020-07 contracted 1 50 50 realised 2 50 100 1 0 50
2 A xyz 2020-07 contracted 1 50 50 realised 0 0 0 -1 0 -50
因此,我得到的总收入差是100(+50和+50),而不是0(+50和-50)。有没有办法通过合并两个DF来解决这个问题,或者我需要从另一个方向开始思考。如果是这样,那么任何建议都会很有帮助!谢谢。为了安全起见,您可能应该在两个dfs上获得客户端产品周期的总计。假设df_1中的所有行都是“收缩的”,则可以执行以下操作:
df_1 = (df_1.groupby(['Client', 'Prooduct', 'Period'])
.agg({'Stage': 'first', 'Qty': sum, 'Price': 'first', 'Rev': sum})
# if price can vary between rows of the same product-client
# .agg({'Stage': 'first', 'Qty': sum, 'Price': 'mean', 'Rev': sum})
# same for df_2
现在,您可以将两个dfs与以下内容合并:
df_merged = df_1.merge(df_2)
结果将分别为df_1和df_2的重复列添加后缀,
\u x
和\u y
。在合并这两个列之前,请考虑分组df_1
,这样,当您合并时,您将拥有唯一的行:)相同产品的两个不同行的价格是否始终相同?@Roelant:分组可能是一种解决方案,但也可以消除信息。在实际的数据帧中,第二行有“new sales”,第三行有“upsell”作为合同\排序。@RichieV:在这种情况下是的,因为有一个固定价格的已签署合同。但在其他情况下,价格也可能有所不同。例如,一个新的潜在客户将以标准价格包含在销售渠道中,但在合同中可能会以更高或更低的价格结束。请注意,如果您在代码末尾添加groupby,您可以对差异列求和,并按客户产品获得净差,在您的示例中,该值将为零。谢谢。正如我上面所说,它消除了一些信息,但我想一个解决方案,完全解决这一问题可能涉及大量的编码…我理解。这就是为什么包含尽可能小的样本数据很重要,但这仍然代表了问题的全部复杂性。您需要在groupby之后包含.reset_index(),以防止获取具有层次索引的数据帧。然后合并将崩溃。
df_merged = df_1.merge(df_2)