Variance of a list of numbers in python - python

For some reason, my code below isn't giving me the right solution to solve the sample variance of x= [7, 6, 8, 4, 2, 7, 6, 7, 6, 5]. The solution should be 3.067, but I keep getting 11.044 and I have no idea why. Can someone help?
def var_method_0(x):
n = len(x) # Number of samples
mean=sum(x)/n
variance=sum([((mean-i)**2) for i in range(n)])/(n-1)
return variance

Try this:
def var_method(lst):
n = len(lst)
mean = sum(lst) / float(n)
return sum((mean - x) ** 2 for x in lst) / float(n - 1)
I fixed two things:
Making sure that the divisions are returning float values (not a problem in Python 3.x, but could mess things in Python 2.x)
In the line where you calculate the actual variance, you don't want to iterate over the range, but over the actual values of the list of numbers
Apart from that I did a bit of cleaning-up and renaming, to make the code more concise. Now it works as expected:
var_method([7, 6, 8, 4, 2, 7, 6, 7, 6, 5])
=> 3.066666666666667

Related

Is there a way to use setdiff1d on 2D arrays?

I have an assignment to code kfold(n, n_folds) function, which is supposed to work exactly like sklearn.model_selection.KFold: divide list of integers from 1 to n into n % k_folds groups of n // k_folds + 1 elements and n - n % k groups of n // k_folds elements (this part works well & optimized), then for each group get tuple (all integers from 1 to n not being part of the group, the group) My own realization of this last step just hits TL verdict hard (yet outputs correct answers).
def kfold(n, n_folds):
elements = np.arange(0, n)
slices = np.array(np.array_split(elements, n_folds))
ans = []
for slice in slices:
ans.append((np.setdiff1d(elements, slice), slice))
return ans
kfold(10, 3) as example returns:
[([5, 6, 7, 8, 9, 10], [1, 2, 3, 4]), ([1, 2, 3, 4, 8, 9, 10], [5, 6, 7]), ([1, 2, 3, 4, 5, 6, 7], [8, 9, 10])]
I believe the problem is my code is not fully vectorized, employing one cycle instead of numpy methods. I've read documentation of setdiff1d, setxor1d and likewise functions. While they work well dividing a single slice, I cannot see a way to make them execute all the n_folds slices simultaneously. Is there a way to make this functions work? If there is a nice alternative solution, I'd like to hear about it too

Trying to produce a Random list of single digit integers which are not repeated. Getting only 5 instead of 9 [duplicate]

This question already has answers here:
Random number generator, how to get random numbers that are not the same
(2 answers)
Closed 6 years ago.
Here is my code
from random import randint
SudList = []
numbers = [1,2,3,4,5,6,7,8,9]
for i in numbers:
SudList.append(numbers[randint(0,len(numbers)-1)])
print("Sudlist-" + str(SudList))
numbers.remove(SudList[-1])
print("numbers-" + str(numbers))
print(SudList)
I expected this code to return something like this- (the final SudList)
[9,7,2,8,6,4,5,3,1]
But Instead it Returns something like this -
[9,4,6,7,2]
Here is the whole output-
Sudlist-[5]
numbers-[1, 2, 3, 4, 6, 7, 8, 9]
Sudlist-[5, 1]
numbers-[2, 3, 4, 6, 7, 8, 9]
Sudlist-[5, 1, 9]
numbers-[2, 3, 4, 6, 7, 8]
Sudlist-[5, 1, 9, 3]
numbers-[2, 4, 6, 7, 8]
Sudlist-[5, 1, 9, 3, 4]
numbers-[2, 6, 7, 8]
[5, 1, 9, 3, 4]
Press any key to quit
How do i correct my code?
You can use shuffle. It's will meet your needs.
import random
random.shuffle(numbers)
output
[7, 4, 3, 2, 1, 8, 6, 5, 9]
If you wish to stick with this piece of code, simply use i in range len(numbers) instead of i in numbers. Your remove statement is reducing the length of numbers and thus, the number of numbers printed is always (len(numbers)+1)/2
from random import randint
SudList = []
numbers = [1,2,3,4,5,6,7,8,9]
for i in range(len(numbers)):
SudList.append(numbers[randint(0,len(numbers)-1)])
print("Sudlist-" + str(SudList))
numbers.remove(SudList[-1])
print("numbers-" + str(numbers))
print(SudList)
If you want to stay with your implementation just change:
for i in numbers:
To:
for i in range(len(numbers)):
So you don't iterate over the list that changes
As has been mentioned, shuffle is the quickest and most readable solution.
import random
numbers = [1,2,3,4,5,6,7,8,9]
random.shuffle(numbers)
print(numbers)
However, it looks like you're wanting to see the state of each list at every step, so if you're looking for a custom implementation, you could also try the following:
from random import randint
Sudlist = []
numbers = [1,2,3,4,5,6,7,8,9]
while len(numbers) > 0:
index = randint(0, len(numbers) - 1)
Sudlist.append(numbers.pop(index))
print('Sudlist-' + str(Sudlist))
print('numbers-' + str(numbers))
print(Sudlist)

Write the digits of a number into an array

I want to calculate with seperated digits of a very long number. How can I do this in Python2.7? I thought about somehow write the digits in an array so that I can access the digits with array(x):
number = 123456789123456789
array = [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]
The problem is, that the number has so many digits, that it would take very long to do that manually. So how can I do this automatically?
You can use map, int and str functions like this
print map(int, str(number))
str function converts the number to a string.
map function applies the int function to each and every element of stringifed number, to convert the string to an integer.
Output
[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9]
If you are doing this again and again, like in a loop, then list comprehension will be faster than the map approach
number = 123456789123456789
from timeit import timeit
print timeit("map(int, str(number))", "from __main__ import number")
print timeit("[int(dig) for dig in str(number)]", "from __main__ import number")
Output on my machine
12.8388962786
10.7739010307
You can also use a list comprehension link this.
array = [int(x) for x in str(number)]
As an alternative, the purely mathematical solution is below. By repeatedly dividing by 10 and taking the remainder you can extract each digit.
n = 123456789123456789
result = []
while n != 0:
n, d = divmod(n, 10)
result.append(int(d))
result.reverse()
print result # [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9]
You can simply iterate over each digit in number and push into an array. Try this
result = []
for d in str(number):
result.append (int(d))
print result

Contracting in python

I'm supposed to write a program that contracts a list. For example:
[1, 3, 4, 5, 1, 8, 6,]
has to be contracted into a list that looks like this:
[1, 5, 1, 8, 6, 6]
I don't have a clue on how to do this and was hoping that any of you could help me.
I'm given a list that looks like this l1 = [1, 3, 9, 1, 2, 7, 8] and i'm supposed to contract the list into a new list which consist of the old lists nondecending segments extremities. It is supposed to work with any list given.
Let me try to understand the question:
im given a list that looks like this l1 = [1, 3, 9, 1, 2, 7, 8] and im
supposed to contract the list by taking the first number then the next
bigest and the smallest after that and then the biggest again. This is
a school assignment and i have no idea on how to do this. english
isn't my first language and it's realy difficult to explain the
assignment :/
I supposed that "biggest" and "smallest" refer to local maxima and minima. So a number at index i is "biggest" if l[i-1] < l[i] and l[i] > l[i+1]. "Smallest" the other way around. So basically your are searching for the extrema of a function N -> N.
If this is what you want, this should help (considering that start and end points always are extrema):
#! /usr/bin/python3.2
def sign(x): return 0 if not x else x // abs(x)
def extrema (l):
return [l[0]] + [e for i, e in enumerate(l[:-1]) if i and sign(e-l[i-1])==sign(e-l[i+1])] + [l[-1]]
l1 = [1, 3, 9, 1, 2, 7, 8]
print (extrema (l1))

List and Integer Python

I am trying to write a code that changes the position of an integer inside a list (basically swaps the position with another integer)
I have tried to use all logic, but still can't understand why my code is messing up:
SpecialNum = 10
def number_move(move_number):
for elements in range(len(move_number)):
if ( SpecialNum != move_number[-1]):
x = move_number.index(SpecialNum)
y = move_number.index(SpecialNum)+1
move_number[y], move_number[x] = move_number[x], move_number[y]
return (move_number)
the output should be:
[1,2,3,10,4,5,6]
>>>[1,2,3,4,10,5,6]
but output comes as:
[1,2,3,4,5,6,10]
Assuming your actual indentation looks like this:
SpecialNum = 10
def number_move(move_number):
for elements in range(len(move_number)):
if ( SpecialNum != move_number[-1]):
x = move_number.index(SpecialNum)
y = move_number.index(SpecialNum)+1
move_number[y], move_number[x] = move_number[x], move_number[y]
return move_number
… the problem is that you're swapping the 10 to the right over and over in a loop, until it reaches the very end.
If that isn't what you want, why do you have the for elements in range(len(move_number)) in the first place? Just take it out, and it will only get swapped right once.
As a side note, you rarely need range(len(eggs)); you can just do for egg in eggs (or, if you need the index along with the actual object, for index, egg in enumerate(eggs)).
Also, you've got a whole lot of extra parentheses that aren't needed, and make the code harder to read.
Meanwhile, every call to index has to search the entire list to find your object's position; if you already know the position, it's better to just use it. Not only is it a lot faster, and simpler, it's also more robust—if there are two elements of the list with the same value, index can only find the first one. In your case, there's no obvious way around using index, but at least you can avoid calling it twice.
Putting that together:
SpecialNum = 10
def number_move(move_number):
x = move_number.index(SpecialNum)
y = x + 1
if y != len(move_number):
move_number[y], move_number[x] = move_number[x], move_number[y]
Finally, I said there's no obvious way around using index… but is there a non-obvious way? Sure. If you're going to call index repeatedly on the same object, we can make the last-found index part of the interface to the function, or we can even store a cache inside the function. The simplest way to do this is to turn the whole thing into a generator. A generator that mutates its arguments can be kind of confusing, so let's make it return copies instead. And finally, to make it customizable, let's take a parameter so you can specify a different SpecialNum than 10.
SpecialNum = 10
def number_move(move_number, special_num=SpecialNum):
for x, element in reversed(list(enumerate(move_number))):
if element == special_num:
while x+1 < len(move_number):
move_number = (move_number[:x] +
[move_number[x+1], move_number[x]] +
move_number[x+2:])
yield move_number
x += 1
Now, it'll move all of the 10s to the end, one step at a time. Like this:
>>> n = [1, 10, 2, 3, 10, 4, 5, 6]
>>> for x in number_move(n):
... print(x)
[1, 10, 2, 3, 4, 10, 5, 6]
[1, 10, 2, 3, 4, 5, 10, 6]
[1, 10, 2, 3, 4, 5, 6, 10]
[1, 2, 10, 3, 4, 5, 6, 10]
[1, 2, 3, 10, 4, 5, 6, 10]
[1, 2, 3, 4, 10, 5, 6, 10]
[1, 2, 3, 4, 5, 10, 6, 10]
[1, 2, 3, 4, 5, 6, 10, 10]
[1, 2, 3, 4, 5, 6, 10, 10]
You don't need the for loop :)
def number_move(move_number):
x = move_number.index(SpecialNum)
y = move_number.index(SpecialNum)+1
move_number[y], move_number[x] = move_number[x], move_number[y]
Alternative:
>>> def number_move(m, i):
num = m.pop(i)
m.insert(i+1, num)
return m
>>> l = number_move([1,2,3,10,4,5,6], 3)
>>> l
[1, 2, 3, 4, 10, 5, 6]

Categories

Resources