Mikhail T. - 1 year ago 128

Python Question

I have a 1d

`np.array`

Please advise if there is an efficient way to create a symmetric 2d

`np.array`

I realise it is possible to do with a python

`for`

`list`

Many thanks in advance!

For example, we have

`x = np.array([1, 2, 3])`

`M = np.array([[1, 2, 3],`

[2, 1, 2],

[3, 2, 1])

Answer Source

Basically you are trying to assign the elements from the input `1D`

array into a symmetric `2D`

array. As such, if you want to use all elements from the `1D`

array, it would only work for a specific size of it. So, as a pre-processing step, we need to perform that error-checking. After we are through the error-checking, we will initialize an output array and use row and column indices of a `triangular array`

to assign values once as they are and once with swapped indices to assign values in the other triangular part, thus giving it the symmetry *effect*.

It seemed like `Scipy's squareform`

should do be able to do this task, but from the docs, it doesn't look like it supports filling up the diagonal elements with the input array elements. So, let's give our solution a closely-related name.

Thus, we would have an implementation like so -

```
def squareform_diagfill(arr1D):
n = int(np.sqrt(arr1D.size*2))
if (n*(n+1))//2!=arr1D.size:
print "Size of 1D array not suitable for creating a symmetric 2D array!"
return None
else:
R,C = np.triu_indices(n)
out = np.zeros((n,n),dtype=arr1D.dtype)
out[R,C] = arr1D
out[C,R] = arr1D
return out
```

Sample run -

```
In [179]: arr1D = np.random.randint(0,9,(12))
In [180]: squareform_diagfill(arr1D)
Size of 1D array not suitable for creating a symmetric 2D array!
In [181]: arr1D = np.random.randint(0,9,(10))
In [182]: arr1D
Out[182]: array([0, 4, 3, 6, 4, 1, 8, 6, 0, 5])
In [183]: squareform_diagfill(arr1D)
Out[183]:
array([[0, 4, 3, 6],
[4, 4, 1, 8],
[3, 1, 6, 0],
[6, 8, 0, 5]])
```