如何删除重复项并强制numpy数组中的元素在给定范围内唯一?

时间:2019-04-25 13:43:20

标签: python numpy permutation

在差异进化的情况下,突变期间,最常用的公式是

arr[a] = (arr[b] + M * (arr[c] - arr[d])) % arr.shape[1]

哪里
arr是由非负整数组成的2d数组,因此每一行中的所有元素都是唯一的,
a代表arr的每一行,
M是介于0到2之间的变异常数,
bcd是3个唯一的随机数。

但是,在使用此公式时,我发现arr[a]具有基于arr[b]arr[c]arr[d]的值的重复值。我希望在arr[a]中只有唯一的数字。如何使用Numpy?

例如

arr[a] = [2, 8, 4, 9, 1, 6, 7, 3, 0, 5]
arr[b] = [3, 5, 1, 2, 9, 8, 0, 6, 7, 4]
arr[c] = [2, 3, 8, 4, 5, 1, 0, 6, 9, 7]
arr[d] = [6, 1, 9, 2, 7, 5, 8, 0, 3, 4]

应用公式时,arr[a]变为[9, 7, 0, 4, 7, 4, 2, 2, 3, 7]。但是我希望它在0arr.shape[1]之间只有唯一的数字。如果愿意有意义地使用M,arr [b],arr [c]和arr [d],我愿意修改突变函数。

3 个答案:

答案 0 :(得分:1)

尝试执行以下操作:

list(set(arr[a])) 

答案 1 :(得分:1)

这是解决问题的完全不同的方法,但是由于您似乎正在使用排列,因此我不确定数值差异是否有意义。但是,您可以从排列(即向量的重新排序)方面看到问题。除了考虑两个向量之间的差异,还可以考虑将您从一个向量转移到另一个向量的置换,并且可以考虑对向量应用置换,而不是将两个向量相加。如果您想要一个M参数,也许这就是您应用排列的次数? (假设这是一个非负整数)

这是如何实现此目的的基本思想:

import numpy as np

# Finds the permutation that takes you from vector a to vector b.
# Returns a vector p such that a[p] = b.
def permutation_diff(a, b):
    p = np.zeros_like(a)
    p[a] = np.arange(len(p), dtype=p.dtype)
    return p[b]

# Applies permutation p to vector a, m times.
def permutation_apply(a, p, m=1):
    out = a.copy()
    for _ in range(m):
        out = out[p]
    return out

# Combination function
def combine(b, c, d, m):
    return permutation_apply(b, permutation_diff(d, c), m)

# Test
b = np.array([3, 5, 1, 2, 9, 8, 0, 6, 7, 4])
c = np.array([2, 3, 8, 4, 5, 1, 0, 6, 9, 7])
d = np.array([6, 1, 9, 2, 7, 5, 8, 0, 3, 4])
m = 1
a = combine(b, c, d, m)
print(a)
# [2 7 0 4 8 5 6 3 1 9]

由于您正在处理以矩阵形式排列的许多矢量,因此您可能更喜欢上述函数的矢量化版本。您可以使用类似的东西(在这里我假设M是整个算法的固定参数,而不是每个人):

import numpy as np

# Finds the permutations that takes you from vectors in a to vectors in b.
def permutation_diff_vec(a, b):
    p = np.zeros_like(a)
    i = np.arange(len(p))[:, np.newaxis]
    p[i, a] = np.arange(p.shape[-1], dtype=p.dtype)
    return p[i, b]

# Applies permutations in p to vectors a, m times.
def permutation_apply_vec(a, p, m=1):
    out = a.copy()
    i = np.arange(len(out))[:, np.newaxis]
    for _ in range(m):
        out = out[i, p]
    return out

# Combination function
def combine_vec(b, c, d, m):
    return permutation_apply_vec(b, permutation_diff_vec(d, c), m)

# Test
np.random.seed(100)
arr = np.array([[2, 8, 4, 9, 1, 6, 7, 3, 0, 5],
                [3, 5, 1, 2, 9, 8, 0, 6, 7, 4],
                [2, 3, 8, 4, 5, 1, 0, 6, 9, 7],
                [6, 1, 9, 2, 7, 5, 8, 0, 3, 4]])
n = len(arr)
b = arr[np.random.choice(n, size=n)]
c = arr[np.random.choice(n, size=n)]
d = arr[np.random.choice(n, size=n)]
m = 1
arr[:] = combine_vec(b, c, d, m)
print(arr)
# [[3 6 0 2 5 1 4 7 8 9]
#  [6 1 9 2 7 5 8 0 3 4]
#  [6 9 2 3 5 0 4 1 8 7]
#  [2 6 5 4 1 9 8 0 7 3]]

答案 2 :(得分:0)

这是一个示例,可以做什么:

array = np.array([9, 7, 0, 4, 7, 4, 2, 2, 3, 7])
shape = array.shape[0]
array = list(set(array))
for i in range(shape):
    if i not in array:
        array.append(i)
array = np.array(array)

如果要填写的索引号重复,则逻辑略有差异。但想法是那样的。希望我能对您有所帮助。