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

jtw3ybtb  于 12个月前  发布在  Python
关注(0)|答案(3)|浏览(114)

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

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]])

我将专注于具有全零值的行,例如row 2,然后,我想在row 2的某个列中random 1 two or three times,但该列在其他行中不得出现1。根据uvv表,我可以在1,2,3,7,8,9,10,11,12,14,16,18列的row 2中随机1。
这是我在row 22, 14, 18列中添加随机1时的目标示例:

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]])

谢谢.

q9rjltbz

q9rjltbz1#

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

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
zpjtge22

zpjtge222#

解决方案

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

# 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}")
wribegjk

wribegjk3#

不是 NumPy Maven,这里有一个解决方案(当然还有其他更快,更优雅的解决方案)。
使用的功能:

  • [NumPy]:numpy.
  • [NumPy]:numpy.any
  • [NumPy]:numpy.random.choice
  • 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.

相关问题