我想简单地为数组的每个元素分配一个标签,基于它低于或高于某个阈值,并使用布尔索引解决这个问题:
def easy_labeling(arr, thresh=5):
negative_mask = arr < thresh
positive_mask = arr >= thresh
labels = np.empty_like(arr, dtype=str)
labels[negative_mask] = 'N'
labels[positive_mask] = 'P'
return labels
到目前为止,一切都很好。我创建了一些虚拟数组来检查它是否有效:
test_arr1 = np.arange(24).reshape((12,2))
test_arr1
>>> test_arr1
array([[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11],
[12, 13],
[14, 15],
[16, 17],
[18, 19],
[20, 21],
[22, 23]])
easy_labeling(test_arr1)
>>> array([['N', 'N'],
['N', 'N'],
['N', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P']], dtype='<U1')
test_arr2 = np.random.randint(12, size=(12,2))
test_arr2
>>> array([[ 1, 11],
[ 5, 6],
[11, 7],
[ 9, 4],
[11, 3],
[ 0, 9],
[ 0, 4],
[11, 8],
[ 3, 6],
[ 0, 1],
[ 5, 8],
[10, 4]])
easy_labeling(test_arr2)
>>> array([['N', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'N'],
['P', 'N'],
['N', 'P'],
['N', 'N'],
['P', 'P'],
['N', 'P'],
['N', 'N'],
['P', 'P'],
['P', 'N']], dtype='<U1')
......似乎确实如此。
但是,在我的特定应用程序中,出现了一些其他数组 - 相同的形状、类型和 dtype,但结果不同:
test_arr3 = np.array([[ 2, 0, 4, 4], [ 0, 2, 9, 11], [ 4, 4, 6, 10], [11, 5, 10, 15],
[ 5, 8, 0, 8], [ 3, 6, 5, 11], [ 6, 7, 2, 9], [ 1, 1, 1, 2], [ 9, 11, 3, 14], [ 8,
10, 7, 17], [10, 3, 11, 14], [ 7, 9, 8, 17]])
test_arr3 = test_arr3[:, 1:3]
test_arr3
>>> array([[ 0, 4],
[ 2, 9],
[ 4, 6],
[ 5, 10],
[ 8, 0],
[ 6, 5],
[ 7, 2],
[ 1, 1],
[11, 3],
[10, 7],
[ 3, 11],
[ 9, 8]])
easy_labeling(test_arr3):
>>> array([['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P'],
['P', 'P']], dtype='<U1')
--> 突然之间,所有元素都被标记为正数,即使数组中包含明显低于 5 的数字。据我所知,索引仍然有效,所以如果我要求 arr[mask],我会得到正确的元素,但是分配给它会产生这个错误的结果。
更奇怪的是:在写下这个问题时,我想简化上面的表达式,而不必做“test_arr3 = test_arr3[:, 1:3]”部分,所以我直接输入了我想要的数组:
test_arr4 = np.array([[0, 4], [2, 9], [4, 6], [5, 10], [8, 0], [6, 5], [7, 2], [1, 1],
[11, 3], [10, 7], [3, 11], [9, 8]])
test_arr4
>>> array([[ 0, 4],
[ 2, 9],
[ 4, 6],
[ 5, 10],
[ 8, 0],
[ 6, 5],
[ 7, 2],
[ 1, 1],
[11, 3],
[10, 7],
[ 3, 11],
[ 9, 8]])
easy_labeling(test_arr4)
>>> array([['N', 'N'],
['N', 'P'],
['N', 'P'],
['P', 'P'],
['P', 'N'],
['P', 'P'],
['P', 'N'],
['N', 'N'],
['P', 'N'],
['P', 'P'],
['N', 'P'],
['P', 'P']], dtype='<U1')
......突然它起作用了。即使数组是相同的(至少看起来如此)!
我确保所有测试数组都具有相同的类型、形状和 dtype:
for x in [test_arr1, test_arr2, test_arr3, test_arr4]:
... print(type(x), x.shape, x.dtype)
>>> <class 'numpy.ndarray'> (12, 2) int32
<class 'numpy.ndarray'> (12, 2) int32
<class 'numpy.ndarray'> (12, 2) int32
<class 'numpy.ndarray'> (12, 2) int32
我假设数组有某种我不知道的隐藏属性,整件事对我来说意义不大——有人知道吗?
一种解决方法似乎是使用 np.chararray(arr.shape, unicode=True) 而不是 np.empty_like(arr, dtype=str),但是我仍然想知道其他解决方案有什么问题。