python, matrix column extraction and sum - python

Say I have a matrix A = [a_1,a_2,...,a_n]. Each column a_i belongs to a class. All classes are from 1 to K. All n column's labels are stored in one n-dim vector b.
Now for each class i, I need to sum all vectors in class i together and put the result vector as the i-th column of a new matrix. So the new matrix has K columns, same number of rows as A.
I know nonzero() can help me get index corresponding to one same label. But I don't know how to write everything without loop. I'm actually working on a large matrix. So using any "for" loop will definitely ruin the efficiency.
Example as following:
A = [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
label = [1,2,3,1,2,3]
New matrix = [[1+4,2+5,3+6],
[7+10,8+11,9+12]]
K=3, n=6

One way to avoid loops is to use map.
First create a func to reduce a list.
def red(l):
return list(map(lambda x: x[0] + x[1], zip(l[:3], l[3:])))
A = [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
Then apply map to the list of lists.
>>> list(map(red, A))
[[5, 7, 9], [17, 19, 21]]


I do not know why you are not able to use loops but here is the solution
import numpy as np
def masksum(v,vmask,elemn):
vmask = list(map(lambda x: 1 if x == elemn else 0, vmask))
a = np.array(v)
return np.sum(a * vmask)
def mysum(v1,vmask):
norepeat = list(set(vmask))
return list(map(lambda elemn: masksum(v1,vmask,elemn),norepeat))
A = [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]]
label = [1,2,3,1,2,3]
result = list(map(lambda vectori: mysum(vectori,label), A))
print(result)
label is like a mask you can try with [1,3,3,1,3,3] or [4,4,4,5,5,5] etc and the code will works

Related

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))

How to add elements of python lists in a dictionary

Below is list of arrays:
{'array_1': [1, 2, 3, 4], 'array_2': [3, 4, 5, 6], 'array_3': [7, 8, 9, 0]}
Code for array input:
def main():
a = int(input("Enter the number of array's: "))
size = int(input('Each array size: '))
arrays = dict()
for i in range(1, a + 1):
arrays['array_' + str(i)] = list(
map(lambda j: int(input('value: ')), [j for j in range(size)]))
print(arrays)
I want to add 'array_1' with array_2
Just for clarification, you have a dictionary of lists, not a list of arrays. I think this is what you're looking for
list_dict = {'array_1': [1, 2, 3, 4], 'array_2': [3, 4, 5, 6], 'array_3': [7, 8, 9, 0]}
[sum(items) for items in zip(list_dict['array_1'], list_dict['array_2'])]
this results in the list [4, 6, 8, 10] - I'm assuming that's what you mean by add array_1 and array_2
If by add you mean concatenate do this:
new_list = array['array_1'] + array['array_2']
else if you mean addition of individual values you can do:
from operator import add
new_array = list(map(add,array['array_1'],array['array_2']))
If you want to sum element wise then
d= {'array_1': [1, 2, 3, 4], 'array_2': [3, 4, 5, 6], 'array_3': [7, 8, 9, 0]}
[sum(x) for x in zip(*d.values())] # will add elements from all the lists
Output:
[11, 14, 17, 10]
going along the same lines if you just want to add lists corresponding to some keys then you can filter the keys to create a new dict and use it in a same way
[sum(x) for x in zip(*{key:value for key,value in d.items() if key in ['array_1','array_2']}.values())]
Output
[4, 6, 8, 10]

Finding unique solution puzzle python

x = np.array([[0,1,11],[0,2,11],[0,3,10],[0,4,10],[0,5,9],[0,6,9],[1,7,9],
[1,5,11],[1,6,11],[2,7,11],[2,8,10]])
I'm pretty new to this so i'm gonna call things like this [element1,element2,element3]
i have an array as shown above, and i want to find a solution to this array.
It should satisfy the following conditions:
The first element 0:
it should have atleast one solution from [0,1,11],[0,2,11],[0,3,10],[0,4,10],[0,5,9],[0,6,9]
The first element 1:
this : [1,7,9],[1,5,11],[1,6,11]
The first element 2:
and this : [2,7,11],[2,8,10]
Such that the second element and 3rd element is unique for each solution(where 1st element=0,second element=1 and 3rd element=2)
o/p can be :
[0,1,11] and [1,7,9] and [2,8,10]
wrong output :
[0,1,11], [1,6,11] ,[2,8,10]
here parameter 3 of the first and the second are same.
If I understand correctly, you want to produce triplets from the given x array so that the first, second and third element are all unique in one triplet. Code to do that:
import itertools
x = [[0,1,11],[0,2,11],[0,3,10],[0,4,10],[0,5,9],[0,6,9],[1,7,9],
[1,5,11],[1,6,11],[2,7,11],[2,8,10]]
triplets = itertools.combinations(x,3)
for t in triplets:
isGood = True
for pos in range(3):
if (t[0][pos] == t[1][pos] or t[0][pos] == t[2][pos] or t[1][pos] == t[2][pos]):
isGood = False
if (isGood):
print(repr(t))
This procudes the following output:
([0, 1, 11], [1, 7, 9], [2, 8, 10])
([0, 2, 11], [1, 7, 9], [2, 8, 10])
([0, 5, 9], [1, 6, 11], [2, 8, 10])
([0, 6, 9], [1, 5, 11], [2, 8, 10])
A more pythonic solution which does the same in only 3 lines
for t in itertools.combinations(x,3):
if all(len(col) == len(set(col)) for col in zip(*t)):
print(repr(t))
Insane one-liner:
print(''.join(repr(t) + '\n' for t in itertools.combinations(x,3) if all(len(col) == len(set(col)) for col in zip(*t))))

Looping through a mutidimentional array in python

How do i achieve line 9 and 10 i.e the two for loops in python
matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
]
newMatrix = []
for (i=0; i < len(matrix); i++):
for (j=0; j < len(matrix[i]); j++):
newMatrix[j][i] = matrix[i][j]
print newMatrix
PS: i know i can do [[row[i] for row in matrix] for i in range(4)] but how i do only using for loops
Use range (or xrange).
for i in range(len(matrix)):
for j in range(len(matrix[i])):
FYI, assigning to newMatrix[i][j] will fail, because newMatrix is an empty list. You need to add a new empty list to newMatrix for every row and then append the new value to that list in every iteration.
You can use the enumerate() function to loop over both the matrix values and give you indices:
newMatrix = [[0] * len(matrix) for _ in xrange(len(matrix[0]))]
for i, row in enumerate(matrix):
for j, value in enumerate(row):
newMatrix[j][i] = value
This outputs:
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
Because you are addressing rows and columns in the new matrix directly, you need to have initialized that new matrix with empty values first. The list comprehension on the first line of my example does this for you. It creates a new matrix that is (y, x) in size, given an input matrix of size (x, y).
Alternatively, you can avoid explicit looping altogether by (ab)using the zip function:
newMatrix = zip(*matrix)
which takes each row of matrix and groups each column in those rows into new rows.
In the generic case, python for constructs loop over sequences. The range() and xrange() functions can produce numerical sequences for you, these generate a number sequence in much the same way that a for loop in C or JavaScript would produce:
>>> for i in range(5):
>>> print i,
0 1 2 3 4
but the construct is far more powerful than the C-style for construct. In most such loops your goal is to provide indices into some sequence, the python construct bypasses the indices and goes straight to the values in the sequence instead.
Just to throw something else into the mix of answers, if you are doing any kind of matrix operations with Python, consider using numpy:
>>> import numpy
>>> matrix = numpy.matrix([
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12]
... ])
The transpose is pretty simple to do:
>>> matrix.transpose()
matrix([[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11],
[ 4, 8, 12]])
If I understand you correctly, what you want to do is a matrix transposition, which can be done this way:
zip(*matrix)

Categories

Resources