Pandas version checks
-
[X] I have checked that this issue has not already been reported.
-
[X] I have confirmed this bug exists on the latest version of pandas.
-
[X] I have confirmed this bug exists on the main branch of pandas.
Reproducible Example
import pandas as pd
p = pd.Period("2012-1-1", freq="D")
as_period_index = pd.period_range("2012-1-1", periods=10, freq="D")
offset_index = p - as_period_index
print(offset_index)
result = p + offset_index
print(result)
Issue Description
In pandas 1.5.2, here is the result:
Index([ <0 * Days>, <-1 * Day>, <-2 * Days>, <-3 * Days>, <-4 * Days>,
<-5 * Days>, <-6 * Days>, <-7 * Days>, <-8 * Days>, <-9 * Days>],
dtype='object')
PeriodIndex(['2012-01-01', '2011-12-31', '2011-12-30', '2011-12-29',
'2011-12-28', '2011-12-27', '2011-12-26', '2011-12-25',
'2011-12-24', '2011-12-23'],
dtype='period[D]')
In master version 2.0.0.dev0+881.gcab77e3d6c
Index([ <0 * Days>, <-1 * Day>, <-2 * Days>, <-3 * Days>, <-4 * Days>,
<-5 * Days>, <-6 * Days>, <-7 * Days>, <-8 * Days>, <-9 * Days>],
dtype='object')
Index([2012-01-01, 2011-12-31, 2011-12-30, 2011-12-29, 2011-12-28, 2011-12-27,
2011-12-26, 2011-12-25, 2011-12-24, 2011-12-23],
dtype='object')
So the result used to be PeriodIndex, now it is Index. This was picked up in our tests for pandas-stubs
Expected Behavior
Should return PeriodIndex when you add offsets
Installed Versions
Comment From: ramvikrams
If we change the pandas/_libs/_tslibs/period.pyi and add the def __add__(self, other: Index) -> PeriodIndex: ... the result does not changes, so if not here where should the change ne done
Comment From: Dr-Irv
If we change the
pandas/_libs/_tslibs/period.pyiand add thedef __add__(self, other: Index) -> PeriodIndex: ...the result does not changes, so if not here where should the change ne done
The error is in the pyx or py files, not the pyi files.
Comment From: jbrockmendel
This is probably the result of #49999, specifically moving away from doing type inference on object-dtype results. Use result.infer_objects(copy=False) to get the old behavior
(the reversed op offset_index + p raises a TypeError that looks very wrong to me)
Comment From: Dr-Irv
I find this change to be inconsistent. Aside from the TypeError that should be investigated, this behavior seems inconsistent:
p = pd.Period("2012-1-1", freq="D")
as_period_index = pd.period_range("2012-1-1", periods=10, freq="D")
offset_index = p - as_period_index
print(offset_index)
result = p + offset_index
print(result)
iresult = pd.Index([p]*10) + offset_index
print(iresult)
This produces output:
Index([ <0 * Days>, <-1 * Day>, <-2 * Days>, <-3 * Days>, <-4 * Days>,
<-5 * Days>, <-6 * Days>, <-7 * Days>, <-8 * Days>, <-9 * Days>],
dtype='object')
Index([2012-01-01, 2011-12-31, 2011-12-30, 2011-12-29, 2011-12-28, 2011-12-27,
2011-12-26, 2011-12-25, 2011-12-24, 2011-12-23],
dtype='object')
PeriodIndex(['2012-01-01', '2011-12-31', '2011-12-30', '2011-12-29',
'2011-12-28', '2011-12-27', '2011-12-26', '2011-12-25',
'2011-12-24', '2011-12-23'],
dtype='period[D]')
In the first addition, you are adding a Period plus an index of offsets, the latter has type object, and you get an Index.
In the second addition, you are adding a PeriodIndex plus an index of offsets, the latter has type object and you get a PeriodIndex.
So that PR documents the change as:
Changed behavior of :class:
Index, :class:Series, and :class:DataFramearithmetic methods when working with object-dtypes, the results no longer do type inference on the result of the array operation
That's not really correct, because in the second addition I did, you added one Index that had a dtype of Period and a second index that had a dtype of object, and it kept the dtype of Period (as I would expect). So it seems that if you do arithmetic on a single object that has a type, then it doesn't do the inference. This could get really confusing.
Why did you make that change?
Comment From: jbrockmendel
Not sure what changed since the last post and now, but the all three examples in @Dr-Irv 's last post now come back as object dtype, which is what I would expect. The reversed op which previously raised TypeError now works.
Closable?
Comment From: Dr-Irv
Yes, we can close since the behavior is now consistent.