Soy sospechoso que esto es trivial, pero yo todavía por descubrir el hechizo que me permitirá seleccionar filas de una Pandas dataframe basada en los valores de una jerárquico clave. Así, por ejemplo, imaginemos que tenemos el siguiente dataframe:

import pandas
df = pandas.DataFrame({'group1': ['a','a','a','b','b','b'],
                       'group2': ['c','c','d','d','d','e'],
                       'value1': [1.1,2,3,4,5,6],
                       'value2': [7.1,8,9,10,11,12]
})
df = df.set_index(['group1', 'group2'])

df se ve como sería de esperar:

La selección de las filas de una Pandas dataframe con un compuesto (jerárquica) índice de

Si df no indizadas en el grupo 1 que yo podría hacer lo siguiente:

df['group1' == 'a']

Pero que falla en este dataframe con un índice. Así que tal vez debería pensar en esto como un Pandas serie con un índice jerárquico:

df['a','c']

Nope. Que falla así.

Entonces, ¿cómo puedo seleccionar todas las filas donde:

  1. grupo1 == ‘a’
  2. grupo1 == ‘a’ & grupo2 == ‘c’
  3. grupo2 == ‘c’
  4. grupo 1 en [‘a’,’b’,’c’]
InformationsquelleAutor JD Long | 2012-08-13

3 Comentarios

  1. 49

    Trate de usar xs ser muy precisa:

    In [5]: df.xs('a', level=0)
    Out[5]: 
            value1  value2
    group2                
    c          1.1     7.1
    c          2.0     8.0
    d          3.0     9.0
    
    In [6]: df.xs('c', level='group2')
    Out[6]: 
            value1  value2
    group1                
    a          1.1     7.1
    a          2.0     8.0
    • Yo sabía que tenía que ser una más simple expresión. Gracias!
    • ¿qué acerca de group1 in ['a','b','c']
    • df[[grupo 1 en [‘a’, ‘b’, ‘c’] para el grupo1, grupo2 en el df.índice]]
    • que absolutamente funciona, pero no tengo idea de por qué. Puede usted explicar cómo [group1 in ['a', 'b', 'c'] for group1, group2 in df.index] funciona?
    • df.el índice se comporta como una tupla de la lista aquí. Así que iterar a través de las tuplas, descartando el grupo 2 (de asignar el primer elemento de cada tupla a «grupo 1» y el segundo a «grupo2», pero sólo el uso de «grupo1») y la comprobación de si el primer elemento de la tupla está en la lista [‘a’, ‘b’, ‘c’]. Esto crea un valor booleano de la máscara que se utiliza para el subconjunto.
    • Sospecho que a pesar de que la np.in1d(df.índice.etiquetas[0], [label_of_a,label_of_b,label_of_c]) será mucho más rápido y hace el mismo trabajo. Por favor me corrija si estoy equivocado.
    • np.in1d(df.índice.etiquetas[0], match([‘a’,’b’, ‘c’], df.índice.los niveles de[0])) parece hacer el truco de la forma en que entendía el MultiIndex código (las etiquetas se crean utilizando Categórica.from_arrays(valores) )
    • La técnica utilizada es booleano de indexación (ver también pandas.pydata.org/pandas-docs/stable/…). Arthur explicó cómo he creado el booleano índice, como lo ha indicado que hay otras formas de crear el Verdadero/Falso iterable. Pero al final todo se reduce a booleanos de indexación por parte #4 de su pregunta. Tenga en cuenta que Arthur abrió un problema en GitHub con una solicitud para simplificar este caso de uso (ver github.com/pydata/pandas/issues/1766).
    • Gracias a todos por tanto de explicar las cosas para mí y también para pasar el tiempo y la energía para hacer que los Pandas mejor.

  2. 9

    Una sintaxis como la siguiente obra:

    df.ix['a']
    df.ix['a'].ix['c']

    desde group1 y group2 son los índices. Por favor, perdona mi intento anterior!

    Para llegar al segundo índice único, creo que tienes que cambiar de índices:

    df.swaplevel(0,1).ix['c']

    Pero estoy seguro de que Wes se me corrija si estoy equivocado.

    • Que no funciona, porque 'group1' == 'a' es simplemente Falso, así que esto es sólo df.ix[False], o df.ix[0]. Como resultado, df.ix['group1'=='a'] será exactamente el mismo que df.ix['group2'=='d'].
    • Ah, ya veo. Nunca la mente.
    • Estamos cerca… pero algo no es del todo correcto. Cuando hago df.ix['group2'=='d'] sólo obtener un registro de la espalda… y es el primer registro, no uno donde grupo2==d.
    • es el primer registro porque «grupo2′ == ‘d’ es Falso, que es 0. Cada una de estas comparaciones se evalúa antes, y así es .ix[0], .ix[0,0], y .ix[0] de nuevo.
    • ok.. que tiene sentido. gracias DSM
    • así df.ix['a'].ix['d'] funciona… así que cubre los dos primeros ejemplos. Pero, ¿cómo iba yo a seleccionar sólo en la segunda parte del índice?
    • OK, he modificado a algo que funciona.
    • Me gusta la swaplevel… pero no estoy seguro de cómo usarlo para los índices con más de 2 niveles. Naturalmente mi aplicación a la vida real utiliza una profunda índice 🙁
    • Bueno, mientras se conocía la profundidad del índice, siempre se puede swaplevel(0,x), pero supongo que usted no sabe necesariamente el índice del índice!
    • swaplevel también toma nombres como parámetro, de modo que si conoce al menos el nombre de la misma, que podría ayudar.

  3. 1

    En Python 0.19.0 hay un nuevo enfoque sugerido, lo que se explica aquíUno. Creo que el ejemplo más claro se da es la siguiente, en la que se rebanada de cuatro niveles de indexación. Esto es cómo el dataframe está hecho:

    In [46]: def mklbl(prefix,n):
    ....:     return ["%s%s" % (prefix,i)  for i in range(n)]
    ....: 
    In [47]: miindex = pd.MultiIndex.from_product([mklbl('A',4),
    ....:                                       mklbl('B',2),
    ....:                                       mklbl('C',4),
    ....:                                       mklbl('D',2)])
    ....: 
    In [48]: micolumns = pd.MultiIndex.from_tuples([('a','foo'),('a','bar'),
    ....:                                        ('b','foo'),('b','bah')],
    ....:                                       names=['lvl0', 'lvl1'])
    ....: 
    In [49]: dfmi = pd.DataFrame(np.arange(len(miindex)*len(micolumns)).reshape((len(miindex),len(micolumns))),
    ....:                     index=miindex,
    ....:                     columns=micolumns).sort_index().sort_index(axis=1)
    ....: 
    In [50]: dfmi
    Out[50]: 
    lvl0           a         b     
    lvl1         bar  foo  bah  foo
    A0 B0 C0 D0    1    0    3    2
    D1    5    4    7    6
    C1 D0    9    8   11   10
    D1   13   12   15   14
    C2 D0   17   16   19   18
    D1   21   20   23   22
    C3 D0   25   24   27   26
    ...          ...  ...  ...  ...
    A3 B1 C0 D1  229  228  231  230
    C1 D0  233  232  235  234
    D1  237  236  239  238
    C2 D0  241  240  243  242
    D1  245  244  247  246
    C3 D0  249  248  251  250
    D1  253  252  255  254

    Y esta es la forma en que selecciona las diferentes filas:

    In [51]: dfmi.loc[(slice('A1','A3'),slice(None), ['C1','C3']),:]
    Out[51]: 
    lvl0           a         b     
    lvl1         bar  foo  bah  foo
    A1 B0 C1 D0   73   72   75   74
    D1   77   76   79   78
    C3 D0   89   88   91   90
    D1   93   92   95   94
    B1 C1 D0  105  104  107  106
    D1  109  108  111  110
    C3 D0  121  120  123  122
    ...          ...  ...  ...  ...
    A3 B0 C1 D1  205  204  207  206
    C3 D0  217  216  219  218
    D1  221  220  223  222
    B1 C1 D0  233  232  235  234
    D1  237  236  239  238
    C3 D0  249  248  251  250
    D1  253  252  255  254

    Así que simplemente, en df.loc[(indices),:], debe especificar los índices que desea seleccionar en cada nivel, desde el nivel más alto al más bajo. Si usted no desea hacer una selección de los de más bajo nivel(s) de los índices, se puede omitir la especificación de los mismos. Si usted no quiere hacer una división entre el resto de los niveles especificados, agregar slice(None). Ambos casos se muestra en el ejemplo, en el nivel D se omite y el nivel B se especifica entre a y C.

    • gracias por la adición de la solución actualizada. muy apreciado.

Dejar respuesta

Please enter your comment!
Please enter your name here