Skip to content

ENH: Decimal year #60391

Open
Open
@dshean

Description

@dshean

Feature Type

  • Adding new functionality to pandas

  • Changing existing functionality in pandas

  • Removing existing functionality in pandas

Problem Description

I wish I could use pandas to quickly convert datetime/Timestamp objects to "decimal year" floating point numbers for subsequent visualization and analysis.

A number of plotting packages (e.g., GeoPandas, matplotlib) encounter issues when casting datetime/Timestamp objects to float. For example, I often encounter errors when trying to create a choropleth map to visualize a GeoDataFrame column containing datetime objects. Decimal years also simplify the legend/colorbar labels.

example decimal year map

Feature Description

This is a simple function to accomplish this. It's not perfect, but does the job. Would need to re-implement as a Timestamp and/or dt accessor property (dt.decyear). Should be relatively simple, I think.

#Decimal year (useful for plotting)
from datetime import datetime as dt
import time
def toYearFraction(date):
    def sinceEpoch(date): # returns seconds since epoch
        return time.mktime(date.timetuple())
    s = sinceEpoch

    year = date.year
    startOfThisYear = dt(year=year, month=1, day=1)
    startOfNextYear = dt(year=year+1, month=1, day=1)

    yearElapsed = s(date) - s(startOfThisYear)
    yearDuration = s(startOfNextYear) - s(startOfThisYear)
    fraction = yearElapsed/yearDuration

    return date.year + fraction

Alternative Solutions

Define and apply a custom function:
df['dt_col_decyear'] = df['dt_col'].apply(toYearFraction)

Additional Context

When attempting to plot column containing datetime values...

gdf.plot(column='dt_col', legend=True)

File [~/sw/miniconda3/envs/shean_py3/lib/python3.12/site-packages/geopandas/plotting.py:175](http://localhost:8888/lab/tree/src/stereo-lidar_archive_search/notebooks/~/sw/miniconda3/envs/shean_py3/lib/python3.12/site-packages/geopandas/plotting.py#line=174), in _plot_polygon_collection(ax, geoms, values, color, cmap, vmin, vmax, autolim, **kwargs)
    172 collection = PatchCollection([_PolygonPatch(poly) for poly in geoms], **kwargs)
    174 if values is not None:
--> 175     collection.set_array(np.asarray(values))
    176     collection.set_cmap(cmap)
    177     if "norm" not in kwargs:

File [~/sw/miniconda3/envs/shean_py3/lib/python3.12/site-packages/matplotlib/cm.py:452](http://localhost:8888/lab/tree/src/stereo-lidar_archive_search/notebooks/~/sw/miniconda3/envs/shean_py3/lib/python3.12/site-packages/matplotlib/cm.py#line=451), in ScalarMappable.set_array(self, A)
    450 A = cbook.safe_masked_invalid(A, copy=True)
    451 if not np.can_cast(A.dtype, float, "same_kind"):
--> 452     raise TypeError(f"Image data of dtype {A.dtype} cannot be "
    453                     "converted to float")
    455 self._A = A
    456 if not self.norm.scaled():

TypeError: Image data of dtype object cannot be converted to float

Metadata

Metadata

Assignees

No one assigned

    Labels

    DatetimeDatetime data dtypeEnhancementNeeds DiscussionRequires discussion from core team before further action

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions