J'essaie de filtrer une trame de données avec un multi-index similaire au suivant.

import numpy as np
import pandas as pd

data = pd.DataFrame(np.random.rand(8),
             index=[list('AABBCCDD'),
                    ['M', 'F']*4])
data['Count'] = [1,2,15,17,8,12,11,20]

Je voudrais sélectionner toutes les lignes où «Count» pour les deux «M» et «F» à l'intérieur d'un indice de niveau externe donné est supérieur à 10. Ainsi, pour l'exemple de trame de données, tous les «B» et « Les lignes D doivent être sélectionnées, mais aucune des autres lignes. La seule façon de penser à cela est de parcourir l'index externe, mais comme les boucles dans les pandas ne sont presque jamais la meilleure façon de faire les choses, je pense qu'il doit y avoir une meilleure solution.

4
elz 16 avril 2018 à 19:44

3 réponses

Meilleure réponse

groupby index puis nous utilisons filter + all pour obtenir le tout compte plus que le seuil

data.groupby(level=0).filter(lambda x : x['Count'].gt(10).all())
Out[495]: 
            0  Count
B M  0.232856     15
  F  0.536026     17
D M  0.375064     11
  F  0.795447     20

Inspiré par Jpp en utilisant isin

s=data.Count.min(level=0).gt(10)
data.loc[data.index.get_level_values(0).isin(s[s].index)]
6
YOBEN_S 16 avril 2018 à 17:03

Option 1

Empiler et désempiler avec un masque de niveau

data.unstack()[data.Count.gt(10).all(level=0)].stack()

            0  Count
B F  0.778883     17
  M  0.548054     15
D F  0.035073     20
  M  0.544838     11

Option 2

Utilisation de l'argument level pour pandas.Series.all et pd.DataFrame.reindex.
Cela évite le dépilage / empilage

mask = data.Count.gt(10).all(level=0)
data.reindex(mask.index[mask], level=0)

            0  Count
B M  0.548054     15
  F  0.778883     17
D M  0.544838     11
  F  0.035073     20
3
piRSquared 16 avril 2018 à 17:16

Vous pouvez utiliser groupby.transform pour une solution vectorisée:

res = data[data.groupby(data.index.get_level_values(0))['Count'].transform('min') > 10]

print(res)

#             0  Count
# B M  0.143501     15
#   F  0.964689     17
# D M  0.092362     11
#   F  0.981470     20
2
jpp 16 avril 2018 à 16:55