python Pandas EXCLUSIVE LEFT OUTER JOIN with line count

mec1mxoz  于 2023-06-04  发布在  Python
关注(0)|答案(2)|浏览(126)

我正在创建一个交易导入工具,每天用新的交易更新数据库。我得到了一个Excel文件(我使用Pandas打开),其中包含整个月的交易,我试图通过将新的DataFrame与现有的合并来过滤新的交易。为此,我使用pandas merge来执行EXCULSIVE LEFT OUTER JOIN,但我遇到了多行具有相同精确值的问题。请看下面的例子:

import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.array([[pd.Timestamp('2023-1-1'), 'A', 10]
                            , [pd.Timestamp('2023-1-1'), 'A', 10]
                            , [pd.Timestamp('2023-1-1'), 'B', 11]
                            , [pd.Timestamp('2023-1-2'), 'C', 12]
                            , [pd.Timestamp('2023-1-2'), 'D', 13]
                            , [pd.Timestamp('2023-1-2'), 'E', 14]
                            , [pd.Timestamp('2023-1-3'), 'F', 15]]),
                   columns=['Date', 'Title', 'Amount'])

df2 = pd.DataFrame(np.array([[pd.Timestamp('2023-1-1'), 'A', 10]
                            , [pd.Timestamp('2023-1-1'), 'B', 11]
                            , [pd.Timestamp('2023-1-2'), 'C', 12]]),
                   columns=['Date', 'Title', 'Amount'])

df3 = pd.merge(df1, df2, on=['Date', 'Title', 'Amount'], how="outer", indicator=True)
df3 = df3[df3['_merge'] == 'left_only']

print(df1)
print(df2)
print(df3) # Both 'A' rows deleted while one 'A' row is new and should be in df3

输出为:

Date Title Amount
0 2023-01-01     A     10
1 2023-01-01     A     10
2 2023-01-01     B     11
3 2023-01-02     C     12
4 2023-01-02     D     13
5 2023-01-02     E     14
6 2023-01-03     F     15
        Date Title Amount
0 2023-01-01     A     10
1 2023-01-01     B     11
2 2023-01-02     C     12
        Date Title Amount     _merge
4 2023-01-02     D     13  left_only
5 2023-01-02     E     14  left_only
6 2023-01-03     F     15  left_only

使用上面的方法,两个'A'行都被删除,而一个'A'行是新的,因此应该在新的DataFrame中。有什么想法可以用来保持行,在第一个数据框考虑行计数?为了给予更多一点的信息,同一天中的事务不被排序(没有时间信息,只有日期),并且新的事务可以在过去的多天中被添加。

g52tjvyc

g52tjvyc1#

我想你最想要的是这个:

df3 = (
    pd.merge(df1, df2,
             left_on = [*list(df1), df1.groupby(list(df1)).cumcount()],
             right_on= [*list(df2), df2.groupby(list(df2)).cumcount()],
             how="outer", indicator=True)
        .query("_merge == 'left_only'")
        .drop(columns="key_3")
)

输出:

print(df3)

        Date Title Amount     _merge
1 2023-01-01     A     10  left_only
4 2023-01-02     D     13  left_only
5 2023-01-02     E     14  left_only
6 2023-01-03     F     15  left_only
vsdwdz23

vsdwdz232#

我们可以通过添加一个'Existence'列来标记df1中的重复项,该列指示每行是否是重复项。然后,我们使用pd.merge()执行左连接,并包含'_merge'列来标识df1和df2之间的匹配行。最后,我们过滤df3以保留df1独占的行或在df1中标记为重复的行。

df1['Existence'] = df1.duplicated(keep='first')  # Mark duplicates in df1
df3 = pd.merge(df1, df2, on=['Date', 'Title', 'Amount'], how='left', 
indicator=True)
df3 = df3[(df3['_merge'] == 'left_only') | (df3['Existence'] ==True)].drop(columns=['Existence', '_merge'])

只要调整合并部分,它就会工作。

相关问题