I have one list
a = [1.0, 2.0, 2.1, 3.0, 3.1, 4.2, 5.1, 7.2, 9.2]
I want to compare this list with other list but also I want to extract the information regarding the list content in numeric order.All other list have the elements that are same as a.
So I have tried this
a = [1.0, 2.0, 2.1, 3.0, 3.1, 4.2, 5.1, 7.2, 9.2]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print dict(zip(a,b))
a1=[2.1, 3.1, 4.2, 7.2]
I want to compare a1 with a and extract dict values [3, 5, 6, 8].
Just loop through a1 and see if there is a matching key in the dictionary you created:
mapping = dict(zip(a, b))
matches = [mapping[value] for value in a1 if value in mapping]
Demo:
>>> a = [1.0, 2.0, 2.1, 3.0, 3.1, 4.2, 5.1, 7.2, 9.2]
>>> b = [1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a1 = [2.1, 3.1, 4.2, 7.2]
>>> mapping = dict(zip(a, b))
>>> [mapping[value] for value in a1 if value in mapping]
[3, 5, 6, 8]
However, take into account that you are using floating point numbers. You may not be able to match values exactly, since floating point numbers are binary approximations to decimal values; the value 2.999999999999999 (15 nines) for example, may be presented by the Python str() function as 3.0, but is not equal to 3.0:
>>> 2.999999999999999
2.999999999999999
>>> str(2.999999999999999)
'3.0'
>>> 2.999999999999999 == 3.0
False
>>> 2.999999999999999 in mapping
False
If your input lists a is sorted, you could use the math.isclose() function (or a backport of it), together with the bisect module to keep matching efficient:
import bisect
try:
from math import isclose
except ImportError:
def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
# simplified backport, doesn't handle NaN or infinity.
if a == b: return True
return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
result = []
for value in a1:
index = bisect.bisect(a, value)
if index and isclose(a[index - 1], value):
result.append(b[index - 1])
elif index < len(a) and isclose(a[index], value):
result.append(b[index])
This tests up to two values from a per input value; one that is guaranteed to equal or lower (at index - 1) and the next, higher value. For your sample a, the value 2.999999999999999 is bisected to index 3, between 2.1 and 3.0. Since isclose(3.0, 2.999999999999999) is true, that would still let you map that value to 4 in b.
Related
I need to write a function called var_fun that returns the variance of the list and testing with 2 lists. I have to return the standard deviation of each element actually.
list_1 = [8, 8, 3, 5, 5, 8, 1, 4, 8, 6, 3, 10, 9]
list_2 = [8, 12, 3, 5, 5, 8, 1, 4, 8, 3, 10, 9]
This is the code that I did but it returns <function var_func at 0x7f462679ad08>
How can I solve this?
def var_fun(x):
for i in x:
var = ((i - mean_fun(x))**2)
return var_fun
print(var_fun(list_1))
print(var_fun(list_2))
This is my mean_fun:
def mean_fun(values) :
length = len(values)
total_sum = 0
for i in range(length):
total_sum += values[i]
average = (total_sum/length)
return round(average, 2)
print(mean_fun(list_1))
print(mean_fun(list_2))
The output should look like this:
[25.0, 9.0, 9.0, 4.0, 1.0, 1.0, 0.0, 4.0, 4.0, 4.0, 4.0, 9.0, 16.0]
[28.41, 11.09, 11.09, 5.43, 1.77, 1.77, 2.79, 2.79, 2.79, 7.13, 13.47, 32.15]
In function var_fun(), return var instead of var_fun. That should solve the problem.
You get the error because you are trying to return the function itself.
Also, these lines don't make any sense. You can remove them:
mean_fun = list_1
mean_fun = list_2
Better Alternative:
https://numpy.org/doc/stable/reference/generated/numpy.var.html
https://numpy.org/doc/stable/reference/generated/numpy.mean.html
Have a look at the above numpy functions which does the job of directly calculating the mean and variance.
Say I got a list like this:
list = [1, 2.1, 3.3, 4.5, 3.2, 4.7, 1, 3, 3.3, 3.9, 4.9]
Now everytime the subsequent element in the list is less than the preceding element, i.e. list[i] < list[i-1] I want to add multiples of say 10 in ascending order to all the elements from this point until the next point where the condition is met. The resulting list for the example above should look like this:
new_list = [1, 2.1, 3.3, 4.5, 13.2, 14.7, 21, 23, 23.3, 23.9, 24.9]
So first 10 is added, then 20...
I'll mention that the length of each intervall is abritrarily long.
How could i achieve that elegantly? I did what I wanted by using the list as a temporary list and appending to a new list through a for and if loop but that seems rather ugly. I thought of doing it with list comprehension but I cannot figure out how this would work.
This can be done using the numpy package. The idea is to first determine the positions where a the next value is lower. Then you do a cumulative sum and multiply this by 10. Finally you add this back to the original list.
import numpy as np
a = [1, 2.1, 3.3, 4.5, 3.2, 4.7, 1, 3, 3.3, 3.9, 4.9]
b = [0] + [int(a[i+1] < a[i]) for i in range(len(a)-1)]
aa = np.array(a)
ba = np.array(b).cumsum() * 10
print(aa + ba)
>>> [ 1. 2.1 3.3 4.5 13.2 14.7 21. 23. 23.3 23.9 24.9]
list1 = [1, 2.1, 3.3, 4.5, 3.2, 4.7, 1, 3, 3.3, 3.9, 4.9]
for i in range(len(list1)):
while True:
try:
if list1[i] > list1[i+1]:
list1[i+1] = list1[i+1] + 10
else:
break
except:
print("Done")
break
print(list1)
print("Final List: ")
print(list1)
I have a list of values: [0,2,3,5,6,7,9] and want to get a list of the numbers in the middle in between each number: [1, 2.5, 4, 5.5, 6.5, 8]. Is there a neat way in python to do that?
It's a simple list comprehension (note I'm asuming you want all your values as floats rather than a mixture of ints and floats):
>>> lst = [0,2,3,5,6,7,9]
>>> [(a + b) / 2.0 for a,b in zip(lst, lst[1:])]
[1.0, 2.5, 4.0, 5.5, 6.5, 8.0]
(Dividing by 2.0 ensure floor division is not applied in Python 2)
Use a for loop:
>>> a = [0,2,3,5,6,7,9]
>>> [(a[x] + a[x + 1])/2 for x in range(len(a)-1)]
[1.0, 2.5, 4.0, 5.5, 6.5, 8.0]
However using zip as #Chris_Rands said is better... (and more readable ¬¬)
Obligatory itertools solution:
>>> import itertools
>>> values = [0,2,3,5,6,7,9]
>>> [(a+b)/2.0 for a,b in itertools.izip(values, itertools.islice(values, 1, None))]
[1.0, 2.5, 4.0, 5.5, 6.5, 8.0]
values = [0,2,3,5,6,7,9]
middle_values = [(values[i] + values[i + 1]) / 2.0 for i in range(len(values) - 1)]
Dividing by 2.0 rather than 2 is unnecessary in Python 3, or if you use from __future__ import division to change the integer division behavior.
The zip or itertools.izip answers are more idiomatic.
Simple for loop:
nums = [0,2,3,5,6,7,9]
betweens = []
for i in range(1, len(nums)):
if nums[i] - nums[i-1] > 1:
betweens.extend([item for item in range(nums[i-1]+1, nums[i])])
else:
betweens.append((nums[i] + nums[i-1]) / 2)
Output is as desired, which doesn't need further conversion (in Python3.x):
[1, 2.5, 4, 5.5, 6.5, 8]
[(l[i]+l[i+1])/2 for i in range(len(l)-1)]
Hi I have a list of numbers with some 'None''s in them that I want to replace with other numbers in the list that are not 'None'.
For example, for the list below:
listP = [ 2.5, 3, 4, None, 4, 8.5, None, 7.3]
I want the two None items to be replaced with random numbers in the list that are not themselves a None. So in this example the None could be replaced by 2.5 or 3 or 4 or 8.5 or 7.3.
Is there anyway to do this in one line of code?
You'll need to use two steps; extract the non-None values for random.choice() to pick from, then use a list comprehension to actually pick the random values:
import random
numbers = [n for n in listP if n is not None]
result = [n if n is not None else random.choice(numbers) for n in listP]
You can filter the list first to construct a list of not-None values and then randomly choose from it using choice:
import random
listP = [ 2.5, 3, 4, None, 4, 8.5, None, 7.3]
listR = filter(lambda x: x is not None, listP)
print([l if l is not None else random.choice(listR) for l in listP])
result:
[2.5, 3, 4, 7.3, 4, 8.5, 4, 7.3]
Use list comprehensions
>>> [x if x else 'WHATEVER' for x in [ 2.5, 3, 4, None, 4, 8.5, None, 7.3]]
[2.5, 3, 4, 'WHATEVER', 4, 8.5, 'WHATEVER', 7.2999999999999998]
You could use the following:
import random
listP = [2.5, 3, 4, None, 4, 8.5, None, 7.3]
numbers = [num for num in listP if num is not None]
answer = [el if el is not None else random.choice(numbers) for el in listP]
print(answer)
Sample Output
[2.5, 3, 4, 3, 4, 8.5, 8.5, 7.3]
This creates a numbers list by filtering out the None values from listP. It then uses a list comprehension with random.choice() to fill None values with a random choice from numbers.
Get any value from a list except None. I use max function to get this.
Check max value is not None
Use list comprehension to create new list which replace None value with max value.
Demo:
>>> listP = [ 2.5, 3, 4, None, 4, 8.5, None, 7.3]
>>> l_max = max(listP)
>>> if l_max:
... listP = [n if n is not None else max(listP) for n in listP]
...
>>> listP
[2.5, 3, 4, 8.5, 4, 8.5, 8.5, 7.3]
>>>
max is inbuilt function.
List Comprehension
I have a dictionary.
{1 : [1.2, 2.3, 4.9, 2.0], 2 : [4.1, 5.1, 6.3], 3 : [4.9, 6.8, 9.5, 1.1, 7.1]}
I want to pass each key:value pair to an instance of matplotlib.pyplot as two lists: x values and y values.
Each key is an x value associated with each item in its value.
So I want two lists for each key:
[1,1,1,1] [1.2,2.3,4.9,2.0]
[2,2,2] [4.1,5.1,6.3]
[3,3,3,3,3] [4.9,6.8,9.5,1.1,7.1]
Is there an elegant way to do this?
Or perhaps there is a way to pass a dict to matplotlib.pyplot?
for k, v in dictionary.iteritems():
x = [k] * len(v)
y = v
pyplot.plot(x, y)
d = {1 : [1.2, 2.3, 4.9, 2.0], 2 : [4.1, 5.1, 6.3], 3 : [4.9, 6.8, 9.5, 1.1, 7.1]}
res = [([x]*len(y), y) for x, y in d.iteritems()]
res will be a list of tuples, where the first element in the tuple is your list of x-values and second element in the tuple is your list f y-values
Maybe something like:
d = {1 : [1.2, 2.3, 4.9, 2.0], 2 : [4.1, 5.1, 6.3], 3 : [4.9, 6.8, 9.5, 1.1, 7.1]}
result = []
for key, values in d.items():
result.append(([key]*len(values), values))
Use this list comprehension:
[([k]*len(v), v) for k, v in D.iteritems()]
Here's an example of it being used:
>>> from pprint import pprint
>>> D = {1: [1.2, 2.3, 4.9, 2.0], 2: [4.1, 5.1, 6.3], 3: [4.9, 6.8, 9.5, 1.1, 7.1]}
>>> LL = [([k]*len(v), v) for k, v in D.iteritems()]
>>> pprint(LL)
[([1, 1, 1, 1], [1.2, 2.2999999999999998, 4.9000000000000004, 2.0]),
([2, 2, 2], [4.0999999999999996, 5.0999999999999996, 6.2999999999999998]),
([3, 3, 3, 3, 3],
[4.9000000000000004,
6.7999999999999998,
9.5,
1.1000000000000001,
7.0999999999999996])]
As a list comprehension:
r = [([k]*len(v), v) for k,v in d.items()]
If your dictionary is very large, you'd want to use a generator expression:
from itertools import repeat
r = ((repeat(k, len(v)), v) for k,v in d.iteritems())
...though note that using repeat means that the first item in each tuple the generator returns is itself a generator. That's unnecessary if the dictionary's values don't themselves have many items.
>>> d = {1 : [1.2, 2.3, 4.9, 2.0], 2 : [4.1, 5.1, 6.3], 3 : [4.9, 6.8, 9.5, 1.1, 7.1]}
>>> result = [ ([k] * len(d[k]), d[k]) for k in d.keys() ]
>>> print result
[([1, 1, 1, 1], [1.2, 2.2999999999999998, 4.9000000000000004, 2.0]), ([2, 2, 2],
[4.0999999999999996, 5.0999999999999996, 6.2999999999999998]), ([3, 3, 3, 3, 3],
[4.9000000000000004, 6.7999999999999998, 9.5, 1.1000000000000001, 7.0999999999999996])]
I guess that a wizard will put something nicer, but I would do something like:
map(lambda x: ([x]*len(a[x]),a[x]),a)
for a tuple, or
map(lambda x: [[x]*len(a[x]),a[x]],a)
for a list.
btw: a is the dictionary, of course!
I assume that you work with the 2.x series...
Regards
the map function in python will allow this
x = [1,2,4]
y = [1,24,2]
c = zip(x,y)
print c
d = map(None,x,y)
print d
check it out. This will give you
[(1, 1), (2, 24), (4, 2)]
In the case of zip(), if one of the lists are smaller then the others, values will be truncated:
x = [1,2,4]
a = [1,2,3,4,5]
c = zip(x,a)
print c
d = map(None,x,a)
print d
[(1, 1), (2, 2), (4, 3)]
[(1, 1), (2, 2), (4, 3), (None, 4), (None, 5)]