Как интерполировать все значения в двух отдельных фреймах данных Pandas? - PullRequest
0 голосов
/ 05 февраля 2019

Предположим, у вас есть два кадра данных Pandas, один из которых содержит данные за 2020 год, а другой - данные за 2030 год. Оба кадра данных имеют одинаковую форму, имена столбцов и содержат только числовые значения.Для простоты мы создадим их следующим образом:

twenty = pd.DataFrame({'A':[1,1,1], 'B':[3,3,3]})
thirty = pd.DataFrame({'A':[3,3,3], 'B':[7,7,7]})

Теперь цель состоит в том, чтобы выполнить линейную интерполяцию для всех значений в этих фреймах данных, чтобы получить новый фрейм данных для 2025 года (или любого другого года, когда мыВыбрать).Итак, мы хотели бы интерполировать между каждым парным набором значений, таких как twenty['A'][0] и thirty['A'][0].Если мы сделали это для целевого 2025 года, результат должен быть:

twentyfive = pd.DataFrame({'A':[2,2,2],'B':[5,5,5]})

Я пытался использовать np.interp;однако, насколько я могу судить, это действительно предназначено для интерполяции в данном (единственном) массивеИ я решил проблему, используя более грубый метод плавления DataFrames, добавления столбцов года, объединения их вместе, а затем создания нового столбца с интерполированными значениями.Это немного грязно и многословно.

Я чувствую, что должен быть более прямой (и оптимизированный) способ выполнения этой задачи.Любая помощь приветствуется.

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Вы можете concat быть умным по отношению к клавишам (называя их целыми числами), а затем groupby, позволяя вам интерполировать все:

import pandas as pd

df = pd.concat([twenty, thirty], keys=[20,30], axis=1)
s = (df.groupby(df.columns.get_level_values(1), axis=1)
        .apply(lambda x: x.T.reset_index(1, drop=True).reindex(np.arange(20,31)).interpolate())).T

      20   21   22   23   24   25   26   27   28   29   30
A 0  1.0  1.2  1.4  1.6  1.8  2.0  2.2  2.4  2.6  2.8  3.0
  1  1.0  1.2  1.4  1.6  1.8  2.0  2.2  2.4  2.6  2.8  3.0
  2  1.0  1.2  1.4  1.6  1.8  2.0  2.2  2.4  2.6  2.8  3.0
B 0  3.0  3.4  3.8  4.2  4.6  5.0  5.4  5.8  6.2  6.6  7.0
  1  3.0  3.4  3.8  4.2  4.6  5.0  5.4  5.8  6.2  6.6  7.0
  2  3.0  3.4  3.8  4.2  4.6  5.0  5.4  5.8  6.2  6.6  7.0

Теперь, если вы просто заботитесь о 25:

s[25].unstack(0)

     A    B
0  2.0  5.0
1  2.0  5.0
2  2.0  5.0
0 голосов
/ 05 февраля 2019

Вы можете попробовать взять среднее значение напрямую, если оба имеют одинаковую форму

(thirty + twenty)/2

Out:

    A   B
0   2   5
1   2   5
2   2   5

Редактировать: если кадры данных не имеют одинаковые формы, вы можете попробоватьслияния со столбцами внутреннего объединения и группировки, чтобы получить интерполированное среднее.

df = pd.merge(twenty,thirty, left_index=True, right_index=True, how='inner').rename(columns=lambda x: x.split('_')[0])
df.T.groupby(df.T.index).mean().T

Out:

    A   B
0   2   5
1   2   5
2   2   5
...