functions on arrays of different sizes in for loop - python

I have two arrays of different sizes that I want to perform logical functions on in a for loop. For example, if I have:
array1 = [6,7,8]
array2 = [1,2,3,4,5]
I want to do each element from array1 minus each element of array2 to get something like
[6-1,6-2,6-3,6-4,6-5],[7-1,7-2,7-3,7-4,7-5],[8-1,8-2,8-3,8-4,8-5]
which is subtracting each element from array2 from each element of array1
So i tried to do a for loop like:
for i in range(len(array1)):
ar = array1[i]-array2
and also
for i in range(len(array1)):
for j in range(len(array2)):
ar = array1[i]-array2[j]
But neither of these seem to be working
The first way seems to be returning an array of the right shape but certainly not the right values.
I'd like it to be returned in separate arrays because in reality, I have a very large sample size.

We can solve this using itertools.product
from itertools import product
from operator import sub
final = []
for item in array1:
prods = product([item], array2)
subs = [sub(*p) for p in prods]
final.append(subs)
print(final)
# [[5, 4, 3, 2, 1], [6, 5, 4, 3, 2], [7, 6, 5, 4, 3]]
How it works is product returns the cartesian product of the two arrays in the form of tuples, so:
(6, 1), (6, 2), etc....
Then we simply apply the sub function to each tuple using a list-comprehension.

The following solution should work using a list comprehension:
result = []
for value1 in array1:
result.append([value1 - value2 for value2 in array2])
You could even write this in 1 line using both for loops for the list comprehension:
result = [[value1 - value2 for value2 in array2] for value1 in array1]

Loops solution:
array1 = [6, 7, 8]
array2 = [1, 2, 3, 4, 5]
arr = []
for i in array1:
tmp = []
for j in array2:
tmp.append(i - j)
arr.append(tmp)
print(arr)
Output:
[[5, 4, 3, 2, 1], [6, 5, 4, 3, 2], [7, 6, 5, 4, 3]]

Your for loop is nearly correct except, you overwrite the value of ar every iteration (and you make it slightly more complicated with range)
You can achieve this through list comprehension
[[i - j for j in array2] for i in array1]
# [[5, 4, 3, 2, 1], [6, 5, 4, 3, 2], [7, 6, 5, 4, 3]]

You were on the right track but you had your arrays switched. You want array1 inside the inner loop to perform the operation you want to perform:
array1 = [6,7,8]
array2 = [1,2,3,4,5]
finalarray=[]
for i in range(len(array2)):
for j in range(len(array1)):
ar = array1[j]-array2[i]
finalarray.append(ar)
print(finalarray)
>>>[5, 6, 7, 4, 5, 6, 3, 4, 5, 2, 3, 4, 1, 2, 3]

ar is not being treated properly in your code, it needs to be an array of arrays (matrix) and you'll need another variable to hold the result per iteration, there's probably a better way to do this using list comprehensions but here is one way:
array1 = [6,7,8]
array2 = [1,2,3,4,5]
ar = []
row = []
for i in range(len(array1)):
for j in range(len(array2)):
row.append(array1[i]-array2[j])
ar.append(row)
row = []
print ar

There are plenty of good answers here, but another option especially useful for larger arrays is to use numpy, a package designed for moving large arrays of numbers efficiently. One possible answer in numpy would be this:
import numpy as np
array1 = np.arange(6,9) # make arrays 1 and 2
array2 = np.arange(1,6)
output = (array1.repeat(array2.shape[0]) # repeat array1 as many times as there are elements in array2
.reshape(array1.shape[0], -1) # reshape so we have a row for each element in array1
) - array2 # subtract array2 from each row
output
array([[5, 4, 3, 2, 1],
[6, 5, 4, 3, 2],
[7, 6, 5, 4, 3]])

Related

How to add value to particular part of python list?

NOTE: My need isn't this e.g. List[2:4] = 5
Suppose my List=[1,2,3,4,5,6]
I want to add 5 from index 2 to 4.
So the resultant List would be like List=[1,2,8,9,10,6]
If I have 2d array List=[[1,2,3],[4,5,6]] and want to add 5 to col 1 List=[[6,2,3],[9,5,6]]then what would be the code?
One approach is
my_list = [1,2,3,4,5]
add_item = [2,3]
new_list = [x+1 if i in add_item else x for i, x in enumerate(my_list)]
print(new_list)
This can be easily done through list comprehension.
The following function takes a 2D array 2d, a position index i and a value v, and adds v to the i-th element of each array.
def add_value(2d, i, v):
return [array[:i] + [array[i]+v] + array[i+1:] for array in 2d]
So, calling the function on the list in your example:
my_list = [[1,2,3],[4,5,6]]
add_value(my_list,0,5)
Would print out the desired output:
>>> [[6, 2, 3], [9, 5, 6]]
Numpy arrays can handle such slice operations:
import numpy as np
List = np.array([1, 2, 3, 4, 5, 6])
List[2:5] += 5
print(List)
Numpy will really come in handy for you if you have many of such tasks to do in your code. However, if it's just a one time thing in your code, you can do:
List = [1, 2, 3, 4, 5, 6]
for i in range(2, 5):
List[i] += 5
print(List)
Output:
[1, 2, 8, 9, 10, 6]
EDIT
Addressing your edit, you can also use numpy arrays like so:
import numpy as np
List = np.array([[1, 2, 3], [4, 5, 6]])
List[0] += 5
print(List)
Or using a loop:
List = [[1, 2, 3], [4, 5, 6]]
for i in range(len(List[0])):
List[0][i] += 5
print(List)
Output:
[[6, 7, 8], [4, 5, 6]]
One solution uses NumPy but my implementation is on an in-built list and other solutions are copying unnecessary elements.
So here I found the manual way to do it.
List = [[1,2,3,4,5],[6,7,8,9,10]]
# for horizontal update
colToUpdate = 2
for r in range(0,2):
A[r][colToUpdate] += add
# for vertical update
rowToUpdate = 1
for c in range(2,5):
A[rowToUpdate][c] += add

Transpose an already flattened square matrix

Given a square matrix represented as a list of lists, you can transpose it:
>>> l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> l_T = list(map(list, zip(*l)))
>>> l_T
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
You can then flatten a list of lists using a list comprehension:
>>> v = [i for j in l for i in j]
>>> v_T = [i for j in l_T for i in j]
>>> v
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> v_T
[1, 4, 7, 2, 5, 8, 3, 6, 9]
My question is, is there a way to take the flattened list version of a square matrix, and rearrange it so it becomes the transposed version? Here, that would be to get from v to v_T without going back through a list of lists. I have tried to map out the relationship between the matrix position and the list indices, but I am not seeing the pattern, let alone one that would generalize to lists of any (square) length.
In order to try to avoid any XY problems: my original goal was to be able to take some simple list of list matrices and iterate over them in different ways (i.e. left>right then top>bottom versus top>bottom then left>right). And if your starting point is l, then it is easy to just create the transpose and unpack. But I am imagining you have the flattened matrix (v) as a starting point, and you want to compute v_T directly. So I am really more curious about that algorithm now, and how to do so in Python.
Start by finding the square root of the lists' length, and take slices of the list iteratively, starting on different lags until you've sliced all columns (or what would be the columns in a transposed 2D array):
def transpose_flat_list(l):
n = int(len(l)**.5)
return [v for i in range(n) for v in l[i::n]]
For the shared example:
l = [1, 2, 3, 4, 5, 6, 7, 8, 9]
transpose_flat_list(l)
# [1, 4, 7, 2, 5, 8, 3, 6, 9]
This could easily be done in NumPy too by reshaping and raveling in fortran order as:
def transpose_flat_list_numpy(l):
n = int(len(l)**.5)
return np.array(l).reshape(n,n).ravel('F').tolist()
transpose_flat_list_numpy(l)
# [1, 4, 7, 2, 5, 8, 3, 6, 9]

Function is kicking out variable with 3, separate lists

For the program I am writing my goal is to call a function, give it 2 values and then have it spit back lists based on those 2 numbers. Here's what I have so far,
import numpy as np
def list_maker (n, m):
for n in range(n):
l = list(np.random.randint(1,9, m))
print(l)
My goal is to type "list_maker(3,5)" and have it output 3 lists, each with 5 elements. I want to keep using numpy so I can learn more about it rather than another type of operation. Whenever I call the function my out it,
list_maker(3,5)
[2, 7, 1, 5, 6]
[8, 5, 1, 3, 5]
[8, 2, 6, 3, 7]
However, I can not specifically change one element in one list, if I do l[0] = "Blank", all the elements at 0 position turn to blank and I can't do [0],[1]....
Any idea how to get an output like,
list_maker(3,5)
[[2, 7, 1, 5, 6],
[8, 5, 1, 3, 5],
[8, 2, 6, 3, 7]]
Where I can then specifically edit one element in one of the lists done by numpy?
Thank you for all the replies!
you want to return a list of lists. A simple list comprehension would work:
import numpy as np
def list_maker (n, m):
return [list(np.random.randint(1,9, m)) for _ in range(n)]
then:
>>> list_maker(3,5)
[[1, 7, 2, 5, 7], [3, 5, 5, 7, 7], [8, 5, 1, 1, 1]]
At the moment your function is just printing the lists and not returning them.
And I'm not entirely sure of your intent; at the moment you're not creating a numpy array, but a list. More specifically, you're creating a list of 3 lists, not 3 separate lists.
You could create a numpy array by passing the n, m values directly to numpy's randint:
np.random.randint(1,9, size=(n, m))

Adjacent/Connected Elements Array

I want to find connected (adjacent) elements in array.
For example, in the array:
[1,2,3,4,5]
To access all 2-connected elements, output would be:
1,2
2,3
3,4
4,5
To access all 3-connected elements, output would be
1,2,3
2,3,4
3,4,5
So as input I have an array and a value of n adjacent elements, and need to generate all the cases
With basic for loop:
for x in xrange(n):
I can get all the values of the index of the array, but I'm not sure how to get the next elements (using while loop runs into problem because the last index will not have any adjacent elements)
(What I was thinking of)
array = [1,2,3,4,5]
answer = []
for x in xrange(n):
while len(answer) < adjacent_value:
answer.append(array[x])
x+=1
def grouper(input_list, n):
return [input_list[i:i + n] for i in range(len(input_list) + 1 - n)]
print grouper([1, 2, 3, 4, 5], 3)
# [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
print grouper([1, 2, 3, 4, 5], 2)
# [[1, 2], [2, 3], [3, 4], [4, 5]]

How do you extract a column from a multi-dimensional array?

Does anybody know how to extract a column from a multi-dimensional array in Python?
>>> import numpy as np
>>> A = np.array([[1,2,3,4],[5,6,7,8]])
>>> A
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
>>> A[:,2] # returns the third columm
array([3, 7])
See also: "numpy.arange" and "reshape" to allocate memory
Example: (Allocating a array with shaping of matrix (3x4))
nrows = 3
ncols = 4
my_array = numpy.arange(nrows*ncols, dtype='double')
my_array = my_array.reshape(nrows, ncols)
Could it be that you're using a NumPy array? Python has the array module, but that does not support multi-dimensional arrays. Normal Python lists are single-dimensional too.
However, if you have a simple two-dimensional list like this:
A = [[1,2,3,4],
[5,6,7,8]]
then you can extract a column like this:
def column(matrix, i):
return [row[i] for row in matrix]
Extracting the second column (index 1):
>>> column(A, 1)
[2, 6]
Or alternatively, simply:
>>> [row[1] for row in A]
[2, 6]
If you have an array like
a = [[1, 2], [2, 3], [3, 4]]
Then you extract the first column like that:
[row[0] for row in a]
So the result looks like this:
[1, 2, 3]
check it out!
a = [[1, 2], [2, 3], [3, 4]]
a2 = zip(*a)
a2[0]
it is the same thing as above except somehow it is neater
the zip does the work but requires single arrays as arguments, the *a syntax unpacks the multidimensional array into single array arguments
>>> x = arange(20).reshape(4,5)
>>> x array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14],
[15, 16, 17, 18, 19]])
if you want the second column you can use
>>> x[:, 1]
array([ 1, 6, 11, 16])
If you have a two-dimensional array in Python (not numpy), you can extract all the columns like so,
data = [
['a', 1, 2],
['b', 3, 4],
['c', 5, 6]
]
columns = list(zip(*data))
print("column[0] = {}".format(columns[0]))
print("column[1] = {}".format(columns[1]))
print("column[2] = {}".format(columns[2]))
Executing this code will yield,
>>> print("column[0] = {}".format(columns[0]))
column[0] = ('a', 'b', 'c')
>>> print("column[1] = {}".format(columns[1]))
column[1] = (1, 3, 5)
>>> print("column[2] = {}".format(columns[2]))
column[2] = (2, 4, 6)
def get_col(arr, col):
return map(lambda x : x[col], arr)
a = [[1,2,3,4], [5,6,7,8], [9,10,11,12],[13,14,15,16]]
print get_col(a, 3)
map function in Python is another way to go.
array = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
col1 = [val[1] for val in array]
col2 = [val[2] for val in array]
col3 = [val[3] for val in array]
col4 = [val[4] for val in array]
print(col1)
print(col2)
print(col3)
print(col4)
Output:
[1, 5, 9, 13]
[2, 6, 10, 14]
[3, 7, 11, 15]
[4, 8, 12, 16]
[matrix[i][column] for i in range(len(matrix))]
The itemgetter operator can help too, if you like map-reduce style python, rather than list comprehensions, for a little variety!
# tested in 2.4
from operator import itemgetter
def column(matrix,i):
f = itemgetter(i)
return map(f,matrix)
M = [range(x,x+5) for x in range(10)]
assert column(M,1) == range(1,11)
You can use this as well:
values = np.array([[1,2,3],[4,5,6]])
values[...,0] # first column
#[1,4]
Note: This is not working for built-in array and not aligned (e.g. np.array([[1,2,3],[4,5,6,7]]) )
let's say we have n X m matrix(n rows and m columns) say 5 rows and 4 columns
matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16],[17,18,19,20]]
To extract the columns in python, we can use list comprehension like this
[ [row[i] for row in matrix] for in range(4) ]
You can replace 4 by whatever number of columns your matrix has.
The result is
[ [1,5,9,13,17],[2,10,14,18],[3,7,11,15,19],[4,8,12,16,20] ]
I think you want to extract a column from an array such as an array below
import numpy as np
A = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
Now if you want to get the third column in the format
D=array[[3],
[7],
[11]]
Then you need to first make the array a matrix
B=np.asmatrix(A)
C=B[:,2]
D=asarray(C)
And now you can do element wise calculations much like you would do in excel.
One more way using matrices
>>> from numpy import matrix
>>> a = [ [1,2,3],[4,5,6],[7,8,9] ]
>>> matrix(a).transpose()[1].getA()[0]
array([2, 5, 8])
>>> matrix(a).transpose()[0].getA()[0]
array([1, 4, 7])
Just use transpose(), then you can get the columns as easy as you get rows
matrix=np.array(originalMatrix).transpose()
print matrix[NumberOfColumns]
Well a 'bit' late ...
In case performance matters and your data is shaped rectangular, you might also store it in one dimension and access the columns by regular slicing e.g. ...
A = [[1,2,3,4],[5,6,7,8]] #< assume this 4x2-matrix
B = reduce( operator.add, A ) #< get it one-dimensional
def column1d( matrix, dimX, colIdx ):
return matrix[colIdx::dimX]
def row1d( matrix, dimX, rowIdx ):
return matrix[rowIdx:rowIdx+dimX]
>>> column1d( B, 4, 1 )
[2, 6]
>>> row1d( B, 4, 1 )
[2, 3, 4, 5]
The neat thing is this is really fast. However, negative indexes don't work here! So you can't access the last column or row by index -1.
If you need negative indexing you can tune the accessor-functions a bit, e.g.
def column1d( matrix, dimX, colIdx ):
return matrix[colIdx % dimX::dimX]
def row1d( matrix, dimX, dimY, rowIdx ):
rowIdx = (rowIdx % dimY) * dimX
return matrix[rowIdx:rowIdx+dimX]
If you want to grab more than just one column just use slice:
a = np.array([[1, 2, 3],[4, 5, 6],[7, 8, 9]])
print(a[:, [1, 2]])
[[2 3]
[5 6]
[8 9]]
Despite using zip(*iterable) to transpose a nested list, you can also use the following if the nested lists vary in length:
map(None, *[(1,2,3,), (4,5,), (6,)])
results in:
[(1, 4, 6), (2, 5, None), (3, None, None)]
The first column is thus:
map(None, *[(1,2,3,), (4,5,), (6,)])[0]
#>(1, 4, 6)
I prefer the next hint:
having the matrix named matrix_a and use column_number, for example:
import numpy as np
matrix_a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
column_number=2
# you can get the row from transposed matrix - it will be a column:
col=matrix_a.transpose()[column_number]
All columns from a matrix into a new list:
N = len(matrix)
column_list = [ [matrix[row][column] for row in range(N)] for column in range(N) ]

Categories

Resources