Tengo algunos datos jerárquicos que toca fondo en datos de series de tiempo que se ve algo como esto:

df = pandas.DataFrame(
    {'value_a': values_a, 'value_b': values_b},
    index=[states, cities, dates])
df.index.names = ['State', 'City', 'Date']
df

                               value_a  value_b
State   City       Date                        
Georgia Atlanta    2012-01-01        0       10
                   2012-01-02        1       11
                   2012-01-03        2       12
                   2012-01-04        3       13
        Savanna    2012-01-01        4       14
                   2012-01-02        5       15
                   2012-01-03        6       16
                   2012-01-04        7       17
Alabama Mobile     2012-01-01        8       18
                   2012-01-02        9       19
                   2012-01-03       10       20
                   2012-01-04       11       21
        Montgomery 2012-01-01       12       22
                   2012-01-02       13       23
                   2012-01-03       14       24
                   2012-01-04       15       25

Me gustaría realizar el tiempo de remuestreo por la ciudad, algo así como

df.resample("2D", how="sum")

sería la salida de

                             value_a  value_b
State   City       Date                        
Georgia Atlanta    2012-01-01        1       21
                   2012-01-03        5       25
        Savanna    2012-01-01        9       29
                   2012-01-03       13       33
Alabama Mobile     2012-01-01       17       37
                   2012-01-03       21       41
        Montgomery 2012-01-01       25       45
                   2012-01-03       29       49

como es, df.resample('2D', how='sum') me pone

TypeError: Only valid with DatetimeIndex or PeriodIndex

Justo lo suficiente, pero me gustaría especie de esperar que esto funcione:

>>> df.swaplevel('Date', 'State').resample('2D', how='sum')
TypeError: Only valid with DatetimeIndex or PeriodIndex

punto en el que me estoy quedando sin ideas… ¿hay alguna manera de apilar y desapilar, podría ser capaz de ayudar a mí?

InformationsquelleAutor Snakes McGee | 2013-04-03

7 Comentarios

  1. 39

    pd.El mero
    le permite especificar un «groupby instrucción para un objeto de destino». En
    en particular, se puede utilizar para agrupar por fechas, incluso si df.index no es un DatetimeIndex:

    df.groupby(pd.Grouper(freq='2D', level=-1))

    La level=-1 dice pd.Grouper para buscar las fechas en el último nivel de la MultiIndex.
    Por otra parte, usted puede utilizar esto en conjunto con los otros valores del índice:

    level_values = df.index.get_level_values
    result = (df.groupby([level_values(i) for i in [0,1]]
                          +[pd.Grouper(freq='2D', level=-1)]).sum())

    Parece un poco incómodo, pero using_Grouper resulta ser mucho más rápido que el original de mi
    sugerencia, using_reset_index:

    import numpy as np
    import pandas as pd
    import datetime as DT
    def using_Grouper(df):
    level_values = df.index.get_level_values
    return (df.groupby([level_values(i) for i in [0,1]]
    +[pd.Grouper(freq='2D', level=-1)]).sum())
    def using_reset_index(df):
    df = df.reset_index(level=[0, 1])
    return df.groupby(['State','City']).resample('2D').sum()
    def using_stack(df):
    # http://stackoverflow.com/a/15813787/190597
    return (df.unstack(level=[0,1])
    .resample('2D').sum()
    .stack(level=[2,1])
    .swaplevel(2,0))
    def make_orig():
    values_a = range(16)
    values_b = range(10, 26)
    states = ['Georgia']*8 + ['Alabama']*8
    cities = ['Atlanta']*4 + ['Savanna']*4 + ['Mobile']*4 + ['Montgomery']*4
    dates = pd.DatetimeIndex([DT.date(2012,1,1)+DT.timedelta(days = i) for i in range(4)]*4)
    df = pd.DataFrame(
    {'value_a': values_a, 'value_b': values_b},
    index = [states, cities, dates])
    df.index.names = ['State', 'City', 'Date']
    return df
    def make_df(N):
    dates = pd.date_range('2000-1-1', periods=N)
    states = np.arange(50)
    cities = np.arange(10)
    index = pd.MultiIndex.from_product([states, cities, dates], 
    names=['State', 'City', 'Date'])
    df = pd.DataFrame(np.random.randint(10, size=(len(index),2)), index=index,
    columns=['value_a', 'value_b'])
    return df
    df = make_orig()
    print(using_Grouper(df))

    rendimientos

                                   value_a  value_b
    State   City       Date                        
    Alabama Mobile     2012-01-01       17       37
    2012-01-03       21       41
    Montgomery 2012-01-01       25       45
    2012-01-03       29       49
    Georgia Atlanta    2012-01-01        1       21
    2012-01-03        5       25
    Savanna    2012-01-01        9       29
    2012-01-03       13       33

    Aquí es una referencia comparar using_Grouper, using_reset_index, using_stack 5000-fila DataFrame:

    In [30]: df = make_df(10)
    In [34]: len(df)
    Out[34]: 5000
    In [32]: %timeit using_Grouper(df)
    100 loops, best of 3: 6.03 ms per loop
    In [33]: %timeit using_stack(df)
    10 loops, best of 3: 22.3 ms per loop
    In [31]: %timeit using_reset_index(df)
    1 loop, best of 3: 659 ms per loop
    • Gracias — que sin duda hace el trabajo, pero que groupby nos obliga a recalcular las relaciones que ya hemos establecido en nuestro índice jerárquico. No hay una manera de hacer esto con las agrupaciones que ya hemos construido en nuestro índice jerárquico, o son jerárquicos índices simplemente no destinados a ser utilizados para este tipo de cosas?
    • Lo siento, no tengo experiencia suficiente con Pandas decir. La de arriba es más de una alternativa de solución. df.reset_index puede ser una operación lenta y sería mucho mejor si esto se podría hacer sin ella.
    • Una alternativa sería desapilar, el Estado y la Ciudad de las columnas antes de remuestreo, pero dudo si eso es más eficiente.
    • Curiosamente, este es más eficiente que apilar y desapilar: En [561]: timeit.timeit(«de principal importar df; df.reset_index(nivel=[0,1]).groupby([‘Estado’, ‘Ciudad’]).volver a muestrear(‘2D’, cómo=’suma’)», número=1000) Out[561]: 7.496185064315796 En [562]: timeit.timeit(«de principal importar df; df.desapilar(nivel=[0,1]).volver a muestrear(‘2D’, cómo=’suma’).pila(nivel=[2,1]).swaplevel(2,0)», número=1000) Out[562]: 10.618878841400146
    • Creo que la verdadera respuesta a esta pregunta es «si vas a hacer este tipo de cálculos, se debe trabajar con un groupby objeto, no un índice jerárquico»
    • No tengo experiencia suficiente con Pandas de decir». Gracioso leer que, 1000+ respuestas más tarde…
    • Felizmente, 1000+ respuestas más tarde, puedo decir que hay una solución más rápida — uso pd.Grouper.
    • He tratado de usar su método (mi df tiene un triple del índice de '#' (int), 'jobid' (string), 'datetime' (datetime) pero con un pd.Grouper(freq='2D') he obtenido un extraño remuestreo, es decir, los nuevos df carece cada segundo del día, pero unicc todavía tiene valores por hora. No está seguro de lo que estoy diciendo es claro?
    • Puedes construir un ejemplo que se reproduce el problema? Podría ser más fácil de publicar en una nueva pregunta. Yo estaría encantado de echar un vistazo.
    • Yo llegué aquí, pero se olvidó de incluir el enlace stackoverflow.com/q/44718125/6071128

  2. 14

    Una alternativa el uso de la pila/desapilado

    df.unstack(level=[0,1]).resample('2D', how='sum').stack(level=[2,1]).swaplevel(2,0)
    value_a  value_b
    State   City       Date
    Georgia Atlanta    2012-01-01        1       21
    Alabama Mobile     2012-01-01       17       37
    Montgomery 2012-01-01       25       45
    Georgia Savanna    2012-01-01        9       29
    Atlanta    2012-01-03        5       25
    Alabama Mobile     2012-01-03       21       41
    Montgomery 2012-01-03       29       49
    Georgia Savanna    2012-01-03       13       33

    Notas:

    1. Ninguna idea acerca de la comparación de rendimiento
    2. Posible pandas error de la pila(nivel=[2,1]) trabajado, pero la pila(nivel=[1,2]) no
    • Esto fue realmente útil!
    • Me encontré con problemas para el cálculo de pct_change inmediatamente después de esta. Problema Similar, como here. Terminé con la siguiente: reset_index, sort_values, groupby, pct_change (como en el enlace)
  3. 10

    Esto funciona:

    df.groupby(level=[0,1]).apply(lambda x: x.set_index('Date').resample('2D', how='sum'))
    value_a  value_b
    State   City       Date
    Alabama Mobile     2012-01-01       17       37
    2012-01-03       21       41
    Montgomery 2012-01-01       25       45
    2012-01-03       29       49
    Georgia Atlanta    2012-01-01        1       21
    2012-01-03        5       25
    Savanna    2012-01-01        9       29
    2012-01-03       13       33

    Si la columna de Fecha se cuerdas, a continuación, convertir a datetime de antemano:

    df['Date'] = pd.to_datetime(df['Date'])
    • no, este es muy lento.
  4. 6

    Usted necesita el groupby() método y de dotarla de un pd.El mero para cada nivel de la MultiIndex usted desea mantener en el resultado DataFrame. A continuación, puede aplicar una operación de elección.

    Para remuestrear la fecha o de fecha y hora los niveles, es necesario establecer la freq argumento con la frecuencia de la elección — con un enfoque similar, el uso de pd.TimeGrouper() está en desuso en favor de pd.Grouper() con el freq argumento.

    Esto debe darle el DataFrame usted necesita:

    df.groupby([pd.Grouper(level='State'), pd.Grouper(level='City'), pd.Grouper(level='Date', freq='2D')]).sum()

    La Serie De Tiempo De La Guía en la pandas documentación describe resample() como: «la base del tiempo groupby, seguido por un método de reducción en cada uno de sus grupos». Por lo tanto, el uso de groupby() debe ser técnicamente la misma operación como el uso de .resample() en un DataFrame con un único índice.

    El mismo párrafo señala a la sección de libros de cocina en el remuestreo para obtener ejemplos más avanzados, donde el ‘ Agrupamiento por medio de un MultiIndex la entrada es muy relevante para esta pregunta. Espero que ayude.

    • A diferencia de muchos de contorneado respuestas a este problema, esto es fácil de entender la solución que resulta en un fácil para leer el código.
    • La mejor respuesta.
  5. 1

    Sé que esta pregunta es de un par de años, pero tuve el mismo problema y se llegó a una solución más simple que requiere de 1 línea:

    >>> import pandas as pd
    >>> ts = pd.read_pickle('time_series.pickle')
    >>> ts
    xxxxxx1  yyyyyyyyyyyyyyyyyyyyyy1  2012-07-01     1
    2012-07-02    13
    2012-07-03     1
    2012-07-04     1
    2012-07-05    10
    2012-07-06     4
    2012-07-07    47
    2012-07-08     0
    2012-07-09     3
    2012-07-10    22
    2012-07-11     3
    2012-07-12     0
    2012-07-13    22
    2012-07-14     1
    2012-07-15     2
    2012-07-16     2
    2012-07-17     8
    2012-07-18     0
    2012-07-19     1
    2012-07-20    10
    2012-07-21     0
    2012-07-22     3
    2012-07-23     0
    2012-07-24    35
    2012-07-25     6
    2012-07-26     1
    2012-07-27     0
    2012-07-28     6
    2012-07-29    23
    2012-07-30     0
    ..
    xxxxxxN  yyyyyyyyyyyyyyyyyyyyyyN  2014-06-02     0
    2014-06-03     1
    2014-06-04     0
    2014-06-05     0
    2014-06-06     0
    2014-06-07     0
    2014-06-08     2
    2014-06-09     0
    2014-06-10     0
    2014-06-11     0
    2014-06-12     0
    2014-06-13     0
    2014-06-14     0
    2014-06-15     0
    2014-06-16     0
    2014-06-17     0
    2014-06-18     0
    2014-06-19     0
    2014-06-20     0
    2014-06-21     0
    2014-06-22     0
    2014-06-23     0
    2014-06-24     0
    2014-06-25     4
    2014-06-26     0
    2014-06-27     1
    2014-06-28     0
    2014-06-29     0
    2014-06-30     1
    2014-07-01     0
    dtype: int64
    >>> ts.unstack().T.resample('W', how='sum').T.stack()
    xxxxxx1  yyyyyyyyyyyyyyyyyyyyyy1  2012-06-25/2012-07-01      1
    2012-07-02/2012-07-08     76
    2012-07-09/2012-07-15     53
    2012-07-16/2012-07-22     24
    2012-07-23/2012-07-29     71
    2012-07-30/2012-08-05     38
    2012-08-06/2012-08-12    258
    2012-08-13/2012-08-19    144
    2012-08-20/2012-08-26    184
    2012-08-27/2012-09-02    323
    2012-09-03/2012-09-09    198
    2012-09-10/2012-09-16    348
    2012-09-17/2012-09-23    404
    2012-09-24/2012-09-30    380
    2012-10-01/2012-10-07    367
    2012-10-08/2012-10-14    163
    2012-10-15/2012-10-21    338
    2012-10-22/2012-10-28    252
    2012-10-29/2012-11-04    197
    2012-11-05/2012-11-11    336
    2012-11-12/2012-11-18    234
    2012-11-19/2012-11-25    143
    2012-11-26/2012-12-02    204
    2012-12-03/2012-12-09    296
    2012-12-10/2012-12-16    146
    2012-12-17/2012-12-23     85
    2012-12-24/2012-12-30    198
    2012-12-31/2013-01-06    214
    2013-01-07/2013-01-13    229
    2013-01-14/2013-01-20    192
    ...
    xxxxxxN  yyyyyyyyyyyyyyyyyyyyyyN  2013-12-09/2013-12-15      3
    2013-12-16/2013-12-22      0
    2013-12-23/2013-12-29      0
    2013-12-30/2014-01-05      1
    2014-01-06/2014-01-12      3
    2014-01-13/2014-01-19      6
    2014-01-20/2014-01-26     11
    2014-01-27/2014-02-02      0
    2014-02-03/2014-02-09      1
    2014-02-10/2014-02-16      4
    2014-02-17/2014-02-23      3
    2014-02-24/2014-03-02      1
    2014-03-03/2014-03-09      4
    2014-03-10/2014-03-16      0
    2014-03-17/2014-03-23      0
    2014-03-24/2014-03-30      9
    2014-03-31/2014-04-06      1
    2014-04-07/2014-04-13      1
    2014-04-14/2014-04-20      1
    2014-04-21/2014-04-27      2
    2014-04-28/2014-05-04      8
    2014-05-05/2014-05-11      7
    2014-05-12/2014-05-18      5
    2014-05-19/2014-05-25      2
    2014-05-26/2014-06-01      8
    2014-06-02/2014-06-08      3
    2014-06-09/2014-06-15      0
    2014-06-16/2014-06-22      0
    2014-06-23/2014-06-29      5
    2014-06-30/2014-07-06      1
    dtype: int64

    ts.unstack().T.resample('W', how='sum').T.stack() es todo lo que hizo! Muy fácil, parece bastante potente. El pepinillo estoy leyendo en es 331M, así que esta es una muy robusta estructura de datos; el remuestreo se tarda sólo un par de segundos en mi MacBook Pro.

    • Bonito, pero esto sólo funciona si usted tiene una sola columna.
  6. 1

    Tuve el mismo problema, estaba rompiendo mi cabeza por un tiempo, pero luego he leído la documentación de la .resample función en la 0.19.2 docs, y veo que hay un nuevo kwarg llamado «nivel» que puede utilizar para especificar un nivel en un MultiIndex.

    Edit: Más detalles en el «Lo Nuevo» sección.

    • Doesnt realmente responder a la pregunta acerca de cuando usted necesita para volver a muestrear mientras que la preservación de varios índices. En la documentación, el nivel de kwarg debe ser un datetime-como parámetro y la pregunta fue de alrededor de no-datetime secundaria columnas de agrupación
  7. 0

    No he comprobado la eficacia de esta, pero mi instinto forma de llevar a cabo datetime operaciones en un multi-índice fue por una especie de manual de «split-aplicar-combinar el» proceso de uso de un diccionario de comprensión.

    Suponiendo que el DataFrame es no indexada. (Usted puede hacer .reset_index() primero), este funciona de la siguiente manera:

    1. Grupo por parte de los no-columnas de fecha
    2. Conjunto de «Fecha» como índice y volver a muestrear cada fragmento
    3. Volver a montar el uso de pd.concat

    El código final se ve como:

    pd.concat({g: x.set_index("Date").resample("2D").mean()
    for g, x in house.groupby(["State", "City"])})

Dejar respuesta

Please enter your comment!
Please enter your name here