Привет! В настоящее время я делаю следующее, чтобы найти все уникальные предметы в нескольких сериях панд:
In [44]: data = [Series([1,2,7,4]), Series([2,5,3,1]), Series([3, 2, 4])]
In [45]: counts = Counter(chain.from_iterable(data))
In [46]: unique_occurrences = [item for item, count in counts.items() if count == 1]
In [47]: unique_occurrences
Out[47]: [7, 5]
Есть ли способ ускорить это, поскольку реальные данные велики.
Благодарю.
Подход № 1
Здесь один массив на основе NumPy -
a = np.concatenate(data)
unq,c = np.unique(a, return_counts=1)
out = unq[c==1]
Подход № 2 (для положительных целых данных)
Для положительных данных целых чисел, мы можем использовать np.bincount
, чтобы получить out
непосредственно из - a
out = np.flatnonzero(np.bincount(a)==1) # a from app#1
Подход № 3
Если мы хотим использовать counts
, которые мы могли бы предпочесть при работе с очень большим числом рядов, конкатенация могла бы быть медленнее в этом сценарии -
k = np.array(list(counts.keys()))
v = np.array(list(counts.values()))
out = k[v==1]
Подход № 4 (для положительных целых данных)
С большим количеством рядов, содержащих положительные целые числа, мы можем использовать bincount
для каждого и, таким образом, избежать конкатенации -
L = max([i.max() for i in data])+1
out = np.flatnonzero(np.sum([np.bincount(i,minlength=L) for i in data],axis=0)==1)
Подход № 5 (для положительных целых данных)
Это может быть улучшено с точки зрения эффективности памяти, например, так:
L = max([i.max() for i in data])+1
sums = np.zeros(L,dtype=int)
for i in data:
sums += np.bincount(i,minlength=L)
out = np.flatnonzero(sums==1)
Мы можем использовать pd.concat
в сочетании с value_counts
и применять логическое индексирование:
v = pd.concat(data).value_counts()
v.index[v == 1].to_numpy()
Который дает
array([7, 5], dtype=int64)
Заметка
Если ваша версия для панд <0.24.0, используйте вместо:
v.index[v == 1].values
Узнайте больше здесь.