I'd like to be able to use list comprehension syntax to work with NumPy arrays easily.
For instance, I would like something like the below obviously wrong code to just reproduce the same array.
>>> X = np.random.randn(8,4)
>>> [[X[i,j] for i in X] for j in X[i]]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: arrays used as indices must be of integer (or boolean) type
What is the easy way to do this, to avoid using range(len(X)?
First, you should not be using NumPy arrays as lists of lists.
Second, let's forget about NumPy; your listcomp doesn't make any sense in the first place, even for lists of lists.
In the inner comprehension, for i in X is going to iterate over the rows in X. Those rows aren't numbers, they're lists (or, in NumPy, 1D arrays), so X[i] makes no sense whatsoever. You may have wanted i[j] instead.
In the outer comprehension, for j in X[i] has the same problem, but is has an even bigger problem: there is no i value. You have a comprehension looping over each i inside this comprehension.
If you're confused by a comprehension, write it out as an explicit for statement, as explained in the tutorial section on List Comprehensions:
tmp = []
for j in X[i]:
tmp.append([X[i,j] for i in X])
… which expands to:
tmp = []
for j in X[i]:
tmp2 = []
for i in X:
tmp2.append(X[i,j])
tmp.append(tmp2)
… which should make it obvious what's wrong here.
I think what you wanted was:
[[cell for cell in row] for row in X]
Again, turn it back into explicit for statements:
tmp = []
for row in X;
tmp2 = []
for cell in row:
tmp2.append(cell)
tmp.append(tmp2)
That's obviously right.
Or, if you really want to use indexing (but you don't):
[[X[i][j] for j in range(len(X[i]))] for i in range(len(X))]
So, back to NumPy. In NumPy terms, that last version is:
[[X[i,j] for j in range(X.shape[1])] for i in range(X.shape[0])]
… and if you want to go in column-major order instead of row-major, you can (unlike with a list of lists):
[[X[i,j] for i in range(X.shape[0])] for j in range(X.shape[1])]
… but that will of course transpose the array, which isn't what you wanted to do.
The one thing you can't do is mix up column-major and row-major order in the same expression, because you end up with nonsense.
Of course the right way to make a copy of an array is to use the copy method:
X.copy()
Just as the right way to transpose an array is:
X.T
The easy way is to not do this. Use numpy's implicit vectorization instead. For example, if you have arrays A and B as follows:
A = numpy.array([[1, 3, 5],
[2, 4, 6],
[9, 8, 7]])
B = numpy.array([[5, 3, 5],
[3, 5, 3],
[5, 3, 5]])
then the following code using list comprehensions:
C = numpy.array([[A[i, j] * B[i, j] for j in xrange(A.shape[1])]
for i in xrange(A.shape[0])])
can be much more easily written as
C = A * B
It'll also run much faster. Generally, you will produce faster, clearer code if you don't use list comprehensions with numpy than if you do.
If you really want to use list comprehensions, standard Python list-comprehension-writing techniques apply. Iterate over the elements, not the indices:
C = numpy.array([[a*b for a, b in zip(a_row, b_row)]
for a_row, b_row in zip(A, B)]
Thus, your example code would become
numpy.array([[elem for elem in x_row] for x_row in X])
Another option (though not necessarily performant) is to rethink your problem as a map instead of a comprehension and write a ufunc:
http://docs.scipy.org/doc/numpy/reference/ufuncs.html
You can call functional-lite routines like:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.apply_over_axes.html
http://docs.scipy.org/doc/numpy/reference/generated/numpy.vectorize.html
Etc.
Do you mean following?
>>> [[X[i,j] for j in range(X.shape[1])] for i in range(X.shape[0])]
[[0.62757350000000001, -0.64486080999999995, -0.18372566000000001, 0.78470704000000002],
[1.78209799, -1.336448459999999 9, -1.3851422200000001, -0.49668994],
[-0.84148266000000005, 0.18864597999999999, -1.1135151299999999, -0.40225053999999 999],
[0.93852824999999995, 0.24652238000000001, 1.1481637499999999, -0.70346624999999996],
[0.83842508000000004, 1.0058 697599999999, -0.91267403000000002, 0.97991269000000003],
[-1.4265273000000001, -0.73465904999999998, 0.6684284999999999 8, -0.21551155],
[-1.1115614599999999, -1.0035033200000001, -0.11558254, -0.4339924],
[1.8771354, -1.0189299199999999, - 0.84754008000000003, -0.35387946999999997]]
Using numpy.ndarray.copy:
>>> X.copy()
array([[ 0.6275735 , -0.64486081, -0.18372566, 0.78470704],
[ 1.78209799, -1.33644846, -1.38514222, -0.49668994],
[-0.84148266, 0.18864598, -1.11351513, -0.40225054],
[ 0.93852825, 0.24652238, 1.14816375, -0.70346625],
[ 0.83842508, 1.00586976, -0.91267403, 0.97991269],
[-1.4265273 , -0.73465905, 0.6684285 , -0.21551155],
[-1.11156146, -1.00350332, -0.11558254, -0.4339924 ],
[ 1.8771354 , -1.01892992, -0.84754008, -0.35387947]])
Related
From a list of strings, like this one:
example_list = ['010','101']
I need to get an array of integers, where each row is each one of the strings, being each character in one column, like this one:
example_array = np.array([[0,1,0],[1,0,1]])
I have tried with this code, but it isn't working:
example_array = np.empty([2,3],dtype=int)
i = 0 ; j = 0
for string in example_list:
for bit in string:
example_array[i,j] = int(bit)
j+=1
i+=1
Can anyone help me? I am using Python 3.6.
Thank you in advance for your help!
If all strings are the same length (this is crucial to building a contiguous array), then use view to efficiently separate the characters.
r = np.array(example_list)
r = r.view('<U1').reshape(*r.shape, -1).astype(int)
print(r)
array([[0, 1, 0],
[1, 0, 1]])
You could also go the list comprehension route.
r = np.array([[*map(int, list(l))] for l in example_list])
print(r)
array([[0, 1, 0],
[1, 0, 1]])
The simplest way is to use a list comprehension because it automatically generates the output list for you, which can be easily converted to a numpy array. You could do this using multiple for loops, but then you are stuck creating your list, sub lists, and appending to them. While not difficult, the code looks more elegant with list comprehensions.
Try this:
newList = np.array([[int(b) for b in a] for a in example_list])
newList now looks like this:
>>> newList
... [[0, 1, 0], [1, 0, 1]]
Note: there is not need to invoke map at this point, though that certainly works.
So what is going on here? We are iterating through your original list of strings (example_list) item-by-item, then iterating through each character within the current item. Functionally, this is equivalent to...
newList = []
for a in example_list:
tmpList = []
for b in a:
tmpList.append(int(b))
newList.append(tmpList)
newList = np.array(newList)
Personally, I find the multiple for loops to be easier to understand for beginners. However, once you grasp the list comprehensions you probably won't want to go back.
You could do this with map:
example_array = map(lambda x: map(lambda y: int(y), list(x)), example_list)
The outer lambda performs a list(x) operation on each item in example_list. For example, '010' => ['0','1','0']. The inner lambda converts the individual characters (resultants from list(x)) to integers. For example, ['0','1','0'] => [0,1,0].
I am working through some code trying to understand some Python mechanics, which I just do not get. I guess it is pretty simple and I also now, what it does, but i do not know how it works. I understand the normal use of for-loops but this here... I do not know.
Remark: I know some Python, but I am not an expert.
np.array([[[S[i,j]] for i in range(order+1)] for j in range(order+1)])
The second piece of code, I have problems with is this one:
for i in range(len(u)):
for j in range(len(v)):
tmp+=[rm[i,j][k]*someFuction(name,u[i],v[j])[k] for k in range(len(rm[i,j])) if rm[i,j][k]]
How does the innermost for-loop work? And also what does the if do here?
Thank you for your help.
EDIT: Sorry that the code is so unreadable, I just try to understand it myself. S, rm are numpy matrices, someFunction returns an array with scalar entries, andtmp is just a help variable
There are quite a few different concepts inside your code. Let's start with the most basic ones. Python lists and numpy arrays have different methodologies for indexation. Also you can build a numpy array by providing it a list:
S_list = [[1,2,3], [4,5,6], [7,8,9]]
S_array = np.array(S_list)
print(S_list)
print(S_array)
print(S_list[0][2]) # indexing element 2 from list 0
print(S_array[0,2]) # indexing element at position 0,2 of 2-dimensional array
This results in:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1 2 3]
[4 5 6]
[7 8 9]]
3
3
So for your first line of code:
np.array([[[S[i,j]] for i in range(order+1)] for j in range(order+1)])
You are building a numpy array by providing it a list. This list is being built with the concept of list comprehension. So the code inside the np.array(...) method:
[[[S[i,j]] for i in range(order+1)] for j in range(order+1)]
... is equivalent to:
order = 2
full_list = []
for j in range(order+1):
local_list = []
for i in range(order+1):
local_list.append(S_array[i, j])
full_list.append(local_list)
print(full_list)
This results in:
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
As for your second snippet its important to notice that although typically numpy arrays have very specific and constant (for all the array) cell types you can actually give the data type object to a numpy array. So creating a 2-dimensional array of lists is possible. It is also possible to create a 3-dimensional array. Both are compatible with the indexation rm[i,j][k]. You can check this in the following example:
rm = np.array(["A", 3, [1,2,3]], dtype="object")
print(rm, rm[2][0]) # Acessing element 0 of list at position 2 of the array
rm2 = np.zeros((3, 3, 3))
print(rm2[0, 1][2]) # This is also valid
The following code:
[rm[i,j][k]*someFuction(name,u[i],v[j])[k] for k in range(len(rm[i,j])) if rm[i,j][k]]
... could be written as such:
some_list = []
for k in range(len(rm[i,j])):
if rm[i, j][k]: # Expecting a boolean value (or comparable)
a_list = rm[i,j][k]*someFuction(name,u[i],v[j])
some_list.append(a_list[k])
The final detail is the tmp+=some_list. When you sum two list they'll be concatenated as can been seen in this simple example:
tmp = []
tmp += [1, 2, 3]
print(tmp)
tmp += [4, 5, 6]
print(tmp)
Which results in this:
[1, 2, 3]
[1, 2, 3, 4, 5, 6]
Also notice that multiplying a list by a number will effectively be the same as summing the list several times. So 2*[1,2] will result in [1,2,1,2].
Its a list comprehension, albeit a pretty unreadable one. That was someome doing something very 'pythonic' in spite of readablity. Just look up list comprehensions and try to rewrite it yourself as a traditional for loop. list comprehensions are very useful, not sure I would have gone that route here.
The syntax for a list comprehension is
[var for var in iterable if optional condition]
So this bottom line can be rewritten like so:
for k in range(len(rm[i,j]):
if rm[i,j][k]:
tmp+= rm[i,j][k]*someFunction(name,u[i],v[j])[k]
How to set the same value to the matrix of multiple rows and each row with different column numbers without for loop?
For example for matrix a:
a=matrix([[1,2,3],
[8,2,9],
[1,8,7]])
row = [1,2,3]
col = [[1,2]
[1,3]
[2,3]]
I want to set a[1,1],a[1,2],a[2,1],a[2,3],a[3,2],a[3,3] to the same value.
I know use for loop:
for i in xrange(len(row)):
a[row[i],col[i]] = setvalue
But is there anyway to do this without for loop?
Using numpy, you can avoid loops:
import numpy as np
from numpy.matlib import repmat
a = np.array([[1,2,3],
[8,2,9],
[1,8,7]])
row = np.array([[1],
[2],
[3]])
col = np.array([[1,2],
[1,3],
[2,3]])
row = repmat(row,1,col.shape[1])
setvalue = 0
a[row.ravel(),col.ravel()] = setvalue
However, it's important to note that in python indexing starts at 0, so you should actually do
a[row-1,col-1] = setvalue
Or even better, use the correct (zero-based) indices to initialise your row and col arrays.
Case 1: Use list comprehension
You can do like this:
value = 2
col_length = 3
line_length = 3
a = [[value for x in range(col_length)] for x in range(line_length)]
If you print a,
[[2, 2, 2], [2, 2, 2], [2, 2, 2]]
EDIT: Case 2 : Use map()
I am not very used to this one. But you can find more informations about it here in terms of performance. General idea: it seems faster when used with one function and no lambda expression.
You'll have to use a for loop.
Usually you want to avoid for loops (by using comprehesions) when following the functional paradigm, by building new instances instead of mutating the old one. As your goal is to mutate the old one, somewhere you will need a loop. The best you can do is to wrap it up in a function:
def set_items_to(mx, indices, value=0):
for row,cols in indices:
for col in cols:
mx[row, col] = value
a = matrix([[1,2,3],[4,5,6],[7,8,9]])
set_items_to(a, [
[0, [0,1]],
[1, [0,2]],
[2, [1,2]]
], setvalue)
EDIT
In case it is a programming challenge, there are ways to accomplish that without explicit for loops by using one of the built in aggregator functions. But this approach doesn't make the code clearer nor shorter. Just for completeness, it would look something like this:
def set_items_to(mx, indices, value=0):
sum(map(lambda item: [0,
sum(map(lambda col: [0,
mx.__setitem__((item[0], col), value)
][0], item[1]))
][0], indices))
I appreciate this may not be directly possible so I would be interested how you would go about solving this problem for a general case.
I have a list item that looks like this, [(array,time),(array,time)...] the array is a numpy array which can have any n by m dimensions. This will look like array[[derivatives dimension1],[derivatives dimension 2] ...]
From the list I want a function to create two lists which would contain all the values at the position passed to it. These could then be used for plotting.
I can think of ways to do this with alternative data structures but unfortunately this is no an option.
Essentially what I want is
def f(list, pos1, pos2):
xs = []
ys = []
for i in list:
ys.append(i pos1)
xs.append(i pos2)
return xs, ys
Where i pos1 is equivalent to i[n][m]
The real problem being when it's 1 by 1 so i can't just pass integers.
Any advice would be great, sorry the post is a bit long I wanted to be clear.
Thanks
If I'm understanding your question correctly, you essentially want to select indexes from a list of lists, and create new lists from that selection.
Selecting indexes from a list of lists is fairly simple, particularly if you have a fixed number of selections:
parts = [(item[pos1], item[pos2]) for item in list]
Creating new lists from those selections is also fairly easy, using the built-in zip() function:
separated = zip(*parts)
You can further reduce memory usage by using a generator expression instead of a list comprehension in the final function:
def f( list, pos1, pos2 ):
partsgen = ((item[pos1], item[pos2]) for item in list)
return zip(*partsgen)
Here's how it looks in action:
>>> f( [['ignore', 'a', 1], ['ignore', 'b', 2],['ignore', 'c', 3]], 1, 2 )
[('a', 'b', 'c'), (1, 2, 3)]
Update: After re-reading the question and comments, I'm realizing this is a bit over-simplified. However, the general idea should still work when you exchange pos1 and pos2 for appropriate indexing into the contained array.
if i understand your question, something like the following should be easy and fast, particularly if you need to do this multiple times:
z = np.dstack([ arr for arr, time in lst ])
x, y = z[pos1], z[pos2]
for example:
In [42]: a = arange(9).reshape(3,3)
In [43]: z = np.dstack([a, a*2, a*3])
In [44]: z[0,0]
Out[44]: array([0, 0, 0])
In [45]: z[1,1]
Out[45]: array([ 4, 8, 12])
In [46]: z[0,1]
Out[46]: array([1, 2, 3])
I am very new to Python, I need to read numbers from a file and store them in a matrix like I would do it in fortran or C;
for i
for j
data[i][j][0]=read(0)
data[i][j][1]=read(1)
data[i][j][2]=read(2)
...
...
How can I do the same in Python? I read a bit but got confused with tuples and similar things
If you could point me to a similar example it would be great
thanks
Python doesn't come with multi-dimensional arrays, though you can add them through the popular numpy third-party package. If you want to avoid third-party packages, what you would do in Python would be to use a list of lists of lists (each "list" being a 1-D "vector-like" sequence, which can hold items of any type).
For example:
data = [ [ [0 for i in range(4)] for j in range(5)] for k in range(6)]
this makes a list of 6 items which are lists of 5 items which are lists of 4 0's -- i.e., a 6 x 5 x 4 "3D matrix" which you could then address the way you want,
for i in range(6):
for j in range(5):
data[i][j][0]=read(0)
data[i][j][1]=read(1)
data[i][j][2]=read(2)
to initialize the first three of the four items on each most-nested sublist with calls to that mysterious function read which presumably you want to write yourself (I have no idea what it's supposed to do -- not "read and return the next number" since it takes a mysterious argument, but, then what?).
It depends on your file format, but take a look on:
Link
and
http://docs.scipy.org/doc/scipy/reference/tutorial/io.html
You may want to use numpy and use the built in function for using I/O, in particular loadtxt.
http://docs.scipy.org/doc/numpy/reference/generated/numpy.loadtxt.html
There are a lot of addictional functions to handle I/O:
http://docs.scipy.org/doc/numpy/reference/routines.io.html
A simple example would be:
data = []
with open(_filename_, 'r') as f:
for line in f:
data.append([int(x) for x in line.split()])
A way to extend the list in a form to work like matrix. I have gone through other codes of matrix in python, all are using comprehensions to first initialize a list of required size and then update the values (which takes a little more time).Let the r represents row and c for column.
r = input('Enter row size: ')
c = input('Enter column size: ')
m = []
for i in range(r):
m.append([])
for j in range(c):
m[i].append(input())
for i in m:
print i
Here, you can input the elements of matrix as it was in 'C' or equivalent languages. Hope this may help someone a different view of implementing matrices.
Matrices are two dimensional structures. In plain Python, the most natural representation of a matrix is as a list of lists.
So, you can write a row matrix as:
[[1, 2, 3, 4]]
And write a column matrix as:
[[1],
[2],
[3],
[4]]
This extends nicely to m x n matrices as well:
[[10, 20],
[30, 40],
[50, 60]]
See matfunc.py for an example of how to develop a full matrix package in pure Python.
The documentation for it is here.
And here is a worked-out example of doing matrix multiplication in plain python using a list-of-lists representation:
>>> from pprint import pprint
>>> def mmul(A, B):
nr_a, nc_a = len(A), len(A[0])
nr_b, nc_b = len(B), len(B[0])
if nc_a != nr_b:
raise ValueError('Mismatched rows and columns')
return [[sum(A[i][k] * B[k][j] for k in range(nc_a))
for j in range(nc_b)] for i in range(nr_a)]
>>> A = [[1, 2, 3, 4]]
>>> B = [[1],
[2],
[3],
[4]]
>>> pprint(mmul(A, B))
[[30]]
>>> pprint(mmul(B, A), width=20)
[[1, 2, 3, 4],
[2, 4, 6, 8],
[3, 6, 9, 12],
[4, 8, 12, 16]]
As another respondent mentioned, if you get serious about doing matrix work, it would behoove you to install numpy which has direct support for many matrix operations: