Как сортировать имена столбцов, которые представляют собой даты в формате строки, по порядку даты и времени

#python #pandas #sorting

#python #pandas #сортировка

Вопрос:

У меня есть фрейм данных, в котором есть столбец даты и времени с именем Месяц и два других столбца:

 data = [['Canada',10, '2020-09-01'], ['Canada',20, '2020-10-01'], ['Canada',30, '2020-12-01'], ['Canada',40, '2021-01-01'],
            ['Europe',30, '2020-09-01'], ['Europe',20, '2020-10-01'], ['Europe',10, '2020-12-01'], ['Europe',40, '2021-01-01'],
            ['US',40, '2020-09-01'], ['US',10, '2020-10-01'], ['US',20, '2020-12-01'], ['US',30, '2021-01-01']]

df = pd.DataFrame(data,columns=['Region','sales', 'Month'])
  

Затем я преобразую столбец «Месяц» в строку с определенным форматом:

 df['Month'] = df['Month'].dt.strftime('%b-%Y')
  

Теперь я поворачиваю фрейм данных и экспортирую в Excel:

 df['Month'] = pd.pivot_table(df['Month'], values = 'sales', index=["Region"], columns = "Month").reset_index() 

df.to_excel(writer, sheet_name='sales', index=False, startrow=4, header=False)
  

Поскольку столбец «Месяц» представляет собой строку, когда я записываю фрейм данных в Excel, даты сортируются в алфавитном порядке. Я хочу, чтобы даты сортировались по значениям даты и времени.

Я попытался преобразовать столбец «Месяц» в datetime перед поворотом, но в этом случае я не получаю даты в правильном формате после экспорта в Excel:

 df['Month'] = pd.to_datetime(df['Month'], format='%b-%Y')
  

Я даже пытался использовать формат ExcelWriter, но, похоже, это не работает.

Вывод, который я получаю: Вывод, который я получаю:

Желаемый результат: Желаемый результат

 df['Month'] = pd.to_datetime(df['Month'])
df = pd.pivot_table(df, values = 'sales', index=["Region"], columns = "Month").reset_index()
df = df.append(pd.Series(df.sum(),name='System'))
    .assign(Total=df.sum(1))

# extract the datetime component of the multilevel column names
dates = [v for v in df.columns[1:]]

# reformat dates to the desired string format
dates_str = [v.strftime('%b-%Y') for v in dates]

# create a dict
updates = dict(zip(dates, dates_str))

# rename the columns, which will stay in the current, correct order
df = df.rename(columns=updates, inplace=True)

df.to_excel(writer, sheet_name='sales', index=False, startrow=4, header=False)
  

Ответ №1:

  • Предполагается 'Month' , что даты столбцов являются datetime dtype from pd.to_datetime .
    • df.Month = pd.to_datetime(df.Month) , перед поворотом.
  • Разверните фрейм данных перед преобразованием 'Months' в строку, а затем переименуйте столбцы.
    • .rename используется, потому что присвоение имен столбцов путем нарезки списка и присваивания приводит к TypeError (например df.columns[:1] = 3 )
 import pandas as pd

# sample dataframe
data = {'Region': ['Canada', 'Canada', 'Canada', 'Canada', 'Europe', 'Europe', 'Europe', 'Europe', 'US', 'US', 'US', 'US'],
        'sales': [10, 20, 30, 40, 30, 20, 10, 40, 40, 10, 20, 30],
        'Month': [pd.Timestamp('2020-09-01 00:00:00'), pd.Timestamp('2020-10-01 00:00:00'), pd.Timestamp('2020-12-01 00:00:00'), pd.Timestamp('2021-01-01 00:00:00'), pd.Timestamp('2020-09-01 00:00:00'), pd.Timestamp('2020-10-01 00:00:00'), pd.Timestamp('2020-12-01 00:00:00'), pd.Timestamp('2021-01-01 00:00:00'), pd.Timestamp('2020-09-01 00:00:00'), pd.Timestamp('2020-10-01 00:00:00'), pd.Timestamp('2020-12-01 00:00:00'), pd.Timestamp('2021-01-01 00:00:00')]}
df = pd.DataFrame(data)

# pivot the dataframe before changing Month to a string
dfp = pd.pivot_table(df, values='sales', index=["Region"], columns="Month").reset_index() 

# add Total column
dfp = dfp.append(pd.Series(dfp.sum(), name='System')).assign(Total=dfp.sum(1))

# extract the datetime column names
dates = [v for v in dfp.columns[1:-1]]

# reformat dates to the desired string format
dates_str = [v.strftime('%b-%Y') for v in dates]

# create a dict
updates = dict(zip(dates, dates_str))

# rename the columns, which will stay in the current, correct order
dfp.rename(columns=updates, inplace=True)

# display(dfp)
Month           Region  Sep-2020  Oct-2020  Dec-2020  Jan-2021  Total
0               Canada        10        20        30        40  100.0
1               Europe        30        20        10        40  100.0
2                   US        40        10        20        30  100.0
System  CanadaEuropeUS        80        50        60       110    NaN

# save to Excel, without the Total column; remove .iloc[:, :-1] to keep the Total column
dfp.iloc[:, :-1].to_excel('test.xlsx', sheet_name='sales', index=False, header=True)
  

Просмотр Excel

введите описание изображения здесь

Комментарии:

1. Мой плохой! Я должен был упомянуть о столбцах итогов. Теперь это работает отлично. Спасибо за помощь !! 🙂