@@ -2688,6 +2688,14 @@ def is_multi_index(self):
26882688 """ the levels attribute is 1 or a list in the case of a multi-index """
26892689 return isinstance (self .levels ,list )
26902690
2691+ def validate_multiindex (self , obj ):
2692+ """ validate that we can store the multi-index; reset and return the new object """
2693+ levels = [ l if l is not None else "level_{0}" .format (i ) for i , l in enumerate (obj .index .names ) ]
2694+ try :
2695+ return obj .reset_index (), levels
2696+ except (ValueError ):
2697+ raise ValueError ("duplicate names/columns in the multi-index when storing as a table" )
2698+
26912699 @property
26922700 def nrows_expected (self ):
26932701 """ based on our axes, compute the expected nrows """
@@ -3701,10 +3709,9 @@ class AppendableMultiSeriesTable(AppendableSeriesTable):
37013709 def write (self , obj , ** kwargs ):
37023710 """ we are going to write this as a frame table """
37033711 name = obj .name or 'values'
3704- cols = list (obj .index .names )
3712+ obj , self .levels = self .validate_multiindex (obj )
3713+ cols = list (self .levels )
37053714 cols .append (name )
3706- self .levels = list (obj .index .names )
3707- obj = obj .reset_index ()
37083715 obj .columns = cols
37093716 return super (AppendableMultiSeriesTable , self ).write (obj = obj , ** kwargs )
37103717
@@ -3764,6 +3771,7 @@ class AppendableMultiFrameTable(AppendableFrameTable):
37643771 table_type = u ('appendable_multiframe' )
37653772 obj_type = DataFrame
37663773 ndim = 2
3774+ _re_levels = re .compile ("^level_\d+$" )
37673775
37683776 @property
37693777 def table_type_short (self ):
@@ -3774,11 +3782,11 @@ def write(self, obj, data_columns=None, **kwargs):
37743782 data_columns = []
37753783 elif data_columns is True :
37763784 data_columns = obj .columns [:]
3777- for n in obj .index .names :
3785+ obj , self .levels = self .validate_multiindex (obj )
3786+ for n in self .levels :
37783787 if n not in data_columns :
37793788 data_columns .insert (0 , n )
3780- self .levels = obj .index .names
3781- return super (AppendableMultiFrameTable , self ).write (obj = obj .reset_index (), data_columns = data_columns , ** kwargs )
3789+ return super (AppendableMultiFrameTable , self ).write (obj = obj , data_columns = data_columns , ** kwargs )
37823790
37833791 def read (self , columns = None , ** kwargs ):
37843792 if columns is not None :
@@ -3787,7 +3795,11 @@ def read(self, columns=None, **kwargs):
37873795 columns .insert (0 , n )
37883796 df = super (AppendableMultiFrameTable , self ).read (
37893797 columns = columns , ** kwargs )
3790- df .set_index (self .levels , inplace = True )
3798+ df = df .set_index (self .levels )
3799+
3800+ # remove names for 'level_%d'
3801+ df .index = df .index .set_names ([ None if self ._re_levels .search (l ) else l for l in df .index .names ])
3802+
37913803 return df
37923804
37933805
0 commit comments