diff --git a/doc/source/release.rst b/doc/source/release.rst index 8b753abc83ca7..c33c2fe61429a 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -65,6 +65,7 @@ API Changes - ``select_as_multiple`` will always raise a ``KeyError``, when a key or the selector is not found (:issue:`6177`) - ``df['col'] = value`` and ``df.loc[:,'col'] = value`` are now completely equivalent; previously the ``.loc`` would not necessarily coerce the dtype of the resultant series (:issue:`6149`) +- ``dtypes`` and ``ftypes`` now return a series with ``dtype=object`` on empty containers (:issue:`5740`) Experimental Features diff --git a/pandas/core/generic.py b/pandas/core/generic.py index c8e1247416806..d607be6bfb733 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -1947,7 +1947,8 @@ def get_ftype_counts(self): def dtypes(self): """ Return the dtypes in this object """ from pandas import Series - return Series(self._data.get_dtypes(),index=self._info_axis) + return Series(self._data.get_dtypes(), index=self._info_axis, + dtype=np.object_) @property def ftypes(self): @@ -1956,7 +1957,8 @@ def ftypes(self): in this object. """ from pandas import Series - return Series(self._data.get_ftypes(),index=self._info_axis) + return Series(self._data.get_ftypes(), index=self._info_axis, + dtype=np.object_) def as_blocks(self, columns=None): """ diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index 6eddd52dba634..f85c95e8b81db 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -12164,6 +12164,47 @@ def test_concat_empty_dataframe_dtypes(self): self.assertEqual(result['b'].dtype, np.float64) self.assertEqual(result['c'].dtype, np.float64) + def test_empty_frame_dtypes_ftypes(self): + empty_df = pd.DataFrame() + assert_series_equal(empty_df.dtypes, pd.Series(dtype=np.object)) + assert_series_equal(empty_df.ftypes, pd.Series(dtype=np.object)) + + nocols_df = pd.DataFrame(index=[1,2,3]) + assert_series_equal(nocols_df.dtypes, pd.Series(dtype=np.object)) + assert_series_equal(nocols_df.ftypes, pd.Series(dtype=np.object)) + + norows_df = pd.DataFrame(columns=list("abc")) + assert_series_equal(norows_df.dtypes, pd.Series(np.object, index=list("abc"))) + assert_series_equal(norows_df.ftypes, pd.Series('object:dense', index=list("abc"))) + + norows_int_df = pd.DataFrame(columns=list("abc")).astype(np.int32) + assert_series_equal(norows_int_df.dtypes, pd.Series(np.dtype('int32'), index=list("abc"))) + assert_series_equal(norows_int_df.ftypes, pd.Series('int32:dense', index=list("abc"))) + + odict = OrderedDict + df = pd.DataFrame(odict([('a', 1), ('b', True), ('c', 1.0)]), index=[1, 2, 3]) + assert_series_equal(df.dtypes, pd.Series(odict([('a', np.int64), + ('b', np.bool), + ('c', np.float64)]))) + assert_series_equal(df.ftypes, pd.Series(odict([('a', 'int64:dense'), + ('b', 'bool:dense'), + ('c', 'float64:dense')]))) + + # same but for empty slice of df + assert_series_equal(df[:0].dtypes, pd.Series(odict([('a', np.int), + ('b', np.bool), + ('c', np.float)]))) + assert_series_equal(df[:0].ftypes, pd.Series(odict([('a', 'int64:dense'), + ('b', 'bool:dense'), + ('c', 'float64:dense')]))) + +def skip_if_no_ne(engine='numexpr'): + if engine == 'numexpr': + try: + import numexpr as ne + except ImportError: + raise nose.SkipTest("cannot query engine numexpr when numexpr not " + "installed") def skip_if_no_pandas_parser(parser):