I have a code in Matlab and I want to convert it to Python.
Matlab code:
...
...
for i=1:Z
index=0;
N_no=0;
clear A
clear B
for j=1:Z
Dist=distance(X(:,i),X(:,j));
if (all(Dist<=r) && all(Dist~=0))
index=index+1;
N_no=N_no+1;
A(:,index)=DeltaX(:,j);
B(:,index)=X(:,j);
end
end
...
...
end
Python code:
for i in range(0, Z):
index = -1
N_no = -1
A = np.zeros((Z, dim))
B = np.zeros((Z, dim))
for j in range(0, Z):
Dist = Distance(X[i, :], X[j, :])
if np.all(Dist <= r) and np.all(Dist != 0):
index = index + 1
N_no = N_no + 1
A[index, :] = DeltaX[j, :]
B[index, :] = X[j, :]
...
This code is working, but I am looking for an efficient way to convert it. I cannot use del A, del B in the Python code, instead of A = np.zeros((Z, dim)), B = np.zeros((Z, dim)), because I will get this error: UnboundLocalError: local variable 'A'/'B' referenced before assignment. Any suggestion?
This is the standard approach to assign an empty Numpy array. I would see no need of deleting the variable at all.
I assume, that you don't use the variable 'A' and 'B' in the code above and thus the error message is also valid.
You can not delete a variable that does not exist.
Related
I have a function that takes three arrays and runs a few lines of code to interpolate the data.
It looks something like this:
def interpolate(a, b, c):
# Avoid crashing if a > max(b)
xm_ = b[-1]
a[a > xm_] = xm_
i = np.arange(a.size)
j = np.searchsorted(b, a) - 1
d = (a - b[j]) / (b[j + 1] - b[j])
return (1 - d) * c[i, j] + c[i, j + 1] * d
Here are the shapes of the arrays:
a is (163080,)
b is (71,)
c is (162080, 71)
I keep running into the IndexError. I have tried to extend the b with higher values to try to not hit max values. I have also tried to use up to fourth last index when assigning xm_.
Any suggestions to what might be happening here? And potentially how to solve it?
Cheers!
I have a NumPy array with the following properties:
shape: (9986080, 2)
dtype: np.float32
I have a method that loops over the range of the array, performs an operation and then inputs result to new array:
def foo(arr):
new_arr = np.empty(arr.size, dtype=np.uint64)
for i in range(arr.size):
x, y = arr[i]
e, n = ''
if x < 0:
e = '1'
else:
w = '2'
if y > 0:
n = '3'
else:
s = '4'
new_arr[i] = int(f'{abs(x)}{e}{abs(y){n}'.replace('.', ''))
I agree with Iguananaut's comment that this data structure seems a bit odd. My biggest problem with it is that it is really tricky to try and vectorize the putting together of integers in a string and then re-converting that to an integer. Still, this will certainly help speed up the function:
def foo(arr):
x_values = arr[:,0]
y_values = arr[:,1]
ones = np.ones(arr.shape[0], dtype=np.uint64)
e = np.char.array(np.where(x_values < 0, ones, ones * 2))
n = np.char.array(np.where(y_values < 0, ones * 3, ones * 4))
x_values = np.char.array(np.absolute(x_values))
y_values = np.char.array(np.absolute(y_values))
x_values = np.char.replace(x_values, '.', '')
y_values = np.char.replace(y_values, '.', '')
new_arr = np.char.add(np.char.add(x_values, e), np.char.add(y_values, n))
return new_arr.astype(np.uint64)
Here, the x and y values of the input array are first split up. Then we use a vectorized computation to determine where e and n should be 1 or 2, 3 or 4. The last line uses a standard list comprehension to do the string merging bit, which is still undesirably slow for super large arrays but faster than a regular for loop. Also vectorizing the previous computations should speed the function up hugely.
Edit:
I was mistaken before. Numpy does have a nice way of handling string concatenation using the np.char.add() method. This requires converting x_values and y_values to Numpy character arrays using np.char.array(). Also for some reason, the np.char.add() method only takes two arrays as inputs, so it is necessary to first concatenate x_values and e and y_values and n and then concatenate these results. Still, this vectorizes the computations and should be pretty fast. The code is still a bit clunky because of the rather odd operation you are after, but I think this will help you speed up the function greatly.
You may use np.apply_along_axis. When you feed this function with another function that takes row (or column) as an argument, it does what you want to do.
For you case, You may rewrite the function as below:
def foo(row):
x, y = row
e, n = ''
if x < 0:
e = '1'
else:
w = '2'
if y > 0:
n = '3'
else:
s = '4'
return int(f'{abs(x)}{e}{abs(y){n}'.replace('.', ''))
# Where you want to you use it.
new_arr = np.apply_along_axis(foo, 1, n)
I want to achieve this function in Python like Matlab
in matlab, the code is
A = [];
for ii = 0:9
B = [ii, ii+1, ii**2];
C = [ii+ii**2, ii-5];
A = [A, B, C];
end
but in Python, use np.hstack or np.concatenate, the ndarray must have same number of dimensions
if the A in first loop is empty, the code will make mistake as following:
for ii in range(10):
B = np.array([ii, ii+1, ii**2])
C = np.array([ii+ii**2, ii-5])
if ii == 0:
A = np.hstack([B, C])
else:
A = np.hstack([A, B, C])
and, that is my Python code, B and C are variable, not repeat the ndarray, plz don't close my question!
for ii in range(10):
B = np.array([ii, ii+1, ii**2])
C = np.array([ii+ii**2, ii-5])
if ii == 0:
A = np.hstack([B, C])
else:
A = np.hstack([A, B, C])
but, i think it a little troublesome and unreadable.
how can i rewrite it?(It's better to use only one line of code)
Without knowing what the result Should be - I think this is close
import numpy as np
q = np.arange(10)
bs = np.vstack((q,q+1,q**2)).T
cs = np.vstack((q,q**2,q-5)).T
a = np.hstack((bs,cs))
Or maybe:
a = np.hstack((bs,cs)).ravel()
I am used to write code in c++ but now I am trying to learn python. I came to know about the Python language and it is very popular among everyone. So I thought, let's give it a shot.
Currently I am preparing for companies interview questions and able to solve most of them in c++. Alongside which, I am trying to write the code for the same in Python. For the things which I am not familiar with, I do a google search or watch tutorials etc.
While I was writing code for my previously solved easy interview questions in python, I encountered a problem.
Code : Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Given an array of integers, print the indices of the two numbers such that they add up to a specific target.
def twoNum(*arr, t):
cur = 0
x = 0
y = 0
for i in range (len(arr) - 1):
for j in range (len(arr) - 1):
if(i == j):
break
cur = arr[i] + arr[j]
if(t == cur):
x = arr[i]
y = arr[j]
break
if(t == cur):
break
print(f"{x} + {y} = {x+y} ")
arr = [3, 5, -4, 8, 11, 1, -1, 6]
target = 10
twoNum(arr, t=target)
So here is the problem: I have defined x, y in function and then used x = arr[i] and y = arr[j] and I m printing those values.
output coming is : is 0 + 0 = 10 (where target is 10)
This is I guess probably because I am using x = 0 and y = 0 initially in the function and it seems x and y values are not updating then I saw outline section in VSCode there I saw x and y are declared twice, once at the starting of the function and second in for loop.
Can anyone explain to me what is going on here?
For reference, here is an image of the code I wrote in C++
Change this:
def twoNum(*arr, t):
to this:
def twoNum(arr, t):
* is used to indicate that there will be a variable number of arguments, see this. It is not for pointers as in C++.
Basically what you are trying to do is to write C code in python.
I would instead try to focus first on how to write python code in a 'pythonic' way first. But for your question - sloving it your way using brute force in python:
In [173]: def two_num(arr, t):
...: for i in arr:
...: for j in arr[i + 1: ]:
...: if i + j == t:
...: print(f"{i} + {j} = {t}")
...: return
Here's a way to implement a brute force approach using a list comprehension:
arr = [1,3,5,7,9]
target = 6
i,j = next((i,j) for i,n in enumerate(arr[:-1]) for j,m in enumerate(arr[i+1:],i+1) if n+m==target)
output:
print(f"arr[{i}] + arr[{j}] = {arr[i]} + {arr[j]} = {target}")
# arr[0] + arr[2] = 1 + 5 = 6
Perhaps even more pythonic would be to use iterators:
from itertools import tee
iArr = enumerate(arr)
i,j = next((i,j) for i,n in iArr for j,m in tee(iArr,1)[0] if n+m==target)
When you get to implementing an O(n) solution, you should look into dictionaries:
d = { target-n:j for j,n in enumerate(arr) }
i,j = next( (i,d[m]) for i,m in enumerate(arr) if m in d and d[m] != i )
The Problem occurs in line 29:
It is a Type Error
I can't figure out where I went wrong with my parameters. It should assign every a[i][k] with a value but it just ends up with the following error message:
a[i][k].append(g * m[i] * dr[k]/d3)
TypeError: 'int' object is not subscriptable
Here the full code:
import numpy as np
from numpy import absolute
from numpy import power
r = [[1,1,1],[1,1,1],[0,0,0]]
v = [[0,0,0],[0,0,0],[0,0,0]]
a = [[0,0,0],[0,0,0],[0,0,0]]
m = [1,1,1]
O = -1
N = 3
def beschleunigung(O, N, m, r, a):
i = 0
k = 0
dr = [0,0,0]
d3 = 0
g = 1
for k in range(1,3):
a[i][k] = 0
for i in range(1,N):
if i != O:
for k in range(1,3):
a = (r[i][k])
b = (r[0][k])
dr[k] = a - b
d3 = np.power(np.absolute(dr),3)
for k in range(1,3):
a[i][k].append(g * m[i] * dr[k]/d3)
beschleunigung(O,N,m,r,a)
print(a[1])
When your code executes the line a = (r[i][k]), a becomes an integer, rather than a list of lists as it was in the input to this function. This causes your append to fail as you cannot append to an integer.
I expect that you intended to create another variable to use in your subtraction with b - make sure to use a name that is not already defined in your scope.