我想在公共日期索引上合并两个数据框(PRIM_recs和SECO_recs)。
PRIM_recs =
Hsig Thsig Hrms Hmax Tc Tz
1976-10-31 15:00:00 0.93 8.21 0.64 1.75 2.82 5.42...
1976-11-01 03:00:00 1.34 6.08 0.93 2.11 3.14 4.56...
1976-11-01 15:00:00 1.39 6.01 0.99 2.40 2.80 4.38...
1976-11-02 03:00:00 1.30 6.35 0.93 2.18 3.24 4.91...
1976-11-02 15:00:00 1.31 9.91 0.91 2.18 3.36 6.71...
: : : : : : : : : :
2017-05-20 04:00:00 1.442527 7.407674 1.050540 2.61 5.868847 5.891295...
2017-05-20 04:30:00 1.555761 6.361763 1.108141 3.16 5.758905 5.770841...
2017-05-20 05:00:00 1.563837 7.925315 1.143206 2.31 6.160781 6.181728...
2017-05-20 05:30:00 1.637766 7.488912 1.154951 2.66 5.647312 5.672689...
2017-05-20 06:00:00 1.622043 7.154768 1.146905 2.55 5.679639 5.714273...
SECO_recs =
Spc
1976-10-31 15:00:00 [0.0124, 0.0096, 0.0325, 0.1562, 0.4494, 0.738...
1976-11-01 03:00:00 [0.0254, 0.0299, 0.0273, 0.1229, 0.596, 0.9833...
1976-11-01 15:00:00 [0.0226, 0.0236, 0.0269, 0.085, 0.4163, 0.8011...
1976-11-02 03:00:00 [0.0132, 0.0154, 0.0172, 0.1336, 0.4743, 0.694...
1976-11-02 15:00:00 [0.0124, 0.0169, 0.028, 0.5028, 1.4503, 1.6055...
: : : : : : : : : :
2017-05-20 04:00:00 [5.374061e-13, 1.2720002e-06, 0.00052255474, 0...
2017-05-20 04:30:00 [1.2021946e-12, 3.3477074e-06, 0.0014435094, 0...
2017-05-20 05:00:00 [1.2236685e-13, 5.018357e-07, 0.00023753957, 0...
2017-05-20 05:30:00 [3.5527579e-13, 1.1004944e-06, 0.0005480177, 0...
2017-05-20 06:00:00 [4.968573e-13, 1.4969078e-06, 0.00065009575, 0...
我使用以下语句执行合并:
# Merge PRIM data with SECO data on common dates
df_PRIM_SECO = pd.merge(PRIM_recs, SECO_recs, left_index=True, right_index=True)
这给了我一个合并的数据帧(df_PRIM_SECO),但是这个df包含许多重复的行!
PRIM长度= 364229
SECO长度= 364228
合并长度= 364271
要解决此问题,我目前包含以下声明:
# Need to drop any duplicate index values that resulted from the merge
df_PRIM_SECO = df_PRIM_SECO.loc[~df_PRIM_SECO.index.duplicated(keep='first')]
这给了我所需的数据帧(减去重复项)!
PRIM长度= 364229
SECO长度= 364228
合并长度= 364202
df_PRIM_SECO中的行数较少(比PRIM_recs或SECO_recs少)是由于原始数据帧具有一些非公共日期而被合并所忽略。
我的问题是:
尽管我现在有了想要的结果,为什么我的merge语句会产生一些重复的行?
答案 0 :(得分:0)
TLDR:合并时的熊猫会自动合并重复键的所有可能组合。
首先,您要执行内部合并(默认how
参数),如果键(在您的情况下为索引)不在两个集合中,则将其从最终合并中排除。
在这里,我们要合并一个以字符串为键的列以简化操作,而不是时间戳索引。例如,
d1 = pd.DataFrame({'A': ['a', 'b'], 'n1': [1,2]})
d2 = pd.DataFrame({'A': ['b', 'c'], 'n2': [8,9]})
pd.merge(d1,d2, on='A')
产生
A n1 n2
0 b 2 8
我们可以看到,'b'
是两个列中唯一的键,因此在合并时,它仅保留这些实例。因此,数据框的最终大小为1。如果我们稍微更改d2
d1 = pd.DataFrame({'A': ['a', 'b'], 'n1': [1,2]})
d2 = pd.DataFrame({'A': ['b', 'b'], 'n2': [8,9]}) # change instance 'c' to 'b'
pd.merge(d1,d2, on='A')
合并反而产生
A n1 n2
0 b 2 8
1 b 2 9
可以理解,'b'
中有两个'd2'
实例,因此合并后有两个'b'
实例。但是,如果我们现在稍微更改d1
会怎样
d1 = pd.DataFrame({'A': ['a', 'b', 'b'], 'n1': [1,2,3]}) # added another instance of b
d2 = pd.DataFrame({'A': ['b', 'b'], 'n2': [8,9]})
好吧,按照相同的逻辑,每个数据帧中有两个'b'
实例,并且我们正在进行内部合并,因此合并之后应该有两个'b'
实例...对吧?
这是不正确的,因为每个'b'
现在必须在'b'
的所有实例上合并。为了显示,
pd.merge(d1,d2, on='A')
A n1 n2
0 b 2 8
1 b 2 9
2 b 3 8
3 b 3 9
现在大小为4。经检查,'b' 2
不仅与'b' 8
合并,而且还与'b' 9
合并。 'b' 3
也是如此。如果我们注意到d1
和d2
的大小分别为3和2,我们得到的数据帧的大小都比两者都大。之所以会这样,是因为合并之前,两个数据框中都存在该类别的多个实例。如陈述的那样,您可以通过在合并后删除重复的值来解决大小问题。您将保留第一个重复的值,并丢弃其余的值。然后,在此示例中,
pd.merge(d1,d2, on='A').drop_duplicates(subset='A', keep='first')
A n1 n2
0 b 2 8
如我们所见,这将从第一个示例合并返回相同的输出。合并后,由于键上的此重复,输出的数据帧的大小可能会更大,这可能会令人不舒服。
为减轻这种感觉,您可以在合并之前删除重复的值。如果执行合并,则将数据框与添加的'b'
实例一起使用
d1 = pd.DataFrame({'A': ['a', 'b', 'b'], 'n1': [1,2,3]}).drop_duplicates(subset='A', keep='first')
d2 = pd.DataFrame({'A': ['b', 'b'], 'n2': [8,9]})
pd.merge(d1,d2, on='A')
我们获得与上面概述的原始第二次合并相同的输出
A n1 n2
0 b 2 8
1 b 2 9
最后,如果我们从两个数据帧中删除重复项,则将获得原始的第一个合并输出
d1 = pd.DataFrame({'A': ['a', 'b', 'b'], 'n1': [1,2,3]}).drop_duplicates(subset='A', keep='first')
d2 = pd.DataFrame({'A': ['b', 'b'], 'n2': [8,9]}).drop_duplicates(subset='A', keep='first')
pd.merge(d1,d2, on='A')
A n1 n2
0 b 2 8
那么,为什么merge语句会产生重复的行?如图所示,它与键的映射有关。 熊猫在合并时会自动合并重复键的所有可能组合。如果不这样做,那么操作的灵活性就会降低。相反,您可以在合并之前(或之后)指定删除重复项的位置,这样就不会发生这种情况。
在具有许多重复键值的较大数据框上,进行所有可能组合的此操作可以快速扩展结果数据框很多(尝试一下,在两个{{中添加更多'b'
实例1}}和d1
)。但是,在您的情况下,每个数据帧中似乎只有几个重复项。如果有更多重复项,我建议您在合并之前删除重复项,但这对您来说似乎不是一个大问题。