Skip to content

Commit 532bdbf

Browse files
jbrockmendelKevin D Smith
authored and
Kevin D Smith
committed
PERF: TimedeltaArray.__iter__ (pandas-dev#36551)
1 parent 7f78299 commit 532bdbf

File tree

5 files changed

+61
-18
lines changed

5 files changed

+61
-18
lines changed

asv_bench/benchmarks/timeseries.py

+13-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,14 @@
33
import dateutil
44
import numpy as np
55

6-
from pandas import DataFrame, Series, date_range, period_range, to_datetime
6+
from pandas import (
7+
DataFrame,
8+
Series,
9+
date_range,
10+
period_range,
11+
timedelta_range,
12+
to_datetime,
13+
)
714

815
from pandas.tseries.frequencies import infer_freq
916

@@ -121,12 +128,15 @@ def time_convert(self):
121128

122129
class Iteration:
123130

124-
params = [date_range, period_range]
131+
params = [date_range, period_range, timedelta_range]
125132
param_names = ["time_index"]
126133

127134
def setup(self, time_index):
128135
N = 10 ** 6
129-
self.idx = time_index(start="20140101", freq="T", periods=N)
136+
if time_index is timedelta_range:
137+
self.idx = time_index(start=0, freq="T", periods=N)
138+
else:
139+
self.idx = time_index(start="20140101", freq="T", periods=N)
130140
self.exit = 10000
131141

132142
def time_iter(self, time_index):

pandas/core/arrays/datetimelike.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,10 @@ def _box_values(self, values):
226226
return lib.map_infer(values, self._box_func)
227227

228228
def __iter__(self):
229-
return (self._box_func(v) for v in self.asi8)
229+
if self.ndim > 1:
230+
return (self[n] for n in range(len(self)))
231+
else:
232+
return (self._box_func(v) for v in self.asi8)
230233

231234
@property
232235
def asi8(self) -> np.ndarray:

pandas/core/arrays/datetimes.py

+15-13
Original file line numberDiff line numberDiff line change
@@ -563,19 +563,21 @@ def __iter__(self):
563563
------
564564
tstamp : Timestamp
565565
"""
566-
567-
# convert in chunks of 10k for efficiency
568-
data = self.asi8
569-
length = len(self)
570-
chunksize = 10000
571-
chunks = int(length / chunksize) + 1
572-
for i in range(chunks):
573-
start_i = i * chunksize
574-
end_i = min((i + 1) * chunksize, length)
575-
converted = ints_to_pydatetime(
576-
data[start_i:end_i], tz=self.tz, freq=self.freq, box="timestamp"
577-
)
578-
yield from converted
566+
if self.ndim > 1:
567+
return (self[n] for n in range(len(self)))
568+
else:
569+
# convert in chunks of 10k for efficiency
570+
data = self.asi8
571+
length = len(self)
572+
chunksize = 10000
573+
chunks = int(length / chunksize) + 1
574+
for i in range(chunks):
575+
start_i = i * chunksize
576+
end_i = min((i + 1) * chunksize, length)
577+
converted = ints_to_pydatetime(
578+
data[start_i:end_i], tz=self.tz, freq=self.freq, box="timestamp"
579+
)
580+
yield from converted
579581

580582
def astype(self, dtype, copy=True):
581583
# We handle

pandas/core/arrays/timedeltas.py

+20-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@
1717
)
1818
from pandas._libs.tslibs.conversion import precision_from_unit
1919
from pandas._libs.tslibs.fields import get_timedelta_field
20-
from pandas._libs.tslibs.timedeltas import array_to_timedelta64, parse_timedelta_unit
20+
from pandas._libs.tslibs.timedeltas import (
21+
array_to_timedelta64,
22+
ints_to_pytimedelta,
23+
parse_timedelta_unit,
24+
)
2125
from pandas.compat.numpy import function as nv
2226

2327
from pandas.core.dtypes.common import (
@@ -346,6 +350,21 @@ def astype(self, dtype, copy: bool = True):
346350
return self
347351
return dtl.DatetimeLikeArrayMixin.astype(self, dtype, copy=copy)
348352

353+
def __iter__(self):
354+
if self.ndim > 1:
355+
return (self[n] for n in range(len(self)))
356+
else:
357+
# convert in chunks of 10k for efficiency
358+
data = self.asi8
359+
length = len(self)
360+
chunksize = 10000
361+
chunks = int(length / chunksize) + 1
362+
for i in range(chunks):
363+
start_i = i * chunksize
364+
end_i = min((i + 1) * chunksize, length)
365+
converted = ints_to_pytimedelta(data[start_i:end_i], box=True)
366+
yield from converted
367+
349368
# ----------------------------------------------------------------
350369
# Reductions
351370

pandas/tests/arrays/test_datetimelike.py

+9
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,15 @@ def test_getitem_2d(self, arr1d):
324324
expected = arr1d[-1]
325325
assert result == expected
326326

327+
def test_iter_2d(self, arr1d):
328+
data2d = arr1d._data[:3, np.newaxis]
329+
arr2d = type(arr1d)._simple_new(data2d, dtype=arr1d.dtype)
330+
result = list(arr2d)
331+
for x in result:
332+
assert isinstance(x, type(arr1d))
333+
assert x.ndim == 1
334+
assert x.dtype == arr1d.dtype
335+
327336
def test_setitem(self):
328337
data = np.arange(10, dtype="i8") * 24 * 3600 * 10 ** 9
329338
arr = self.array_cls(data, freq="D")

0 commit comments

Comments
 (0)