Skip to content

Commit 28f8097

Browse files
committed
DEPR: Deprecate from_csv in favor of read_csv
Closes gh-4191.
1 parent 3ba2cff commit 28f8097

File tree

5 files changed

+120
-57
lines changed

5 files changed

+120
-57
lines changed

doc/source/whatsnew/v0.21.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,7 @@ Other API Changes
715715
Deprecations
716716
~~~~~~~~~~~~
717717

718+
- :meth:`DataFrame.from_csv` and :meth:`Series.from_csv` have been deprecated in favor of :func:`read_csv()` (:issue:`4191`)
718719
- :func:`read_excel()` has deprecated ``sheetname`` in favor of ``sheet_name`` for consistency with ``.to_excel()`` (:issue:`10559`).
719720
- :func:`read_excel()` has deprecated ``parse_cols`` in favor of ``usecols`` for consistency with :func:`read_csv` (:issue:`4988`)
720721
- :func:`read_csv()` has deprecated the ``tupleize_cols`` argument. Column tuples will always be converted to a ``MultiIndex`` (:issue:`17060`)

pandas/core/frame.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ def _constructor(self):
298298

299299
_constructor_sliced = Series
300300
_deprecations = NDFrame._deprecations | frozenset(
301-
['sortlevel', 'get_value', 'set_value'])
301+
['sortlevel', 'get_value', 'set_value', 'from_csv'])
302302

303303
@property
304304
def _constructor_expanddim(self):
@@ -1291,7 +1291,7 @@ def from_csv(cls, path, header=0, sep=',', index_col=0, parse_dates=True,
12911291
encoding=None, tupleize_cols=False,
12921292
infer_datetime_format=False):
12931293
"""
1294-
Read CSV file (DISCOURAGED, please use :func:`pandas.read_csv`
1294+
Read CSV file (DEPRECATED, please use :func:`pandas.read_csv`
12951295
instead).
12961296
12971297
It is preferable to use the more powerful :func:`pandas.read_csv`
@@ -1339,6 +1339,13 @@ def from_csv(cls, path, header=0, sep=',', index_col=0, parse_dates=True,
13391339
y : DataFrame
13401340
13411341
"""
1342+
1343+
warnings.warn("from_csv is deprecated. Please use read_csv(...) "
1344+
"instead. Note that some of the default arguments are "
1345+
"different, so please refer to the documentation "
1346+
"for from_csv when changing your function calls",
1347+
FutureWarning, stacklevel=2)
1348+
13421349
from pandas.io.parsers import read_table
13431350
return read_table(path, header=header, sep=sep,
13441351
parse_dates=parse_dates, index_col=index_col,

pandas/core/series.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ class Series(base.IndexOpsMixin, generic.NDFrame):
147147
_metadata = ['name']
148148
_accessors = frozenset(['dt', 'cat', 'str'])
149149
_deprecations = generic.NDFrame._deprecations | frozenset(
150-
['sortlevel', 'reshape', 'get_value', 'set_value'])
150+
['sortlevel', 'reshape', 'get_value', 'set_value', 'from_csv'])
151151
_allow_index_ops = True
152152

153153
def __init__(self, data=None, index=None, dtype=None, name=None,
@@ -2688,7 +2688,7 @@ def between(self, left, right, inclusive=True):
26882688
def from_csv(cls, path, sep=',', parse_dates=True, header=None,
26892689
index_col=0, encoding=None, infer_datetime_format=False):
26902690
"""
2691-
Read CSV file (DISCOURAGED, please use :func:`pandas.read_csv`
2691+
Read CSV file (DEPRECATED, please use :func:`pandas.read_csv`
26922692
instead).
26932693
26942694
It is preferable to use the more powerful :func:`pandas.read_csv`
@@ -2736,6 +2736,9 @@ def from_csv(cls, path, sep=',', parse_dates=True, header=None,
27362736
-------
27372737
y : Series
27382738
"""
2739+
2740+
# We're calling `DataFrame.from_csv` in the implementation,
2741+
# which will propagate a warning regarding `from_csv` deprecation.
27392742
from pandas.core.frame import DataFrame
27402743
df = DataFrame.from_csv(path, header=header, index_col=index_col,
27412744
sep=sep, parse_dates=parse_dates,

pandas/tests/frame/test_to_csv.py

+53-30
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@
3131

3232
class TestDataFrameToCSV(TestData):
3333

34+
def read_csv(self, path, **kwargs):
35+
params = dict(index_col=0, parse_dates=True)
36+
params.update(**kwargs)
37+
38+
return pd.read_csv(path, **params)
39+
40+
def test_from_csv_deprecation(self):
41+
# see gh-17812
42+
with ensure_clean('__tmp_from_csv_deprecation__') as path:
43+
self.tsframe.to_csv(path)
44+
45+
with tm.assert_produces_warning(FutureWarning):
46+
depr_recons = DataFrame.from_csv(path)
47+
assert_frame_equal(self.tsframe, depr_recons)
48+
3449
def test_to_csv_from_csv1(self):
3550

3651
with ensure_clean('__tmp_to_csv_from_csv1__') as path:
@@ -43,24 +58,25 @@ def test_to_csv_from_csv1(self):
4358

4459
# test roundtrip
4560
self.tsframe.to_csv(path)
46-
recons = DataFrame.from_csv(path)
47-
61+
recons = self.read_csv(path)
4862
assert_frame_equal(self.tsframe, recons)
4963

5064
self.tsframe.to_csv(path, index_label='index')
51-
recons = DataFrame.from_csv(path, index_col=None)
65+
recons = self.read_csv(path, index_col=None)
66+
5267
assert(len(recons.columns) == len(self.tsframe.columns) + 1)
5368

5469
# no index
5570
self.tsframe.to_csv(path, index=False)
56-
recons = DataFrame.from_csv(path, index_col=None)
71+
recons = self.read_csv(path, index_col=None)
5772
assert_almost_equal(self.tsframe.values, recons.values)
5873

5974
# corner case
6075
dm = DataFrame({'s1': Series(lrange(3), lrange(3)),
6176
's2': Series(lrange(2), lrange(2))})
6277
dm.to_csv(path)
63-
recons = DataFrame.from_csv(path)
78+
79+
recons = self.read_csv(path)
6480
assert_frame_equal(dm, recons)
6581

6682
def test_to_csv_from_csv2(self):
@@ -71,27 +87,26 @@ def test_to_csv_from_csv2(self):
7187
df = DataFrame(np.random.randn(3, 3), index=['a', 'a', 'b'],
7288
columns=['x', 'y', 'z'])
7389
df.to_csv(path)
74-
result = DataFrame.from_csv(path)
90+
result = self.read_csv(path)
7591
assert_frame_equal(result, df)
7692

7793
midx = MultiIndex.from_tuples(
7894
[('A', 1, 2), ('A', 1, 2), ('B', 1, 2)])
7995
df = DataFrame(np.random.randn(3, 3), index=midx,
8096
columns=['x', 'y', 'z'])
97+
8198
df.to_csv(path)
82-
result = DataFrame.from_csv(path, index_col=[0, 1, 2],
83-
parse_dates=False)
84-
# TODO from_csv names index ['Unnamed: 1', 'Unnamed: 2'] should it
85-
# ?
99+
result = self.read_csv(path, index_col=[0, 1, 2],
100+
parse_dates=False)
86101
assert_frame_equal(result, df, check_names=False)
87102

88103
# column aliases
89104
col_aliases = Index(['AA', 'X', 'Y', 'Z'])
90105
self.frame2.to_csv(path, header=col_aliases)
91-
rs = DataFrame.from_csv(path)
106+
107+
rs = self.read_csv(path)
92108
xp = self.frame2.copy()
93109
xp.columns = col_aliases
94-
95110
assert_frame_equal(xp, rs)
96111

97112
pytest.raises(ValueError, self.frame2.to_csv, path,
@@ -231,8 +246,9 @@ def make_dtnat_arr(n, nnat=None):
231246
with ensure_clean('1.csv') as pth:
232247
df = DataFrame(dict(a=s1, b=s2))
233248
df.to_csv(pth, chunksize=chunksize)
234-
recons = DataFrame.from_csv(pth)._convert(datetime=True,
235-
coerce=True)
249+
250+
recons = self.read_csv(pth)._convert(datetime=True,
251+
coerce=True)
236252
assert_frame_equal(df, recons, check_names=False,
237253
check_less_precise=True)
238254

@@ -247,16 +263,17 @@ def _do_test(df, r_dtype=None, c_dtype=None,
247263
if rnlvl is not None:
248264
kwargs['index_col'] = lrange(rnlvl)
249265
kwargs['header'] = lrange(cnlvl)
266+
250267
with ensure_clean('__tmp_to_csv_moar__') as path:
251268
df.to_csv(path, encoding='utf8',
252269
chunksize=chunksize, tupleize_cols=False)
253-
recons = DataFrame.from_csv(
254-
path, tupleize_cols=False, **kwargs)
270+
recons = self.read_csv(path, tupleize_cols=False, **kwargs)
255271
else:
256272
kwargs['header'] = 0
273+
257274
with ensure_clean('__tmp_to_csv_moar__') as path:
258275
df.to_csv(path, encoding='utf8', chunksize=chunksize)
259-
recons = DataFrame.from_csv(path, **kwargs)
276+
recons = self.read_csv(path, **kwargs)
260277

261278
def _to_uni(x):
262279
if not isinstance(x, compat.text_type):
@@ -398,7 +415,7 @@ def test_to_csv_from_csv_w_some_infs(self):
398415

399416
with ensure_clean() as path:
400417
self.frame.to_csv(path)
401-
recons = DataFrame.from_csv(path)
418+
recons = self.read_csv(path)
402419

403420
# TODO to_csv drops column name
404421
assert_frame_equal(self.frame, recons, check_names=False)
@@ -413,7 +430,7 @@ def test_to_csv_from_csv_w_all_infs(self):
413430

414431
with ensure_clean() as path:
415432
self.frame.to_csv(path)
416-
recons = DataFrame.from_csv(path)
433+
recons = self.read_csv(path)
417434

418435
# TODO to_csv drops column name
419436
assert_frame_equal(self.frame, recons, check_names=False)
@@ -448,11 +465,13 @@ def test_to_csv_headers(self):
448465
to_df = DataFrame([[1, 2], [3, 4]], columns=['X', 'Y'])
449466
with ensure_clean('__tmp_to_csv_headers__') as path:
450467
from_df.to_csv(path, header=['X', 'Y'])
451-
recons = DataFrame.from_csv(path)
468+
recons = self.read_csv(path)
469+
452470
assert_frame_equal(to_df, recons)
453471

454472
from_df.to_csv(path, index=False, header=['X', 'Y'])
455-
recons = DataFrame.from_csv(path)
473+
recons = self.read_csv(path)
474+
456475
recons.reset_index(inplace=True)
457476
assert_frame_equal(to_df, recons)
458477

@@ -471,13 +490,15 @@ def test_to_csv_multiindex(self):
471490

472491
# round trip
473492
frame.to_csv(path)
474-
df = DataFrame.from_csv(path, index_col=[0, 1], parse_dates=False)
493+
494+
df = self.read_csv(path, index_col=[0, 1],
495+
parse_dates=False)
475496

476497
# TODO to_csv drops column name
477498
assert_frame_equal(frame, df, check_names=False)
478499
assert frame.index.names == df.index.names
479500

480-
# needed if setUP becomes a classmethod
501+
# needed if setUp becomes a class method
481502
self.frame.index = old_index
482503

483504
# try multiindex with dates
@@ -487,21 +508,22 @@ def test_to_csv_multiindex(self):
487508
tsframe.index = MultiIndex.from_arrays(new_index)
488509

489510
tsframe.to_csv(path, index_label=['time', 'foo'])
490-
recons = DataFrame.from_csv(path, index_col=[0, 1])
511+
recons = self.read_csv(path, index_col=[0, 1])
512+
491513
# TODO to_csv drops column name
492514
assert_frame_equal(tsframe, recons, check_names=False)
493515

494516
# do not load index
495517
tsframe.to_csv(path)
496-
recons = DataFrame.from_csv(path, index_col=None)
518+
recons = self.read_csv(path, index_col=None)
497519
assert len(recons.columns) == len(tsframe.columns) + 2
498520

499521
# no index
500522
tsframe.to_csv(path, index=False)
501-
recons = DataFrame.from_csv(path, index_col=None)
523+
recons = self.read_csv(path, index_col=None)
502524
assert_almost_equal(recons.values, self.tsframe.values)
503525

504-
# needed if setUP becomes classmethod
526+
# needed if setUp becomes class method
505527
self.tsframe.index = old_index
506528

507529
with ensure_clean('__tmp_to_csv_multiindex__') as path:
@@ -606,7 +628,8 @@ def _make_frame(names=None):
606628
with ensure_clean('__tmp_to_csv_multiindex__') as path:
607629
# empty
608630
tsframe[:0].to_csv(path)
609-
recons = DataFrame.from_csv(path)
631+
recons = self.read_csv(path)
632+
610633
exp = tsframe[:0]
611634
exp.index = []
612635

@@ -631,7 +654,7 @@ def test_to_csv_withcommas(self):
631654

632655
with ensure_clean('__tmp_to_csv_withcommas__.csv') as path:
633656
df.to_csv(path)
634-
df2 = DataFrame.from_csv(path)
657+
df2 = self.read_csv(path)
635658
assert_frame_equal(df2, df)
636659

637660
def test_to_csv_mixed(self):
@@ -746,7 +769,7 @@ def test_to_csv_wide_frame_formatting(self):
746769

747770
def test_to_csv_bug(self):
748771
f1 = StringIO('a,1.0\nb,2.0')
749-
df = DataFrame.from_csv(f1, header=None)
772+
df = self.read_csv(f1, header=None)
750773
newdf = DataFrame({'t': df[df.columns[0]]})
751774

752775
with ensure_clean() as path:

0 commit comments

Comments
 (0)