如何用另一个蒙版数组的值填充蒙版2D数组?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何用另一个蒙版数组的值填充蒙版2D数组?相关的知识,希望对你有一定的参考价值。

我试图通过交叉重叠从两个父代生成两个子代。我想固定父A的一个部分,并用父B的元素填充空白。

我可以屏蔽两个父代,并在另一个数组中获得元素,但我无法用父代B中的填充元素来填补父代A中固定部分的空白。

这是我目前试过的。

    import numpy as np
    from numpy.random import default_rng
    rng = default_rng()

    numMachines = 5
    numJobs = 5

    population =[[[4, 0, 2, 1, 3],
                    [4, 2, 0, 1, 3],
                    [4, 2, 0, 1, 3],
                    [4, 0, 3, 2, 1],
                    [2, 3, 4, 1, 0]], 

                    [[2, 0, 1, 3, 4],
                    [4, 3, 1, 2, 0],
                    [2, 0, 3, 4, 1],
                    [4, 3, 1, 0, 2],
                    [4, 0, 3, 1, 2]]]

    parentA = np.array(population[0])
    parentB = np.array(population[1])

    childA = np.zeros((numJobs, numMachines))
    np.copyto(childA, parentA)

    childB = np.zeros((numJobs, numMachines))
    np.copyto(childB, parentB)

    subJobs = np.stack([rng.choice(numJobs ,size=int(np.max([2, np.floor(numJobs/2)])), replace=False) for i in range(numMachines)])

    maskA = np.stack([(np.isin(childA[i], subJobs[i])) for i in range(numMachines)])
    invMaskA = np.invert(maskA)

    maskB = np.stack([(np.isin(childB[i], subJobs[i])) for i in range(numMachines)])
    invMaskB = np.invert(maskB)

    maskedChildAFixed = np.ma.masked_array(childA, maskA)
    maskedChildBFixed = np.ma.masked_array(childB, maskB)

    maskedChildAFill = np.ma.masked_array(childA, invMaskA)
    maskedChildBFill = np.ma.masked_array(childB, invMaskB)

    maskedChildAFill = np.stack([maskedChildAFill[i].compressed() for i in range(numMachines)])
    maskedChildBFill = np.stack([maskedChildBFill[i].compressed() for i in range(numMachines)])

EDIT:

抱歉,我昨天对这个问题太沮丧了,忘了再补充一些信息以使其更加清晰。首先,我已经固定了代码,所以现在只需要复制和粘贴就可以运行了(我忘记添加一些导入调用和一些变量)。

这是来自父A的固定部分,在子A中不会改变。

>>> print(maskedChildAFixed)
[[-- 0.0 2.0 -- 3.0]
 [4.0 -- 0.0 1.0 --]
 [4.0 -- -- 1.0 3.0]
 [-- 0.0 3.0 2.0 --]
 [-- -- 4.0 1.0 0.0]]

我需要用来自父B的填充部分来填充这些空白部分。

>>> print(maskedChildBFill)
[[1. 4.]
 [3. 2.]
 [2. 0.]
 [4. 1.]
 [3. 2.]]

为了使我的子代合法,我不能在每一行中重复一个整数。如果我尝试使用 "np.na.filled() "函数与压缩的 maskedChildBFill一起使用,它会给我一个错误。

>>> print(np.ma.filled(maskedChildAFixed, fill_value=maskedChildBFill)) 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\Rafael\.conda\envs\CoutoBinario\lib\site-packages\numpy\ma\core.py", line 639, in filled
    return a.filled(fill_value)
  File "C:\Users\Rafael\.conda\envs\CoutoBinario\lib\site-packages\numpy\ma\core.py", line 3752, in filled
    np.copyto(result, fill_value, where=m)
  File "<__array_function__ internals>", line 6, in copyto
ValueError: could not broadcast input array from shape (5,2) into shape (5,5)

现在我把压缩填充部分的代码部分(第46行和第47行)加上注释。它不会删除maskedChildBFill中的空白处,这样就保留了矩阵的大小。

>>> print(np.ma.filled(maskedChildAFixed, fill_value=maskedChildBFill))
[[2. 0. 2. 3. 3.]
 [4. 3. 0. 1. 0.]
 [4. 0. 3. 1. 3.]
 [4. 0. 3. 2. 2.]
 [4. 0. 4. 1. 0.]]

看看我是如何得到一个无效的个体的?请注意第1行中重复的整数,个体应该是这样的。

[[1.0 0.0 2.0 4.0 3.0]
 [4.0 3.0 0.0 1.0 2.0]
 [4.0 2.0 0.0 1.0 3.0]
 [4.0 0.0 3.0 2.0 1.0]
 [3.0 2.0 4.0 1.0 0.0]]

我希望这个更新能让你更容易理解我在做什么。感谢到目前为止所有的帮助!<3

EDIT 2

我可以通过将所有的东西都转换为list,然后用for循环来替代这些值,但这应该是超级慢的。也许有一种方法可以用numpy来实现。

maskedChildAFill = maskedChildAFill.tolist()
maskedChildBFill = maskedChildBFill.tolist()

maskedChildAFixed = maskedChildAFixed.tolist()
maskedChildBFixed = maskedChildBFixed.tolist()

for i in range(numMachines):
    counterA = 0
    counterB = 0

    for n, j in enumerate(maskedChildAFixed[i]):
        if maskedChildAFixed[i][n] is None:
            maskedChildAFixed[i][n] = maskedChildBFill[i][counterA]
            counterA += 1

    for n, j in enumerate(maskedChildBFixed[i]):
        if maskedChildBFixed[i][n] is None:
            maskedChildBFixed[i][n] = maskedChildAFill[i][counterB]
            counterB += 1
答案

我想你要找的是这个。

parentA = np.array(population[0])
parentB = np.array(population[1])

childA = np.zeros((numJobs, numMachines))
np.copyto(childA, parentA)

childB = np.zeros((numJobs, numMachines))
np.copyto(childB, parentB)

subJobs = np.stack([rng.choice(numJobs ,size=int(np.max([2, np.floor(numJobs/2)])), replace=False) for i in range(numMachines)])

maskA = np.stack([(np.isin(childA[i], subJobs[i])) for i in range(numMachines)])
invMaskA = np.invert(maskA)

maskB = np.stack([(np.isin(childB[i], subJobs[i])) for i in range(numMachines)])
invMaskB = np.invert(maskB)

maskedChildAFixed = np.ma.masked_array(childA, maskA)
maskedChildBFixed = np.ma.masked_array(childB, maskB)

maskedChildAFill = np.ma.masked_array(childB, invMaskA)
maskedChildBFill = np.ma.masked_array(childA, invMaskB)

from operator import and_
crossA = np.ma.array(maskedChildAFixed.filled(0)+maskedChildAFill.filled(0),mask=list(map(and_,maskedChildAFixed.mask,maskedChildAFill.mask)))
crossB = np.ma.array(maskedChildBFixed.filled(0)+maskedChildBFill.filled(0),mask=list(map(and_,maskedChildBFixed.mask,maskedChildBFill.mask)))

请注意,我改变了行 maskedChildAFill = np.ma.masked_array(childB, invMaskA) 以符合你的问题描述。如果这不是你想要的,只需把它改回原来的代码即可。最后两行应该能帮你完成工作。

输出。

crossA
[[4.0 0.0 2.0 1.0 4.0]
 [4.0 2.0 0.0 2.0 0.0]
 [2.0 2.0 3.0 1.0 3.0]
 [4.0 3.0 3.0 2.0 2.0]
 [2.0 0.0 4.0 1.0 0.0]]
crossB
[[2.0 0.0 1.0 1.0 4.0]
 [4.0 2.0 0.0 2.0 0.0]
 [2.0 2.0 3.0 1.0 1.0]
 [4.0 3.0 3.0 2.0 2.0]
 [4.0 0.0 4.0 1.0 2.0]]

EDIT: 根据OP对问题的编辑,这将是一个有效的目的。

maskedChildAFixed[np.where(maskA)] = maskedChildBFill.ravel()
maskedChildBFixed[np.where(maskB)] = maskedChildAFill.ravel()

产出示例: maskedChildAFixed:

[[4.0 0.0 2.0 1.0 3.0]
 [4.0 2.0 0.0 1.0 3.0]
 [3.0 2.0 0.0 1.0 4.0]
 [4.0 0.0 3.0 2.0 1.0]
 [1.0 3.0 4.0 2.0 0.0]]

以上是关于如何用另一个蒙版数组的值填充蒙版2D数组?的主要内容,如果未能解决你的问题,请参考以下文章

将蒙版阵列 2d 应用到 3d

SciPy 创建 2D 多边形蒙版

如何用另一个数组创建或填充一个 numpy 数组?

如何用越来越多的数字填充二维数组?

如何让蒙版数组为pyplot中的整个段着色?

html5 canvas系列教程-像素操作(反色,黑白,亮度,复古,蒙版,透明)