Skip to content

Commit 3cf0e69

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

File tree

5 files changed

+121
-57
lines changed

5 files changed

+121
-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

+54-30
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,22 @@
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+
check_stacklevel=False):
47+
depr_recons = DataFrame.from_csv(path)
48+
assert_frame_equal(self.tsframe, depr_recons)
49+
3450
def test_to_csv_from_csv1(self):
3551

3652
with ensure_clean('__tmp_to_csv_from_csv1__') as path:
@@ -43,24 +59,25 @@ def test_to_csv_from_csv1(self):
4359

4460
# test roundtrip
4561
self.tsframe.to_csv(path)
46-
recons = DataFrame.from_csv(path)
47-
62+
recons = self.read_csv(path)
4863
assert_frame_equal(self.tsframe, recons)
4964

5065
self.tsframe.to_csv(path, index_label='index')
51-
recons = DataFrame.from_csv(path, index_col=None)
66+
recons = self.read_csv(path, index_col=None)
67+
5268
assert(len(recons.columns) == len(self.tsframe.columns) + 1)
5369

5470
# no index
5571
self.tsframe.to_csv(path, index=False)
56-
recons = DataFrame.from_csv(path, index_col=None)
72+
recons = self.read_csv(path, index_col=None)
5773
assert_almost_equal(self.tsframe.values, recons.values)
5874

5975
# corner case
6076
dm = DataFrame({'s1': Series(lrange(3), lrange(3)),
6177
's2': Series(lrange(2), lrange(2))})
6278
dm.to_csv(path)
63-
recons = DataFrame.from_csv(path)
79+
80+
recons = self.read_csv(path)
6481
assert_frame_equal(dm, recons)
6582

6683
def test_to_csv_from_csv2(self):
@@ -71,27 +88,26 @@ def test_to_csv_from_csv2(self):
7188
df = DataFrame(np.random.randn(3, 3), index=['a', 'a', 'b'],
7289
columns=['x', 'y', 'z'])
7390
df.to_csv(path)
74-
result = DataFrame.from_csv(path)
91+
result = self.read_csv(path)
7592
assert_frame_equal(result, df)
7693

7794
midx = MultiIndex.from_tuples(
7895
[('A', 1, 2), ('A', 1, 2), ('B', 1, 2)])
7996
df = DataFrame(np.random.randn(3, 3), index=midx,
8097
columns=['x', 'y', 'z'])
98+
8199
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-
# ?
100+
result = self.read_csv(path, index_col=[0, 1, 2],
101+
parse_dates=False)
86102
assert_frame_equal(result, df, check_names=False)
87103

88104
# column aliases
89105
col_aliases = Index(['AA', 'X', 'Y', 'Z'])
90106
self.frame2.to_csv(path, header=col_aliases)
91-
rs = DataFrame.from_csv(path)
107+
108+
rs = self.read_csv(path)
92109
xp = self.frame2.copy()
93110
xp.columns = col_aliases
94-
95111
assert_frame_equal(xp, rs)
96112

97113
pytest.raises(ValueError, self.frame2.to_csv, path,
@@ -231,8 +247,9 @@ def make_dtnat_arr(n, nnat=None):
231247
with ensure_clean('1.csv') as pth:
232248
df = DataFrame(dict(a=s1, b=s2))
233249
df.to_csv(pth, chunksize=chunksize)
234-
recons = DataFrame.from_csv(pth)._convert(datetime=True,
235-
coerce=True)
250+
251+
recons = self.read_csv(pth)._convert(datetime=True,
252+
coerce=True)
236253
assert_frame_equal(df, recons, check_names=False,
237254
check_less_precise=True)
238255

@@ -247,16 +264,17 @@ def _do_test(df, r_dtype=None, c_dtype=None,
247264
if rnlvl is not None:
248265
kwargs['index_col'] = lrange(rnlvl)
249266
kwargs['header'] = lrange(cnlvl)
267+
250268
with ensure_clean('__tmp_to_csv_moar__') as path:
251269
df.to_csv(path, encoding='utf8',
252270
chunksize=chunksize, tupleize_cols=False)
253-
recons = DataFrame.from_csv(
254-
path, tupleize_cols=False, **kwargs)
271+
recons = self.read_csv(path, tupleize_cols=False, **kwargs)
255272
else:
256273
kwargs['header'] = 0
274+
257275
with ensure_clean('__tmp_to_csv_moar__') as path:
258276
df.to_csv(path, encoding='utf8', chunksize=chunksize)
259-
recons = DataFrame.from_csv(path, **kwargs)
277+
recons = self.read_csv(path, **kwargs)
260278

261279
def _to_uni(x):
262280
if not isinstance(x, compat.text_type):
@@ -398,7 +416,7 @@ def test_to_csv_from_csv_w_some_infs(self):
398416

399417
with ensure_clean() as path:
400418
self.frame.to_csv(path)
401-
recons = DataFrame.from_csv(path)
419+
recons = self.read_csv(path)
402420

403421
# TODO to_csv drops column name
404422
assert_frame_equal(self.frame, recons, check_names=False)
@@ -413,7 +431,7 @@ def test_to_csv_from_csv_w_all_infs(self):
413431

414432
with ensure_clean() as path:
415433
self.frame.to_csv(path)
416-
recons = DataFrame.from_csv(path)
434+
recons = self.read_csv(path)
417435

418436
# TODO to_csv drops column name
419437
assert_frame_equal(self.frame, recons, check_names=False)
@@ -448,11 +466,13 @@ def test_to_csv_headers(self):
448466
to_df = DataFrame([[1, 2], [3, 4]], columns=['X', 'Y'])
449467
with ensure_clean('__tmp_to_csv_headers__') as path:
450468
from_df.to_csv(path, header=['X', 'Y'])
451-
recons = DataFrame.from_csv(path)
469+
recons = self.read_csv(path)
470+
452471
assert_frame_equal(to_df, recons)
453472

454473
from_df.to_csv(path, index=False, header=['X', 'Y'])
455-
recons = DataFrame.from_csv(path)
474+
recons = self.read_csv(path)
475+
456476
recons.reset_index(inplace=True)
457477
assert_frame_equal(to_df, recons)
458478

@@ -471,13 +491,15 @@ def test_to_csv_multiindex(self):
471491

472492
# round trip
473493
frame.to_csv(path)
474-
df = DataFrame.from_csv(path, index_col=[0, 1], parse_dates=False)
494+
495+
df = self.read_csv(path, index_col=[0, 1],
496+
parse_dates=False)
475497

476498
# TODO to_csv drops column name
477499
assert_frame_equal(frame, df, check_names=False)
478500
assert frame.index.names == df.index.names
479501

480-
# needed if setUP becomes a classmethod
502+
# needed if setUp becomes a class method
481503
self.frame.index = old_index
482504

483505
# try multiindex with dates
@@ -487,21 +509,22 @@ def test_to_csv_multiindex(self):
487509
tsframe.index = MultiIndex.from_arrays(new_index)
488510

489511
tsframe.to_csv(path, index_label=['time', 'foo'])
490-
recons = DataFrame.from_csv(path, index_col=[0, 1])
512+
recons = self.read_csv(path, index_col=[0, 1])
513+
491514
# TODO to_csv drops column name
492515
assert_frame_equal(tsframe, recons, check_names=False)
493516

494517
# do not load index
495518
tsframe.to_csv(path)
496-
recons = DataFrame.from_csv(path, index_col=None)
519+
recons = self.read_csv(path, index_col=None)
497520
assert len(recons.columns) == len(tsframe.columns) + 2
498521

499522
# no index
500523
tsframe.to_csv(path, index=False)
501-
recons = DataFrame.from_csv(path, index_col=None)
524+
recons = self.read_csv(path, index_col=None)
502525
assert_almost_equal(recons.values, self.tsframe.values)
503526

504-
# needed if setUP becomes classmethod
527+
# needed if setUp becomes class method
505528
self.tsframe.index = old_index
506529

507530
with ensure_clean('__tmp_to_csv_multiindex__') as path:
@@ -606,7 +629,8 @@ def _make_frame(names=None):
606629
with ensure_clean('__tmp_to_csv_multiindex__') as path:
607630
# empty
608631
tsframe[:0].to_csv(path)
609-
recons = DataFrame.from_csv(path)
632+
recons = self.read_csv(path)
633+
610634
exp = tsframe[:0]
611635
exp.index = []
612636

@@ -631,7 +655,7 @@ def test_to_csv_withcommas(self):
631655

632656
with ensure_clean('__tmp_to_csv_withcommas__.csv') as path:
633657
df.to_csv(path)
634-
df2 = DataFrame.from_csv(path)
658+
df2 = self.read_csv(path)
635659
assert_frame_equal(df2, df)
636660

637661
def test_to_csv_mixed(self):
@@ -746,7 +770,7 @@ def test_to_csv_wide_frame_formatting(self):
746770

747771
def test_to_csv_bug(self):
748772
f1 = StringIO('a,1.0\nb,2.0')
749-
df = DataFrame.from_csv(f1, header=None)
773+
df = self.read_csv(f1, header=None)
750774
newdf = DataFrame({'t': df[df.columns[0]]})
751775

752776
with ensure_clean() as path:

0 commit comments

Comments
 (0)