Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: pd.Timedelta does not accept np.int32, etc. #8757

Closed
wholmgren opened this issue Nov 8, 2014 · 9 comments · Fixed by #8787
Closed

BUG: pd.Timedelta does not accept np.int32, etc. #8757

wholmgren opened this issue Nov 8, 2014 · 9 comments · Fixed by #8787
Labels
Bug Dtype Conversions Unexpected or buggy dtype conversions Timedelta Timedelta data type
Milestone

Comments

@wholmgren
Copy link
Contributor

pd.Timedelta is a great addition, thanks!

Is it the intended behavior of pd.Timedelta to only accept np.int64, python ints, and python floats? I ran into this when I tried to construct a list of pd.Timedeltas from the np.int32 array returned by pd.DatetimeIndex.dayofyear.

>>> import pandas as pd
>>> import numpy as np
>>> pd.Timedelta(days=np.int64(1))
Timedelta('1 days 00:00:00')
>>> pd.Timedelta(days=np.int32(1))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pandas/tslib.pyx", line 1638, in pandas.tslib.Timedelta.__new__ (pandas/tslib.c:27693)
ValueError: cannot construct a TimeDelta from the passed arguments, allowed keywords are [days, seconds, microseconds, milliseconds, minutes, hours, weeks]
>>> pd.Timedelta(days=np.int16(1))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pandas/tslib.pyx", line 1638, in pandas.tslib.Timedelta.__new__ (pandas/tslib.c:27693)
ValueError: cannot construct a TimeDelta from the passed arguments, allowed keywords are [days, seconds, microseconds, milliseconds, minutes, hours, weeks]
>>> pd.Timedelta(days=np.float64(1))
Timedelta('1 days 00:00:00')
>>> pd.Timedelta(days=np.float32(1))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pandas/tslib.pyx", line 1638, in pandas.tslib.Timedelta.__new__ (pandas/tslib.c:27693)
ValueError: cannot construct a TimeDelta from the passed arguments, allowed keywords are [days, seconds, microseconds, milliseconds, minutes, hours, weeks]
>>> pd.Timedelta(days=1)
Timedelta('1 days 00:00:00')
>>> pd.Timedelta(days=1.0)
Timedelta('1 days 00:00:00')

Here's my version info:

>>> pd.show_versions()

INSTALLED VERSIONS
------------------
commit: None
python: 2.7.6.final.0
python-bits: 64
OS: Linux
OS-release: 2.6.32-431.17.1.el6.x86_64
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8

pandas: 0.15.1
nose: 1.3.4
Cython: 0.21
numpy: 1.9.1
scipy: 0.14.0
statsmodels: None
IPython: 2.3.0
sphinx: 1.2.3
patsy: None
dateutil: 2.2
pytz: 2014.9
bottleneck: None
tables: None
numexpr: None
matplotlib: 1.4.0
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml: None
bs4: None
html5lib: None
httplib2: None
apiclient: None
rpy2: None
sqlalchemy: 0.9.7
pymysql: 0.6.2.None
psycopg2: None
@jreback
Copy link
Contributor

jreback commented Nov 8, 2014

hmm be a little too strict in this but sure easy enough to add

interested in doing a pull-request?

@jreback jreback added Community Bug Dtype Conversions Unexpected or buggy dtype conversions Timedelta Timedelta data type and removed Community labels Nov 8, 2014
@jreback jreback added this to the 0.15.2 milestone Nov 8, 2014
@jreback
Copy link
Contributor

jreback commented Nov 8, 2014

out of curiosity did you manually download? this should not be visible yet in pypi
(I am waiting to put all the binaries there before releasing it)

@wholmgren
Copy link
Contributor Author

pandas 0.15.1? I just did a pip install pandas --upgrade this morning (I was on .14). I was a little surprised that it started downloading 0.15.1 but I didn't look into it.

I'll take a shot at the pull request.

@wholmgren
Copy link
Contributor Author

Further documentation... pd.Timedelta cannot accept np.int64 on python 3.3 or 3.4, however np.float64 does work.

>>> import pandas as pd
>>> import numpy as np
>>> pd.Timedelta(days=np.int64(1))
Traceback (most recent call last):
  File "pandas/tslib.pyx", line 1636, in pandas.tslib.Timedelta.__new__ (pandas/tslib.c:27653)
TypeError: unsupported type for timedelta days component: numpy.int64

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pandas/tslib.pyx", line 1638, in pandas.tslib.Timedelta.__new__ (pandas/tslib.c:27693)
ValueError: cannot construct a TimeDelta from the passed arguments, allowed keywords are [days, seconds, microseconds, milliseconds, minutes, hours, weeks]
>>> pd.Timedelta(days=1)
Timedelta('1 days 00:00:00')
>>> pd.Timedelta(days=np.float64(1))
Timedelta('1 days 00:00:00')
>>> pd.Timedelta(days=np.float32(1))
Traceback (most recent call last):
  File "pandas/tslib.pyx", line 1636, in pandas.tslib.Timedelta.__new__ (pandas/tslib.c:27653)
TypeError: unsupported type for timedelta days component: numpy.float32

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pandas/tslib.pyx", line 1638, in pandas.tslib.Timedelta.__new__ (pandas/tslib.c:27693)
ValueError: cannot construct a TimeDelta from the passed arguments, allowed keywords are [days, seconds, microseconds, milliseconds, minutes, hours, weeks]
>>> pd.show_versions()

INSTALLED VERSIONS
------------------
commit: None
python: 3.4.2.final.0
python-bits: 64
OS: Linux
OS-release: 2.6.32-431.17.1.el6.x86_64
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8

pandas: 0.15.1
nose: 1.3.4
Cython: None
numpy: 1.9.1
scipy: 0.14.0
statsmodels: None
IPython: 2.3.0
sphinx: None
patsy: None
dateutil: 2.2
pytz: 2014.9
bottleneck: None
tables: None
numexpr: None
matplotlib: 1.4.2
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml: None
bs4: None
html5lib: None
httplib2: None
apiclient: None
rpy2: None
sqlalchemy: None
pymysql: None
psycopg2: None

@jreback jreback reopened this Nov 8, 2014
@wholmgren
Copy link
Contributor Author

ack. sorry bout the close.

@jreback
Copy link
Contributor

jreback commented Nov 8, 2014

floats are legit, mostly, eg.

pd.Timedelta('1.5d')
Timedelta('1 days 12:00:00')

not 100% sure about accepting this though:

pd.Timedelta(days=1.5) prob need some validation

though pd.Timedelta(days=np.float32(1)) should work
e.g. if x == int(x) (a whole integer) then for sure ok, even if its a float

@wholmgren
Copy link
Contributor Author

Now that I've looked at the source code, I see that it's failing when trying to construct a python datetime.timedelta. So, I think that the blame lies with numpy for failing to provide python with the right translation.

In [13]: datetime.timedelta(days=1)
Out[13]: datetime.timedelta(1)

In [14]: datetime.timedelta(days=1.0)
Out[14]: datetime.timedelta(1)

In [15]: datetime.timedelta(days=np.int64(1.0))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-194c3cc228db> in <module>()
----> 1 datetime.timedelta(days=np.int64(1.0))

TypeError: unsupported type for timedelta days component: numpy.int64

In [16]: datetime.timedelta(days=np.float64(1.0))
Out[16]: datetime.timedelta(1)

In [17]: datetime.timedelta(days=np.float32(1.0))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-17-2055ee731de0> in <module>()
----> 1 datetime.timedelta(days=np.float32(1.0))

TypeError: unsupported type for timedelta days component: numpy.float32

In [19]: datetime.timedelta(dayss=1)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-19-699cc4692f32> in <module>()
----> 1 datetime.timedelta(dayss=1)

TypeError: 'dayss' is an invalid keyword argument for this function

I'm not sure if it's appropriate to provide a work around here or not. At the very least, I think that the exception text should be made more accurate. It's a little tricky because both exceptions are classified as TypeErrors. One possibility would be to simply remove the try/except on line 1635 and let the python message through. Another possibility would be to check the python exception text for 'is an invalid keyword' or similar, and if true, raise the current pandas error, and if false, raise the error verbatim.

Thoughts?

@jreback
Copy link
Contributor

jreback commented Nov 11, 2014

see here: https://github.com/pydata/pandas/blob/master/pandas/tslib.pyx

i would just iterate on the kwargs and coerce the not-None values to ints here (side issue is what to do with a float that is not == to its int value).

wholmgren added a commit to wholmgren/pandas that referenced this issue Nov 11, 2014
wholmgren added a commit to wholmgren/pandas that referenced this issue Nov 11, 2014
jreback added a commit that referenced this issue Nov 11, 2014
BUG: pd.Timedelta np.int, np.float. fixes #8757
@jpweytjens
Copy link

jpweytjens commented Mar 22, 2023

pd.Timedelta now supports np.int, but it's close cousin pd.Dateoffset does not when using pandas version 1.5.3 and numpy version 1.23.5.

import pandas as pd
import numpy as np

date = pd.Timestamp(year=2000, month=1, day=1)
dtypes = [int, float, np.int64, np.int32, np.float64, np.float32]

for dtype in dtypes:
    try:
        date + pd.DateOffset(days=dtype(1))
    except:
        print(f"{dtype} is not supported with pd.DateOffset.")
    try:
        date + pd.Timedelta(value=dtype(1), unit="days")
    except:
        print(f"{dtype} is not supported with pd.TimeDelta.")

I'll open a PR, similar to #8787 when I can find the time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Dtype Conversions Unexpected or buggy dtype conversions Timedelta Timedelta data type
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants