Подсчет количества вхождений массива в массиве двумерных массивов numpy

#python #arrays #numpy

#питон #массивы #тупица

Вопрос:

У меня есть массив массивов numpy 2D:

samples = np.array([[1,2,3], [2,3,4], [4,5,6], [1,2,3], [2,3,4], [2,3,4]])

Мне нужно посчитать, сколько раз массив внутри массива встречается выше, например:

counts = [[1,2,3]:2, [2,3,4]:3, [4,5,6]:1]

Я не уверен, как это можно подсчитать или перечислить так, как я описал выше, чтобы узнать, какие массивы и счетчики связаны друг с другом, любая помощь будет признательна. Спасибо!

Ответ №1:

Все, что вам нужно, находится непосредственно в numpy :

 import numpy as np  a = np.array([[1,2,3], [2,3,4], [4,5,6], [1,2,3], [2,3,4], [2,3,4]])  print(np.unique(a, axis=0, return_counts=True))  

Результат:

 (array([[1, 2, 3],  [2, 3, 4],  [4, 5, 6]]), array([2, 3, 1], dtype=int64))  

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

Если вам нужно пройти через них попарно:

 unique_rows, counts = np.unique(a, axis=0, return_counts=True)  for row, c in zip(unique_rows, counts):  print(row, c)  

Результат:

 [1 2 3] 2 [2 3 4] 3 [4 5 6] 1  

Ответ №2:

Вот способ обойтись без использования большей части библиотеки numpy:

 import numpy as np samples = np.array([[1,2,3], [2,3,4], [4,5,6], [1,2,3], [2,3,4], [2,3,4]])  result = {}  for row in samples:  inDictionary = False  for check in range(len(result)):  if np.all(result[str(check)][0] == row):  result[str(check)][1] = 1  inDictionary = True  else:  pass  if inDictionary == False:  result[str(len(result))] = [row, 1]   print("------------------") print(result)  

Этот метод создает словарь под названием result, а затем просматривает различные вложенные списки в образцах и проверяет, есть ли они уже в словаре. Если они есть, то количество раз, сколько раз оно появлялось, увеличивается на 1. В противном случае он создает новую запись для этого массива. Теперь к сохраненным подсчетам и значениям можно получить доступ, используя result["index"] нужный индекс и result["index"][0] — значение массива amp; result["index"][1] — количество раз, когда оно появлялось.

Комментарии:

1. Учитывая , что OP уже использует numpy , не согласитесь ли вы, что использование сильных сторон очень быстрой библиотеки на самом деле лучше, чем написание решения на основе Python?

2. да, это правда. Я просто хотел попробовать и дать возможность обойтись без этого.

Ответ №3:

Существует относительно быстрый метод Python по сравнению с другими решениями на Python (нет numpy ) :

 from collections import Counter gt;gt;gt; Counter(map(tuple, samples.tolist())) # convert to dict if you need it Counter({(1, 2, 3): 2, (2, 3, 4): 3, (4, 5, 6): 1})  

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

 import benchit %matplotlib inline benchit.setparams(rep=3)  sizes = [3, 10, 30, 100, 300, 900, 3000, 9000, 30000, 90000, 300000, 900000, 3000000] arr = np.random.randint(0,10, size=(sizes[-1], 3)).astype(int)   def count_python(samples):  return Counter(map(tuple, samples.tolist()))   def count_numpy(samples):  return np.unique(samples, axis=0, return_counts=True)  fns = [count_python, count_numpy] in_ = {s: (arr[:s],) for s in sizes} t = benchit.timings(fns, in_, multivar=True, input_name='Number of items') t.plot(logx=True, figsize=(12, 6), fontsize=14)  

Обратите внимание, что это arr.tolist() занимает около 0,8 секунды/3 м вычислительного времени Python.

введите описание изображения здесь