我试图弄清楚如何采用以下for循环,根据行中最低值的索引拆分数组并使用向量化。我看过这个link并且一直在尝试使用numpy.where函数,但目前还不成功。
例如,如果一个数组有 n 列,那么 col [0] 具有最低值的所有行都放在一个数组中,所有行都在哪里< em> col [1] 被放入另一个等等。
这是使用for循环的代码。
import numpy
a = numpy.array([[ 0. 1. 3.]
[ 0. 1. 3.]
[ 0. 1. 3.]
[ 1. 0. 2.]
[ 1. 0. 2.]
[ 1. 0. 2.]
[ 3. 1. 0.]
[ 3. 1. 0.]
[ 3. 1. 0.]])
result_0 = []
result_1 = []
result_2 = []
for value in a:
if value[0] <= value[1] and value[0] <= value[2]:
result_0.append(value)
elif value[1] <= value[0] and value[1] <= value[2]:
result_1.append(value)
else:
result_2.append(value)
print(result_0)
>>[array([ 0. 1. 3.]), array([ 0. 1. 3.]), array([ 0. 1. 3.])]
print(result_1)
>>[array([ 1. 0. 2.]), array([ 1. 0. 2.]), array([ 1. 0. 2.])]
print(result_2)
>>[array([ 3. 1. 0.]), array([ 3. 1. 0.]), array([ 3. 1. 0.])]
答案 0 :(得分:1)
首先,使用argsort
查看每行中最低值的位置:
>>> a.argsort(axis=1)
array([[0, 1, 2],
[0, 1, 2],
[0, 1, 2],
[1, 0, 2],
[1, 0, 2],
[1, 0, 2],
[2, 1, 0],
[2, 1, 0],
[2, 1, 0]])
请注意,只要行有0
,就是该行中的最小列。
现在您可以构建结果:
>>> sortidx = a.argsort(axis=1)
>>> [a[sortidx[:,i] == 0] for i in range(a.shape[1])]
[array([[ 0., 1., 3.],
[ 0., 1., 3.],
[ 0., 1., 3.]]),
array([[ 1., 0., 2.],
[ 1., 0., 2.],
[ 1., 0., 2.]]),
array([[ 3., 1., 0.],
[ 3., 1., 0.],
[ 3., 1., 0.]])]
因此,只需在列上使用一个循环即可完成,如果行数远远大于列数,则会产生巨大的加速。
答案 1 :(得分:0)
这不是最好的解决方案,因为它依赖于简单的python循环,并且在你开始处理大型数据集时效率不高但它应该让你开始。
重点是创建一个&#34;桶的数组&#34;它根据最长元素的深度存储数据。然后枚举values
中的每个元素,选择最小的元素并保存其偏移量,随后将其附加到每个a
的正确结果&#34; bucket&#34;。最后,我们在最后一个循环中打印出来。
使用循环解决方案:
import numpy
import pprint
# random data set
a = numpy.array([[0, 1, 3],
[0, 1, 3],
[0, 1, 3],
[1, 0, 2],
[1, 0, 2],
[1, 0, 2],
[3, 1, 0],
[3, 1, 0],
[3, 1, 0]])
# create a list of results as big as the depth of elements in an entry
results = list()
for l in range(max(len(i) for i in a)):
results.append(list())
# don't do the following because all the references to the lists will be the same and you get dups:
# results = [[]]*max(len(i) for i in a)
for value in a:
res_offset, _val = min(enumerate(value), key=lambda x: x[1]) # get the offset and min value
results[res_offset].append(value) # store the original Array obj in the correct "bucket"
# print for visualization
for c, r in enumerate(results):
print("result_%s: %s" % (c, r))
输出:
result_0:[array([0,1,3]),array([0,1,3]),array([0,1,3])]
result_1:[array([1,0,2]),array([1,0,2]),array([1,0,2])]
result_2:[array([3,1,0]),array([3,1,0]),array([3,1,0])]
答案 2 :(得分:0)
我找到了一种更简单的方法。我希望我正确地解释OP。
我的感觉是OP想要根据一些条件创建一个较大阵列的片段。
请注意,上面创建数组的代码似乎不起作用 - 至少在python 3.5中。我按如下方式生成了数组。
a = np.array([0., 1., 3., 0., 1., 3., 0., 1., 3., 1., 0., 2., 1., 0., 2.,1., 0., 2.,3., 1., 0.,3., 1., 0.,3., 1., 0.]).reshape([9,3])
接下来,我将原始数组切成较小的数组。 Numpy
已经内置了帮助。
result_0 = a[np.logical_and(a[:,0] <= a[:,1],a[:,0] <= a[:,2])]
result_1 = a[np.logical_and(a[:,1] <= a[:,0],a[:,1] <= a[:,2])]
result_2 = a[np.logical_and(a[:,2] <= a[:,0],a[:,2] <= a[:,1])]
这将生成符合给定条件的新numpy
数组。
请注意,如果用户想要将这些单独的行转换为列表或数组,他/她只需输入以下代码即可获得结果。
result_0 = [np.array(x) for x in result_0.tolist()]
result_0 = [np.array(x) for x in result_1.tolist()]
result_0 = [np.array(x) for x in result_2.tolist()]
这应该产生OP中要求的结果。