Pandas - 具有重复值的列的外部连接
Posted
技术标签:
【中文标题】Pandas - 具有重复值的列的外部连接【英文标题】:Pandas - Outer Join on Column with Repeating Values 【发布时间】:2018-12-15 05:28:53 【问题描述】:这是我在 Stack Overflow 上的第一个问题,如果我的问题不清楚,请告诉我如何帮助您。
目标:使用 Python 和 Pandas 外连接(或合并)包含不同实验试验的数据集,其中每个试验的“x”轴非常相似,但有一些偏差。最重要的是,“x”轴增加、达到最大值然后减小,通常与先前存在的“x”点重叠。
问题:当我去加入/合并“x”上的数据集时,“x”列被排序,弄乱了收集数据的顺序,无法正确绘制它。
这是我正在尝试做的一个小例子:
不让我添加图片,因为我是新人。这是生成这些示例数据集的代码。
数据集:
进口:
import numpy as np
import pandas as pd
import random as rand
代码:
T1 = 'x':np.array([1,1.5,2,2.5,3,3.5,4,5,2,1]),'y':np.array([10000,8500,7400,6450,5670,5100,4600,4500,8400,9000]),'z':np.array(rand.sample(range(0,10000),10))'
T2 = 'x':np.array([1,2,3,4,5,6,7,2,1.5,1]),'y':np.array([10500,7700,5500,4560,4300,3900,3800,5400,8400,8800]),'z':np.array(rand.sample(range(0,10000),10))
Trial1 = pd.DataFrame(T1)
Trial2 = pd.DataFrame(T2)
尝试合并/加入:
WomboCombo = Trial1.join(Trial2,how='outer',lsuffix=1,rsuffix=2, on='x')
WomboCombo2 = pd.merge(left=Trial1, right= Trial2, how = 'outer', left
尝试分成两部分,增加部分和减少部分(手动找到数据“x”开始减少的行号):
Trial1Inc = Trial1[0:8]
Trial2Inc = Trial2[0:7]
结果 - 合并效果很好,与“x”列连接混乱,不知道为什么:
Trial1Inc.merge(Trial2Inc,on='x',how='outer', suffixes=[1,2])
Incrementing section Merge Result
Trial1Inc.join(Trial2Inc,on='x',how='outer', lsuffix=1,rsuffix=2)
Incrementing section Join Result 希望我的例子很清楚,试验 1 中的“x”列增加到 5,然后减少回 0。在试验 2 中,我稍微改变了测试,因为我注意到我需要的数据“x”值稍高。 Trial 2 增加至 7,然后迅速减少回 0。
我的最终目标是绘制所有 y 值的平均值(试验之间存在重叠的地方)与相应的 x 值。
如果有重叠,我可以添加误差线。 Pandas 对我正在尝试做的事情几乎是完美的,因为外连接会在没有重叠的地方添加空值,并且能够在有重叠时水平连接两个试验。
现在剩下的就是弄清楚如何加入“x”列,但要保持其值递增然后递减的顺序。首先增加“x”然后减少它对我来说很重要的原因是,当查看“y”值时,似乎给定“x”处的初始“y”值大于“y” " x" 减小时的值(EG 在试验 1 中 x=1,y=10000,然而,在试验后期,当我们回到 x=1,y=9000 时,这种趋势很重要。当 Pandas 对合并之前的列,而不是有一条干净的曲线显示“y”随着“x”的增加而减少,然后相反,在数据连接的任何点都有垂直向下的跳跃。
我非常感谢任何帮助:
A) 当“x”包含重复项时,让我加入“x”的完美解决方案
B) 一种将数据集拆分为递增“x”和递减“x”的有效方法,以便我可以分别合并每个试验的递增和递减部分,然后垂直连接它们。
希望我在解释我想解决的问题方面做得很好。如果我能澄清任何事情,请告诉我,
感谢您的帮助!
【问题讨论】:
能否添加包含 pd.merge 以及 numpy 和 rand 的导入的自包含代码?我的想法是考虑使用索引而不是 x 进行合并。我认为这会阻止对 x 进行排序,但我想在回答之前在代码中尝试一下。 您可以根据“x”值(前半部分单调递增,后半部分单调递减)将每个数据帧分成两部分,并分别进行连接。 @DavidGaertner 感谢您的回复。我更新了我的帖子,请注意,试验不一定有相同数量的数据点,有的有 30 个,有的有 1000 个。期待看到我们如何在索引上合并,但仍然要确保排列所有“x”值在一起。 @xyzjayne 我同意你关于解决方案的想法,有没有一种有效的方法将数据集分成两部分?一半增加一半减少? 【参考方案1】:我认为@xyzjayne 拆分数据框的想法是个好主意。
拆分 Trial1 和 Trial2:
# index of max x value in Trial2
t2_max_index = Trial2.index[Trial2['x'] == Trial2['x'].max()].tolist()
# split Trial2 by max value
trial2_high = Trial2.loc[:t2_max_index[0]].set_index('x')
trial2_low = Trial2.loc[t2_max_index[0]+1:].set_index('x')
# index of max x value in Trial1
t1_max_index = Trial1.index[Trial1['x'] == Trial1['x'].max()].tolist()
# split Trial1 by max vlaue
trial1_high = Trial1.loc[:t1_max_index[0]].set_index('x')
trial1_low = Trial1.loc[t1_max_index[0]+1:].set_index('x')
一旦我们拆分数据帧,我们将higher
s 和lowers
连接在一起:
WomboCombo_high = trial1_high.join(trial2_high, how='outer', lsuffix='1', rsuffix='2', on='x').reset_index()
WomboCombo_low = trial1_low.join(trial2_low, how='outer', lsuffix='1', rsuffix='2', on='x').reset_index()
我们现在将它们组合在一起,得到一个数据帧WomboCombo
WomboCombo = WomboCombo_high.append(WomboCombo_low)
输出:
x y1 z1 y2 z2
0 1.0 10000.0 3425.0 10500.0 3061.0
1 1.5 8500.0 5059.0 NaN NaN
2 2.0 7400.0 2739.0 7700.0 7090.0
3 2.5 6450.0 9912.0 NaN NaN
4 3.0 5670.0 2099.0 5500.0 1140.0
5 3.5 5100.0 9637.0 NaN NaN
6 4.0 4600.0 7581.0 4560.0 9584.0
7 5.0 4500.0 8616.0 4300.0 3940.0
8 6.0 NaN NaN 3900.0 5896.0
9 7.0 NaN NaN 3800.0 6211.0
0 2.0 8400.0 3181.0 5400.0 9529.0
2 1.5 NaN NaN 8400.0 3260.0
1 1.0 9000.0 4280.0 8800.0 8303.0
【讨论】:
【参考方案2】:一种可能的解决方案是为您提供试验行特定的 ID,然后在这些 ID 上合并。应该保持 x 值不被排序。
【讨论】:
【参考方案3】:这是我正在尝试的,但它没有解决不同数量的数据点。我喜欢gym-hh的回答,虽然我不清楚你想要两列y,z对。所以你可以结合他的想法和这段代码来得到你需要的东西。
Trial1['index1'] = Trial1.index
Trial2['index1'] = Trial2.index
WomboCombo = Trial1.append(Trial2)
WomboCombo.sort_values(by=['index1'],inplace=True)
WomboCombo
输出:
x y z index1
0 1.0 10000 7148 0
0 1.0 10500 2745 0
1 1.5 8500 248 1
1 2.0 7700 9505 1
2 2.0 7400 6380 2
2 3.0 5500 3401 2
3 2.5 6450 6183 3
3 4.0 4560 5281 3
4 3.0 5670 99 4
4 5.0 4300 8864 4
5 3.5 5100 5132 5
5 6.0 3900 7570 5
6 4.0 4600 9951 6
6 7.0 3800 7447 6
7 2.0 5400 3713 7
7 5.0 4500 3863 7
8 1.5 8400 8776 8
8 2.0 8400 1592 8
9 1.0 9000 2167 9
9 1.0 8800 782 9
【讨论】:
以上是关于Pandas - 具有重复值的列的外部连接的主要内容,如果未能解决你的问题,请参考以下文章
合并具有来自两个不同列的匹配值的 DataFrame - Pandas [重复]
Pandas列表的列,通过迭代(选择)三列的每个列表元素作为新列和行来创建多列[重复]