@@ -254,13 +254,27 @@ def _add_margins(table, data, values, rows, cols, aggfunc,
254
254
255
255
256
256
def _check_margins_name (margins_name , table ):
257
+ """
258
+ Checks if margins_name is a correct input argument for pivot_table
259
+ or crosstab.
260
+
261
+ Parameters
262
+ ----------
263
+
264
+ margins_name : string, default 'All'
265
+ Name of the row / column that will contain the totals
266
+ when margins is True.
267
+ table : DataFrame
268
+ """
269
+
257
270
if not isinstance (margins_name , compat .string_types ):
258
271
raise ValueError ('margins_name argument must be a string' )
259
272
260
273
exception_msg = 'Conflicting name "{0}" in margins' .format (margins_name )
261
274
for level in table .index .names :
262
275
if margins_name in table .index .get_level_values (level ):
263
276
raise ValueError (exception_msg )
277
+
264
278
# could be passed a Series object with no 'columns'
265
279
if hasattr (table , 'columns' ):
266
280
for level in table .columns .names [1 :]:
@@ -541,10 +555,13 @@ def crosstab(index, columns, values=None, rownames=None, colnames=None,
541
555
542
556
if normalize != 'columns' :
543
557
# add margin row
544
- if type (table .index ) is MultiIndex :
545
- table = table .transpose ()
546
- table [margins_name ] = table .sum (axis = 1 )
547
- table = table .transpose ()
558
+ if isinstance (table .index , MultiIndex ):
559
+ # workaround for adding a margins row to a MultiIndex object
560
+ # to be removed when GH 17024 is fixed
561
+ new_index = _add_margins_to_multiindex (table .index ,
562
+ margins_name )
563
+ table .loc [margins_name ] = table .sum (axis = 0 )
564
+ table .index = new_index
548
565
else :
549
566
table .loc [margins_name ] = table .sum (axis = 0 )
550
567
# Post-process
@@ -555,6 +572,25 @@ def crosstab(index, columns, values=None, rownames=None, colnames=None,
555
572
return table
556
573
557
574
575
+ def _add_margins_to_multiindex (index , margins_name ):
576
+ # workaround for adding a margins row to a MultiIndex object
577
+ # to be removed when GH 17024 is fixed
578
+ levels = list (index .levels )
579
+ labels = list (index .labels )
580
+
581
+ levels [0 ] = levels [0 ].append (Index ([margins_name ]))
582
+ for i in range (1 , len (levels )):
583
+ levels [i ] = levels [i ].append (Index (['' ]))
584
+ for i in range (len (labels )):
585
+ lbl = list (labels [i ])
586
+ lbl .append (max (labels [i ] + 1 ))
587
+ labels [i ] = lbl
588
+
589
+ return MultiIndex (levels = levels ,
590
+ labels = labels ,
591
+ names = index .names )
592
+
593
+
558
594
def _normalize (table , normalize , margins , margins_name = 'All' ):
559
595
560
596
if not isinstance (normalize , bool ) and not isinstance (normalize ,
@@ -585,11 +621,7 @@ def _normalize(table, normalize, margins, margins_name='All'):
585
621
586
622
normalizers [True ] = normalizers ['all' ]
587
623
588
- try :
589
- f = normalizers [normalize ]
590
- except KeyError :
591
- raise ValueError (
592
- "Not a valid normalize argument: {!r}" .format (normalize ))
624
+ f = normalizers [normalize ]
593
625
594
626
table = f (table )
595
627
table = table .fillna (0 )
0 commit comments