I looked around and could not find anything this specific, so here goes:
I have a list of lists:
S = [[3,4],[6,7],[10,12]]
and I would like to add the 0th index of the ith index element and on to the end of another list:
R = [5,6,7]
Normally with a 1D list I could say:
R = R + S[i:]
and take all of the elements from the ith index on, but I want the 0th index of the ith index of a 2D S. If we started at i = 1 I would end up with:
R = [5,6,7,6,10]
Also, I don't want to use for loops I want a list slice method that will work (if there is one) because it needs to be within a certain bound.
You can use zip to transpose the matrix:
>>> S
[[3, 4], [6, 7], [10, 12]]
>>> zip(*S)
[(3, 6, 10), (4, 7, 12)]
Then slice the transposition:
>>> j=0
>>> i=1
>>> zip(*S)[j][i:]
(6, 10)
A tuple is iterable, so concatenation will work with a list:
>>> R = [5,6,7]
>>> R+=zip(*S)[j][i:]
>>> R
[5, 6, 7, 6, 10]
As #jonrsharpe mentioned, numpy will do the trick for you:
import numpy as np
# Create two arrays
S = np.asarray([[3,4],[6,7],[10,12]])
R = np.asarray([5, 6, 7])
# Slice the S array
i = 1
sliced_S = S[i:, 0]
# Concatenate the arrays
R = np.concatenate((R, sliced_S))
Have a look at numpy's impressive documentation and indexing in particular.
Related
Basically i have array = [[1 2 3],[4 5 6]]
I want to sum the values within 1 array to get sum_array = [6,15].
I have tried sum(array) on my actual dataset and got random numbers.(not the anticipated output).
sum can only be performed on an element that is configured with __add__ to handle it. For a list it needs to be, in a loose sense single dimensioned. Hence you need to get the flattened list inside.
Using List comprehension.
>>> [sum(l) for l in array]
=> [6, 15]
Using map
>>> list( map(sum, array) )
=> [6, 15]
#driver values :
IN : array = [[1,2,3],[4,5,6]]
Apart from existing answers, you can also use map and sum together for a better and cleaner approach:
array = [[1, 2, 3],[4, 5, 6]]
sumArray = map(sum, array)
OUTPUT
>>> sumArray
[6, 15]
You can use sum(array) as you suggested, just make sure you're creating a list with the values returned by sum:
array = [[1, 2, 3], [4, 5, 6]]
sums = [sum(x) for x in array]
>> [6, 15]
Using list comprehension along with sum eases the above task.
a = [ [1,2,3] , [4,5,6] ]
sum_list = [ sum[elem] for elem in a ]
print(sum_list)
#Output [6,15]
The below approach is lengthy, but I feel it is easier to understand for the beginner
array = [ [1,2,3], [4,5,6] ]
sum_list = []
for elements in array:
elements_sum = 0
for elem in elements:
elements_sum = elements_sum + elem
sum_list.append(elements_sum)
print(sum_list)
#Output [6,15]
and if you want the full sum of the array of array
do that
print(sum(list(map(sum, array)))
this will give you 21
I'm running Python 2.7.
I have an array called "altitude" with the following points
[0,1,2,3,4,5,6,7,8,9]
I also have an array called "arming_pin"
[0,0,0,0,0,0,1,1,1,1]
In my program when arming_pin is greater than zero I would like to use the "altitude" array data points and ignore the previous points when "arming_pin" was = to 0. I would like to call this new array "altitude_new". The "altitude_new" array would look like:
[6,7,8,9]
How can I do create this new array in python? Using a conditional statement of some sort?
You can use zip function within a list comprehension to filter your array :
>>> f=[0,1,2,3,4,5,6,7,8,9]
>>> sec=[0,0,0,0,0,0,1,1,1,1]
>>>
>>> [i for i,j in zip(f,sec) if j]
[6, 7, 8, 9]
You can also use itertools.compress Which is more efficient when you are dealing with larger list :
>>> from itertools import compress
>>> list(compress(f,sec))
[6, 7, 8, 9]
Or use numpy.compress:
>>> import numpy as np
>>> np.compress(sec,f)
array([6, 7, 8, 9])
You can also use the compress method from itertools module, this way:
>>> import itertools as it
>>> l1 = [0,1,2,3,4,5,6,7,8,9]
>>> l2 = [0,0,0,0,0,0,1,1,1,1]
>>> list(it.compress(l1,l2))
[6, 7, 8, 9]
altitude_new=[]
for i in range(len(arming_pin)):
if arming_pin[i] == 1:
altitude_new.append(altitude[i])
one line list comprehension:
altitude_new = [altitude[i] for i in range(len(arming_pin)) if arming_pin[i]]
night shade's comment is now more succinct [j for i,j in enumerate(altitude) if arming_pin[i]]
This is my solution, is meant to be easy to understand for people not accustomed to list comprehension.
altitude = [0,1,2,3,4,5,6,7,8,9]
arming_pin = [0,0,0,0,0,0,1,1,1,1]
altitude_new = []
idx = 0 # track the indices
for item in arming_pin:
if item > 0:
altitude_new.append(altitude[idx])
idx += 1
print altitude_new
>>> [6, 7, 8, 9]
This question already has answers here:
Transpose list of lists
(14 answers)
Closed 9 years ago.
I have a 2d list like this:
1 2 3
4 5 6
and I want to make this:
1 4
2 5
3 6
I've tried to do a for loop and switch each value but I keep getting an index out of bound error. Here's what I have:
for i in results:
for j in range(numCenturies):
rotated[i][j] = results [j][i]
From python documentation on zip function:
This function returns a list of tuples, where the i-th tuple contains the i-th element from each of the argument sequences or iterables. The returned list is truncated in length to the length of the shortest argument sequence. When there are multiple arguments which are all of the same length, zip() is similar to map() with an initial argument of None. With a single sequence argument, it returns a list of 1-tuples. With no arguments, it returns an empty list.
Example:
zip([1, 2, 3], [4, 5, 6]) # returns [(1, 4), (2, 5), (3, 6)]
If you need the result to be the list of lists, not the list of tuples, you can use list comprehension:
[list(x) for x in zip([1, 2, 3], [4, 5, 6], [7, 8, 9])] # returns [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
If all your variables are stored in one 2d list, and you want it pass it into zip function, you can use the following (I'll call it the star notation, because I can't remember the proper English term for it):
results = [[1, 2, 3], [4, 5, 6]]
zip(*results) # returns [(1, 4), (2, 5), (3, 6)]
http://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html
>>> from numpy import transpose
>>> transpose([[1,2,3],[4,5,6]])
array([[1, 4],
[2, 5],
[3, 6]])
zip is the right way to do this, as shown by aga.
But if you want to know why your original code wasn't working:
for i in results:
for j in range(numCenturies):
rotated[i][j] = results [j][i]
There are two clear problems here, and likely two others. (Since you didn't show us enough of the code or data to be sure, I can't guarantee the two likely ones.)
Presumably results looks something like this:
results = [[1, 2, 3], [4, 5, 6]]
When you do for i in results, that means i will be each element in results—that is, it will be [1, 2, 3], and then [4, 5, 6]. You can't use a list as an index into a list, so this is guaranteed to give you a TypeError: list indices must be integers, not list.
To fix this, you need:
for i in range(len(results)):
… or …
for i, row in enumerate(results):
Next, results[j][i] is guaranteed to raise IndexError: list index out of range, because i is each row number, but you're trying to use it as a column number. If you're iterating over the rows and columns of results, you want this:
rotated[j][i] = results[i][j]
Next, unless you pre-filled rotated with 3 lists, each of which was pre-filled with 2 objects of some kind, you're going to get an IndexError: list assignment index out of range.
To fix this, you need to pre-fill rotated, something like this:
rotated = [[None for j in range(2)] for i in range(3)]
… or …
rotated = [[None, None], [None, None], [None, None]]
Finally, I'll bet numCenturies is 3, in which case you'll get another IndexError: list index out of range as soon as j reaches 2. The simplest thing to do here is to just use the length of the row; there's no chance of an off-by-one error that way.
Putting it all together:
rotated = [[None for j in range(2)] for i in range(3)]
for i, row in enumerate(results):
for j, value in enumerate(row):
rotated[j][i] = value
But in general, Python gives you easier ways to do things than pre-creating arrays and looping over indices to fill in the values. You can use append—or, better, a list comprehension. Or, even better, find a higher-level way to write your use, like a single call to zip.
I have 2D list and I need to search for the index of an element. As I am begineer to programming I used the following function:
def in_list(c):
for i in xrange(0,no_classes):
if c in classes[i]:
return i;
return -1
Here classes is a 2D list and no_classes denotes the number of classes i.e the 1st dimesntion of the list. -1 is returned when c is not in the araray. Is there any I can optimize the search?
You don't need to define no_classes yourself. Use enumerate():
def in_list(c, classes):
for i, sublist in enumerate(classes):
if c in sublist:
return i
return -1
Use list.index(item)
a = [[1,2],[3,4,5]]
def in_list(item,L):
for i in L:
if item in i:
return L.index(i)
return -1
print in_list(3,a)
# prints 1
if order doesn't matter and you have no duplicates in your data, I suggest to turn you 2D list into list of sets:
>>> l = [[1, 2, 4], [6, 7, 8], [9, 5, 10]]
>>> l = [set(x) for x in l]
>>> l
[set([1, 2, 4]), set([8, 6, 7]), set([9, 10, 5])]
After that, your original function will work faster, because search of element in set is constant (while search of element in list is linear), so you algorithm becomes O(N) and not O(N^2).
Note that you should not do this in your function or it would be converted each time function is called.
If your "2D" list is rectangular (same number of columns for each line), you should convert it to a numpy.ndarray and use numpy functionalities to do the search. For an array of integers, you can use == for comparison. For an array of float numbers, you should use np.isclose instead:
a = np.array(c, dtype=int)
i,j = np.where(a == element)
or
a = np.array(c, dtype=float)
i,j = np.where(np.isclose(a, element))
such that i and j contain the line and column indices, respectively.
Example:
a = np.array([[1, 2],
[3, 4],
[2, 6]], dtype=float)
i, j = np.where(np.isclose(a, 2))
print(i)
#array([0, 2])
print(j)
#array([1, 0]))
using list comprehension: (2D list to 1D)
a = [[1,22],[333,55555,6666666]]
d1 = [x for b in a for x in b]
print(d1)
I know the steps to multiply two matrices are as follow
Step 1: Make sure that the the number of columns in the 1st one equals the number of rows in the 2nd one.
Step 2: Multiply the elements of each row of the first matrix by the elements of each column in the second matrix.
Step 3: Add the products.
How do you do the second step?
For example
A = [[3,4,5],[5,0,6],[5,7,1]]
B = [[2,1,3],[2,6,4]]
So far I got a function to find each column for the second one
def column(B,j):
col = []
for column in B:
col.append(column[j])
return col
Next I will have to make a function that finds each row for the first one
def rows(A,i):
But then I don't know how to create a function that will multiply them together like
row(A,0) • col(B,0)
row(A,0) • col(B,1)
row(A,1) • col(B,0)
row(A,1) • col(B,1)
row(A,2) • col(B,0)
row(A,2) • col(B,1)
You should probably use numpy:
import numpy as np
np.dot(row(A,0), col(B,0))
However, assuming you don't want to use that, you could do:
def dot(arr1, arr2):
return sum([x*y for x,y in zip(arr1, arr2)])
dot(row(A,0), col(B,0))
If you insist on using lists for this....
For C = A.B, you need
C_{ij} = sum(A_{ik} * B_{kj})
Here, i, j, and k are subscripts, with the first subscript denoting the row and the second denoting the column. i, j, k run over the rows and columns (i.e., list indices) of the matrix, so you can just write for loops over i, j, and k.
A has 3 columns, while B has 2 rows. So your example seems to contradict the requirement stated in Step 1. Nevertheless, this might be close to what you are looking for.
In [1]: A = [[3,4,5],[5,0,6],[5,7,1]]
In [2]: B = [[2,1,3],[2,6,4]]
In [3]: [[sum(r*c for r,c in zip(row, col)) for col in B] for row in A]
Out[3]: [[25, 50], [28, 34], [20, 56]]
By the way, here is a useful trick which you might find useful:
If you want to transpose a matrix, use zip(*B):
In [4]: zip(*B)
Out[4]: [(2, 2), (1, 6), (3, 4)]
This may be useful to you because it allows you to easily loop through the columns of B.
Here's a worked out example:
>>> 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]