Reputation: 1841
I have a 2-d array and a 1-d array, shown below. What I'd like to do is to fill the blank spaces in the 2-d array with the product of the 2-d and 1-d array - probably simplest to demonstrate below:
all_holdings = np.array([[1, 0, 0, 2, 0],
[2, 0, 0, 1, 0]]).astype('float64')
sub_holdings = np.array([0.2, 0.3, 0.5])
For which I'd like the desired result to be:
array([[1. , 0.2, 0.3, 2. , 1. ],
[2. , 0.4, 0.6, 1. , 0.5]])
i.e., (workings shown here):
array([[1., 1*0.2, 1*0.3, 2, 2*0.5],
[2., 2*0.2, 2*0.3, 1, 1*0.5]])
Is anybody able to think of a relatively fast, preferably vectorized way to do this? I have to run this calculation repeatedly on a number of 2-d arrays, though always with the blank spaces in the same location on the 2-d array.
Thanks in advance (and afterwards)
Upvotes: 0
Views: 998
Reputation: 231355
In [76]: all_holdings = np.array([[1, 0, 0, 2, 0],
...: [2, 0, 0, 1, 0]]).astype('float64')
...: sub_holdings = np.array([0.2, 0.3, 0.5])
With one level of iteration:
In [77]: idx = np.where(all_holdings[0,:]==0)[0]
In [78]: idx
Out[78]: array([1, 2, 4])
In [79]: res = all_holdings.copy()
In [80]: for i,j in zip(idx, sub_holdings):
...: res[:,i] = res[:,i-1]*j
...:
In [81]: res
Out[81]:
array([[1. , 0.2 , 0.06, 2. , 1. ],
[2. , 0.4 , 0.12, 1. , 0.5 ]])
Oops that res[:,2]
column is wrong; I need to use something other than idx-1
.
Now I can visualize the action better. For example, all the new values are:
In [82]: res[:,idx]
Out[82]:
array([[0.2 , 0.06, 1. ],
[0.4 , 0.12, 0.5 ]])
OK, I need a way of properly pairing each of the idx
values with the right nonzero column.
In [84]: jdx = np.where(all_holdings[0,:])[0]
In [85]: jdx
Out[85]: array([0, 3])
This doesn't cut it.
But lets assume we have a proper jdx
.
In [87]: jdx = np.array([0,0,3])
In [88]: res = all_holdings.copy()
In [89]: for i,j,v in zip(idx,jdx, sub_holdings):
...: res[:,i] = res[:,j]*v
...:
In [90]: res
Out[90]:
array([[1. , 0.2, 0.3, 2. , 1. ],
[2. , 0.4, 0.6, 1. , 0.5]])
In [91]: res[:,idx]
Out[91]:
array([[0.2, 0.3, 1. ],
[0.4, 0.6, 0.5]])
I get the same values without iteration:
In [92]: all_holdings[:,jdx]*sub_holdings
Out[92]:
array([[0.2, 0.3, 1. ],
[0.4, 0.6, 0.5]])
In [94]: res[:,idx] = res[:,jdx] *sub_holdings
In [95]: res
Out[95]:
array([[1. , 0.2, 0.3, 2. , 1. ],
[2. , 0.4, 0.6, 1. , 0.5]])
So the key to find the right jdx
array. I'll that up to you!
Upvotes: 1