Turning weekly to monthly data in Python dictionary - python-2.7

I'm trying to turn this dictionary:
dic = {'2007-10-21': '53', '2007-10-28': '50', '2007-11-05': '100','2007-11-06': '99'}
Into something like this:
dic = {'2007-10': '103', '2007-11': '199'}
Since I need to do that in scale, pythonly speaking I need to sum all the values which its keys start with the same 7 characters.

Try this,
__author__ = 'Fawzan'
dic = {'2007-10-21': '53', '2007-10-28': '50', '2007-11-05': '100', '2007-11-06': '99'}
# create a new dictionary
newDic = {}
# iterate the old dictionary
for key in dic:
# get the desiresd string for comparision
k = key[0:7]
# for debug
print(k)
# if the key is already in the new dictionary, then add the value to existing key
if (k in newDic):
newDic[k] += float(dic[key])
# else append the key, value
else:
newDic[k] = float(dic[key])
# print and check the answer :)
print(newDic)

Related

Python 2.7 create a dictionary from dotted values [duplicate]

I'm trying to programmatically set a value in a dictionary, potentially nested, given a list of indices and a value.
So for example, let's say my list of indices is:
['person', 'address', 'city']
and the value is
'New York'
I want as a result a dictionary object like:
{ 'Person': { 'address': { 'city': 'New York' } }
Basically, the list represents a 'path' into a nested dictionary.
I think I can construct the dictionary itself, but where I'm stumbling is how to set the value. Obviously if I was just writing code for this manually it would be:
dict['Person']['address']['city'] = 'New York'
But how do I index into the dictionary and set the value like that programmatically if I just have a list of the indices and the value?
Python
Something like this could help:
def nested_set(dic, keys, value):
for key in keys[:-1]:
dic = dic.setdefault(key, {})
dic[keys[-1]] = value
And you can use it like this:
>>> d = {}
>>> nested_set(d, ['person', 'address', 'city'], 'New York')
>>> d
{'person': {'address': {'city': 'New York'}}}
I took the freedom to extend the code from the answer of Bakuriu. Therefore upvotes on this are optional, as his code is in and of itself a witty solution, which I wouldn't have thought of.
def nested_set(dic, keys, value, create_missing=True):
d = dic
for key in keys[:-1]:
if key in d:
d = d[key]
elif create_missing:
d = d.setdefault(key, {})
else:
return dic
if keys[-1] in d or create_missing:
d[keys[-1]] = value
return dic
When setting create_missing to True, you're making sure to only set already existing values:
# Trying to set a value of a nonexistent key DOES NOT create a new value
print(nested_set({"A": {"B": 1}}, ["A", "8"], 2, False))
>>> {'A': {'B': 1}}
# Trying to set a value of an existent key DOES create a new value
print(nested_set({"A": {"B": 1}}, ["A", "8"], 2, True))
>>> {'A': {'B': 1, '8': 2}}
# Set the value of an existing key
print(nested_set({"A": {"B": 1}}, ["A", "B"], 2))
>>> {'A': {'B': 2}}
Here's another option:
from collections import defaultdict
recursivedict = lambda: defaultdict(recursivedict)
mydict = recursivedict()
I originally got this from here: Set nested dict value and create intermediate keys.
It is quite clever and elegant if you ask me.
First off, you probably want to look at setdefault.
As a function I'd write it as
def get_leaf_dict(dct, key_list):
res=dct
for key in key_list:
res=res.setdefault(key, {})
return res
This would be used as:
get_leaf_dict( dict, ['Person', 'address', 'city']) = 'New York'
This could be cleaned up with error handling and such. Also using *args rather than a single key-list argument might be nice; but the idea is that
you can iterate over the keys, pulling up the appropriate dictionary at each level.
Here is my simple solution: just write
terms = ['person', 'address', 'city']
result = nested_dict(3, str)
result[terms] = 'New York' # as easy as it can be
You can even do:
terms = ['John', 'Tinkoff', '1094535332'] # account in Tinkoff Bank
result = nested_dict(3, float)
result[terms] += 2375.30
Now the backstage:
from collections import defaultdict
class nesteddict(defaultdict):
def __getitem__(self, key):
if isinstance(key, list):
d = self
for i in key:
d = defaultdict.__getitem__(d, i)
return d
else:
return defaultdict.__getitem__(self, key)
def __setitem__(self, key, value):
if isinstance(key, list):
d = self[key[:-1]]
defaultdict.__setitem__(d, key[-1], value)
else:
defaultdict.__setitem__(self, key, value)
def nested_dict(n, type):
if n == 1:
return nesteddict(type)
else:
return nesteddict(lambda: nested_dict(n-1, type))
The dotty_dict library for Python 3 can do this. See documentation, Dotty Dict for more clarity.
from dotty_dict import dotty
dot = dotty()
string = '.'.join(['person', 'address', 'city'])
dot[string] = 'New York'
print(dot)
Output:
{'person': {'address': {'city': 'New York'}}}
Use these pair of methods
def gattr(d, *attrs):
"""
This method receives a dict and list of attributes to return the innermost value of the give dict
"""
try:
for at in attrs:
d = d[at]
return d
except:
return None
def sattr(d, *attrs):
"""
Adds "val" to dict in the hierarchy mentioned via *attrs
For ex:
sattr(animals, "cat", "leg","fingers", 4) is equivalent to animals["cat"]["leg"]["fingers"]=4
This method creates necessary objects until it reaches the final depth
This behaviour is also known as autovivification and plenty of implementation are around
This implementation addresses the corner case of replacing existing primitives
https://gist.github.com/hrldcpr/2012250#gistcomment-1779319
"""
for attr in attrs[:-2]:
# If such key is not found or the value is primitive supply an empty dict
if d.get(attr) is None or isinstance(d.get(attr), dict):
d[attr] = {}
d = d[attr]
d[attrs[-2]] = attrs[-1]
Here's a variant of Bakuriu's answer that doesn't rely on a separate function:
keys = ['Person', 'address', 'city']
value = 'New York'
nested_dict = {}
# Build nested dictionary up until 2nd to last key
# (Effectively nested_dict['Person']['address'] = {})
sub_dict = nested_dict
for key_ind, key in enumerate(keys[:-1]):
if not key_ind:
# Point to newly added piece of dictionary
sub_dict = nested_dict.setdefault(key, {})
else:
# Point to newly added piece of sub-dictionary
# that is also added to original dictionary
sub_dict = sub_dict.setdefault(key, {})
# Add value to last key of nested structure of keys
# (Effectively nested_dict['Person']['address']['city'] = value)
sub_dict[keys[-1]] = value
print(nested_dict)
>>> {'Person': {'address': {'city': 'New York'}}}
This is a pretty good use case for a recursive function. So you can do something like this:
def parse(l: list, v: str) -> dict:
copy = dict()
k, *s = l
if len(s) > 0:
copy[k] = parse(s, v)
else:
copy[k] = v
return copy
This effectively pops off the first value of the passed list l as a key for the dict copy that we initialize, then runs the remaining list through the same function, creating a new key under that key until there's nothing left in the list, whereupon it assigns the last value to the v param.
This is much easier in Perl:
my %hash;
$hash{"aaa"}{"bbb"}{"ccc"}=1; # auto creates each of the intermediate levels
# of the hash (aka: dict or associated array)

Dictionary update overwrites duplicate keys

I have a table that has 6982 records that I am reading through to make a dictionary. I used a literal to create the dictionary
fld_zone_dict = dict()
fields = ['uniqueid', 'FLD_ZONE', 'FLD_ZONE_1']
...
for row in cursor:
uid = row[0]
old_zone_value = row[1]
new_zone_value = row[2]
fld_zone_dict[uid] = [old_zone_value, new_zone_value]
However, I noticed that using this method, if a uid has the same value as a previous uid (theoretically, there could be duplicate), the entry gets overwritten. So, if I had 2 entries I wanted to add: 'CA10376036': ['AE', 'X'] and 'CA10376036': ['V', 'D'], the first one gets overwritten and I only get 'CA10376036': ['V', 'D']. How can I add to my dictionary with out overwriting the duplicate keys so that I get something like this?
fld_zone_dict = {'CA10376036': ['AE', 'X'], 'CA9194089':['D', 'X'],'CA10376036': ['V', 'D']....}
Short answer: There is no way to have duplicate keys in a dictionary object in Python.
However, if you were to restructure your data and take that key and put it inside of a dictionary that is nested in a list, you could have duplicate IDs. EX:
[
{
"id": "CA10376036",
"data: ['AE', 'X']
},
{
"id": "CA10376036",
"data: ['V', 'D']
},
]
Doing this though will negate any benefits of lookup speed and ease.
edit: blhsing also has a good example of how to restructure data with a reduced initial lookup time, though you would still have to iterate through data to get the record you wanted.
Dicts are not allowed to have duplicate keys in Python. You can use the dict.setdefault method to convert existing keys to a list instead:
for row in cursor:
uid = row[0]
old_zone_value = row[1]
new_zone_value = row[2]
fld_zone_dict.setdefault(uid, []).append([old_zone_value, new_zone_value])
so that fld_zone_dict will become like:
{'CA10376036': [['AE', 'X'], ['V', 'D']], 'CA9194089': ['D', 'X'], ...}
but then other keys will not have a list of lists as values, so you probably should convert them all instead:
for k, v in fld_zone_dict.items():
fld_zone_dict[k] = [v]
for row in cursor:
uid = row[0]
old_zone_value = row[1]
new_zone_value = row[2]
fld_zone_dict[uid].append([old_zone_value, new_zone_value])
so that fld_zone_dict will become like:
{'CA10376036': [['AE', 'X'], ['V', 'D']], 'CA9194089': [['D', 'X']], ...}

print dict keys and values using another variable

I have dict 'SR' as given below.
>>> SR = {'threshold':'95', 'math':'mean', 'dir':'down'}
>>> SR
{'threshold': '95', 'dir': 'down', 'math': 'mean'}
>>> var='SR'
How can i print all key & value of 'SR' using variable var . My script dynamically select dict name based on some logic , store it in some variable . So I have to print dict values and keys using an another variable. Please help .
Put the various dicts into another dict and look it up that way.
d = {
'SR': {'threshold': '95', 'math': 'mean', 'dir': 'down'},
'AB': {'foo': 'bar'},
'XY': {'blah': 'baz'},
}
which_to_print = 'SR'
for key, value in d[which_to_print].items():
print key, value

How do I extract part of a tuple that's duplicate as key to a dictionary, and have the second part of the tuple as value?

I'm pretty new to Python and Qgis, right now I'm just running scripts but I my end-goal is to create a plugin.
Here's the part of the code I'm having problems with:
import math
layer = qgis.utils.iface.activeLayer()
iter = layer.getFeatures()
dict = {}
#iterate over features
for feature in iter:
#print feature.id()
geom = feature.geometry()
coord = geom.asPolyline()
points=geom.asPolyline()
#get Endpoints
first = points[0]
last = points[-1]
#Assemble Features
dict[feature.id() ]= [first, last]
print dict
This is my result :
{0L: [(355277,6.68901e+06), (355385,6.68906e+06)], 1L: [(355238,6.68909e+06), (355340,6.68915e+06)], 2L: [(355340,6.68915e+06), (355452,6.68921e+06)], 3L: [(355340,6.68915e+06), (355364,6.6891e+06)], 4L: [(355364,6.6891e+06), (355385,6.68906e+06)], 5L: [(355261,6.68905e+06), (355364,6.6891e+06)], 6L: [(355364,6.6891e+06), (355481,6.68916e+06)], 7L: [(355385,6.68906e+06), (355501,6.68912e+06)]}
As you can see, many of the lines have a common endpoint:(355385,6.68906e+06) is shared by 7L, 4L and 0L for example.
I would like to create a new dictionary, fetching the shared points as a key, and having the second points as value.
eg : {(355385,6.68906e+06):[(355277,6.68901e+06), (355364,6.6891e+06), (355501,6.68912e+06)]}
I have been looking though list comprehension tutorials, but without much success: most people are looking to delete the duplicates, whereas I would like use them as keys (with unique IDs). Am I correct in thinking set() would still be useful?
I would be very grateful for any help, thanks in advance.
Maybe this is what you need?
dictionary = {}
for i in dict:
for j in dict:
c = set(dict[i]).intersection(set(dict[j]))
if len(c) == 1:
# ok, so now we know, that exactly one tuple exists in both
# sets at the same time, but this one will be the key to new dictionary
# we need the second tuple from the set to become value for this new key
# so we can subtract the key-tuple from set to get the other tuple
d = set(dict[i]).difference(c)
# Now we need to get tuple back from the set
# by doing list(c) we get list
# and our tuple is the first element in the list, thus list(c)[0]
c = list(c)[0]
dictionary[c] = list(d)[0]
else: pass
This code attaches only one tuple to the key in dictionary. If you want multiple values for each key, you can modify it so that each key would have a list of values, this can be done by simply modifying:
# some_value cannot be a set, it can be obtained with c = list(c)[0]
key = some_value
dictionary.setdefault(key, [])
dictionary[key].append(value)
So, the correct answer would be:
dictionary = {}
for i in a:
for j in a:
c = set(a[i]).intersection(set(a[j]))
if len(c) == 1:
d = set(a[i]).difference(c)
c = list(c)[0]
value = list(d)[0]
if c in dictionary and value not in dictionary[c]:
dictionary[c].append(value)
elif c not in dictionary:
dictionary.setdefault(c, [])
dictionary[c].append(value)
else: pass
See this code :
dict={0L: [(355277,6.68901e+06), (355385,6.68906e+06)], 1L: [(355238,6.68909e+06), (355340,6.68915e+06)], 2L: [(355340,6.68915e+06), (355452,6.68921e+06)], 3L: [(355340,6.68915e+06), (355364,6.6891e+06)], 4L: [(355364,6.6891e+06), (355385,6.68906e+06)], 5L: [(355261,6.68905e+06), (355364,6.6891e+06)], 6L: [(355364,6.6891e+06), (355481,6.68916e+06)], 7L: [(355385,6.68906e+06), (355501,6.68912e+06)]}
dictionary = {}
list=[]
for item in dict :
list.append(dict[0])
list.append(dict[1])
b = []
[b.append(x) for c in list for x in c if x not in b]
print b # or set(b)
res={}
for elm in b :
lst=[]
for item in dict :
if dict[item][0] == elm :
lst.append(dict[item][1])
elif dict[item][1] == elm :
lst.append(dict[item][0])
res[elm]=lst
print res

Multidict in python not working ?? How to create it?

I want to create an python multi dimensional dictionary :-
Currently i am doing like this
multidict = {}
IN LOOP
mulitdict[i] = data
if loop runs ten times I am getting same value in all index..
Eg:
I want to have like this
multidict {0 : {'name':name1, 'age' : age1}, 1: {'name':name2, 'age' : age2}
but i am getting as shown below
multidict {0 : {'name':name1, 'age' : age1}, 1: {'name':name1, 'age' : age1}
I also tried the default dict also....but every time i get same value in all index. What is the problem?
Tried code :
csv_parsed_data2 = {}
with open('1112.txt') as infile:
i =0
for lineraw in infile:
line = lineraw.strip()
if 'sample1 ' in line:
### TO GET SOURCE ROUTER NAME ###
data['sample1'] = line[8:]
elif 'sample2- ' in line:
### TO GET DESTINATION ROUTER NAME ###
data['sample2'] = line[13:]
elif 'sample3' in line:
### TO GET MIN,MAX,MEAN AND STD VALUES ###
min_value = line.replace("ms"," ")
min_data = min_value.split(" ")
data['sample3'] = min_data[1]
csv_parsed_data2[i] = data
i = i + 1
print i,'::',csv_parsed_data2,'--------------'
print csv_parsed_data2,' all index has same value'
any efficient way to do this??
It sounds you are assigning the same data dict to each of the values of your outer multidict, and just modifying the values it holds on each pass through the loop. This will result in all the values appearing the same, with the values from the last pass through the loop.
You probably need to make sure that you create a separate dictionary object to hold the data from each value. A crude fix might be to replace multidict[i] = data with multidict[i] = dict(data), but if you know how data is created, you can probably do something more elegant.
Edit: Seeing your code, here's a way to fix the issue:
csv_parsed_data2 = {}
with open('1112.txt') as infile:
i =0
data = {} # start with empty data dict
for lineraw in infile:
line = lineraw.strip()
if 'sample1 ' in line:
### TO GET SOURCE ROUTER NAME ###
data['sample1'] = line[8:]
elif 'sample2- ' in line:
### TO GET DESTINATION ROUTER NAME ###
data['sample2'] = line[13:]
elif 'sample3' in line:
### TO GET MIN,MAX,MEAN AND STD VALUES ###
min_value = line.replace("ms"," ")
min_data = min_value.split(" ")
data['sample3'] = min_data[1]
csv_parsed_data2[i] = data
data = {} # after saving a reference to the dict, reinitialize it
i = i + 1
print i,'::',csv_parsed_data2,'--------------'
print csv_parsed_data2,' all index has same value'
To understand what was going on, consider this simpler situation, where I a values in a dictionary after saving a reference to it when it had some older values:
my_dict = { "foo": "bar" }
some_ref = my_dict
print some_ref["foo"] # prints "bar"
my_dict["foo"] = "baz"
print some_ref["foo"] # prints "baz", since my_dict and some_ref refer to the same object
print some_ref is d # prints "True", confirming that fact
In your code, my_dict was data and some_ref were all the values of csv_parsed_data2. They would all end up being references to the same object, which would hold whatever the last values assigned to data were.
Try this:
multidict = {}
for j in range(10):
s = {}
s['name'] = raw_input()
s['age'] = input()
multidict[j] = s
This will have the desired result