@@ -2688,6 +2688,14 @@ def is_multi_index(self):
2688
2688
""" the levels attribute is 1 or a list in the case of a multi-index """
2689
2689
return isinstance (self .levels ,list )
2690
2690
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
+
2691
2699
@property
2692
2700
def nrows_expected (self ):
2693
2701
""" based on our axes, compute the expected nrows """
@@ -3701,10 +3709,9 @@ class AppendableMultiSeriesTable(AppendableSeriesTable):
3701
3709
def write (self , obj , ** kwargs ):
3702
3710
""" we are going to write this as a frame table """
3703
3711
name = obj .name or 'values'
3704
- cols = list (obj .index .names )
3712
+ obj , self .levels = self .validate_multiindex (obj )
3713
+ cols = list (self .levels )
3705
3714
cols .append (name )
3706
- self .levels = list (obj .index .names )
3707
- obj = obj .reset_index ()
3708
3715
obj .columns = cols
3709
3716
return super (AppendableMultiSeriesTable , self ).write (obj = obj , ** kwargs )
3710
3717
@@ -3764,6 +3771,7 @@ class AppendableMultiFrameTable(AppendableFrameTable):
3764
3771
table_type = u ('appendable_multiframe' )
3765
3772
obj_type = DataFrame
3766
3773
ndim = 2
3774
+ _re_levels = re .compile ("^level_\d+$" )
3767
3775
3768
3776
@property
3769
3777
def table_type_short (self ):
@@ -3774,11 +3782,11 @@ def write(self, obj, data_columns=None, **kwargs):
3774
3782
data_columns = []
3775
3783
elif data_columns is True :
3776
3784
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 :
3778
3787
if n not in data_columns :
3779
3788
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 )
3782
3790
3783
3791
def read (self , columns = None , ** kwargs ):
3784
3792
if columns is not None :
@@ -3787,7 +3795,11 @@ def read(self, columns=None, **kwargs):
3787
3795
columns .insert (0 , n )
3788
3796
df = super (AppendableMultiFrameTable , self ).read (
3789
3797
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
+
3791
3803
return df
3792
3804
3793
3805
0 commit comments