Permute a tuple by a list of indices - python

I have a 3 element python tuple that I'm trying to sort or re-arrange using the indices of a 3-element list, and I want to know what the most concise way to do this is.
So far I've got:
my_tuple = (10, 20, 30)
new_positions = [2, 0, 1]
my_shuffled_tuple = my_tuple[new_positions[0]], my_tuple[new_positions[1]], my_tuple[new_positions[2]]
# outputs: (30, 10, 20)
I also get the same result if I do:
my_shuffled_tuple = tuple([my_tuple[i] for i in new_positions])
Is there a more concise way to create my_shuffled_tuple?

One way to do this is with a generator expression as an argument to tuple, which accepts an iterable:
In [1]: my_tuple = (10, 20, 30)
...: new_positions = [2, 0, 1]
...:
In [2]: my_shuffled_tuple = tuple(my_tuple[i] for i in new_positions)
In [3]: my_shuffled_tuple
Out[3]: (30, 10, 20)
If speed is an issue and you are working with a large amount of data, you should consider using Numpy. This allows direct indexing with a list or array of indices:
In [4]: import numpy as np
In [5]: my_array = np.array([10, 20, 30])
In [6]: new_positions = [2, 0, 1] # or new_positions = np.array([2, 0, 1])
In [7]: my_shuffled_array = my_array[new_positions]
In [8]: my_shuffled_array
Out[8]: array([30, 10, 20])

You can use operator.itemgetter like this:
from operator import itemgetter
my_tuple = (10, 20, 30)
new_positions = [2, 0, 1]
print itemgetter(*new_positions)(my_tuple)
If you will be accessing the elements of my_tuple (or other things too) in the new ordering a lot, you can save this itemgetter as a helper function:
access_at_2_0_1 = itemgetter(*new_positions)
and then access_at_2_0_1(foo) will be the same as tuple(foo[2], foo[0], foo[1]).
This is very helpful when you are trying to work with an argsort-like operation (where lots of arrays need to be re-accessed in a sort order that comes from sorting some other array). Generally, by that point you should probably be using NumPy arrays, but still this is a handy approach.
Note that as itemgetter relies on the __getitem__ protocol (derp) it is not guaranteed to work with all types of iterables, if that is important.

use a comprehension in a tuple() built-in function (it accept generators)
>>> my_tuple = (10, 20, 30)
>>> new_positions = [2, 0, 1]
>>> tuple(my_tuple[i] for i in new_positions)
(30, 10, 20)

Related

Numpy: How to subtract every other element in array

I have the following numpy array
u = np.array([a1,b1,a2,b2...,an,bn])
where I would like to subtract the a and b elements from each other and end up with a numpy array:
u_result = np.array([(a2-a1),(b2-b1),(a3-a2),(b3-b2),....,(an-a_(n-1)),(an-a_(n-1))])
How can I do this without too much array splitting and for loops? I'm using this in a larger loop so ideally, I would like to do this efficiently (and learn something new)
(I hope the indexing of the resulting array is clear)
Or simply, perform a substraction :
u = np.array([3, 2, 5, 3, 7, 8, 12, 28])
u[2:] - u[:-2]
Output:
array([ 2, 1, 2, 5, 5, 20])
you can use ravel torearrange as your original vector.
Short answer:
u_r = np.ravel([np.diff(u[::2]),
np.diff(u[1::2])], 'F')
Here a long and moore detailed explanation:
separate a from b in u this can be achieved indexing
differentiate a and b you can use np.diff for easiness of code.
ravel again the differentiated values.
#------- Create u---------------
import numpy as np
a_aux = np.array([50,49,47,43,39,34,28])
b_aux = np.array([1,2,3,4,5,6,7])
u = np.ravel([a_aux,b_aux],'F')
print(u)
#-------------------------------
#1)
# get a as elements with index 0, 2, 4 ....
a = u[::2]
b = u[1::2] #get b as 1,3,5,....
#2)
#differentiate
ad = np.diff(a)
bd = np.diff(b)
#3)
#ravel putting one of everyone
u_result = np.ravel([ad,bd],'F')
print(u_result)
You can try in this way. Firstly, split all a and b elements using array[::2], array[1::2]. Finally, subtract from b to a (np.array(array[1::2] - array[::2])).
import numpy as np
array = np.array([7,8,9,6,5,2])
u_result = np.array(array[1::2] - array[::2] )
print(u_result)
Looks like you need to use np.roll:
shift = 2
u = np.array([1, 11, 2, 12, 3, 13, 4, 14])
shifted_u = np.roll(u, -shift)
(shifted_u - u)[:-shift]
Returns:
array([1, 1, 1, 1, 1, 1])

numpy: how to get the maximum value like this in numpy? [duplicate]

I need a fast way to keep a running maximum of a numpy array. For example, if my array was:
x = numpy.array([11,12,13,20,19,18,17,18,23,21])
I'd want:
numpy.array([11,12,13,20,20,20,20,20,23,23])
Obviously I could do this with a little loop:
def running_max(x):
result = [x[0]]
for val in x:
if val > result[-1]:
result.append(val)
else:
result.append(result[-1])
return result
But my arrays have hundreds of thousands of entries and I need to call this many times. It seems like there's got to be a numpy trick to remove the loop, but I can't seem to find anything that will work. The alternative will be to write this as a C extension, but it seems like I'd be reinventing the wheel.
numpy.maximum.accumulate works for me.
>>> import numpy
>>> numpy.maximum.accumulate(numpy.array([11,12,13,20,19,18,17,18,23,21]))
array([11, 12, 13, 20, 20, 20, 20, 20, 23, 23])
As suggested, there is scipy.maximum.accumulate:
In [9]: x
Out[9]: [1, 3, 2, 5, 4]
In [10]: scipy.maximum.accumulate(x)
Out[10]: array([1, 3, 3, 5, 5])

Unpack a List in to Indices of another list in python

Is it possible to unpack a list of numbers in to list indices? For example I have a lists with in a list containing numbers like this:
a = [[25,26,1,2,23], [15,16,11,12,10]]
I need to place them in a pattern so i did something like this
newA = []
for lst in a:
new_nums = [lst[4],lst[2],lst[3],lst[0],lst[1]]
newA.append(new_nums)
print (newA) # prints -->[[23, 1, 2, 25, 26], [10, 11, 12, 15, 16]]
so instead of writing new_nums = [lst[4],lst[2],lst[3],lst[0],lst[1]] , i thought of defining a pattern as list called pattern = [4,2,3,0,1] and then unpack these in to those indices of lst to create new order of lst.
Is there a fine way to do this.
Given a list of indices called pattern, you can use a list comprehension like so:
new_lst = [[lst[i] for i in pattern] for lst in a]
operator.itemgetter provides a useful mapping function:
from operator import itemgetter
a = [[25,26,1,2,23], [15,16,11,12,10]]
f = itemgetter(4,2,3,0,1)
print [f(x) for x in a]
[(23, 1, 2, 25, 26), (10, 11, 12, 15, 16)]
Use list(f(x)) if you want list-of-lists instead of list-of-tuples.
If you're not opposed to using numpy, then try something like:
import numpy as np
pattern = [4, 2, 3, 0, 1]
newA = [list(np.array(lst)[pattern]) for lst in a]
Hope it helps.
In pure Python, you can use a list comprehension:
pattern = [4,2,3,0,1]
newA = []
for lst in a:
new_nums = [lst[i] for i in pattern]
newA.append(new_nums)
In numpy, you may use the fancy indexing feature:
>>> [np.array(lst)[pattern].tolist() for lst in a]
[[23, 1, 2, 25, 26], [10, 11, 12, 15, 16]]
it is slower than other, but it is another option. you can sort the list based on your pattern
a = [[25,26,1,2,23], [15,16,11,12,10]]
pattern = [4,2,3,0,1]
[sorted(line,key=lambda x:pattern.index(line.index(x))) for line in a]
[[23, 1, 2, 25, 26], [10, 11, 12, 15, 16]]

logical arrays and mapping in python

I'm trying to vectorize some element calculations but having difficulty doing so without creating list comprehensions for local information to global information. I was told that I can accomplish what I want to do using logical arrays, but so far the examples I've found has not been helpful. While yes I can accomplish this with list comprehensions, speed is a main concern with my code.
I have a set of values that indicate indices in the "global" calculation that should not be adjusted.
For example, these "fixed" indices are
1 2 6
If my global calculation has ten elements, I would be able to set all the "free" values by creating a list of the set of the global indices and subtracting the fixed indices.
free = list(set(range(len(global)) - set(fixed))
[0, 3, 4, 5, 7, 8, 9]
in the global calculation, I would be able to adjust the "free" elements as shown in the following code snippet
global = np.ones(10)
global[free] = global[free] * 10
which should produce:
global = [10, 1, 1, 10, 10, 10, 1, 10, 10, 10]
my "local" calculation is a subset of the global one, where the local map indicates the corresponding indices in the global calculation.
local_map = [4, 2, 1, 8, 6]
local_values = [40, 40, 40, 40, 40]
but I need the values associated with the local map to retain their order for calculation purposes.
What would the equivalent of global[free] be on the local level?
the desired output would be something like this:
local_free = list(set(range(len(local)) - set(fixed))
local_values[local_free] *= 10
OUTPUT: local_values = [400, 40, 40, 400, 40]
I apologize if the question formatting is off, the code block formatting doesn't seem to be working in my browser, so please let me know if you need clarification.
For such comparison-related operations, NumPy has tools like np.setdiff1d and np.in1d among others. To solve our case, these two would be enough. I would assume that the inputs are NumPy arrays, as then we could use vectorized indexing methods supported by NumPy.
On the first case, we have -
In [97]: fixed = np.array([1,2,6])
...: global_arr = np.array([10, 1, 1, 10, 10, 10, 1, 10, 10, 10])
...:
To get the equivalent of list(set(range(len(global_arr)) - set(fixed)) in NumPy, we could make use of np.setdiff1d -
In [98]: np.setdiff1d(np.arange(len(global_arr)),fixed)
Out[98]: array([0, 3, 4, 5, 7, 8, 9])
Next up, we have -
In [99]: local_map = np.array([4, 2, 1, 8, 6])
...: local_values = np.array([42, 40, 48, 41, 43])
...:
We were trying to get -
local_free = list(set(range(len(local)) - set(fixed))
local_values[local_free] *= 10
Here, we can use np.in1d to get a mask to be an equivalent for local_free that could be used to index and assign into local_values with NumPy's boolean-indexing method -
In [100]: local_free = ~np.in1d(local_map,fixed)
...: local_values[local_free] *= 10
...:
In [101]: local_values
Out[101]: array([420, 40, 48, 410, 43])

Python dictionary hold array ranges?

I am tryng to make a dict that could hold some array sniplets
like [127:130, 122:124] but dict = {1:[127:130, 122:124], 2:[127:129, 122:123]} doesn't work.
Is there a way to do this? It doesn't need to be dicts, but I want a bunch of these areas to be callable.
So I have 256x256 arrays and I want to select small areas in them for some calculations:
fft[127:130, 122:124]
Would be great if the whole part between brackets could be in a dict
You could use the slice function. It returns a slice object that can be stored in a dictionary. eg:
slice_1 = slice(127, 130)
slice_2 = slice(122, 124)
slice_a = slice(127, 129)
slice_b = slice(122, 123)
d = {1:[slice_1, slice_2],
2:[slice_a, slice_b]
}
x = fft[d[1]] # Same as fft[127:130, 122:124]
y = fft[d[2]] # Same as fft[127:129, 122:123]
Slicing numpy arrays returns a view, and not a copy, maybe this is what you are looking for?
import numpy
a = numpy.arange(10)
b = a[3:6] # array([3, 4, 5])
a[4] = 0
#b is now array([ 3, 0, 5])
b[1] = 1
#a is now array([0, 1, 2, 3, 1, 5, 6, 7, 8, 9])

Categories