我有一个大的numpy数组,我想使用以下条件进行填充:
我当前正在使用以下功能
def uniqify(in_array):
#warning: array is mutable and gets modified outside this scope
out_array = np.arange(in_array.size).reshape(in_array.shape)
return out_array.astype(np.float32)
但是,这违反了第一个条件,因为数组值上升到非常高的数字。由于在输入此函数之前我不知道这些数组的大小,所以我宁愿限制每个条目中可以包含的数字的大小。
有没有完美的解决方案来实现这一目标?
编辑
我目前正在查看numpy中的一些随机化功能,例如https://docs.scipy.org/doc/numpy/reference/generated/numpy.random.randn.html。
以下是我使用np.random.choice
制作的示例
import numpy as np
data = np.array([[1,1,1], [1,1,1], [1,1,1]])
size = np.size(data)
for i in range(20):
random_list = np.random.choice(size, size, replace= False)/(size-1)
print(random_list)
print('\ndone')
这会打印各种列表,编号范围从0到1,这很好,但是对于大型数据集,我可以想象到可能的样本之间的差异很小,以致于它们几乎相等。因此,我无法随机化,但需要以明确的目标为避免相邻单元格相等来驱动函数。我想数字可以从1画到9 ...
答案 0 :(得分:1)
正如Paul Panzer所说,可以构建规则的棋盘状图案:
def uniq(shape):
f = lambda *idx: np.mod(np.sum(idx, axis=0), 10)
return np.fromfunction(f, shape)
例如,uniq((5, 17))
是
[[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 0. 1. 2. 3. 4. 5. 6.]
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 0. 1. 2. 3. 4. 5. 6. 7.]
[ 2. 3. 4. 5. 6. 7. 8. 9. 0. 1. 2. 3. 4. 5. 6. 7. 8.]
[ 3. 4. 5. 6. 7. 8. 9. 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
[ 4. 5. 6. 7. 8. 9. 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 0.]]
没有相邻的元素相等。模数甚至可以取为mod 2,得到0-1数组。
如果您希望数组是随机的(或至少看起来是随机的),则分数步可以提供帮助。
def uniq(shape):
steps = 1 + np.mod(np.random.randint(1, 100, size=len(shape))*(np.sqrt(5)+1)/2, 8)
f = lambda *idx: np.mod(np.floor(np.random.uniform(0, 10) + np.moveaxis(idx, 0, -1).dot(steps)), 10)
return np.fromfunction(f, shape)
现在uniq((5, 17))
看起来很像
[[ 4. 8. 3. 7. 2. 7. 1. 6. 0. 5. 0. 4. 9. 3. 8. 3. 7.]
[ 0. 4. 9. 4. 8. 3. 7. 2. 7. 1. 6. 0. 5. 0. 4. 9. 3.]
[ 6. 1. 5. 0. 4. 9. 4. 8. 3. 7. 2. 7. 1. 6. 0. 5. 0.]
[ 2. 7. 1. 6. 1. 5. 0. 4. 9. 4. 8. 3. 7. 2. 7. 1. 6.]
[ 8. 3. 8. 2. 7. 1. 6. 1. 5. 0. 4. 9. 4. 8. 3. 7. 2.]]
第一个版本的所有步骤总计为1。步骤的计算基于黄金比率(np.sqrt(5)+1)/2
,因为黄金的倍数会产生均匀分布但看起来随机的数字。步数保证在1到9之间,因此在铺设地板并采用mod 10之后,每一步我们都可以保证使用不同的数字。