Reputation: 470
I've placed a blank row after each level 0 row label in the below DataFrame for more convenient viewing. I had a row of values in each I didn't require, so transformed that.
What is the correct way to go about it, as opposed to my hack job?
B S
Depth3 Depth2 Depth1 Depth1 Depth2 Depth3
Market1 actionIndicator B B B S S S
limit 555 557 558 560 561 562
quantity 18.474 8.355 8.286 0.626 17.101 17.576
Market2 actionIndicator B B B S S S
limit 475 477 478 479 480 481
quantity 30.156 8.329 8.182 37.483 84.416 37.659
Market3 actionIndicator B B B S S S
limit 583 586 587 589 590 591
quantity 39.548 8.382 8.18 55.181 17.289 17.689
I wanted this:
B S
Depth3 Depth2 Depth1 Depth1 Depth2 Depth3
Market1 limit 555 557 558 560 561 562
quantity 18.474 8.355 8.286 0.626 17.101 17.576
Market2 limit 475 477 478 479 480 481
quantity 30.156 8.329 8.182 37.483 84.416 37.659
Market3 limit 583 586 587 589 590 591
quantity 39.548 8.382 8.18 55.181 17.289 17.689
The following was used on the original DataFrame to achieve it:
df = df.reindex(display_order, level=0).reindex(["limit", "quantity",
"actionIndicator"], level=1)
df.index = df.index.set_levels(["limit", "quantity", ""], level=1)
for level in set(df.index.get_level_values(0)):
df.ix[(level, "")] = ""
Full code:
data = {
'Market1': {'B': {'Depth1': {'actionIndicator': 'B',
'limit': '558',
'quantity': '8.286'},
'Depth2': {'actionIndicator': 'B', 'limit': '557', 'quantity': '8.355'},
'Depth3': {'actionIndicator': 'B', 'limit': '555', 'quantity': '18.474'}},
'S': {'Depth1': {'actionIndicator': 'S',
'limit': '560',
'quantity': '0.626'},
'Depth2': {'actionIndicator': 'S', 'limit': '561', 'quantity': '17.101'},
'Depth3': {'actionIndicator': 'S', 'limit': '562', 'quantity': '17.576'}}},
'Market2': {'B': {'Depth1': {'actionIndicator': 'B',
'limit': '478',
'quantity': '8.182'},
'Depth2': {'actionIndicator': 'B', 'limit': '477', 'quantity': '8.329'},
'Depth3': {'actionIndicator': 'B', 'limit': '475', 'quantity': '30.156'}},
'S': {'Depth1': {'actionIndicator': 'S',
'limit': '479',
'quantity': '37.483'},
'Depth2': {'actionIndicator': 'S', 'limit': '480', 'quantity': '84.416'},
'Depth3': {'actionIndicator': 'S', 'limit': '481', 'quantity': '37.659'}}},
'Market3': {'B': {'Depth1': {'actionIndicator': 'B',
'limit': '587',
'quantity': '8.18'},
'Depth2': {'actionIndicator': 'B', 'limit': '586', 'quantity': '8.382'},
'Depth3': {'actionIndicator': 'B', 'limit': '583', 'quantity': '39.548'}},
'S': {'Depth1': {'actionIndicator': 'S',
'limit': '589',
'quantity': '55.181'},
'Depth2': {'actionIndicator': 'S', 'limit': '590', 'quantity': '17.289'},
'Depth3': {'actionIndicator': 'S', 'limit': '591', 'quantity': '17.689'}}},
}
df = DataFrame.from_dict(
{(k1, k2, k3): data[k1][k2][k3] for k1 in data.keys() for k2 in
data[k1].keys() for k3 in data[k1][k2].keys()}, orient="columns")
df = df.unstack().reorder_levels([0,3,2,1]).unstack(level=[3,2])
dfB = df[["B"]].sort_index(axis=1, ascending=False)
dfS = df[["S"]]
df = pd.concat([dfB, dfS], axis=1)
df = df.reindex(["limit", "quantity", "actionIndicator"], level=1)
df.index = df.index.set_levels(["limit", "quantity", ""], level=1)
for level in set(df.index.get_level_values(0)):
df.ix[(level, "")] = ""
print(df)
Upvotes: 0
Views: 132
Reputation: 862511
You can use another hack:
df = pd.DataFrame.from_dict(
{(k1, k2, k3): data[k1][k2][k3] for k1 in data.keys() for k2 in
data[k1].keys() for k3 in data[k1][k2].keys()}, orient="columns")
df = df.stack(0).swaplevel(1,0).sort_index()
print (df)
B S
Depth1 Depth2 Depth3 Depth1 Depth2 Depth3
Market1 actionIndicator B B B S S S
limit 558 557 555 560 561 562
quantity 8.286 8.355 18.474 0.626 17.101 17.576
Market2 actionIndicator B B B S S S
limit 478 477 475 479 480 481
quantity 8.182 8.329 30.156 37.483 84.416 37.659
Market3 actionIndicator B B B S S S
limit 587 586 583 589 590 591
quantity 8.18 8.382 39.548 55.181 17.289 17.689
#rename index value 'actionIndicator' for last for sort e.g. zzz
df = df.rename(index={'actionIndicator':'zzz'})
#sorting index, zzz row is last in each group
df = df.sort_index()
#get mask where zzz
mask = df.index.get_level_values(1) == 'zzz'
#replace rows where mask is True by empty spaces
df.loc[mask] = ''
#replace value zzz to empty space
df = df.rename(index={'zzz':''})
print (df)
B S
Depth1 Depth2 Depth3 Depth1 Depth2 Depth3
Market1 limit 558 557 555 560 561 562
quantity 8.286 8.355 18.474 0.626 17.101 17.576
Market2 limit 478 477 475 479 480 481
quantity 8.182 8.329 30.156 37.483 84.416 37.659
Market3 limit 587 586 583 589 590 591
quantity 8.18 8.382 39.548 55.181 17.289 17.689
Another possible solution with reindex
by MultiIndex.from_product
:
#dynamically remove 'actionIndicator' and add it to the end of list
a = 'actionIndicator'
lvls = [lvl for lvl in df.index.levels[1] if lvl != a] + [a]
print (lvls)
['limit', 'quantity', 'actionIndicator']
df = df.reindex(pd.MultiIndex.from_product([df.index.levels[0],lvls]))
mask = df.index.get_level_values(1) == a
df.loc[mask] = ''
df = df.rename(index={a:''})
print (df)
B S
Depth1 Depth2 Depth3 Depth1 Depth2 Depth3
Market1 limit 558 557 555 560 561 562
quantity 8.286 8.355 18.474 0.626 17.101 17.576
Market2 limit 478 477 475 479 480 481
quantity 8.182 8.329 30.156 37.483 84.416 37.659
Market3 limit 587 586 583 589 590 591
quantity 8.18 8.382 39.548 55.181 17.289 17.689
Upvotes: 1