From fa8a35ce35283dac2f14a0b062c7e56639bb69b3 Mon Sep 17 00:00:00 2001 From: Jason Sexauer Date: Thu, 20 Mar 2014 21:56:08 -0400 Subject: [PATCH] Fix #6645. Raises warning on use of cols and update unit tests --- doc/source/release.rst | 5 +++++ doc/source/v0.14.0.txt | 5 +++++ pandas/core/frame.py | 36 +++++++++++++++++++++++++++++------ pandas/io/tests/test_excel.py | 24 +++++++++++++++-------- pandas/tests/test_frame.py | 19 ++++++++++++------ 5 files changed, 69 insertions(+), 20 deletions(-) diff --git a/doc/source/release.rst b/doc/source/release.rst index c0bd8f424c2b2..d7312893f5727 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -134,6 +134,11 @@ API Changes ``FutureWarning`` is raised to alert that the old ``rows`` and ``cols`` arguments will not be supported in a future release (:issue:`5505`) +- The :meth:`DataFrame.to_csv` and :meth:`DataFrame.to_excel` functions + now takes argument ``columns`` instead of ``cols``. A + ``FutureWarning`` is raised to alert that the old ``cols`` arguments + will not be supported in a future release (:issue:`6645`) + - Allow specification of a more complex groupby, via ``pd.Grouper`` (:issue:`3794`) - A tuple passed to ``DataFame.sort_index`` will be interpreted as the levels of diff --git a/doc/source/v0.14.0.txt b/doc/source/v0.14.0.txt index a2990644fa124..4a438b9f4d444 100644 --- a/doc/source/v0.14.0.txt +++ b/doc/source/v0.14.0.txt @@ -178,6 +178,11 @@ These are out-of-bounds selections ``FutureWarning`` is raised to alert that the old ``rows`` and ``cols`` arguments will not be supported in a future release (:issue:`5505`) +- The :meth:`DataFrame.to_csv` and :meth:`DataFrame.to_excel` functions + now takes argument ``columns`` instead of ``cols``. A + ``FutureWarning`` is raised to alert that the old ``cols`` arguments + will not be supported in a future release (:issue:`6645`) + - Following keywords are now acceptable for :meth:`DataFrame.plot(kind='bar')` and :meth:`DataFrame.plot(kind='barh')`. - `width`: Specify the bar width. In previous versions, static value 0.5 was passed to matplotlib and it cannot be overwritten. - `position`: Specify relative alignments for bar plot layout. From 0 (left/bottom-end) to 1(right/top-end). Default is 0.5 (center). (:issue:`6604`) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 4f23fd69d7621..40947e6f8fc6a 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -1068,7 +1068,7 @@ def to_panel(self): to_wide = deprecate('to_wide', to_panel) def to_csv(self, path_or_buf=None, sep=",", na_rep='', float_format=None, - cols=None, header=True, index=True, index_label=None, + columns=None, header=True, index=True, index_label=None, mode='w', nanRep=None, encoding=None, quoting=None, quotechar='"', line_terminator='\n', chunksize=None, tupleize_cols=False, date_format=None, doublequote=True, @@ -1086,7 +1086,7 @@ def to_csv(self, path_or_buf=None, sep=",", na_rep='', float_format=None, Missing data representation float_format : string, default None Format string for floating point numbers - cols : sequence, optional + columns : sequence, optional Columns to write header : boolean or list of string, default True Write out column names. If a list of string is given it is assumed @@ -1124,17 +1124,29 @@ def to_csv(self, path_or_buf=None, sep=",", na_rep='', float_format=None, or new (expanded format) if False) date_format : string, default None Format string for datetime objects + cols : kwarg only alias of columns [deprecated] """ if nanRep is not None: # pragma: no cover warnings.warn("nanRep is deprecated, use na_rep", FutureWarning) na_rep = nanRep + # Parse old-style keyword argument + cols = kwds.pop('cols', None) + if cols is not None: + warnings.warn("cols is deprecated, use columns", FutureWarning) + if columns is None: + columns = cols + else: + msg = "Can only specify either 'columns' or 'cols'" + raise TypeError(msg) + + formatter = fmt.CSVFormatter(self, path_or_buf, line_terminator=line_terminator, sep=sep, encoding=encoding, quoting=quoting, na_rep=na_rep, - float_format=float_format, cols=cols, + float_format=float_format, cols=columns, header=header, index=index, index_label=index_label, mode=mode, chunksize=chunksize, quotechar=quotechar, @@ -1149,9 +1161,9 @@ def to_csv(self, path_or_buf=None, sep=",", na_rep='', float_format=None, return formatter.path_or_buf.getvalue() def to_excel(self, excel_writer, sheet_name='Sheet1', na_rep='', - float_format=None, cols=None, header=True, index=True, + float_format=None, columns=None, header=True, index=True, index_label=None, startrow=0, startcol=0, engine=None, - merge_cells=True, encoding=None): + merge_cells=True, encoding=None, **kwds): """ Write DataFrame to a excel sheet @@ -1189,6 +1201,7 @@ def to_excel(self, excel_writer, sheet_name='Sheet1', na_rep='', encoding: string, default None encoding of the resulting excel file. Only necessary for xlwt, other writers support unicode natively. + cols : kwarg only alias of columns [deprecated] Notes ----- @@ -1202,6 +1215,17 @@ def to_excel(self, excel_writer, sheet_name='Sheet1', na_rep='', >>> writer.save() """ from pandas.io.excel import ExcelWriter + + # Parse old-style keyword argument + cols = kwds.pop('cols', None) + if cols is not None: + warnings.warn("cols is deprecated, use columns", FutureWarning) + if columns is None: + columns = cols + else: + msg = "Can only specify either 'columns' or 'cols'" + raise TypeError(msg) + need_save = False if encoding == None: encoding = 'ascii' @@ -1212,7 +1236,7 @@ def to_excel(self, excel_writer, sheet_name='Sheet1', na_rep='', formatter = fmt.ExcelFormatter(self, na_rep=na_rep, - cols=cols, + cols=columns, header=header, float_format=float_format, index=index, diff --git a/pandas/io/tests/test_excel.py b/pandas/io/tests/test_excel.py index e1d168b66420f..8ba2a5dfc3d9c 100644 --- a/pandas/io/tests/test_excel.py +++ b/pandas/io/tests/test_excel.py @@ -396,6 +396,14 @@ def test_excel_sheet_by_name_raise(self): self.assertRaises(xlrd.XLRDError, xl.parse, '0') + def test_excel_deprecated_options(self): + with ensure_clean(self.ext) as path: + with tm.assert_produces_warning(FutureWarning): + self.frame.to_excel(path, 'test1', cols=['A', 'B']) + + with tm.assert_produces_warning(False): + self.frame.to_excel(path, 'test1', columns=['A', 'B']) + def test_excelwriter_contextmanager(self): _skip_if_no_xlrd() @@ -417,7 +425,7 @@ def test_roundtrip(self): self.frame['A'][:5] = nan self.frame.to_excel(path, 'test1') - self.frame.to_excel(path, 'test1', cols=['A', 'B']) + self.frame.to_excel(path, 'test1', columns=['A', 'B']) self.frame.to_excel(path, 'test1', header=False) self.frame.to_excel(path, 'test1', index=False) @@ -479,7 +487,7 @@ def test_basics_with_nan(self): with ensure_clean(self.ext) as path: self.frame['A'][:5] = nan self.frame.to_excel(path, 'test1') - self.frame.to_excel(path, 'test1', cols=['A', 'B']) + self.frame.to_excel(path, 'test1', columns=['A', 'B']) self.frame.to_excel(path, 'test1', header=False) self.frame.to_excel(path, 'test1', index=False) @@ -537,7 +545,7 @@ def test_sheets(self): self.frame['A'][:5] = nan self.frame.to_excel(path, 'test1') - self.frame.to_excel(path, 'test1', cols=['A', 'B']) + self.frame.to_excel(path, 'test1', columns=['A', 'B']) self.frame.to_excel(path, 'test1', header=False) self.frame.to_excel(path, 'test1', index=False) @@ -562,7 +570,7 @@ def test_colaliases(self): self.frame['A'][:5] = nan self.frame.to_excel(path, 'test1') - self.frame.to_excel(path, 'test1', cols=['A', 'B']) + self.frame.to_excel(path, 'test1', columns=['A', 'B']) self.frame.to_excel(path, 'test1', header=False) self.frame.to_excel(path, 'test1', index=False) @@ -583,7 +591,7 @@ def test_roundtrip_indexlabels(self): self.frame['A'][:5] = nan self.frame.to_excel(path, 'test1') - self.frame.to_excel(path, 'test1', cols=['A', 'B']) + self.frame.to_excel(path, 'test1', columns=['A', 'B']) self.frame.to_excel(path, 'test1', header=False) self.frame.to_excel(path, 'test1', index=False) @@ -630,7 +638,7 @@ def test_roundtrip_indexlabels(self): self.frame.to_excel(path, 'test1', - cols=['A', 'B', 'C', 'D'], + columns=['A', 'B', 'C', 'D'], index=False, merge_cells=self.merge_cells) # take 'A' and 'B' as indexes (same row as cols 'C', 'D') df = self.frame.copy() @@ -733,7 +741,7 @@ def test_to_excel_multiindex(self): with ensure_clean(self.ext) as path: frame.to_excel(path, 'test1', header=False) - frame.to_excel(path, 'test1', cols=['A', 'B']) + frame.to_excel(path, 'test1', columns=['A', 'B']) # round trip frame.to_excel(path, 'test1', merge_cells=self.merge_cells) @@ -1020,7 +1028,7 @@ def test_swapped_columns(self): with ensure_clean(self.ext) as path: write_frame = DataFrame({'A': [1, 1, 1], 'B': [2, 2, 2]}) - write_frame.to_excel(path, 'test1', cols=['B', 'A']) + write_frame.to_excel(path, 'test1', columns=['B', 'A']) read_frame = read_excel(path, 'test1', header=0) diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index 4391de0ebfe58..db8f7bc49ff76 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -5407,6 +5407,13 @@ def test_to_csv_deprecated_options(self): self.tsframe.to_csv(path, nanRep='foo') recons = read_csv(path,index_col=0,parse_dates=[0],na_values=['foo']) assert_frame_equal(self.tsframe, recons) + + with tm.assert_produces_warning(FutureWarning): + self.frame.to_csv(path, cols=['A', 'B']) + + with tm.assert_produces_warning(False): + self.frame.to_csv(path, columns=['A', 'B']) + def test_to_csv_from_csv(self): @@ -5416,7 +5423,7 @@ def test_to_csv_from_csv(self): self.frame['A'][:5] = nan self.frame.to_csv(path) - self.frame.to_csv(path, cols=['A', 'B']) + self.frame.to_csv(path, columns=['A', 'B']) self.frame.to_csv(path, header=False) self.frame.to_csv(path, index=False) @@ -5490,9 +5497,9 @@ def test_to_csv_cols_reordering(self): def _check_df(df,cols=None): with ensure_clean() as path: - df.to_csv(path,cols = cols,engine='python') + df.to_csv(path,columns = cols,engine='python') rs_p = pd.read_csv(path,index_col=0) - df.to_csv(path,cols = cols,chunksize=chunksize) + df.to_csv(path,columns = cols,chunksize=chunksize) rs_c = pd.read_csv(path,index_col=0) if cols: @@ -5518,7 +5525,7 @@ def test_to_csv_new_dupe_cols(self): import pandas as pd def _check_df(df,cols=None): with ensure_clean() as path: - df.to_csv(path,cols = cols,chunksize=chunksize) + df.to_csv(path,columns = cols,chunksize=chunksize) rs_c = pd.read_csv(path,index_col=0) # we wrote them in a different order @@ -5775,7 +5782,7 @@ def test_to_csv_multiindex(self): with ensure_clean(pname) as path: frame.to_csv(path, header=False) - frame.to_csv(path, cols=['A', 'B']) + frame.to_csv(path, columns=['A', 'B']) # round trip frame.to_csv(path) @@ -5893,7 +5900,7 @@ def _make_frame(names=None): # write with cols with assertRaisesRegexp(TypeError, 'cannot specify cols with a MultiIndex'): - df.to_csv(path, tupleize_cols=False, cols=['foo', 'bar']) + df.to_csv(path, tupleize_cols=False, columns=['foo', 'bar']) with ensure_clean(pname) as path: # empty