我有一个大的numpy 1-d包含大约700,000个类。另外,我有另一个类似大小的数组,它包含类的新值。
示例数组
original_classes = np.array([0,1,2,3,4,5,6,7,8,9,10,10])
new_classes = np.array([1,0,1,2,2,10,1,6,6,9,5,12])
所需的输出
>>> reclassify_function(original_classes, new_classes)
array([ 1, 1, 1, 1, 1, 12, 1, 1, 9, 12, 12])
困难在于有多种阶级关系。
原始类1应该获得0的新值,这意味着0和1是相等的类,并且所有出现的这些值都应该分配给相同的新类号。原始类2应归类为1,这意味着类2等于0级和1级。因此,原始类0-2应分配给相同的新类号等...
当我使用大型数组时,我希望将重分类函数进行矢量化。
答案 0 :(得分:1)
您可以使用scipy.sparse.csgraph.connected_components重新标记您的课程。对于您的示例数据:
from scipy.sparse import csr_matrix
from scipy.sparse.csgraph import connected_components
A = np.array([0,1,2,3,4,5, 6,7,8,9,10,10])
B = np.array([1,0,1,2,2,10,1,6,6,9,5 ,12])
N = max(A.max(), B.max()) + 1
weights = np.ones(len(A), int)
graph = csr_matrix((weights, (A, B)), shape=(N, N))
n_remaining, mapping = connected_components(graph, directed=False)
print mapping[A]
给出:
[0 0 0 0 0 1 0 0 0 2 1 1]
这些是重新标记的类。我相信你可以弄清楚如何根据输入数据来表达这些。注意为了获得最佳性能,“原始”和“新”类应该是没有间隙的单个连续整数范围。
答案 1 :(得分:0)
这不是矢量化解决方案,在我的笔记本电脑上花了大约一个小时。这会创建一个名为class_sets
的集合列表;每一组都是等价类的集合。
original_classes = np.random.randint(0,20000,700000)
new_classes = np.random.randint(0,20000,700000)
pairs = zip(original_classes, new_classes)
class_sets = [set(next(pairs))]
for i,p in enumerate(pairs):
ps = set(p)
intsect = [ps.intersection(cs) for cs in class_sets]
if any([ps.intersection(cs) for cs in class_sets]):
index = np.argmax(intsect)
class_sets[index] = class_sets[index].union(ps)
else:
class_sets.append(ps)