2016-01-27 3 views
6

В Python можно проверить, содержит ли значение float целочисленное значение с использованием n.is_integer() на основе этого QA: How to check if a float value is a whole number.Numpy: проверьте, содержит ли массив с плавающей точкой целые числа

Имеет ли numpy аналогичную операцию, которая может быть применена к массивам? Что-то, что позволило бы следующее:

>>> x = np.array([1.0 2.1 3.0 3.9]) 
>>> mask = np.is_integer(x) 
>>> mask 
array([True, False, True, False], dtype=bool) 

можно сделать что-то вроде

>>> mask = (x == np.floor(x)) 

или

>>> mask = (x == np.round(x)) 

, но они связаны с вызовом дополнительные методы и создавая кучу временных массивов, можно было бы избежать.

Имеет ли numpy векторизованную функцию, которая проверяет дробные части поплавков способом, аналогичным float.is_integer Python?

ответ

4

Из того, что я могу сказать, нет такой функции, которая возвращает логический массив, указывающий, имеет ли поплавки дробную часть или нет. Самое близкое, что я могу найти, это np.modf, который возвращает дробные и целочисленные части, но создает два массива с плавающей точкой (по крайней мере временно), поэтому он может быть не лучшим по размеру.

Если вы счастливы работать на месте, вы можете попробовать что-то вроде:

>>> np.mod(x, 1, out=x) 
>>> mask = (x == 0) 

Это должно сохранить память по сравнению с использованием круглой или пола (где вы должны держать x вокруг), но, конечно, вы потеряете оригинал x.

Другой вариант - попросить его реализовать в Numpy или реализовать его самостоятельно.

+0

Забавно, что вы должны это упомянуть. Я спрашивал, потому что я думаю об этом. –

+0

РЕДАКТОР: Нет, не будет -> Не было бы битлод и быстрее здесь? EDIT: oh, right, они по своей сути применимы только к целым числам, а не к плавающим! Прошло слишком много времени, делая последнее целое число JS в последнее время ... – Job

1

Мне нужен был ответ на этот вопрос по несколько иной причине: проверка того, когда я могу преобразовать целый массив чисел с плавающей запятой в целые числа без потери данных.

ответ Hunse едва не работает для меня, за исключением того, что я, очевидно, не может использовать трюк на месте, так как мне нужно, чтобы иметь возможность отменить операцию:

if np.all(np.mod(x, 1) == 0): 
    x = x.astype(int) 

От там, я думал о следующий вариант, который, вероятно, работает быстрее во многих ситуациях:

x_int = x.astype(int) 
if np.all((x - x_int) == 0): 
    x = x_int 

причина заключается в том, что операция по модулю медленнее, чем вычитание. Однако теперь мы выполняем кастинг с целыми числами вперед - я не знаю, насколько быстро эта операция, относительно говоря. Но если больше всего ваших массивов являются целыми числами (они в моем случае), последняя версия почти наверняка быстрее.

Еще одно преимущество заключается в том, что вы можете заменить субстрат чем-то вроде np.isclose для проверки в пределах определенного допуска (конечно, вы должны быть осторожны здесь, поскольку усечение не является правильным округлением!).

x_int = x.astype(int) 
if np.all(np.isclose(x, x_int, 0.0001)): 
    x = x_int 

EDIT: Медленнее, но, возможно, стоит в зависимости от вашего сценария использования, также преобразования целых чисел в отдельности, если присутствует.

x_int = x.astype(int) 
safe_conversion = (x - x_int) == 0 
# if we can convert the whole array to integers, do that 
if np.all(safe_conversion): 
    x = x_int.tolist() 
else: 
    x = x.tolist() 
    # if there are _some_ integers, convert them 
    if np.any(safe_conversion): 
     for i in range(len(x)): 
      if safe_conversion[i]: 
       x[i] = int(x[i]) 

В качестве примера, где это важно: это работает для меня, потому что у меня есть редкие данные (что означает, в основном нули), которые я затем преобразовать в формат JSON, один раз и повторно использовать позже на сервере. Для float ujson преобразует их как [ ...,0.0,0.0,0.0,... ], а для ints, которые приводят к [...,0,0,0,...], сохраняя до половины количества символов в строке. Это уменьшает накладные расходы как на сервере (более короткие строки), так и на клиенте (более короткие строки, по-видимому, немного быстрее JSON-синтаксический анализ).

+0

Просто понял, что это мой собственный вопрос. Спасибо за хороший ответ. –

+1

Добро пожаловать! :) Я просто понял, что если _some_ элементов можно безопасно преобразовать, добавленные накладные расходы на это для меня это достойны, поэтому я добавил код для того, как это сделать. – Job

Смежные вопросы