standard python library to construct matrix - python

What is the easiest way to construct a zeros matrix with a cardinality of 1000 (row) x 10 (column) in Python without using numpy? (just the standard library)
Also, say if I get a list of values with 10 elements. say a=[1 2 3 ... 10], and I would like overwrite the 1st row of the zeros matrix with this list a. How would I go about doing it.
Many thanks.
PS: the reason that I would like to use the normal python list rather than numpy to construct the matrix is because of the requirement of this assignment, which does not allow any external libraries other than the python standard lib.

You can do:
m = [[0 for _ in range(10)] for _ in range(1000)]
m[0] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Note that if you use:
>>> matrix = 3*[3*[0]]
>>> matrix
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
after changing one element:
>>> matrix[0][0] = 1
>>> matrix
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]
the whole column will change. So you should use this method only if you don't need your elements to be able to change independently.

Related

How to modify a list if a matrix contain a value?

I have a list with values [5, 5, 5, 5, 5] and I have a matrix too filled with with 1 and 0.
I want to have a new list that have to be like this:
if there's a 1 into the matrix then sum a '2' into the v's value if it's the first row and sum a '3' it's the second row.
example:
list:
v = [5,5,5,5,5]
matrix:
m = [[0, 1, 1, 0, 0], [0, 0, 1, 1, 0]]
final result:
v1 = [5,7,10,8,5]
Create a function that adds array lines, you can have the parameters be 1D numeric arrays. Loops through the arrays and returns a result array that is the addition of each element.
If your task requires it, add a check if the lines are of equal length and abort the function with an error if so.
Run this function on all of the matrix lines and then run it for the result of that and the input array.
Hope I managed to be comprehensive enough
You can use NumPy package for efficient code.
import numpy as np
v = [5,5,5,5,5]
matrix = [[0, 1, 1, 0, 0],
[0, 0, 1, 1, 0]]
weights = np.array([2,3])
w_matrix = np.multiply(matrix, weights[:, np.newaxis]).sum(axis=0)
v1 = v + w_matrix
classical python:
You can use a loop comprehension:
to_add = [sum((A*B) for A,B in zip(factors,x)) for x in zip(*m)]
[a+b for a,b in zip(v, to_add)]
output: [5, 7, 10, 8, 5]
numpy:
That said, this is a perfect use case for numpy that is more efficient and less verbose:
import numpy as np
v = [5,5,5,5,5]
m = [[0, 1, 1, 0, 0], [0, 0, 1, 1, 0]]
factors = [2,3]
V = np.array(v)
M = np.array(m)
F = np.array(factors)
V+(M*F[:,None]).sum(0)
output: array([ 5, 7, 10, 8, 5])

Slicing Numpy array using List

Consider 2D Numpy array A and in-place function x like
A = np.arange(9).reshape(3,3)
def x(M):
M[:,2] = 0
Now, I have a list (or 1D numpy array) L pointing the rows, I want to select and apply the function f on them like
L = [0, 1]
x(A[L, :])
where the output will be written to A. Since I used index access to A, the matrix A is not affected at all:
A = array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
What I actually need is to slice the matrix such as
x(A[:2, :])
giving me the desired output
A = array([[0, 1, 0],
[3, 4, 0],
[6, 7, 8]])
The question is now, how to provide Numpy array slicing by the list L (either any automatic conversion of list to slice or if there is any build in function for that), because I am not able to convert the list L easily to slice like :2 in this case.
Note that I have both large matrix A and list L in my problem - that is the reason, why I would need the in-place operations to control the available memory.
Can you modify the function so as you can pass slice L inside it:
def func(M,L):
M[L,2] = 0
func(A,L)
print(A)
Out:
array([[0, 1, 0],
[3, 4, 0],
[6, 7, 8]])

I would expect the output to be like [[0,0,0,0,],[0,1,0,0],[0,2,0,0],[0,3,0,0]]

time_count = [[0, 0, 0, 0]] * 4
j = 0
for i in range(len(time_count)):
time_count[i][1] = j
j += 1
print(time_count)
Output:
[[0, 3, 0, 0], [0, 3, 0, 0], [0, 3, 0, 0], [0, 3, 0, 0]]
I would expect the output to be like:
[[0,0,0,0],[0,1,0,0],[0,2,0,0],[0,3,0,0]]
can someone explain why every index[1] is 3 ?
Easy fix:
time_count = [[0, 0, 0, 0] for _ in range(4)]
As Klaus D. has alluded, using the * operator on nested lists is usually a bad idea, as it duplicates the contents by copying the references. You won't notice this when multiplying sequences of immutable types, e.g. a list of integers, but when the elements are mutable, you get duplicates.
It's not good to write a list as [[0, 0, 0, 0]]*4. Lists are mutable. Each time you change any of the list elements all the copies of it will change. one good way to write is as below because that way you are not copying list elements.
[[0, 0, 0, 0] for i in range(4)]
The * operator just creates a new reference to the original list (here [0, 0, 0, 0]).
If you change the original list as time_count[i][1] = j, all the references reflect the same changes.
If you want to create a new list, you can use the extend method with a loop on it :
time_count = []
time_count.extend([0,0,0,0] for _ in range(4))
Now, all the element list in time_count store separate memory and can have different values.
Do:
time_count = [[0, 0, 0, 0]] * 4
print([[v if x!=1 else i for x,v in enumerate(a)] for i,a in enumerate(time_count)])
Output:
[[0, 0, 0, 0], [0, 1, 0, 0], [0, 2, 0, 0], [0, 3, 0, 0]]
UPDATE:
Explanation:
Use enumerate to iterate trough both the indexes and values of the list time_count.
Use enumerate again to iterate trough both the indexes and values of the list a. which is the iterator for time_count.
Go trough the indexes of a and say i (the index iterator for time_count) if x (the index iterator for a) is 1, otherwise say v (the iterator for a)
Note: This is all in a list comprehension
Basically, The entities of a list are pointers to a particular memory location. When one assigns list(a) to list(b) It implies that list(b) points to the same memory location as the list(a).
a = [1, 2, 3]
b = a
a = [3, 4, 5]
print(a, b)
[3, 4, 5] [1, 2, 3]
In the above-asked question if the inside of the nested list is multiplied by 4 times then all the sublists point to the same memory location. so, If one of the sublists is changed then the change is propagated to all of the sublists, Which basically creates unexpected results upon code execution. For anyone interested to know more,
the video sums up all the basic features of lists that are not obvious. It also explains the above question in further detail.
https://www.youtube.com/watch?v=_AEJHKGk9ns

Python Two-Dimensional Query..

I am seeing a very unusual behavior in python.. Kindly let me know what am i doing wrong!!
bc = [[0]*(n+1)]*(n+1)
for i in range(n+1):
bc[i][i] = 1
print (bc)
Output
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
I am trying to initialize the diagonal elements of two dimensional array to 1, but it is initializing all the elements with 1. I think I am doing something wrong with accessing two dimensional Array..
Also, kindly let me know how can I use two loops to access all the elements of two dimensional array.. my next step..
Thanks.
Your array is initialized incorrectly. The correct way to initialize a 2d array is this:
bc = [[0 for i in xrange(n + 1)] for i in xrange(n + 1)]
It's a common mistake, but the * operator copies the pointer to an list rather than copying the list, so while it looks like you have a 2d list, you actually have a 1d list of pointers to the same list.
the problem is that each array in your array is the same array in memory. you need a new array each time. the [[0]]*6 will for example make 6 of the same arrays in an array, editing one of them will update the other ones.
e.g.
>>> x=[1]
>>> y=x
>>> x.append(3)
>>> x
[1, 3]
>>> y
[1, 3]
>>> z=[x]*3
>>> x.append(6)
>>> z
[[1, 3, 4, 6], [1, 3, 4, 6], [1, 3, 4, 6]]
here is a fix by simply editing bc to be n+1 different arrays:
n=4
bc = [[0]*(n+1) for i in range(n+1)]
for i in range(n+1):
bc[i][i] = 1
print (bc)
[[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1]]
Try this one:
bc = [[0 for i in range(n+1)] for j in range(n+1)]
In your example you have only one (!) instance of [0] which is referenced multiple times. So if you change that instance, all references are changed.

Python multi-dimensional array initialization without a loop

Is there a way in Python to initialize a multi-dimensional array / list without using a loop?
Sure there is a way
arr = eval(`[[0]*5]*10`)
or
arr = eval(("[[0]*5]+"*10)[:-1])
but it's horrible and wasteful, so everyone uses loops (usually list comprehensions) or numpy
Depending on your real needs, the de facto "standard" package Numpy might provide you with exactly what you need.
You can for instance create a multi-dimensional array with
numpy.empty((10, 4, 100)) # 3D array
(initialized with arbitrary values) or create the same arrays with zeros everywhere with
numpy.zeros((10, 4, 100))
Numpy is very fast, for array operations.
The following does not use any special library, nor eval:
arr = [[0]*5 for x in range(6)]
and it doesn't create duplicated references:
>>> arr[1][1] = 2
>>> arr
[[0, 0, 0, 0, 0],
[0, 2, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]
Sure, you can just do
mylist = [
[1,2,3],
[4,5,6],
[7,8,9]
]
I don't believe it's possible.
You can do something like this:
>>> a = [[0] * 5] * 5
to create a 5x5 matrix, but it is repeated objects (which you don't want). For example:
>>> a[1][2] = 1
[[0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0]]
You almost certainly need to use some kind of loop as in:
[[0 for y in range(5)] for x in range(5)]
Recursion is your friend :D
It's a pretty naive implementation but it works!
dim = [2, 2, 2]
def get_array(level, dimension):
if( level != len(dimension) ):
return [get_array(level+1, dimension) for i in range(dimension[level])]
else:
return 0
print get_array(0, dim)
It depends on what you what to initialize the array to, but sure. You can use a list comprehension to create a 5×3 array, for instance:
>>> [[0 for x in range(3)] for y in range(5)]
[[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> [[3*y+x for x in range(3)] for y in range(5)]
[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [12, 13, 14]]
Yes, I suppose this still has loops—but it's all done in one line, which I presume is the intended meaning of your question?
a = [[]]
a.append([1,2])
a.append([2,3])
Then
>>> a
[[1, 2], [2, 3]]
If you're doing numerical work using Numpy, something like
x = numpy.zeros ((m,n))
x = numpy.ones ((m,n))
Python does not have arrays. It has other sequence types ranging from lists to dictionaries without forgetting sets - the right one depends on your specific needs.
Assuming your "array" is actually a list, and "initialize" means allocate a list of lists of NxM elements, you can (pseudocode):
for N times: for M times: add an element
for N times: add a row of M elements
write the whole thing out
You say you don't want to loop and that rules out the first two points, but why?
You also say you don't want to write the thing down (in response to JacobM), so how would you exactly do that? I don't know of any other way of getting a data structure without either generating it in smaller pieces (looping) or explicitly writing it down - in any programming language.
Also keep in mind that a initialized but empty list is no better than no list, unless you put data into it. And you don't need to initialize it before putting data...
If this isn't a theoretical exercise, you're probably asking the wrong question. I suggest that you explain what do you need to do with that array.
You can do by this way:
First without using any loop:
[[0] * n] * m
Secondly using simple inline list comprehension:
[[0 for column in range(n)] for row in range(m)]
You can use N-dimensional array (ndarray). Here is the link to the documentation. http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html

Categories

Resources