Dropping Empty Lists from Nested List - python

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

Related

Python list data filtering

I have a list that holds names of files, some of which are almost identical except for their timestamp string section. The list is in the format of [name-subname-timestamp] for example:
myList = ['name1-001-20211202811.txt', 'name1-001-202112021010.txt', 'name1-002-202112021010.txt', 'name2-002-202112020811.txt']
What I need is a list that holds for every name and subname, the most recent file derived by the timestamp. I have started by creating a list that holds every [name-subname]:
name_subname_list = []
for row in myList:
name_subname_list.append((row.rpartition('-')[0]))
name_subname_list = set(name_subname_list) # {'name1-001', 'name2-002', 'name1-002'}
Not sure if it is the right approach, moreover I am not sure how to continue. Any ideas?
This code is what you asked for:
For each name-subname, you will have the corresponding newest file:
from datetime import datetime as dt
dic = {}
for i in myList:
sp = i.split('-')
name_subname = sp[0]+'-'+sp[1]
mytime = sp[2].split('.')[0]
if name_subname not in dic:
dic[name_subname] = mytime
else:
if dt.strptime(mytime, "%Y%m%d%H%M") > dt.strptime(dic[name_subname], "%Y%m%d%H%M"):
dic[name_subname] = mytime
result = []
for name_subname in dic:
result.append(name_subname+'-'+dic[name_subname]+'.txt')
which out puts resutl to be like:
['name1-001-202112021010.txt',
'name1-002-202112021010.txt',
'name2-002-202112020811.txt']
Try this:
myList = ['name1-001-20211202811.txt', 'name1-001-202112021010.txt', 'name1-002-202112021010.txt', 'name2-002-202112020811.txt']
dic = {}
for name in myList:
parts = name.split('-')
dic.setdefault(parts[0] + '-' + parts[1], []).append(parts[2])
unique_list = []
for key,value in dic.items():
unique_list.append(key + '-' + max(value))

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

Python filtering out a list using elements from another list

I am trying to filter out a list using another list. However, the elements of the list I am using to filter the other list is not identical strings. Please see my example as it will make more sense:
mylist = ['14001IB_L1P0', '14001OB_L1P1', '14002IB_L3P0', '14003OB_L1P1', '14001OB_L2P0']
remove_list = ['14001', '14002']
I want to remove the values from mylist that start with the values from remove_list.
I have tried doing this:
filtered_mylist = mylist[:]
for x in remove_list:
for i in filtered_mylist:
if x in i:
print('remove ' +i)
filtered_mylist.remove(i)
else:
print('keep '+i)
However, this is the result:
remove 14001IB_L1P0
keep 14002IB_L3P0
keep 14003OB_L1P1
remove 14001OB_L2P0
keep 14001OB_L1P1
remove 14002IB_L3P0
and this is what filtered_mylist consists of:
['14001OB_L1P1', '14003OB_L1P1']
However, it should consist of only 1 element:
['14003OB_L1P1']
It seems to me that for some reason, the loop has skipped over '14001OB_L1P1', the second element in the first loop. Why has this happened?
Here's a one liner
mylist = list(filter(lambda x: all([x.find(y) != 0 for y in remove_list]), mylist))
#Output
['14003OB_L1P1']
The all([x.find(y) != 0 for y in remove_list]) will return True if and only if x does not start with a single value from remove_list.
all() means all have to be True. x.find(y) != 0 means x does not begin with y.
The rest is just executing the filter.
Would this help?
remove_final = []
keep_final = []
for element in mylist:
if any([element.startswith(x) for x in remove_list]):
print(f'remove {element}')
remove_final.append(element)
else:
print(f'keep {element}')
keep_final.append(element)
Output:
remove 14001IB_L1P0
remove 14001OB_L1P1
remove 14002IB_L3P0
keep 14003OB_L1P1
remove 14001OB_L2P0
And final lists:
keep_final
['14003OB_L1P1']
remove_final
['14001IB_L1P0', '14001OB_L1P1', '14002IB_L3P0', '14001OB_L2P0']
Hope this code help you.
mylist = ['14001IB_L1P0', '14001OB_L1P1', '14002IB_L3P0', '14003OB_L1P1', '14001OB_L2P0']
remove_list = ['14001', '14002']
filtered_mylist = mylist[:]
for x in remove_list:
i = 0
while i < len(filtered_mylist):
if x in filtered_mylist[i]:
print('remove ' + filtered_mylist[i])
filtered_mylist.remove(filtered_mylist[i])
else:
print('keep '+ filtered_mylist[i])
i+=1
Here's another method - append method.
Try to use "filter function + append" to do this instead of remove. That's much safer.
mylist = ['14001IB_L1P0', '14001OB_L1P1', '14002IB_L3P0', '14003OB_L1P1', '14001OB_L2P0']
remove_list = ['14001', '14002']
def is_valid(item):
for pattern in remove_list:
if item.startswith(pattern):
return False
return True
res = []
for item in mylist:
if is_valid(item):
res.append(item)
print(res)

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.

Out of range issue within a loop

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.

Categories