python如何替换array(x,n)中每个x的第一个f(x)值

Posted

技术标签:

【中文标题】python如何替换array(x,n)中每个x的第一个f(x)值【英文标题】:python How to replace the first f(x) values of each x in array(x,n) 【发布时间】:2018-01-20 02:05:24 【问题描述】:

我想将数组a 每一行中的前x 值替换为1,并保留所有其他值NaN。然而,前 x 值在每一行中都会发生变化,并由列表 b 确定。

由于我对数组不是很熟悉,我想我可以使用如下所示的 for 循环来执行此操作,但这不起作用 (我从How to set first N elements of array to zero? 获得了关于数组替换基础知识的灵感)。

In:
a = np.empty((3,4))
a.fill(np.nan)
b = [2,3,1]

for i in range(b):
    a[0:b[i]] = [1] * b[i] 
    a[i:] = np.ones((b[i]))
pass

Out:
line 7:
ValueError: could not broadcast input array from shape (2) into shape (2,4)

结果应该是这样的:

Out:
[[1, 1, nan, nan], 
 [1, 1, 1, nan], 
 [1, nan, nan, nan]] 

【问题讨论】:

当你发布这样的代码时,你应该说的不仅仅是“它不起作用”。哪里错了?什么样的错误?一个小的调整让它工作:for i in range(3): a[i,0:b[i]] = 1你没有完全应用链接的答案。 @hpaulj 你说得对,为了完整起见,我现在添加了它。如果我使用你的调整,最后一行导致的错误出现(ValueError: could not broadcast input array from shape (2) into shape (3,4))。如果我删除这一行,那真的很好! @hpaulj 我的错,它不起作用。整个数组都被填充了。但是,您的枚举解决方案非常完美 【参考方案1】:

在链接的答案中,How to set first N elements of array to zero?

数组的解决方案是

y = numpy.array(x)
y[0:n] = 0

换句话说,如果我们用相同的数字填充一个切片(索引范围),我们可以指定一个标量。它可以是相同大小的数组,例如np.ones(n)。但不一定是这样。

所以我们只需要遍历a 的行(以及b 的元素)并执行这个索引赋值

In [368]: a = np.ones((3,4))*np.nan
In [369]: for i in range(3):
     ...:     a[i,:b[i]] = 1
     ...:     
In [370]: a
Out[370]: 
array([[  1.,   1.,  nan,  nan],
       [  1.,   1.,   1.,  nan],
       [  1.,  nan,  nan,  nan]])

有多种方法可以用nan“填充”原始数组。 np.full 执行 np.empty 后跟 copyto

行迭代的一个变体是for i,n in enumerate(a):

在协调意义上进行迭代的另一种好方法是使用zip

In [371]: for i,x in zip(b,a):
     ...:     x[:i] = 1

这利用了 2d 数组上的迭代迭代其行这一事实。所以xa 的一维视图,可以就地更改。

但是有了一些索引技巧,我们甚至不必循环。

In [373]: a = np.full((3,4),np.nan)

In [375]: mask = np.array(b)[:,None]>np.arange(4)
In [376]: mask
Out[376]: 
array([[ True,  True, False, False],
       [ True,  True,  True, False],
       [ True, False, False, False]], dtype=bool)
In [377]: a[mask] = 1
In [378]: a
Out[378]: 
array([[  1.,   1.,  nan,  nan],
       [  1.,   1.,   1.,  nan],
       [  1.,  nan,  nan,  nan]])

这是numpy ***海报@Divakar 的最爱之一。

Numpy: Fix array with rows of different lengths by filling the empty elements with zeros

它可以用于pad 一个列表列表。说到填充,itertools 有一个方便的工具,zip_longest(py3 名称)

In [380]: np.array(list(itertools.zip_longest(*[np.ones(x).tolist() for x in b],fillvalue=np.nan))).T
Out[380]: 
array([[  1.,   1.,  nan],
       [  1.,   1.,   1.],
       [  1.,  nan,  nan]])

您的问题应该说明出了什么问题;你遇到了什么样的错误:

for i in w2:
    a[0:b[i]] = [1] * b[i] 
    a[i:] = np.ones((b[i]))

w2 未指定,但可能是range(3)

a[0:b[i]] 是错误的,因为它指定了所有行,而您一次只处理一个行。 a[i:] 也指定了行的范围。

【讨论】:

不错的答案!我想涉及口罩的解决方案是最快的。 mask = np.array(b)[:,None] > np.arange(4) 这行真是天才:) 非常感谢,很好的解释 :) 为了完整起见,我将替换 w2 并写下我遇到的错误。【参考方案2】:

您可以通过循环执行此操作。初始化nan 值的数组,然后循环遍历第一个 n 的列表,并根据每行的 n 将值设置为 1。

a = np.full((3, 4), np.nan)
b = [2, 3, 1]
for i, x in enumerate(b):
    a[i, :x] = 1

【讨论】:

您可以使用numpy.full 使用np.NAN 值而不是零来初始化矩阵。 a = np.full((3, 4), np.NAN) 否则很好的解决方案! 如果我开始将我的数组全部设为 NaN 是否有关系,因此省略最后一行,而不是先将它们设为零,然后(使用你的最后一行)使所有剩余部分为零?也许速度? @SVerhoef,主要是可读性,有时比速度更重要。 Answer 已更新为使用 @OwlMax 建议的“numpy.full”作为其更具可读性的解决方案。感谢您的建议! fullfill 之间的区别很挑剔。查看np.full 的代码。真正的问题是——我们能避免迭代吗?到目前为止,所有答案都是对原作的细微改动。【参考方案3】:

您可以使用列表推导来初始化您的矩阵:

>>> import numpy as np
>>> b = [2, 3, 1]
>>> max_len = 4
>>> gen_array = lambda i: [1] * i + [np.NAN] * (max_len - i)
>>> np.matrix([gen_array(i) for i in b])

详细步骤:

[1] * N 将创建一个长度为 N 并用 1 填充的数组:

>>> [1] * 3
[1, 1, 1]

您可以使用+ 连接数组:

>>> [1, 2] + [3, 4]
[1, 2, 3, 4]

您只需将两者结合起来 [1] * X + [np.NAN] * (N - X) 将创建一个 N 维度的数组,其中填充有 X 1

最后一个,列表理解:

[i for i in b]

是一个“捷径”(不是真的,但更容易理解):

a = []
for i in b:
    a.append(i)

【讨论】:

【参考方案4】:
import numpy as np
a = np.random.rand(3,4)  #Create matrix with random numbers (you can change this to np.empty or whatever you want.
b = [1, 2, 3] # Your 'b' list
for idr, row in enumerate(a): # Loop through the matrix by row
  a[idr,:b[idr]] = 1  # idr is the row index, here you change the row 'idr' from the column 0 to the column b[idr] that will be 0, 1 and 3
  a[idr,b[idr]:] = 'NaN'  # the values after that receive NaN
print(a) # Outputs matrix
#[[  1.  nan  nan  nan]
 [  1.   1.  nan  nan]
 [  1.   1.   1.  nan]]

【讨论】:

这是已发布答案的过于复杂的副本 答案是在 13 分钟前发布的,imo 可以对已经解决的事情的重复答案投反对票,但是当我开始这样做时,另一个答案甚至还没有发布,我现在才看到.

以上是关于python如何替换array(x,n)中每个x的第一个f(x)值的主要内容,如果未能解决你的问题,请参考以下文章

python列表,如何批量查找替换

大于 x 时替换数组中的值 [重复]

Python 配对列表和绘图示例

Python中ndarray数组切片问题a[-n -x:-y]

如何在多索引的第 n 级替换所有等于 x 的值

如何在 python 中的 KMeans 聚类中获得 X 值?