how to select pieces of 2 lists using np.sign? - python

I have 2 separate lists which I would like to select some pieces of both. In the first variable set, I need to select based on its sign then when I could have zero crossing, I should select from both lists based on the indices coming from zero_crossing.
I could define the function to have zero_crossing indices but I do not know how to select from both lists using the indices.
def func_1(arr1):
for i, a in enumerate(arr1):
zero_crossings = np.where(np.diff(np.sign(arr1)))[0]
return zero_crossings
def func_2(arr1,arr2):
res_list1 = []
res_list2 = []
for i in (zero_crossings):
res_list1.append(arr1[i:i+1])
res_list2.append(arr2[i:i+1])
zero_crossing = [3,12,18]
list1 = [-12,-14,-16,-10,1,3,6,2,,1,5,5,3,-1,-12,-2,-3,-5,-3,3,2,5,2]
list2 = [0.00040409 0.00041026 0.0004162 ... 0.00116538 0.001096 0.00102431]
The expected results:
new_list_1 = [list1[0:3]+list1[3:12]+list1[12:18]]
new_list_1 = [list2[0:3]+list2[3:12]+list2[12:18]]
for i in range(len(zero_crossing)):
list_{%d} = []
list_i = list1[zero_crossing[i]:zero_crossing[i+1]]
I want to use list1 to see where we have a change in sign then through the list of indices of sign changing, try to select the values of both lists.
All efforts will be appreciated.

Related

Create words by combining all elements in a set of lists with each other

I have 6 different lists, which I need to combine and create sequences/words for all possible combinations.
These are my lists:
product = ['SOC', 'SOCCAMP', 'ETI', 'CARDASS', 'VRS', 'PRS', 'INT', 'GRS', 'VeloVe', 'HOME']
fam = ['IND', 'FAM']
area = ['EUR', 'WOR']
type = ['STD', 'PLU']
assist = ['MOT', 'NMOT']
All of the elements in all of the lists need to be combined in words.
The result will be a list of all the elements possible.
I will have among all of the elements f.e. the following words:
('SOC', 'SOCIND', 'SOCFAM', 'SOCFAMMOT', 'SOCMOTFAM'...)
I thus combine each element of a precise list with all the elements of the other lists.
Up to now I managed to combine them with a series of loops:
combos = []
##1##
for i in range(len(product)):
combos.append(str(product[i]))
##2##
for a in range(len(product)):
for b in range(len(fam)):
combos.append(str(product[a]) + str(fam[b]))
##3##
for a in range(len(product)):
for b in range(len(fam)):
for c in range(len(area)):
combos.append(str(product[a]) + str(fam[b]) + str(area[c]))
##4##
for a in range(len(product)):
for b in range(len(fam)):
for c in range(len(area)):
for d in range(len(type)):
combos.append(str(product[a]) + str(fam[b]) + str(area[c]) + str(type[d]))
##5##
for a in range(len(product)):
for b in range(len(fam)):
for c in range(len(area)):
for d in range(len(type)):
for e in range(len(assist)):
combos.append(str(product[a]) + str(fam[b]) + str(area[c]) + str(type[d]) + str(assist[e]))
This code manages to combine the words in a list of combinations but solely in the precise order the lists are mentioned:
['SOC', 'SOCCAMP', 'ETI', 'CARDASS', 'VRS', 'PRS', 'INT', 'GRS', 'VeloVe', 'HOME', 'SOCIND', 'SOCFAM', 'SOCCAMPIND', 'SOCCAMPFAM', 'ETIIND', 'ETIFAM', 'CARDASSIND', 'CARDASSFAM', 'VRSIND', 'VRSFAM', 'PRSIND', 'PRSFAM', 'INTIND', 'INTFAM', 'GRSIND', 'GRSFAM', 'VeloVeIND', 'VeloVeFAM', 'HOMEIND', 'HOMEFAM', ...]
So, 'SOCINDEUR' is a combination in this list but 'SOCEURIND' is not.
Is there a smart way to avoid writing down another 100 loops to look for all the possible combinations?
You can make use of various tools provided by itertools.
Overall, one solution is:
source_lists = product, fam, area, type, assist
combos = [
''.join(prod)
for l in range(1, len(source_lists))
for subset in itertools.permutations(source_lists, l)
for prod in itertools.product(*subset)
]
This code is effectively equivalent of:
combos = []
source_lists = product, fam, area, type, assist
for l in range(1, len(source_lists)):
for subset in itertools.permutations(source_lists, l):
for prod in itertools.product(*subset):
combos.append(''.join(prod))
The first loop selects how many different source lists you want to select, so it will first produce the results from single list, i.e. the "original" input. Then it moves to combining two etc.
The second loop select which source lists and in which order we will combine (and goes over all possible permutations).
Finally the third and last loop takes the selected source list and produces all the possible combinations (or, better said "product") of these lists.
Finally this produces the tuples of results, since you want one single string per result, we need to join them.
The magic of itertools!
from itertools import product, permutations
def concat_combinations(sequence):
new_seq = []
for i,j in enumerate(sequence):
if i == 0:
new_str = j
new_seq.append(new_str)
else:
new_str += j
new_seq.append(new_str)
return new_seq
def final_list(*iterables)->list:
s = set()
for seq in list(product(*iterables)):
[s.update(concat_combinations(i)) for i in permutations(seq)]
return sorted(s,key=lambda x: len(x))

Sum total by two conditions in list of lists

cust_id = semi_final_df['0_x'].tolist()
date = semi_final_df[1].tolist()
total_amount = semi_final_df[0].tolist()
prod_num = semi_final_df['0_y'].tolist()
prod_deduped = []
quant_cleaned = []
product_net_amount = []
cust_id_final = []
date_final = []
for row in total_amount:
quant_cleaned.append(float(row))
for unique_prodz in prod_num:
if unique_prodz not in prod_deduped:
prod_deduped.append(unique_prodz)
for unique_product in prod_deduped:
indices = [i for i, x in enumerate(prod_num) if x == unique_product]
product_total = 0
for index in indices:
product_total += quant_cleaned[index]
product_net_amount.append(product_total)
first_index = prod_num.index(unique_product)
cust_id_final.append(cust_id[first_index])
date_final.append(date[first_index])
Above code calculates sum amount by one condition in order to sum the total on an invoice.
The data had multiple lines but shared the same invoice/product number.
Problem:
I need to modify the below code so that I can sum by unique product and unique date.
I have given it a go but I am getting a value error -
saying x, y is not in a list
As per my understanding the issue lies in the fact that I am zipping two de-duped lists together of different lengths and then I am attempting to loop through the result inline.
This line causes the error
for i,[x, y] in enumerate(zipped_list):
Any help would be sincerely appreciated. Here is the second batch of code with comments.
from itertools import zip_longest
#I have not included the code for the three lists below but you can assume they are populated as these are the lists that I will be #working off of. They are of the same length.
prod_numbers = []
datesz = []
converted_quant = []
#Code to dedupe date and product which will end up being different lengths. These two lists are populated by the two for loops below
prod_deduped = []
dates_deduped = []
for unique_prodz in prod_numbers:
if unique_prodz not in prod_deduped:
prod_deduped.append(unique_prodz)
for unique_date in datesz:
if unique_date not in dates_deduped:
dates_deduped.append(unique_date)
#Now for the fun part. Time to sum by date and product. The three lists below are empty until we run the code
converted_net_amount = []
prod_id_final = []
date_final = []
#I zipped the list together using itertools which I imported at the top
for unique_product, unique_date in zip_longest(prod_deduped, dates_deduped, fillvalue = ''):
indices = []
zipped_object = zip(prod_numbers, datesz)
zipped_list = list(zipped_object)
for i,[x, y] in enumerate(zipped_list):
if x == unique_product and y == unique_date:
indices.append(i)
converted_total = 0
for index in indices:
converted_total += converted_quant[index]
converted_net_amount.append[converted_total]
first_index = zipped_list.index([unique_product, unique_date])
prod_id_final.append(prod_numbers[first_index])
date_final.append(datesz[first_index])
from collections import defaultdict
summed_dictionary = defaultdict(int)
for x, y, z in list:
summed_dictionary[(x,y)] += z
Using defaultdict should solve your problem and is a lot easier on the eyes than all your code above. I saw this on reddit this morning and figured you crossposted. Credit to the guy from reddit on /r/learnpython

Creating a new list from the means of a list of a function

I've defined a function called CalcspeedAngle
def CalcspeedAngle(k):
xpos = [1,2,3,4,5,6,7,8,9]
ypos = [10,11,12,13,14,15,16,17,18]
turnrates = [entry/3.099 for entry in xpos][::k]
vts = [entry/3.099 for entry in ypos][::k]
return(turnrates,vts)
then I write
turnrates, vts = CalcspeedAngle(k)
My question is: How can I create two new lists (m1list and m2list) that contain the averages of the turnrates and vts with k = 1,2,3,4,5,6,7,8,9,10,15,20? In other words, how can I create:
m1list = [mean(flattened(turnrates(k=1))), mean(flattened(turnrates(k=2))), ...]
m2list = [mean(flattened(vts(k=1))), mean(vts(turnrates(k=2))), ...]
Any help would be greatly appreciated.
One way to simplify your code is to perform one iteration over range(10), unpack your 2 lists of lists, calculate the mean for each, and append them to your result lists:
def lists_of_means():
m1list = []
m2list = []
for i in range(10):
turnrates, vts = CalcspeedAngle(i)
m1list.append(np.mean(turnrates))
m2list.append(np.mean(vts))
return m1list, m2list

Python list, take even elements and odd elements to their own respective new lists

I am working on a problem wherein I paste a set of numbers, and I want to put the even and odd list elements from these numbers and put them in their own list, then add them together for a 3rd list.
Here is my code:
#list of numbers
start = """
601393 168477
949122 272353
944397 564134
406351 745395
281988 610822
451328 644000
198510 606886
797923 388924
470601 938098
578263 113262
796982 62212
504090 378833
"""
x = start.split()
#turn string into list elements then append to a list
step_two = []
step_two.append(x)
print step_two
# doublecheck that step_two is a list with all the numbers
step_three = step_two[1::2]
#form new list that consists of all the odd elements
print step_three
#form new list that consists of all the even elements
step_four = step_two[0::2]
print step_four
#add ascending even/odd element pairs together and append to new list
final_step = [x + y for x, y in zip(step_three, step_four)]
print final_step
This code yields these results:
"""
"Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
[['601393', '168477', '949122', '272353', '944397', '564134', '406351', '745395'
, '281988', '610822', '451328', '644000', '198510', '606886', '797923', '388924'
, '470601', '938098', '578263', '113262', '796982', '62212', '504090', '378833']
]
[]
[['601393', '168477', '949122', '272353', '944397', '564134', '406351', '745395'
, '281988', '610822', '451328', '644000', '198510', '606886', '797923', '388924'
, '470601', '938098', '578263', '113262', '796982', '62212', '504090', '378833']
]
[]
"""
Why is my list in step_three and step_four not working? I am not sure why my [::] functions aren't registering.
Thanks in advance for any advice.
You were too explicit here in step two:
x = start.split()
#turn string into list elements then append to a list
step_two = []
step_two.append(x)
x is already the list you need. step_two creates a new list and adds the previous list to it, so instead of ['601393', '168477',...], you have [['601393', '168477',...]].
To fix this, simply call the split string step_two and proceed from there:
step_two = start.split()
The reason your lists don't split the numbers into odd and even is that your code assumes that the list alternates between them - you take every other index for each list generation, but the numbers aren't arranged that way in the original string.
You'll need to do an 'evenness' test:
step_two = start.split()
step_three = []
step_four = []
for item in step_two:
if int(item) % 2: # If it divides evenly by two, it returns 0, or False
step_three.append(item)
else:
step_four.append(item)
The lists step_three and step_four will now correctly contain only odds or evens.
Here is how I would generate the odd list, hope it helps!
import sys
# Provided main(), calls mimic_dict() and mimic()
def main():
#list of numbers
start = '601393 168477 949122 272353 944397 564134 406351 745395 281988 610822 451328 644000 198510 606886 797923 388924470601 938098 578263 113262 796982 62212 504090 378833'
x = start.split()
#turn string into list elements then append to a list
step_two = []
# gives you 23 items in your list "step_two" instead of 1 item with original append on it's own
for s in x:
step_two.append(s)
#print (step_two)
# print (step_two)
# doublecheck that step_two is a list with all the numbers
i = 1
step_three_odd_list = []
while i < len(step_two):
currentodditem = step_two[i]
step_three_odd_list.append(currentodditem)
i = i + 2
#form new list that consists of all the odd elements
print (step_three_odd_list)
if __name__ == '__main__':
main()
The [::] that you have going on are extended slices, not tests for even and odd:
https://docs.python.org/release/2.3.5/whatsnew/section-slices.html
Also, since those numbers are in a string, when you split them you end up with strings, not integers that you test with math. So, you need to convert them to integers.
This post clued me in on a quick even/odd test: Check if a number is odd or even in python
This code seems to do what you want, if I understand it correctly:
start = """
601393 168477
949122 272353
944397 564134
406351 745395
281988 610822
451328 644000
198510 606886
797923 388924
470601 938098
578263 113262
796982 62212
504090 378833
"""
# List comprehension to generate a list of the numbers converted to integers
step_two = [int(x) for x in start.split()]
# Sort the list
step_two.sort()
# Create new lists for even and odd
even_numbers = []
odd_numbers = []
# For each item in the list, test for even or odd and add to the right list
for number in step_two:
if (number % 2 == 0):
#even
even_numbers.append(number)
else:
#odd
odd_numbers.append(number)
print(even_numbers)
print(odd_numbers)
final_step = [x + y for x, y in zip(even_numbers, odd_numbers)]
print(final_step)
You can use list comprehensions to create two lists odd and even :
import itertools
start = """
601393 168477
949122 272353
944397 564134
406351 745395
281988 610822
451328 644000
198510 606886
797923 388924
470601 938098
578263 113262
796982 62212
504090 378833
"""
lst = start.split()
even = [int(i) for i in lst if int(i) % 2 == 0]
odd = [int(i) for i in lst if int(i) % 2 != 0]
Then you can zip these 2 lists but as even and odd are not the same length, you have to use itertools.zip_longest() in Python 3 and itertools.izip_longest() in Python 2. You will then have a list of tuples:
final_step = [i for i in itertools.zip_longest(even,odd)]
[(949122, 601393),
(564134, 168477),
(281988, 272353),
(610822, 944397),
(451328, 406351),
(644000, 745395),
(198510, 797923),
(606886, 470601),
(388924, 578263),
(938098, 378833),
(113262, None),
(796982, None),
(62212, None),
(504090, None)]
You can create the third list result to sum() the values using an other list comprehension but you have to make sure not to try to sum the tuples where one value is None.
result = [sum(e) if e[1] is not None else e[0] for e in final_step]
The final output:
[1550515,
732611,
554341,
1555219,
857679,
1389395,
996433,
1077487,
967187,
1316931,
113262,
796982,
62212,
504090]

Filtering a list of images by using a filter and association lists

I've got an assignment and part of it asks to define a process_filter_description. Basically I have a list of images I want to filter:
images = ["1111.jpg", "2222.jpg", "circle.JPG", "square.jpg", "triangle.JPG"]
Now I have an association list that I can use to filter the images:
assc_list = [ ["numbers", ["1111.jpg", "2222.jpg"]] , ["shapes", ["circle.JPG", "square.jpg", "triangle.JPG"]] ]
I can use a filter description to select which association list I want to apply the filter the keyword is enclosed by colons):
f = ':numbers:'
I'm not exactly sure how to start it. In words I can at least think:
Filter is ':numbers:'
Compare each term of images to each term associated with numbers in the association list.
If term matches, then append term to empty list.
Right now I am just trying to get my code to print only the terms from the numbers association list, but it prints out all of them.
def process_filter_description(f, images, ia):
return_list = []
f = f[1:-1]
counter = 0
if f == ia[counter][0]:
#print f + ' is equal to ' + ia[counter][0]
for key in ial:
for item in key[1]:
#print item
#return_list.append(item)
return return_list
Instead of an "associative list", how about using a dictionary?
filter_assoc = {'numbers': ['1111.jpg', '2222.jpg'] ,
'shapes': ['circle.JPG', 'square.jpg', 'triangle.JPG']}
Now, just see which images are in each group:
>>> filter_assoc['numbers']
['1111.jpg', '2222.jpg']
>>>
>>> filter_assoc['shapes']
['circle.JPG', 'square.jpg', 'triangle.JPG']
Your processing function would become immensely simpler:
def process_filter_description(filter, association):
return association[filter[1:-1]]
I'll just think aloud here, so this is what I'd use as a function to perform the task of the dictionary:
def process_filter_description(index, images, association):
return_list = []
index = index[1:-1]
for top_level in association:
if top_level[0] == index:
for item in top_level[1]:
return_list.append(item)
break
return return_list

Categories

Resources