Python 使用修订合并样式中的索引合并数据帧
我有两个相当大的数据帧,比如~300k行,一个有N~30列(包括一个“描述”列),另一个只有一个“描述”列。第一个df包含完整的数据,但有些行太多(几千行),有些行缺失(600行),大致均匀地分布在整个df中;另一个正确指定了行,但没有任何进一步的数据。我希望将它们合并到一个数据帧中,该数据帧具有后者指定的行和前者的信息(即,删除后者中未出现的行,并在需要时创建新行,比如用nan填充)。所以最后一个数据帧的大小应该是mxn,werm是第二个数据帧的行数 这将是pandas.merge的一个典型案例,如果不是因为我想要合并的键有重复项的话。它们“大部分是唯一的”,但有些条目会重复(通常在不少于100行之后),我不希望它们出现多次。相反,我想做一些看起来像“版本控制”的事情,即逐行比较以获得两个描述的最佳匹配,删除第一个数据帧中添加的行,并从正确的行中推送新的行。事实上,如果我只在两个CSV中提取两个df的“Description”列,我可以轻松地用手工完成我需要的工作,例如meld(行足够长,因此在如何检查相等行时确实没有歧义),但是1)这很慢,2)它不能解决我的问题(最后,我将得到第二个数据帧的副本,因为我必须删除其他列以使用meld) 举例来说,假设我有以下两个数据帧:Python 使用修订合并样式中的索引合并数据帧,python,pandas,dataframe,version-control,merge,Python,Pandas,Dataframe,Version Control,Merge,我有两个相当大的数据帧,比如~300k行,一个有N~30列(包括一个“描述”列),另一个只有一个“描述”列。第一个df包含完整的数据,但有些行太多(几千行),有些行缺失(600行),大致均匀地分布在整个df中;另一个正确指定了行,但没有任何进一步的数据。我希望将它们合并到一个数据帧中,该数据帧具有后者指定的行和前者的信息(即,删除后者中未出现的行,并在需要时创建新行,比如用nan填充)。所以最后一个数据帧的大小应该是mxn,werm是第二个数据帧的行数 这将是pandas.merge的一个典型案
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