Skip to content

Commit 4395a8c

Browse files
jbrockmendeljreback
authored andcommitted
diff reduction for 24024 (#24543)
1 parent 179822a commit 4395a8c

File tree

11 files changed

+70
-51
lines changed

11 files changed

+70
-51
lines changed

pandas/core/arrays/datetimes.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
is_extension_type, is_float_dtype, is_int64_dtype, is_object_dtype,
2020
is_period_dtype, is_string_dtype, is_timedelta64_dtype, pandas_dtype)
2121
from pandas.core.dtypes.dtypes import DatetimeTZDtype
22-
from pandas.core.dtypes.generic import ABCIndexClass, ABCSeries
22+
from pandas.core.dtypes.generic import ABCIndexClass, ABCPandasArray, ABCSeries
2323
from pandas.core.dtypes.missing import isna
2424

2525
from pandas.core import ops
@@ -224,7 +224,7 @@ def _simple_new(cls, values, freq=None, tz=None):
224224
# for compat with datetime/timedelta/period shared methods,
225225
# we can sometimes get here with int64 values. These represent
226226
# nanosecond UTC (or tz-naive) unix timestamps
227-
values = values.view('M8[ns]')
227+
values = values.view(_NS_DTYPE)
228228

229229
assert values.dtype == 'M8[ns]', values.dtype
230230

@@ -417,7 +417,7 @@ def tz(self):
417417
Returns None when the array is tz-naive.
418418
"""
419419
# GH 18595
420-
return getattr(self._dtype, "tz", None)
420+
return getattr(self.dtype, "tz", None)
421421

422422
@tz.setter
423423
def tz(self, value):
@@ -517,10 +517,6 @@ def astype(self, dtype, copy=True):
517517
# ----------------------------------------------------------------
518518
# ExtensionArray Interface
519519

520-
@property
521-
def _ndarray_values(self):
522-
return self._data
523-
524520
@Appender(dtl.DatetimeLikeArrayMixin._validate_fill_value.__doc__)
525521
def _validate_fill_value(self, fill_value):
526522
if isna(fill_value):
@@ -1568,6 +1564,8 @@ def sequence_to_dt64ns(data, dtype=None, copy=False,
15681564
copy = False
15691565
elif isinstance(data, ABCSeries):
15701566
data = data._values
1567+
if isinstance(data, ABCPandasArray):
1568+
data = data.to_numpy()
15711569

15721570
if hasattr(data, "freq"):
15731571
# i.e. DatetimeArray/Index

pandas/core/arrays/period.py

-6
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,6 @@ def _check_compatible_with(self, other):
269269
def dtype(self):
270270
return self._dtype
271271

272-
@property
273-
def _ndarray_values(self):
274-
# Ordinals
275-
return self._data
276-
277272
@property
278273
def freq(self):
279274
"""
@@ -475,7 +470,6 @@ def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs):
475470
"""
476471
actually format my specific types
477472
"""
478-
# TODO(DatetimeArray): remove
479473
values = self.astype(object)
480474

481475
if date_format:

pandas/core/arrays/timedeltas.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,9 @@ def _addsub_offset_array(self, other, op):
369369
# TimedeltaIndex can only operate with a subset of DateOffset
370370
# subclasses. Incompatible classes will raise AttributeError,
371371
# which we re-raise as TypeError
372-
return dtl.DatetimeLikeArrayMixin._addsub_offset_array(self, other,
373-
op)
372+
return super(TimedeltaArrayMixin, self)._addsub_offset_array(
373+
other, op
374+
)
374375
except AttributeError:
375376
raise TypeError("Cannot add/subtract non-tick DateOffset to {cls}"
376377
.format(cls=type(self).__name__))

pandas/core/indexes/datetimelike.py

+21
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class DatetimeIndexOpsMixin(ExtensionOpsMixin):
5555
"""
5656
common ops mixin to support a unified interface datetimelike Index
5757
"""
58+
_data = None # type: DatetimeLikeArrayMixin
5859

5960
# DatetimeLikeArrayMixin assumes subclasses are mutable, so these are
6061
# properties there. They can be made into cache_readonly for Index
@@ -72,6 +73,9 @@ class DatetimeIndexOpsMixin(ExtensionOpsMixin):
7273

7374
@property
7475
def freq(self):
76+
"""
77+
Return the frequency object if it is set, otherwise None.
78+
"""
7579
return self._eadata.freq
7680

7781
@freq.setter
@@ -81,6 +85,9 @@ def freq(self, value):
8185

8286
@property
8387
def freqstr(self):
88+
"""
89+
Return the frequency object as a string if it is set, otherwise None.
90+
"""
8491
return self._eadata.freqstr
8592

8693
def unique(self, level=None):
@@ -111,6 +118,20 @@ def wrapper(self, other):
111118
def _ndarray_values(self):
112119
return self._eadata._ndarray_values
113120

121+
# ------------------------------------------------------------------------
122+
# Abstract data attributes
123+
124+
@property
125+
def values(self):
126+
# type: () -> np.ndarray
127+
# Note: PeriodArray overrides this to return an ndarray of objects.
128+
return self._eadata._data
129+
130+
@property
131+
@Appender(DatetimeLikeArrayMixin.asi8.__doc__)
132+
def asi8(self):
133+
return self._eadata.asi8
134+
114135
# ------------------------------------------------------------------------
115136

116137
def equals(self, other):

pandas/core/indexes/datetimes.py

-1
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,6 @@ def _simple_new(cls, values, name=None, freq=None, tz=None, dtype=None):
330330
result._eadata = dtarr
331331
result.name = name
332332
# For groupby perf. See note in indexes/base about _index_data
333-
# TODO: make sure this is updated correctly if edited
334333
result._index_data = result._data
335334
result._reset_identity()
336335
return result

pandas/core/indexes/period.py

+5-16
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
from pandas.core import common as com
1919
from pandas.core.accessor import delegate_names
2020
from pandas.core.algorithms import unique1d
21-
from pandas.core.arrays.datetimelike import DatelikeOps
2221
from pandas.core.arrays.period import (
2322
PeriodArray, period_array, validate_dtype_freq)
2423
from pandas.core.base import _shared_docs
@@ -70,9 +69,9 @@ class PeriodDelegateMixin(DatetimelikeDelegateMixin):
7069
typ='property')
7170
@delegate_names(PeriodArray,
7271
PeriodDelegateMixin._delegated_methods,
73-
typ="method")
74-
class PeriodIndex(DatelikeOps, DatetimeIndexOpsMixin, Int64Index,
75-
PeriodDelegateMixin):
72+
typ="method",
73+
overwrite=True)
74+
class PeriodIndex(DatetimeIndexOpsMixin, Int64Index, PeriodDelegateMixin):
7675
"""
7776
Immutable ndarray holding ordinal values indicating regular periods in
7877
time such as particular years, quarters, months, etc.
@@ -291,20 +290,15 @@ def _eadata(self):
291290
def values(self):
292291
return np.asarray(self)
293292

294-
@property
295-
def _values(self):
296-
return self._data
297-
298293
@property
299294
def freq(self):
300-
# TODO(DatetimeArray): remove
301-
# Can't simply use delegate_names since our base class is defining
302-
# freq
303295
return self._data.freq
304296

305297
@freq.setter
306298
def freq(self, value):
307299
value = Period._maybe_convert_freq(value)
300+
# TODO: When this deprecation is enforced, PeriodIndex.freq can
301+
# be removed entirely, and we'll just inherit.
308302
msg = ('Setting {cls}.freq has been deprecated and will be '
309303
'removed in a future version; use {cls}.asfreq instead. '
310304
'The {cls}.freq setter is not guaranteed to work.')
@@ -897,11 +891,6 @@ def flags(self):
897891
FutureWarning, stacklevel=2)
898892
return self._ndarray_values.flags
899893

900-
@property
901-
def asi8(self):
902-
# TODO(DatetimeArray): remove
903-
return self.view('i8')
904-
905894
def item(self):
906895
"""
907896
return the first element of the underlying data as a python

pandas/core/indexes/timedeltas.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ class TimedeltaDelegateMixin(DatetimelikeDelegateMixin):
7070
@delegate_names(TimedeltaArray,
7171
TimedeltaDelegateMixin._delegated_methods,
7272
typ="method", overwrite=False)
73-
class TimedeltaIndex(DatetimeIndexOpsMixin,
74-
dtl.TimelikeOps, Int64Index, TimedeltaDelegateMixin):
73+
class TimedeltaIndex(DatetimeIndexOpsMixin, dtl.TimelikeOps, Int64Index,
74+
TimedeltaDelegateMixin):
7575
"""
7676
Immutable ndarray of timedelta64 data, represented internally as int64, and
7777
which can be boxed to timedelta objects
@@ -238,7 +238,6 @@ def _simple_new(cls, values, name=None, freq=None, dtype=_TD_DTYPE):
238238
result._eadata = tdarr
239239
result.name = name
240240
# For groupby perf. See note in indexes/base about _index_data
241-
# TODO: make sure this is updated correctly if edited
242241
result._index_data = tdarr._data
243242

244243
result._reset_identity()

pandas/core/internals/blocks.py

+15-10
Original file line numberDiff line numberDiff line change
@@ -2165,7 +2165,7 @@ def should_store(self, value):
21652165

21662166

21672167
class DatetimeLikeBlockMixin(object):
2168-
"""Mixin class for DatetimeBlock and DatetimeTZBlock."""
2168+
"""Mixin class for DatetimeBlock, DatetimeTZBlock, and TimedeltaBlock."""
21692169

21702170
@property
21712171
def _holder(self):
@@ -2857,15 +2857,17 @@ def to_native_types(self, slicer=None, na_rep=None, date_format=None,
28572857
""" convert to our native types format, slicing if desired """
28582858

28592859
values = self.values
2860+
i8values = self.values.view('i8')
2861+
28602862
if slicer is not None:
2861-
values = values[..., slicer]
2863+
i8values = i8values[..., slicer]
28622864

28632865
from pandas.io.formats.format import _get_format_datetime64_from_values
28642866
format = _get_format_datetime64_from_values(values, date_format)
28652867

28662868
result = tslib.format_array_from_datetime(
2867-
values.view('i8').ravel(), tz=getattr(self.values, 'tz', None),
2868-
format=format, na_rep=na_rep).reshape(values.shape)
2869+
i8values.ravel(), tz=getattr(self.values, 'tz', None),
2870+
format=format, na_rep=na_rep).reshape(i8values.shape)
28692871
return np.atleast_2d(result)
28702872

28712873
def should_store(self, value):
@@ -3115,8 +3117,16 @@ def get_block_type(values, dtype=None):
31153117
dtype = dtype or values.dtype
31163118
vtype = dtype.type
31173119

3118-
if is_categorical(values):
3120+
if is_sparse(dtype):
3121+
# Need this first(ish) so that Sparse[datetime] is sparse
3122+
cls = ExtensionBlock
3123+
elif is_categorical(values):
31193124
cls = CategoricalBlock
3125+
elif issubclass(vtype, np.datetime64):
3126+
assert not is_datetime64tz_dtype(values)
3127+
cls = DatetimeBlock
3128+
elif is_datetime64tz_dtype(values):
3129+
cls = DatetimeTZBlock
31203130
elif is_interval_dtype(dtype) or is_period_dtype(dtype):
31213131
cls = ObjectValuesExtensionBlock
31223132
elif is_extension_array_dtype(values):
@@ -3128,11 +3138,6 @@ def get_block_type(values, dtype=None):
31283138
cls = TimeDeltaBlock
31293139
elif issubclass(vtype, np.complexfloating):
31303140
cls = ComplexBlock
3131-
elif issubclass(vtype, np.datetime64):
3132-
assert not is_datetime64tz_dtype(values)
3133-
cls = DatetimeBlock
3134-
elif is_datetime64tz_dtype(values):
3135-
cls = DatetimeTZBlock
31363141
elif issubclass(vtype, np.integer):
31373142
cls = IntBlock
31383143
elif dtype == np.bool_:

pandas/core/ops.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -1539,17 +1539,20 @@ def wrapper(left, right):
15391539
raise TypeError("{typ} cannot perform the operation "
15401540
"{op}".format(typ=type(left).__name__, op=str_rep))
15411541

1542-
elif (is_extension_array_dtype(left) or
1543-
(is_extension_array_dtype(right) and not is_scalar(right))):
1544-
# GH#22378 disallow scalar to exclude e.g. "category", "Int64"
1545-
return dispatch_to_extension_op(op, left, right)
1546-
15471542
elif is_datetime64_dtype(left) or is_datetime64tz_dtype(left):
1543+
# Give dispatch_to_index_op a chance for tests like
1544+
# test_dt64_series_add_intlike, which the index dispatching handles
1545+
# specifically.
15481546
result = dispatch_to_index_op(op, left, right, pd.DatetimeIndex)
15491547
return construct_result(left, result,
15501548
index=left.index, name=res_name,
15511549
dtype=result.dtype)
15521550

1551+
elif (is_extension_array_dtype(left) or
1552+
(is_extension_array_dtype(right) and not is_scalar(right))):
1553+
# GH#22378 disallow scalar to exclude e.g. "category", "Int64"
1554+
return dispatch_to_extension_op(op, left, right)
1555+
15531556
elif is_timedelta64_dtype(left):
15541557
result = dispatch_to_index_op(op, left, right, pd.TimedeltaIndex)
15551558
return construct_result(left, result,

pandas/tests/arrays/test_datetimes.py

+8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@
1616

1717

1818
class TestDatetimeArrayConstructor(object):
19+
def test_from_pandas_array(self):
20+
arr = pd.array(np.arange(5, dtype=np.int64)) * 3600 * 10**9
21+
22+
result = DatetimeArray._from_sequence(arr, freq='infer')
23+
24+
expected = pd.date_range('1970-01-01', periods=5, freq='H')._eadata
25+
tm.assert_datetime_array_equal(result, expected)
26+
1927
def test_mismatched_timezone_raises(self):
2028
arr = DatetimeArray(np.array(['2000-01-01T06:00:00'], dtype='M8[ns]'),
2129
dtype=DatetimeTZDtype(tz='US/Central'))

pandas/tests/frame/test_indexing.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -3245,7 +3245,9 @@ def test_setitem(self):
32453245
b1 = df._data.blocks[1]
32463246
b2 = df._data.blocks[2]
32473247
assert b1.values.equals(b2.values)
3248-
assert id(b1.values.values.base) != id(b2.values.values.base)
3248+
if b1.values.values.base is not None:
3249+
# base being None suffices to assure a copy was made
3250+
assert id(b1.values.values.base) != id(b2.values.values.base)
32493251

32503252
# with nan
32513253
df2 = df.copy()

0 commit comments

Comments
 (0)