I would like to create some basic statistics for several lists of data and store them in a dictionary:
>>> from statistics import mean,median
>>> a,b,c=[1,2,3],[4,5,6],[7,8,9]
The following list comprehension works and outputs stats for "a":
>>> [eval("{}({})".format(op,a)) for op in ['mean','median','min','max']]
[2, 2, 1, 3]
Assigning the list's variable name (a) to another object (dta) and evaluating "dta" in a list comprehension also works:
>>> dta="a"
>>> [eval("{}({})".format(op,eval("dta"))) for op in ['mean','median','min','max']]
[2, 2, 1, 3]
But when I try to tie this all together in a dictionary comprehension, it does not work:
>>> {k:[eval("{}({})".format(op,eval("k"))) for op in ['mean','median','min','max']] for k in ['a','b','c']}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <dictcomp>
File "<stdin>", line 1, in <listcomp>
File "<string>", line 1, in <module>
NameError: name 'k' is not defined
My guess is that the eval is processed before the comprehension, which is why 'k' is not yet defined? Any suggestions for how to get this work or a different routine that would accomplish the same output?
Do not quote the k in the inner eval:
{k:[eval("{}({})".format(op,eval(k))) for op in ['mean','median','min','max']] for k in ['a','b','c']}
^
Or drop eval altogether:
[[mean(k), median(k), min(k), max(k)] for k in [a, b, c]]
You can do a simple workaround with the keys to change this to a dictionary comprehension.
Try removing the quotation marks around k in your call to eval in the format function.
I ran the following commands:
> from statistics import mean,median
> a,b,c=[1,2,3],[4,5,6],[7,8,9]
> {k:[eval("{}({})".format(op,eval(k))) for op in ['mean','median','min','max']] for k in ['a','b','c']}
and got the following output:
{'a': [2.0, 2, 1, 3], 'c': [8.0, 8, 7, 9], 'b': [5.0, 5, 4, 6]}
Related
I'm trying to write a higher order function that will take 2 lambda expressions and a list and will return the result. I have my code below.
#Square
square = lambda x:x ** 2
#Mod_2
mod_2 = lambda x:x % 2
def map(f,x):
return f(x)
It looks very simple, and should be. This is the error I get:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "main.py", line 8, in map
return f(x)
File "main.py", line 2, in <lambda>
square = lambda x:x ** 2
TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'
Here's what the results should be:
>>> map(square, [1, 2, 3, 4])
[1, 4, 9, 16]
>>> map(square, [])
[]
>>> map(mod_2, range(1, 11))
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
This is NOT homework, and is simply and way to understand higher order functions better. Also, this is not a repeat of any other submission because this is fixing MY code, not how to do the problem itself. If it needs rethinking, please reply and tell me how. Thank you!
Use a list comprehension:
def map(f,x):
return [f(i) for i in x]
You can use a lambda here too:
map = lambda f, x: [f(i) for i in x]
Or just use the map() built-in.
map() is a built-in function. Why are you redefining it? Delete def map().
#Square
square = lambda x: x**2
#Mod_2
mod_2 = lambda x:x % 2
r1 = list(map(square, [1, 2, 3, 4]))
r2 = list(map(mod_2, range(1, 11)))
I've looked at another post with this heading but I'm puzzled because my values are already integers. I want the script to look at each key's values (an array with multiple values), sort the array by making it a list, and then iterate through the sorted and converted list's values subtracting the first from the second, then the second from the third, and so on, storing the differences in a list.
b = {"a":[5,2,1],"b":[8,4,3]}
for k in b.values():
eVals = []
#print listVals
x = 0
for i in sorted(k):
dif = i[x+1] - i[x]
print dif
eVals.append(dif)
x +=1
Here is the error:
Traceback (most recent call last):
File "C:\Python27\ArcGIS10.2\Lib\site-packages\pythonwin\pywin\framework\scriptutils.py", line 323, in RunScript
debugger.run(codeObject, __main__.__dict__, start_stepping=0)
File "C:\Python27\ArcGIS10.2\Lib\site-packages\pythonwin\pywin\debugger\__init__.py", line 60, in run
_GetCurrentDebugger().run(cmd, globals,locals, start_stepping)
File "C:\Python27\ArcGIS10.2\Lib\site-packages\pythonwin\pywin\debugger\debugger.py", line 654, in run
exec cmd in globals, locals
File "N:\Python\test_dict.py", line 1, in <module>
b = {"a":[5,2,1],"b":[8,4,3]}
TypeError: 'int' object has no attribute '__getitem__'
>>> b = {"a":[5,2,1],"b":[8,4,3]}
>>> for key, value in b.iteritems():
... value.sort()
... value[:] = [cur-prev for cur, prev in zip(value, [0] + value[:-1])]
...
>>> b
{'a': [1, 1, 3], 'b': [3, 1, 4]}
If you have numpy conveniently available, you can do this in a one-liner comprehension:
>>> import numpy as np
>>> b = {"a":[5,2,1],"b":[8,4,3]}
>>> {k: np.diff([0] + sorted(v)) for k, v in b.iteritems()}
{'a': array([1, 1, 3]), 'b': array([3, 1, 4])}
You try to use __getitem__ on an int.
Here's a possible solution
inp = {"a":[5,2,1],"b":[8,4,3]}
out = {}
for key, lis in inp.iteritems():
difLis = []
sLis = sorted(lis)
for i, _ in enumerate(sLis[:-1]):
dif = sLis[i+1] - sLis[i]
print "%d - %d = %d" % (sLis[i+1], sLis[i], dif)
difLis.append(dif)
out[key] = difLis
print out # {'a': [1, 3], 'b': [1, 4]}
I'm attempting to try a simple command on the command line,
dict(zip(ascii_lowercase, range(4)))
expecting to get
{'a': 0, 'b': 1, 'c': 2, 'd': 3}
but I keep getting the error
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'ascii_lowercase' is not defined
What am I missing here?
ascii_lowercase is a value provided by the string module. To use it unqualified, you must have previously imported it via:
from string import ascii_lowercase
Why zip with range when you can enumerate?
from string import ascii_lowercase
print {b:a for a,b in enumerate(ascii_lowercase[:4])}
Output:
{'a': 0, 'b': 1, 'c': 2, 'd': 3}
You can also import the string module, and apply your own function using string.ascii_lowercase:
Test
import string
print(dict(zip(string.ascii_lowercase, range(4))))
Output
{'a': 0, 'b': 1, 'c': 2, 'd': 3}
I could be completely wrong here with how to go about this, but basically I need to at first create a dictionary of names with empty lists of values for a race.
contestants = {[("Alice", []),("Dennis", []), ("Bob", []), ("Eva", []), ("Clare", [])]}
I'm assuming that is it how I do it ^^
and then I need to be able to append the values to the empty lists and sort the the positions based upon the overall score.
{'Dennis': [4, 4, 4, 4, 4, 5], 'Alice': [2, 2, 2, 1, 1, 2], 'Bob': [3, 3, 3, 3, 2, 1], 'Eva': [5, 5, 5, 5, 3, 3], 'Clare': [1, 1, 1, 2, 5, 4]}
Above are the score that each player has had and it has also been sorted for them.
def seriesscores(racescores):
contestants = {[("Alice", []),("Dennis", []), ("Bob", []), ("Eva", []), ("Clare", [])]}
contestants.append(racescores[1])
return contestants
I have currently been testing this code above and it keep displaying a error like this:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in seriesscores
TypeError: unhashable type: 'list'
All I'm looking for right now is a way to append the scores to the empty lists, I assume I could just sort it then with this code:
return sorted(contestants, key=lambda x: (sum(x[1])))
Am I on the correct track?
Try this:
contestants = {"Alice": [], "Dennis": [], "Bob": [], "Eva": [], "Clare": []}
Instead of this:
contestants = {[("Alice", []),("Dennis", []), ("Bob", []), ("Eva", []), ("Clare", [])]}
Also, what exactly is in racescores argument? I guess you may want to do something like this:
for key, value in enumerate(racescores):
contestants[key] += value
But I am guessing and without data format in racescores I can't really help you more.
When I define a dictionary which use list as key
collections.defaultdict(list)
When I print it out, it shows itself is using tuple as key.
May I know why?
import collections
tuple_as_dict_key = collections.defaultdict(tuple)
tuple_as_dict_key['abc', 1, 2] = 999
tuple_as_dict_key['abc', 3, 4] = 999
tuple_as_dict_key['abc', 5, 6] = 888
# defaultdict(<type 'tuple'>, {('abc', 5, 6): 888, ('abc', 1, 2): 999, ('abc', 3, 4): 999})
print tuple_as_dict_key
list_as_dict_key = collections.defaultdict(list)
list_as_dict_key['abc', 1, 2] = 999
list_as_dict_key['abc', 3, 4] = 999
list_as_dict_key['abc', 5, 6] = 888
# defaultdict(<type 'list'>, {('abc', 5, 6): 888, ('abc', 1, 2): 999, ('abc', 3, 4): 999})
# Isn't it should be defaultdict(<type 'list'>, {['abc', 5, 6]: 888, ...
print list_as_dict_key
The parameter to defaultdict is not the type of the key, it is a function that creates default data. Your test cases don't exercise this because you're filling the dict with defined values and not using any defaults. If you were to try to get the value list_as_dict_key['abc', 7, 8] it would return an empty list, since that is what you defined as a default value and you never set the value at that index.
When you're adding values to your dictionary you're doing it the same way in both cases and they're treated as a tuple. What you're passing to the constructor is the default value for any keys that are not present. Your default value in this case happens to be of type "type", but that has absolutely nothing to do with how other keys are treated.
There's a nice article explaining the answer to why you can't use a list as key here.
Dictionary keys can only be immutable types. Since a list is a mutable type it must be converted to an immutable type such as a tuple to be used as a dictionary key, and this conversion is being done automatically.
defaultdict is not setting the key as a list. It's setting the default value.
>>> from collections import defaultdict
>>> d1 = collections.defaultdict(list)
>>> d1['foo']
[]
>>> d1['foo'] = 37
>>> d1['foo']
37
>>> d1['bar']
[]
>>> d1['bar'].append(37)
>>> d1['bar']
[37]
The way that you're getting a tuple as the key type is normal dict behaviour:
>>> d2 = dict()
>>> d2[37, 19, 2] = [14, 19]
>>> d2
{(37, 19, 2): [14, 19]}
The way Python works with subscripting is that a is a, a, b is a tuple, a:b is a slice object. See how it works with a list:
>>> mylist = [1, 2, 3]
>>> mylist[4, 5]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: list indices must be integers, not tuple
It's taken 4, 5 as a tuple. The dict has done the same.