How do I append values in an empty numpy array? I have an array of values that I want to perform a mathematical equation on and from those values I want to append it to a new empty array. What I have is:
qa = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
values_a = np.array([])
for n in qa:
value = np.math.factorial(n + 19)/(np.math.factorial(n)*np.math.factorial(19))
values_array = np.append(values_a, value)
However, it isn't appending and not sure why?
You're missing the array name, you're using values_array instead of values_a. Here's a code that works using your logic:
qa = np.arange(21)
values_a = np.array([])
for n in qa:
value = np.math.factorial(n + 19)/(np.math.factorial(n)*np.math.factorial(19))
values_a = np.append(values_a, value)
Nevertheless, as some comments say, it is not recommended to use numpy.append inside a loop, so you can use scipy.special.factorial instead. It allows calculating the factorial of the whole array element-wise:
from scipy.special import factorial
factorial(qa + 19)/(factorial(qa) * factorial(19))
You are assigning the result of np.append to values_array, but next time through your loop you are overwriting that assignment. Instead, you want to assign the results of np.append into values_a so that you are building up values_a each successive iteration:
values_a = np.array([])
for n in qa:
value = np.math.factorial(n + 19)/(np.math.factorial(n)*np.math.factorial(19))
values_a = np.append(values_a, value)
Related
Suppose I have a sorted array of integers say
partition = [0, 3, 7, 12, 18, 23, 27]
and then given a value
value = 9
I would like to return the interval on which my value sits. For example
bounds = function(partition, value)
print(bounds)
>>>[7,12]
Is there a function out there that might be able to help me or do I have to build this from scratch?
Try numpy.searchsorted(). From the documentary:
Find indices where elements should be inserted to maintain order.
import numpy as np
partition = np.array( [0, 3, 7, 12, 18, 23, 27] )
value = 9
idx = np.searchsorted(partition,value)
bound = (partition[idx-1],partition[idx])
print(bound)
>>>>(7,12)
The advantage of searchsorted is that it can give you the index for multiple values at once.
The bisect module is nice for doing this efficiently. It will return the index of the higher bound.
You'll need to do some error checking if the value can fall outside the bounds:
from bisect import bisect
partition = [0, 3, 7, 12, 18, 23, 27]
value = 9
top = bisect(partition, value)
print(partition[top-1], partition[top])
# 7 12
def function(partition,value):
for i in range(len(partition)):
if partition[i]<value and partition[i+1]>value:
print [partition[i],partition[i+1]]
partition = [0, 3, 7, 12, 18, 23, 27,5,10]
value=9
function(partition,value)
Actually i want to remove the elements from numpy array which are closer to each other.For example i have array [1,2,10,11,18,19] then I need code that can give output like [1,10,18] because 2 is closer to 1 and so on.
In the following is provided an additional solution using numpy functionalities (more precisely np.ediff1d which makes the differences between consecutive elements of a given array. This code considers as threshold the value associated to the th variable.
a = np.array([1,2,10,11,18,19])
th = 1
b = np.delete(a, np.argwhere(np.ediff1d(a) <= th) + 1) # [1, 10, 18]
Here is simple function to find the first values of series of consecutives values in a 1D numpy array.
import numpy as np
def find_consec(a, step=1):
vals = []
for i, x in enumerate(a):
if i == 0:
diff = a[i + 1] - x
if diff == step:
vals.append(x)
elif i < a.size-1:
diff = a[i + 1] - x
if diff > step:
vals.append(a[i + 1])
return np.array(vals)
a = np.array([1,2,10,11,18,19])
find_consec(a) # [1, 10, 18]
Welcome to stackoverflow. below is the code that can answer you question:
def closer(arr,cozy):
result = []
result.append(arr[0])
for i in range(1,len(arr)-1):
if arr[i]-result[-1]>cozy:
result.append(arr[i])
print result
Example:
a = [6,10,7,20,21,16,14,3,2]
a.sort()
closer(a,1)
output : [2, 6, 10, 14, 16, 20]
closer(a,3)
Output: [2, 6, 10, 14, 20]
Numpy has а repeat function, that repeats each element of the array a given (per element) number of times.
I want to implement a function that does similar thing but repeats not individual elements, but variably sized blocks of consecutive elements. Essentially I want the following function:
import numpy as np
def repeat_blocks(a, sizes, repeats):
b = []
start = 0
for i, size in enumerate(sizes):
end = start + size
b.extend([a[start:end]] * repeats[i])
start = end
return np.concatenate(b)
For example, given
a = np.arange(20)
sizes = np.array([3, 5, 2, 6, 4])
repeats = np.array([2, 3, 2, 1, 3])
then
repeat_blocks(a, sizes, repeats)
returns
array([ 0, 1, 2,
0, 1, 2,
3, 4, 5, 6, 7,
3, 4, 5, 6, 7,
3, 4, 5, 6, 7,
8, 9,
8, 9,
10, 11, 12, 13, 14, 15,
16, 17, 18, 19,
16, 17, 18, 19,
16, 17, 18, 19 ])
I want to push these loops into numpy in the name of performance. Is this possible? If so, how?
Here's one vectorized approach using cumsum -
# Get repeats for each group using group lengths/sizes
r1 = np.repeat(np.arange(len(sizes)), repeats)
# Get total size of output array, as needed to initialize output indexing array
N = (sizes*repeats).sum() # or np.dot(sizes, repeats)
# Initialize indexing array with ones as we need to setup incremental indexing
# within each group when cumulatively summed at the final stage.
# Two steps here:
# 1. Within each group, we have multiple sequences, so setup the offsetting
# at each sequence lengths by the seq. lengths preceeeding those.
id_ar = np.ones(N, dtype=int)
id_ar[0] = 0
insert_index = sizes[r1[:-1]].cumsum()
insert_val = (1-sizes)[r1[:-1]]
# 2. For each group, make sure the indexing starts from the next group's
# first element. So, simply assign 1s there.
insert_val[r1[1:] != r1[:-1]] = 1
# Assign index-offseting values
id_ar[insert_index] = insert_val
# Finally index into input array for the group repeated o/p
out = a[id_ar.cumsum()]
This function is a great candidate to speed up using Numba:
#numba.njit
def repeat_blocks_jit(a, sizes, repeats):
out = np.empty((sizes * repeats).sum(), a.dtype)
start = 0
oi = 0
for i, size in enumerate(sizes):
end = start + size
for rep in range(repeats[i]):
oe = oi + size
out[oi:oe] = a[start:end]
oi = oe
start = end
return out
This is significantly faster than Divakar's pure NumPy solution, and a lot closer to your original code. I made no effort at all to optimize it. Note that np.dot() and np.repeat() can't be used here, but that doesn't matter when all the code gets compiled.
Plus, since it is njit meaning "nopython" mode, you can even use #numba.njit(nogil=True) and get multicore speedup if you have many of these calls to make.
I want to go through each element of an array I've created. However, I'm doing some debugging and it's not. Here's what I have so far and what it's printing out.
def prob_thirteen(self):
#create array of numbers 2-30
xcoords = [range(2,31)]
ycoords = []
for i in range(len(xcoords)):
print 'i:', xcoords[i]
output:
i: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
Why does 'i' return my whole array and not just the first element: 2? I'm not sure why this is returning my whole array.
xcoords = [range(2,31)]
This line will create an array of length 1. The only element in that array is an array of the numbers 2 -> 30. Your loop is printing the elements of the outer array. Change that line to:
xcoords = range(2,31)
This answer is correct for Python 2 because the range function returns a list. Python 3 will return a range object (which can be iterated on producing the required values). The following line should work in Python 2 and 3:
xoords = list(range(2,31))
First of all, change xcoords so that it isn't a list inside a list:
xcoords = range(2, 31)
We don't need to iterate over a list using an index into the list using len(xcoords). In python we can simply iterate over a list like this:
for coord in xcoords:
print "i: ", coord
If we did need to keep track of the index we could use enumerate:
for i, coord in enumerate(xcoords):
print str(i) + ":", coord
I'm having a problem where when I pass an array into a function, the original value of the array is changed. My example below should clarify what I mean.
So if I have the falling example:
def swap(array):
while True:
noChange = True
for i in range(len(array) - 1):
if array[i] > array[i + 1]:
array[i], array[i + 1] = array[i + 1], array[i]
noChange = False
if noChange:
return array
def baseline(array):
array = sorted(array)
return array
array = [20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0]
sortedArray = swap(array)
print array # Result: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
array = [20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0]
sortedArray = baseline(array)
print array # Result: [20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
From above, you can see that for some reason, array has been changed when the function called swap is run but when I run baseline. In the function called swap, I've tried re-naming all instances of array to localArray to see if it made a difference but I'm still having the same problem.
I'm sure this is something very obvious that I've over looked but would somebody be able to explain why this is happening?
When you pass the list array to a function, the argument reference to the same list object, if it's modified inside the function, the original list is modifed as well.
If this is not what you want, copy the list in the beginning of the function:
def swap(array):
array = array[:]
# ...
When you pass a list to a function, you are passing the reference to it, hence if you change the list inside the function it will also get changed, you can send a shallow copy of the list (as the list only contains integers) as the argument, so that it does not get changed.
When calling the function do -
import copy
sortedArray = swap(copy.copy(array))
Another way to do it would be to copy the array inside your function, Example -
import copy
def swap(array):
array = copy.copy(array)
When your list contains references to other mutable objects, you should use copy.deepcopy() function (If you will be making changes inside the objects, but you do not want the same changes to reflect to the objects in the original list).