#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.