I'm trying to statistically process data using python for learning purposes.
In my problem I generate two tosses of a dice n times, where X is a random variable, defining a product of two tosses. I managed how to calculate the expectation of X, then the variance of X, but I have problems with computing the standard deviation of X.
Here is my question.
How to get a third list from two lists, based on algebraic operations on elements of these two lists with the same serial numbers? Precisely, I want to get something like this.
x = [x0, x1, .., xi, .., xn]
y = [y0, y1, .., yi, .., yn]
z = [(x0-y0)^2, (x1-y1)^2, .., (xi-yi)^2, .., (xn-yn)^2]
Here is my code. Maybe it's a bit bulky, but it's my first one. I receive an error
unsupported operand type(s) for -: 'list' and 'Decimal
on the line
x_error_2 = Decimal (((x_storage) - (expectation_x))**2).quantize(Decimal('.0001'))
Clearly, I'm doing it wrong.
n = input ("n=")
sum_x = 0
sum_x_2 = 0
sum_x_error_2 = 0
x_storage = [ ]
expectation_x_storage = []
from decimal import Decimal
for i in range (0, n):
from random import *
x = Decimal ((randint(1, 6)*randint(1, 6))).quantize(Decimal('1'))
x_storage.append(x)
x_2 = Decimal (x**2).quantize(Decimal('.01'))
sum_x = sum_x + x
sum_x_2 = sum_x_2 + x_2
expectation_x = Decimal (sum_x / n).quantize(Decimal('.01'))
expectation_x_2 = Decimal (sum_x_2 / n).quantize(Decimal('.01'))
variance_x = Decimal ((expectation_x_2 - (expectation_x)**2)).quantize(Decimal('.01'))
print ("E(X)=")
print (expectation_x)
print ("V(X)=")
print (variance_x)
for i in range (0, n):
expectation_x_storage.append(expectation_x)
print x_storage
print expectation_x_storage
#code is working until the next line
for i in range (0, n):
x_error_2 = Decimal (((x_storage) - (expectation_x))**2).quantize(Decimal('.0001'))
sum_x_error_2 = sum_x_error_2 + x_error_2
standard_deviation_x_2 = Decimal ((sum_x_error_2)/(n-1)).quantize(Decimal('.01'))
print ("Sn2(X)=")
print (standard_deviation_x_2)
Looks that you simply need to take i-th element of x_storage here.
x_error_2 = Decimal (((x_storage[i]) - (expectation_x))**2).quantize(Decimal('.0001'))
Also change identation of the line
standard_deviation_x_2 = Decimal ((sum_x_error_2)/(n-1)).quantize(Decimal('.01'))
To place it outside for-loop. Not sure is it worth mentioning, but in python identation is critical.
Then it should work.
Seems you're using python 2.7? I'd suggest you to not mix style you call print with and without parentheses. Use print(...).
You already have two lists x = [x1,x2,...xn] and y=[y1,y2,...,yn] now z should be z=[(x1-y1)^2,(x2-y2)^2,...,(xn-yn)^2]
You can do it this way:
>>> a=[35.5,36.6,37.7]
>>> b=[12.34,13.89,30.8]
>>> c=[(a[i]-b[i])**2 for i in range(len(a))]
>>> c
[536.3856, 515.7441, 47.61000000000003]
>>>
If you to round those digits you can use round function
>>> c=[round((a[i]-b[i])**2,3) for i in range(len(a))]
>>> c
[536.386, 515.744, 47.61]
>>>
round(x,y) is round number x to y decimal digits
I am trying to do one liner of one challenge in codefights , but I seem to be stuck with:
SyntaxError: Generator expression must be parenthesized if not sole argument
when I execute
def magicNumber(n):
return [i for i in itertools.takewhile
(lambda x: x % d for d in [3,5,7] == 0, range(0,n))]
The challenge is: Consider the numbers the only prime factors of which are 3, 5 and 7. Write a program to find the nth largest among them.
Example output :
For n = 1 the output should be: 1 (3^0 * 5^0 * 7^0).
For n = 2 the output should be: 3 (3^1 * 5^0 * 7^0).
For n = 6 the output should be: 15(3^1 * 5^1 * 7^0).
I know I am far from solving it with this I just want to know what's the problem here.
You need to add the parenthesis:
takewhile(lambda x: (x % d for d in [3,5,7] == 0), range(0,n))
Note that your original code was parsed as:
takewhile((lambda x: x % d) for d in [3,5,7] == 0, range(0,n))
i.e. the parser thought you was creating a generator yielding lambdas as first argument to takewhile. And you are doing a function call to takewhile with two arguments, which requires parenthesis around the generator, so if you really wanted to do that you had to write:
takewhile(((lambda x: x % d) for d in [3,5,7] == 0), range(0,n))
You need to put your generator expression in lambda function in a parenthesis, also I think you need to check the equality of the result of x % d with zero:
lambda x: (x % d==0 for d in [3,5,7])
So, I am using the answer to this question to color some values I have for some polygons to plot to a basemap instance. I modified the function found in that link to be the following. The issue I'm having is that I have to convert the string that it returns to a hex digit to use so that I can color the polygons. But when I convert something like "0x00ffaa" to a python hex digit, it changes it to be "0xffaa", which cannot be used to color the polygon
How can I get around this?
Here is the modified function:
def rgb(mini,maxi,value):
mini, maxi, value = float(mini), float(maxi), float(value)
ratio = 2* (value - mini) / (maxi-mini)
b = int(max(0,255*(1-ratio)))
r = int(max(0,255*(ratio -1)))
g = 255 - b - r
b = hex(b)
r = hex(r)
g = hex(g)
if len(b) == 3:
b = b[0:2] + '0' + b[-1]
if len(r) == 3:
r = r[0:2] + '0' + r[-1]
if len(g) == 3:
g = g[0:2] + '0' + g[-1]
string = r+g[2:]+b[2:]
return string
The answer from cdarke is OK, but using the % operator for string interpolation is kind of deprecated. For the sake of completion, here is the format function or the str.format method:
>>> format(254, '06X')
'0000FE'
>>> "#{:06X}".format(255)
'#0000FF'
New code is expected to use one of the above instead of the % operator. If you are curious about "why does Python have a format function as well as a format method?", see my answer to this question.
But usually you don't have to worry about the representation of the value if the function/method you are using takes integers as well as strings, because in this case the string '0x0000AA' is the same as the integer value 0xAA or 170.
Use string formatting, for example:
>>> "0x%08x" % 0xffaa
'0x0000ffaa'
I have a function that takes two inputs, and will return an array of tuples where the two numbers in a given tuple have the exact same ratio as the two numbers given to the function!
So everything was working fine, but for some reason in some instances, it is not picking up every tuple. Here is an example of it, and I don't know why:
In [52]: def find_r(num1,num2):
....: ratio = num1/float(num2)
....: ratio = 1/ratio
....: my_list = [(a,int(a * ratio)) for a in range(1,num1) if float(a * ratio).is_integer()] #and a * 1/float(ratio) + a <= num1]
....: return my_list
....:
In [53]: find_r(100,364)
Out[53]: [(75, 273)]
so it returned just one tuple, but if you divide both 75 and 273 by 3, you get a tuple of 25 and 91, which have the same ratio! Why did my function not pick up this instance?
If it helps, I do suspect it has something to do with the is_integer() method, but I am not too sure.
Thanks!
It is due to the imprecision of floating point arithmetic:
>>> ((100/364)*364).is_integer()
False
>>> ((25/91)*91).is_integer()
False
Instead of doing what you're doing, you should check for equivalence of fractions by cross-multiplying. That is, given a fraction a/b, to check if it is equivalent to another c/d, check whether ad == bc. This will avoid division and keep everything as integers.
You can do this:
def find_r(num1,num2):
return [(a, a*num2//num1) for a in range(1, num1) if (a*num2) % num1 == 0]
>>> find_r(100, 364)
[(25, 91), (50, 182), (75, 273)]
(There are other ways to accomplish your task, but this is the most similar to your original approach.)
I think that you get the answer you expect
>>> r=100/float(364)
>>> r
0.27472527472527475
>>> r=1/r
>>> r
3.6399999999999997
>>> r*25
90.99999999999999
>>> r*75
273.0
To make your integer check, you can use
if(int(a*ratio) == a*ratio) like in
def find_r(num1,num2):
ratio = num1/float(num2)
ratio = 1/ratio
my_list = [(a,int(a * ratio)) for a in range(1,num1) if int(a * ratio) == a * ratio]
for a in range(1,num1):
if int(a * ratio) == a * ratio:
print a * ratio
return my_list
print find_r(100,364)
I want to swap each pair of characters in a string. '2143' becomes '1234', 'badcfe' becomes 'abcdef'.
How can I do this in Python?
oneliner:
>>> s = 'badcfe'
>>> ''.join([ s[x:x+2][::-1] for x in range(0, len(s), 2) ])
'abcdef'
s[x:x+2] returns string slice from x to x+2; it is safe for odd len(s).
[::-1] reverses the string in Python
range(0, len(s), 2) returns 0, 2, 4, 6 ... while x < len(s)
The usual way to swap two items in Python is:
a, b = b, a
So it would seem to me that you would just do the same with an extended slice. However, it is slightly complicated because strings aren't mutable; so you have to convert to a list and then back to a string.
Therefore, I would do the following:
>>> s = 'badcfe'
>>> t = list(s)
>>> t[::2], t[1::2] = t[1::2], t[::2]
>>> ''.join(t)
'abcdef'
Here's one way...
>>> s = '2134'
>>> def swap(c, i, j):
... c = list(c)
... c[i], c[j] = c[j], c[i]
... return ''.join(c)
...
>>> swap(s, 0, 1)
'1234'
>>>
''.join(s[i+1]+s[i] for i in range(0, len(s), 2)) # 10.6 usec per loop
or
''.join(x+y for x, y in zip(s[1::2], s[::2])) # 10.3 usec per loop
or if the string can have an odd length:
''.join(x+y for x, y in itertools.izip_longest(s[1::2], s[::2], fillvalue=''))
Note that this won't work with old versions of Python (if I'm not mistaking older than 2.5).
The benchmark was run on python-2.7-8.fc14.1.x86_64 and a Core 2 Duo 6400 CPU with s='0123456789'*4.
If performance or elegance is not an issue, and you just want clarity and have the job done then simply use this:
def swap(text, ch1, ch2):
text = text.replace(ch2, '!',)
text = text.replace(ch1, ch2)
text = text.replace('!', ch1)
return text
This allows you to swap or simply replace chars or substring.
For example, to swap 'ab' <-> 'de' in a text:
_str = "abcdefabcdefabcdef"
print swap(_str, 'ab','de') #decabfdecabfdecabf
Loop over length of string by twos and swap:
def oddswap(st):
s = list(st)
for c in range(0,len(s),2):
t=s[c]
s[c]=s[c+1]
s[c+1]=t
return "".join(s)
giving:
>>> s
'foobar'
>>> oddswap(s)
'ofbora'
and fails on odd-length strings with an IndexError exception.
There is no need to make a list. The following works for even-length strings:
r = ''
for in in range(0, len(s), 2) :
r += s[i + 1] + s[i]
s = r
A more general answer... you can do any single pairwise swap with tuples or strings using this approach:
# item can be a string or tuple and swap can be a list or tuple of two
# indices to swap
def swap_items_by_copy(item, swap):
s0 = min(swap)
s1 = max(swap)
if isinstance(item,str):
return item[:s0]+item[s1]+item[s0+1:s1]+item[s0]+item[s1+1:]
elif isinstance(item,tuple):
return item[:s0]+(item[s1],)+item[s0+1:s1]+(item[s0],)+item[s1+1:]
else:
raise ValueError("Type not supported")
Then you can invoke it like this:
>>> swap_items_by_copy((1,2,3,4,5,6),(1,2))
(1, 3, 2, 4, 5, 6)
>>> swap_items_by_copy("hello",(1,2))
'hlelo'
>>>
Thankfully python gives empty strings or tuples for the cases where the indices refer to non existent slices.
To swap characters in a string a of position l and r
def swap(a, l, r):
a = a[0:l] + a[r] + a[l+1:r] + a[l] + a[r+1:]
return a
Example:
swap("aaabcccdeee", 3, 7) returns "aaadcccbeee"
Do you want the digits sorted? Or are you swapping odd/even indexed digits? Your example is totally unclear.
Sort:
s = '2143'
p=list(s)
p.sort()
s = "".join(p)
s is now '1234'. The trick is here that list(string) breaks it into characters.
Like so:
>>> s = "2143658709"
>>> ''.join([s[i+1] + s[i] for i in range(0, len(s), 2)])
'1234567890'
>>> s = "badcfe"
>>> ''.join([s[i+1] + s[i] for i in range(0, len(s), 2)])
'abcdef'
re.sub(r'(.)(.)',r"\2\1",'abcdef1234')
However re is a bit slow.
def swap(s):
i=iter(s)
while True:
a,b=next(i),next(i)
yield b
yield a
''.join(swap("abcdef1234"))
One more way:
>>> s='123456'
>>> ''.join([''.join(el) for el in zip(s[1::2], s[0::2])])
'214365'
>>> import ctypes
>>> s = 'abcdef'
>>> mutable = ctypes.create_string_buffer(s)
>>> for i in range(0,len(s),2):
>>> mutable[i], mutable[i+1] = mutable[i+1], mutable[i]
>>> s = mutable.value
>>> print s
badcfe
def revstr(a):
b=''
if len(a)%2==0:
for i in range(0,len(a),2):
b += a[i + 1] + a[i]
a=b
else:
c=a[-1]
for i in range(0,len(a)-1,2):
b += a[i + 1] + a[i]
b=b+a[-1]
a=b
return b
a=raw_input('enter a string')
n=revstr(a)
print n
A bit late to the party, but there is actually a pretty simple way to do this:
The index sequence you are looking for can be expressed as the sum of two sequences:
0 1 2 3 ...
+1 -1 +1 -1 ...
Both are easy to express. The first one is just range(N). A sequence that toggles for each i in that range is i % 2. You can adjust the toggle by scaling and offsetting it:
i % 2 -> 0 1 0 1 ...
1 - i % 2 -> 1 0 1 0 ...
2 * (1 - i % 2) -> 2 0 2 0 ...
2 * (1 - i % 2) - 1 -> +1 -1 +1 -1 ...
The entire expression simplifies to i + 1 - 2 * (i % 2), which you can use to join the string almost directly:
result = ''.join(string[i + 1 - 2 * (i % 2)] for i in range(len(string)))
This will work only for an even-length string, so you can check for overruns using min:
N = len(string)
result = ''.join(string[min(i + 1 - 2 * (i % 2), N - 1)] for i in range(N))
Basically a one-liner, doesn't require any iterators beyond a range over the indices, and some very simple integer math.
While the above solutions do work, there is a very simple solution shall we say in "layman's" terms. Someone still learning python and string's can use the other answers but they don't really understand how they work or what each part of the code is doing without a full explanation by the poster as opposed to "this works". The following executes the swapping of every second character in a string and is easy for beginners to understand how it works.
It is simply iterating through the string (any length) by two's (starting from 0 and finding every second character) and then creating a new string (swapped_pair) by adding the current index + 1 (second character) and then the actual index (first character), e.g., index 1 is put at index 0 and then index 0 is put at index 1 and this repeats through iteration of string.
Also added code to ensure string is of even length as it only works for even length.
DrSanjay Bhakkad post above is also a good one that works for even or odd strings and is basically doing the same function as below.
string = "abcdefghijklmnopqrstuvwxyz123"
# use this prior to below iteration if string needs to be even but is possibly odd
if len(string) % 2 != 0:
string = string[:-1]
# iteration to swap every second character in string
swapped_pair = ""
for i in range(0, len(string), 2):
swapped_pair += (string[i + 1] + string[i])
# use this after above iteration for any even or odd length of strings
if len(swapped_pair) % 2 != 0:
swapped_adj += swapped_pair[-1]
print(swapped_pair)
badcfehgjilknmporqtsvuxwzy21 # output if the "needs to be even" code used
badcfehgjilknmporqtsvuxwzy213 # output if the "even or odd" code used
One of the easiest way to swap first two characters from a String is
inputString = '2134'
extractChar = inputString[0:2]
swapExtractedChar = extractChar[::-1] """Reverse the order of string"""
swapFirstTwoChar = swapExtractedChar + inputString[2:]
# swapFirstTwoChar = inputString[0:2][::-1] + inputString[2:] """For one line code"""
print(swapFirstTwoChar)
#Works on even/odd size strings
str = '2143657'
newStr = ''
for i in range(len(str)//2):
newStr += str[i*2+1] + str[i*2]
if len(str)%2 != 0:
newStr += str[-1]
print(newStr)
#Think about how index works with string in Python,
>>> a = "123456"
>>> a[::-1]
'654321'