Skip to content

Instantly share code, notes, and snippets.

@spencerkclark
Created December 4, 2016 23:39
Show Gist options
  • Save spencerkclark/158ddbd0b0df7de1332020429e4c97c2 to your computer and use it in GitHub Desktop.
Save spencerkclark/158ddbd0b0df7de1332020429e4c97c2 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"metadata": {},
"cell_type": "markdown",
"source": "Experimental NetCDFTimeIndex\n----------------------------"
},
{
"metadata": {
"collapsed": true,
"trusted": true
},
"cell_type": "code",
"source": "import xarray as xr\nimport numpy as np\n\nfrom pandas import Index\nfrom netCDF4 import netcdftime",
"execution_count": 1,
"outputs": []
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "def get_date_field(datetimes, field):\n \"\"\"This is implemented in cython in pandas; perhaps we \n could implement something similar for our purposes upstream\n in netcdftime, but as a proof of concept I'll just use\n this for now.\n \"\"\"\n a = []\n for d in datetimes:\n a.append(getattr(d, field))\n return np.array(a)\n\ndef _field_accessor(name, docstring=None):\n def f(self):\n values = self._data\n return get_date_field(values, name)\n \n f.__name__ = name\n f.__doc__ = docstring\n return property(f)\n\nclass NetCDFTimeIndex(Index):\n def __new__(cls, data):\n result = object.__new__(cls)\n result._data = np.array(data)\n return result\n \n year = _field_accessor('year', 'The year of the datetime')\n month = _field_accessor('month', 'The month of the datetime')\n day = _field_accessor('day', 'The days of the datetime')\n hour = _field_accessor('hour', 'The hours of the datetime')\n minute = _field_accessor('minute', 'The minutes of the datetime')\n second = _field_accessor('second', 'The seconds of the datetime')\n millisecond = _field_accessor('millisecond', 'The milliseconds of the datetime')\n microsecond = _field_accessor('microsecond', 'The microseconds of the datetime')\n \n def _maybe_convert_str_to_date(self, key):\n if isinstance(key, str):\n date_type = type(self._data[0]) # Is there a better way of doing this?\n return date_type(*netcdftime._parse_date(key))\n else:\n return key\n \n def get_loc(self, key, method=None, tolerance=None):\n \"\"\"Add support for ISO 8601 format string date specification\"\"\"\n return Index.get_loc(self, self._maybe_convert_str_to_date(key),\n method, tolerance)\n \n def slice_locs(self, start=None, end=None, step=None, kind=None):\n \"\"\"Add support for ISO 8601 format string date specification\"\"\"\n return Index.slice_locs(self, self._maybe_convert_str_to_date(start),\n self._maybe_convert_str_to_date(end),\n step, kind)",
"execution_count": 2,
"outputs": []
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "dates_0001 = [netcdftime.DatetimeAllLeap(1, m, 1) for m in range(1, 13)]\ndates_0002 = [netcdftime.DatetimeAllLeap(2, m, 1) for m in range(1, 13)]",
"execution_count": 3,
"outputs": []
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "# Create a DataArray with a NetCDFTimeIndex as a coordinate\nda = xr.DataArray(np.arange(35, 35 + 24), coords=[NetCDFTimeIndex(dates_0001 + dates_0002)], dims=['time'])",
"execution_count": 4,
"outputs": []
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "da",
"execution_count": 5,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "<xarray.DataArray (time: 24)>\narray([35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,\n 52, 53, 54, 55, 56, 57, 58])\nCoordinates:\n * time (time) object 1-01-01 00:00:00 1-02-01 00:00:00 ..."
},
"metadata": {},
"execution_count": 5
}
]
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "da.time",
"execution_count": 6,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "<xarray.DataArray 'time' (time: 24)>\narray([netcdftime._netcdftime.DatetimeAllLeap(1, 1, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(1, 2, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(1, 3, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(1, 4, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(1, 5, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(1, 6, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(1, 7, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(1, 8, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(1, 9, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(1, 10, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(1, 11, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(1, 12, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 1, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 2, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 3, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 4, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 5, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 6, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 7, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 8, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 9, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 10, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 11, 1, 0, 0, 0, 0, -1, 1),\n netcdftime._netcdftime.DatetimeAllLeap(2, 12, 1, 0, 0, 0, 0, -1, 1)], dtype=object)\nCoordinates:\n * time (time) object 1-01-01 00:00:00 1-02-01 00:00:00 ..."
},
"metadata": {},
"execution_count": 6
}
]
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "da.sel(time=slice(netcdftime.DatetimeAllLeap(1, 5, 1), netcdftime.DatetimeAllLeap(1, 7, 1)))",
"execution_count": 7,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "<xarray.DataArray (time: 3)>\narray([39, 40, 41])\nCoordinates:\n * time (time) object 1-05-01 00:00:00 1-06-01 00:00:00 ..."
},
"metadata": {},
"execution_count": 7
}
]
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "da.sel(time=slice('0001-05-01', '0001-07-01'))",
"execution_count": 8,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "<xarray.DataArray (time: 3)>\narray([39, 40, 41])\nCoordinates:\n * time (time) object 1-05-01 00:00:00 1-06-01 00:00:00 ..."
},
"metadata": {},
"execution_count": 8
}
]
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "da.groupby('time.month').mean('time')",
"execution_count": 9,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "<xarray.DataArray (month: 12)>\narray([ 41., 42., 43., 44., 45., 46., 47., 48., 49., 50., 51.,\n 52.])\nCoordinates:\n * month (month) int64 1 2 3 4 5 6 7 8 9 10 11 12"
},
"metadata": {},
"execution_count": 9
}
]
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "da.groupby('time.year').mean('time')",
"execution_count": 10,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "<xarray.DataArray (year: 2)>\narray([ 40.5, 52.5])\nCoordinates:\n * year (year) int64 1 2"
},
"metadata": {},
"execution_count": 10
}
]
},
{
"metadata": {},
"cell_type": "markdown",
"source": "The approach is calendar-agnostic\n---------------------------------"
},
{
"metadata": {
"collapsed": true,
"trusted": true
},
"cell_type": "code",
"source": "# Try out a 360-day calendar\ndates_0001 = [netcdftime.Datetime360Day(1, m, 30) for m in range(1, 13)]\ndates_0002 = [netcdftime.Datetime360Day(2, m, 30) for m in range(1, 13)]",
"execution_count": 11,
"outputs": []
},
{
"metadata": {
"collapsed": true,
"trusted": true
},
"cell_type": "code",
"source": "da = xr.DataArray(np.arange(35, 35 + 24), coords=[NetCDFTimeIndex(dates_0001 + dates_0002)], dims=['time'])",
"execution_count": 12,
"outputs": []
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "da.sel(time=slice(netcdftime.Datetime360Day(1, 2, 1), netcdftime.Datetime360Day(1, 7, 1)))",
"execution_count": 13,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "<xarray.DataArray (time: 5)>\narray([36, 37, 38, 39, 40])\nCoordinates:\n * time (time) object 1-02-30 00:00:00 1-03-30 00:00:00 ..."
},
"metadata": {},
"execution_count": 13
}
]
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "da.sel(time=slice('0001-02-01', '0001-07-01'))",
"execution_count": 14,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "<xarray.DataArray (time: 5)>\narray([36, 37, 38, 39, 40])\nCoordinates:\n * time (time) object 1-02-30 00:00:00 1-03-30 00:00:00 ..."
},
"metadata": {},
"execution_count": 14
}
]
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "da.groupby('time.month').mean('time')",
"execution_count": 15,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "<xarray.DataArray (month: 12)>\narray([ 41., 42., 43., 44., 45., 46., 47., 48., 49., 50., 51.,\n 52.])\nCoordinates:\n * month (month) int64 1 2 3 4 5 6 7 8 9 10 11 12"
},
"metadata": {},
"execution_count": 15
}
]
},
{
"metadata": {
"collapsed": false,
"trusted": true
},
"cell_type": "code",
"source": "da.groupby('time.year').mean('time')",
"execution_count": 16,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": "<xarray.DataArray (year: 2)>\narray([ 40.5, 52.5])\nCoordinates:\n * year (year) int64 1 2"
},
"metadata": {},
"execution_count": 16
}
]
}
],
"metadata": {
"kernelspec": {
"name": "python2",
"display_name": "Python 2",
"language": "python"
},
"language_info": {
"mimetype": "text/x-python",
"nbconvert_exporter": "python",
"name": "python",
"pygments_lexer": "ipython2",
"version": "2.7.12",
"file_extension": ".py",
"codemirror_mode": {
"version": 2,
"name": "ipython"
}
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment