Pandas加入/合并/连接两个DataFrame并组合相同键/索引的行

时间:2017-05-31 21:26:33

标签: python pandas join dataframe merge

我正在尝试组合两组数据,但是我无法弄清楚哪个方法最合适(加入,合并,连接等)这个应用程序,并且文档没有没有任何例子可以做我需要做的事情。

我有两组数据,结构如下:

>>> A
Time     Voltage
1.0      5.1
2.0      5.5
3.0      5.3
4.0      5.4
5.0      5.0

>>> B
Time     Current
-1.0     0.5
0.0      0.6
1.0      0.3
2.0      0.4
3.0      0.7

我想合并数据列并将“时间”列合并在一起,以便获得以下内容:

>>> AB
Time     Voltage     Current
-1.0                 0.5
0.0                  0.6
1.0      5.1         0.3
2.0      5.5         0.4
3.0      5.3         0.7
4.0      5.4            
5.0      5.0            

我尝试了AB = merge_ordered(A, B, on='Time', how='outer'),虽然它成功地合并了数据,但它输出的内容类似于:

>>> AB
Time     Voltage     Current
-1.0                 0.5
0.0                  0.6
1.0      5.1            
1.0                  0.3
2.0      5.5            
2.0                  0.4
3.0      5.3            
3.0                  0.7
4.0      5.4            
5.0      5.0            

您会注意到它没有将行与共享的“时间”值组合在一起。

我也试过合并一个la AB = A.merge(B, on='Time', how='outer'),但是输出了一些组合但没有排序的东西,如下所示:

>>> AB
Time     Voltage     Current
-1.0                 0.5
0.0                  0.6
1.0      5.1            
2.0      5.5            
3.0      5.3         0.7
4.0      5.4            
5.0      5.0            
1.0                  0.3
2.0                  0.4

...它基本上跳过了“当前”中数据的部分并将其附加到底部,但它的确不一致。而且,它不会将行合并在一起。

尝试了AB = pandas.concat(A, B, axis=1),但结果没有合并。我只是得到了两个DataFrame的串联,如下所示:

>>> AB
Time     Voltage     Time     Current
1.0      5.1         -1.0     0.5
2.0      5.5         0.0      0.6
3.0      5.3         1.0      0.3
4.0      5.4         2.0      0.4
5.0      5.0         3.0      0.7

我一直在搜索文档,并在这里尝试找出mergejoin之间的确切差异,但从我收集的内容来看,它们非常相似。尽管如此,我还没有找到任何具体回答“如何合并共享相同键/索引的行”的问题。任何人都可以告诉我如何做到这一点?我只有几天的熊猫经验!

3 个答案:

答案 0 :(得分:6)

<强> merge
merge结合了列。默认情况下,它采用所有通常命名的列。否则,您可以指定要组合的列。在此示例中,我选择了Time

A.merge(B, 'outer', 'Time')

   Time  Voltage  Current
0   1.0      5.1      0.3
1   2.0      5.5      0.4
2   3.0      5.3      0.7
3   4.0      5.4      NaN
4   5.0      5.0      NaN
5  -1.0      NaN      0.5
6   0.0      NaN      0.6

<强> join
除非您指定左侧的列,否则 join会合并索引值。这就是为什么我设置右侧的索引并指定左侧的列Time

A.join(B.set_index('Time'), 'Time', 'outer')

   Time  Voltage  Current
0   1.0      5.1      0.3
1   2.0      5.5      0.4
2   3.0      5.3      0.7
3   4.0      5.4      NaN
4   5.0      5.0      NaN
4  -1.0      NaN      0.5
4   0.0      NaN      0.6    ​

<强> pd.concat
concat结合索引值...所以我创建了一个列表推导,我在其中迭代我要组合的每个数据帧[A, B]。在理解中,每个数据框都假定名称为d,因此为for d in [A, B]axis=1表示将它们并排组合使用索引作为连接功能。

pd.concat([d.set_index('Time') for d in [A, B]], axis=1).reset_index()

   Time  Voltage  Current
0  -1.0      NaN      0.5
1   0.0      NaN      0.6
2   1.0      5.1      0.3
3   2.0      5.5      0.4
4   3.0      5.3      0.7
5   4.0      5.4      NaN
6   5.0      5.0      NaN

combine_first

A.set_index('Time').combine_first(B.set_index('Time')).reset_index()

   Time  Current  Voltage
0  -1.0      0.5      NaN
1   0.0      0.6      NaN
2   1.0      0.3      5.1
3   2.0      0.4      5.5
4   3.0      0.7      5.3
5   4.0      NaN      5.4
6   5.0      NaN      5.0

答案 1 :(得分:2)

如果Time列在两个DF中具有相同的dtype,它应该可以正常工作:

In [192]: A.merge(B, how='outer').sort_values('Time')
Out[192]:
   Time  Voltage  Current
5  -1.0      NaN      0.5
6   0.0      NaN      0.6
0   1.0      5.1      0.3
1   2.0      5.5      0.4
2   3.0      5.3      0.7
3   4.0      5.4      NaN
4   5.0      5.0      NaN

In [193]: A.dtypes
Out[193]:
Time       float64
Voltage    float64
dtype: object

In [194]: B.dtypes
Out[194]:
Time       float64
Current    float64
dtype: object

重现您的问题:

In [198]: A.merge(B.assign(Time=B.Time.astype(str)), how='outer').sort_values('Time')
Out[198]:
   Time  Voltage  Current
5  -1.0      NaN      0.5
6   0.0      NaN      0.6
0   1.0      5.1      NaN
7   1.0      NaN      0.3
1   2.0      5.5      NaN
8   2.0      NaN      0.4
2   3.0      5.3      NaN
9   3.0      NaN      0.7
3   4.0      5.4      NaN
4   5.0      5.0      NaN

In [199]: B.assign(Time=B.Time.astype(str)).dtypes
Out[199]:
Time        object   # <------ NOTE
Current    float64
dtype: object

视觉上很难区分:

In [200]: B.assign(Time=B.Time.astype(str))
Out[200]:
   Time  Current
0  -1.0      0.5
1   0.0      0.6
2   1.0      0.3
3   2.0      0.4
4   3.0      0.7

In [201]: B
Out[201]:
   Time  Current
0  -1.0      0.5
1   0.0      0.6
2   1.0      0.3
3   2.0      0.4
4   3.0      0.7

答案 2 :(得分:0)

找到解决方案 根据下面的建议,我必须在合并它们之前对“时间”列中的数字进行舍入,尽管事实上它们都是相同的dtype(float64)。建议是这样回合:

A = A.assign(A.Time = A.Time.round(4))

但在我的实际情况中,该列被标记为“时间,(秒)”(标点符号与作业相符。所以我使用以下行来围绕它:

A['Time, (sec)'] = A['Time, (sec)'].round(4)

它就像一个魅力。这样做有什么问题吗?