@@ -1359,6 +1359,73 @@ def test_crosstab_normalize(self):
1359
1359
margins = True )
1360
1360
tm .assert_frame_equal (test_case , norm_sum )
1361
1361
1362
+ def test_crosstab_norm_margins_with_multiindex (self ):
1363
+ # GH 15150
1364
+ a = np .array (['foo' , 'bar' , 'foo' , 'bar' ,'bar' , 'foo' ])
1365
+ b = np .array (['one' , 'one' , 'two' , 'one' ,'two' , 'two' ])
1366
+ c = np .array (['dull' , 'shiny' , 'dull' , 'dull' ,'dull' , 'shiny' ])
1367
+ d = np .array (['a' , 'a' , 'b' , 'a' ,'b' , 'b' ])
1368
+ expected_col_colnorm = MultiIndex (levels = [['All' , 'dull' , 'shiny' ],
1369
+ ['' , 'a' , 'b' ]],
1370
+ labels = [[1 , 1 , 2 , 2 , 0 ],
1371
+ [1 , 2 , 1 , 2 , 0 ]],
1372
+ names = ['col_0' , 'col_1' ])
1373
+ expected_index_colnorm = MultiIndex (levels = [['All' , 'bar' , 'foo' ],
1374
+ ['' , 'one' , 'two' ]],
1375
+ labels = [[1 , 1 , 2 , 2 ],
1376
+ [1 , 2 , 1 , 2 ]],
1377
+ names = ['row_0' , 'row_1' ])
1378
+ expected_data_colnorm = np .array ([[.5 , 0. , 1. , 0. , .333333 ],
1379
+ [0. , .5 , 0. , 0. , .166667 ],
1380
+ [.5 , 0. , 0. , 0. , .166667 ],
1381
+ [0. , .5 , 0. , 1. , .333333 ]])
1382
+ expected_colnorm = pd .DataFrame (expected_data_colnorm ,
1383
+ index = expected_index_colnorm ,
1384
+ columns = expected_col_colnorm )
1385
+ expected_col_indexnorm = MultiIndex (levels = [['All' , 'dull' , 'shiny' ],
1386
+ ['' , 'a' , 'b' ]],
1387
+ labels = [[1 , 1 , 2 , 2 ],
1388
+ [1 , 2 , 1 , 2 ]],
1389
+ names = ['col_0' , 'col_1' ])
1390
+ expected_index_indexnorm = MultiIndex (levels = [['All' , 'bar' , 'foo' ],
1391
+ ['' , 'one' , 'two' ]],
1392
+ labels = [[1 , 1 , 2 , 2 , 0 ],
1393
+ [1 , 2 , 1 , 2 , 0 ]],
1394
+ names = ['row_0' , 'row_1' ])
1395
+ expected_data_indexnorm = np .array ([[.5 , 0. , .5 , 0. ],
1396
+ [0. , 1. , 0. , 0. ],
1397
+ [1. , 0. , 0. , 0. ],
1398
+ [0. , .5 , 0. , .5 ],
1399
+ [.33333333 , .33333333 ,
1400
+ .16666667 , .16666667 ]])
1401
+ expected_indexnorm = pd .DataFrame (expected_data_indexnorm ,
1402
+ index = expected_index_indexnorm ,
1403
+ columns = expected_col_indexnorm )
1404
+ expected_data_allnorm = np .array ([[0.16666667 , 0. , .16666667 ,
1405
+ 0. , .33333333 ],
1406
+ [0. ,.16666667 , 0. ,
1407
+ 0. , .16666667 ],
1408
+ [.16666667 , 0. , 0. ,
1409
+ 0. , .16666667 ],
1410
+ [0. , .16666667 , 0. ,
1411
+ .16666667 , .33333333 ],
1412
+ [0.33333333 , .33333333 , .16666667 ,
1413
+ .16666667 , 1. ]])
1414
+ expected_allnorm = pd .DataFrame (expected_data_allnorm ,
1415
+ index = expected_index_indexnorm ,
1416
+ columns = expected_col_colnorm )
1417
+
1418
+ result_colnorm = pd .crosstab ([a , b ], [c ,d ], normalize = 'columns' ,
1419
+ margins = True )
1420
+ result_indexnorm = pd .crosstab ([a , b ], [c ,d ], normalize = 'index' ,
1421
+ margins = True )
1422
+ result_allnorm = pd .crosstab ([a , b ], [c ,d ], normalize = 'all' ,
1423
+ margins = True )
1424
+
1425
+ tm .assert_frame_equal (result_colnorm , expected_colnorm )
1426
+ tm .assert_frame_equal (result_indexnorm , expected_indexnorm )
1427
+ tm .assert_frame_equal (result_allnorm , expected_allnorm )
1428
+
1362
1429
def test_crosstab_with_empties (self ):
1363
1430
# Check handling of empties
1364
1431
df = pd .DataFrame ({'a' : [1 , 2 , 2 , 2 , 2 ], 'b' : [3 , 3 , 4 , 4 , 4 ],
0 commit comments