Out of range issue within a loop - python

I try to make a script allowing to loop through a list (tmpList = openFiles(cop_node)). This list contains 5 other sublists of 206 components.
The last 200 components of the sublists are string numbers ( a line of 200 string numbers for each component separated with a space character).
I need to loop through the main list and create a new list of 5 components, each new component containing the 200*200 values in float.
My actual code is try to add a second loop to an older code working with the equivalent of one sublist. But python return an error "Index out of range"
def valuesFiles(cop_node):
tmpList = openFiles(cop_node)
valueList = []
valueListStr = []*len(tmpList)
for j in range (len(tmpList)):
tmpList = openFiles(cop_node)[j][6:]
tmpList.reverse()
for i in range (len(tmpList)):
splitList = tmpList[i].split(' ')
valueListStr[j].extend(splitList)
#valueList.append(float(valueListStr[j][i]))
return(valueList)

valueListStr = []*len(tmpList) does not do what you think it does, if you want a list of lists use a list comp with range:
valueListStr = [[] for _ in range(len(tmpList))]
That will create a list of lists:
In [9]: valueListStr = [] * i
In [10]: valueListStr
Out[10]: []
In [11]: valueListStr = [[] for _ in range(i)]
In [12]: valueListStr
Out[12]: [[], [], [], []]
So why you get an error is because of valueListStr[j].extend(splitList), you cannot index an empty list.
You don't actually seem to return the list anywhere so I presume you actually want to actually return it, you can also just create lists inside the loop as needed, you can also just loop over tmpList and openFiles(cop_node):
def valuesFiles(cop_node):
valueListStr = []
for j in openFiles(cop_node):
tmpList = j[6:]
tmpList.reverse()
tmp = []
for s in tmpList:
tmp.extend(s.split(' '))
valueListStr.append(tmp)
return valueListStr
Which using itertools.chain can become:
from itertools import chain
def values_files(cop_node):
return [list(chain(*(s.split(' ') for s in reversed(sub[6:]))))
for sub in openFiles(cop_node)]

def valuesFiles(cop_node):
valueListStr = []
for j in openFiles(cop_node):
tmpList = j[6:]
tmpList.reverse()
tmp = []
for s in tmpList:
tmp.extend(s.split(' '))
valueListStr.append(tmp)
return valueListStr
After little modification I get it to work as excepted :
def valuesFiles(cop_node):
valueList = []
for j in range (len(openFiles(cop_node))):
tmpList = openFiles(cop_node)[j][6:]
tmpList.reverse()
tmpStr =[]
for s in tmpList:
tmpStr.extend(s.split(' '))
tmp = []
for t in tmpStr:
tmp.append(float(t))
valueList.append(tmp)
return(valueList)
I don't understand why but the first loop statement didn't work. At the end the I had empty lists like so : [[],[],[],[],[]] . That's why I changed the beginning. Finally I converted the strings to floats.

Related

Dropping Empty Lists from Nested List

So I have a function which returns a List which contains either empty lists or Series. I loop through a list of tickers and for each it will return a empty list or Series and store them inside one list.
However, after looping through all I want to be able to drop the empty lists and only have the Series within the list.
def get_revenue_growth(ticker) -> pd.DataFrame:
income_statement_annually = fa.financial_statement_growth(ticker, FA_API_KEY, period="annual")
if 'revenueGrowth' in income_statement_annually.index:
revenue_growth = income_statement_annually.loc['revenueGrowth']
exchange_df = pd.DataFrame({ticker : revenue_growth})
exchange_df.index = pd.to_datetime(pd.Series(exchange_df.index))
exchange_df = exchange_df[exchange_df.index.year >= 1998]
exchange_df = exchange_df.sort_index()
print('Getting Revenue Growth for ' + ticker + ': Passed')
else:
print('Getting Revenue Growth for ' + ticker + ': Failed')
exchange_df = []
return exchange_df
This is the function I am calling via this:
revenue_growth = [get_revenue_growth(t) for t in tickers]
Here is what the output looks like...
So what I am trying to achieve is to remove all the empty lists. I tried this list2 = [x for x in list1 if x != []] but it did not work.
You can simply solve it via:
list2 = [x for x in list1 if len(x)>0]
Look at this Example -
mylist = []
if len(mylist) == 0:
del mylist # Deletes the Empty List
else:
# Do Something else
Modify this piece for your program

Iteration each elements of a list to split it based on a condition - Python

I have this list :
names = ['pipeline-1__YearBuilt',
'pipeline-1__NumberofBuildings',
'pipeline-1__NumberofFloors',
'pipeline-1__PropertyGFATotal',
'onehotencoder__x0_Low-Rise Multifamily',
'onehotencoder__x0_Medical Office',
'onehotencoder__x0_Mixed Use Property',
'onehotencoder__x0_Office',
'onehotencoder__x0_Other',
'onehotencoder__x0_Refrigerated Warehouse',
'onehotencoder__x5_Yes'
]
I would like to iterate through each elemens of my list to change it (to clean it for a better readability).
I guess I am close but it doesn't work when I try this :
for n in names:
new = []
if n.startswith('pipeline-1'):
n = n.split('__', 1)[-1]
else:
n = n.split('__x', 1)[-1]
new.append(n)
I only get :
new = ['5_Yes']
I want to keep only the last part of my string.
If anyone can help please. Thanks
[wrong code]
for n in names:
new = []
if n.startswith('pipeline-1'):
n = n.split('__', 1)[-1]
else:
n = n.split('__x', 1)[-1]
new.append(n)
in this way you create a new list called new n times, where n is the names length.
You must do something like this:
new = []
for n in names:
if n.startswith('pipeline-1'):
n = n.split('__', 1)[-1]
else:
n = n.split('__x', 1)[-1]
new.append(n)
I think this will help you:
new = []
for n in names:
if n.startswith('pipeline-1'):
n = n.split('__', 1)[-1]
else:
n = n.split('__x', 1)[-1]
new.append(n)
Your array new was overwritten on each loop therefore you see only the last element. Just put it in front of the loop.
new = []
for n in names:
if n.startswith('pipeline-1'):
n = n.split('__', 1)[-1]
else:
n = n.split('__x', 1)[-1]
new.append(n)
If new is inside your loop each iteration of the loop will reset new to []
The problem is that you are starting an empty array for every object in your names array, you should have new = [] outside the for loop

removing numbers which are close to each other in a list

I have a list like
mylist = [75,75,76,77,78,79,154,155,154,156,260,262,263,550,551,551,552]
i need to remove numbers are close to each other by maxumim four number like:
num-4 <= x <= num +4
the list i need at the end should be like :
list = [75,154,260,550]
or
list = [76,156,263,551]
doesn't really matter which number to stay in the list , only one of those which are close.
i tried this which gave me :
for i in range(len(l)):
for j in range(len(l)):
if i==j or i==j+1 or i==j+2 or i == j+3:
pp= l.pop(j)
print(pp)
print(l)
IndexError: pop index out of range
and this one which doesn't work the way i need:
for q in li:
for w in li:
print(q,'////',w)
if q == w or q ==w+1 or q==w+2 or q==w+3:
rem = li.remove(w)
thanks
The below uses groupby to identify runs from the iterable that start with a value start and contain values that differ from start by no more than 4. We then collect all of those start values into a list.
from itertools import groupby
def runs(difference=4):
start = None
def inner(n):
nonlocal start
if start is None:
start = n
elif abs(start-n) > difference:
start = n
return start
return inner
print([next(g) for k, g in groupby(mylist, runs())])
# [75, 154, 260, 550]
This assumes that the input data is already sorted. If it's not, you'll have to sort it: groupby(sorted(mylist), runs()).
You can accomplish this using a set or list, you don't need a dict.
usedValues = set()
newList = []
for v in myList:
if v not in usedValues:
newList.append(v)
for lv in range(v - 4, v + 5):
usedValues.add(lv)
print(newList)
This method stores all values within 4 of every value you've seen so far. When you look at a new value from myList, you only need to check if you've seen something in it's ballpark before by checking usedValues.

Convert integers inside a list into strings and then a date in python 3.x

i've just started studying python in college and i have a problem with this exercise:
basically i have to take a list of integers, like for example [10,2,2013,11,2,2014,5,23,2015], turn the necessary elements to form a date into a string, like ['1022013',1122014,5232015] and then put a / between the strings so i have this ['10/2/2013', '11/22/2014','05/23/2015']. It needs to be a function, and the length of the list is assumed to be a multiple of 3. How do i go about doing this?
I wrote this code to start:
def convert(lst):
...: for element in lst:
...: result = str(element)
...: return result
...:
but from a list [1,2,3] only returns me '1'.
To split your list into size 3 chunks you use a range with a step of 3
for i in range(0, len(l), 3):
print(l[i:i+3])
And joining the pieces with / is as simple as
'/'.join([str(x) for x in l[i:i+3]])
Throwing it all together into a function:
def make_times(l):
results = []
for i in range(0, len(l), 3):
results.append('/'.join([str(x) for x in l[i:i+3]]))
return results
testList = [10,2,2013,11,2,2014,5,23,2015]
def convert(inputList):
tempList = []
for i in range (0, len(inputList), 3): #Repeats every 3 elements
newDate = str(inputList[i])+"/"+str(inputList[i+1])+"/"+str(inputList[i+2]) #Joins everything together
tempList.append(newDate)
return tempList
print(convert(testList))
Saswata sux
Use datetime to extract the date and and strftime to format it:
from datetime import datetime
dates = [10,2,2013,11,2,2014,5,23,2015]
for i in range(0, len(dates), 3):
d = datetime(dates[i+2], dates[i], dates[i+1])
print(d.strftime("%m/%d/%y"))
OUTPUT
10/02/13
11/02/14
05/23/15
Something like this would work:
def convert(lst):
string = ''
new_lst = []
for x in lst:
if len(str(x)) < 4:
string += str(x)+'/'
else:
string += str(x)
new_lst.append(string)
string = ''
return(new_lst)
lst = [10,2,2013,11,2,2014,5,23,2015]
lst = convert(lst)
print(lst)
#output
['10/2/2013', '11/2/2014', '5/23/2015']
So create a placeholder string and a new list. Then loop through each element in your list. If the element is not a year, then add it to the string with a '/'. If it is a year, add the string to the new list and clear the string.

python random.shuffle() in a while loop

I have a list:
k = [1,2,3,4,5]
Now I want 3 permutations of this list to be listed in another list but when I do this:
x = []
i = 0
while i < 3:
random.shuffle(k)
x.append(k)
i += 1
I end up with 3 times the same permutation of k in x, like this:
x = [[1,3,5,2,4], [1,3,5,2,4], [1,3,5,2,4]]
In stead of what I would like, something like this:
x = [[1,5,4,2,3], [1,3,5,2,4], [5,3,4,1,2]]
Note that it is not possible due to the way the data in k is gathered to place k inside the loop, as for I know this would solve the problem. The real code is this:
def create_random_chromosomes(genes):
temp_chromosomes = []
chromosomes = []
i = 0
while i < 2000:
print(genes)
random.shuffle(genes)
temp_chromosomes.append(genes)
i += 1
print(temp_chromosomes)
for element in temp_chromosomes:
if element not in chromosomes:
chromosomes.append(element)
return chromosomes
Shuffling a list changes it in-place, and you are creating 3 references to the same list. Create a copy of the list before shuffling:
x = []
for i in range(3):
kcopy = k[:]
random.shuffle(kcopy)
x.append(kcopy)
I've simplified your loop as well; just use for i in range(3). Or, to place this in the context of your full method:
def create_random_chromosomes(genes):
temp_chromosomes = []
chromosomes = []
for i in range(2000):
print(genes)
randomgenes = genes[:]
random.shuffle(randomgenes)
temp_chromosomes.append(randomgenes)
print(temp_chromosomes)
for element in temp_chromosomes:
if element not in chromosomes:
chromosomes.append(element)
return chromosomes
You can further simplify the above by using a set to weed out dupes:
def create_random_chromosomes(genes):
chromosomes = set()
randomgenes = genes[:]
for i in range(2000):
random.shuffle(randomgenes)
chromosomes.add(tuple(randomgenes))
return list(chromosomes)
This uses a tuple copy of the random genes list to fit the hashable constraint of set contents.
You can then even ensure that you return 2000 unique items regardless:
def create_random_chromosomes(genes):
chromosomes = set()
randomgenes = genes[:]
while len(chromosomes) < 2000:
random.shuffle(randomgenes)
chromosomes.add(tuple(randomgenes))
return list(chromosomes)

Categories