本问题已经有最佳答案,请猛点这里访问。
我正在尝试合并两组数据,但是我无法弄清楚哪种方法最适合此应用程序(联接,合并,合并等),并且文档中没有任何示例可以满足我的需要去做。
我有两组数据,结构如下:
>>> 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
我一直在搜索文档,这里试图找出merge和join之间的确切差异,但是从我的收集来看,它们非常相似。不过,我还没有找到任何东西可以专门回答"如何合并共享相同键/索引的行"的问题。谁能启发我该怎么做?我只有几天的熊猫经验!
确保两个DF中的Time列具有相同的dtype
请问您将解决方案移至答案框吗? 我们在此不提出解决方案。 如果您想问这是否是一个很好的解决方案,可以问其他答案的人。
@halfer好像您为我编辑了我的帖子。 我还有什么需要做的吗? 恐怕我不知道您指的是什么答案框...
如果您希望按照Ive的建议进行操作,请单击下面的"回答问题"按钮,在出现的框中发布"找到解决方案"的材料,然后从问题中删除该材料。 我们在这里希望将问题材料和答案材料分开,这样可以使事情变得更清楚。 谢谢!
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
那么,join与merge确实几乎没有差别吗?有趣。并以您的示例为例,尽管有一些我不理解其功能的参数,但concat看起来确实能达到我想要的效果。您能解释一下发生了什么吗? d来自哪里? reset_index的目的是什么? (我以为Time是我的索引?)
在这种情况下,要扩大对concat的使用:我试图按照您的编写来实现它,但是产生的输出与merge类似。那就是:数据大部分按照我的期望进行合并,但是第N行没有合并,如我的原始帖子所示。考虑到多种方法产生的结果相同,在我看来,问题不一定是该方法,而是我的数据中的某些问题。大小可能有问题吗?速度?是什么导致它定期跳过合并行?
我认为@MaxU正在识别您的问题。在加入之前尝试A = A.astype.float()和B = B.astype(float)。
刚刚尝试过,但是输出没有变化。每8或9行不合并。 :(
@ J.Day您可以输出A.dtypes和B.dtypes并将其包含在您的帖子中吗?
我验证了两个DF中的时间dtypes是float64。但是,我在上面的@MaxUs响应中找到了一种解决方法,并且我已经更新了我的初始文章以反映出来。我在编辑中发布的方法有什么问题吗?
@ J.Day对我来说很好。 ID肯定会选择MaxUs答案。
如果两个DF中的Time列具有相同的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 #
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
我已经验证了两个DF中"时间"列的数据类型相同(float64)。正如您所建议的那样,使用merge方法会导致类似的不一致合并,这与我在最初帖子中的A.merge示例类似。在这种情况下,数据确实得到排序,但是第N行没有合并。我希望我可以举一个例子,但是字符数太低了...
@ J.Day,请尝试以下操作:pd.merge_ordered(A.assign(Time=A.Time.round(4)), B.assign(Time=B.Time.round(4)))
我想我知道这是怎么回事。唯一需要注意的是,我的实际数据列名称是Time(秒),而不仅仅是Time(为简洁起见,我简化了最初的示例)。如何编写此行以容纳名称中的额外标点符号?
找到解决方案
根据下面的建议,尽管它们都是相同的dtype(float64),但在合并它们之前,我必须在"时间"列中将它们四舍五入。建议是这样的:
A = A.assign(A.Time = A.Time.round(4))
但是在我的实际情况下,该列被标记为"时间,(秒)"(标点符号与分配关系不大。因此,我使用以下行将其四舍五入:
A['Time, (sec)'] = A['Time, (sec)'].round(4)
它就像一个魅力。这样做有什么问题吗?