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 melt
s.
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
我从 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 melt
s.
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