我有一个问题,但找不到有效的解决方案。
作为起点,我有一个从 xml 文件创建的数组,其中包含以下信息:
| Location | Description | Status | ..... | Product| Name | Price | Product| Name | Price | ...
| 1 | "Foo" | 1 | | | 124 | 4.2 | | 122 | 8.8 |
| 2 | "Bar" | 1 | | | 122 | 8.9 | | NaN | NaN |
前 n 列包含通用信息,对于相应行中的所有“产品”来说都是相同的。最后 24 列包含 3 列的 8 个子集,具有相同的重复名称集 [“产品”、“名称”、“价格”]。
为了进一步处理数据,我想将最后 24 列的数据“堆叠”为三列的子集,以获得如下所示的结果:
| Location | Description | Status | ..... | Product| Name | Price |
| 1 | "Foo" | 1 | | | 124 | 4.2 |
| | | | | | 122 | 8.8 |
| 2 | "Bar" | 1 | | | 122 | 8.9 |
| | | | | | NaN | NaN |
或
| Location | Description | Status | ..... | Product| Name | Price |
| 1 | "Foo" | 1 | | | 124 | 4.2 |
| 1 | "Foo" | 1 | | | 122 | 8.8 |
| 2 | "Bar" | 1 | | | 122 | 8.9 |
| 2 | "Bar" | 1 | | | NaN | NaN |
我尝试按如下方式解决我的转换问题:
第 1 步:删除重复的相同列名(以便稍后能够使用 df.stack():
cols=pd.Series(result_list_xml_t[0])
for dup in cols[cols.duplicated()].unique():
cols[cols[cols == dup].index.values.tolist()] = [dup + '.' + str(i) if i != 0 else dup for i in range(sum(cols == dup))]
第2步:创建MultiIndex进行分组
columns_xml = pd.MultiIndex.from_arrays([xml_groups,cols])
用这个我创建了一个 pandas df,看起来像:
| base | prod1 | prod 2
| Location | Description | Status | ..... | Product.1| Name.1 | Price.1 | Product.2| Name.2 | Price.2 | ...
1 | 1 | "Foo" | 1 | | | 124 | 4.2 | | 122 | 8.8 |
2 | 2 | "Bar" | 1 | | | 122 | 8.9 | | NaN | NaN |
现在,我只想堆叠产品组,同时维护基础组。这可以通过使用堆栈函数来完成还是有其他更有效的方法?
因为这个线程,我尝试使用 df.stack: Stack Overflow - Unnnest 多索引数据框 但
df.stack(future_stack=True,level=0)
似乎并没有让我更接近我想要的格式。
| | base | prod1 | prod2 | prod3| ...
0 | Location | 1 |
0 | Description| "Foo" |
0 | Status | 1 |
...
0 | Product.1 | | | | |
0 | Name.1 | | 124 | | |
0 | Price.1 | | 4.2 | | |
...
我还尝试使用以下线程Unstack或Pivot in Pandas提出的.melt()和.set_index()组合,但这也没有让我更接近。
用途:
print (df)
Location Description Status Product Name Price Product Name Price
0 1 Foo 1 a 124 4.2 v 122.0 8.8
1 2 Bar 1 b 122 8.9 b NaN NaN
n = 3
out = df.set_index(df.columns[:n].tolist())
out.columns = [out.columns, out.columns.to_series().groupby(level=0).cumcount()]
out = out.stack(dropna=False).droplevel(-1).reset_index()
print (out)
Location Description Status Product Name Price
0 1 Foo 1 a 124.0 4.2
1 1 Foo 1 v 122.0 8.8
2 2 Bar 1 b 122.0 8.9
3 2 Bar 1 b NaN NaN