Inserting list of dictionaries into mongodb and removing int keys - python

I have to insert a list of dictionaries having this syntax (I have more than 6500 dicts like these 3):
0: {208271891: {'bra': 'Solarmax',
'bri': 4,
'eur': 95.4,
'max': 1980,
'nam': '2000S',
'pan': {'bra': 'Sanyo',
'bri': 3,
'eff': 16,
'h': 861,
'hea': 50,
'mni': 1,
'mnm': 'free standing',
'n': 7,
'nam': 'HDE1 230',
'slo': 35,
't': -0.3,
'w': 1610,
'wp': 230},
'pha': 1,
'rat': 0.81,
'wp': 1610}},
1: {208271900: {'bra': 'Solarmax',
'bri': 4,
'eur': 95.4,
'max': 1980,
'nam': '2000S',
'pan': {'bra': 'Sanyo',
'bri': 3,
'eff': 16,
'h': 861,
'hea': -40,
'mni': 1,
'mnm': 'free standing',
'n': 9,
'nam': 'HDE1 230',
'slo': 30,
't': -0.3,
'w': 1610,
'wp': 230},
'pha': 1,
'rat': 1.05,
'wp': 2070}},
2: {208271892: {'bra': 'Solarmax',
'bri': 4,
'eur': 95.4,
'max': 1980,
'nam': '2000S',
'pan': {'bra': 'Sanyo',
'bri': 3,
'eff': 16,
'h': 861,
'hea': 50,
'mni': 1,
'mnm': 'free standing',
'n': 9,
'nam': 'HDE1 230',
'slo': 30,
't': -0.3,
'w': 1610,
'wp': 230},
'pha': 1,
'rat': 1.05,
'wp': 2070}}
I tried to delete keys with dict.pop() and 'del' but got this error: 'TypeError: 'int' object does not support item deletion'.
slMetadata = {}
for row in metadatas: #metadatas coming from mysql
mid = int(row['met_id'])
slMetadata.update(mid = mid)
bsInv = {
mid:
{
'wp' : wp,
'bra': str(row['invbraname']),
'bri': int(row['inm_bra_id']),
'nam': str(row['inm_name']),
'pha': int(row['inm_phases']),
'max': int(row['inm_maximal_power']),
'eur': float(row['inm_euro_efficiency']),
'pan':
{
'n' : int(row['inv_pan_numbers']),
'hea': int(row['inv_pan_heading']),
'slo': int(row['inv_pan_slope']),
'mni': int(row['inv_mnt_id']),
'mnm': str(row['mnt_name']),
'bra': str(row['panbraname']),
'bri': int(row['pan_bra_id']),
'nam': str(row['pan_name']),
'wp' : int(row['pan_wc']),
'eff': int(row['efficiency']),
't' : float(row['coefficient_p']),
'w' : int(row['pan_width']),
'h' : int(row['pan_height'])
}
}
}
i = 0
dictToInsert = {}
for dic in slMetadata:
dictToInsert[i] = slMetadata[dic]
i += 1
if len(dictToInsert) > 0:
insertion = dbCollection.insert_many(dictToInsert)
What I want is to insert all these dicts into mongoDb but I have the error below : bson.errors.InvalidDocument: documents must have only string keys, key was 0.
Which I fully understand and know that I can't insert into mongoDb with 'int' key. But what is the alternative?
Thanks.

Try
dictToInsert[str(i)] = slMetadata[dic]
instead of
dictToInsert[i] = slMetadata[dic]

Related

Nested dictionary from a txt with the dictionary

I have a txt file with the dictionary like this:
{'origin': {'Ukraine': 50, 'Portugal': 20, 'others': 10}, 'native language': {'ucranian': 50; 'english': 45, 'russian': 30, 'others': 10}, 'second language': {'ucranian': 50; 'english': 45, 'russian': 30, 'others': 10, 'none': 0}, 'profession': {'medical doctor': 50, 'healthcare professional': 40, 'cooker': 30, 'others': 10, 'spy': 0}, 'first aid skills': {'yes': 50, 'no': 0}, 'driving skills': {'yes': 40, 'no': 0}, 'cooking skills': {'yes': 50, 'some': 30, 'no': 0}, 'IT skills': {'yes': 50, 'little': 35, 'no': 0}}
And I want to create a dictionary from this
I tried using ast.literal_eval but it gives me the following error:
SyntaxError: expression expected after dictionary key and ':'
This is my code :
def helpersSkills(helpersFile, skillsFile):
"""
"""
helpers = open(helpersFile, 'r')
skills = open(skillsFile, 'r')
skillsLines = skills.read()
dictionary = ast.literal_eval(skillsLines)
...
helpersSkills('helpersArrived2.txt', 'skills.txt')
as said by #ThierryLathuille it was just some writing errors in the txt file
so its working:
{'origin': {'Ukraine': 50, 'Portugal': 20, 'others': 10}, 'native language': {'ucranian': 50, 'english': 45, 'russian': 30, 'others': 10}, 'second language': {'ucranian': 50, 'english': 45, 'russian': 30, 'others': 10, 'none': 0}, 'profession': {'medical doctor': 50, 'healthcare professional': 40, 'cooker': 30, 'others': 10, 'spy': 0}, 'first aid skills': {'yes': 50, 'no': 0}, 'driving skills': {'yes': 40, 'no': 0}, 'cooking skills': {'yes': 50, 'some': 30, 'no': 0}, 'IT skills': {'yes': 50, 'little': 35, 'no': 0}}
This is the code :
def helpersSkills(helpersFile, skillsFile):
"""
"""
helpers = open(helpersFile, 'r')
skills = open(skillsFile, 'r')
skillsLines = skills.read()
dictionary = ast.literal_eval(skillsLines)
...
helpersSkills('helpersArrived2.txt', 'skills.txt')

Python3 Merge two dictionaries based on sub dictionaries keys w/o for loop

Maybe this is impossible but without a for loop through each key in a given dictionary merge the two based on the key in the dictionary
Given :
dict1 = { 'APPL' : { 'cp': 1, 'sed': 'bull'}, 'BAC' : { 'cp': 1, 'sed': 'bull'}}
dict2 = { 'APPL' : { 'tp': 100}}
dict3 = dict1 | dict2 ## python ≥3.9 only
print(dict3)
{'APPL': {'tp': 100}, 'BAC': {'cp': 1, 'sed': 'bull'}}
dict1.update(dict2)
print(dict1)
{'APPL': {'tp': 100}, 'BAC': {'cp': 1, 'sed': 'bull'}}
Desired output
{'APPL': {'tp': 100,'cp': 1, 'sed': 'bull'}, 'BAC': {'cp': 1, 'sed': 'bull'}}
I can do it now with a for loop , just wondering if there is a more elegant solution
Do:
dict1 = {'APPL': {'cp': 1, 'sed': 'bull'}, 'BAC': {'cp': 1, 'sed': 'bull'}}
dict2 = {'APPL': {'tp': 100}}
res = {key: {**value, **dict2.get(key, {})} for key, value in dict1.items()}
print(res)
Output
{'APPL': {'cp': 1, 'sed': 'bull', 'tp': 100}, 'BAC': {'cp': 1, 'sed': 'bull'}}
No, this isn't possible without iteration. You could use a custom joiner function and then reduce a list of dictionaries however:
data = [{'BAC': {'a': 40}, 'XYZ': {'c': 81, 'b': 16}, 'ABC': {'b': 85}},
{'APPL': {'b': 55},
'BAC': {'b': 16, 'f': 59},
'ABC': {'d': 9, 'c': 43},
'XYZ': {'b': 82}},
{'ABC': {'b': 43, 'c': 35},
'APPL': {'f': 17, 'a': 1, 'd': 16},
'BAC': {'f': 35, 'a': 1},
'XYZ': {'a': 2, 'c': 55}},
{'BAC': {'f': 4, 'd': 87},
'XYZ': {'d': 31, 'f': 92},
'APPL': {'b': 18, 'a': 74, 'c': 69}},
{'XYZ': {'d': 84, 'f': 49},
'ABC': {'d': 88, 'a': 82, 'f': 96},
'APPL': {'a': 23},
'BAC': {'b': 40}},
{'BAC': {'c': 88, 'd': 38},
'APPL': {'c': 48, 'b': 30},
'ABC': {'d': 95, 'b': 38},
'XYZ': {'d': 90, 'a': 5}}]
def join_dict(d1, d2):
result = {k: {**d1[k], **d2[k]} for k in d1}
result.update({k: {**d1[k], **d2[k]} for k in d2})
return result
>>> import functools
>>> functools.reduce(join_dict, data)
{'XYZ': {'a': 39, 'f': 78, 'c': 42, 'd': 30, 'b': 24},
'ABC': {'c': 22, 'f': 69, 'a': 8, 'b': 51, 'd': 70},
'APPL': {'d': 19, 'b': 35, 'a': 6, 'f': 33, 'c': 64},
'BAC': {'f': 97, 'c': 38, 'd': 1, 'b': 63, 'a': 91}}
Of course, this will overwrite any common values in the sub-dictionaries. Assuming that isn't an issue for you, this should work fine as a "more elegant solution".

delete dict in list from dict in list

I have two lists (with dicts in it):
old_device_data_list = [{'_id': ObjectId('5f48c8e34545fac49fbff5'), 'device_id': 5, 'time': datetime.datetime(2020, 8, 26, 9, 5, 39, 827000), 'values': {'count': 100, 'late': 0, 'max': 0, 'min': 0, 'on_time': 100, 'sum': 100}}]
result = [{'_id': ObjectId('5f48c8e3997640fac49fbff5'), 'device_id': 5, 'time': datetime.datetime(2020, 8, 26, 9, 5, 39, 827000), 'values': {'count': 100, 'late': 0, 'max': 0, 'min': 0, 'on_time': 100, 'sum': 100}}, {'_id': ObjectId('5f48c8e3997640fac49fbff6'), 'device_id': 4, 'time': datetime.datetime(2020, 8, 26, 9, 5, 39, 827000), 'values': {'count': 180, 'late': 0, 'max': 0, 'min': 0, 'on_time': 180, 'sum': 180}}, {'_id': ObjectId('5f48c8e3997640fac49fbff8'), 'device_id': 3, 'time': datetime.datetime(2020, 8, 27, 9, 5, 39, 827000), 'values': {'count': 50, 'late': 0, 'max': 0, 'min': 0, 'on_time': 50, 'sum': 50}}, {'_id': ObjectId('5f48c8e3997640fac49fbff7'), 'device_id': 4, 'time': datetime.datetime(2020, 8, 27, 9, 5, 39, 827000), 'values': {'count': 120, 'late': 0, 'max': 0, 'min': 0, 'on_time': 120, 'sum': 120}}, {'_id': ObjectId('5f48c8e3997640fac49fbff9'), 'device_id': 3, 'time': datetime.datetime(2020, 8, 28, 9, 5, 39, 827000), 'values': {'count': 210, 'late': 0, 'max': 0, 'min': 0, 'on_time': 210, 'sum': 210}}]
I want to delete the dicts from the old_device_data_list out of the result list. I tried it with numpy with:
numpy.setdiff1d(result, old_device_data_list)
Then I got error:
TypeError: '<' not supported between instances of 'dict' and 'dict'
The description of numpy.setdiff1d says:
Return the sorted, unique values in ar1 that are not in ar2.
In order to sort the values, it needs to compare them using the < operator. But dictionaries cannot be compared like this. The relation "smaller than" is not defined for dictionaries.
NumPy is designed for working with numeric values, not for arbitrary Python data structures.
You could use a simple list comprehension to create a list of those dictionaries that are in result but not in old_device_data_list:
result = [d for d in result if d not in old_device_data_list]

Scatter plot line to out of order data

I am tracking the movements of an avian animal. I have detection points on an xy plot. I want to connect the previous detected point to the next detection, regardless of direction. This will assist with removing extraneous detections.
Data Sample:
Sample input
The goal is to have a line from the previous data point to the next point.
Sample output
Unsuccessful method 1:
plt.figure('Frame',figsize=(16,12))
plt.imshow(frame)
plt.plot(x, y, '-ro', 'd',markersize=2.5, color='orange')
Method 1 output
Unsuccessful method 2:
plt.plot(np.sort(x), y[np.argsort(x)], '-bo', ms = 2)
Method 2 output
I used your sample data and make a plot with method 1 (but with pandas) and the output was as you expected. I don't understand why you have an unsuccessful result.
data = [{'frame': 1, 'x': 5, 'y': 15},
{'frame': 4, 'x': 10, 'y': 15},
{'frame': 5, 'x': 15, 'y': 15},
{'frame': 6, 'x': 20, 'y': 15},
{'frame': 7, 'x': 23, 'y': 20},
{'frame': 8, 'x': 25, 'y': 25},
{'frame': 11, 'x': 20, 'y': 23},
{'frame': 15, 'x': 15, 'y': 20},
{'frame': 18, 'x': 8, 'y': 18},
{'frame': 19, 'x': 8, 'y': 10},
{'frame': 20, 'x': 12, 'y': 7}]
df = pd.DataFrame(data).sort_values('frame')
df.plot(x='x', y='y')

Storing list into dictionary from excel

I have stored data into list from excel but now I want to store it into dictionary.
here is the excel
in list it giving output like this.
[['Nodeb_IN_New', 107, 'class-default', 'mobility-platinum', 'h1', 7, 'dscp-fc-map', ['ef']], ['', 107, '', 'mobility-gold-new', 'h2', 5, 'dscp-fc-map', ['af41']], ['', 107, '', 'mobility-silver-new', 'l1', 4, 'dscp-fc-map', ['af11', 'af21', 'af31']], ['Nokia_SRAN_S1-MME_X2_IN', 102, '', 'Nokia_SRAN_mobility_platinum', 'h1', 7, 'dscp-fc-map', ['ef', 'nc1']]]
same I want into dictionary. I have written this code
def myfun(list):
list = list
res=dict()
qos=None
for row in list:
if row[0]=="":
res[qos]['b']=row[1]
res[qos]['c']=row[2]
res[qos]['d']=row[3]
res[qos]['e']=row[4]
res[qos]['f']=row[5]
res[qos]['g']=row[6]
res[qos]['h']=row[7]
else:
qos=row[0]
res[qos]=dict()
res[qos]['b']=row[1]
res[qos]['c']=row[2]
res[qos]['d']=row[3]
res[qos]['e']=row[4]
res[qos]['f']=row[5]
res[qos]['g']=row[6]
res[qos]['h']=row[7]
but it is giving output like this.
{'Nodeb_IN_New': {
'b': 107, 'c': '', 'd': 'mobility-silver-new',
'e': 'l1', 'f': 4, 'g': 'dscp-fc-map',
'h': ['af11', 'af21', 'af31']
},
'Nokia_SRAN_S1-MME_X2_IN': {
'b': 102, 'c': '', 'd': 'Nokia_SRAN_mobility_platinum', 'e': 'h1', 'f': 7, 'g': 'dscp-fc-map', 'h': ['ef', 'nc1']}}
under 'Nodeb_IN_New' I want all the 3 lines(from excel).
The reason your code isn't working, is that when you are going through the rows and inserting them into the target dictionary res, you are also setting the value to a sub-dictionary, and in this sub-dictionary, the rows will always go under the same key ‘b’, ‘c’, ‘d’, etc., in other words, the rows at the bottom are overwriting the rows at top, leaving you just the 3rd row for Nodeb_IN_New.
Another way would be to set the value to a list, and go through the rows, append them to this list if they belong to the same qos, here's the code:
# Original excel sheet in a list
raw_list = [
['Nodeb_IN_New', 107, 'class-default', 'mobility-platinum', 'h1', 7, 'dscp-fc-map', ['ef']],
['', 107, '', 'mobility-gold-new', 'h2', 5, 'dscp-fc-map', ['af41']],
['', 107, '', 'mobility-silver-new', 'l1', 4, 'dscp-fc-map', ['af11', 'af21', 'af31']],
['Nokia_SRAN_S1-MME_X2_IN', 102, '', 'Nokia_SRAN_mobility_platinum', 'h1', 7, 'dscp-fc-map', ['ef', 'nc1']]
]
result_dict = {}
# title, will be used as key in the result_dict
title = ""
# Loop through the input list
for row in raw_list:
# If the first value is not empty, replace the title with this new value
if row[0] != "":
# update title
title = row[0]
# Insert into the dictionary, and give an empty list as a place holder,
# later we can append to this list
result_dict[title] = []
# At this stage we can append the rest of the input row to the dictionary value
result_dict[title].append(row[1:])
print("Result dict: ")
for (key, value) in result_dict.items():
print("Key: {}".format(key))
for row in value:
print(" {}".format(row))
And here's the output of the code above:
Key: Nodeb_IN_New
[107, 'class-default', 'mobility-platinum', 'h1', 7, 'dscp-fc-map', ['ef']]
[107, '', 'mobility-gold-new', 'h2', 5, 'dscp-fc-map', ['af41']]
[107, '', 'mobility-silver-new', 'l1', 4, 'dscp-fc-map', ['af11', 'af21', 'af31']]
Key: Nokia_SRAN_S1-MME_X2_IN
[102, '', 'Nokia_SRAN_mobility_platinum', 'h1', 7, 'dscp-fc-map', ['ef', 'nc1']]
try this code :
import json
l=[['Nodeb_IN_New', 107, 'class-default', 'mobility-platinum', 'h1', 7, 'dscp-fc-map', ['ef']], ['', 107, '', 'mobility-gold-new', 'h2', 5, 'dscp-fc-map', ['af41']], ['', 107, '', 'mobility-silver-new', 'l1', 4, 'dscp-fc-map', ['af11', 'af21', 'af31']], ['Nokia_SRAN_S1-MME_X2_IN', 102, '', 'Nokia_SRAN_mobility_platinum', 'h1', 7, 'dscp-fc-map', ['ef', 'nc1']]]
def myfun(list):
res=dict()
qos=None
d={}
li=[]
for row in list:
if row[0]=="":
res[qos]=dict()
res[qos]['b']=row[1]
res[qos]['c']=row[2]
res[qos]['d']=row[3]
res[qos]['e']=row[4]
res[qos]['f']=row[5]
res[qos]['g']=row[6]
res[qos]['h']=row[7]
else:
qos=row[0]
res[qos]=dict()
res[qos]['b']=row[1]
res[qos]['c']=row[2]
res[qos]['d']=row[3]
res[qos]['e']=row[4]
res[qos]['f']=row[5]
res[qos]['g']=row[6]
res[qos]['h']=row[7]
x = res.keys()
keylist = []
keylist.extend(iter(x))
if keylist[0] in d.keys():
d[keylist[0]].append(res[qos])
else:
d[keylist[0]] = []
d[keylist[0]].append(res[qos])
print(d)
print(json.dumps(d))
myfun(l)
output:
{'Nokia_SRAN_S1-MME_X2_IN': [{'d': 'Nokia_SRAN_mobility_platinum', 'f': 7, 'e': 'h1', 'b': 102, 'c': '', 'h': ['ef', 'nc1'], 'g': 'dscp-fc-map'}], 'Nodeb_IN_New': [{'d': 'mobility-platinum', 'f': 7, 'e': 'h1', 'b': 107, 'c': 'class-default', 'h': ['ef'], 'g': 'dscp-fc-map'}, {'d': 'mobility-gold-new', 'f': 5, 'e': 'h2', 'b': 107, 'c': '', 'h': ['af41'], 'g': 'dscp-fc-map'}, {'d': 'mobility-silver-new', 'f': 4, 'e': 'l1', 'b': 107, 'c': '', 'h': ['af11', 'af21', 'af31'], 'g': 'dscp-fc-map'}]}
result in json to be readable :
{
"Nokia_SRAN_S1-MME_X2_IN": [
{
"d": "Nokia_SRAN_mobility_platinum",
"f": 7,
"e": "h1",
"b": 102,
"c": "",
"h": [
"ef",
"nc1"
],
"g": "dscp-fc-map"
}
],
"Nodeb_IN_New": [
{
"d": "mobility-platinum",
"f": 7,
"e": "h1",
"b": 107,
"c": "class-default",
"h": [
"ef"
],
"g": "dscp-fc-map"
},
{
"d": "mobility-gold-new",
"f": 5,
"e": "h2",
"b": 107,
"c": "",
"h": [
"af41"
],
"g": "dscp-fc-map"
},
{
"d": "mobility-silver-new",
"f": 4,
"e": "l1",
"b": 107,
"c": "",
"h": [
"af11",
"af21",
"af31"
],
"g": "dscp-fc-map"
}
]
}

Categories

Resources