I received the output from my Vector AutoRegression (VAR) algorithm as a data frame and converted it into a dictionary giving me the following structure:
{
'Date': '2021-05-07',
'BMI': 40.53002073252068,
'BP': 123.00463807559225,
'BloodSugar': 126.85415609085157,
'ThyroidFunction': 3.0,
'TF': 5.0
}
and I want to restructure it in this form :
# {Vital : {date : value, risk_value : 1}}
{
'BMI' : {'2021-05-07' : 40.53002073252068, risk_value : 1},
'BP': {'2021-05-07' : 123.00463807559225, risk_value : 1},
'BloodSugar' :{'2021-05-07' : 126.85415609085157, risk_value : 1},
'ThyroidFunction' : {'2021-05-07' : 3.0, risk_value:1},
'TF' : {'2021-05-07' : 5.0, risk_value:1}
}
Here the "risk_value : 1" is static for now.
The only thing constant in the output from VAR in the 1st dictionary would be the 1st key- date.
The value of date will change everyday.
The Vitals(BMI, BP, BloodSugar, ThyroidFunction, TF) may vary with input with either new vitals such as (weight, height, BMI, BP, BloodSugar) or completely different vitals(cholestrolLevel, HeartRate, LDL). Like so:
{
'Date': '2021-05-07',
'weight': '170lbs',
'height': '175cm',
'BMI': 39.3252068004638,
'BP': 104.530020707559225,
'BloodSugar': 126.85415609085157,
}
I wanted to make a function which dynamically restructures the dictionary. so I tried creating a function which would take all the keys of the dictionary and tried to run it through while loop and which then creates a dictionary with vitals and the values but was unsuccessful.
I've been stuck on this for a long time and any help will be greatly appreciated.
your_dict = {
'Date': '2021-05-07',
'BMI': 40.53002073252068,
'BP': 123.00463807559225,
'BloodSugar': 126.85415609085157,
'ThyroidFunction': 3.0,
'TF': 5.0
}
def parse_dict(dict_in):
dictionary = {}
for x in dict_in:
if x != 'Date':
dictionary[x] = {dict_in['Date']: dict_in[x], 'risk_value': 1}
return dictionary
dict_out = parse_dict(your_dict)
Seems #peter beat me to it but since I've already bothered...
def foo(some_dict, **kwargs):
ret = {}
date_key = some_dict.pop('Date')
for k, v in some_dict.items():
ret[k] = {date_key: v}
ret[k].update(kwargs)
return ret
d = {
'Date': '2021-05-07',
'weight': '170lbs',
'height': '175cm',
'BMI': 39.3252068004638,
'BP': 104.530020707559225,
'BloodSugar': 126.85415609085157,
}
from pprint import pprint
pprint(foo(d, risk_value=42, abc='x'))
Here you go!
def restructure (dct):
date = dct['Date'] #store the date
dct.pop('Date') #remove 'Date' key from the dict since it not needed anymore
for key, value in dct.items():
dct[key] = {date:value, 'risk_value' : 1} #update values for each key
return dct
print(restructure(d))
Related
I have a list of dicts that looks like this:
{
"Player_Name":"Byeong-Hun An",
"Tournament":[
{
"Name":"Arnold Palmer Invitational presented by Mastercard",
"Points":"32.80",
"Salary":"10300.00"
}
]
},
{
"Player_Name":"Byeong-Hun An",
"Tournament":[
{
"Name":"Different",
"Points":"18.80",
"Salary":"10400.00"
}
]
}
and I want this:
[
{
"Player_Name":"Byeong-Hun An",
"Tournament":[
{
"Name":"Arnold Palmer Invitational presented by Mastercard",
"Points":"32.80",
"Salary":"10300.00"
},
{
"Name":"Different",
"Points":"18.80",
"Salary":"10400.00"
}
]
}
]
I've tried collections, but it doesn't do exactly what I'm wanting. I essentially want to take every single player and combine all the tournament objects into one so each player has one object instead of each event having its own object.
Here's my code
import json
import numpy as np
import pandas as pd
from collections import Counter
# using json open the player objects file and set it equal to data
with open('PGA_Player_Objects.json') as json_file:
data = json.load(json_file)
points = []
players = []
for a in data:
for b in a['Tournament']:
points.append(int(float(b['Points'])))
for x in data:
players.append(x['Player_Name'])
def Average(lst):
unrounded = sum(lst) / len(lst)
return round(unrounded,2)
result = Counter()
for d in data:
for b in d['Tournament']:
result[d['Player_Name']] += int(float(b['Points']))
How can I do that?
if your list is in l:
l = [{'Player_Name': 'Byeong-Hun An', 'Tournament': [{'Name': 'Arnold Palmer Invitational presented by Mastercard', 'Points': '32.80', 'Salary': '10300.00'}]},
{'Player_Name': 'Byeong-Hun An', 'Tournament': [{'Name': 'Different', 'Points': '18.80', 'Salary': '10400.00'}]},]
Try this:
from itertools import groupby
result = []
for k,g in groupby(sorted(l, key=lambda x:x['Player_Name']), lambda x:x['Player_Name']):
result.append({'Player_Name':k, 'Tournament':[i['Tournament'][0] for i in g]})
Then the result will be:
[{'Player_Name': 'Byeong-Hun An',
'Tournament': [
{'Name': 'Arnold Palmer Invitational presented by Mastercard',
'Points': '32.80',
'Salary': '10300.00'},
{'Name': 'Different',
'Points': '18.80',
'Salary': '10400.00'}]}]
This works as well, and it's a more general solution that works for arbitrary key names:
from collections import defaultdict
d = defaultdict(list)
for dic in lst:
for k, v in dic.items():
if isinstance(v, list):
d[k].extend(v)
else:
d[k] = v
answer = [dict(d)]
Here's my take on a solution.
Create a new list of dictionaries
Iterate through the original list of dictionaries.
Store one copy of the beginning data for each player that is the same into the new list of dictionaries
Append additional Tournament data for each player into that one dictionary into a unified Tournament list.
Untested code below as an example, but should work with some tweaks.
listofDicts = [{'Player_Name': 'Byeong-Hun An', 'Tournament': [{'Name': 'Arnold Palmer Invitational presented by Mastercard', 'Points': '32.80', 'Salary': '10300.00'}]},{'Player_Name': 'Byeong-Hun An', 'Tournament': [{'Name': 'Different', 'Points': '18.80', 'Salary': '10400.00'}]}]
newListOfDicts = []
playerName = " "
playerNo = -1
for dicts in listofDicts:
if playerName == dicts['Player_Name']:
newListOfDicts[playerNo]['Tournament'].append(dicts['Tournament'][0])
else:
newListOfDicts.append(dicts)
playerName = dicts['Player_Name']
playerNo += 1
I couldn't find any examples that match my use case. Still working through my way in python lists and dictionaries.
Problem:
all_cars = {'total_count': 3,'cars': [{'name': 'audi','model': 'S7'}, {'name': 'honda', 'model': 'accord'},{'name': 'jeep', 'model': 'wrangler'} ]}
owners = {'users':[{'owner': 'Nick', 'car': 'audi'},{'owner': 'Jim', 'car': 'ford'},{'owner': 'Mike', 'car': 'mercedes'} ]}
def duplicate():
for c in all_cars['cars']:
if c['name'] == [c['users']for c in owners['users']]:
pass
else:
res = print(c['name'])
return res
output = ['honda', 'jeep', audi']
and
def duplicate():
for c in all_cars['cars']:
if c['name'] == 'audi':
pass
else:
res = print(c['name'])
return res
output - ['honda', 'jeep']
I am trying to find matching values in both dictionaries, using list comprehension, then return non-matching values only.
Solution: Using 'in' rather than '==' operator, I was able to compare values between both lists and skip duplicates.
def duplicate():
for c in all_cars['cars']:
if c['name'] in [c['users']for c in owners['users']]:
pass
else:
res = print(c['name'])
return res
To answer the question in your title, you can conditionally add elements during a list comprehension using the syntax [x for y in z if y == a], where y == a is any condition you need - if the condition evaluates to True, then the element y will be added to the list, otherwise it will not.
I would just keep a dictionary of all of the owner data together:
ownerData = { "Shaft" : {
"carMake" : "Audi",
"carModel" : "A8",
"year" : "2015" },
"JamesBond" : {
"carMake" : "Aston",
"carModel" : "DB8",
"year" : "2012" },
"JeffBezos" : {
"carMake" : "Honda",
"carModel" : "Accord"
"year" : "1989"}
}
Now you can loop through and query it something like this:
for o in ownerData:
if "Audi" in o["carMake"]:
print("Owner %s drives a %s %s %s" % (o, o["year"], o["carMake"], o["carModel"]))
Should output:
"Owner Shaft drives a 2015 Audi A8"
This way you can expand your data set for owners without creating multiple lists.
OK, based on your feedback on the solution above, here is how I would tackle your problem. Drop your common items into lists and then use "set" to print out the diff.
all_cars = {'total_count': 3,'cars': [{'name': 'audi','model': 'S7'},
{'name': 'honda', 'model': 'accord'},{'name': 'jeep', 'model': 'wrangler'} ]}
owners = {'users':[{'owner': 'Nick', 'car': 'audi'},{'owner': 'Jim',
'car': 'ford'},{'owner': 'Mike', 'car': 'mercedes'} ]}
allCarList = []
ownerCarList = []
for auto in all_cars['cars']:
thisCar = auto['name']
if thisCar not in allCarList:
allCarList.append(thisCar)
for o in owners['users']:
thisCar = o['car']
if thisCar not in ownerCarList:
ownerCarList.append(thisCar)
diff = list(set(allCarList) - set(ownerCarList))
print(diff)
I put this in and ran it and came up with this output:
['jeep', 'honda']
Hope that helps!
I have problem with filtering dict of dict while using dict comprehension.
I have dict:
clients = {
'Shop': {'url' : 'url_v', 'customer' : 'cumoster_v',
'some_other_key1' : 'some_value'},
'Gym': {'url' : 'url_v1', 'customer_1' : 'customer_v1', 'customer_2': 'customer_v2',
'some_other_key2' : 'some_value'},
'Bank': {'url' : 'url_v2', 'customer_3' : 'customer_v3',
'some_other_key3' : 'some_value'}
}
I would like to make another dict which will have only 'customer.*' keys.
So, new dict should looks like:
dict_only_cust = {
'Shop': {'customer' : 'cumoster_v'},
'Gym': {'customer_1' : 'customer_v1', 'customer_2': 'customer_v2'},
'Bank': {'customer_3' : 'customer_v3'}
}
As I'm big fan of lists and dicts comprehension, I'm wondering if it is possible to do it with this.
So far, I've written:
dict_only_cust = {v.pop(t) for k, v in clients.items()
for t, vv in v.items()
if not re.match('.*customer.*', t)}
Code fails with 'RuntimeError: dictionary changed size during iteration'
Second time I've tried:
dict_only_cust = {k:{t: vv} for k, v in clients.items()
for t, vv in v.items()
if re.match('.*customer.*', t)}
It is almost OK, but it is returning
dict_only_cust = {
'Shop' : {'customer' : 'cumoster_v'},
'Gym' : {'customer_1' : 'customer_v1'},
'Bank' : {'customer_3' : 'customer_v3'}
}
How to solve this problem using dict comprehension?
I'm using python 3.4.
Thanks!
>>> {key:{k:v for k,v in dic.items() if 'customer' in k} for key,dic in clients.items()}
{'Shop': {'customer': 'cumoster_v'}, 'Gym': {'customer_2': 'customer_v2', 'customer_1': 'customer_v1'}, 'Bank': {'customer_3': 'customer_v3'}}
{k:{k1:v1 for k1,v1 in v.items() if k1.startswith('customer')} for k, v in clients.items()}
Output :
{'Shop': {'customer': 'cumoster_v'}, 'Gym': {'customer_2': 'customer_v2', 'customer_1': 'customer_v1'}, 'Bank': {'customer_3': 'customer_v3'}}
I have a data set which follows the structure of the following example:
exampleset = {
'body' : {
'abdomen' : [{
'arms' : {
'value' : 2,
}
},{
'legs': {
'value' : 2,
}
}],
'hands' : {
'fingers' : {
'value' : 5,
}
},
}
}
I am trying to reverse this so I get something like:
{'value': {'value1': {5: {'fingers': {'hands': {'body': {}}}}},
'value2': {2: {'legs': {'abdomen': {'body': {}}}}},
'value3': {2: {'arms': {'abdomen': {'body': {}}}}}},
}
(I hope I got the bracket matching right, but you get the idea.)
I am using a couple of recursion functions to do this, like so:
def recurse_find(data, values, count):
global conf
for key in data:
for v in conf['value_names']:
if key == v:
values[v+str(count)] = {}
values[v+str(count)][data[key]] = {}
count += 1
# originally just using this line:
# values[data[key]] = {}
if type(data[key]) is list:
for i in data[key]:
if type(i) is dict:
values = recurse_find(i, values, count)
values = add_new_level(values, key)
elif type(data[key]) is dict:
values = recurse_find(data[key], values, count)
values = add_new_level(values, key)
return values
def add_new_level(data, new_key):
for key in data:
if data[key] == {}:
data[key][new_key] = {}
else:
data[key] = add_new_level(data[key], new_key)
return data
conf = { "value_names": ["value"] }
for value in conf['value_names']:
values[value] = recurse_find(exampleset, {}, 1)
print(values)
At the moment I only get one value returned correctly, obviously I would like them all. Originally I didn't label the values (value1, value2 etc), but when doing this example set I realised that of course if the values are the same I'll only get one! If I remove the value name keys it finds all the values (unless duplicate) but still doesn't return the correct levels as it includes some of the others while it loops round. I don't care about the order of the values, just that they are labelled differently so I don't miss out any.
Current result:
{'value': {'value1': {5: {'fingers': {'hands': {'body': {}}}}}}}
I think that the solution is the inclusion of a pretty simple step, but I can't see it at the moment and I've already spent too long looking at this.
Any help appreciated.
EDIT:
I've gotten a little further by changing my recursive function to make count a global variable and having count=1 outside the function which has sorted out the getting all the values problem.
I have narrowed down the addition of extra keys to the add_new_level function, but haven't yet figured out how to change it.
Output:
{'value': {'value1': {2: {'arms': {'abdomen': {'legs': {'abdomen': {'fingers': {'hands': {'body': {}}}}}}}}},
'value2': {2: {'legs': {'abdomen': {'fingers': {'hands': {'body': {}}}}}}},
'value3': {5: {'fingers': {'hands': {'body': {}}}}}}}
I have adjusted your output type slightly to make the dictionary containing 'value1' 'value2' etc... to an array. I believe this is better because the order of these will be lost anyway unless an OrderedDict (from collections package) is used and in any case an array will translate quite easily from index 0,1,2,3.. to val1, val2, val3, etc...
res = {'value': []}
def revnest(inp, keys=[]):
res2 = res['value']
if type(inp) == list:
inp = {i:j[i] for j in inp for i in j}
for x in inp:
if x == 'value':
res2.append({inp[x]:{}})
res2 = res2[-1][inp[x]]
for y in keys[::-1]:
res2[y] = {}
res2 = res2[y]
else:
revnest(inp[x], keys+[x])
revnest(exampleset)
print res
which given your exampleset, prints:
{'value': [{2: {'legs': {'abdomen': {'body': {}}}}}, {2: {'arms': {'abdomen': {'body': {}}}}}, {5: {'fingers': {'hands': {'body': {}}}}}]}
I have a bit of a complex question that I can't seem to get to the bottom of. I have a list of keys corresponding to a position in a Python dictionary. I would like to be able to dynamically change the value at the position (found by the keys in the list).
For example:
listOfKeys = ['car', 'ford', 'mustang']
I also have a dictionary:
DictOfVehiclePrices = {'car':
{'ford':
{'mustang': 'expensive',
'other': 'cheap'},
'toyota':
{'big': 'moderate',
'small': 'cheap'}
},
'truck':
{'big': 'expensive',
'small': 'moderate'}
}
Via my list, how could I dynamically change the value of DictOfVehiclePrices['car']['ford']['mustang']?
In my actual problem, I need to follow the list of keys through the dictionary and change the value at the end position. How can this be done dynamically (with loops, etc.)?
Thank you for your help! :)
Use reduce and operator.getitem:
>>> from operator import getitem
>>> lis = ['car', 'ford', 'mustang']
Update value:
>>> reduce(getitem, lis[:-1], DictOfVehiclePrices)[lis[-1]] = 'cheap'
Fetch value:
>>> reduce(getitem, lis, DictOfVehiclePrices)
'cheap'
Note that in Python 3 reduce has been moved to functools module.
A very simple approach would be:
DictOfVehiclePrices[listOfKeys[0]][listOfKeys[1]][listOfKeys[2]] = 'new value'
print reduce(lambda x, y: x[y], listOfKeys, dictOfVehiclePrices)
Output
expensive
In order to change the values,
result = dictOfVehiclePrices
for key in listOfKeys[:-1]:
result = result[key]
result[listOfKeys[-1]] = "cheap"
print dictOfVehiclePrices
Output
{'car': {'toyota': {'small': 'cheap', 'big': 'moderate'},
'ford': {'mustang': 'cheap', 'other': 'cheap'}},
'truck': {'small': 'moderate', 'big': 'expensive'}}
You have a great solution here by #Joel Cornett.
based on Joel method you can use it like this:
def set_value(dict_nested, address_list):
cur = dict_nested
for path_item in address_list[:-2]:
try:
cur = cur[path_item]
except KeyError:
cur = cur[path_item] = {}
cur[address_list[-2]] = address_list[-1]
DictOfVehiclePrices = {'car':
{'ford':
{'mustang': 'expensive',
'other': 'cheap'},
'toyota':
{'big': 'moderate',
'small': 'cheap'}
},
'truck':
{'big': 'expensive',
'small': 'moderate'}
}
set_value(DictOfVehiclePrices,['car', 'ford', 'mustang', 'a'])
print DictOfVehiclePrices
STDOUT:
{'car': {'toyota': {'small': 'cheap', 'big': 'moderate'}, 'ford':
{'mustang': 'a', 'other': 'cheap'}}, 'truck': {'small': 'moderate',
'big': 'expensive'}}
def update_dict(parent, data, value):
'''
To update the value in the data if the data
is a nested dictionary
:param parent: list of parents
:param data: data dict in which value to be updated
:param value: Value to be updated in data dict
:return:
'''
if parent:
if isinstance(data[parent[0]], dict):
update_dict(parent[1:], data[parent[0]], value)
else:
data[parent[0]] = value
parent = ["test", "address", "area", "street", "locality", "country"]
data = {
"first_name": "ttcLoReSaa",
"test": {
"address": {
"area": {
"street": {
"locality": {
"country": "india"
}
}
}
}
}
}
update_dict(parent, data, "IN")
Here is a recursive function to update a nested dict based on a list of keys:
1.Trigger the update dict function with the required params
2.The function will iterate the list of keys, and retrieves the value from the dict.
3.If the retrieved value is dict, it pops the key from the list and also it updates the dict with the value of the key.
4.Sends the updated dict and list of keys to the same function recursively.
5.When the list gets empty, it means that we have reached the desired the key, where we need to apply our replacement. So if the list is empty, the funtion replaces the dict[key] with the value