У меня есть два 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
. Я надеюсь, что в этом есть смысл. Если по какой-то причине это окажется бессмысленным, я открыт для других предложений!
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
указывает на индексb
мы находим следующий максимум a
и сохраняем его, когда находимb
== a
то мы закончили с этими записями, поэтому мы идем впередa
> b
тогда мы находим значение b
поэтому перемещаем b. Мы не двигаем, потому что это также может быть кандидатом на следующие a
b
a
< b
мы перемещаем a
потому что кандидат на b
будет где-то после текущего a
потому что он отсортирован.