Skip to content

Commit

Permalink
DEPR: remove auto broadcasting with a time-series, xref pandas-dev#2304
Browse files Browse the repository at this point in the history
  • Loading branch information
jreback committed Aug 23, 2015
1 parent dae0b09 commit 35f1eaf
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 52 deletions.
30 changes: 30 additions & 0 deletions doc/source/whatsnew/v0.17.0.txt
Expand Up @@ -37,6 +37,7 @@ Highlights include:
- Support for ``Series.dt.strftime`` to generate formatted strings for datetime-likes, see :ref:`here <whatsnew_0170.strftime>`
- Development installed versions of pandas will now have ``PEP440`` compliant version strings (:issue:`9518`)
- Support for reading SAS xport files, see :ref:`here <whatsnew_0170.enhancements.sas_xport>`
- Removal of the automatic TimeSeries broadcasting, deprecated since 0.8.0, see :ref:`here <whatsnew_0170.prior_deprecations>`

Check the :ref:`API Changes <whatsnew_0170.api>` and :ref:`deprecations <whatsnew_0170.deprecations>` before updating.

Expand Down Expand Up @@ -673,6 +674,35 @@ Removal of prior version deprecations/changes
- Removal of ``na_last`` parameters from ``Series.order()`` and ``Series.sort()``, in favor of ``na_position``, xref (:issue:`5231`)
- Remove of ``percentile_width`` from ``.describe()``, in favor of ``percentiles``. (:issue:`7088`)
- Removal of ``colSpace`` parameter from ``DataFrame.to_string()``, in favor of ``col_space``, circa 0.8.0 version.
- Removal of automatic time-series broadcasting (:issue:`2304`)

.. ipython :: python

np.random.seed(1234)
df = DataFrame(np.random.randn(5,2),columns=list('AB'),index=date_range('20130101',periods=5))
df

Previously

.. code-block:: python

In [3]: df + df.A
FutureWarning: TimeSeries broadcasting along DataFrame index by default is deprecated.
Please use DataFrame.<op> to explicitly broadcast arithmetic operations along the index

Out[3]:
A B
2013-01-01 0.942870 -0.719541
2013-01-02 2.865414 1.120055
2013-01-03 -1.441177 0.166574
2013-01-04 1.719177 0.223065
2013-01-05 0.031393 -2.226989

Current

.. ipython :: python

df.add(df.A,axis='index')

.. _whatsnew_0170.performance:

Expand Down
11 changes: 1 addition & 10 deletions pandas/core/frame.py
Expand Up @@ -3354,16 +3354,7 @@ def _combine_series_infer(self, other, func, level=None, fill_value=None):
return self._constructor(data=self._series, index=self.index,
columns=self.columns)

# teeny hack because one does DataFrame + TimeSeries all the time
if self.index.is_all_dates and other.index.is_all_dates:
warnings.warn(("TimeSeries broadcasting along DataFrame index "
"by default is deprecated. Please use "
"DataFrame.<op> to explicitly broadcast arithmetic "
"operations along the index"),
FutureWarning)
return self._combine_match_index(other, func, level=level, fill_value=fill_value)
else:
return self._combine_match_columns(other, func, level=level, fill_value=fill_value)
return self._combine_match_columns(other, func, level=level, fill_value=fill_value)

def _combine_match_index(self, other, func, level=None, fill_value=None):
left, right = self.align(other, join='outer', axis=0, level=level, copy=False)
Expand Down
15 changes: 10 additions & 5 deletions pandas/sparse/tests/test_sparse.py
Expand Up @@ -1189,14 +1189,19 @@ def _compare_to_dense(a, b, da, db, op):
frame['A'].reindex(fidx[::2]),
SparseSeries([], index=[])]

for op in ops:
for op in opnames:
_compare_to_dense(frame, frame[::2], frame.to_dense(),
frame[::2].to_dense(), op)
frame[::2].to_dense(), getattr(operator, op))

# 2304, no auto-broadcasting
for i, s in enumerate(series):
f = lambda a, b: getattr(a,op)(b,axis='index')
_compare_to_dense(frame, s, frame.to_dense(),
s.to_dense(), op)
_compare_to_dense(s, frame, s.to_dense(),
frame.to_dense(), op)
s.to_dense(), f)

# rops are not implemented
#_compare_to_dense(s, frame, s.to_dense(),
# frame.to_dense(), f)

# cross-sectional operations
series = [frame.xs(fidx[0]),
Expand Down
67 changes: 34 additions & 33 deletions pandas/tests/test_frame.py
Expand Up @@ -6039,46 +6039,47 @@ def test_combineSeries(self):
#added = self.mixed_int + (100*series).astype('int32')
#_check_mixed_int(added, dtype = dict(A = 'int32', B = 'float64', C = 'int32', D = 'int64'))

# TimeSeries
buf = StringIO()
tmp = sys.stderr
sys.stderr = buf

try:
ts = self.tsframe['A']
added = self.tsframe + ts

for key, col in compat.iteritems(self.tsframe):
result = col + ts
assert_series_equal(added[key], result, check_names=False)
self.assertEqual(added[key].name, key)
if col.name == ts.name:
self.assertEqual(result.name, 'A')
else:
self.assertTrue(result.name is None)
# TimeSeries
ts = self.tsframe['A']

# 10890
# we no longer allow auto timeseries broadcasting
# and require explict broadcasting
added = self.tsframe.add(ts, axis='index')

for key, col in compat.iteritems(self.tsframe):
result = col + ts
assert_series_equal(added[key], result, check_names=False)
self.assertEqual(added[key].name, key)
if col.name == ts.name:
self.assertEqual(result.name, 'A')
else:
self.assertTrue(result.name is None)

smaller_frame = self.tsframe[:-5]
smaller_added = smaller_frame + ts
smaller_frame = self.tsframe[:-5]
smaller_added = smaller_frame.add(ts, axis='index')

self.assertTrue(smaller_added.index.equals(self.tsframe.index))
self.assertTrue(smaller_added.index.equals(self.tsframe.index))

smaller_ts = ts[:-5]
smaller_added2 = self.tsframe + smaller_ts
assert_frame_equal(smaller_added, smaller_added2)
smaller_ts = ts[:-5]
smaller_added2 = self.tsframe.add(smaller_ts, axis='index')
assert_frame_equal(smaller_added, smaller_added2)

# length 0
result = self.tsframe + ts[:0]
# length 0, result is all-nan
result = self.tsframe.add(ts[:0], axis='index')
expected = DataFrame(np.nan,index=self.tsframe.index,columns=self.tsframe.columns)
assert_frame_equal(result, expected)

# Frame is length 0
result = self.tsframe[:0] + ts
self.assertEqual(len(result), 0)
# Frame is all-nan
result = self.tsframe[:0].add(ts, axis='index')
expected = DataFrame(np.nan,index=self.tsframe.index,columns=self.tsframe.columns)
assert_frame_equal(result, expected)

# empty but with non-empty index
frame = self.tsframe[:1].reindex(columns=[])
result = frame * ts
self.assertEqual(len(result), len(ts))
finally:
sys.stderr = tmp
# empty but with non-empty index
frame = self.tsframe[:1].reindex(columns=[])
result = frame.mul(ts,axis='index')
self.assertEqual(len(result), len(ts))

def test_combineFunc(self):
result = self.frame * 2
Expand Down
8 changes: 4 additions & 4 deletions pandas/tests/test_series.py
Expand Up @@ -4515,10 +4515,10 @@ def test_operators_frame(self):
# rpow does not work with DataFrame
df = DataFrame({'A': self.ts})

tm.assert_almost_equal(self.ts + self.ts, (self.ts + df)['A'])
tm.assert_almost_equal(self.ts ** self.ts, (self.ts ** df)['A'])
tm.assert_almost_equal(self.ts < self.ts, (self.ts < df)['A'])
tm.assert_almost_equal(self.ts / self.ts, (self.ts / df)['A'])
tm.assert_almost_equal(self.ts + self.ts, self.ts + df['A'])
tm.assert_almost_equal(self.ts ** self.ts, self.ts ** df['A'])
tm.assert_almost_equal(self.ts < self.ts, self.ts < df['A'])
tm.assert_almost_equal(self.ts / self.ts, self.ts / df['A'])

def test_operators_combine(self):
def _check_fill(meth, op, a, b, fill_value=0):
Expand Down

0 comments on commit 35f1eaf

Please sign in to comment.