@@ -1325,6 +1325,73 @@ def test_crosstab_normalize(self):
1325
1325
margins = True )
1326
1326
tm .assert_frame_equal (test_case , norm_sum )
1327
1327
1328
+ def test_crosstab_norm_margins_with_multiindex (self ):
1329
+ # GH 15150
1330
+ a = np .array (['foo' , 'bar' , 'foo' , 'bar' ,'bar' , 'foo' ])
1331
+ b = np .array (['one' , 'one' , 'two' , 'one' ,'two' , 'two' ])
1332
+ c = np .array (['dull' , 'shiny' , 'dull' , 'dull' ,'dull' , 'shiny' ])
1333
+ d = np .array (['a' , 'a' , 'b' , 'a' ,'b' , 'b' ])
1334
+ expected_col_colnorm = MultiIndex (levels = [['All' , 'dull' , 'shiny' ],
1335
+ ['' , 'a' , 'b' ]],
1336
+ labels = [[1 , 1 , 2 , 2 , 0 ],
1337
+ [1 , 2 , 1 , 2 , 0 ]],
1338
+ names = ['col_0' , 'col_1' ])
1339
+ expected_index_colnorm = MultiIndex (levels = [['All' , 'bar' , 'foo' ],
1340
+ ['' , 'one' , 'two' ]],
1341
+ labels = [[1 , 1 , 2 , 2 ],
1342
+ [1 , 2 , 1 , 2 ]],
1343
+ names = ['row_0' , 'row_1' ])
1344
+ expected_data_colnorm = np .array ([[.5 , 0. , 1. , 0. , .333333 ],
1345
+ [0. , .5 , 0. , 0. , .166667 ],
1346
+ [.5 , 0. , 0. , 0. , .166667 ],
1347
+ [0. , .5 , 0. , 1. , .333333 ]])
1348
+ expected_colnorm = pd .DataFrame (expected_data_colnorm ,
1349
+ index = expected_index_colnorm ,
1350
+ columns = expected_col_colnorm )
1351
+ expected_col_indexnorm = MultiIndex (levels = [['All' , 'dull' , 'shiny' ],
1352
+ ['' , 'a' , 'b' ]],
1353
+ labels = [[1 , 1 , 2 , 2 ],
1354
+ [1 , 2 , 1 , 2 ]],
1355
+ names = ['col_0' , 'col_1' ])
1356
+ expected_index_indexnorm = MultiIndex (levels = [['All' , 'bar' , 'foo' ],
1357
+ ['' , 'one' , 'two' ]],
1358
+ labels = [[1 , 1 , 2 , 2 , 0 ],
1359
+ [1 , 2 , 1 , 2 , 0 ]],
1360
+ names = ['row_0' , 'row_1' ])
1361
+ expected_data_indexnorm = np .array ([[.5 , 0. , .5 , 0. ],
1362
+ [0. , 1. , 0. , 0. ],
1363
+ [1. , 0. , 0. , 0. ],
1364
+ [0. , .5 , 0. , .5 ],
1365
+ [.33333333 , .33333333 ,
1366
+ .16666667 , .16666667 ]])
1367
+ expected_indexnorm = pd .DataFrame (expected_data_indexnorm ,
1368
+ index = expected_index_indexnorm ,
1369
+ columns = expected_col_indexnorm )
1370
+ expected_data_allnorm = np .array ([[0.16666667 , 0. , .16666667 ,
1371
+ 0. , .33333333 ],
1372
+ [0. ,.16666667 , 0. ,
1373
+ 0. , .16666667 ],
1374
+ [.16666667 , 0. , 0. ,
1375
+ 0. , .16666667 ],
1376
+ [0. , .16666667 , 0. ,
1377
+ .16666667 , .33333333 ],
1378
+ [0.33333333 , .33333333 , .16666667 ,
1379
+ .16666667 , 1. ]])
1380
+ expected_allnorm = pd .DataFrame (expected_data_allnorm ,
1381
+ index = expected_index_indexnorm ,
1382
+ columns = expected_col_colnorm )
1383
+
1384
+ result_colnorm = pd .crosstab ([a , b ], [c ,d ], normalize = 'columns' ,
1385
+ margins = True )
1386
+ result_indexnorm = pd .crosstab ([a , b ], [c ,d ], normalize = 'index' ,
1387
+ margins = True )
1388
+ result_allnorm = pd .crosstab ([a , b ], [c ,d ], normalize = 'all' ,
1389
+ margins = True )
1390
+
1391
+ tm .assert_frame_equal (result_colnorm , expected_colnorm )
1392
+ tm .assert_frame_equal (result_indexnorm , expected_indexnorm )
1393
+ tm .assert_frame_equal (result_allnorm , expected_allnorm )
1394
+
1328
1395
def test_crosstab_with_empties (self ):
1329
1396
# Check handling of empties
1330
1397
df = pd .DataFrame ({'a' : [1 , 2 , 2 , 2 , 2 ], 'b' : [3 , 3 , 4 , 4 , 4 ],
0 commit comments