numpy 如何为矩阵中的元素增加无

xdyibdwo  于 2023-01-17  发布在  其他
关注(0)|答案(3)|浏览(118)

我想生成一个矩阵Z_comb,它由大小为(len(m),len(m))的元素z组成,z的值从0到(m-1)。
例如:
m =[m [0],[m [1],[m [2]]=[4,2,1]。
对于m [0]= 2,则z [0]=[0,1]并且len(m [0])= 2
对于m [1]= 4,则z [1]=[0,1,2,3]并且len(m [1])= 4
对于m [2]= 1,则z [2]=[0]并且len(m [2])= 1
预期内容包括:对于m [0]= 2,则z [0]=[0,1,无,无]并且len(m [0])= 4
对于m [1]= 4,则z [1]=[0,1,2,3]并且len(m [1])= 4
对于m [2]= 1,则z [2]=[0,无,无,无]并且len(m [2])= 4
下面是我编写的代码:

import numpy as np
    m = np.array([2,4,1])
    Z_comb = np.array([np.arange(0,m[0]),np.arange(0,m[1]),np.arange(0,m[2])],dtype=object)

打印结果为
Z_comb =数组([数组([0,1]),数组([0,1,2,3]),数组([0])],数据类型=对象)
预期结果:
Z_comb =[[0,1,无,无],[0,1,2,3],[0,无,无,无]]
有谁能告诉我代码需要修改什么吗?谢谢。

f87krz0w

f87krz0w1#

可以使用列表解析生成矩阵Z_comb,其中对于m中的每个元素,创建一个从0m[i]-1的整数列表,然后将None追加到列表末尾,直到列表长度为4。下面是如何执行此操作的示例:

m = [2, 4, 1]
Z_comb = [[i if i < m[j] else None for i in range(4)] for j in range(len(m))]

这将生成预期结果:

[[0, 1, None, None], [0, 1, 2, 3], [0, None, None, None]]

如果愿意,可以将Z_comb转换为numpy数组。
这个解决方案 * 确实 * 生成了您所说的预期结果,尽管它 * 没有 * 大小为(len(m), len(m)),而您 * 也 * 在开始时提到了它应该具有的大小。

k75qkfdt

k75qkfdt2#

numpy 解决方案

您可以使用广播:

# input
m = np.array([2,4,1])

N = m.max()
# 4
a = np.arange(N) 
# array([0, 1, 2, 3])

Z_comb = np.where(m[:,None] >= a, a, np.nan)
  • 注意:输出包含nan而不是None,因为None在numpy数组中实际上没有意义(这将强制object dtype并阻止矢量化)。*

输出Z_comb

array([[ 0.,  1.,  2., nan],
       [ 0.,  1.,  2.,  3.],
       [ 0.,  1., nan, nan]])
纯Python解决方案

如果你想要一个纯粹的python解决方案:

N = max(m)
Z_comb = [list(range(x))+[None]*(N-x) for x in m]

输出:

[[0, 1, None, None],
 [0, 1, 2, 3],
 [0, None, None, None]]
vh0rcniy

vh0rcniy3#

这是一个填充问题,经常在SO上出现。
因为你想用None填充,我们必须创建一个object dtype数组,这里有一个简单的方法:

In [60]: res = np.empty((len(m), max(m)), object)    
In [61]: res
Out[61]: 
array([[None, None, None, None],
       [None, None, None, None],
       [None, None, None, None]], dtype=object)

我可以从一个0数组开始,或者用np.nan填充float dtype。
然后只需将所需范围分配给每一行:

In [62]: for i,v in enumerate(m):
    ...:     res[i,:v] = np.arange(v)
    ...:     
In [63]: res
Out[63]: 
array([[0, 1, None, None],
       [0, 1, 2, 3],
       [0, None, None, None]], dtype=object)

将其与您创建不规则数组的方法进行比较:

In [64]: np.array([np.arange(v) for v in m], object)
Out[64]: array([array([0, 1]), array([0, 1, 2, 3]), array([0])], dtype=object)

一种更快的填充方式是从布尔掩码开始,例如:

In [65]: np.arange(4)<m[:,None]
Out[65]: 
array([[ True,  True, False, False],
       [ True,  True,  True,  True],
       [ True, False, False, False]])

简单地乘以arange得到一个填充0的数组:

In [66]: np.arange(4) * _
Out[66]: 
array([[0, 1, 0, 0],
       [0, 1, 2, 3],
       [0, 0, 0, 0]])

您可以看到该掩码如何与res的非None元素相关联:

In [67]: res[Out[65]]
Out[67]: array([0, 1, 0, 1, 2, 3, 0], dtype=object)

itertools具有一个zip_longest

In [79]: list(zip(*zip_longest(*(list(range(i)) for i in m))))
Out[79]: [(0, 1, None, None), (0, 1, 2, 3), (0, None, None, None)]

In [80]: np.array(_)
Out[80]: 
array([[0, 1, None, None],
       [0, 1, 2, 3],
       [0, None, None, None]], dtype=object)

相关问题