Solution
设置索引...
使用巧妙的专栏groupby
...
另一个巧妙的功能apply
...
d1 = df.set_index(['id', 'name', 'model_#', 'ms'])
def melt_(df):
id_vars = df.index.names
return df.reset_index().melt(id_vars=id_vars).set_index(id_vars)
d2 = d1.groupby(d1.columns.str.extract('(\D+)', expand=False), axis=1).apply(melt_)
d2.columns = d2.columns.swaplevel(0, 1).map('_'.join)
d2.reset_index()
id name model_# ms variable_bp value_bp variable_cd value_cd variable_rq value_rq variable_sa value_sa variable_sf value_sf
0 1 John 23984 1 bp1 23 cd1 234 rq1 252 sa1 25 sf1 124
1 2 John 23984 2 bp1 234 cd1 234 rq1 262 sa1 62 sf1 242
2 1 John 23984 1 bp2 252 cd2 62 rq2 234 sa2 234 sf2 194
3 2 John 23984 2 bp2 622 cd2 262 rq2 262 sa2 26 sf2 622
过度功能化
e = lambda d, n: dict(zip(n, d.dtypes))
i = lambda d, n: pd.DataFrame(d.values, d.index, n).astype(e(d, n))
h = lambda d: i(d, d.columns.map(fmt)).reset_index()
m = lambda d: d.reset_index().melt(cols).set_index(cols)
fmt = '{0[1]}_{0[0]}'.format
cols = ['id', 'name', 'model_#', 'ms']
d1 = df.set_index(cols)
g = d1.columns.str.extract('(\D+)', expand=False)
d1.groupby(g, axis=1).apply(m).pipe(h)
id name model_# ms variable_bp value_bp variable_cd value_cd variable_rq value_rq variable_sa value_sa variable_sf value_sf
0 1 John 23984 1 bp1 23 cd1 234 rq1 252 sa1 25 sf1 124
1 2 John 23984 2 bp1 234 cd1 234 rq1 262 sa1 62 sf1 242
2 1 John 23984 1 bp2 252 cd2 62 rq2 234 sa2 234 sf2 194
3 2 John 23984 2 bp2 622 cd2 262 rq2 262 sa2 26 sf2 622
旧答案
这一点也不漂亮,我什至不确定这是否是您想要的。
d1 = df.set_index(['id', 'name', 'model_#', 'ms'])
cidx = pd.MultiIndex.from_tuples(
d1.columns.to_series().str.extract('(\D+)(\d+)', expand=False).values.tolist(),
names=[None, 'variable']
)
d1.columns = cidx
d2 = d1.sort_index(axis=1).stack()
variables = pd.DataFrame(
(d2.columns + d2.index.get_level_values('variable')[:, None]).tolist(),
d2.index, d2.columns
)
d3 = pd.concat(
[variables, d2], axis=1, keys=['variable', 'value']
).reset_index('variable', drop=True).sort_index(axis=1, level=1, sort_remaining=False)
d3.columns = d3.columns.map('_'.join)
d3.reset_index()
id name model_# ms variable_bp value_bp variable_cd value_cd variable_rq value_rq variable_sa value_sa variable_sf value_sf
0 1 John 23984 1 bp1 23 cd1 234 rq1 252 sa1 25 sf1 124
1 1 John 23984 1 bp2 252 cd2 62 rq2 234 sa2 234 sf2 194
2 2 John 23984 2 bp1 234 cd1 234 rq1 262 sa1 62 sf1 242
3 2 John 23984 2 bp2 622 cd2 262 rq2 262 sa2 26 sf2 622