PYTHON-在日期索引上合并两个数据框

时间:2020-01-04 08:03:40

标签: python pandas dataframe merge

我想在公共日期索引上合并两个数据框(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语句会产生一些重复的行

1 个答案:

答案 0 :(得分:0)

为什么我的merge语句会产生一些重复的行?

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也是如此。如果我们注意到d1d2的大小分别为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)。但是,在您的情况下,每个数据帧中似乎只有几个重复项。如果有更多重复项,我建议您在合并之前删除重复项,但这对您来说似乎不是一个大问题。