Numpy приведен от подписанного к неподписанному int с параметром same_kind - PullRequest
0 голосов
/ 20 июня 2019

В numpy, похоже, что я могу разыграть, используя same_kind от uint до int, но не от int до uint, что имеет смысл:

> np.array([0, 2], dtype=np.uint8).astype(np.int64, casting='same_kind')
array([0, 2])
> np.array([0, 2], dtype=np.int8).astype(np.uint64, casting='same_kind')
TypeError: Cannot cast array from dtype('int8') to dtype('uint64') according to the rule 'same_kind'

Я хочу разыграть вот такпосле проверки границ значений в массиве (чтобы я знал, что не потеряю данные).Но если я сделаю casting='unsafe' после проверки границ, я разрешу приведение, например, из.плавает (что я не хочу разрешать).Так как я могу разрешить int <=> кастинг uint, но запретить другие типы?

Ответы [ 2 ]

0 голосов
/ 20 июня 2019

На данный момент я просто хакуюсь вокруг этого, проверяя np.dtype(from_dtype).kind == 'i' and np.dtype(to_dtype).kind == 'u' и, если да, устанавливая casting = 'unsafe', но мне это кажется немного хакерским!

FWIW, вот функция I 'м используя сейчас:

def safe_np_int_conversion(int_array, dtype=np.uint8, copy=True):
    """
    A few functions require arrays of a certain type (e.g. np.int32, np.uint8).
    To allow functions to accept standard numpy integer arrays (usually of 
    dtype=np.int64) we cast but check bounds to avoid wrap-around
    conversion errors (numpy doesn't seem to provide this functionality)
    """
    int_array = np.array(int_array)
    if int_array.size == 0:
        return int_array.astype(dtype, copy=copy)  # Allow empty arrays of any type
    try:
        return int_array.astype(dtype, casting='safe', copy=copy)
    except TypeError:
        bounds = np.iinfo(dtype)
        if np.all(int_array >= bounds.min) and np.all(int_array <= bounds.max):
            if int_array.dtype.kind == 'i' and np.dtype(dtype).kind == 'u':
                # Allow casting from int to unsigned int, since we have checked bounds
                casting = 'unsafe'
            else:
                # Raise a TypeError when we try to convert from, e.g., a float.
                casting = 'same_kind'
            return int_array.astype(dtype, casting=casting, copy=copy)
        else:
            raise OverflowError("Cannot convert safely to {} type".format(dtype))
0 голосов
/ 20 июня 2019

np.int8 охватывает числа со знаком от -128 до 127, тогда как np.uint64 охватывает числа от 0 до 1.844e + 19. Это означает, что ваш приглушенный кастинг не сможет представлять отрицательные значения от np.int8.

Numpy работает так, чтобы возвращать согласованные dtypes, основываясь только на dtypes аргументов. Это очень важно, чтобы избежать

Не каждый подписанный int может быть безопасно приведен к беззнаковому int даже в большем интервале без знака.

В этом случае вы фактически потеряете свои данные и сделаете противоположное тому, что вы хотели с самого начала. Вот лучший способ:

np.array([0, 2], dtype=np.int8).view(np.uint64) 
...