Python Pandas: Как преобразовать мою таблицу из длинного формата в широкоформатный (пример c указан ниже)? - PullRequest
0 голосов
/ 25 февраля 2020

В значительной степени название. Я прилагаю электронную таблицу здесь . Мне нужно преобразовать лист «Вход» в лист «Выход». Я знаю о Pandas wide_to_long . Но я не смог использовать его, чтобы получить желаемый результат, строки разбиты на выходных данных.

import pandas as pd
df=pd.read_excel('../../Downloads/test.xlsx',sheet_name='Input', header=0)
newdf=pd.wide_to_long(df, [str(i) for i in range(2022,2028)], 'Hotel Name', 'value', sep='', suffix='.+')\
  .reset_index()\
  .sort_values('Hotel Name')\
  .drop('value', axis=1)
newdf

Выход составляет

enter image description here

Ответы [ 2 ]

3 голосов
/ 25 февраля 2020

Вы можете создать Index / MultiIndex по всем столбцам без лет в именах столбцов на DataFrame.set_index, затем MultiIndex in columns на Series.str.split, поэтому возможно изменение формы по DataFrame.stack, последний установить имена индексов и преобразовать MultiIndex in index в столбцы по DataFrame.reset_index, затем преобразовать Val столбец в упорядоченный categorical по порядку значений в столбцах , поэтому вы можете добавить DataFrame.sort_values для правильного порядка:

df = pd.read_excel('test.xlsx')

df = df.set_index(['Hotel Name'])
df.columns = df.columns.str.split(n=1, expand=True)

cats = df.columns.get_level_values(1).unique()
print (cats)
Index(['Revenue', 'Cost', 'Profit', 'Cum. Profit'], dtype='object')

df = (df.stack()
        .rename_axis(('Hotel Name','Val'))
        .reset_index()
        .assign(Val = lambda x: pd.Categorical(x.Val, ordered=True, categories=cats))
        .sort_values(['Hotel Name','Val'])
        )
print (df.head())
   Hotel Name          Val  2022     2023      2024    2025    2026    2027  \
3     Hotel A      Revenue     0  35478.0   59130.0   94608  118260  141912   
0     Hotel A         Cost     0      0.0       0.0       0       0       0   
2     Hotel A       Profit     0  35478.0   59130.0   94608  118260  141912   
1     Hotel A  Cum. Profit     0  35478.0   94608.0  189216  307476  449388   
15   Hotel A1      Revenue     0  93622.5  156037.5  249660  312075  374490   

        2028  
3   177390.0  
0        0.0  
2   177390.0  
1   626778.0  
15  468112.5  

В вашем решении необходимо изменить range на 2029 для включаемого года 2028:

df = pd.read_excel('test.xlsx')


df = (pd.wide_to_long(df, 
                      stubnames=[str(i) for i in range(2022,2029)],
                      i='Hotel Name', 
                      j='value', 
                      sep='',
                      suffix='.+')
                    .reset_index()
                   .sort_values('Hotel Name')
                   .drop('value', axis=1))
print (df.head())
   Hotel Name  2022     2023      2024    2025    2026    2027      2028
0     Hotel A     0  35478.0   59130.0   94608  118260  141912  177390.0
5     Hotel A     0      0.0       0.0       0       0       0       0.0
10    Hotel A     0  35478.0   59130.0   94608  118260  141912  177390.0
15    Hotel A     0  35478.0   94608.0  189216  307476  449388  626778.0
3    Hotel A1     0  93622.5  156037.5  249660  312075  374490  468112.5
1 голос
/ 25 февраля 2020

Я бы скрыл название отеля в индексе, затем изменил бы столбцы на MultiIndex и суммировал:

df = pd.read_csv('test.csv', sep=';').set_index('Hotel Name')
df.columns = pd.MultiIndex.from_tuples([name.split(None, 1) for name in df.columns])
resul = df.stack()

, это напрямую дает:

                         2022     2023      2024    2025     2026     2027       2028
Hotel Name                                                                           
Hotel A    Cost             0        0         0       0        0        0          0
           Cum. Profit      0    35478     94608  189216   307476   449388     626778
           Profit           0    35478     59130   94608   118260   141912     177390
           Revenue          0    35478     59130   94608   118260   141912     177390
Hotel B    Cost        -25000        0         0       0        0        0          0
           Cum. Profit -25000   116036    351096  727192  1197312  1761456    2466636
           Profit      -25000   141036    235060  376096   470120   564144     705180
           Revenue          0   141036    235060  376096   470120   564144     705180
Hotel B2   Cost             0        0         0       0        0        0          0
           Cum. Profit      0  34711,5     92564  185128   300833   439679   613236,5
           Profit           0  34711,5   57852,5   92564   115705   138846   173557,5
           Revenue          0  34711,5   57852,5   92564   115705   138846   173557,5
Hotel A1   Cost        -25000        0         0       0        0        0          0
           Cum. Profit -25000  68622,5    224660  474320   786395  1160885  1628997,5
           Profit      -25000  93622,5  156037,5  249660   312075   374490   468112,5
           Revenue          0  93622,5  156037,5  249660   312075   374490   468112,5
Hotel C    Cost        -25000        0         0       0        0        0          0
           Cum. Profit -25000    54935    188160  401320   667770   987510    1387185
           Profit      -25000    79935    133225  213160   266450   319740     399675
           Revenue          0    79935    133225  213160   266450   319740     399675

Всегда можно отсортировать MultiIndex, используя пользовательский порядок, обрабатывая его как итеративный набор кортежей и используя стандартную функцию sorted с ключом:

resul = resul.loc[sorted(resul.index, key=lambda x:
                         (x[0], ['Revenue', 'Cost', 'Profit', 'Cum. Profit'].index(x[1])))]

, тогда он дает:

                         2022     2023      2024    2025     2026     2027       2028
Hotel Name                                                                           
Hotel A    Revenue          0    35478     59130   94608   118260   141912     177390
           Cost             0        0         0       0        0        0          0
           Profit           0    35478     59130   94608   118260   141912     177390
           Cum. Profit      0    35478     94608  189216   307476   449388     626778
Hotel A1   Revenue          0  93622,5  156037,5  249660   312075   374490   468112,5
           Cost        -25000        0         0       0        0        0          0
           Profit      -25000  93622,5  156037,5  249660   312075   374490   468112,5
           Cum. Profit -25000  68622,5    224660  474320   786395  1160885  1628997,5
Hotel B    Revenue          0   141036    235060  376096   470120   564144     705180
           Cost        -25000        0         0       0        0        0          0
           Profit      -25000   141036    235060  376096   470120   564144     705180
           Cum. Profit -25000   116036    351096  727192  1197312  1761456    2466636
Hotel B2   Revenue          0  34711,5   57852,5   92564   115705   138846   173557,5
           Cost             0        0         0       0        0        0          0
           Profit           0  34711,5   57852,5   92564   115705   138846   173557,5
           Cum. Profit      0  34711,5     92564  185128   300833   439679   613236,5
Hotel C    Revenue          0    79935    133225  213160   266450   319740     399675
           Cost        -25000        0         0       0        0        0          0
           Profit      -25000    79935    133225  213160   266450   319740     399675
           Cum. Profit -25000    54935    188160  401320   667770   987510    1387185
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...