Skip to content

Commit 5c7c89b

Browse files
committed
Merge branch 'master' of https://github.com/pandas-dev/pandas into ref-liboffsets-cdefit
2 parents e414666 + 83530bd commit 5c7c89b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+602
-328
lines changed

doc/source/user_guide/computation.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,24 @@ from present information back to past information. This allows the rolling windo
648648
Currently, this feature is only implemented for time-based windows.
649649
For fixed windows, the closed parameter cannot be set and the rolling window will always have both endpoints closed.
650650

651+
.. _stats.iter_rolling_window:
652+
653+
Iteration over window:
654+
~~~~~~~~~~~~~~~~~~~~~~
655+
656+
.. versionadded:: 1.1.0
657+
658+
``Rolling`` and ``Expanding`` objects now support iteration. Be noted that ``min_periods`` is ignored in iteration.
659+
660+
.. ipython::
661+
662+
In [1]: df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
663+
664+
In [2]: for i in df.rolling(2):
665+
...: print(i)
666+
...:
667+
668+
651669
.. _stats.moments.ts-versus-resampling:
652670

653671
Time-aware rolling vs. resampling

doc/source/whatsnew/v1.1.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ Other enhancements
235235
:class:`~pandas.io.stata.StataWriter`, :class:`~pandas.io.stata.StataWriter117`,
236236
and :class:`~pandas.io.stata.StataWriterUTF8` (:issue:`26599`).
237237
- :meth:`HDFStore.put` now accepts `track_times` parameter. Parameter is passed to ``create_table`` method of ``PyTables`` (:issue:`32682`).
238+
- Make :class:`pandas.core.window.Rolling` and :class:`pandas.core.window.Expanding` iterable(:issue:`11704`)
238239

239240
.. ---------------------------------------------------------------------------
240241

pandas/_libs/tslibs/frequencies.pxd

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
cpdef str get_rule_month(object source, str default=*)
22

33
cpdef get_freq_code(freqstr)
4-
cpdef object get_freq(object freq)
54
cpdef str get_base_alias(freqstr)
65
cpdef int get_to_timestamp_base(int base)
76
cpdef str get_freq_str(base, mult=*)

pandas/_libs/tslibs/frequencies.pyx

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -306,25 +306,6 @@ cpdef int get_to_timestamp_base(int base):
306306
return base
307307

308308

309-
cpdef object get_freq(object freq):
310-
"""
311-
Return frequency code of given frequency str.
312-
If input is not string, return input as it is.
313-
314-
Examples
315-
--------
316-
>>> get_freq('A')
317-
1000
318-
319-
>>> get_freq('3A')
320-
1000
321-
"""
322-
if isinstance(freq, str):
323-
base, mult = get_freq_code(freq)
324-
freq = base
325-
return freq
326-
327-
328309
# ----------------------------------------------------------------------
329310
# Frequency comparison
330311

pandas/_libs/tslibs/np_datetime.pxd

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ cdef extern from "src/datetime/np_datetime.h":
5353
npy_datetimestruct *result) nogil
5454

5555

56-
cdef int reverse_ops[6]
57-
5856
cdef bint cmp_scalar(int64_t lhs, int64_t rhs, int op) except -1
5957

6058
cdef check_dts_bounds(npy_datetimestruct *dts)

pandas/_libs/tslibs/np_datetime.pyx

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,6 @@ cdef inline NPY_DATETIMEUNIT get_datetime64_unit(object obj) nogil:
6868
# ----------------------------------------------------------------------
6969
# Comparison
7070

71-
cdef int reverse_ops[6]
72-
73-
reverse_ops[Py_LT] = Py_GT
74-
reverse_ops[Py_LE] = Py_GE
75-
reverse_ops[Py_EQ] = Py_EQ
76-
reverse_ops[Py_NE] = Py_NE
77-
reverse_ops[Py_GT] = Py_LT
78-
reverse_ops[Py_GE] = Py_LE
79-
8071

8172
cdef inline bint cmp_scalar(int64_t lhs, int64_t rhs, int op) except -1:
8273
"""

pandas/_libs/tslibs/offsets.pyx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ from pandas._libs.tslibs.util cimport is_integer_object, is_datetime64_object
2323

2424
from pandas._libs.tslibs.base cimport ABCTimestamp
2525

26-
from pandas._libs.tslibs.ccalendar import MONTHS, DAYS
26+
from pandas._libs.tslibs.ccalendar import MONTHS, DAYS, weekday_to_int, int_to_weekday
2727
from pandas._libs.tslibs.ccalendar cimport get_days_in_month, dayofweek
2828
from pandas._libs.tslibs.conversion cimport (
2929
convert_datetime_to_tsobject,
@@ -993,10 +993,16 @@ class CustomMixin:
993993
object.__setattr__(self, "calendar", calendar)
994994

995995

996-
class WeekOfMonthMixin:
996+
class WeekOfMonthMixin(BaseOffset):
997997
"""
998998
Mixin for methods common to WeekOfMonth and LastWeekOfMonth.
999999
"""
1000+
def __init__(self, n=1, normalize=False, weekday=0):
1001+
BaseOffset.__init__(self, n, normalize)
1002+
object.__setattr__(self, "weekday", weekday)
1003+
1004+
if weekday < 0 or weekday > 6:
1005+
raise ValueError(f"Day must be 0<=day<=6, got {weekday}")
10001006

10011007
@apply_wraps
10021008
def apply(self, other):
@@ -1017,6 +1023,14 @@ class WeekOfMonthMixin:
10171023
return False
10181024
return dt.day == self._get_offset_day(dt)
10191025

1026+
@property
1027+
def rule_code(self) -> str:
1028+
weekday = int_to_weekday.get(self.weekday, "")
1029+
if self.week == -1:
1030+
# LastWeekOfMonth
1031+
return f"{self._prefix}-{weekday}"
1032+
return f"{self._prefix}-{self.week + 1}{weekday}"
1033+
10201034

10211035
# ----------------------------------------------------------------------
10221036
# RelativeDelta Arithmetic

pandas/_libs/tslibs/timedeltas.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ from pandas._libs.tslibs.base cimport ABCTimedelta, ABCTimestamp
2626
from pandas._libs.tslibs.ccalendar cimport DAY_NANOS
2727

2828
from pandas._libs.tslibs.np_datetime cimport (
29-
cmp_scalar, reverse_ops, td64_to_tdstruct, pandas_timedeltastruct)
29+
cmp_scalar, td64_to_tdstruct, pandas_timedeltastruct)
3030

3131
from pandas._libs.tslibs.nattype cimport (
3232
checknull_with_nat,

pandas/_libs/tslibs/timestamps.pxd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ cdef class _Timestamp(ABCTimestamp):
1515
cdef readonly:
1616
int64_t value, nanosecond
1717
object freq
18-
list _date_attributes
18+
1919
cpdef bint _get_start_end_field(self, str field)
2020
cpdef _get_date_name_field(self, object field, object locale)
2121
cdef int64_t _maybe_convert_value_to_local(self)

pandas/_libs/tslibs/timestamps.pyx

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,10 @@ cdef class _Timestamp(ABCTimestamp):
387387
dtype=object,
388388
)
389389

390+
elif not isinstance(self, _Timestamp):
391+
# cython semantics, args have been switched and this is __radd__
392+
return other.__add__(self)
393+
390394
return NotImplemented
391395

392396
def __sub__(self, other):
@@ -1051,7 +1055,7 @@ timedelta}, default 'raise'
10511055
return Period(self, freq=freq)
10521056

10531057
@property
1054-
def dayofweek(self):
1058+
def dayofweek(self) -> int:
10551059
"""
10561060
Return day of the week.
10571061
"""
@@ -1092,7 +1096,7 @@ timedelta}, default 'raise'
10921096
return self._get_date_name_field('month_name', locale)
10931097

10941098
@property
1095-
def dayofyear(self):
1099+
def dayofyear(self) -> int:
10961100
"""
10971101
Return the day of the year.
10981102
"""
@@ -1115,7 +1119,7 @@ timedelta}, default 'raise'
11151119
return ((self.month - 1) // 3) + 1
11161120

11171121
@property
1118-
def days_in_month(self):
1122+
def days_in_month(self) -> int:
11191123
"""
11201124
Return the number of days in the month.
11211125
"""
@@ -1428,16 +1432,7 @@ default 'raise'
14281432

14291433
return base1 + base2
14301434

1431-
def _has_time_component(self) -> bool:
1432-
"""
1433-
Returns if the Timestamp has a time component
1434-
in addition to the date part
1435-
"""
1436-
return (self.time() != _zero_time
1437-
or self.tzinfo is not None
1438-
or self.nanosecond != 0)
1439-
1440-
def to_julian_date(self):
1435+
def to_julian_date(self) -> np.float64:
14411436
"""
14421437
Convert TimeStamp to a Julian Date.
14431438
0 Julian date is noon January 1, 4713 BC.
@@ -1474,11 +1469,6 @@ default 'raise'
14741469
np.array([self.value], dtype='i8'), tz=self.tz)[0]
14751470
return Timestamp(normalized_value).tz_localize(self.tz)
14761471

1477-
def __radd__(self, other):
1478-
# __radd__ on cython extension types like _Timestamp is not used, so
1479-
# define it here instead
1480-
return self + other
1481-
14821472

14831473
# Add the min and max fields at the class level
14841474
cdef int64_t _NS_UPPER_BOUND = np.iinfo(np.int64).max

pandas/core/arrays/categorical.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ def _cat_compare_op(op):
6464

6565
@unpack_zerodim_and_defer(opname)
6666
def func(self, other):
67+
if is_list_like(other) and len(other) != len(self):
68+
# TODO: Could this fail if the categories are listlike objects?
69+
raise ValueError("Lengths must match.")
70+
6771
if not self.ordered:
6872
if opname in ["__lt__", "__gt__", "__le__", "__ge__"]:
6973
raise TypeError(

pandas/core/arrays/datetimelike.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ def _validate_comparison_value(self, other):
8484
elif not is_list_like(other):
8585
raise InvalidComparison(other)
8686

87+
elif len(other) != len(self):
88+
raise ValueError("Lengths must match")
89+
8790
else:
8891
try:
8992
other = self._validate_listlike(other, opname, allow_object=True)
@@ -1234,6 +1237,9 @@ def _add_timedelta_arraylike(self, other):
12341237
"""
12351238
# overridden by PeriodArray
12361239

1240+
if len(self) != len(other):
1241+
raise ValueError("cannot add indices of unequal length")
1242+
12371243
if isinstance(other, np.ndarray):
12381244
# ndarray[timedelta64]; wrap in TimedeltaIndex for op
12391245
from pandas.core.arrays import TimedeltaArray

pandas/core/arrays/datetimes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,9 @@ def _assert_tzawareness_compat(self, other):
654654

655655
def _sub_datetime_arraylike(self, other):
656656
"""subtract DatetimeArray/Index or ndarray[datetime64]"""
657+
if len(self) != len(other):
658+
raise ValueError("cannot add indices of unequal length")
659+
657660
if isinstance(other, np.ndarray):
658661
assert is_datetime64_dtype(other)
659662
other = type(self)(other)

pandas/core/arrays/integer.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,8 @@ def cmp_method(self, other):
517517
raise NotImplementedError(
518518
"can only perform ops with 1-d structures"
519519
)
520+
if len(self) != len(other):
521+
raise ValueError("Lengths must match to compare")
520522

521523
if other is libmissing.NA:
522524
# numpy does not handle pd.NA well as "other" scalar (it returns
@@ -620,6 +622,8 @@ def integer_arithmetic_method(self, other):
620622
raise NotImplementedError(
621623
"can only perform ops with 1-d structures"
622624
)
625+
if len(self) != len(other):
626+
raise ValueError("Lengths must match")
623627
if not (is_float_dtype(other) or is_integer_dtype(other)):
624628
raise TypeError("can only perform ops with numeric values")
625629

pandas/core/arrays/period.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -746,8 +746,7 @@ def _check_timedeltalike_freq_compat(self, other):
746746
IncompatibleFrequency
747747
"""
748748
assert isinstance(self.freq, Tick) # checked by calling function
749-
own_offset = frequencies.to_offset(self.freq.rule_code)
750-
base_nanos = delta_to_nanoseconds(own_offset)
749+
base_nanos = self.freq.base.nanos
751750

752751
if isinstance(other, (timedelta, np.timedelta64, Tick)):
753752
nanos = delta_to_nanoseconds(other)

pandas/core/arrays/timedeltas.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,10 @@ def __mul__(self, other):
471471
if not hasattr(other, "dtype"):
472472
# list, tuple
473473
other = np.array(other)
474+
if len(other) != len(self) and not is_timedelta64_dtype(other.dtype):
475+
# Exclude timedelta64 here so we correctly raise TypeError
476+
# for that instead of ValueError
477+
raise ValueError("Cannot multiply with unequal lengths")
474478

475479
if is_object_dtype(other.dtype):
476480
# this multiplication will succeed only if all elements of other
@@ -514,7 +518,10 @@ def __truediv__(self, other):
514518
# e.g. list, tuple
515519
other = np.array(other)
516520

517-
if is_timedelta64_dtype(other.dtype):
521+
if len(other) != len(self):
522+
raise ValueError("Cannot divide vectors with unequal lengths")
523+
524+
elif is_timedelta64_dtype(other.dtype):
518525
# let numpy handle it
519526
return self._data / other
520527

@@ -564,7 +571,10 @@ def __rtruediv__(self, other):
564571
# e.g. list, tuple
565572
other = np.array(other)
566573

567-
if is_timedelta64_dtype(other.dtype):
574+
if len(other) != len(self):
575+
raise ValueError("Cannot divide vectors with unequal lengths")
576+
577+
elif is_timedelta64_dtype(other.dtype):
568578
# let numpy handle it
569579
return other / self._data
570580

@@ -613,8 +623,10 @@ def __floordiv__(self, other):
613623
if not hasattr(other, "dtype"):
614624
# list, tuple
615625
other = np.array(other)
626+
if len(other) != len(self):
627+
raise ValueError("Cannot divide with unequal lengths")
616628

617-
if is_timedelta64_dtype(other.dtype):
629+
elif is_timedelta64_dtype(other.dtype):
618630
other = type(self)(other)
619631

620632
# numpy timedelta64 does not natively support floordiv, so operate
@@ -666,7 +678,10 @@ def __rfloordiv__(self, other):
666678
# list, tuple
667679
other = np.array(other)
668680

669-
if is_timedelta64_dtype(other.dtype):
681+
if len(other) != len(self):
682+
raise ValueError("Cannot divide with unequal lengths")
683+
684+
elif is_timedelta64_dtype(other.dtype):
670685
other = type(self)(other)
671686

672687
# numpy timedelta64 does not natively support floordiv, so operate

0 commit comments

Comments
 (0)