I approached this problem from a slightly different angle and created a function that can be used as a general method of ordering columns in a crosstab in pandas. It may also work for a pivot table but I didn't test that nor did I look at the details. I suppose it can also be used to order row labels too but I didn't try for that.
This creates a crosstab with column labels such as "12 10_Oct 12" and 12 11_Nov 12". The label effectively forces the alphabetizing of crosstab to work in my favor. The alphabetizing section of the label is concatenated with "_" and the label that I want to use.
table_1=pd.crosstab(f_dtflt.EW_REGIONCOLLSITE, f_dtflt.COLLECTION_DATE.apply(lambda x: x.strftime("%y %m_%b %y")), margins=True)
Output:
"COLLECTION_DATE 12 10_Oct 12 12 11_Nov 12 12 12_Dec 12 13 01_Jan 13
EW_REGIONCOLLSITE
EAST 825 2108 2280 2757
WEST 42 407 1003 2216
All 867 2515 3283 4973
COLLECTION_DATE 13 02_Feb 13 13 03_Mar 13 13 04_Apr 13 13 05_May 13
EW_REGIONCOLLSITE
EAST 2272 1682 1964 1981
WEST 2351 2770 2579 3014
All 4623 4452 4543 4995
COLLECTION_DATE 13 06_Jun 13 13 07_Jul 13 13 08_Aug 13 13 09_Sep 13
EW_REGIONCOLLSITE
EAST 1902 2113 2092 975
WEST 1823 1506 2011 888
All 3725 3619 4103 1863
COLLECTION_DATE All
EW_REGIONCOLLSITE
EAST 22951
WEST 20610
All 43561 "
The function and calls:
def clean_label(label_list, margins='False'):
''' This function takes the column index list from a crosstab (or pivot table?) in pandas and removes the
part of the label before and including the "_". This allows the user to order the columns manually by creating
an alphabetical index followed by "_" and then the label that they would like to use. For example, a label such as
['a_Positive', 'b_Negative'] will be converted to ['Positive', 'Negative']. Another example would be to order dates
in a table from ['12 10_Oct 12', '12 11_Nov 12'] to ['Oct 12', 'Nov 12']
margins = False if the crosstab was created without margins and therefore does not have an "All" at the end of the list
margins = True if the crosstab was created with margins and therefore has an "All" at the end of the list
'''
corrected_list=list()
# If one creates margins in pivot/crosstab, will get the last column of "All"
# This has to be removed from the following code or it will throw an error.
if margins:
convert_list = label_list[:-1]
else:
convert_list = label_list
for l in convert_list:
x,y=l.split('_')
corrected_list.append(y)
if margins:
corrected_list.append('Total') # Renames "All" to "Total"
return corrected_list
# Change the labels on the crosstab table
table_1.columns=clean_label(table_1.columns, margins=True)
# Change name of columns
table_1.columns.name = 'Month of Collection'
# Change name of rows
table_1.index.name = 'Region'
Output (final table):
"Month of Collection Oct 12 Nov 12 Dec 12 Jan 13 Feb 13 Mar 13 Apr 13
Region
EAST 825 2108 2280 2757 2272 1682 1964
WEST 42 407 1003 2216 2351 2770 2579
All 867 2515 3283 4973 4623 4452 4543
Month of Collection May 13 Jun 13 Jul 13 Aug 13 Sep 13 Total
Region
EAST 1981 1902 2113 2092 975 22951
WEST 3014 1823 1506 2011 888 20610
All 4995 3725 3619 4103 1863 43561 "