Iterating through multiple lists with same index position in python - python

I am new to python and I was just trying some list manipulations. I have three lists
A = [10,20,30,40,50,60]
B = [22,44,66,88,12,10]
C = [2,4,6,8,10,20]
I want to iterate over these three lists and for each value of C I want to add half of that value to the corresponding values of A and B.
For example for the 1st iteration -
half = 2/2= 1
So A = 10 + 1 and B = 22+1
So the final lists should look something like this
A = [11,22,33,44,55,70]
B = [23,46,69,92,17,20]
C = [2,4,6,8,10,20]

As long as the lists all have the same lengths, you can iterate with enumerate() function:
for i, n in enumerate(C):
A[i] += n/2
B[i] += n/2
>>> A
[11, 22, 33, 44, 55, 70]
>>> B
[23, 46, 69, 92, 17, 20]

>>> A, B = zip(*((a + c/2, b + c/2) for a, b, c in zip(A, B, C)))

ITs best to use Numpy arrays.
import numpy as np
A, B, C = map(np.array, [A, B, C])
A, B = A - C/2, B - C/2

Related

How to predict custom functions values?

There is this function, m=[12,24,168,672], the integer values of the function from t=0 to t=168 are known , as well as the fact that there are integers in the array b, it is required to calculate the following values of the function at t from 168 to 335, please tell me how this can be done.
Try this:
from math import cos, pi
def f(t, a, b, m):
# t is a number
# a is a list of 5 numbers
# b and m are lists of 4 numbers
return a[0] + sum(a[i + 1] * cos((t / m[i] + b[i] / 24) * 2 * pi)
for i in range(4))
Now you can compute your function:
>>> a = [10, 11, 11, 12, 12]
>>> b = [1, 2, 3, 4]
>>> m = [12, 24, 168, 672]
>>> f(170, a, b, m)
15.671777368560361

How do you compare and return duplicates in two different 2d list?

I would like to return the duplicates in two different 2d lists. But I'm having trouble figuring out what code to write. For example I would like variable "a" to compare to variable "b" and return the duplicates. Here are my two 2d list below.
a = [[2,3,6,8],[4,5,7,8,10],[15,17,21,22],[12,13,14,23,25]]
b = [[4,5,6],[15,17,21,22],[2,3,4],[2,3,6,8],[5,7,8,12,15],[7,12,14,17,32],[5,6,7,12,14]]
I would like my results to be:
c = [[2,3,6,8],[15,17,21,22]]
You just need to check if a list in a is also in b or not.
a = [[2,3,6,8],[4,5,7,8,10],[15,17,21,22],[12,13,14,23,25]]
b = [[4,5,6],[15,17,21,22],[2,3,4],[2,3,6,8],[5,7,8,12,15],[7,12,14,17,32],[5,6,7,12,14]]
c=[]
for i in a:
if i in b:
c.append(i)
print(c)
Output:
[[2, 3, 6, 8], [15, 17, 21, 22]]
This should work, it should get you started -
import itertools
#Input lists
a = [[2,3,6,8],[4,5,7,8,10],[15,17,21,22],[12,13,14,23,25]]
b = [[4,5,6],[15,17,21,22],[2,3,4],[2,3,6,8],[5,7,8,12,15],[7,12,14,17,32],[5,6,7,12,14]]
#Take a product of both the lists ( a X b )
z = itertools.product(a,b)
#Uncomment the following to see what itertools.product does
#[i for i in z]
#Return only the elements which the pair of the same element repeats (using string match)
[i[0] for i in z if str(i[0])==str(i[1])]
[[2, 3, 6, 8], [15, 17, 21, 22]]
one liner list comprehension approach:
dups = [i for i in a if i in b]
output:
[[2, 3, 6, 8], [15, 17, 21, 22]]
Try this:
a = [[2,3,6,8],[4,5,7,8,10],[15,17,21,22],[12,13,14,23,25]]
b = [[4,5,6],[15,17,21,22],[2,3,4],[2,3,6,8],[5,7,8,12,15],[7,12,14,17,32],[5,6,7,12,14]]
c = []
for i in a + b:
if (a + b).count(i) > 1 and i not in c:
c.append(i)
#mulaixi's answer is OK but in output list you may see duplicates.

Replace numbers in array for specific places only

There are 32 numbers in array c and all the number are 21. I want to replace the numbers in position 0,5,10,18,21,24,28 with 63. How can I do that?
a =32
b = [0,5,10,18,21,24,28]
c = []
for i in range(a):
c.append(21)
Setup:
More efficient creation of c, per Barmar
a = 32
b = [0, 5, 10, 18, 21, 24, 28]
c = [21] * a
Replace values at given indices:
list[index] allows for retrieval or assignment of a value to a specific index location in a list
for x in b:
c[x] = 63
Resources:
Python Lists

Solving for variables if you have the equation and variables using Python

If I have an equation, (a + (b - c) d - e) f = 75, how can I iterate through changing my variables a thru f? If a thru f are unique numbers [1,6], then there would be 6! ways of placing the numbers, right? So I imagine I have to increment through my variables somehow.
Assumptions/Limitations:
a-f are unique integers [1,6]
I'm using python and trying to solve without using built-in functions or libraries
Use 6 nested for-loops to enumerate all ways of setting each of a, b, c, d, e, and f to the values 1-6 (part I'm having an issue understanding how to organize)
Apparently there is only one permutation that will solve this particular equation
This seems like a good occasion to use sets:
In [17]: set1 = set([1,2,3,4,5,6])
In [18]: for a in set1:
...: for b in set1 - set([a]):
...: for c in set1 - set([a,b]):
...: for d in set1 - set([a,b,c]):
...: for e in set1 - set([a,b,c,d]):
...: for f in set1 - set([a,b,c,d,e]):
...: if (a + (b - c)*d - e)*f == 75:
...: print('found:', a, b, c, d, e, f)
...: break
...:
found: 4 6 2 3 1 5
In [19]: (4+(6-2)*3-1)*5
Out[19]: 75
By using the difference between sets, you make sure that you don't use the same value twice. For example:
In [20]: set([1,2,3,4,5,6]) - set([1,5])
Out[20]: {2, 3, 4, 6}
You can use itertools.permutations (the documentation contains a code sample if you don't want to use it directly):
>>> def func(a, b, c, d, e, f):
... return (a + (b - c) * d - e) * f == 75
>>> from itertools import permutations
>>> next(filter(lambda x: func(*x), permutations(range(1, 7), 6)))
(4, 6, 2, 3, 1, 5)

Optimizing assignment into an array from various arrays - NumPy

I have four square matrices with dimension 3Nx3N, called A, B, C and D.
I want to combine them in a single matrix.
The code with for loops is the following:
import numpy
N = 3
A = numpy.random.random((3*N, 3*N))
B = numpy.random.random((3*N, 3*N))
C = numpy.random.random((3*N, 3*N))
D = numpy.random.random((3*N, 3*N))
final = numpy.zeros((6*N, 6*N))
for i in range(N):
for j in range(N):
for k in range(3):
for l in range(3):
final[6*i + k][6*j + l] = A[3*i+k][3*j+l]
final[6*i + k + 3][6*j + l + 3] = B[3*i+k][3*j+l]
final[6*i + k + 3][6*j + l] = C[3*i+k][3*j+l]
final[6*i + k][6*j + l + 3] = D[3*i+k][3*j+l]
Is it possible to write the previous for loops in a numpythonic way?
Great problem for practicing array-slicing into multi-dimensional tensors/arrays!
We will initialize the output array as a multi-dimensional 6D array and simply slice it and assign the four arrays being reshaped as 4D arrays. The intention is avoid any stacking/concatenating as those would be expensive specially when working with large arrays by instead working with reshaping of input arrays, which would be merely views.
Here's the implementation -
out = np.zeros((N,2,3,N,2,3),dtype=A.dtype)
out[:,0,:,:,0,:] = A.reshape(N,3,N,3)
out[:,0,:,:,1,:] = D.reshape(N,3,N,3)
out[:,1,:,:,0,:] = C.reshape(N,3,N,3)
out[:,1,:,:,1,:] = B.reshape(N,3,N,3)
out.shape = (6*N,6*N)
Just to explain a bit more, we had :
|------------------------ Axes for selecting A, B, C, D
np.zeros((N,2,3,N,2,3),dtype=A.dtype)
|------------------------- Axes for selecting A, B, C, D
Thus, those two axes (second and fifth) of lengths (2x2) = 4 were used to select between the four inputs.
Runtime test
Approaches -
def original_app(A, B, C, D):
final = np.zeros((6*N,6*N),dtype=A.dtype)
for i in range(N):
for j in range(N):
for k in range(3):
for l in range(3):
final[6*i + k][6*j + l] = A[3*i+k][3*j+l]
final[6*i + k + 3][6*j + l + 3] = B[3*i+k][3*j+l]
final[6*i + k + 3][6*j + l] = C[3*i+k][3*j+l]
final[6*i + k][6*j + l + 3] = D[3*i+k][3*j+l]
return final
def slicing_app(A, B, C, D):
out = np.zeros((N,2,3,N,2,3),dtype=A.dtype)
out[:,0,:,:,0,:] = A.reshape(N,3,N,3)
out[:,0,:,:,1,:] = D.reshape(N,3,N,3)
out[:,1,:,:,0,:] = C.reshape(N,3,N,3)
out[:,1,:,:,1,:] = B.reshape(N,3,N,3)
return out.reshape(6*N,6*N)
Timings and verification -
In [147]: # Setup input arrays
...: N = 200
...: A = np.random.randint(11,99,(3*N,3*N))
...: B = np.random.randint(11,99,(3*N,3*N))
...: C = np.random.randint(11,99,(3*N,3*N))
...: D = np.random.randint(11,99,(3*N,3*N))
...:
In [148]: np.allclose(slicing_app(A, B, C, D), original_app(A, B, C, D))
Out[148]: True
In [149]: %timeit original_app(A, B, C, D)
1 loops, best of 3: 1.63 s per loop
In [150]: %timeit slicing_app(A, B, C, D)
100 loops, best of 3: 9.26 ms per loop
I'll start with a couple of generic observations
For numpy arrays we normally use the [ , ] syntax rather than [][]
final[6*i + k][6*j + l]
final[6*i + k, 6*j + l]
For new arrays built from others we often use things like reshape and slicing so that we can then add them together as blocks rather than with iterative loops
For an simple example, to take successive differences:
y = x[1:] - x[:-1]
Regarding the title, 'matrix creation' is clearer. 'load' has more of the sense of reading data from a file, as in np.loadtxt.
=================
So with N=1,
In [171]: A=np.arange(0,9).reshape(3,3)
In [172]: B=np.arange(10,19).reshape(3,3)
In [173]: C=np.arange(20,29).reshape(3,3)
In [174]: D=np.arange(30,39).reshape(3,3)
In [178]: final
Out[178]:
array([[ 0, 1, 2, 30, 31, 32],
[ 3, 4, 5, 33, 34, 35],
[ 6, 7, 8, 36, 37, 38],
[20, 21, 22, 10, 11, 12],
[23, 24, 25, 13, 14, 15],
[26, 27, 28, 16, 17, 18]])
Which can be created with one call to bmat:
In [183]: np.bmat([[A,D],[C,B]]).A
Out[183]:
array([[ 0, 1, 2, 30, 31, 32],
[ 3, 4, 5, 33, 34, 35],
[ 6, 7, 8, 36, 37, 38],
[20, 21, 22, 10, 11, 12],
[23, 24, 25, 13, 14, 15],
[26, 27, 28, 16, 17, 18]])
bmat uses a mix of hstack and vstack. It also produces a np.matrix, hence the need for .A. #Divakar's solution is bound to be faster.
This does not match with N=3. 3x3 blocks are out of order. But expanding the array to 6d (as Divakar does), and swapping some axes, puts the sub blocks into the the right order.
For N=3:
In [57]: block=np.bmat([[A,D],[C,B]])
In [58]: b1=block.A.reshape(2,3,3,2,3,3)
In [59]: b2=b1.transpose(1,0,2,4,3,5)
In [60]: b3=b2.reshape(18,18)
In [61]: np.allclose(b3,final)
Out[61]: True
In quick time tests (N=3), my approach is about half the speed of slicing_app.
As a matter of curiosity, bmat works with a string input: np.bmat('A,D;C,B'). That's because np.matrix was trying, years ago, to give a MATLAB feel.
you can just concat em
concat A and B horizontally
concat C and D horizontally
concat the conjunction of AB with the conjucntion of CD vertically
example:
AB = numpy.concatenate([A,B],1)
CD = numpy.concatenate([C,D],1)
ABCD = numpy.concatenate([AB,CD],0)
i hope that helps :)
Yet another way to do that, using view_as_blocks :
from skimage.util import view_as_blocks
def by_blocks():
final = numpy.empty((6*N,6*N))
a,b,c,d,f= [view_as_blocks(X,(3,3)) for X in [A,B,C,D,final]]
f[0::2,0::2]=a
f[1::2,1::2]=b
f[1::2,0::2]=c
f[0::2,1::2]=d
return final
You just have to think block by block, letting view_as_blocks manage strides and shapes for you. It is as fast as other numpy solutions.

Categories