Python 使用修订合并样式中的索引合并数据帧

Python 使用修订合并样式中的索引合并数据帧,python,pandas,dataframe,version-control,merge,Python,Pandas,Dataframe,Version Control,Merge,我有两个相当大的数据帧,比如~300k行,一个有N~30列(包括一个“描述”列),另一个只有一个“描述”列。第一个df包含完整的数据,但有些行太多(几千行),有些行缺失(600行),大致均匀地分布在整个df中;另一个正确指定了行,但没有任何进一步的数据。我希望将它们合并到一个数据帧中,该数据帧具有后者指定的行和前者的信息(即,删除后者中未出现的行,并在需要时创建新行,比如用nan填充)。所以最后一个数据帧的大小应该是mxn,werm是第二个数据帧的行数 这将是pandas.merge的一个典型案

我有两个相当大的数据帧,比如~300k行,一个有N~30列(包括一个“描述”列),另一个只有一个“描述”列。第一个df包含完整的数据,但有些行太多(几千行),有些行缺失(600行),大致均匀地分布在整个df中;另一个正确指定了行,但没有任何进一步的数据。我希望将它们合并到一个数据帧中,该数据帧具有后者指定的行和前者的信息(即,删除后者中未出现的行,并在需要时创建新行,比如用nan填充)。所以最后一个数据帧的大小应该是mxn,werm是第二个数据帧的行数

这将是pandas.merge的一个典型案例,如果不是因为我想要合并的键有重复项的话。它们“大部分是唯一的”,但有些条目会重复(通常在不少于100行之后),我不希望它们出现多次。相反,我想做一些看起来像“版本控制”的事情,即逐行比较以获得两个描述的最佳匹配,删除第一个数据帧中添加的行,并从正确的行中推送新的行。事实上,如果我只在两个CSV中提取两个df的“Description”列,我可以轻松地用手工完成我需要的工作,例如meld(行足够长,因此在如何检查相等行时确实没有歧义),但是1)这很慢,2)它不能解决我的问题(最后,我将得到第二个数据帧的副本,因为我必须删除其他列以使用meld)

举例来说,假设我有以下两个数据帧:

df1 = pd.DataFrame({'Description': ['A','B','Y','D','A','E','F','Y','B'], 'Values': np.arange(9)**2})
df2 = pd.DataFrame({'Description': ['A','B','D','A','E','B','F','B']})

>>> df1
    Description Values
0   A   0
1   B   1
2   Y   4
3   D   9
4   A   16
5   E   25
6   F   36
7   Y   49
8   B   64
>>> df2
    Description
0   A
1   B
2   D
3   A
4   E
5   B
6   F
7   B
我想得到的是:

    Description Values
0   A   0.0
1   B   1.0
2   D   9.0
3   A   16.0
4   E   25.0
5   B   NaN
6   F   36.0
7   B   64.0
我发现的唯一一种解决方案是,通过简单地将一列添加到复制索引的第一个数据帧中

df1['id'] = df1.index
(我知道这是标准,即
np.arange(len(df1))
),使用
pd.merge(df1,df2,how='right'))
,然后从合并的数据帧中提取与列id的最大递增序列相对应的索引。为此,请参见需要调整的索引,以便始终在序列中包含任何
NaN

然而,在重新发明轮子之前,我想知道是否有人知道这个代码的一个已经存在的实现,也许是在一些用于自动版本控制的包中

编辑:在问题
df2
的前一个版本中是
df2=pd.DataFrame({'Description':['a','B','D','a','E','Z','F','B']})
。读了@jezrael的第一个答案,我意识到它表明附加的行是“特殊的”通过字母
Z
,但实际上它们会出现在数据帧的其他位置。这使得@jezrael提出了一个非常好和优雅的答案,但不幸的是,这对我不起作用


另一方面,对于一个稍微简化的假设,实际上要删除的行是相当特殊的,因此我将它们重命名为“Y”,因为我可以事先删除它们并忽略问题的这一部分——“增加”部分是我真正关心的。

我认为您需要创建具有不同值的新列,其中通过以下方式复制:

如果顺序很重要,请添加
reset_index
,最后添加帮助器列:

df = pd.merge(df1, df2.reset_index(), how='right', on=['Description','a'])
df = df.sort_values('index').drop(['a','index'], axis=1)
print (df)
      Description  Values
0           A     0.0
1           B     1.0
2           D     9.0
3           A    16.0
4           E    25.0
7           Z     NaN
5           F    36.0
6           B    64.0

感谢您的快速回答!不幸的是,尽管这解决了我编写的示例,但我担心一般情况下还有一个困难使此解决方案无法工作:df2中的附加行可能已经出现在其他地方(在df1和df2中)。例如,df2=pd.DataFrame({'Description':['A','B','D','A','E','C','F','B']))。在这种情况下,您的解决方案将为该行提供C值,而不是NaN(如果还有其他C,则会中断所有匹配,因为cumcount()与该行不同):(
merge
duplicated
值不是朋友,现在我没有其他想法。您可以在注释中按值更改问题中的示例吗?编辑问题,谢谢!也非常感谢您的回答,我今天学习了cumcount()命令:-)
df = pd.merge(df1, df2.reset_index(), how='right', on=['Description','a'])
df = df.sort_values('index').drop(['a','index'], axis=1)
print (df)
      Description  Values
0           A     0.0
1           B     1.0
2           D     9.0
3           A    16.0
4           E    25.0
7           Z     NaN
5           F    36.0
6           B    64.0