我有两个数据帧df1, df2
,它们的索引类型相同,但是几乎没有相同的匹配项。索引也可能有重复项。列A和B将由内部唯一值组成。所有索引和列都是有序的,但方向不同。 df1.index
正在下降,df1['A']
正在下降。 df2.index
上升而df2['B']
下降。
df1:(左侧数字是数据框的未命名索引)
A
80 -13.545215
76 -12.270691
73 -11.274724
65 -8.280187
38 -7.965972
13 -7.788130
10 -6.690969
6 -5.273063
df2:
B
8 -13.827641
10 -12.283885
14 -11.459951
62 -11.067622
64 -10.745988
87 -10.661594
95 -9.816053
97 -7.740810
我想组合数据帧,以便将df2['B']
中的值放置到距df2
中的df1
最近的对应索引处,以便所需的输出采用以下形式:
B A
8 -13.827641 -6.690969
10 -12.283885 -6.690969
14 -11.459951 -7.965972
62 -11.067622 -8.280187
64 -10.745988 -8.280187
87 -10.661594 NaN
95 -9.816053 NaN
97 -7.740810 NaN
如果从绝对角度而言最接近的索引A低于索引B,则索引A的上限值是正确的匹配项。如果索引B在索引A中没有更高的对应匹配,则NaN是正确的匹配。
到目前为止,我已经使用pd.merge()
和fillna()
进行了必要的分析。但是有些人可能发现对插值/综合数据进行分析是“不自然的”。无论如何,这就是我一直在做的事情:
pd.merge()
和dropna():
的部分代码示例
# outer merge
df3 = pd.merge(df1,df2, how = 'outer', left_index = True, right_index = True)
#df4 = df3.interpolate(method = 'linear')[1:]
df4 = df3.interpolate(method = 'linear').dropna()
df4
输出:
A B
8 -5.982016 -13.827641
10 -6.690969 -12.283885
13 -7.788130 -11.871918
14 -7.877051 -11.459951
38 -7.965972 -11.263787
62 -8.070710 -11.067622
64 -8.175448 -10.745988
65 -8.280187 -10.729109
73 -11.274724 -10.712230
76 -12.270691 -10.695352
80 -13.545215 -10.678473
87 -13.545215 -10.661594
95 -13.545215 -9.816053
97 -13.545215 -7.740810
情节:
完整的数据和代码示例
#imports
import numpy as np
import pandas as pd
# Some sample data
np.random.seed(1)
df1_index = sorted(np.random.randint(1,101,8), reverse = True)
df1info = {'A':sorted((np.random.normal(10, 2, 8))*-1)}
df2_index = sorted(np.random.randint(1,101,8))
df2info = {'B':sorted(np.random.normal(10, 2, 8)*-1)}
# Two dataframes
df1 = pd.DataFrame(df1info, index = df1_index)
df2 = pd.DataFrame(df2info, index = df2_index)
# outer merge
df3 = pd.merge(df1,df2, how = 'outer', left_index = True, right_index = True)
# interpolate missing values
df4 = df3.interpolate(method = 'linear').dropna()
# plot
df4.plot()
谢谢您的任何建议!
编辑1:场景1重复:
如果df2.index
在df1.index
中有完全匹配项,并且df1.index
有重复项,则正确的匹配项是最低的df1.index
。我希望这是有道理的。如果由于某种原因被证明是荒谬的,我愿意接受其他建议!
答案 0 :(得分:2)
O(n)
解决方案df2_index.sort()
df1_index.sort()
a = 0
b = 0
mapping = [[],[]]
while b < len(df2_index) and a < len(df1_index):
if df1_index[a] == df2_index[b]:
mapping[0].append(df2_index[b])
mapping[1].append(df1.loc[df1_index[a], "A"])
b += 1
a += 1
elif df1_index[a] > df2_index[b]:
mapping[0].append(df2_index[b])
mapping[1].append(df1.loc[df1_index[a], "A"])
b += 1
else:
a += 1
df = pd.DataFrame({'A': mapping[1]}, index = mapping[0])
df2.merge(df, left_index=True, right_index=True, how='outer')
输出
B A
8 -13.827641 -6.690969
10 -12.283885 -6.690969
14 -11.459951 -7.965972
62 -11.067622 -8.280187
64 -10.745988 -8.280187
87 -10.661594 NaN
95 -9.816053 NaN
97 -7.740810 NaN
b
指向B的索引,a
指向A的索引b
,我们就会找到下一个最大值a
,并在找到它时将其保存b
== a
,那么我们就完成了这些记录,因此我们继续前进a
> b
,那么我们喜欢b
的值,所以我们移动b。我们不会移动a
,因为这也可以成为下一个b
的候选人a
<b
之所以移至a
,是因为b
的候选对象将在当前a
之后,因为它已排序。