如何在 Python 中通过行和列约束来改进数组矩阵 [0,1]?

How can I and improve array matrix [0,1] by row and column constraints in Python?

提问人:Maluma Corazón 提问时间:9/3/2023 最后编辑:CristiFatiMaluma Corazón 更新时间:9/3/2023 访问量:63

问:

假设我有一个矩阵数组表。

uvv = np.array([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]])

我将重点关注值为零的行,例如 然后,我想在某一列中,但该列不得在其他行中显示 1。根据 uvv 表,I 可以在列中随机 1 。row 2random 1 two or three timesrow 2row 21,2,3,7,8,9,10,11,12,14,16,18

这是我的目标示例,当在列中添加随机 1 时:2, 14, 18row 2

tem = np.array([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
                [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]])

谢谢。

Python 数组 列表 numpy 矩阵

评论


答:

0赞 Jesse Sealand 9/3/2023 #1

解决方案

解释作为注释包含在整个代码中。

# Loop over each column in array
for col_num in range(uvv.shape[1]):
    
    # Get column and list of non-zero row positions
    col_arr = uvv[:, col_num]
    index_pos = np.where(col_arr!=0)

    # If only zeroes exist in row, proceed
    if len(index_pos[0]) == 0:
        
        # Get number of times to insert a value (num_inserts)
        # Get row numbers to insert value into (row_inserts)
        num_inserts = random.choice([2,3])
        row_numbers = range(0, len(col_arr)-1)
        row_inserts = random.sample(row_numbers, num_inserts)
        
        # For each time to insert a value
        for i in range(num_inserts):
            
            # Insert value into selected row
            uvv[row_inserts[i], col_num] = 1
            print(f"Inserted value in row: {row_inserts[i]}, col: {col_num}")
0赞 CristiFati 9/3/2023 #2

不是 NumPy 专家,这里有一个有效的解决方案(当然还有其他更快、更优雅的解决方案)。

使用的功能:

code00.py

#!/usr/bin/env python

import sys

import numpy as np


def modify(arr, max_row_count=1, max_element_count=3, value=1):
    ret = arr.copy()  # Don't operate on original array
    rows = np.where(~ret.any(axis=1))[0]  # All rows that only have 0s
    for idx, row in enumerate(rows):
        if idx >= max_row_count:
            break
        column_choices = np.where(~ret.any(axis=0))[0]  # All columns that only have 0s
        #print(column_choices)
        columns = np.random.choice(
            column_choices,
            size=min(max_element_count, len(column_choices)),
            replace=False
        )  # Select randomly from (above) columns
        ret[row, columns] = value
    return ret


def main(*argv):
    arr0 = np.array([
        [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1-1, 0, 0, 0]
    ])
    print("Original:\n{:}".format(arr0))
    for i in range(3):
        arr = modify(arr0)
        print("\nModified (variant {:}):\n{:}".format(i + 1, arr))


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.\n")
    sys.exit(rc)

输出

(py_pc064_03.08_test0_lancer) [cfati@cfati-5510-0:/mnt/e/Work/Dev/StackExchange/StackOverflow/q077032322]> python ./code00.py 
Python 3.8.18 (default, Aug 25 2023, 13:20:30) [GCC 11.4.0] 064bit on linux

Original:
[[0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0]
 [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]

Modified (variant 1):
[[0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0]
 [1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0]
 [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]

Modified (variant 2):
[[0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0]
 [0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0]
 [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]

Modified (variant 3):
[[0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0]
 [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1]
 [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0]
 [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]

Done.
1赞 Corralien 9/3/2023 #3

您可以使用布尔掩码来查找行和可用列:

m1 = ~uvv.any(axis=1)  # rows with all zeroes
m2 = ~uvv.any(axis=0)  # columns with all zeroes

rows = np.nonzero(m1)[0]  # find rows to fill
cols = np.nonzero(m2)[0]  # find available columns

for row in rows:
    idx = np.random.choice(cols, np.random.randint(1, 4), replace=False)
    uvv[row, idx] = 1
    cols = np.setdiff1d(cols, idx)

输出:

>>> uvv
array([[0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
       [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0]])

# rows to fill
>>> rows
array([1])

# before the loop
>>> cols
[ 0  1  2  6  7  8  9 10 11 13 15 17]

# after the loop
[ 0  1  2  6  8  9 10 11 13 15]  # col 7 and 17 are not available now

评论

0赞 Maluma Corazón 9/4/2023
如果有一个可用的列,但我们在 2 到 3 之间随机以替换 1 ?当随机值超过可用列时,我该如何解决此问题?
0赞 Corralien 9/4/2023
这应该没什么大不了的。尝试将 替换为 。现在有效吗?np.random.randint(1, 4)1+np.random.randint(min(3, len(cols)))