Pandas: разгруппировать и расплавить записи с пробелами - PullRequest
2 голосов
/ 27 января 2020

Я новичок в Python & pandas, не могли бы вы посоветовать мне, если возможно разгруппировать и развернуть такой фрейм данных?

Группы в исходных данных находятся в единственном столбце, отмеченном пробелами префиксов и выглядит как

import pandas as pd
import numpy
df = pd.DataFrame([
    ['Costs', numpy.nan, numpy.nan, numpy.nan],
    ['  Vehicles', numpy.nan, numpy.nan, numpy.nan],
    ['    Cars', numpy.nan, numpy.nan, numpy.nan],
    ['      BMW', 1000, 1100, 1010],
    ['      Toyota', 1203, 1302, 1322],
    ['    Cars - Total', 2203, 2402, 2332],
    ['    Trucks', numpy.nan, numpy.nan, numpy.nan],
    ['      Volvo', 5000, 5001, 5010],
    ['      MAN', 5500, 5055, 5066],
    ['    Trucks - Total', 10500, 10056, 10076],
    ['  Vehicles - Total', 12703, 12458, 12408],
    ['  Crew', numpy.nan, numpy.nan, numpy.nan],
    ['    Gomez Addams', 10000, 10000, 10000],
    ['    Morticia Addams', 10000, 10000, 10000],
    ['  Crew - Total', 20000, 20000, 20000],
    ['Costs - Total', 32703, 32458, 32408],
    ],    
    columns=['Level', 'Q1_2019', 'Q2_2019', 'Q3_2019'])

Мне нужно преобразовать его в таблицу типа

Level, Sublevel1, Sublevel2, Sublevel3, Sublevel4, Date, Value
"Costs", "Vehicles", "Cars", "BMW", "Q1_2019", 1000
"Costs", "Crew", "Gomez Addams", , "Q1_2019", 10000

Пока я создал дополнительные столбцы "Sublevel", засыпал их регулярным выражением, а затем заполнил Подуровни пропускаются построчно, затем примените melt (). Можно ли сделать больше pythoni sh?

1 Ответ

0 голосов
/ 27 января 2020

Возможно, это более удачный способ сделать это, но идея состоит в том, чтобы отфильтровать группы с помощью Total, затем использовать обратную и заливку вперед.

Затем мы отбрасываем что-либо в группе с менее чем 1 появлением. и таять по уровням 1-2

df['sub_level'] = df['Level'].str.count('\s+')

df.loc[df["Level"].str.contains("Total"), "group"] = (
    df["Level"].str.strip().str.replace("- Total", "")
)

df['group'] = df['group'].bfill().ffill()

df = df[df.groupby('group')['group'].transform('count') > 1].dropna(how='any')

final_df = pd.melt(
    df.loc[df["sub_level"].isin([1, 2])].drop("sub_level", axis=1), id_vars=["Level",'group']
)

final_df.columns = ['Level','Type','Date','Value']

print(final_df)

                  Level     Type     Date    Value
0                   BMW    Cars   Q1_2019   1000.0
1                Toyota    Cars   Q1_2019   1203.0
2                 Volvo  Trucks   Q1_2019   5000.0
3                   MAN  Trucks   Q1_2019   5500.0
4          Gomez Addams    Crew   Q1_2019  10000.0
5       Morticia Addams    Crew   Q1_2019  10000.0
6                   BMW    Cars   Q2_2019   1100.0
7                Toyota    Cars   Q2_2019   1302.0
8                 Volvo  Trucks   Q2_2019   5001.0
9                   MAN  Trucks   Q2_2019   5055.0
10         Gomez Addams    Crew   Q2_2019  10000.0
11      Morticia Addams    Crew   Q2_2019  10000.0
12                  BMW    Cars   Q3_2019   1010.0
13               Toyota    Cars   Q3_2019   1322.0
14                Volvo  Trucks   Q3_2019   5010.0
15                  MAN  Trucks   Q3_2019   5066.0
16         Gomez Addams    Crew   Q3_2019  10000.0
17      Morticia Addams    Crew   Q3_2019  10000.0
...