J'essaie de trier un dataframe pandas par bloc sans changer l'ordre dans les blocs.
Le dataframe contient des messages de forum, des horodatages et des noms de threads. J'ai déjà trié le dataframe de sorte que tous les messages appartenant au même fil soient dans le bon ordre en utilisant df.sort_values (['thread', 'timestamp'], inplace = True)
. Je veux maintenant trier les blocs de données appartenant au même thread en fonction de l'horodatage du premier message de chaque bloc. L'ordre dans les blocs doit rester inchangé.
Ce que j'ai actuellement:
post timestamp thread 6 some 2004/09/01 09:32 game 3 text 2007/04/22 14:11 question 4 this 2007/04/24 11:03 question 5 be 2007/05/03 17:55 question 2 some 2008/07/10 15:23 nice 0 this 2009/10/30 16:51 hello 1 be 2009/11/02 17:11 hello 7 text 2010/01/01 03:32 wheather
Ce que je veux:
post timestamp thread 0 this 2009/10/30 16:51 hello 1 be 2009/11/02 17:11 hello 2 some 2008/07/10 15:23 nice 3 text 2007/04/22 14:11 question 4 this 2007/04/24 11:03 question 5 be 2007/05/03 17:55 question 6 some 2004/09/01 09:32 game 7 text 2010/01/01 03:32 wheather
4 Réponses :
argsort
. groupby
, en profitant du fait que groupby
trie les groupes par clé, mais ne change pas l'ordre dans les groupes. concatre
les groupes résultants dans un ordre trié. idx = df['thread'].map(df.groupby('thread')['timestamp'].first().argsort()) idx 0 3 1 3 2 2 3 1 4 1 5 1 6 0 7 4 Name: thread, dtype: int64 pd.concat([g for _, g in df.groupby(idx)]) post timestamp thread 6 some 2004/09/01 09:32 game 3 text 2007/04/22 14:11 question 4 this 2007/04/24 11:03 question 5 is 2007/05/03 17:55 question 2 some 2008/07/10 15:23 nice 0 this 2009/10/30 16:51 hello 1 is 2009/11/02 17:11 hello 7 text 2010/01/01 03:32 wheather
une façon est de créer une colonne temporaire par exemple nommée 'first_ts' avec groupby
sur 'thread' et transform
pour obtenir le min
(donc la première date) sur la colonne 'timestamp' pour chaque fil. Vous pouvez maintenant trier les valeurs
par cette colonne et supprimer
la colonne temporaire.
df = df.reindex(df.groupby('thread').timestamp.transform(min) .sort_values().index)
et vous obtenez comme prévu
print(df) post timestamp thread 6 some 2004-09-01 09:32:00 game 3 text 2007-04-22 14:11:00 question 4 this 2007-04-24 11:03:00 question 5 be 2007-05-03 17:55:00 question 2 some 2008-07-10 15:23:00 nice 0 this 2009-10-30 16:51:00 hello 1 be 2009-11-02 17:11:00 hello 7 text 2010-01-01 03:32:00 wheather
ou si vous ne souhaitez pas créer la colonne, vous pouvez également utiliser reindex
avec l'index de la valeur triée de groupby
telle que:
# you might need to convert timestamp to datetime df.timestamp = pd.to_datetime(df.timestamp) #create the column df['first_ts'] = df.groupby('thread').timestamp.transform(min) #sort and drop df = df.sort_values(['first_ts']).drop('first_ts',axis=1)
Essayons d'abord de thread groupby
puis récupérons le premier enregistrement, trions ces enregistrements par heure, puis utilisons l'attribut groups
de DataFrameGroupBy pour obtenir l'ordre actuel de l'index dans chaque groupe. Enfin, utilisez pd.concat
et la compréhension de liste pour reconstruire le dataframe dans l'ordre trié des premiers enregistrements.
post timestamp thread 6 some 2004-09-01 09:32:00 game 3 text 2007-04-22 14:11:00 question 4 this 2007-04-24 11:03:00 question 5 be 2007-05-03 17:55:00 question 2 some 2008-07-10 15:23:00 nice 0 this 2009-10-30 16:51:00 hello 1 be 2009-11-02 17:11:00 hello 7 text 2010-01-01 03:32:00 wheather
Sortie:
g = df.groupby('thread') s = g.head(1).sort_values('timestamp')['thread'] dg = g.groups pd.concat([df.reindex(dg[i[1]]) for i in s.iteritems()])
En utilisant sort_values
avec drop_duplicates
obtenir le min, puis nous utilisons Categorical
cate=df.sort_values('timestamp').drop_duplicates('thread') df.thread=pd.Categorical(df.thread,ordered=True,categories=cate.thread.tolist()) df=df.sort_values('thread') df post timestamp thread 6 some 2004-09-01 09:32:00 game 3 text 2007-04-22 14:11:00 question 4 this 2007-04-24 11:03:00 question 5 be 2007-05-03 17:55:00 question 2 some 2008-07-10 15:23:00 nice 0 this 2009-10-30 16:51:00 hello 1 be 2009-11-02 17:11:00 hello 7 text 2010-01-01 03:32:00 wheather