2016-12-06 1 views
1

J'essaie d'utiliser un masque pour faire une sélection de mon objet groupby, mais j'obtiens une erreur que je ne peux pas résoudre.Pandas: utiliser un timeseries comme masque de sélection

premier groupe I par groupId

df_grouped = df.groupby('groupid') 

Je calcule la STD, min et max de chaque groupe à utiliser dans mes masques de sélection. Ensuite, je crée deux masques sur des paramètres différents. Puis, je crée deux masques sur différents paramètres.

s1 = df_grouped_std['distance']<0.05 
s2 = (df_grouped_max.speed- df_grouped_min.speed) < 10 

Enfin, je combine les masques.

sTot = s1&s2 

Cela donne l'erreur/stacktrace suivante:

Traceback (most recent call last): 

    File "<ipython-input-198-b0df7aa8bb76>", line 1, in <module> 
    selection = df_grouped[sTot.values] 

    File "C:\Anaconda\lib\site-packages\pandas\core\groupby.py", line 3155, in __getitem__ 
    % str(bad_keys)[1:-1]) 

KeyError: 'Columns not found: False, True' 

Ensuite, je voudrais utiliser le masque pour sélectionner.

selection = df_grouped[sTot] 

Je vois que s1, s2 et Stot sont des séries chronologiques et peut-être c'est pourquoi je ne peux pas les utiliser pour sélectionner, mais je ne peux pas comprendre pourquoi ce serait. Qu'est-ce que j'oublie ici?

Exemple de données:

print(s1.head()) 
print(s2.head()) 
print(sTot.head()) 

groupid 
941   True 
942   True 
1721   True 
1722   True 
2201   True 
Name: distance, dtype: bool 

groupid 
941   True 
942   True 
1721   False 
1722   True 
2201   False 
Name: speed, dtype: bool 

groupid 
941   True 
942   True 
1721   False 
1722   True 
2201   False 
dtype: bool 
+0

pouvez-vous sortir la tête de s1 et s2? Faites 'print (s1.head())' et 'print (s2.head())' et copiez et collez la sortie ici –

Répondre

1

Je pense que vous pouvez utiliser filter:

print (df.groupby('groupID') 
     .filter(lambda x: (x.distance.std() < 0.05) & 
          ((x.speed.max()- x.speed.min()) < 10))) 

Sample (changé 0.05-1):

df = pd.DataFrame({'groupID':[1,1,3,3], 
        'speed':[4,5,6,1], 
        'distance':[1,2,3,1]}) 

print (df) 
    distance groupID speed 
0   1  1  4 
1   2  1  5 
2   3  3  6 
3   1  3  1 

print (df.groupby('groupID') 
     .filter(lambda x: (x.distance.std() < 1) & 
          ((x.speed.max()- x.speed.min()) < 10))) 

    distance groupID speed 
0   1  1  4 
1   2  1  5 
+0

Je vais essayer ceci. – marqram

+0

Fonctionne comme un charme et est beaucoup plus propre que l'approche que j'ai compris. – marqram

1

Que voulez-vous le résultat ? Voulez-vous toutes les entrées dans quels groupes (où les conditions sont valides), ou simplement les informations agrégées pour les groupes?

Je pense que la solution de @jezrael est bonne si vous voulez toutes les entrées. Btw, vous pouvez trouver .get_group() utile.

Vous pouvez effectuer les opérations suivantes:

for k, v in sTot.iteritems(): 
    if v == True: 
     print df_grouped.get_group(k) 
+0

Merci, ça marche aussi. Cependant ce que je veux, c'est toutes les entrées et comme vous l'avez mentionné, la solution @jezraels est géniale pour ça. – marqram

0

Je compris une autre solution. Une fois le code dans la question:

df_grouped = df.groupby('groupid') 

df_grouped_std = df_grouped.std() 
df_grouped_min = df_grouped.min() 
df_grouped_max = df_grouped.max() 

s1 = df_grouped_std['distance']<0.05 
s2 = (df_grouped_max.speed- df_grouped_min.speed) < 10 

J'applique toutes les sélections sur le df_grouped_std

sTot2 = df_grouped_std[s1][s2][s3][s4][s5] 

Puis-je utiliser les valeurs d'index des colonnes sélectionnées, et sélectionnez ceux de l'original (dissociées) trame de données. Enfin, je regroupe de nouveau, car j'ai besoin des groupes. Bien que cela fonctionne, je préfère l'approche de @jezraels car je pense que c'est beaucoup plus propre.