Copy float values from within lists of lists - python

I do apologize if I'm not looking in the right places, but I cannot for the life of me figure out how to get a value from say
list[[1,2,3][4,5,6.01]] , list[1][2] integrated into code as anything but a list.
import random
fruits = [
['mango',7],
['apple',4],
['kiwi',6],
['grape',12],
['pear',3]
]
#Finding Probability
def setup():
fsum = 0;
prob = 0;
i = 0
#Finding the sum
while i < len(fruits):
fsum += fruits[i][1]
i += 1
i = 0
#Calculating Probability
while i < len(fruits):
prob = [fruits[i][1] / fsum]
fruits[i].append(prob)
i += 1
print(fsum)
print(fruits)
setup()
def pick(x):
rand = random.random()
index = 0
while rand > 0:
#How do I get the value of the float in the list from the next line
#(fruits[index][2])
#to be stored in a variable that I can plug into this.
#rand = rand - (var)
index+=1
pick (fruits)
Any feedback would be greatly appreciated.

Your problem is this line:
prob = [fruits[i][1] / fsum]
You are defining prob to be a list with one value, just eliminate the unnecessary list, e.g.:
prob = fruits[i][1] / fsum
Then fruits[index][2] will be the probability.
You should consider replacing your while loops with for loops, e.g.:
while i < len(fruits):
fsum += fruits[i][1]
i += 1
i = 0
Is equivalent to:
for fruit in fruits:
fsum += fruit[1]
Which could be be accomplished with a generator expression:
fsum = sum(fruit[1] for fruit in fruits)
But if what you are looking to do is just pick the fruit based on the relative weights (fruits[i][1]) then there is an easier way to do this in Py3.6, without the setup(), e.g.:
def pick(fruits):
items, weights = zip(*fruits)
return random.choices(items, weights)[0]
Prior to Py3.6 you could do:
def pick(fruits):
return random.choice([f for fruit in fruits for f in [fruit[0]]*fruit[1]])

Just access the first item of the list/array, using the index access and the index 0:
var = fruits[index][2][0]

Related

Problem with my probability calculator in Python

Essentially I am making a probability calculator using Python. It is meant to find the probability to finding a set number of balls after performing a set number of experiments (could be a large number), where in each experiment, you draw a certain number of balls randomly from a hat. I used object oriented programming to do this under the class Hat.
A hat object can be created this way:
hat = Hat(blue=3,red=2,green=6)
The class should take a variable number of arguments that specify the number of balls of each color that are in the hat. Here the hat contains 3 blue balls, 2 red balls and 6 green balls.
Outside the class, there is a function called experiment that works out the probability of drawing certain type of balls (expected_balls) from a argument called 'hat' when you decide to draw a set number of balls (num_balls_drawn) after performing a certain number of experiments (num_experiments). The certain balls can be balls of different colors or styles. So a typical way/example of calling the experiment function is:
probability = experiment(hat=hat, expected_balls={"blue":2,"green":1}, num_balls_drawn=4, num_experiments=1000)
The probabilities produced each time the code is run should vary slightly. I was testing my code with this object and specific function call:
hat = Hat(blue=3,red=2,green=6)
probability = experiment(hat=hat, expected_balls={"blue":2,"green":1}, num_balls_drawn=4, num_experiments=1000)
While my probabilities varied slightly and produce probabilities between 0.31 and 0.39, the expected probability is actually 0.272 or values close to that probability (with a difference of 0.01). So it appears that I am far off. However, I can't quite work out what the problem is and how to fix it.
Any help will be appreciated! Thank you in advance.
THE CODE
import copy
import random
class Hat:
def __init__(self,**ball):
self.contents = list() #holds the balls
ball_and_count = list() #list for colour of ball and its count
for key, value in ball.items():
ball_and_count.append(f"{key}= {value}")
#print(ball_and_count)
for i in ball_and_count:
equal_pos = i.find("=")
ball_type = i[:equal_pos] #using string splicing to find ball type
count = int(i[equal_pos+1:])#using string splicing to find the number of balls of that type
c = 0
while c < count:
self.contents.append(ball_type)
c = c + 1
def draw(self,num)
self.num = num
c = 0 #used in a while loop
drawed_ball = list() #this is where all the balls that were drawed out from contents will stay
try:
while c < self.num:
drawed_ball.append(self.contents.pop(random.randint(0,len(self.contents)-1)))
c = c + 1
return drawed_ball
except:
return drawed_ball
def experiment(hat, expected_balls,num_balls_drawn, num_experiments):
M = 0
exp_done = 0
while exp_done < num_experiments:
drawn = 0
drawn_balls = list()
while drawn < num_balls_drawn:
dc_contents = copy.deepcopy(hat.contents) # we are creating a deep copy of hat contents so that hat.contents stays the same
drawn_balls.append(dc_contents.pop(random.randint(0,len(dc_contents)-1))) #append to the drawn_balls list
v = 0
for key, val in expected_balls.items():
if key in drawn_balls:
k = drawn_balls.count(key)
if k >= val:#here we are checking if for one ball type, we are drew the expected number of balls, then we increment the variable v
v = v + 1
if v == len(expected_balls):#we check if we have drawn the expected no. balls for all the balls and types, either we did or we did not, no in between, then we increment the variable M
M = M + 1
#incrementing the number of balls drawn
drawn = drawn + 1
exp_done = exp_done + 1 #incrementing the number of experiments drawn
N = num_experiments
prob = M / N
return prob
There's more efficient ways to approach the problem, but following your original structure:
def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
exp_done = 0
M = 0
while exp_done < num_experiments:
drawn = 0
drawn_balls = list()
dc_contents = copy.deepcopy(
hat.contents) # we are creating a deep copy of hat contents so that hat.contents stays the same
while drawn < num_balls_drawn:
drawn_balls.append(
dc_contents.pop(random.randint(0, len(dc_contents) - 1))) # append to the drawn_balls list
for key, val in expected_balls.items():
if drawn_balls.count(key) < val:
break
else:
M += 1
break
drawn += 1
exp_done += 1 # incrementing the number of experiments drawn
N = num_experiments
prob = M / N
return prob
Problems that had to be fixed:
you were resetting the hat after every ball drawn, the deepcopy needs to be outside the loop
your check routine counted a success as soon as each required type was drawn
Runnable:
import copy
import random
class Hat:
def __init__(self,**ball):
self.contents = list() #holds the balls
ball_and_count = list() #list for colour of ball and its count
for key, value in ball.items():
ball_and_count.append(f"{key}= {value}")
#print(ball_and_count)
for i in ball_and_count:
equal_pos = i.find("=")
ball_type = i[:equal_pos] #using string splicing to find ball type
count = int(i[equal_pos+1:])#using string splicing to find the number of balls of that type
c = 0
while c < count:
self.contents.append(ball_type)
c = c + 1
def draw(self,num):
self.num = num
c = 0 #used in a while loop
drawed_ball = list() #this is where all the balls that were drawed out from contents will stay
try:
while c < self.num:
drawed_ball.append(self.contents.pop(random.randint(0,len(self.contents)-1)))
c = c + 1
return drawed_ball
except:
return drawed_ball
def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
exp_done = 0
M = 0
while exp_done < num_experiments:
drawn = 0
drawn_balls = list()
dc_contents = copy.deepcopy(
hat.contents) # we are creating a deep copy of hat contents so that hat.contents stays the same
while drawn < num_balls_drawn:
drawn_balls.append(
dc_contents.pop(random.randint(0, len(dc_contents) - 1))) # append to the drawn_balls list
for key, val in expected_balls.items():
if drawn_balls.count(key) < val:
break
else:
M += 1
break
drawn += 1
exp_done += 1 # incrementing the number of experiments drawn
N = num_experiments
prob = M / N
return prob
hat = Hat(blue=3,red=2,green=6)
probability = experiment(hat=hat, expected_balls={"blue":2,"green":1}, num_balls_drawn=4, num_experiments=1000)
print(probability)
This prints values like 0.288 - how you'd be getting values like 8.0 is a mystery to me, but I'm fairly certain this isn't actually the code you're running. (and thus you weren't running the solution given with your code - that still has a typo and won't run on def draw(self,num) anyway)
I finally fixed it! I'm relieved. I just simply made some adjustments on my draw method in the Hat class. Then I used the draw method in the experiment function, as well as the changes that you (Grismar) mentioned. Thank you so so much!
import copy
import random
class Hat:
def __init__(self,**ball):
self.contents = list() #holds the balls
ball_and_count = list() #list for colour of ball and its count
for key, value in ball.items():
ball_and_count.append(f"{key}= {value}")
#print(ball_and_count)
for i in ball_and_count:
equal_pos = i.find("=")
ball_type = i[:equal_pos] #using string splicing to find ball type
count = int(i[equal_pos+1:])#using string splicing to find the number of balls of that type
c = 0
while c < count:
self.contents.append(ball_type)
c = c + 1
def draw(self,num):
self.num = num
c = 0 #used in a while loop
drawed_ball = list() #this is where all the balls that were drawed out from contents will stay
if self.num <= len(self.contents):
while c < self.num:
drawed_ball.append(self.contents.pop(random.randint(0,len(self.contents)-1)))
c = c + 1
return drawed_ball
else:
drawed_ball = self.contents
return drawed_ball
def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
exp_done = 0
M = 0
while exp_done < num_experiments:
dc_contents = copy.deepcopy(hat) # we are creating a deep copy of hat contents so that hat.contents stays the same
drawn_balls = dc_contents.draw(num_balls_drawn)
for key,val in expected_balls.items():
if drawn_balls.count(key) < val:
break
else:
M += 1
exp_done += 1 # incrementing the number of experiments drawn
N = num_experiments
prob = M / N
return prob

Python: defining a function with mean and standard deviation calculation

I am trying to calculate mean and the population standard deviation without using stats module...and my code will be
total = 0
sum3 = 0
def stats():
global total
for numbers in range(0,len(my_list)):
total = total + my_list[numbers]
mean = total / len(my_list)
print(mean)
for numbers in range(0,len(my_list)):
global sum3
sum3 = sum3 + (my_list[numbers] - mean)**2
sum21 = sum3 / len(my_list)
standard_dev = sum21**(1/2)
print(standard_dev)
my_list1 = input()
my_list = my_list1.split()
print(my_list)
stats()
also help me to assign a list of numbers to int.....thank u
Try this code. The stats methods have not been used here.
Only python methods have been used to speed up the functions.
def mean(my_list):
sum = sum(my_list)
return sum/len(my_list)
def standard_deviation(my_list):
mean = mean(my_list)
temp = 0
for item in my_list:
temp = temp + ((item - mean) ** 2)
return (temp/len(my_list))**0.5
This seems like a nice place to use list comprehension for brevity's sake.
def mean(l):
return sum(l) / len(l)
def stdev(l):
# Get the mean of the list
m = mean(l)
# Subtract the mean from each item and square the result
# Take the mean from the resulting list
m_of_sqrd = mean([(i-m)**2 for i in l])
# Return the root
return m_of_sqrd ** 0.5
inp = input()
values = [int(item) for item in inp.split()]
print(mean(values))
print(stdev(values))

Count occurances with if statement python

Think of the Unit Circle x 2. What I have done is create two lists, one for x and one for y, producing 500 pairs of random (x,y). Then I created r=x2+y2 in my while loop, where r is the radius and x2=x**2 and y2=y**2. What I want to be able to do is count the number of times r=<2. I assume my if statement needs to be in the while loop, but I don't know how to actually count the number of times the condition r=<2is met. Do I need to create a list for the r values?
import random
from math import *
def randomgen(N):
rlg1=[]
rlg2=[]
a=random.randint(0,N)
b=float(a)/N
return b
i=0
rlg=[]
rlg2=[]
countlist=[]
while i<500:
x=randomgen(100)*2
y=randomgen(100)*2
x2=x**2
y2=y**2
r=x2+y2
rlg.append(x)
rlg2.append(y)
print rlg[i],rlg2[i]
i+=1
if r<=2:
import random
from math import *
def randomgen(N):
rlg1=[]
rlg2=[]
a=random.randint(0,N)
b=float(a)/N
return b
i=0
rlg=[]
rlg2=[]
countlist=[]
amount = 0
while i<500:
x=randomgen(100)*2
y=randomgen(100)*2
x2=x**2
y2=y**2
r=x2+y2
rlg.append(x)
rlg2.append(y)
print rlg[i],rlg2[i]
i+=1
if r<=2:
amount += 1
You need two counters here. One for the total number of points (i) and one for the number of points that lie within your circle r <= 2 (I'm calling this one isInside). You only want to increment the isInside counter if the point lies within your circle (r <= 2).
i = 0
rlg = []
rlg2 = []
countlist = []
isInside = 0
while i < 500:
x=randomgen(100)*2
y=randomgen(100)*2
x2=x**2
y2=y**2
r=x2+y2
rlg.append(x)
rlg2.append(y)
print rlg[i],rlg2[i]
i+=1
if r <= 2:
# increment your isInside counter
isInside += 1

summing the dice trials and histogram plot

I am stuck in a code in python which takes in number of dices and number of rolls and returns the sum of numbers obtained. It should also print the histogram of the sum. I am stuck in the first part of the code. Can someone help me fix this? Not sure where i am going wrong. Any help for the second part (returning histogram) would be helpful for me to learn it in python.
from random import choice
def roll(rolls,dice):
d = []
for _ in range(rolls):
d[sum(choice(range(1,7)) for _ in range(dice))] += 1
return(d)
Your problem here is that you can't arbitrarily index into an empty list:
l = []
l[13] += 1 # fails with IndexError
Instead, you could use a defaultdict, which is a special type of dictionary that doesn't mind if a key hasn't been used yet:
from collections import defaultdict
d = defaultdict(int) # default to integer (0)
d[13] += 1 # works fine, adds 1 to the default
or Counter, which is designed for cases like this ("provided to support convenient and rapid tallies") and provides extra handy functions (like most_common(n), to get the n most common entries):
from collections import Counter
c = Counter()
c[13] += 1
To manually use a standard dict to do this, just add a check:
d = {}
if 13 in d: # already there
d[13] += 1 # increment
else: # not already there
d[13] = 1 # create
Try this,
from random import choice
import pylab
def roll( rolls, dice ):
s = list()
for d in range( dice ):
for r in range( rolls ):
s.append( choice( range(1,7) ) )
return s
s = roll( rolls, dice )
sum_of_rolls = sum( s )
# then to plot..
pylab.hist( s )
This should do it
import random
def rolls(N, r): # N=number of dice. r=number of rolls
myDie = [1,2,3,4,5,6]
answer = {}
for _rolling in range(r):
rolls = []
for _die in range(N):
rolls.append(random.choice(myDie))
total = 0
for roll in rolls:
total += roll
if total not in answer:
answer[total] = 0
answer[total] += 1
return answer

When calling an array only the first element is used?

When calling QuarterlySales into the DetermineRate procedure it only uses the first number in the array every time the loop goes around. I think I have it indexed properly. Also it only prints out 9 numbers when it should print out 10.
def FillQuarterlySales(QuarterlySales):
#declare local variables
Index = 0
QuarterlySales = [0] * 10
#Loading the array
QuarterlySales = [21487, 22450, 7814, 12458, 4325, 9247, 18125, 5878, 16875, 10985]
#Determine the quarterly sales based on the index
return QuarterlySales
def DetermineRate(QuarterlySales):
#declare local variables
Rate = float()
Index = 0
Counter = 0
Rates = [Index] * 9
for Index in range (9):
if QuarterlySales[Counter] < 5000:
Rate = 0
elif QuarterlySales[Counter] < 10000:
Rate = 0.04
elif QuarterlySales[Counter] < 15000:
Rate = 0.08
elif QuarterlySales[Counter] < 20000:
Rate = 0.12
else:
Rate = 0.15
#end if
Rates[Index] = Rate
#end for
return Rates
There is no error code but when I print out rates to make sure they are correct the array is filled with the same number. This is happening anywhere I call QuarterlySales throughout the program as well.
It's because you use Counter to index QuarterlySales instead of Index.
But your question shows some inexperience with python, so let's try to address some other issues, too.
Rates = [Index] * 9
...
QuarterlySales = [0] * 10
This looks like you're trying to do allocation in advance, which is almost always unnecessary in python. Certainly for lists of only ten elements, it hurts more than it helps.
Instead do this:
Rates = []
...
QuarterlySales = []
and then just use the .append() method to add sequential data elements to the list.
For example:
def DetermineRate(QuarterlySales):
Rates = []
for sales in QuarterlySales:
if sales < 5000:
Rates.append(0.)
elif sales < 10000:
Rates.append(0.04)
elif sales < 15000:
Rates.append(0.08)
elif sales < 20000:
Rates.append(0.12)
else:
Rates.append(0.15)
return Rates

Categories

Resources