Sum of column if not a square matirx in numpy? - python

a=np.array([[1,2,3],[1]])
print(np.sum(a,axis=1))
I am assuming that a matrix will be like
[1,2,3]
[1]

Not very general, because it only works if the first line is the longest, but you can simply stick your array into an array of zeros.
For example:
a = np.array([[1,2,3],[4,5]])
dim_x = len(a[0])
dim_y = a.shape[0]
a0 = np.zeros((dim_y, dim_x))
for i in range(dim_y):
dim = len(a[i])
a0[i,0:dim] = a[i]

Related

Multiplying a square array and row array with nested for loops

I'm trying to multiply a square array and a row array with nested for loops but I am running into errors such as object of type numpy.int64' has no len().
I need to be able to calculate the product with two nested for loops but I am unsure where I can change my code to optimise and fix my errors.
def matvec_row_variant_scalar(A,x):
product_array = np.zeros((len(A),len(A)),dtype=int)
for i in range(len(A)):
for j in range(len(x[0])):
for k in range(len(x)):
product_array[i][j] += A[i][k] * x[k][j]
return product_array
# Test arrays
square_array = np.array([[1,2],[3,4]])
row_array = np.array([2,2])
matvec_row_variant_scalar(square_array,row_array)
I think the code has two problems.
On the second for loop you used len(x[0]). as declaration x is 1D array and then x[0] is an Integer and calculating length on integer will thrown type error .
print(len(2)) #TypeError: object of type int has no len()
On product_array[i][j] += A[i][k] * x[k][j], again you should consider x is 1D!
Here is your fixed code.
import numpy as np
def matvec_row_variant_scalar(A,x):
product_array = np.zeros((len(A),len(A)),dtype=int)
for i in range(len(A)):
for j in range(len(A[i])):
for k in range(len(x)):
product_array[i][j] += A[i][k] * x[j]
return product_array
# Test arrays
square_array = np.array([[1,2],[3,4]])
row_array = np.array([2,2])
matvec_row_variant_scalar(square_array,row_array)
The returned Result is
array([[ 6, 6],
[14, 14]])
Okay, I figured it out. Thanks for the help from everyone. Here's the code for anyone interested:
import numpy as np
def matvec_row_variant_scalar(A,x):
product_array = np.zeros((len(A),len(A)),dtype=int)
for i in range(len(A)):
for j in range(len(A[i])):
product_array[i][j] += x[i] * A[i][j]
column_sum = product_array.sum(axis=0)
return column_sum
square_array = np.array([[1,2],[3,4]])
row_array = np.array([2,2])
matvec_row_variant_scalar(square_array,row_array)

How can this function be vectorized?

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)

Numpy subtraction from two arrays

I have two numpy arrays like below
a=np.array([11,12])
b=np.array([9])
#a-b should be [2,12]
I want to subtract both a & b such that result should [2,12]. How can I achieve this result?
You can zero-pad one of the array.
import numpy as np
n = max(len(a), len(b))
a_pad = np.pad(a, (0, n - len(a)), 'constant')
b_pad = np.pad(b, (0, n - len(b)), 'constant')
ans = a_pad - b_pad
Here np.pad's second argument is (#of left pads, #of right pads)
A similar method to #BlownhitherMa, would be to create an array of zeros the size of a (we can call it c), then put in b's values where appropriate:
c = np.zeros_like(a)
c[np.indices(b.shape)] = b
>>> c
array([9, 0])
>>> a-c
array([ 2, 12])
You could use zip_longest from itertools:
import numpy as np
from itertools import zip_longest
a = np.array([11, 12])
b = np.array([9])
result = np.array([ai - bi for ai, bi in zip_longest(a, b, fillvalue=0)])
print(result)
Output
[ 2 12]
Here is a very long laid out solution.
diff =[]
n = min(len(a), len(b))
for i in range (n):
diff.append(a[i] - b[i])
if len(a) > n:
for i in range(n,len(a)):
diff.append(a[i])
elif len(b) > n:
for i in range(n,len(b)):
diff.append(b[i])
diff=np.array(diff)
print(diff)
We can avoid unnecessary padding / temporaries by copying a and then subtracting b in-place:
# let numpy determine appropriate dtype
dtp = (a[:0]-b[:0]).dtype
# copy a
d = a.astype(dtp)
# subtract b
d[:b.size] -= b

Efficiently programming array elements to add up to a sum in python

I'm looking to implement in python a simple algorithm which takes as input an array and a sum, and finds a number X where if all elements in the array > X are converted to X, all the elements in the array should add up to the sum.
How do I do this efficiently?
Here is my code:
result = []
for _ in range(int(raw_input())):
input_array = map(int,raw_input().split())
sum_target = raw_input()
for e in input_array:
test_array = input_array
test_array[test_array > e] = e // supposed to replace all elements > e with e, but what's wrong here?
if sum(test_array) == sum_target:
result.append(e)
print result
Using the Numpy library (import numpy), you could replace the line
input_array = map(int,raw_input().split())
with
input_array = numpy.array(raw_input().split()).astype(int)
Then
test_array[test_array > e] = e
just works. Then, you could also do test_array.sum().
(That is, if you want to alter the array in-place, else you could replace
test_array = input_array
with
test_array = np.array(input_array)

Retrieving array elements with an array of frequencies in NumPy

I have an array of numbers, a. I have a second array, b, specifying how many times I want to retrieve the corresponding element in a. How can this be achieved? The ordering of the output is not important in this case.
import numpy as np
a = np.arange(5)
b = np.array([1,0,3,2,0])
# desired output = [0,2,2,2,3,3]
# i.e. [a[0], a[2], a[2], a[2], a[3], a[3] ]
Thats exactly what np.arange(5).repeat([1,0,3,2,0]) does.
A really inefficient way to do that is this one :
import numpy as np
a = np.arange(5)
b = np.array([1,0,3,2,0])
res = []
i = 0
for val in b:
for aa in range(val):
res.append(a[i])
i += 1
print res
here's one way to do it:
res = []
for i in xrange(len(b)):
for j in xrange(b[i]):
out.append(a[i])
res = np.array(res) # optional

Categories

Resources