Merge two arrays from a given index - PYTHON - python

I am wondering if there is an easy way to 'append' new elements to an array, but not at the end
Imagine I have a vector
a = np.array([1,2,3,4,5,6])
I want to append a new vector
b = np.array([1,1,1,1])
to a, starting from element 3 so that the new array would be
c = np.array([1,2,3,5,6,7,1])
that is the last 3 elements of array a are resulting from a+b while the new element just belong to C
Any ideas?
THX
I tried just append!

Using numpy with pad:
a = np.array([1,2,3,4,5,6])
b = np.array([1,1,1,1])
# or
# a = [1,2,3,4,5,6]
# b = [1,1,1,1]
n = 3
extra = len(b)-len(a)+n
c = np.pad(a, (0, extra))
c[n:] += b
Output:
array([1, 2, 3, 5, 6, 7, 1])

Related

Multiply two lists but multiply each number in the first list by all numbers in the second list in python

I have two lists I want to multiply each number in the first list by all numbers in the second list
[1,2]x[1,2,3]
I want my result to be like this [(1x1)+(1x2)+(1x3),(2x1)+(2x2)+(2x3)]
numpy
a = np.array([1,2])
b = np.array([1,2,3])
c = (a[:,None]*b).sum(1)
output: array([ 6, 12])
python
a = [1,2]
b = [1,2,3]
c = [sum(x*y for y in b) for x in a]
output: [6, 12]
old answer (product per element)
numpy
a = np.array([1,2])
b = np.array([1,2,3])
c = (a[:,None]*b).ravel()
output: array([1, 2, 3, 2, 4, 6])
python
a = [1,2]
b = [1,2,3]
c = [x*y for x in a for y in b]
## OR
from itertools import product
c = [x*y for x,y in product(a,b)]
output: [1, 2, 3, 2, 4, 6]
def multiplyLists(list1: list, list2:list) -> list:
toReturn = []
for i in list1:
temp_sum = 0
for j in list2:
temp_sum += i * j
toReturn.append(temp_sum)
return toReturn
Another way using numpy (that you can extend to many other functions between two lists):
a = [1,2]
b = [1,2,3]
np.multiply.outer(a,b).ravel()
#array([1, 2, 3, 2, 4, 6])
As the comments point out a pure Python solution will be very different to a numpy solution.
Pyhton
Here it woud be straightforward to use a nested loop or list comprehension:
list1 = [1, 2]
list2 = [1, 2, 3]
lst_output = []
for i in list1:
for j in list2:
lst_output .append(i*j)
#equivalent alternative
lst_output = [i*j for i in list1 for j in list2]
Numpy
There are mny ways to go about it with numpy as well. Here's one example:
arr1 = np.array([1, 2])
arr2 = np.array([1, 2, 3])
xx, yy = np.meshgrid(arr1, arr2)
arr_output = xx * yy
# optionally (to get a 1d array)
arr_output_flat = arr_output.flatten()
Edit: Reading your question again I noticed you state you actually want the output to be 2 sums (of 3 products). I suggest you phrase more precisely what you want an what you've tried. But to provide that here's what you can do with the lists or arrays from above:
# Pure Python
lst_output = [sum(i*j for j in list2) for i in list1]
# Numpy
xx, yy = np.meshgrid(arr1, arr2)
arr_output = np.sum(xx * yy, axis=0)

How to efficiently add or multiply every Nth element of a numpy array?

Suppose I have the following numpy array.
A = [1,2,3,4,5,6]
Question Is there a quick way to multiply or add every nth element in A to yield the following arrays?
B = [3*1, 2*4, 3*5, 4*6]
C = [3+1, 2+4, 3+5, 4+6]
I can accomplish this by rolling A and then adding or multiplying it to the original A.
T = np.roll(A,-2)
B = (A*T)[0:4]
C = (A*T)[0:4]
Just wondering if there is a more pythonic/efficient way to accomplish this? I have also looked at np.add.reduceat and np.multiply.reduceat but they do not seem to allow for skipping values.
You can do it in the following way:
A = np.array([1, 2, 3, 4, 5, 6])
k = 2
B = A[:-k]
C = A[k:]
print(B * C)
print(B + C)
Output
[ 3 8 15 24]
[ 4 6 8 10]
Cheers.

Pad list of arrays with zeros in order all arrays to have the same size

I have created this array(or I think its a list) that consist of many arrays that are different size and that is the reason I put dtype = object .
m = [data[a:b] for a, b in zip(z[0:-1:2], z[1:-1:2])]
array = np.array(m, dtype=object)
I need to pad each array with zero so that they have the same size (lets say size=smax) and become a "proper" array. My definitions are a little off and I am sorry in advance
You can do this using np.pad on each row. For example:
import numpy as np
data = np.arange(10)
z = [0, 2, 1, 4, 6, 10, 8, 9]
m = [data[a:b] for a, b in zip(z[0:-1:2], z[1:-1:2])]
max_length = max(len(row) for row in m)
result = np.array([np.pad(row, (0, max_length-len(row))) for row in m])
print(result)
# [[0 1 0 0]
# [1 2 3 0]
# [6 7 8 9]]

Numpy array insert every second element from second array

I have two arrays of the same shape and now want to combine them by making every odd element and 0 one of the first array and every even one of the second array in the same order.
E.g.:
a = ([0,1,3,5])
b = ([2,4,6])
c = ([0,1,2,3,4,5,6])
I tried something including modulo to identify uneven indices:
a = ([0,1,3,5])
b = ([2,4,6])
c = a
i = 0
j = 2
l = 0
for i in range(1,22):
k = (i+j) % 2
if k > 0:
c = np.insert(c, i, b[l])
l+=1
else:
continue
I guess there is some easier/faster slicing option, but can't figure it out.
np.insert would work well:
>>> A = np.array([1, 3, 5, 7])
>>> B = np.array([2, 4, 6, 8])
>>> np.insert(B, np.arange(len(A)), A)
array([1, 2, 3, 4, 5, 6, 7, 8])
However, if you don't rely on sorted values, try this:
>>> A = np.array([5, 3, 1])
>>> B = np.array([1, 2, 3])
>>> C = [ ]
>>> for element in zip(A, B):
C.extend(element)
>>> C
[5, 1, 3, 2, 1, 3]
read the documentation of the range
for i in range(0,10,2):
print(i)
will print [0,2,4,6,8]
From what I understand, the first element in a is always first the rest are just intereleaved. If that is the case, then some clever use of stacking and reshaping is probably enough.
a = np.array([0,1,3,5])
b = np.array([2,4,6])
c = np.hstack([a[:1], np.vstack([a[1:], b]).T.reshape((-1, ))])
You could try something like this
import numpy as np
A = [0,1,3,5]
B = [2,4,6]
lst = np.zeros(len(A)+len(B))
lst[0]=A[0]
lst[1::2] = A[1:]
lst[2::2] = B
Even though I don't understand why you would make it so complicated

How to select item from 2 arrays?

I have 2 arrays a and b that contain some data. I also have an array select that I wish to use to select from either a or b. I was just wondering if there is a pythonic way to do so. Here is my current implementation which puts each row of a and b into a list then selects from it.
a = np.zeros(shape=(10,2,1,3,4))
b = np.ones(shape=(10,2,1,3,4))
select = [1,1,1,0,1,0,1,0,1,0]
c = []
for a1,b1,select1 in zip(a,b,select):
a1b1 = [a1,b1]
c.append(a1b1[select])
If you choose only from two arrays, you can use select as a weight:
w = np.array(select)
c = (a.T * w + b.T * (1 - w)).T
This hack does not work if you want to combine more than two arrays.
In [512]: a = np.zeros(shape=(10,2,1,3,4))
...: b = np.ones(shape=(10,2,1,3,4))
...:
...: select = [1,1,1,0,1,0,1,0,1,0]
Using transpose in the same way that #DYZ does:
In [513]: res = np.where(select, a.T, b.T).T
In [514]: res.shape
Out[514]: (10, 2, 1, 3, 4)
If you don't want to transpose, you could add dimensions to select so that it broadcasts to the same shape as a and b:
In [516]: res1 = np.where(np.array(select)[:,None,None,None,None],a,b)
In [517]: res1.shape
Out[517]: (10, 2, 1, 3, 4)
In [518]: np.allclose(res,res1)
Out[518]: True
np.where is a very efficient solution but only works for up to two arrays.
I'd do it this way:
np.stack((a, b))[select, np.arange(len(a))]
This should scale to any number of arrays, e.g.:
a = ...
b = ...
# ...
z = ...
select = [0, 13, 2, 5, 25, ...]
np.stack((a, b, ... z))[select, np.arange(len(a))]

Categories