You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
i.e. xray's groupby is ~100 times slower than pandas' one (and 200 times slower than passing "mean" to pandas' groupby, which I assume involves some specialization).
(This is the actual order or magnitude of the data size and redundancy I want to handle, i.e. thousands of points with very limited duplication.)
Yes, I'm afraid this is a known issue. Grouped aggregations are currently implemented with a loop in pure Python, which, of course, is pretty slow.
I've done some exploratory work to rewrite them in Numba, which shows some encouraging preliminary results:
from numba import guvectorize, jit
import pandas as pd
import numpy as np
@guvectorize(['(float64[:], int64[:], float64[:])'],
'(x),(x),(y)', nopython=True)
def _grouped_mean(values, int_labels, target):
count = np.zeros(len(target), np.int64)
for i in range(len(values)):
val = values[i]
if not np.isnan(val):
lab = int_labels[i]
target[lab] += val
count[lab] += 1
target /= count
def move_axis_to_end(array, axis):
array = np.asarray(array)
return np.rollaxis(array, axis, start=array.ndim)
def grouped_mean(values, by, axis=-1):
int_labels, uniques = pd.factorize(by, sort=True)
values = move_axis_to_end(values, axis)
target = np.zeros(values.shape[:-1] + uniques.shape)
_grouped_mean(values, int_labels, target)
return target, uniques
values = np.random.RandomState(0).rand(int(1e6))
values[::50] = np.nan
by = np.random.randint(50, size=int(1e6))
df = pd.DataFrame({'x': values, 'y': by})
np.testing.assert_allclose(grouped_mean(values, by)[0], df.groupby('y')['x'].mean())
%timeit grouped_mean(values, by) # 100 loops, best of 3: 15.3 ms per loop
%timeit df.groupby('y').mean() # 10 loops, best of 3: 21.4 ms per loop
Unfortunately, I'm unlikely to have time to work on this in the near future. If you or anyone else is interested in taking the lead on this, it would be greatly appreciated!
Note that we can't reuse the routines from pandas because they are only designed for 1D or at most 2D data.
Another approach here (rather than writing something new with Numba) would be to write a pure NumPy engine for groupby that relies on reordering data and np.add.accumulate. This could yield performance within a factor of 2-3x slower than pandas. See this comment for an example: numpy/numpy#7265 (comment)
In case anyone gets here by Googling something like "xarray groupby slow" and you loaded data from a netCDF file, be aware that slowness you see in groupby aggregation on a Dataset or DataArray may actually be due not to this issue but to the lazy loading that's done by default. This can be fixed by calling .load() on the Dataset or DataArray. See the Tip about lazy loading at http://xarray.pydata.org/en/stable/io.html#netcdf.
Reacted by Stephan Hoyer, Joe Hamman, Tim Blazina, Elise Penn, Scott Staniewicz and Zhihua Zheng
I gave a look to functions such as "np.add.at" which can be highly faster than home-made solution. The aggregate function of the "numpy-groupies" package is even faster (25 x faster than np.add.at in my case).
Maybe xarray groupby functionalities can rely on such effective package.
Activity
shoyer commentedon Nov 16, 2015
Yes, I'm afraid this is a known issue. Grouped aggregations are currently implemented with a loop in pure Python, which, of course, is pretty slow.
I've done some exploratory work to rewrite them in Numba, which shows some encouraging preliminary results:
Unfortunately, I'm unlikely to have time to work on this in the near future. If you or anyone else is interested in taking the lead on this, it would be greatly appreciated!
Note that we can't reuse the routines from pandas because they are only designed for 1D or at most 2D data.
anntzer commentedon Nov 16, 2015
In my case I could just switch to pandas, so I'll leave it as it is for now.
shoyer commentedon Nov 16, 2015
Yes, switching to pandas for these operations is certainly a recommended approach :).
anntzer commentedon Nov 16, 2015
Perhaps worth mentioning in the docs? The difference turned out to be a major bottleneck in my code.
shoyer commentedon Nov 16, 2015
Agreed! If you'd like to make a pull request that would be greatly
appreciated
On Sun, Nov 15, 2015 at 10:10 PM, Antony Lee notifications@github.com
wrote:
shoyer commentedon Mar 23, 2016
Another approach here (rather than writing something new with Numba) would be to write a pure NumPy engine for groupby that relies on reordering data and
np.add.accumulate. This could yield performance within a factor of 2-3x slower than pandas. See this comment for an example:numpy/numpy#7265 (comment)
jjpr-mit commentedon Oct 4, 2017
In case anyone gets here by Googling something like "xarray groupby slow" and you loaded data from a netCDF file, be aware that slowness you see in groupby aggregation on a
DatasetorDataArraymay actually be due not to this issue but to the lazy loading that's done by default. This can be fixed by calling.load()on theDatasetorDataArray. See the Tip about lazy loading at http://xarray.pydata.org/en/stable/io.html#netcdf.lanougue commentedon Aug 19, 2019
I gave a look to functions such as "np.add.at" which can be highly faster than home-made solution. The aggregate function of the "numpy-groupies" package is even faster (25 x faster than np.add.at in my case).
Maybe xarray groupby functionalities can rely on such effective package.
andersy005 commentedon May 13, 2022
#5734 has greatly improved the performance. Fantastic work @dcherian 👏🏽
Enable `flox` in `GroupBy` and `resample` (pydata#5734)
Enable `flox` in `GroupBy` and `resample` (pydata#5734)
Enable flox in GroupBy and resample (pydata#5734)