How do I generate dice rolls with different probabilities? - python

just working on a homework question where it asks to produce a dice rolling program where one or two numbers may be more likely to print than the rest. For example 2 and/or 3 might be 10% or 20% more likely to print than other elements on the dice. I got the code up to the point where I can get it to print a random number on the dice but can't figure out how to have a weighted output.
input:
def roll_dice(n, faces = 6):
rolls = []
rand = random.randrange
for x in range (n):
rolls.append(rand(1, faces + 1 ))
return rolls
print (roll_dice(5))
output:
[5, 11, 6, 7, 6, 5]

from scipy import stats
values = np.arange(1, 7)
prob = (0.1, 0.2, 0.3, 0.1, 0.1, 0.2) # probabilities must sum to 1
custm = stats.rv_discrete(values=(values, prob))
for i in range(10):
print(custm.rvs())
1, 2, 3, 6, 3, 2, 3, 2, 2, 1
Source: scipy.stats.rv_discrete

If you are on Python 3
import random
rolls = random.choices([1,2,3,4,5,6],weights=[10,10,10,10,10,50], k=10)
rolls
out:[1, 3, 2, 5, 3, 4, 6, 6, 6, 4]

Related

Percentage distribution of values in a python list

Let's say we have following list. This list contains response times of a REST server in a traffic run.
[1, 2, 3, 3, 4, 5, 6, 7, 9, 1]
I need following output
Percentage of the requests served within a certain time (ms)
50% 3
60% 4
70% 5
80% 6
90% 7
100% 9
How can we get it done in python? This is apache bench kind of output. So basically lets say at 50%, we need to find point in list below which 50% of the list elements are present and so on.
You can try something like this:
responseTimes = [1, 2, 3, 3, 4, 5, 6, 7, 9, 1]
for time in range(3,10):
percentage = len([x for x in responseTimes if x <= time])/(len(responseTimes))
print(f'{percentage*100}%')
"So basically lets say at 50%, we need to find point in list below which 50% of the list elements are present and so on"
responseTimes = [1, 2, 3, 3, 4, 5, 6, 7, 9, 1]
percentage = 0
time = 0
while(percentage <= 0.5):
percentage = len([x for x in responseTimes if x <= time])/(len(responseTimes))
time+=1
print(f'Every time under {time}(ms) occurrs lower than 50% of the time')
You basically need to compute the cumulative ratio of the sorted response times.
from collections import Counter
values = [1, 2, 3, 3, 4, 5, 6, 7, 9, 1]
frequency = Counter(values) # {1: 2, 2: 1, 3: 2, ...}
total = 0
n = len(values)
for time in sorted(frequency):
total += frequency[time]
print(time, f'{100*total/n}%')
This will print all times with the corresponding ratios.
1 20.0%
2 30.0%
3 50.0%
4 60.0%
5 70.0%
6 80.0%
7 90.0%
9 100.0%

How to cut the lower values when caclulating percentile?

If I calculate 90 percentile using numpy:
import numpy as np
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
p = np.percentile(a, 90)
print (p)
It cuts the highest value so the result is:
9.1
How to cut instead the lower values so the output would be:
2
Thank you!
You want the 10th percentile, not the 90th.
p = np.percentile(a, 10)
print (p)
# 1.9

Python: Find outliers inside a list

I'm having a list with a random amount of integers and/or floats. What I'm trying to achieve is to find the exceptions inside my numbers (hoping to use the right words to explain this). For example:
list = [1, 3, 2, 14, 108, 2, 1, 8, 97, 1, 4, 3, 5]
90 to 99% of my integer values are between 1 and 20
sometimes there are values that are much higher, let's say somewhere around 100 or 1.000 or even more
My problem is, that these values can be different all the time. Maybe the regular range is somewhere between 1.000 to 1.200 and the exceptions are in the range of half a million.
Is there a function to filter out these special numbers?
Assuming your list is l:
If you know you want to filter a certain percentile/quantile, you can
use:
This removes bottom 10% and top 90%. Of course, you can change any of
them to your desired cut-off (for example you can remove the bottom filter and only filter the top 90% in your example):
import numpy as np
l = np.array(l)
l = l[(l>np.quantile(l,0.1)) & (l<np.quantile(l,0.9))].tolist()
output:
[ 3 2 14 2 8 4 3 5]
If you are not sure of the percentile cut-off and are looking to
remove outliers:
You can adjust your cut-off for outliers by adjusting argument m in
function call. The larger it is, the less outliers are removed. This function seems to be more robust to various types of outliers compared to other outlier removal techniques.
import numpy as np
l = np.array(l)
def reject_outliers(data, m=6.):
d = np.abs(data - np.median(data))
mdev = np.median(d)
s = d / (mdev if mdev else 1.)
return data[s < m].tolist()
print(reject_outliers(l))
output:
[1, 3, 2, 14, 2, 1, 8, 1, 4, 3, 5]
You can use the built-in filter() method:
lst1 = [1, 3, 2, 14, 108, 2, 1, 8, 97, 1, 4, 3, 5]
lst2 = list(filter(lambda x: x > 5,lst1))
print(lst2)
Output:
[14, 108, 8, 97]
So here is a method how to block out those deviators
import math
_list = [1, 3, 2, 14, 108, 2, 1, 8, 97, 1, 4, 3, 5]
def consts(_list):
mu = 0
for i in _list:
mu += i
mu = mu/len(_list)
sigma = 0
for i in _list:
sigma += math.pow(i-mu,2)
sigma = math.sqrt(sigma/len(_list))
return sigma, mu
def frequence(x, sigma, mu):
return (1/(sigma*math.sqrt(2*math.pi)))*math.exp(-(1/2)*math.pow(((x-mu)/sigma),2))
sigma, mu = consts(_list)
new_list = []
for i in range(len(_list)):
if frequence(_list[i], sigma, mu) > 0.01:
new_list.append(i)
print(new_list)

summing element in a range for all element in an array

I have to get the total sum of a range from an array. However the array range needs to move from one element to another. for example if the array is 1,2,3,4,5,6 and if every two element needs to be added , then it should add 1+2 than 2+3 than 3+4 and so on.
I have tried but not getting right approach. I am sure there is a pythonic way of doing this.
here what I have tried
data = np.arange(0,20,.3)
for i in range (0,len(data)):
for j in range(i,len(data)):
get_range = data[j:5]
get_add = get_range.sum()
print("sum:",get_add)
I have tried to add every 5 element here.
You could use a list comprehension which retrieves a chunks list.
l = [1,2,3,4,5,6]
n = 2
output = [sum(l[i:i + n]) for i in range(0, len(l) - n + 1, 1)]
Output
[3, 5, 7, 9, 11]
There is a numpyic way to do this. It is more memory- and CPU- effective if your input data is big enougth.
import numpy as np
# input array: [1, 2, 3, 4, 5, 6]
data = np.arange(1, 7)
# cumulative sum: [1, 3, 6, 10, 15, 21]
data_cumsum = np.cumsum(data)
# append zero to start: [0, 1, 3, 6, 10, 15, 21]
data_cumsum = np.hstack([0, data_cumsum])
# calculate moving sum
window = 2
moving_sum = data_cumsum[window:] - data_cumsum[:-window]
print(moving_sum)
Output:
[ 3 5 7 9 11]
A minor change will solve the problem
data = np.arange(0,10)
for j in range(0,len(data)-1):
get_range = data[j:j+2] #changed from j to j+2
get_add = get_range.sum()
print("sum:",get_add)
OUTPUT
('sum:', 1)
('sum:', 3)
('sum:', 5)
('sum:', 7)
('sum:', 9)
('sum:', 11)
('sum:', 13)
('sum:', 15)
('sum:', 17)
You can easily condense above steps to form a list comprehension giving the same results with same complexity
[sum(data[j:j+2]) for j in range(0,len(data)-1)]
Another fancy approach could be using sliding_window function
from toolz.itertoolz import sliding_window
map(sum,list(sliding_window(2,list(range(0,10)))))
Output
[1, 3, 5, 7, 9, 11, 13, 15, 17]

how to find nearest equal or higher multiple of ten in python [duplicate]

This question already has answers here:
Round to 5 (or other number) in Python
(21 answers)
Closed 6 years ago.
I have a this small task , where I am rounding up the number to higher multiple of ten. But want to round it to nearest multiple of ten.
My code :
import math
a = map(int,list(str(7990442)))
b = map(int,list(str(1313131)))
print "a :",a
print "b :",b
l= []
for p,q in zip(a,b):
l.append(p*q)
print "prod list :",l
ls = sum(l)
print "sum :",ls
def roundup(x):
return int(math.ceil(x / 10.0)) * 10
top = roundup(ls)
print "round value: ",top
val = top-ls
print "val :",val
a.append(val)
print "output :",a
Output :
a : [7, 9, 9, 0, 4, 4, 2]
b : [1, 3, 1, 3, 1, 3, 1]
prod list : [7, 27, 9, 0, 4, 12, 2]
sum : 61
round value: 70
val : 9
output : [7, 9, 9, 0, 4, 4, 2, 9]
Expected Output :
sum : 61
round value: 60
val : 1
output : [7, 9, 9, 0, 4, 4, 2, 1]
You can use round(x / 10.0) * 10 instead of math.ceil.
Even easier would be
def custom_round(x):
return int(round(x, -1))
This immediately rounds to a multiple of ten.
For the general purpose, given a base to round to:
def my_special_round(x, base=10):
return int(base * round(float(x)/base))
To find the smallest multiple of ten, I would do something like this. This way I didn't need to use Math Lib:
while True:
n=int(input("number"))
n=n/10
n=int(n) # it removes decimal
n=n*10 #then by make it times 10 to return to proportion
print(n)
In this code I used the int casting to get rid of the unit.
If you want to find the nearest (including the top one) you could use an if unit is more than 5, then add one:
while True:
n=int(input("number"))
if (n%10>5):
n=n+10
n=n/10
n=int(n)
n=n*10
print(n)

Categories