Repository: pandas-dev/pandas

Issue:
BUG: to_hdf failing with integer columns and data_columns=True
```
In [39]: N = 1000

In [40]: df = DataFrame(np.random.randint(0,8,size=N*400).astype('uint8').reshape(N,-1),index=pd.date_range('20130206',periods=N,freq='ms'))

In [41]: df.to_hdf('test.h5','df',mode='w',format='table')

In [42]: df.to_hdf('test.h5','df',mode='w',format='table',data_columns=True)
AttributeError: 'numpy.int64' object has no attribute 'startswith'
```

BUG: to_hdf failing with integer columns and data_columns=True
```
In [39]: N = 1000

In [40]: df = DataFrame(np.random.randint(0,8,size=N*400).astype('uint8').reshape(N,-1),index=pd.date_range('20130206',periods=N,freq='ms'))

In [41]: df.to_hdf('test.h5','df',mode='w',format='table')

In [42]: df.to_hdf('test.h5','df',mode='w',format='table',data_columns=True)
AttributeError: 'numpy.int64' object has no attribute 'startswith'
```



Discussion:
Looking at this as part of the PyCon Sprints.

Looking at this as part of the PyCon Sprints.


Resolving patch:
diff --git a/pandas/io/pytables.py b/pandas/io/pytables.py
--- a/pandas/io/pytables.py
+++ b/pandas/io/pytables.py
@@ -257,6 +257,7 @@ def _tables():
 def to_hdf(path_or_buf, key, value, mode=None, complevel=None, complib=None,
            append=None, **kwargs):
     """ store this object, close it if we opened it """
+
     if append:
         f = lambda store: store.append(key, value, **kwargs)
     else:
@@ -1535,6 +1536,12 @@ def maybe_set_size(self, min_itemsize=None, **kwargs):
                 self.typ = _tables(
                 ).StringCol(itemsize=min_itemsize, pos=self.pos)
 
+    def validate(self, handler, append, **kwargs):
+        self.validate_names()
+
+    def validate_names(self):
+        pass
+
     def validate_and_set(self, handler, append, **kwargs):
         self.set_table(handler.table)
         self.validate_col()
@@ -2080,6 +2087,10 @@ class DataIndexableCol(DataCol):
     """ represent a data column that can be indexed """
     is_data_indexable = True
 
+    def validate_names(self):
+        if not Index(self.values).is_object():
+            raise ValueError("cannot have non-object label DataIndexableCol")
+
     def get_atom_string(self, block, itemsize):
         return _tables().StringCol(itemsize=itemsize)
 
@@ -3756,6 +3767,9 @@ def write(self, obj, axes=None, append=False, complib=None,
                          min_itemsize=min_itemsize,
                          **kwargs)
 
+        for a in self.axes:
+            a.validate(self, append)
+
         if not self.is_exists:
 
             # create the table


Test patch:
diff --git a/pandas/io/tests/test_pytables.py b/pandas/io/tests/test_pytables.py
--- a/pandas/io/tests/test_pytables.py
+++ b/pandas/io/tests/test_pytables.py
@@ -4640,6 +4640,35 @@ def test_colums_multiindex_modified(self):
             df_loaded = read_hdf(path, 'df', columns=cols2load)
             self.assertTrue(cols2load_original == cols2load)
 
+    def test_to_hdf_with_object_column_names(self):
+        # GH9057
+        # Writing HDF5 table format should only work for string-like
+        # column types
+
+        types_should_fail = [ tm.makeIntIndex, tm.makeFloatIndex,
+                                tm.makeDateIndex, tm.makeTimedeltaIndex,
+                                tm.makePeriodIndex ]
+        types_should_run = [ tm.makeStringIndex, tm.makeCategoricalIndex ]
+
+        if compat.PY3:
+            types_should_run.append(tm.makeUnicodeIndex)
+        else:
+            types_should_fail.append(tm.makeUnicodeIndex)
+
+        for index in types_should_fail:
+            df = DataFrame(np.random.randn(10, 2), columns=index(2))
+            with ensure_clean_path(self.path) as path:
+                with self.assertRaises(ValueError,
+                        msg="cannot have non-object label DataIndexableCol"):
+                    df.to_hdf(path, 'df', format='table', data_columns=True)
+
+        for index in types_should_run:
+            df = DataFrame(np.random.randn(10, 2), columns=index(2))
+            with ensure_clean_path(self.path) as path:
+                df.to_hdf(path, 'df', format='table', data_columns=True)
+                result = pd.read_hdf(path, 'df', where="index = [{0}]".format(df.index[0]))
+                assert(len(result))
+
 
 def _test_sort(obj):
     if isinstance(obj, DataFrame):