Python Exponential function - python-3.x

I have defined the following symbolic matrix:
def DFT(d):
a = symbols('pi')
DFT = Matrix(d, d, lambda i,j: exp((2*I/d)*i*j*a))
return(DFT)
Now, I would like to simplify the exponential to the corresponding 1,-1,I,-I when its argument is an intiger or half integer value, but for the rest of the cases I would like to keep the symbolic expression.
Is there any method that I could use? How should I do it?
Regards!

If I use the predefined symbol sympy.pi instead of a in the definition of DFT, it simplifies the values automatically:
In [27]: from sympy import *
In [28]: def DFT(d):
...: DFT = Matrix(d, d, lambda i,j: exp((2*I/d)*i*j*pi))
...: return(DFT)
...:
In [29]: DFT(4)
Out[29]:
Matrix([
[1, 1, 1, 1],
[1, I, -1, -I],
[1, -1, 1, -1],
[1, -I, -1, I]])
In [30]: DFT(6)
Out[30]:
Matrix([
[1, 1, 1, 1, 1, 1],
[1, exp(I*pi/3), exp(2*I*pi/3), -1, exp(4*I*pi/3), exp(5*I*pi/3)],
[1, exp(2*I*pi/3), exp(4*I*pi/3), 1, exp(8*I*pi/3), exp(10*I*pi/3)],
[1, -1, 1, -1, 1, -1],
[1, exp(4*I*pi/3), exp(8*I*pi/3), 1, exp(16*I*pi/3), exp(20*I*pi/3)],
[1, exp(5*I*pi/3), exp(10*I*pi/3), -1, exp(20*I*pi/3), exp(25*I*pi/3)]])
In [31]: DFT(8)
Out[31]:
Matrix([
[1, 1, 1, 1, 1, 1, 1, 1],
[1, exp(I*pi/4), I, exp(3*I*pi/4), -1, exp(5*I*pi/4), -I, exp(7*I*pi/4)],
[1, I, -1, -I, 1, I, -1, -I],
[1, exp(3*I*pi/4), -I, exp(9*I*pi/4), -1, exp(15*I*pi/4), I, exp(21*I*pi/4)],
[1, -1, 1, -1, 1, -1, 1, -1],
[1, exp(5*I*pi/4), I, exp(15*I*pi/4), -1, exp(25*I*pi/4), -I, exp(35*I*pi/4)],
[1, -I, -1, I, 1, -I, -1, I],
[1, exp(7*I*pi/4), -I, exp(21*I*pi/4), -1, exp(35*I*pi/4), I, exp(49*I*pi/4)]])

Related

repeating specific rows in array n times

I have a huge numpy array with 15413 rows and 70 columns. The first column represents the weight (so if the first element in a row is n, that row should be repeated n times.
I tried with numpy.repeat but I don’t think it’s giving me the correct answer because np.sum(chain[:,0]) is not equal to len(ACT_chain)
ACT_chain = []
for i in range(len(chain[:,0])):
chain_row = chain[i]
ACT_chain.append(chain_row)
if int(chain[:,0][i]) > 1:
chain_row = np.repeat(chain[i], chain[:, 0][i], axis=0)
ACT_chain.append(chain_row)
For example, running this code with this sample array
chain = np.array([[1, 5, 3], [2, 2, 1], [3, 0, 1]])
gives
[array([1, 5, 3]), array([2, 2, 1]), array([[2, 2, 1],
[2, 2, 1]]), array([3, 0, 1]), array([[3, 0, 1],
[3, 0, 1],
[3, 0, 1]])]
but the output I expect is
array([[1, 5, 3], [2, 2, 1], [2, 2, 1], [3, 0, 1], [3, 0, 1], [3, 0, 1]])
You can use repeat here, without the iteration.
np.repeat(chain, chain[:, 0], axis=0)
array([[1, 5, 3],
[2, 2, 1],
[2, 2, 1],
[3, 0, 1],
[3, 0, 1],
[3, 0, 1]])
I solved the typeError by converting the whole array to int
chain = chain.astype(int)

Add 2 dictionary with tuple keys and multiple values

I tried creating a 1D array of a grid point with values of x, and y as a list and then formed a dictionary to make a complete grid with some values stored w.r.t. each key (grid point x,y), in this case, (Vx, Vy,1).
I am trying to add two dictionaries but while I am using the below method dictionary is getting appended instead of getting a sum of values. I tried using the counter as well but that seems to give the error "'>' not supported between instances of 'list' and 'int'". If there is any other more efficient way to add the values of the same keys please mention it.
Edit :- For sake of simplicity, I am adding here same grid but in actuality there will be two different grids with different keys and values stored in dictionary. I wanted method to add values for same keys.
#Define the lower and upper limits for x and y
minX = -1
maxX = 1
minY = -1
maxY = 1
#Spac=Spacing Between gridpoints
Spac = 1
cordinates = {(x,y): [] for x in np.linspace(minX, maxX, XSpac) for y in np.linspace(minY, maxY, YSpac)}
grid={(x,y): [Vx,Vy,1] for (x,y) in cordinates}
print(grid)
pprint(grid)
for key in grid:
if key in grid:
grid2[key] = grid[key] + grid[key]
else:
pass
print(grid2)
pprint(grid2)
>>>grid
>>> {(-1.0, -1.0): [1, 1, 1],
(-1.0, 0.0): [1, 1, 1],
(-1.0, 1.0): [1, 1, 1],
(0.0, -1.0): [1, 1, 1],
(0.0, 0.0): [1, 1, 1],
(0.0, 1.0): [1, 1, 1],
(1.0, -1.0): [1, 1, 1],
(1.0, 0.0): [1, 1, 1],
(1.0, 1.0): [1, 1, 1]}
>>> grid2
>>> {(-1.0, -1.0): [1, 1, 1, 1, 1, 1],
(-1.0, 0.0): [1, 1, 1, 1, 1, 1],
(-1.0, 1.0): [1, 1, 1, 1, 1, 1],
(0.0, -1.0): [1, 1, 1, 1, 1, 1],
(0.0, 0.0): [1, 1, 1, 1, 1, 1],
(0.0, 1.0): [1, 1, 1, 1, 1, 1],
(1.0, -1.0): [1, 1, 1, 1, 1, 1],
(1.0, 0.0): [1, 1, 1, 1, 1, 1],
(1.0, 1.0): [1, 1, 1, 1, 1, 1]}
Desired output is
>>> {(-1.0, -1.0): [2, 2, 2],
(-1.0, 0.0): [2, 2, 2],
(-1.0, 1.0): [2, 2, 2],
(0.0, -1.0): [2, 2, 2],
(0.0, 0.0): [2, 2, 2],
(0.0, 1.0): [2, 2, 2],
(1.0, -1.0): [2, 2, 2],
(1.0, 0.0): [2, 2, 2],
(1.0, 1.0): [2, 2, 2]}

How to reshape an array with numpy like this:

I have this:
array([[0, 0, 1, 1, 2, 2, 3, 3],
[0, 0, 1, 1, 2, 2, 3, 3]])
And I would like to reshape my array like this:
array([[0, 0, 1, 1],
[0, 0, 1, 1],
[2, 2, 3, 3],
[2, 2, 3, 3]])
How do I do it using python numpy?
You can just split and concatenate:
a = np.array([[0, 0, 1, 1, 2, 2, 3, 3],
[0, 0, 1, 1, 2, 2, 3, 3]])
cols = a.shape[1] // 2
np.concatenate((a[:,:cols], a[:,cols:]))
#[[0 0 1 1]
# [0 0 1 1]
# [2 2 3 3]
# [2 2 3 3]]
You can simply swap rows after reshaping it.
a= np.array([[0, 0, 1, 1, 2, 2, 3, 3],
[0, 0, 1, 1, 2, 2, 3, 3]]).reshape(4,4)
a[[1,2]] = a[[2,1]]
Output:
array([[0, 0, 1, 1],
[0, 0, 1, 1],
[2, 2, 3, 3],
[2, 2, 3, 3]])

Numpy Selecting Elements given row and column index arrays

I have row indices as a 1d numpy array and a list of numpy arrays (list as same length as the size of the row indices array. I want to extract values corresponding to these indices. How can I do it ?
This is an example of what I want as output given the input
A = np.array([[2, 1, 1, 0, 0],
[3, 0, 2, 1, 1],
[0, 0, 2, 1, 0],
[0, 3, 3, 3, 0],
[0, 1, 2, 1, 0],
[0, 1, 3, 1, 0],
[2, 1, 3, 0, 1],
[2, 0, 2, 0, 2],
[3, 0, 3, 1, 2]])
row_ind = np.array([0,2,4])
col_ind = [np.array([0, 1, 2]), np.array([2, 3]), np.array([1, 2, 3])]
Now, I want my output as a list of numpy arrays or list of lists as
[np.array([2, 1, 1]), np.array([2, 1]), np.array([1, 2, 1])]
My biggest concern is the efficiency. My array A is of dimension 20K x 10K.
As #hpaulj commented, likely, you won't be able to avoid looping - e.g.
import numpy as np
A = np.array([[2, 1, 1, 0, 0],
[3, 0, 2, 1, 1],
[0, 0, 2, 1, 0],
[0, 3, 3, 3, 0],
[0, 1, 2, 1, 0],
[0, 1, 3, 1, 0],
[2, 1, 3, 0, 1],
[2, 0, 2, 0, 2],
[3, 0, 3, 1, 2]])
row_ind = np.array([0,2,4])
col_ind = [np.array([0, 1, 2]), np.array([2, 3]), np.array([1, 2, 3])]
# make sure the following code is safe...
assert row_ind.shape[0] == len(col_ind)
# 1) select row (A[r, :]), then select elements (cols) [col_ind[i]]:
output = [A[r, :][col_ind[i]] for i, r in enumerate(row_ind)]
# output
# [array([2, 1, 1]), array([2, 1]), array([1, 2, 1])]
Another way to do this could be to use np.ix_ (still requires looping). Use with caution though for very large arrays; np.ix_ uses advanced indexing - in contrast to basic slicing, it creates a copy of the data instead of a view - see the docs.

NumPy doesn't recognize well array shape

I have a code which is as follows:
data = np.array([[[i, j], i * j] for i in range(10) for j in range(10)])
print(data)
x = np.array(data[:,0])
x1 = x[:,0]
x2 = x[:,1]
print(x)
data correctly outputs [[[0,0],0],[[0,1],0],[[0,2],0],...,[[9,9],81]] which is, by the way, the multiplication table and it's results.
So, the first column of the data (which is x) must be separated into x1 and x2, which are the first and last column of it respectively. Which I think I did it right but it raises an error saying too many indices for array. What am I doing wrong?
data.dtype is object because the elements of [[i,j],k] are not homogeneous. A workaround for you :
data = np.array([(i, j, i * j) for i in range(10) for j in range(10)])
print(data)
x1 = data[:,:2]
x2 = data[:,2]
data.shape is now (100,3), data.dtype is int and x1 and x2 what you want.
Because of the mix of list lengths, this produces an object array:
In [97]: data = np.array([[[i, j], i * j] for i in range(3) for j in range(3)])
In [98]: data
Out[98]:
array([[[0, 0], 0],
[[0, 1], 0],
[[0, 2], 0],
[[1, 0], 0],
[[1, 1], 1],
[[1, 2], 2],
[[2, 0], 0],
[[2, 1], 2],
[[2, 2], 4]], dtype=object)
In [99]: data.shape
Out[99]: (9, 2)
One column contains numbers (but is still object dtype), the other lists. Both have (9,) shape
In [100]: data[:,1]
Out[100]: array([0, 0, 0, 0, 1, 2, 0, 2, 4], dtype=object)
In [101]: data[:,0]
Out[101]:
array([[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1],
[2, 2]], dtype=object)
The easiest way of turning that column into a numeric arrays is via .tolist
In [104]: np.array(data[:,0].tolist())
Out[104]:
array([[0, 0],
[0, 1],
[0, 2],
[1, 0],
[1, 1],
[1, 2],
[2, 0],
[2, 1],
[2, 2]])
In [105]: _.shape
Out[105]: (9, 2)
The [i, j, i * j] elements as suggested in the other answer are easier to work with.
A structured array approach to generating such a 'table':
In [113]: dt='(2)int,int'
In [114]: data = np.array([([i, j], i * j) for i in range(3) for j in range(3)],
...: dtype=dt)
In [115]: data
Out[115]:
array([([0, 0], 0), ([0, 1], 0), ([0, 2], 0), ([1, 0], 0), ([1, 1], 1),
([1, 2], 2), ([2, 0], 0), ([2, 1], 2), ([2, 2], 4)],
dtype=[('f0', '<i4', (2,)), ('f1', '<i4')])
In [116]: data['f0']
Out[116]:
array([[0, 0],
[0, 1],
[0, 2],
[1, 0],
[1, 1],
[1, 2],
[2, 0],
[2, 1],
[2, 2]])
In [117]: data['f1']
Out[117]: array([0, 0, 0, 0, 1, 2, 0, 2, 4])

Resources