我有一个一维数组,它包含从0开始的标签。目标是确保每个唯一标签的计数>=常量(例如,10).如果不是,合并最近的标签到它,直到计数大于10.
下面是一个示例:
import random
import numpy as np
data = np.concatenate(([0]*5, [1]*10, [2]*15, [3]*10, [4]*12, [5]*5))
random.Random(4).shuffle(data)
print(data)
array([2, 3, 4, 5, 2, 4, 2, 4, 2, 2, 0, 4, 1, 4, 4, 5, 4, 2, 1, 3, 1, 1,
5, 0, 3, 3, 2, 2, 4, 4, 3, 3, 4, 4, 1, 2, 5, 1, 2, 2, 3, 3, 1, 0,
2, 3, 5, 0, 0, 1, 1, 3, 2, 4, 1, 2, 2])
逻辑应该是这样的:
从标签0
开始,因为0
的计数为5(< 10),通过将1
替换为0
将1
与0合并。那么标签0
有足够的计数(15)。
然后,继续到下一个满足条件的标签2
.
最后一个需要合并的标签是5
,应该替换为4
。
我想出了这个方法:循环np.unique(data)
并检查np.bincount(data)
的计数。然而,如果我们有一个大的data
数组,这种方法是缓慢的。
import random
data = np.concatenate(([0]*5, [1]*10, [2]*15, [3]*10, [4]*12, [5]*5))
random.Random(4).shuffle(data)
counts = np.bincount(data)
new_label = 0
count_num = 0
for label in np.unique(data):
if count_num > 0:
data[data==label] = label-1
count_num += counts[label]
if count_num >= 10:
count_num = 0
if label == np.unique(data)[-1] and counts[label] < 10:
data[data==label] = label-1
array([2, 3, 4, 4, 2, 4, 2, 4, 2, 2, 0, 4, 0, 4, 4, 4, 4, 2, 0, 3, 0, 0,
4, 0, 3, 3, 2, 2, 4, 4, 3, 3, 4, 4, 0, 2, 4, 0, 2, 2, 3, 3, 0, 0,
2, 3, 4, 0, 0, 0, 0, 3, 2, 4, 0, 2, 2])
有什么关于合并数据的想法吗?谢谢你,谢谢
2条答案
按热度按时间3bygqnnd1#
你的循环是低效的,因为你反复切片原始数组。只需运行
np.unique
并获取计数一次:输出量:
计时
在0-100的100 k随机值上
在0-1000的1 M随机值上
5uzkadbs2#
除非你有非常多的标签,否则Python循环不应该是太多的性能消耗。您可能希望基于数据中实际存在的标签进行合并(而不是增加/减少1)。这可以通过在当前索引上使用+1/-1而不是标签值来实现。
产出: