Related
Mathematica Code
In Mathematica, I was able to write out the desired matrix with diagonal and off-diagonal values I was wondering what the best way to do this is in python using numpy?
A virtual clone of your code:
In [146]: arr = np.zeros((5,5),int)
In [147]: arr[np.arange(5),np.arange(5)]=2
In [148]: arr[np.arange(4),np.arange(1,5)]=-1
In [149]: arr[np.arange(1,5),np.arange(4)]=-1
In [150]: arr
Out[150]:
array([[ 2, -1, 0, 0, 0],
[-1, 2, -1, 0, 0],
[ 0, -1, 2, -1, 0],
[ 0, 0, -1, 2, -1],
[ 0, 0, 0, -1, 2]])
or with a diag function:
In [151]: np.diag(np.ones(5,int)*2,0)+np.diag(np.ones(4,int)*-1,-1)+np.diag(np.ones(4,int)*-1,1
...: )
Out[151]:
array([[ 2, -1, 0, 0, 0],
[-1, 2, -1, 0, 0],
[ 0, -1, 2, -1, 0],
[ 0, 0, -1, 2, -1],
[ 0, 0, 0, -1, 2]])
Let's have A like below :
A = np.array([[0, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[1, 0, 0, 0, 0],
[1, 0, 1, 0, 0],
[0, 0, 0, 0, 0]])
And now, I have to take all the lines which have a 1 on first column :
A[A[:, 0] > 0]
return: array([[1, 0, 0, 0, 0],
[1, 0, 1, 0, 0]])
And now, I want to modify the first column of the second line ? How can I do it ? Because this is not working :
A[A[:, 0] > 0][1, 1] = 1
A
array([[0, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[1, 3, 0, 0, 0],
[1, 0, 1, 0, 0],
[0, 0, 0, 0, 0]])
My code is more complicated than this one, and so, the condition have to be done in two times like here : (1) > 0 and (2) [1, 1].
Given a numpy array containing two types of elements:
"numpy.ndarray" entries and
"NoneType" entries
How do I replace all "NoneType" entries with e.g. np.zeros(some_shape)?
Could this be also done for any type of single elements like scalar for instance instead of NoneType?
Example:
test_array=
array([[array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8), ..., None, None,
None],
[array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8), ..., None, None,
None],
[array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8), ...,
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8), None, None],
...,
[array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8), ...,
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8), None],
[array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8), ...,
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8), None],
[array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8), ...,
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8)]], dtype=object)
where an array within test_array might look like this:
test_array[323]=
array([array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8), None, None], dtype=object)
And I want to replace those "None" entries with a zero-vector of same length as the other vectors (here position 0 to 3).
So that my result for each array (test_array[i] within test_array would look like this:
test_array[131]=
array([array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8),
array([[0, 0, 0, ..., 0, 0, 0]], dtype=uint8)], dtype=object)
So I would like to fill all None entries with np.zeros arrays. There does exists the numpy function np.nan_to_num but this does not help me because I would need something like "np.nan_to_array".
Thanks!
Normally I would not use a for loop with NumPy, but in your case you have an object array which is anyway not very efficient, and dealing with the combination of None and sub-arrays stored as objects is very tricky. So, keep it simple:
prototype = a[0]
for i, x in enumerate(a):
if x is None:
a[i] = np.zeros_like(prototype)
Of course you'll need to find a prototype if a[0] is None. That's left as an exercise.
I want to initialise a three dimensional ruby array. For a two-dimensional array, I can do
a = Array.new(4){ Array.new(5, 0) }
so I have tried
a = Array.new(4) { Array.new(5, Array.new(6, 0)) }
but if I do a[1][2][3] = 5, it not only sets that element to 5, it sets the corresponding element to 5 in other sub arrays i.e.
[[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]],
[[0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0], [0, 0, 0, 5, 0, 0]],
[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]],
[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]]
The issue is that if you pass the value as an argument, you will get an array where each value refers to that same object. You do exactly that with:
Array.new(5, Array.new(6, 0))
You can use Array#*, i.e array multiplication instead:
[[[0] * 6] * 5] * 4
Just use the same syntax (with a block instead of an argument : Array.new(n){...}) for all the dimensions.
a = Array.new(4) { Array.new(5) { Array.new(6, 0) } }
This way, your code will create 20 distincts Array.new(6, 0) sub-sub-arrays instead of replicating the same object 5 times.
require 'pp'
a = Array.new(4) { Array.new(5) { Array.new(6, 0) } }
a[1][2][3] = 5
pp a
# [[[0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0]],
# [[0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 5, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0]],
# [[0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0]],
# [[0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0],
# [0, 0, 0, 0, 0, 0]]]
The following worked properly.
a=Array.new(4){ Array.new(5) { Array.new(6,0) }}
You can use recursion to initialize the elements of a multidimensional array of any dimension.1
Code
def init(n, *rest)
rest.empty? ? Array.new(n, 0) : Array.new(n) { init(*rest) }
end
Examples
dims = [2, 3, 2]
a = init(*dims)
#=> [[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]
a[0][0][0] = 1
a #=> [[[1, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]
dims = [2, 3, 2, 4, 2, 3]
a = init(*dims)
a.flatten.size
#=> 288 (= 2*3*2*4*2*3)
a[0][0][0][0][0][0] = 1
a.flatten.count(1)
#=> 1
Explanation
The steps are as follows.
Suppose, as in the example,
dims = [2, 3, 2]
Then
n, *rest = dims
#=> [2, 3, 2]
n #=> 2
rest
#=> [3, 2]
As rest.empty? #=> false, the method returns
Array.new(2) { init(*[3, 2]) } # (1)
#=> [[[0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0]]]
To obtain this result, we execute the block
{ init(*[3, 2]) }
for each of the two elements of the array being constructed. This requires us to compute init([3, 2]) (same as { init(3, 2) }), which is done as follows.
n, *rest = [3, 2]
#=> [3, 2]
n #=> 3
rest
#=> [2]
Again, as rest.empty? #=> false, we return
Array.new(3) { init(*[2]) } # (2)
#=> [[0, 0], [0, 0], [0, 0]]
to expression (1) above. For each of the 3 elements of this array we execute the block
{ init(*[2]) }
This requires us to compute init([2]), which is done as follows.
n, *rest = [2]
#=> [2]
n #=> 2
rest
#=> []
This time, since rest.empty? #=> true, we compute and return
Array.new(2, 0)
#=> [0, 0]
to expression (2) above.
1 Yes, there's no such thing as a "multidimensional array" in Ruby, but I expect readers to know what I mean. The alternative is something like "...of an array containing nested arrays of equal size with any number of levels of nesting", but even that is incomplete as it fails to exclude, for example, [[1, [2,3]], [4,5]]. It would be helpful if Ruby had a name for such objects.
I've written a small test case program in FORTRAN 90 which initializes a 3d array in slices. Can this same behavior be easily replicated in C?
program fortranEngine
real(4) , dimension(10,10) :: tmp
real(4) , dimension(10,10,3) :: p
tmp = RESHAPE( [ 0.973, 1.053, 0, 0, 0, 0, 0, 0, 0, 0, &
1.053, 1.080, 0, 0, 0, 0, 0, 0, 0, 0, &
1.010, 0.408, 0.442, 0, 0, 0, 0, 0, 0, 0, &
1.119, 0.900, 0.399, 0.762, 0, 0, 0, 0, 0, 0, &
1.211, 0.975, 0.845, 0.952, 1.105, 0, 0, 0, 0, 0, &
1.248, 1.016, 0.485, 0.000, 0.000, 1.110, 0, 0, 0, 0, &
1.225, 1.123, 1.056, 0.000, 0.000, 0.949, 0.832, 0, 0, 0, &
1.138, 1.232, 1.089, 1.050, 0.930, 0.402, 0.789, 0.774, 0, 0, &
1.149, 1.406, 1.201, 1.052, 0.416, 0.878, 0.896, 0.431, 1.144, 0, &
1.351, 1.255, 1.290, 1.358, 1.240, 1.228, 1.257, 1.140, 1.123, 1.228] &
, [10,10] )
p(:,:,1) = tmp
...
end program fortranEngine
You can more or less do it in C99 or C2011, but it isn't as convenient as in Fortran. Beware initialization order; Fortran does it in one order (column-major) and C does it in the other (row-major). Ignoring that, you can do:
float tmp[10][10] =
{
{ 0.973, 1.053, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 1.053, 1.080, 0, 0, 0, 0, 0, 0, 0, 0, },
{ 1.010, 0.408, 0.442, 0, 0, 0, 0, 0, 0, 0, },
{ 1.119, 0.900, 0.399, 0.762, 0, 0, 0, 0, 0, 0, },
{ 1.211, 0.975, 0.845, 0.952, 1.105, 0, 0, 0, 0, 0, },
{ 1.248, 1.016, 0.485, 0.000, 0.000, 1.110, 0, 0, 0, 0, },
{ 1.225, 1.123, 1.056, 0.000, 0.000, 0.949, 0.832, 0, 0, 0, },
{ 1.138, 1.232, 1.089, 1.050, 0.930, 0.402, 0.789, 0.774, 0, 0, },
{ 1.149, 1.406, 1.201, 1.052, 0.416, 0.878, 0.896, 0.431, 1.144, 0, },
{ 1.351, 1.255, 1.290, 1.358, 1.240, 1.228, 1.257, 1.140, 1.123, 1.228 },
};
float p[3][10][10];
for (int i = 0; i < 3; i++)
memmove(p[i], tmp, sizeof(tmp));
Note that I moved the dimension [3] from the end of the declaration to the start of the declaration, though. The other way around would not make much sense in C. So, the notation is more or less available, but details of storage management make it less than obvious how to achieve exactly what you want.
Is this easy enough?
for(int i = 0 ; i < 10 ; ++i)
for(int j = 0 ; j < 10 ; ++j )
p[0][i][j] = tmp[i][j] ;