Apologies in advance as I am quite new to this all and I'm not certain on the correct terms for everything.
I have a list of differences between two lists, called Change. I would like to generate a list of percentage changes Percentage by dividing each value in Change by the highest of the respective values in the lists it references (Before and After). If the wrong value is used, a percentage change is showing at -660% in some cases.
Before and After are generated from image files through PIL, but a small section of the output is below.
Before = [135,160,199,]
After = [146,174,176,]
Change = list(After-Before for Before,After in zip(Before,After))
PercentageA = list(Change/After*100 for After,Change in zip(After,Change))
PercentageB = list(Change/Before*100 for Before,Change in zip(Before,Change))
for x in Change:
if x <0:
Percentage = PercentageA
else:
Percentage = PercentageB
print(Percentage)
This code generates:
In [1]:
[8.148148148148149, 8.75, -11.557788944723619]
[8.148148148148149, 8.75, -11.557788944723619]
[7.534246575342466, 8.045977011494253, -13.068181818181818]
However, the result should be:
[7.534246575342466, 8.045977011494253, -11.557788944723619]
My main question is; how can I generate a Percentage list from Change divided by the highest of Before and After for each value in the list?
Edit: Reduced and generalised some of the code, and deleted background. Apologies for putting too much background in.
Edit2: Apologies for misunderstanding what was asked of me.
You are calculating something wrong - this works:
# list must be same lenght for zip() to work
before = [135, 199]
after = [146, 176]
change = [ 11, -23]
print(f"{'before':<10} {'after':<10} {'percent':<10} {'change':<10}")
for b,a,c in zip(before, after, change):
print (f'{b:<10} {a:<10} {c/max(b,a)*100:<10.6} {c:<10}')
Output:
before after percent change
135 146 7.53425 11
199 176 -11.5578 -23
Zipping 3 lists creates tuples from each list that this code iterates over. See f.e. The zip() function in Python 3
Related
This question already has answers here:
Understanding change-making algorithm
(4 answers)
Closed 3 years ago.
In england we have 1, 2, 5, 10, 20, 50 and a pound(100) p coins. Using these coins i would like to work out all the possible combinations that the coins can be added in to make £2.50. The way i approached this question was to make a list of all the possible combinations of all of the coins. To do this i did the following:
ps = [1, 2, 5, 10, 20, 50, 100]
list_of_combos = [[]]
for i in range(7):
for j in range(7):
for k in range(7):
for l in range(7):
for m in range(7):
for n in range(7):
for o in range(7):
print("processing..")
all_combos = (ps[i], ps[j], ps[k], ps[l], ps[m], ps[n], ps[o])
list_of_combos.append(all_combos)
Then from all the possible combos, i tried picking the only ones that actually add up to 250 by doing this.
for i in list_of_combos:
if sum(i) == 250:
print(i)
The problem i am having it that the first nested loop takes forever to complete, which basically makes the program useless. Is there anything i can do to make this loop finish quicker? Thanks.
I can give you an idea that might help. One idea to replace the loop, which I am not honestly sure how more/less efficient could be, but I expect to be better than the above is adapted from this:
How to get all possible combinations of a list’s elements?
Using the same function as the top answer:
list(itertools.combinations(iterable, r))
However, Keep in mind since you want to create a list of combinations of having more than one coin you might want to create a new list with repeated items.
HOWEVER this is a very very inefficient approach, One that will not get you a result due to the fact that you are limiting your combinations, as per this system you cannot ever have the answer be 250 1c coins for example
A better approach is to go the other way around, Starting from the biggest coins you can work from:
100 - 100 - 50
and go down, Dividing each coin in each different way, The advantage is that every operation you will do will be used to create a wanted result. So you are not wasting any loops (which in this approach is a lot) and you will not need to do any further checks to make sure its equal to the wanted results (e.g. 100 100 50 is a result, dividing you have for example 50 50 50 50 50 which is ALSO a result).
You might want to keep the checks to a limit of maybe 2-3 coin sizes down to improve performance and just loop each result and keep diving further to get every possible outcome
I'm working on a problem from this website:
https://www.practicepython.org/exercise/2014/03/05/05-list-overlap.html
The exercise I'm working on asks us to generate two random integer lists of different lengths. Here is what I've got:
import random
n1 = random.sample(range(1,30), random.randint(5,20))
n2 = random.sample(range(1,40), random.randint(21,40))
n3 = set(n1) & set(n2)
print(n3)
For some reason this runs sometimes and not others.
Here is a screenshot of it not running.
It clearly has something to do with the size of the ranges because the larger I make them the less often I return an Error. But, I'd like to understand why it throws the error in the first place so I can avoid it all together.
Thanks in advance.
random.sample(population,k) returns unique k elements from population
In your case, your population is [1,2,3,...39]. Your k = random.randint(21,40). So you will be getting an exception whenever the k value chosen is 40.
This is documented for random.sample:
Return a k length list of unique elements chosen from the population
sequence. Used for random sampling without replacement.
Your screenshots show you use:
n2 = random.sample(range(1, 30), random.randint(21, 40))
That means you could try to take up to 40 samples from a pool of 30 numbers which, without replacement, is not possible. The examples you gave in code in the actual question don't represent what you're trying to do in reality.
I want to eliminate extremes from a list of integers in Python. I'd say that my problem is one of design. Here's what I cooked up so far:
listToTest = [120,130,140,160,200]
def function(l):
length = len(l)
for x in xrange(0,length - 1):
if l[x] < (l[x+1] - l[x]) * 4:
l.remove(l[x+1])
return l
print function(listToTest)
So the output of this should be: 120,130,140,160 without 200, since that's way too far ahead from the others.
And this works, given 200 is the last one or there's only one extreme. Though, it gets problematic with a list like this:
listToTest = [120,200,130,140,160,200]
Or
listToTest = [120,130,140,160,200,140,130,120,200]
So, the output for the last list should be: 120,130,140,160,140,130,120. 200 should be gone, since it's a lot bigger than the "usual", which revolved around ~130-140.
To illustrate it, here's an image:
Obviously, my method doesn't work. Some thoughts:
- I need to somehow do a comparison between x and x+1, see if the next two pairs have a bigger difference than the last pair, then if it does, the pair that has a bigger difference should have one element eliminated (the biggest one), then, recursively do this again. I think I should also have an "acceptable difference", so it knows when the difference is acceptable and not break the recursivity so I end up with only 2 values.
I tried writting it, but no luck so far.
You can use statistics here, eliminating values that fall beyond n standard deviations from the mean:
import numpy as np
test = [120,130,140,160,200,140,130,120,200]
n = 1
output = [x for x in test if abs(x - np.mean(test)) < np.std(test) * n]
# output is [120, 130, 140, 160, 140, 130, 120]
Your problem statement is not clear. If you simply want to remove the max and min then that is a simple
O(N) with 2 extra memory- which is O(1)
operation. This is achieved by retaining the current min/max value and comparing it to each entry in the list in turn.
If you want the min/max K items it is still
O(N + KlogK) with O(k) extra memory
operation. This is achieved by two priorityqueue's of size K: one for the mins, one for the max's.
Or did you intend a different output/outcome from your algorithm?
UPDATE the OP has updated the question: it appears they want a moving (/windowed) average and to delete outliers.
The following is an online algorithm -i.e. it can handle streaming data http://en.wikipedia.org/wiki/Online_algorithm
We can retain a moving average: let's say you keep K entries for the average.
Then create a linked list of size K and a pointer to the head and tail. Now: handling items within the first K entries needs to be thought out separately. After the first K retained items the algo can proceed as follows:
check the next item in the input list against the running k-average. If the value exceeds the acceptable ratio threshold then put its list index into a separate "deletion queue" list. Otherwise: update the running windowed sum as follows:
(a) remove the head entry from the linked list and subtract its value from the running sum
(b) add the latest list entry as the tail of the linked list and add its value to the running sum
(c) recalculate the running average as the running sum /K
Now: how to handle the first K entries? - i.e. before we have a properly initialized running sum?
You will need to make some hard-coded decisions here. A possibility:
run through all first K+2D (D << K) entries.
Keep d max/min values
Remove the d (<< K) max/min values from that list
I am fairly new to Python and I am stuck on a particular question and I thought i'd ask you guys.
The following contains my code so far, aswell as the questions that lie therein:
list=[100,20,30,40 etc...]
Just a list with different numeric values representing an objects weight in grams.
object=0
while len(list)>0:
list_caluclation=list.pop(0)
print(object number:",(object),"evaluates to")
What i want to do next is evaluate the items in the list. So that if we go with index[0], we have a list value of 100. THen i want to separate this into smaller pieces like, for a 100 gram object, one would split it into five 20 gram units. If the value being split up was 35, then it would be one 20 gram unit, on 10 gram unit and one 5 gram unit.
The five units i want to split into are: 20, 10, 5, 1 and 0.5.
If anyone has a quick tip regarding my issue, it would be much appreciated.
Regards
You should think about solving this for a single number first. So what you essentially want to do is split up a number into a partition of known components. This is also known as the Change-making problem. You can choose a greedy algorithm for this that always takes the largest component size as long as it’s still possible:
units = [20, 10, 5, 1, 0.5]
def change (number):
counts = {}
for unit in units:
count, number = divmod(number, unit)
counts[unit] = count
return counts
So this will return a dictionary that maps from each unit to the count of that unit required to get to the target number.
You just need to call that function for each item in your original list.
One way you could do it with a double for loop. The outer loop would be the numbers you input and the inner loop would be the values you want to evaluate (ie [20,10,5,1,0.5]). For each iteration of the inner loop, find how many times the value goes into the number (using the floor method), and then use the modulo operator to reassign the number to be the remainder. On each loop you can have it print out the info that you want :) Im not sure exactly what kind of output you're looking for, but I hope this helps!
Ex:
import math
myList=[100,20,30,40,35]
values=[20,10,5,1,0.5]
for i in myList:
print(str(i)+" evaluates to: ")
for num in values:
evaluation=math.floor(i/num)
print("\t"+str(num)+"'s: "+str(evaluation))
i%=num
I have a non-uniform array 'A'.
A = [1,3,2,4,..., 12002, 13242, ...]
I want to explore how many elements from the array 'A' have values above certain threshold values.
For example, there are 1000 elements that have values larger than 1200, so I want to plot the number of elements that have values larger than 1200. Also, there are other 1500 elements that have values larger than 110 (this includes the 1000 elements, whose values are larger than 1200).
This is a rather large data set, so I would not like to omit any kind of information.
Then, I want to plot the number of elements 'N' above a value A vs. Log (A), i.e.
**'Log N(> A)" vs. 'Log (A)'**.
I thought of binning the data, but I was rather unsuccessful.
I haven't done that much statistics in python, so I was wondering if there is a good way to plot this data?
Thanks in advance.
Let me take another crack at what we have:
A = [1, 3, 2, 4, ..., 12002, 13242, ...]
# This is a List of 12,000 zeros.
num_above = [0]*(12000)
# Notice how we can re-write this for-loop!
for i in B:
num_above = [val+1 if key <= i else val for key,val in enumerate(num_above)]
I believe this is what you want. The final list num_above will be such that for num_above[5] equals the number of elements in A that are above 5.
Explanation::
That last line is where all the magic happens. It goes through elements in A (i)and adds one to all the elements in num_above whose index is less than i.
The enumerate(A) statement is an enumerator that generates an iterator of tuples that include the keys and values of all the elements in A: (0,1) (1,3) -> (2,2) -> (3,4) -> ...
Also, the num_above = [x for y in List] statement is known as List Comprehension, and is a really powerful tool in Python.
Improvements: I see you already modified your question to include these changes, but I think they were important.
I removed the numpy dependency. When possible, removing dependencies reduces the complexity of projects, especially larger projects.
I also removed the original list A. This could be replaced with something that was basically like A = range(12000).