Подсчитайте, сколько значений попадает в каждую ячейку

#python #arrays #numpy #partition

#python #массивы #numpy #раздел

Вопрос:

Предположим, что у меня есть множество разделов P по интервалу [0,1) . P имеет длину N . Например:

 P = np.array([0,0.05,0.1,0.3,0.7,1])
  

которое делится [0,1) на следующие интервалы:

 [0,0.05), [0.05,0.1), [0.1,0.3), [0.3,0.7) , [0.7,1)
  

У меня есть другой массив U длины K более [0,1) , элементы которого находятся u i/K для i = 0,...,K-1 где 0<u<1/K . Например

 U = np.array([0.03,0.13,0.23,0.33,0.43,0.53,0.63,0.73,0.83,0.93])
  

Я хочу подсчитать количество элементов в, U которые попадают в каждый раздел j = 0, ..., N-1 . В этом примере мы имеем

 C = np.array([1,0,2,4,3])
  

Есть ли способ сделать это без использования цикла?

Ответ №1:

Одним из способов является использование np.searchsorted для получения индексов, в которые U должны быть вставлены элементы P для поддержания порядка, с последующим np.bincount подсчетом количества вхождений каждого индекса:

 np.bincount(np.searchsorted(P,U))[1:]
# array([1, 0, 2, 4, 3])
  

Или с np.digitize предположением, что ячейки всегда монотонно увеличиваются:

 np.bincount(np.digitize(U,P))[1:]
# array([1, 0, 2, 4, 3])
  

Подробные сведения

 P = np.array([0,0.05,0.1,0.3,0.7,1])
U = np.array([0.03,0.13,0.23,0.33,0.43,0.53,0.63,0.73,0.83,0.93])
  

Как упоминалось, np.searchsorted вернет индексы, в которые U должны быть вставлены элементы в P , чтобы последние оставались упорядоченными:

 s = np.searchsorted(P,U)
# array([1, 3, 3, 4, 4, 4, 4, 5, 5, 5])
  

Следующее, что мы хотим, это подсчитать количество вхождений каждого индекса. Для этого мы можем использовать np.bincount , который будет делать именно то, что мы хотим. Обратите внимание, что возвращаемый массив бинирования будет содержать до np.amax(x) 1 значений, что означает, что он также выведет количество 0 пропущенных значений, 2 в данном случае, которое соответствует интервалу [0.05,0.1) :

 np.bincount(s)[1:]
# array([1, 0, 2, 4, 3])