2017-08-11 200 views
3

我想用我的阵列a中的每一行替换第一个x值并保留所有其他值NaN 。然而,第一个x值在每一行都有变化,并由列表b确定。python如何取代阵列(x,n)中每个x的第一个f(x)值

因为我对阵列不是很熟悉,所以我想我可以用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]] 
+1

当你发布这样的代码时,你应该说比'它不工作'。什么问题?什么样的错误?一个小调整得到它的工作:'对于我在范围(3):a [i,0:b [i]] = 1'您没有完全应用链接的答案。 – hpaulj

+0

@hpaulj你说得对,我已经添加了它的完整性。如果我使用你的调整,由最后一行引起的错误出现'(ValueError:无法从形状(2)广播输入数组到形状(3,4))''。如果我删除这一行,确实很好! –

+0

@hpaulj我的坏,它不起作用。整个阵列比填充一个。然而,你的枚举解决方案完美工作 –

回答

2

在链接的答案,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 

这利用了以下事实的优点,关于它的行的二维数组迭代迭代。所以xa的1d视图,可以在原地更改。

但有一点索引欺骗,我们甚至不必循环。

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(PY 3名)

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:]也指定了一系列的行。

+0

很好的答案!我猜想涉及面具的解决方案是最快的。 'mask = np.array(b)[:, None]> np.arange(4)''是纯粹的天才:) –

+0

非常感谢,很好的解释:)为了完整性,我将取代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 
+3

你可以使用['numpy.full'](https://docs.scipy.org/doc/numpy/reference/generated/numpy.full.html#numpy-full)来初始化你的矩阵与'np.NAN'值而不是零。 'a = np.full((3,4),np.NAN)'否则很好的解决方案! –

+0

如果我把我的数组全部纳入开始,那么是否将其排列在最前面,而不是将它们设置为零,而不是使用最后一行使所有剩余零为零?也许速度? –

+1

@SVerhoef,主要**可读性**,imo有时比速度最重要。 –

0
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]] 
+0

这是一个已经发布的答案的过于复杂的副本 –

+0

答案在13分钟前发布,imo可以downvote已经解决的事情的重复答案,但是当我开始做这个时,其他答案甚至没有发布,我现在才看到它。 –

1

可以初始化你为基质使用列表理解:

>>> 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将创建长度Ñ填充有1的数组:

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

可以使用+ Concat的数组:

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

你只需要两个[1] * X + [np.NAN] * (N - X)合并将创建充满X1

最后一个列表理解ň维数组:

[i for i in b]

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

a = [] 
for i in b: 
    a.append(i) 
相关问题