nested loop in python with lists input - python

I want to have an array of signals which calculated from a function, by loop through different parameter combination, something like below:
fast_w = list(range(20, 100, 20))
slow_w = list(range(100, 200, 20))
tradeSignal = np.zeros((len(fast_w), len(slow_w)))
for i in fast_w:
for j in slow_w:
tradeSignal[i][j] = signalTrade(i, j, stock_price, end_date)
however "tradeSignal[i][j]" is incorrect as i and j would be the values in the fast_w and slow_w list, which here it suppose to be the index of array tradeSignal
So what is the right way to write such code?
new to python and its package ....thanks for help

How about this? I'm not certain that it works, since we're missing part of your code, but it should.
trade_signal = np.fromfunction(lambda i, j: signalTrade(i, j, stock_price, end_date), shape=(4, 5))
When working with numpy, you should avoid explicit loops and iteration unless absolutely necessary.

You can always use builtin function enumerate().
enumerate(iterable) will let you iterate getting tuples (index, value_from_iterable).
For example:
for idx, x in enumerate(range(5, 8)):
print(idx, x)
This code will produce the nex result:
0 5
1 6
2 7
Hence, your code will look like this:
fast_w = list(range(20, 100, 20))
slow_w = list(range(100, 200, 20))
tradeSignal = np.zeros((len(fast_w), len(slow_w)))
for i, fast_val in enumerate(fast_w):
for j, slow_val in enumerate(slow_w):
tradeSignal[i][j] = signalTrade(fast_val, slow_val, stock_price, end_date)
You can find more information here.

Related

Split a list of arrays and save each array in a new variable

I have the following function that resamples 100 times a file of ~800 elements:
def resample(arg_array):
all_sets = []
i = 1
while i <= 100:
subset = np.random.choice(arg_array, 100, replace=True)
all_sets.append(subset)
i += 1
return all_sets
This produces a list of arrays with 100 elements each, stored in all_sets.
I need to split this list and save each array into a new variable. Thought about doing list comprehension, but doing set1, set2, ..., set100 = [list comprehension] just doesn't seem very efficient or elegant at all.
Would be great if Python had something like bash where you can generate a new variable name for each pass in a loop.
How about like this?
def resample(arg_array):
for i in range(1, 101):
subset = np.random.choice(arg_array, 100, replace=True)
globals()[f"set{i}"] = subset
Instead of creating a variable for each set you could store them in a dictionary like this.
def resample(arg_array):
sample_map = {}
for n in range(1, 100+1):
subset = np.random.choice(arg_array, 100, replace=True)
sample_map[n] = subset
return sample_map
Or even this
def resample(arg_array):
sample_map = {n:np.random.choice(arg_array, 100, replace=True) for n in range(1, 100+1)}
return sample_map

Array organizing in Python

I have python code below:
ht_24 = []
ht_23 = []
ht_22 = []
...
all_arr = [ht_24, ht_23, ht_22, ht_21, ht_20, ht_19, ht_18, ht_17, ht_16, ht_15, ht_14, ht_13, ht_12, ht_11, ht_10, ht_09, ht_08, ht_07, ht_06, ht_05, ht_04, ht_03, ht_02, ht_01]
i = 0
j = 0
while i < 24:
while j < 24864:
all_arr[i].append(read_matrix[j+i])
j += 24
print(j)
i += 1
print(i)
where read_matrix is an array of shape 24864, 17.
I want to read every 24th line from different starting indexs (0-24) and append them to the corresponding arrays for each line. Please help, this is so hard!
Two things to learn in Python:
ONE: for loops -- when you know ahead of time how many times you're going through the loop. Your while loops above are both this type. Try these instead:
for i in range(24):
for j in range(0, 24864, 24):
all_arr[i].append(read_matrix[j+i])
print(j)
print(i)
It's better when you let the language handle the index values for you.
TWO: List comprehensions: sort of a for loop inside a list construction. Your entire posted code can turn into a single statement:
all_arr = [[read_matrix[j+i] \
for j in range(0, 24864, 24) ] \
for i in range(24) ]
Your question is a little unclear, but I think
list(zip(*zip(*[iter(read_matrix)]*24)))
may be what you're looking for.
list(zip(*zip(*[iter(range(24864))]*24)))[0][:5]
The above just looks at the indices, and the first few elements of the first sublist are
(0, 24, 48, 72, 96)
Can numpy library do what you want?
import numpy as np
# 24864 row, 17 columns
read_matrix = np.arange(24864*17).reshape(24864,17)
new_matrices = [[] for i in range(24)]
for i in range(24):
# a has 17 columns
a = read_matrix[slice(i,None,24)]
new_matrices[i].append(a)

Quicksort in python3. Last Pivot

Thanks for taking the time to read this :) I'm implementing my own version of quick-sort in python and i'm trying to get it too work within some restrictions from a previous school assignment. Note that the reasons I've avoided using IN is because it wasn't allowed in the project i worked on (not sure why :3).
it was working fine for integers and strings but i cannot manage to adapt it for my CounterList() which is a list of nodes containing an arbitrary integer and string in each even though i'm only sorting by the integers contained in those nodes.
Pastebins:
My QuickSort: http://pastebin.com/mhAm3YYp.
The CounterList and CounterNode, code. http://pastebin.com/myn5xuv6.
from classes_1 import CounterNode, CounterList
def bulk_append(array1, array2):
# takes all the items in array2 and appends them to array1
itr = 0
array = array1
while itr < len(array2):
array.append(array2[itr])
itr += 1
return array
def quickSort(array):
lss = CounterList()
eql = CounterList()
mre = CounterList()
if len(array) <= 1:
return array # Base case.
else:
pivot = array[len(array)-1].count # Pivoting on the last item.
itr = 0
while itr < len(array)-1:
# Essentially editing "for i in array:" to handle CounterLists
if array[itr].count < pivot:
lss.append(array[itr])
elif array[itr].count > pivot:
mre.append(array[itr])
else:
eql.append(array[itr])
itr += 1
# Recursive step and combining seperate lists.
lss = quickSort(lss)
eql = quickSort(eql)
mre = quickSort(mre)
fnl = bulk_append(lss, eql)
fnl = bulk_append(fnl, mre)
return fnl
I know it is probably quite straightforward but i just can't seem to see the issue.
(Pivoting on last item)
Here is the test im using:
a = CounterList()
a.append(CounterNode("ack", 11))
a.append(CounterNode("Boo", 12))
a.append(CounterNode("Cah", 9))
a.append(CounterNode("Doh", 7))
a.append(CounterNode("Eek", 5))
a.append(CounterNode("Fuu", 3))
a.append(CounterNode("qck", 1))
a.append(CounterNode("roo", 2))
a.append(CounterNode("sah", 4))
a.append(CounterNode("toh", 6))
a.append(CounterNode("yek", 8))
a.append(CounterNode("vuu", 10))
x = quickSort(a)
print("\nFinal List: \n", x)
And the resulting CounterList:
['qck': 1, 'Fuu': 3, 'Eek': 5, 'Doh': 7, 'Cah': 9, 'ack': 11]
Which as you can tell, is missing multiple values?
Either way thanks for any advice, and your time.
There are two mistakes in the code:
You don't need "eql = quickSort(eql)" line because it contains all equal values, so no need to sort.
In every recursive call you loose pivot (reason for missing entries) as you don't append it to any list. You need to append it to eql. So after the code line shown below:
pivot = array[len(array)-1].count
insert this line:
eql.append(array[len(array)-1])
Also remove the below line from your code as it may cause recursion depth sometimes (only with arrays with some repeating values if any repeated value selected as pivot):
eql = quickSort(eql)

Randomly iterating through a 2D list in Python

My first attempt to accomplish this resulted in:
def rand_Random(self):
randomRangeI = range(self.gridWidth)
shuffle(randomRangeI)
randomRangeJ = range(self.gridHeight)
shuffle(randomRangeJ)
for i in randomRangeI:
for j in randomRangeJ:
if self.grid[i][j] != 'b':
print i, j
self.grid[i][j].colour = self.rand_Land_Picker()
Which has the issue of going through one inner list at a time:
[1][1..X]
[2][1..X]
What I'd like to be able to do is iterate through the 2d array entirely at random (with no repeats).
Anyone have any solutions to this problem?
Edit: Thanks for the replies, it appears the way I view 2d arrays in my mind is different to most!
Create an array with all possible pairs of coordinates, shuffle this and iterate through as normal.
import random
coords = [(x,y) for x in range(self.gridWidth) for y in range(self.gridHeight)
random.shuffle(coords)
for i,j in coords:
if self.grid[i][j] != 'b':
print i, j
self.grid[i][j].colour = self.rand_Land_Picker()
You can consider 2D array as 1D array and randomly iterate through it.
def rand_Random(self):
randomRange = range(self.gridWidth*self.gridHeight)
shuffle(randomRange)
for index in randomRange:
i = index / self.gridWidth
j = index % self.gridWidth
if self.grid[i][j] != 'b':
print i, j
self.grid[i][j].colour = self.rand_Land_Picker()
You can do something like:
randomRange = range(w*h)
shuffle(randomRange)
for n in randomRange:
i = n/w
j = n%w
Here randomRange basically enumerates all the coordinates from 0 to w*h-1.
Even prettier, i and j, can be found in one statement:
i,j = divmod(n, w)

Get indices for all elements in an array in numpy

I'm trying to get a list of the indices for all the elements in an array so for an array of 1000 x 1000 I end up with [(0,0), (0,1),...,(999,999)].
I made a function to do this which is below:
def indices(alist):
results = []
ele = alist.size
counterx = 0
countery = 0
x = alist.shape[0]
y = alist.shape[1]
while counterx < x:
while countery < y:
results.append((counterx,countery))
countery += 1
counterx += 1
countery = 0
return results
After I timed it, it seemed quite slow as it was taking about 650 ms to run (granted on a slow laptop). So, figuring that numpy must have a way to do this faster than my mediocre coding, I took a look at the documentation and tried:
indices = [k for k in numpy.ndindex(q.shape)]
which took about 4.5 SECONDS (wtf?)
indices = [x for x,i in numpy.ndenumerate(q)]
better, but 1.5 seconds!
Is there a faster way to do this?
Thanks
how about np.ndindex?
np.ndindex(1000,1000)
This returns an iterable object:
>>> ix = numpy.ndindex(1000,1000)
>>> next(ix)
(0, 0)
>>> next(ix)
(0, 1)
>>> next(ix)
(0, 2)
In general, if you have an array, you can build the index iterable via:
index_iterable = np.ndindex(*arr.shape)
Of course, there's always np.ndenumerate as well which could be implemented like this:
def ndenumerate(arr):
for ix in np.ndindex(*arr.shape):
yield ix,arr[ix]
Have you thought of using itertools? It will generate an iterator for your results, and will almost certainly be optimally fast:
import itertools
a = range(1000)
b = range(1000)
product = itertools.product(a, b)
for x in product:
print x
# (0, 0)
# (0, 1)
# ...
# (999, 999)
Notice this didn't require the dependency on numpy. Also, notice the fun use of range to create a list from 0 to 999.
Ahha!
Using numpy to build an array of all combinations of two arrays
Runs in 41 ms as opposed to the 330ms using the itertool.product one!

Categories