Объединение фреймов данных Pandas с многоиндексными столбцами и нерегулярными временными метками

#python #pandas #time-series #concat #multi-index

#python #pandas #временные ряды #объединение #многоиндексный

Вопрос:

У меня в списке много отдельных фреймов данных, каждый из которых имеет многоиндексные столбцы и представляет собой временные ряды для разных периодов времени и длины. Я хотел бы сделать три вещи:

  1. Объединение всех отдельных фреймов данных
  2. Любые фреймы данных с одинаковыми многоиндексными столбцами добавляются и сортируются по оси времени
  3. Фреймы данных с разными многоиндексными столбцами объединяются вдоль оси столбцов (ось = 1)

Я знаю, что по умолчанию `pandas.concat (objs, axis = 1) объединяет столбцы и сортирует индекс строки, но я также хотел бы, чтобы фреймы данных с одинаковыми метками и уровнями соединялись с длинной временной осью вместо того, чтобы иметь их полностью рядом.

Я должен также упомянуть, что фреймы данных с одинаковыми метками и уровнями находятся в разные периоды времени, которые соединяются друг с другом, но не перекрываются.

В качестве примера:

 first,second,third = rand(5,2),rand(5,2),rand(10,2)

a = pd.DataFrame(first, index=pd.DatetimeIndex(start='1990-01-01', periods=5, freq='d'))
a.columns = pd.MultiIndex.from_tuples([('A','a'),('A','b')])

b = pd.DataFrame(second, index=pd.DatetimeIndex(start='1990-01-06', periods=5, freq='d'))
b.columns = pd.MultiIndex.from_tuples([('A','a'),('A','b')])

c = pd.DataFrame(third, index=pd.DatetimeIndex(start='1990-01-01', periods=10, freq='d'))
c.columns = pd.MultiIndex.from_tuples([('B','a'),('B','b')])

pd.concat([a,b,c], axis=1)
  

Дает это:

 Out[3]:
    A   B
    a   b   a   b   a   b
1990-01-01  0.351481    0.083324    NaN     NaN     0.060026    0.124302
1990-01-02  0.486032    0.742887    NaN     NaN     0.570997    0.633906
1990-01-03  0.145066    0.386665    NaN     NaN     0.166567    0.147794
1990-01-04  0.257831    0.995324    NaN     NaN     0.630652    0.534507
1990-01-05  0.446912    0.374049    NaN     NaN     0.311473    0.727622
1990-01-06  NaN     NaN     0.920003    0.051772    0.731657    0.393296
1990-01-07  NaN     NaN     0.142397    0.837654    0.597090    0.833893
1990-01-08  NaN     NaN     0.506141    0.056407    0.832294    0.222501
1990-01-09  NaN     NaN     0.655442    0.754245    0.802421    0.743875
1990-01-10  NaN     NaN     0.195767    0.880637    0.215509    0.857576
  

Есть ли простой способ получить это?

 d = a.append(b)
pd.concat([d,c], axis=1)

Out[4]:
    A   B
    a   b   a   b
1990-01-01  0.351481    0.083324    0.060026    0.124302
1990-01-02  0.486032    0.742887    0.570997    0.633906
1990-01-03  0.145066    0.386665    0.166567    0.147794
1990-01-04  0.257831    0.995324    0.630652    0.534507
1990-01-05  0.446912    0.374049    0.311473    0.727622
1990-01-06  0.920003    0.051772    0.731657    0.393296
1990-01-07  0.142397    0.837654    0.597090    0.833893
1990-01-08  0.506141    0.056407    0.832294    0.222501
1990-01-09  0.655442    0.754245    0.802421    0.743875
1990-01-10  0.195767    0.880637    0.215509    0.857576
  

Ключевым моментом здесь является то, что я не знаю, как будут упорядочены фреймы данных в списке, мне в основном нужно что-то, что знает, когда нужно объединять (obj, axis = 1) или concat (obj, axis = 0), и может сделать это, чтобы объединить мой список фреймов данных. Может быть, в pandas уже есть что-то, что может это сделать?

Ответ №1:

Я не уверен, что есть однострочный способ сделать это (может быть)…
Это один раз, когда я бы подумал о создании пустого фрейма, а затем его заполнении:

 In [11]: frames = [a, b, c]
  

Получить объединение их индекса и столбцов:

 In [12]: index = sum(x.index for x in frames)
         cols = sum(x.columns for x in frames)

In [13]: res = pd.DataFrame(index=index, columns=cols)
  

Заполните это для каждого фрейма (по метке):

 In [14]: for df in [a, b, c]:
             res.loc[df.index, df.columns] = df

In [15]: res
Out[15]:
                     A                     B
                     a           b         a         b
1990-01-01   0.8516285   0.4087078  0.577000  0.595293
1990-01-02   0.6544393   0.4377864  0.851378  0.595919
1990-01-03   0.3123428  0.03825423  0.834704  0.989195
1990-01-04   0.2314499   0.4971448  0.343455  0.770400
1990-01-05   0.1982945   0.9031414  0.466225  0.463490
1990-01-06   0.7370323   0.3923151  0.263120  0.892815
1990-01-07  0.09038236   0.8778266  0.643816  0.049769
1990-01-08   0.7199705  0.02114493  0.766267  0.472471
1990-01-09  0.06733081    0.443561  0.984558  0.443647
1990-01-10   0.4695022   0.5648693  0.870240  0.949072
  

Комментарии:

1. Отличная идея! Очевидно, не очень быстро, но на самом деле дело не в этом.