首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在数组中的任意位置保持固定大小的唯一值,同时用掩码替换其他值?

如何在数组中的任意位置保持固定大小的唯一值,同时用掩码替换其他值?
EN

Stack Overflow用户
提问于 2021-09-30 04:13:03
回答 2查看 66关注 0票数 1

这可能是一个非常简单的问题,因为我仍然在探索Python。在这个问题上,我用的是numpy。更新日期为09/30/21:采用并修改了以下代码,以供将来参考。我还在循环中为数量少于所需大小的类添加了一个elif。有些代码可能是不必要的。

代码语言:javascript
复制
new_array = test_array.copy()
uniques, counts = np.unique(new_array, return_counts=True)
print("classes:", uniques, "counts:", counts)
for unique, count in zip(uniques, counts):
    #print (unique, count)
    if unique != 0 and count > 3:
        ids = np.random.choice(count, count-3, replace=False)
        new_array[tuple(i[ids] for i in np.where(new_array == unique))] = 0
    elif unique != 0 and count <= 3:
        ids = np.random.choice(count, count, replace=False)
        new_array[tuple(i[ids] for i in np.where(new_array == unique))] = unique

下面是的原始问题.

假设我有这样一个2D数组:

代码语言:javascript
复制
test_array = np.array([[0,0,0,0,0],
                      [1,1,1,1,1],
                      [0,0,0,0,0],
                      [2,2,2,4,4],
                      [4,4,4,2,2],
                      [0,0,0,0,0]])
print("existing classes:", np.unique(test_array))
# "existing classes: [0 1 2 4]"

现在,我希望在每个类中保持一个固定大小的(例如,2个值),即!= 0 (在本例中为两个1s、两个2s和两个4s),并将其余的替换为0。其中被替换的值是随机的,每次运行(或从一个种子)。

例如,使用run 1,我将拥有

代码语言:javascript
复制
([[0,0,0,0,0],
[1,0,0,1,0],
[0,0,0,0,0],
[2,0,0,0,4],
[4,0,0,2,0],
[0,0,0,0,0]])

如果再运行一次,可能是

代码语言:javascript
复制
([[0,0,0,0,0],
[1,1,0,0,0],
[0,0,0,0,0],
[2,0,2,0,4],
[4,0,0,0,0],
[0,0,0,0,0]])

等等,有人能帮我吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-30 05:41:07

我的策略是

创建一个初始化为所有零的新数组( value

  • ),查找每个类

  • 中的每个类

  • 中的元素,随机抽取两个元素以保持

  • 将新数组的这些元素设置为类

诀窍是保持索引的适当形状,以便保留原始数组的形状。

代码语言:javascript
复制
import numpy as  np
test_array = np.array([[0,0,0,0,0],
                      [1,1,1,1,1],
                      [0,0,0,0,0],
                      [2,2,2,4,4],
                      [4,4,4,2,2],
                      [0,0,0,0,0]])

def sample_classes(arr, n_keep=2, random_state=42):
    classes, counts = np.unique(test_array, return_counts=True)
    rng = np.random.default_rng(random_state)
    out = np.zeros_like(arr)
    for klass, count in zip(classes, counts):
        # Find locations of the class elements
        indexes = np.nonzero(arr == klass)
        # Sample up to n_keep elements of the class
        keep_idx = rng.choice(count, n_keep, replace=False)
        # Select the kept elements and reformat for indexing the output array and retaining its shape
        keep_idx_reshape = tuple(ind[keep_idx] for ind in indexes)
        out[keep_idx_reshape] = klass
    return out

你可以把它当作

代码语言:javascript
复制
In [3]: sample_classes(test_array)                                                                                                                                                                         [3/1174]
Out[3]:
array([[0, 0, 0, 0, 0],
       [0, 1, 1, 0, 0],
       [0, 0, 0, 0, 0],
       [2, 0, 0, 4, 0],
       [4, 0, 0, 2, 0],
       [0, 0, 0, 0, 0]])

In [4]: sample_classes(test_array, n_keep=3)
Out[4]:
array([[0, 0, 0, 0, 0],
       [1, 0, 1, 1, 0],
       [0, 0, 0, 0, 0],
       [0, 2, 0, 4, 0],
       [4, 4, 0, 2, 2],
       [0, 0, 0, 0, 0]])

In [5]: sample_classes(test_array, random_state=88)
Out[5]:
array([[0, 0, 0, 0, 0],
       [0, 0, 1, 1, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [4, 0, 4, 2, 2],
       [0, 0, 0, 0, 0]])

In [6]: sample_classes(test_array, random_state=88, n_keep=4)
Out[6]:
array([[0, 0, 0, 0, 0],
       [0, 1, 1, 1, 1],
       [0, 0, 0, 0, 0],
       [2, 2, 0, 4, 4],
       [4, 4, 0, 2, 2],
       [0, 0, 0, 0, 0]])
票数 0
EN

Stack Overflow用户

发布于 2021-09-30 04:38:09

这里是我不那么优雅的解决方案:

代码语言:javascript
复制
def unique(arr, num=2, seed=None):
    np.random.seed(seed)
    vals = {}
    for i, row in enumerate(arr):
        for j, val in enumerate(row):
            if val in vals and val != 0:
                vals[val].append((i, j))
            elif val != 0:
                vals[val] = [(i, j)]
    new = np.zeros_like(arr)
    for val in vals:
        np.random.shuffle(vals[val])
        while len(vals[val]) > num:
            vals[val].pop()
        for row, col in vals[val]:
            new[row,col] = val
    return new
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69386041

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档