Сортировка групп по первому значению без изменения порядка групп - PullRequest
0 голосов
/ 12 января 2019

Я пытаюсь отсортировать кадр данных pandas по блокам, не меняя порядок внутри блоков.

Dataframe содержит сообщения форума, временные метки и имена тем. Я уже отсортировал фрейм данных так, чтобы все записи, принадлежащие одной и той же ветке, были в правильном порядке, используя df.sort_values(['thread', 'timestamp'], inplace=True). Теперь я хочу отсортировать блоки данных, принадлежащие одному и тому же потоку, по отметке времени первого сообщения в каждом блоке. Порядок внутри блоков должен остаться без изменений.

Что у меня сейчас есть:

    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

Что я хочу:

    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

Есть ли способ сделать это?

Ответы [ 4 ]

0 голосов
/ 12 января 2019

Используя sort_values с drop_duplicates получите мин, затем мы используем 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
0 голосов
/ 12 января 2019

Один из способов - создать временный столбец, например, с именем «first_ts» с groupby в «потоке» и transform, чтобы получить min (поэтому первая дата) в столбце ' отметка времени для каждого потока. Теперь вы можете sort_values по этому столбцу и drop по временному столбцу.

# 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)

и вы получите, как ожидалось

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

или, если вы не хотите создавать столбец, вы также можете использовать reindex с индексом отсортированного значения groupby, например:

df = df.reindex(df.groupby('thread').timestamp.transform(min)
                  .sort_values().index)
0 голосов
/ 12 января 2019

Давайте попробуем сначала создать поток groupby, затем получить первую запись, отсортировать эти записи по времени, а затем использовать атрибут groups объекта DataFrameGroupBy, чтобы получить текущий порядок индекса в каждой группе. Наконец, используйте pd.concat и составьте список, чтобы перестроить фрейм данных в отсортированном порядке первых записей.

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()])

Выход:

   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
0 голосов
/ 12 января 2019
  1. Сначала получите первую «временную метку» каждой группы и argsort.
  2. Далее, используйте groupby, используя тот факт, что groupby сортирует группы по ключу, но не меняет порядок внутри групп.
  3. Наконец, concat результирующие группы в отсортированном порядке.

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...