Please help, I need to have a moving value in my code based upon a list!
I have a list, the list is as follows:
my_list = [1, 2, 2, 3, 5, 6, 7, 7, 9, 10]
I have a part of my code which uses this list in order to do a sum, this is as follows:
val = my_list[0]+1
ans = val*9
What I want is to have val be replaced by each of the numbers in my_list i.e. the first time it would be 1x9 and then the next 2x9. However, I cannot find anywhere how to do this.
val = my_list[x]
val += 1
ans = val * 9
x += 1
this way you can just run your code, then add 1 to x
move the x += 1 line to whereever you want
Is your ans a list?
Do "(x+1)*9" for each elements?
ans = [(x+1)*9 for x in my_list]
What you want is vectorization - for which you can use the numpy package:
import numpy as np
my_list = [1, 2, 2, 3, 5, 6, 7, 7, 9, 10]
my_np_list = np.array(my_list)
ans = 9 * my_np_list
# vectorization applies to each element of my_np_list in parallel
# the `9 *` calculation.
## ans contains:
## array([ 9, 18, 18, 27, 45, 54, 63, 63, 81, 90])
## you can sum accross ans by the .sum() method
ans.sum() ## 468
It is as if you do:
ans = []
for x in my_list:
ans.append(9 * x)
Suppose I have the following numpy array:
>>> a = np.arange(0,21,1)
>>> a
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
Now suppose that I want to pick a window of length N, where 2 < N <= a.shape[0], such that the window is "centered" around one of the elements of the array a. For example, if I want to center a window of length N = 5 around the element 10 in array a, then this window would be:
>>> idx = 10 # index of the array element 10
>>> N = 5 # window size
>>> a[idx - N//2:idx + N//2 + 1]
array([ 8, 9, 10, 11, 12])
This method generalizes well for windows that are not near the edges of the array, but I can't make it work otherwise. For example, if I want to extract a window of length N = 7 around the element 2 in a, then what I get is:
>>> idx = 2
>>> N = 7
>>> a[idx - N//2:idx + N//2 + 1]
array([], dtype=int32)
However what I want is:
>>> a[0:7]
array([0, 1, 2, 3, 4, 5, 6])
How can I generalize this method for windows near the edges of a?
Try with:
idx = 2
start = min(idx - N//2, 0)
a[start:start + N]
Note that this is not centered at idx=2.
Based on Quang Hoang's answer, here is what worked:
import numpy as np
a = np.arange(0,21,1)
idx = 5 # desired element index
N = 7 # window length
if N % 2: # if window length is odd
step = N // 2
else: # if window length is even
step = int(N/2 - 1)
# make sure starting index is between 0 and a.shape[0] - N
start = min(max(idx-step,0),a.shape[0] - N)
window = a[start:start + N]
In Python:
How can I generate a list of N (e.g. 10) pseudo-random integers, each drawn from a specific range (e.g. between 3 and 9), with the list summing up to a specific value (e.g. 58)?
For this example the solution would look like this:
solution = [3, 7, 7, 9, 3, 6, 4, 8, 8, 3]
sum(solution)
58
That is, 10 numbers, each between 3 and 9, summing up to 58.
I've tried a solution approaches with np.random.dirichlet or np.random.multinomial as suggested in related questions here, but these do not allow for choosing the integers from a specific range.
import random
N = 10
s = 58
i, j = 3, 9
out = [i] * N
while sum(out) != s:
idx = random.randint(0, N-1)
if out[idx] < j:
out[idx] += 1
print(out)
Prints (for example):
[9, 7, 6, 4, 5, 8, 3, 5, 5, 6]
One idea I've just had is to initialise a list with n values that are the average value (so, as close to being all the same value as possible) and then randomly select a pair of values and increase one while decreasing the other while ensuring values are kept with the required range, so don't increase/decrease if the value will go out of bounds.
Repeat until success?
a = []
while sum(a) != 58:
a = random.choices(range(3, 10), k=10)
Takes about 17 attempts on average.
As shown in the following code, I have a chunk list x and the full list h. I want to reassign back the values stored in x in the correct positions of h.
index = 0
for t1 in range(lbp, ubp):
h[4 + t1] = x[index]
index = index + 1
Does anyone know how to write it in a single line/expression?
Disclaimer: This is part of a bigger project and I simplified the questions as much as possible. You can expect the matrix sizes to be correct but if you think I am missing something please ask for it. For testing you can use the following variable values:
h = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x = [20, 21]
lbp = 2
ubp = 4
You can use slice assignment to expand on the left-hand side and assign your x list directly to the indices of h, e.g.:
h = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
x = [20, 21]
lbp = 2
ubp = 4
h[4 + lbp:4 + ubp] = x # or better yet h[4 + lbp:4 + lbp + len(x)] = x
print(h)
# [1, 2, 3, 4, 5, 6, 20, 21, 9, 10]
I'm not really sure why are you adding 4 to the indexes in your loop nor what lbp and ubp are supposed to mean, tho. Keep in mind that when you select a range like this, the list you're assigning to the range has to be of the same length as the range.
I am trying to dynamically get the first and last element from an array.
So, let us suppose the array has 6 elements.
test = [1,23,4,6,7,8]
If I am trying to get the first and last = 1,8, 23,7 and 4,6. Is there a way to get elements in this order?
I looked at a couple of questions Link Link2. I took help of these links and I came up with this prototype..
#!/usr/bin/env python
import numpy
test = [1,23,4,6,7,8]
test1 = numpy.array([1,23,4,6,7,8])
len_test = len(test)
first_list = [0,1,2]
len_first = len(first_list)
second_list = [-1,-2,-3]
len_second = len(second_list)
for a in range(len_first):
print numpy.array(test)[[first_list[a] , second_list[a]]]
print test1[[first_list[a], second_list[a]]]
But this prototype won't scale for if you have more than 6 elements. So, I was wondering if there is way to dynamically get the pair of elements.
Thanks!
I ended here, because I googled for "python first and last element of array", and found everything else but this. So here's the answer to the title question:
a = [1,2,3]
a[0] # first element (returns 1)
a[-1] # last element (returns 3)
How about:
In [10]: arr = numpy.array([1,23,4,6,7,8])
In [11]: [(arr[i], arr[-i-1]) for i in range(len(arr) // 2)]
Out[11]: [(1, 8), (23, 7), (4, 6)]
Depending on the size of arr, writing the entire thing in NumPy may be more performant:
In [41]: arr = numpy.array([1,23,4,6,7,8]*100)
In [42]: %timeit [(arr[i], arr[-i-1]) for i in range(len(arr) // 2)]
10000 loops, best of 3: 167 us per loop
In [43]: %timeit numpy.vstack((arr, arr[::-1]))[:,:len(arr)//2]
100000 loops, best of 3: 16.4 us per loop
arr = np.array([1,2,3,4])
arr[-1] # last element
Using Numpy's fancy indexing:
>>> test
array([ 1, 23, 4, 6, 7, 8])
>>> test[::-1] # test, reversed
array([ 8, 7, 6, 4, 23, 1])
>>> numpy.vstack([test, test[::-1]]) # stack test and its reverse
array([[ 1, 23, 4, 6, 7, 8],
[ 8, 7, 6, 4, 23, 1]])
>>> # transpose, then take the first half;
>>> # +1 to cater to odd-length arrays
>>> numpy.vstack([test, test[::-1]]).T[:(len(test) + 1) // 2]
array([[ 1, 8],
[23, 7],
[ 4, 6]])
vstack copies the array, but all the other operations are constant-time pointer tricks (including reversal) and hence are very fast.
>>> test = [1,23,4,6,7,8]
>>> from itertools import izip_longest
>>> for e in izip_longest(test, reversed(test)):
print e
(1, 8)
(23, 7)
(4, 6)
(6, 4)
(7, 23)
(8, 1)
Another option
>>> test = [1,23,4,6,7,8]
>>> start, end = iter(test), reversed(test)
>>> try:
while True:
print map(next, [start, end])
except StopIteration:
pass
[1, 8]
[23, 7]
[4, 6]
[6, 4]
[7, 23]
[8, 1]
You can simply use take method and index of element (Last index can be -1).
arr = np.array([1,2,3])
last = arr.take(-1)
# 3
How about this?
>>> import numpy
>>> test1 = numpy.array([1,23,4,6,7,8])
>>> forward = iter(test1)
>>> backward = reversed(test1)
>>> for a in range((len(test1)+1)//2):
... print forward.next(), backward.next()
...
1 8
23 7
4 6
The (len(test1)+1)//2 ensures that the middle element of odd length arrays is also returned:
>>> test1 = numpy.array([1,23,4,9,6,7,8]) # additional element '9' in the middle
>>> forward = iter(test1)
>>> backward = reversed(test1)
>>> for a in range((len(test1)+1)//2):
... print forward.next(), backward.next()
1 8
23 7
4 6
9 9
Using just len(test1)//2 will drop the middle elemen of odd length arrays.
This does it. Note that with an odd number of elements the one in the middle won't be included.
test = [1, 23, 4, 6, 7, 8, 5]
for i in range(len(test)/2):
print (test[i], test[-1-i])
Output:
(1, 5)
(23, 8)
(4, 7)
How about this:
xs = [1,23,4,6,7,8]
np.array(list(zip(xs[:len(xs)//2], xs[::-1])))
array([[ 1, 8],
[23, 7],
[ 4, 6]])
Assuming the list has a even number of elements, you could do:
test = [1,23,4,6,7,8]
test_rest = reversed(test[:len(test)/2])
for n in len(test_rest):
print [test[n], test_test[n]]