#python #pandas #sorting #time-series #pandas-groupby
Вопрос:
После того, как я добавлю 4 разных кадра данных в:
list_1 = [ ]
У меня есть следующие данные, хранящиеся в list_1:
| date | 16/17 |
| -------- | ------|
| 2016-12-29 | 50 |
| 2016-12-30 | 52 |
| 2017-01-01 | 53 |
| 2017-01-02 | 51 |
[4 rows x 1 columns],
16/17
| date | 17/18 |
| -------- | ------|
| 2017-12-29 | 60 |
| 2017-12-31 | 62 |
| 2018-01-01 | 64 |
| 2018-01-03 | 65 |
[4 rows x 1 columns],
17/18
| date | 18/19 |
| -------- | ------|
| 2018-12-30 | 54 |
| 2018-12-31 | 53 |
| 2019-01-02 | 52 |
| 2019-01-03 | 51 |
[4 rows x 1 columns],
18/19
| date | 19/20 |
| -------- | ------|
| 2019-12-29 | 62 |
| 2019-12-30 | 63 |
| 2020-01-01 | 62 |
| 2020-01-02 | 60 |
[4 rows x 1 columns],
19/20
Для изменения формата даты на месяц/день я использую следующий код:
pd.to_datetime(df['date']).dt.strftime('%m/%d')
Но проблема в том, что я хочу упорядочить данные по месяцам/дням таким образом:
| date | 16/17 | 17/18 | 18/19 | 19/20 |
| -------- | ------| ------| ------| ------|
| 12/29 | 50 | 60 | NaN | 62 |
| 12/30 | 52 | NaN | 54 | 63 |
| 12/31 | NaN | 62 | 53 | NaN |
| 01/01 | 53 | 64 | NaN | 62 |
| 01/02 | 51 | NaN | 52 | 60 |
| 01/03 | NaN | 65 | 51 | NaN |
Я попробовал следующее:
df = pd.concat(list_1,axis=1)
тоже:
df = pd.concat(list_1)
df.reset_index(inplace=True)
df = df.groupby(['date']).first()
тоже:
df = pd.concat(list_1)
df.reset_index(inplace=True)
df = df.groupby(['date'] sort=False).first()
но все равно не удается достичь желаемого результата.
Комментарии:
1. Вы пытаетесь
pivot
создать свой фрейм данных?2. Я не уверен в повороте, Люк. Я просто хочу сравнить данные за разные годы по месяцам/дням (следовательно, формат месяц/день), сохраняя при этом порядок дат (начиная с 12/29 и заканчивая 01/03, как в примере).
Ответ №1:
Вы можете использовать sort=False
в groupby
и создать новый столбец для вычитания по первому значению DatetimeIndex
и использовать его для сортировки:
def f(x):
x.index = pd.to_datetime(x.index)
return x.assign(new = x.index - x.index.min())
L = [x.pipe(f) for x in list_1]
df = pd.concat(L, axis=0).sort_values('new', kind='mergesort')
df = df.groupby(df.index.strftime('%m/%d'), sort=False).first().drop('new', axis=1)
print (df)
16/17 17/18 18/19 19/20
date
12/29 50.0 60.0 NaN 62.0
12/30 52.0 NaN 54.0 63.0
12/31 NaN 62.0 53.0 NaN
01/01 53.0 64.0 NaN 62.0
01/02 51.0 NaN 52.0 60.0
01/03 NaN 65.0 51.0 NaN
Комментарии:
1. Спасибо тебе, израэль, за предложение! Проблема, когда я пытаюсь это сделать, заключается в том, что новый кадр данных начинается с 01/01, а не с 12/29, как хотелось бы. Есть ли какой-либо способ сохранить порядок дат (чтобы начать с 12/29 и закончить 01/03, как в примере для желаемого результата)?
2. Я тоже пробовал это сделать. Он сохраняет порядок, но группирует данные по первому столбцу (16/17), а строки, такие как 12/31 (где значение 16/17 равно NaN), перемещаются вниз и не остаются на месте. @израэль
3. @kobo — Ответ был отредактирован.
4. Это работает идеально, спасибо! И какие-нибудь советы, если у меня будет больше месяцев? Например, если данные начинаются с 09/30 и заканчиваются 03/30, соблюдая ту же логику. @израэль