Melt/Stack/Reshape 多 header 数据帧

Melt/Stack/Reshape multi header dataframe

我从 excel 的数据中抓取了超过一行 header 的数据,其中一行有一些 nans:

df = pd.read_excel(文件, header=None)

0  nan  nan   jan20  jan20  feb20  feb20
1  ID   Name   GrpA   GrpB   GrpA   GrpB
2  1    One     1       2      3     4
3  2    Two     5       6      7     8

每个ID/Name对有4条数据需要关联。数据的目标是:

ID Name
1   One jan20 grpA 1
1   One jan20 grpB 2
1   One feb20 grpA 3
1   One feb20 grpB 4
2   Two jan20 grpA 5
2   Two jan20 grpB 6 
2   Two feb20 grpA 7
2   Two feb20 grpB 8

请注意,当它被抓取时,我不会在导入时指出 header 行,因为需要清理数据。我已经尝试了很多 pd.melt、pd.stack、pd.unstack 的各种组合,但没有成功。我已经尝试将前两行都设置为 header 行,但是我的键出现了问题。

似乎 .melt 可能是正确的答案,因为您可以选择 col_level 并可以命名结果列,但是当我尝试该路线时,我无法访问日期(第一行)似乎

df.melt(col_level=1, id_vars=['ID'])

对此有什么想法吗?

让我们正确加载文件

df = pd.read_excel('yourfile.xlsx', 
                   header=[0,1], 
                   index_col=[0,1])

然后你可以stack两次

out = df.stack().stack()

假设您的样本行都是数据框(而非电子表格)的 ,这应该可行。在这里,我创建了一个包含前 2 行的 2 级 MultiIndex,然后删除这些行,并执行 2 melts.

df.columns = pd.MultiIndex.from_arrays([df.iloc[0], df.iloc[1]])
df = df.iloc[2:] # trim off the first 2 rows after we put them in the MultiIndex

tmp = df.melt(id_vars=['ID', 'Name'], col_level=1)
tmp['x'] = df.melt(col_level=0).dropna()[0].to_numpy()
tmp = tmp.rename({1: 'y', 'value': 'z'}, axis=1).set_index(['ID', 'Name'])[['x', 'y', 'z']].sort_index()

输出:

>>> tmp
             x     y  z
ID Name                
1  One   jan20  GrpA  1
   One   jan20  GrpB  2
   One   feb20  GrpA  3
   One   feb20  GrpB  4
2  Two   jan20  GrpA  5
   Two   jan20  GrpB  6
   Two   feb20  GrpA  7
   Two   feb20  GrpB  8

粗略的方法可以是手动整形:

(df
 .set_index([0,1]).T
 .set_index([(float('nan'), float('nan')), ('ID', 'Name')])
 .rename_axis(index=[None,None], columns=[None,None])
 .stack()
 .stack()
)

输出:

jan20  GrpA  One  1    1
             Two  2    5
       GrpB  One  1    2
             Two  2    6
feb20  GrpA  One  1    3
             Two  2    7
       GrpB  One  1    4
             Two  2    8
dtype: object