def axis_as_object(arr, axis=-1):
    """cast the given axis of an array to a void object
    if the axis to be cast is contiguous, a view is returned, otherwise a copy is made
    this is useful for efficiently sorting by the content of an axis, for instance

    Parameters
    ----------
    arr : ndarray
        array to view as void object type
    axis : int
        axis to view as a void object type

    Returns
    -------
    ndarray
        array with the given axis viewed as a void object
    """
    shape = arr.shape
    # make axis to be viewed as a void object as contiguous items
    arr = np.ascontiguousarray(np.rollaxis(arr, axis, arr.ndim))
    # number of bytes in each void object
    nbytes = arr.dtype.itemsize * shape[axis]
    # void type with the correct number of bytes
    voidtype = np.dtype((np.void, nbytes))
    # return the view as such, with the reduced shape
    return arr.view(voidtype).reshape(np.delete(shape, axis))
def axis_as_object ( arr , axis = - 1 ) : shape = arr . shape arr = np . ascontiguousarray ( np . rollaxis ( arr , axis , arr . ndim ) ) nbytes = arr . dtype . itemsize * shape [ axis ] voidtype = np . dtype ( ( np . void , nbytes ) ) return arr . view ( voidtype ) . reshape ( np . delete ( shape , axis ) )
cast the given axis of an array to a void object
    if the axis to be cast is contiguous, a view is returned, otherwise a copy is made
    this is useful for efficiently sorting by the content of an axis, for instance

    Parameters
    ----------
    arr : ndarray
        array to view as void object type
    axis : int
        axis to view as a void object type

    Returns
    -------
    ndarray
        array with the given axis viewed as a void object