Sla*_*wek 6 python dataframe pandas data-science
我正在尝试将 datafarame 转换为所需的输出格式,并满足下面提到的要求。
提供的要求:
例子:
输入:
| 指数 | 模式 | 柱子 | Trh1 | Trh2 | Trh3 | Trh4 |
|---|---|---|---|---|---|---|
| 0 | 架构_1 | 列_1 | 南 | 0.01 | 南 | 南 |
| 1 | 架构_2 | 列_2 | 0.02 | 0.03 | 南 | 南 |
| 2 | 架构_3 | 列_3 | 0.03 | 0.04 | 0.05 | 南 |
| 3 | 架构_4 | 列_4 | 南 | 南 | 0.06 | 0.07 |
预期输出:
| 指数 | 模式 | 柱子 | Trh1 | Trh2 | Trh3 | Trh4 |
|---|---|---|---|---|---|---|
| 0 | 架构_1 | 列_1 | 南 | 0.01 | 南 | 南 |
| 1 | 架构_2 | 列_2 | 0.02 | 0.03 | 南 | 南 |
| 2 | 架构_3 | 列_3 | 0.03 | 0.04 | 南 | 南 |
| 3 | 架构_3 | 列_3 | 南 | 南 | 0.05 | 南 |
| 4 | 架构_4 | 列_4 | 南 | 南 | 0.06 | 南 |
| 5 | 架构_4 | 列_4 | 南 | 南 | 南 | 0.07 |
我探索了以下方法:根据条件 pandas 将行分成 2 行。但是,此方法仅适用于两列中没有 Nan 值的情况下分割行。
cols = ['Index', 'Schema', 'Column', 'Trh1', 'Trh2']
special = ['Trh1', 'Trh2']
others = list(df.columns.difference(cols))
out = (df
.assign(init=lambda d: d[others].isna().all(axis=1))
[cols+['init']+others]
.set_index(cols).stack().to_frame()
.assign(n=lambda d: d.groupby(level=range(df.index.ndim)).cumcount())
.set_index('n', append=True)[0]
.unstack(-2)
.reset_index()
)
out.loc[out['init'].isna(), special] = np.nan
out = out.drop(columns=['n', 'init'])
out = out.dropna(subset=special+others, how='all')
Run Code Online (Sandbox Code Playgroud)
输出:
Index Schema Column Trh1 Trh2 Trh3 Trh4
0 0 schema_1 col_1 NaN 0.01 NaN NaN
1 1 schema_2 col_2 0.02 0.03 NaN NaN
2 2 schema_3 col_3 0.03 0.04 NaN NaN
3 2 schema_3 col_3 NaN NaN 0.05 NaN
5 3 schema_4 col_4 NaN NaN 0.06 NaN
6 3 schema_4 col_4 NaN NaN NaN 0.07
Run Code Online (Sandbox Code Playgroud)
您可以将重塑与重复数据删除结合使用,使用stack/ unstack:
cols = ['Index', 'Schema', 'Column', 'Trh1', 'Trh2']
out = (df
# stack and remove NaNs
.set_index(cols).stack().to_frame()
# deduplicate
.assign(n=lambda d: d.groupby(level=range(df.index.ndim)).cumcount())
# reshape to original shape
.set_index('n', append=True)[0]
.unstack(-2)
# cleanup
.reset_index()
.drop(columns='n')
)
# add rows that were dropped because having no value
out = pd.concat([df[df[df.columns.difference(cols)].isna().all(axis=1)], out],
ignore_index=True).sort_values(by='Index') # optional
Run Code Online (Sandbox Code Playgroud)
注意。这不需要在初始cols.
或者使用melt,这可能会占用更多内存,但如果有重复项,也会更健壮:
cols = ['Index', 'Schema', 'Column', 'Trh1', 'Trh2']
out = (df.melt(cols)
# drop NAs, except first row per group
.loc[lambda d: d['value'].notna() | ~d[cols].duplicated()]
# de-duplicate
.assign(n=lambda d: d.groupby(cols, dropna=False).cumcount())
# reshape
.pivot(index=cols+['n'], columns='variable', values='value')
# cleanup
.reset_index().rename_axis(index=None, columns=None)
)
Run Code Online (Sandbox Code Playgroud)
输出:
Index Schema Column Trh1 Trh2 Trh3 Trh4
0 0 schema_1 col_1 NaN 0.01 NaN NaN
1 1 schema_2 col_2 0.02 0.03 NaN NaN
2 2 schema_3 col_3 0.03 0.04 0.05 NaN
3 3 schema_4 col_4 NaN NaN 0.06 NaN
4 3 schema_4 col_4 NaN NaN NaN 0.07
Run Code Online (Sandbox Code Playgroud)