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