如何使用python连接数据帧而不复制列,并保持默认的左/右或非NaN?

如何使用python连接数据帧而不复制列,并保持默认的左/右或非NaN?,python,pandas,dataframe,join,Python,Pandas,Dataframe,Join,我想合并索引上的两个数据帧(因此join())。 但这两个数据帧大约有20列,完全相同。 我希望避免重复列,因为决定保留哪些列、删除其中一半并重命名其他列可能会很麻烦 我的目标是制作一个数据帧(我称之为“旧的”),作为以前所有数据帧的历史记录。因此,我正在构建一个新的数据帧,然后将其合并到旧的自身中,等等。旧的数据帧将随着迭代的进行而增加 下面是一个简化的例子 import pandas as pd df = pd.DataFrame({'A': [1,2,3], '

我想合并索引上的两个数据帧(因此
join()
)。
但这两个数据帧大约有20列,完全相同。 我希望避免重复列,因为决定保留哪些列、删除其中一半并重命名其他列可能会很麻烦

我的目标是制作一个数据帧(我称之为“旧的”),作为以前所有数据帧的历史记录。因此,我正在构建一个新的数据帧,然后将其合并到旧的自身中,等等。旧的数据帧将随着迭代的进行而增加

下面是一个简化的例子

import pandas as pd
df = pd.DataFrame({'A': [1,2,3],
              'B': [4,5,6],
              'C':[7,8,9]}
     ).set_index([[11,22,33]])

old = df.head(2)
new = df.tail(2)

print( old.join(new,how='outer', lsuffix='_left') )
其中:

    A_left  B_left  C_left    A    B    C
11     1.0     4.0     7.0  NaN  NaN  NaN
22     2.0     5.0     8.0  2.0  5.0  8.0
33     NaN     NaN     NaN  3.0  6.0  9.0
  • 11:我知道,如果new中不存在ID,那么应该保留它,而不是使用NaN创建重复变量

  • 22:如果ID同时存在,则应覆盖旧值;放弃左栏,保留右栏

  • 33:如果ID在旧版本中不存在,但在新版本中不存在,只需追加

我在文档中搜索了很多,但是什么也没找到

到目前为止,我最好的办法是使用后缀进行连接,然后应用过滤器:如果列A_left、B_left、C_left为NaN,则复制A、B、C中的值。删除列A_left、B_left、C_left等。
这似乎不是一个有效的解决方案

或者附加它们,对_值排序,然后删除重复的id

由于我是Python新手,这可能不是最好的方法,请告诉我。

--------------评论后编辑-------------------------------

第一个选项,完整代码: 它保留了两者的索引,同时用new中的值更新具有相同索引但不同值的行

import pandas as pd
old = pd.DataFrame({'A': [2,3,4],
              'B': [5,6,4],
              'C':[8,9,4]}
     ).set_index([[22,33,44]])

new = pd.DataFrame({'A': [1,2,3],
              'B': [44,55,66],
              'C':[7,8,9]}
     ).set_index([[11,22,33]])

new
    A   B   C
11  1   44  7
22  2   55  8
33  3   66  9

old
    A   B   C
22  2   5   8
33  3   6   9
44  4   4   4

pd.merge(new, old, on=['A','B','C'], how='outer', right_index=True, left_index=True)

output:
    A   B   C
11  1   44  7
22  2   55  8
33  3   66  9
44  4   4   4

你试过合并吗

    pd.merge(old, new, on=['A','B','C'], how='outer', left_index=True, right_index=True))

Output:

        A   B   C
    11  1   4   7
    22  2   5   8
    33  3   6   9
备选案文2: 使用追加和删除重复项:

new.append(old).drop_duplicates()

你可以试试这个,我想它会对你有用的

import pandas as pd

df = pd.DataFrame({'A': [1,2,3,4],
              'B': [4,5,6,7],
              'C':[7,8,9,10],
              'D':[10,11,12,14]}
     ).set_index([[11,22,33,44]])

df2 = pd.DataFrame({'A': [1,2,3,4],
              'B': [4,5,6,8],
              'C':[11,12,13,15],
              'D':[14,15,16,17]}
     ).set_index([[11,22,33,44]])
old = df.head(3)
new = df2.tail(3)

intersection = list(set(list(new.index)).intersection(list(old.index)))
old.loc[intersection] = new.loc[intersection]
only_new = [x for x in list(new.index) if x not in list(old.index)]

old.loc[only_new] = new.loc[only_new]

是的,我试过了。语法不同,但如果指定
how='outer',后缀=['''ul',''rur'],左索引=True,右索引=True,则语法相同。这里的示例(
pd.merge(old,new,on=['A','B','C'],how='outer')
)不使用索引,但所有列都不相同。我对其进行了编辑,以使用每个df的索引。我的值是否映射到索引(一对一)?编辑:它不会在所有情况下都映射到1,因为在某些列中,第一个“旧”的信息可能比“新”的信息多或少。问题是,如果左(旧)值存在,它似乎会保留它们(我想不是NaN?),而不管它们是否存在于右(新)df中。因此,如果索引是相互的,您希望新的df只包含新的索引,同时将值从旧的更新为新的?您可能只是在寻找新的。先合并(旧的)
;如果new的22/C是99,那么输出中应该是99,我的想法正确吗?@DSM是的,你是正确的。另外,如果new/22/B是NaN,new/22/C是99,我希望分别是5和99。你会先工作吗?是的。看。@DSM你的答案太完美了!这正是我所需要的,而且非常小,令人难以置信。谢谢你可以回答这个问题,我会把它标记为已解决。