How to generate random variables and sum all them in python - python

My problem explicitly is
Z=sum_(i)^12 (x_i).
where i is indices and x_i's are random number...
I need an explicit code in Python to produce 12 random variables and sum all them.
I tried write code using if, while loop, but I could not get it.
I need your help...

In order to be able to use arbitrary variable just structure it as a function.
You can structure it similar to l82Munch, but this may be more readable for you since your just starting. Note that range is a generator function that returns a list up to the last call. So range(1,3) returns [1,2]
import random
def rand_sum(i, j):
sum_list = []
for rand_num in range(i, j+1):
sum_list.append(random.random()) # Check random docs for a function that returns
return sum(sum_list) # a different set of randoms if this isn't
# appropriate

import random
rand_sum = sum( random.random() for x in range(12) )
See the random documentation for more info.

In probabilistic modelling, you can define distributions then sum them.
Personally, I use OpenTURNS platform for that.
import openturns as ot
x1 = ot.Normal(0, 2) # Normal distribution mean = 0, std = 2
x2 = ot.Uniform(3, 5) # Uniform distribution between 3 and 5
sum = x1 + x2
That's it.
If x1,..., x12 are 12 distributions identically distributed you can write:
sum_12 = sum([x1] * 12)

Related

Does numpy.corrcoef calculate correlation within matrices when two matrices are provided (intra-correlation)?

Here I'm calculating the Pearson correlation such that I'm accounting for every comparison.
x = pd.DataFrame({'a':[3,6,4,7,9],'b':[6,2,4,1,5],'c':[7,9,1,2,9]},index=['aa','bb','cc','dd','ee']).T
y = pd.DataFrame({'A':[9,4,1,3,5],'B':[9,8,9,5,7],'C':[1,1,3,1,2]},index=['aa','bb','cc','dd','ee']).T
table = pd.DataFrame(columns=['Correlation Coeff'])
for i in range(0, len(x)):
for j in range(0, len(y)):
xf = list(x.iloc[i])
yf = list(y.iloc[j])
n = np.corrcoef(xf,yf)[0,1]
name = x.index[i]+'|'+y.index[j]
table.at[name, 'Correlation Coeff'] = n
table
This is the result:
Correlation Coeff
a|A -0.232973
a|B -0.713392
a|C -0.046829
b|A 0.601487
b|B 0.662849
b|C 0.29654
c|A 0.608993
c|B 0.16311
c|C -0.421398
Now when I just apply these tables directly to numpy's function, removing duplicate values and 'ones' it looks this this.
x = pd.DataFrame({'a':[3,6,4,7,9],'b':[6,2,4,1,5],'c':[7,9,1,2,9]},index=['aa','bb','cc','dd','ee']).T.to_numpy()
y = pd.DataFrame({'A':[9,4,1,3,5],'B':[9,8,9,5,7],'C':[1,1,3,1,2]},index=['aa','bb','cc','dd','ee']).T.to_numpy()
n = np.corrcoef(x,y)
n = n.tolist()
n = [element for sub in n for element in sub]
# Rounding to ensure no duplicates are being picked up.
rnd = [round(num, 13) for num in n]
X = [i for i in rnd if i != 1]
X = list(dict.fromkeys(X))
X
[-0.3231828652987,
0.3157400783243,
-0.232972779074,
-0.7133922984085,
-0.0468292905791,
0.3196502842345,
0.6014868821052,
0.6628489803599,
0.2965401263095,
0.608993434846,
0.1631095635753,
-0.4213976904463,
0.2417468892076,
-0.5841782301194,
0.3674842076296]
There are 6 extra values (in bold) not accounted for. I'm assuming that they are correlation values calculated within a single matrix and if so, why? Is there a way to use this function without generating these additional values?
You are right in assuming that those are the correlations from variables within x and y, and so far as I can tell there is no way to turn this behaviour off.
You can see that this is true by looking at the implementation of numpy.corrcoef. As expected, most of the heavy lifting is being done by a separate function that computes covariance - if you look at the implementation of numpy.cov, particularly line 2639, you will see that, if you supply an additional y argument, this is simply concatenated onto x before computing the covariance matrix.
If necessary, it wouldn't be too hard to implement your own version of corrcoef that works how you want. Note that you can do this in pure numpy, which in most cases will be faster than the iterative approach from the example code above.

Creating step-wise function to increase x after given time intervals

I would like to create a step-wise increase in x starting from 0 and increasing by 10 every 30 seconds. I've defined time (t) as t=arange(0,120).
I looked at the Heaviside function but it did not seem to fit my need. I would need my x output to be a single value, not an array.
Sorry if this question is basic or misunderstood - I am very unfamiliar with python.
In order for you to set the value at n[0] to 0.29, n must be an array with something already at position 0.
n = [0.50] #already populated list
n[0] = 0.29
n = [0.29]
Alternatively, you could initialise the list with 0.29 as the first value.
n = [0.29]
n = [0.29]
As for your second question, we could use a for loop
import time #module used for time functions
for x in range(0, 120, 10): #defined a range of x (0,120) with a step of 10
print(x)
time.sleep(30) #wait 30 secs
Do you mean something like this?
import numpy
t=numpy.arange(0,120)
x=numpy.floor(t/30) * 10
It can also be done without numpy using list comprehension.
import math
t=range(0,120)
x=[math.floor(tx/30) * 10 for tx in t]
Or a traditional loop for that matter.
import math
x=[]
t=range(0,120)
for tx in t:
x.append(math.floor(tx/30) * 10)

python filling an list with random amount [lb,ub]

I want to fill some list with size N with random variable between LB and UB in python 3.6.
Would you please guide me?
Something simple like this works, using random.randint:
>>> import random
>>> N = 5 # count
>>> LB = 0 # lower bound
>>> UB = 10 # upper bound
>>> [random.randint(LB, UB) for _ in range(N)]
[6, 6, 5, 3, 2]
Take a look into either random or numpy.random (the second is better in my opinion, but requires numpy to be installed).
The specific function to use depends on which numbers you want, and how you want them to be distributed:
if you want uniformly distributed integers, you can use random.randint(LB, UB). If you want floats, you can use random.uniform(LB, UB). You can also have normally distributed numbers for example.
numpy's random makes it much easier, as it can return a list. e.g.:
numpy.random.randint(LB, UB, N)

Creating an array for values of a square wave function

I have a function shown below
f(t) = 1 : if 2t rounded down to the next lowest integer is even
f(t) = -1 : if 2t rounded down to the next lowest integer is odd
I am trying to eventually carry out fourier transformations on the function but first I need to write a program to create an array of N=1000 elements containing 1000 equally spaced samples from a single cycle of this function which is a square wave.
How do I create this array ?
As you ask for the values of the square function within a cycle, first you have to create the values for the time samples. Starting at t=0 the function you mentioned has a cycle of 1, after t=1 the function repeates itself.
For creating a sequence of equally spaced values between 0 and 1 there are several alternatives, but a straitght one is numpy.linspace. The first parameter is the starting time of the cycle, the second the end of the cycle and the third the number of samples (equally spaced). By using this you create the t_samples.
After that you just need to feed the square wave function (square_func in the code below) with the values stored in t_samples.
See an example here of how you can use it:
import numpy
def square_func(t):
if int(2*t)%2 == 0:
return 1
else:
return -1
t_samples = numpy.linspace(0.0,1.0,1000)
samples = [square_func(i) for i in t_samples]
The variable samples stores a list with the values you need (half of them are '1s' and the other half '-1s', as we are referring to one cycle). The cycle of the function produced with this code is shown in the following figure:
The function can be defined this way.
def f(t):
return 1 if int(2 * t) % 2 == 0 else -1
And if you are using python 2.x you can use map to create the list.
N = 1000
sample = map(f, xrange(N)) # Or alternatively map(lambda n: f(n), xrange(N))
Let's assume you have a method returning the sample value:
import math
def f(t):
"""
f(t) = 1 if ⌊2t⌋ is even, −1 if ⌊2t⌋ is odd
"""
if math.floor(2 * t) % 2 == 0:
return 1
else:
return -1
The easiest way to generate your array would be to do:
a = [f(n) for n in xrange(1000)]
Note: This assumes Python 2.x, use range if Python 3.x
I ended up answering it in this way
F=zeros(1000)
F[0:500]=1
F[500:1000]=-1

Equation to give a number of outputs based on change of one paramater

Here is my equation:
import math
import pandas as pd
import numpy as np
ha = 8.14
k = 0.0187
Do = 0.1738
Di = 0.0138
L = 3
F = 20
Ta = 293
Ts = 113
pi = 3.14159265
Q = (pi*(Ta-Ts))/(((1/ha*Do))+(1/(2*k))*math.log(Do/Di)) * L
h = (Q*3600)/F
Basically, I want the outputs for when F = np.arange(20,100,10)
is this possible?
I tried
a = np.arange(20,100,10)
F = 20 + i
for i in range(a):
print h
not sure why this doesn't work?
any ideas?
When you use numpy you should try to not use explicit loops, as numpy's main virtue is to execute implicitly the loops with the speed of a compiled language.
To come to our problem, it is simply
F = np.arange(20,100,10)
h = Q*3600/F
print h
where I use the array F just as a normal Python variable, and it's up to numpy magics to recognize the need for a loop.
Remember: you can use numpy's arrays in your expressions just like you would use a scalar and, as far as your usage is a sensible one, Python will compute an array-zed result.
Side Note use np.pi instead of 3.14159...
You need to define a function that takes in parameters. then you can call in that function based on a set of parameters. Bellow I show you an example with a sin(x) function because I'm sure you can figure out hwo to adapt it to your needs
import math
points = np.arange(20, 100, 10)
def sine(x, a=1.0, b=2.0):
return a*math.sin(b*x)
for i in points:
print(sine(i,b=i), end=" ")
-0.8509193596391765 0.9978032744219705 -0.8012247906768953 -0.6501275235748956 -0.2620839590180966 -0.7736233386803075 -0.5444763096196569 0.8272184413093554
this will call your sin function with various parameter b and will calculate it in different points x
The way you're doing it should always print out exactly the same number. Since you've already calculated everything. You don't have a function anywhere, and by putting it all in a for loop won't automagically change anything.
Unless it's some for of pandas magic in interpreter I don't know about. (In that case sorry, I'm not a big user of pandas)
Currently your code is giving Q and h a specific value, and never changes that value again.
Explanation:
In the code below
Q = 4
W = Q
print(Q)
print(W)
you are saying: name Q refers to value 4 and name W refers to the current value of Q(that is 4, regardless whether Q changes later on or not).
If you type Q = 10, W will not change:
Q = 10
print(Q)
print(W)
Therefore you need functions that will be calculated each time you call them:
def Q():
return (pi*(Ta-Ts))/(((1/ha*Do))+(1/(2*k))*math.log(Do/Di)) * L
def h():
return (Q()*3600)/F
for i in np.arange(20,100,10):
F = 20 + i
print h()
The above explanation is a bit oversimplified, so you might want to check this link.

Categories