mirror of
https://github.com/meteoinfo/MeteoInfo.git
synced 2025-12-08 20:36:05 +00:00
158 lines
5.2 KiB
Python
158 lines
5.2 KiB
Python
from org.meteoinfo.ndarray.math import ArrayUtil
|
|
from .. import core as np
|
|
|
|
__all__ = ['unique', 'intersect1d']
|
|
|
|
def _unique1d(ar, return_index=False, return_inverse=False,
|
|
return_counts=False):
|
|
"""
|
|
Find the unique elements of an array, ignoring shape.
|
|
"""
|
|
ar = np.asanyarray(ar).flatten()
|
|
|
|
optional_indices = return_index or return_inverse
|
|
|
|
if optional_indices:
|
|
perm = ar.argsort()
|
|
aux = ar[perm]
|
|
else:
|
|
ar.sort()
|
|
aux = ar
|
|
mask = np.empty(aux.shape, dtype=np.bool_)
|
|
mask[:1] = True
|
|
if aux.shape[0] > 0 and aux.dtype.kind in "cfmM" and np.isnan(aux[-1]):
|
|
if aux.dtype.kind == "c": # for complex all NaNs are considered equivalent
|
|
aux_firstnan = np.searchsorted(np.isnan(aux), True, side='left')
|
|
else:
|
|
aux_firstnan = np.searchsorted(aux, aux[-1], side='left')
|
|
if aux_firstnan > 0:
|
|
mask[1:aux_firstnan] = (
|
|
aux[1:aux_firstnan] != aux[:aux_firstnan - 1])
|
|
mask[aux_firstnan] = True
|
|
mask[aux_firstnan + 1:] = False
|
|
else:
|
|
mask[1:] = aux[1:] != aux[:-1]
|
|
|
|
ret = (aux[mask],)
|
|
if return_index:
|
|
ret += (perm[mask],)
|
|
if return_inverse:
|
|
imask = np.cumsum(mask) - 1
|
|
inv_idx = np.empty(mask.shape, dtype=np.intp)
|
|
inv_idx[perm] = imask
|
|
ret += (inv_idx,)
|
|
if return_counts:
|
|
idx = np.concatenate(np.nonzero(mask) + ([mask.size],))
|
|
ret += (np.diff(idx),)
|
|
return ret
|
|
|
|
def unique(a, return_index=False, axis=None):
|
|
"""
|
|
Find the unique elements of an array.
|
|
|
|
Returns the sorted unique elements of an array.
|
|
|
|
:param a: (*array_like*) Array to be sorted.
|
|
:param return_index: (*bool*) Optional, If True, also return the indices of ar (along the specified
|
|
axis, if provided, or in the flattened array) that result in the unique array.
|
|
:param axis: (*int or None*) Optional. Axis along which to operate on. If None, the array is
|
|
flattened.
|
|
|
|
:returns: (*NDArray*) Sorted unique elements of input array.
|
|
"""
|
|
if isinstance(a, list):
|
|
a = np.array(a)
|
|
if return_index:
|
|
r = ArrayUtil.uniqueIndex(a.asarray(), axis)
|
|
return np.NDArray(r[0]), np.NDArray(r[1])
|
|
else:
|
|
r = ArrayUtil.unique(a.asarray(), axis)
|
|
return np.NDArray(r)
|
|
|
|
def intersect1d(ar1, ar2, assume_unique=False, return_indices=False):
|
|
"""
|
|
Find the intersection of two arrays.
|
|
Return the sorted, unique values that are in both of the input arrays.
|
|
|
|
Parameters
|
|
----------
|
|
ar1, ar2 : array_like
|
|
Input arrays. Will be flattened if not already 1D.
|
|
assume_unique : bool
|
|
If True, the input arrays are both assumed to be unique, which
|
|
can speed up the calculation. If True but ``ar1`` or ``ar2`` are not
|
|
unique, incorrect results and out-of-bounds indices could result.
|
|
Default is False.
|
|
return_indices : bool
|
|
If True, the indices which correspond to the intersection of the two
|
|
arrays are returned. The first instance of a value is used if there are
|
|
multiple. Default is False.
|
|
|
|
Returns
|
|
-------
|
|
intersect1d : ndarray
|
|
Sorted 1D array of common and unique elements.
|
|
comm1 : ndarray
|
|
The indices of the first occurrences of the common values in `ar1`.
|
|
Only provided if `return_indices` is True.
|
|
comm2 : ndarray
|
|
The indices of the first occurrences of the common values in `ar2`.
|
|
Only provided if `return_indices` is True.
|
|
|
|
See Also
|
|
--------
|
|
numeric.lib.arraysetops : Module with a number of other functions for
|
|
performing set operations on arrays.
|
|
|
|
Examples
|
|
--------
|
|
>>> np.intersect1d([1, 3, 4, 3], [3, 1, 2, 1])
|
|
array([1, 3])
|
|
To intersect more than two arrays, use functools.reduce:
|
|
>>> from functools import reduce
|
|
>>> reduce(np.intersect1d, ([1, 3, 4, 3], [3, 1, 2, 1], [6, 3, 4, 2]))
|
|
array([3])
|
|
To return the indices of the values common to the input arrays
|
|
along with the intersected values:
|
|
>>> x = np.array([1, 1, 2, 3, 4])
|
|
>>> y = np.array([2, 1, 4, 6])
|
|
>>> xy, x_ind, y_ind = np.intersect1d(x, y, return_indices=True)
|
|
>>> x_ind, y_ind
|
|
(array([0, 2, 4]), array([1, 0, 2]))
|
|
>>> xy, x[x_ind], y[y_ind]
|
|
(array([1, 2, 4]), array([1, 2, 4]), array([1, 2, 4]))
|
|
"""
|
|
ar1 = np.asanyarray(ar1)
|
|
ar2 = np.asanyarray(ar2)
|
|
|
|
if not assume_unique:
|
|
if return_indices:
|
|
ar1, ind1 = unique(ar1, return_index=True)
|
|
ar2, ind2 = unique(ar2, return_index=True)
|
|
else:
|
|
ar1 = unique(ar1)
|
|
ar2 = unique(ar2)
|
|
else:
|
|
ar1 = ar1.ravel()
|
|
ar2 = ar2.ravel()
|
|
|
|
aux = np.concatenate((ar1, ar2))
|
|
if return_indices:
|
|
aux_sort_indices = np.argsort(aux)
|
|
aux = aux[aux_sort_indices]
|
|
else:
|
|
aux.sort()
|
|
|
|
mask = aux[1:] == aux[:-1]
|
|
int1d = aux[:-1][mask]
|
|
|
|
if return_indices:
|
|
ar1_indices = aux_sort_indices[:-1][mask]
|
|
ar2_indices = aux_sort_indices[1:][mask] - ar1.size
|
|
if not assume_unique:
|
|
ar1_indices = ind1[ar1_indices]
|
|
ar2_indices = ind2[ar2_indices]
|
|
|
|
return int1d, ar1_indices, ar2_indices
|
|
else:
|
|
return int1d |