简体   繁体   中英

Pandas: Convert fractional months to datetime

I have some monthly data with a date column in the format: YYYY.fractional month. For example:

0    1960.500
1    1960.583
2    1960.667
3    1960.750
4    1960.833
5    1960.917

Where the first index is June, 1960 (6/12=.5), the second is July, 1960 (7/12=.583) and so on.

The answers in this question don't seem to apply well, though I feel like pd.to_datetime should be able to help somehow. Obviously I can use a map to split this into components and build a datetime, but I'm hoping for a faster and more rigorous method since the data is large.

I think you need a bit maths:

a = df['date'].astype(int)
print (a)
0    1960
1    1960
2    1960
3    1960
4    1960
5    1960
Name: date, dtype: int32

b = df['date'].sub(a).add(1/12).mul(12).round(0).astype(int)
print (b)
0     7
1     8
2     9
3    10
4    11
5    12
Name: date, dtype: int32

c = pd.to_datetime(a.astype(str) + '.' + b.astype(str), format='%Y.%m')
print (c)
0   1960-07-01
1   1960-08-01
2   1960-09-01
3   1960-10-01
4   1960-11-01
5   1960-12-01
Name: date, dtype: datetime64[ns]

Solution with map :

d = {'500':'7','583':'8','667':'9','750':'10','833':'11','917':'12'}

#if necessary
#df['date'] = df['date'].astype(str)
a = df['date'].str[:4]
b = df['date'].str[5:].map(d)

c = pd.to_datetime(a + '.' + b, format='%Y.%m')
print (c)
0   1960-07-01
1   1960-08-01
2   1960-09-01
3   1960-10-01
4   1960-11-01
5   1960-12-01
Name: date, dtype: datetime64[ns]

For future reference, here's the map I was using before. I actually made a mistake in the question; the data is set so that January 1960 is 1960.0, which means 1/12 must be added to each fractional component.

def date_conv(d):
    y, frac_m = str(d).split('.')
    y = int(y)
    m = int(round((float('0.{}'.format(frac_m)) + 1/12) * 12, 0))
    d = 1
    try:
        date = datetime.datetime(year=y, month=m, day=d)
    except ValueError:
        print(y, m, frac_m)
        raise
    return date

dates_series = dates_series.map(lambda d: date_conv(d))

The try/except block was just something I added for troubleshooting while writing it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM