List indexing in Python [duplicate] - python

This question already has answers here:
Python: filtering lists by indices
(7 answers)
Closed 8 years ago.
I have two lists a=[10,5,6,8] and b=[1,3]. How can I use the latter as a subscript of the former? I.e. I would like to extract the second and fourth element of a.
Put otherwise, in Matlab I would use
v = [16 5 9 4 2 11 7 14];
v([1 5 6]) % Extract the first, fifth, and sixth elements
>> ans =
16 2 11
How can I do the same in Python?

You can use operator.itemgetter to do it:
from operator import itemgetter
a=[10,5,6,8]
b=[1,3]
res = itemgetter(*b)(a)
# (5, 8)

You can use a list comprehension like so:
>>> a = [10, 5, 6, 8]
>>> b = [1, 3]
>>> [a[x] for x in b]
[5, 8]
>>>

numpy supports indexing with arrays, as well as a bunch of other array and matrix operations, in Matlab style. Consider using it for computationally intensive tasks:
In [1]: import numpy as np
In [2]: a = np.array([10,5,6,8])
In [3]: b = np.array([1,3])
In [4]: a[b]
Out[4]: array([5, 8])

l=[1 5 6]
v = [16 5 9 4 2 11 7 14];
[v[i] for i in l]
you can try like this
it can be explained like this
for i in l:
print v[i]

a=[10,5,6,8]
b=[1,3]
ex = [a[i] for i in b]
print(ex) # [5, 8]

Related

How to efficiently add or multiply every Nth element of a numpy array?

Suppose I have the following numpy array.
A = [1,2,3,4,5,6]
Question Is there a quick way to multiply or add every nth element in A to yield the following arrays?
B = [3*1, 2*4, 3*5, 4*6]
C = [3+1, 2+4, 3+5, 4+6]
I can accomplish this by rolling A and then adding or multiplying it to the original A.
T = np.roll(A,-2)
B = (A*T)[0:4]
C = (A*T)[0:4]
Just wondering if there is a more pythonic/efficient way to accomplish this? I have also looked at np.add.reduceat and np.multiply.reduceat but they do not seem to allow for skipping values.
You can do it in the following way:
A = np.array([1, 2, 3, 4, 5, 6])
k = 2
B = A[:-k]
C = A[k:]
print(B * C)
print(B + C)
Output
[ 3 8 15 24]
[ 4 6 8 10]
Cheers.

R's which() and which.min() Equivalent in Python

I read the similar topic here. I think the question is different or at least .index() could not solve my problem.
This is a simple code in R and its answer:
x <- c(1:4, 0:5, 11)
x
#[1] 1 2 3 4 0 1 2 3 4 5 11
which(x==2)
# [1] 2 7
min(which(x==2))
# [1] 2
which.min(x)
#[1] 5
Which simply returns the index of the item which meets the condition.
If x be the input for Python, how can I get the indeces for the elements which meet criteria x==2 and the one which is the smallest in the array which.min.
x = [1,2,3,4,0,1,2,3,4,11]
x=np.array(x)
x[x>2].index()
##'numpy.ndarray' object has no attribute 'index'
Numpy does have built-in functions for it
x = [1,2,3,4,0,1,2,3,4,11]
x=np.array(x)
np.where(x == 2)
np.min(np.where(x==2))
np.argmin(x)
np.where(x == 2)
Out[9]: (array([1, 6], dtype=int64),)
np.min(np.where(x==2))
Out[10]: 1
np.argmin(x)
Out[11]: 4
A simple loop will do:
res = []
x = [1,2,3,4,0,1,2,3,4,11]
for i in range(len(x)):
if check_condition(x[i]):
res.append(i)
One liner with comprehension:
res = [i for i, v in enumerate(x) if check_condition(v)]
Here you have a live example
NumPy for R provides you with a bunch of R functionalities in Python.
As to your specific question:
import numpy as np
x = [1,2,3,4,0,1,2,3,4,11]
arr = np.array(x)
print(arr)
# [ 1 2 3 4 0 1 2 3 4 11]
print(arr.argmin(0)) # R's which.min()
# 4
print((arr==2).nonzero()) # R's which()
# (array([1, 6]),)
The method based on python indexing and numpy, which returns the value of the desired column based on the index of the minimum/maximum value
df.iloc[np.argmin(df['column1'].values)]['column2']
built-in index function can be used for this purpose:
x = [1,2,3,4,0,1,2,3,4,11]
print(x.index(min(x)))
#4
print(x.index(max(x)))
#9
However, for indexes based on a condition, np.where or manual loop and enumerate may work:
index_greater_than_two1 = [idx for idx, val in enumerate(x) if val>2]
print(index_greater_than_two1)
# [2, 3, 7, 8, 9]
# OR
index_greater_than_two2 = np.where(np.array(x)>2)
print(index_greater_than_two2)
# (array([2, 3, 7, 8, 9], dtype=int64),)
You could also use heapq to find the index of the smallest. Then you can chose to find multiple (for example index of the 2 smallest).
import heapq
x = np.array([1,2,3,4,0,1,2,3,4,11])
heapq.nsmallest(2, (range(len(x))), x.take)
Returns
[4, 0]

excluding an internal element while slicing [duplicate]

This question already has answers here:
Understanding slicing
(38 answers)
Closed 7 years ago.
So I've got a list...
a = [1,2,3,4,5]
I can produce b without 5 by saying:
b = a[:-1]
How do I produce c without 3?
c = a[:2:]?
You would need to slice twice and concatenate the lists , Example -
c = a[:2] + a[3:] #2 being the index of element `3` in the array.
Demo -
>>> a = [1,2,3,4,5]
>>> a[:2] + a[3:]
[1, 2, 4, 5]
By adding two lists
>>> a = [1,2,3,4,5]
>>> c = a[:3-1] + a[3:] # Explicitly mentioned 3-1 to help understand better
>>> c
[1, 2, 4, 5]
An inplace way to remove
>>> a = [1,2,3,4,5]
>>> a.pop(3-1)
3
>>> a
[1, 2, 4, 5]
One method is to join the two list parts together as follows
a = [1,2,3,4,5]
c = a[:2] + a[3:]
c
[1,2,4,5]
You can also just pop the index out i.e.
>>> a = [1,2,3,4,5]
>>> a.pop(2)
>>> 3
>>> print(a)
[1,2,4,5]

Replace elements in numpy array using list of old and new values

I want to replace elements in a numpy array using a list of old values and new values. See below for a code example (replace_old is the requested method). The method must work for both int, float and string elements. How do I do that?
import numpy as np
dat = np.hstack((np.arange(1,9), np.arange(1,4)))
print dat # [1 2 3 4 5 6 7 8 1 2 3]
old_val = [2, 5]
new_val = [11, 57]
new_dat = replace_old(dat, old_val, new_val)
print new_dat # [1 11 3 4 57 6 7 8 1 11 3]
You can use np.place :
>>> np.place(dat,np.in1d(dat,old_val),new_val)
>>> dat
array([ 1, 11, 3, 4, 57, 6, 7, 8, 1, 11, 3])
For creating the mask array you can use np.in1d(arr1,arr2) which will give you :
a boolean array the same length as ar1 that is True where an element of ar1 is in ar2 and False otherwise
Edit:Note that the preceding recipe will replace old_values based on those order and as #ajcr mentioned it wont work for another arrays,so as a general way for now I suggest the following way using a loop (which I don't think that was the best way):
>>> dat2 = np.array([1, 2, 1, 2])
>>> old_val = [1, 2]
>>> new_val = [33, 66]
>>> z=np.array((old_val,new_val)).T
>>> for i,j in z:
... np.place(dat2,dat2==i,j)
...
>>> dat2
array([33, 66, 33, 66])
In this case you create a new array (z) which is contains the relevant pairs from old_val and new_val and then you can pass them to np.place and replace them .

Updating list values with new values read - Python [duplicate]

This question already has answers here:
How do i add two lists' elements into one list?
(4 answers)
Closed 9 years ago.
I was't really sure how to ask this. I have a list of 3 values initially set to zero. Then I read 3 values in at a time from the user and I want to update the 3 values in the list with the new ones I read.
cordlist = [0]*3
Input:
3 4 5
I want list to now look like:
[3, 4, 5]
Input:
2 3 -6
List should now be
[5, 7, -1]
How do I go about accomplishing this? This is what I have:
cordlist += ([int(g) for g in raw_input().split()] for i in xrange(n))
but that just adds a new list, and doesn't really update the values in the previous list
In [17]: import numpy as np
In [18]: lst=np.array([0]*3)
In [19]: lst+=np.array([int(g) for g in raw_input().split()])
3 4 5
In [20]: lst
Out[20]: array([3, 4, 5])
In [21]: lst+=np.array([int(g) for g in raw_input().split()])
2 3 -6
In [22]: lst
Out[22]: array([ 5, 7, -1])
I would do something like this:
cordlist = [0, 0, 0]
for i in xrange(n):
cordlist = map(sum, zip(cordlist, map(int, raw_input().split())))
Breakdown:
map(int, raw_input().split()) is equivalent to [int(i) for i in raw_input().split()]
zip basically takes a number a lists, and returns a list of tuples containing the elements that are in the same index. See the docs for more information.
map, as I explained earlier, applies a function to each of the elements in an iterable, and returns a list. See the docs for more information.
cordlist = [v1+int(v2) for v1, v2 in zip(cordlist, raw_input().split())]
tested like that:
l1 = [1,2,3]
l2 = [2,3,4]
print [v1+v2 for v1, v2 in zip(l1, l2)]
result: [3, 5, 7]
I would go that way using itertools.zip_longest:
from itertools import zip_longest
def add_lists(l1, l2):
return [int(i)+int(j) for i, j in zip_longest(l1, l2, fillvalue=0)]
result = []
while True:
l = input().split()
print('result = ', add_lists(result, l))
Output:
>>> 1 2 3
result = [1, 2, 3]
>>> 3 4 5
result = [4, 6, 8]
More compact version of #namit's numpy solution
>>> import numpy as np
>>> lst = np.zeros(3, dtype=int)
>>> for i in range(2):
lst += np.fromstring(raw_input(), dtype=int, sep=' ')
3 4 5
2 3 -6
>>> lst
array([ 5, 7, -1])

Categories