Dividir los valores de la matriz anidada de la celda Pandas Dataframe en varias filas

Tengo un Data Frame de Pandas de la siguiente forma

introduzca la descripción de la imagen aquí

Hay una fila por ID por año (2008 – 2015). Para las columnas Max Temp , Min Temp y Rain cada celda contiene una matriz de valores correspondientes a un día en ese año, es decir, para el cuadro de arriba

  • frame3.iloc[0]['Max Temp'][0] es el valor para el 1 de enero de 2011
  • frame3.iloc[0]['Max Temp'][364] es el valor para el 31 de diciembre de 2011.

Soy consciente de que esto está mal estructurado, pero esta es la información con la que tengo que lidiar. Se almacena en MongoDB de esta manera (donde una de estas filas equivale a un documento en Mongo).

Quiero dividir estas matrices anidadas, de modo que en lugar de una fila por ID por año, tenga una fila por ID por día. Sin embargo, al dividir la matriz, también me gustaría crear una nueva columna para capturar el día del año, en función del índice de la matriz actual. Luego usaría este día, más la columna Year para crear un IndiceInterno.

introduzca la descripción de la imagen aquí

Busqué aquí respuestas relevantes, pero solo encontré esta que realmente no me ayuda.

Puede ejecutar .apply(pd.Series) para cada una de sus columnas, luego stack y concatenar los resultados.

Para una serie

 s = pd.Series([[0, 1], [2, 3, 4]], index=[2011, 2012]) s Out[103]: 2011 [0, 1] 2012 [2, 3, 4] dtype: object 

funciona de la siguiente manera

 s.apply(pd.Series).stack() Out[104]: 2011 0 0.0 1 1.0 2012 0 2.0 1 3.0 2 4.0 dtype: float64 

Los elementos de la serie tienen diferente longitud (importa porque 2012 fue un año bisiesto). La serie intermedia, es decir, antes de la stack , tenía un valor de NaN que se ha eliminado posteriormente.

Ahora, vamos a tomar un marco:

 a = list(range(14)) b = list(range(20, 34)) df = pd.DataFrame({'ID': [11111, 11111, 11112, 11112], 'Year': [2011, 2012, 2011, 2012], 'A': [a[:3], a[3:7], a[7:10], a[10:14]], 'B': [b[:3], b[3:7], b[7:10], b[10:14]]}) df Out[108]: AB ID Year 0 [0, 1, 2] [20, 21, 22] 11111 2011 1 [3, 4, 5, 6] [23, 24, 25, 26] 11111 2012 2 [7, 8, 9] [27, 28, 29] 11112 2011 3 [10, 11, 12, 13] [30, 31, 32, 33] 11112 2012 

Entonces podemos correr:

 # set an index (each column will inherit it) df2 = df.set_index(['ID', 'Year']) # the trick unnested_lst = [] for col in df2.columns: unnested_lst.append(df2[col].apply(pd.Series).stack()) result = pd.concat(unnested_lst, axis=1, keys=df2.columns) 

y obten:

 result Out[115]: AB ID Year 11111 2011 0 0.0 20.0 1 1.0 21.0 2 2.0 22.0 2012 0 3.0 23.0 1 4.0 24.0 2 5.0 25.0 3 6.0 26.0 11112 2011 0 7.0 27.0 1 8.0 28.0 2 9.0 29.0 2012 0 10.0 30.0 1 11.0 31.0 2 12.0 32.0 3 13.0 33.0 

El rest (índice de fecha y hora) es más sencillo. Por ejemplo:

 # DatetimeIndex years = pd.to_datetime(result.index.get_level_values(1).astype(str)) # TimedeltaIndex days = pd.to_timedelta(result.index.get_level_values(2), unit='D') # If the above line doesn't work (a bug in pandas), try this: # days = result.index.get_level_values(2).astype('timedelta64[D]') # the sum is again a DatetimeIndex dates = years + days dates.name = 'Date' new_index = pd.MultiIndex.from_arrays([result.index.get_level_values(0), dates]) result.index = new_index result Out[130]: AB ID Date 11111 2011-01-01 0.0 20.0 2011-01-02 1.0 21.0 2011-01-03 2.0 22.0 2012-01-01 3.0 23.0 2012-01-02 4.0 24.0 2012-01-03 5.0 25.0 2012-01-04 6.0 26.0 11112 2011-01-01 7.0 27.0 2011-01-02 8.0 28.0 2011-01-03 9.0 29.0 2012-01-01 10.0 30.0 2012-01-02 11.0 31.0 2012-01-03 12.0 32.0 2012-01-04 13.0 33.0