How to write nested dictionaries to a CSV file - python

i have a dictionary as
count = {'lt60': {'a': 0, 'b': 0, 'c': 0, 'd': 0}, 'ge60le90': {'a': 4, 'b': 0, 'C': 0, 'd': 0}, 'gt90': {'a': 0, 'b': 1, 'c': 2, 'd': 1} }
i want to write this dictionary in a CSV format like this ..as you can see in this picture
what i want is pic the keys from lt60, ge60le90, gt90 and want to write them in a row. like i pick 'a' and its value from all the nested dictionaries and write its value in that row.

You can use pandas to do this:
import pandas as pd
count = {'lt60': {'a': 0, 'b': 0, 'c': 0, 'd': 0},
'ge60le90': {'a': 4, 'b': 0, 'c': 0, 'd': 0},
'gt90': {'a': 0, 'b': 1, 'c': 2, 'd': 1} }
df = pd.DataFrame(count).rename_axis('relation_type').reset_index()
df = df.rename(columns={'ge60le90': 'confidence<90',
'gt90': 'confidence>90',
'lt60': 'confidence<60'})
df.to_csv('out.csv', index=False)
# relation_type confidence<90 confidence>90 confidence<60
# 0 a 4 0 0
# 1 b 0 1 0
# 2 c 0 2 0
# 3 d 0 1 0

Another way of doing it would be to utilize csv module. (Note that in your dictionary you have an upper case C which I corrected in my code below):
import csv
lookup = {'ge60le90': 'confidence<90','gt90': 'confidence>90', 'lt60': 'confidence<60'}
count = {'lt60': {'a': 0, 'b': 0, 'c': 0, 'd': 0}, 'ge60le90': {'a': 4, 'b': 0, 'c': 0, 'd': 0}, 'gt90': {'a': 0, 'b': 1, 'c': 2, 'd': 1} }
# Getting keys from dictionary that match them with titles below.
rowKeys = [k for k in count['lt60'].keys()]
titles = [['relation type'] + list(lookup[k] for k in count.keys())]
# Getting all row variable values for every title.
rows = [[count[k][i] for k in count.keys()] for i in rowKeys]
# Concatenating variables and values.
fields = [[rowKeys[i]] + rows[i] for i in range(len(rowKeys))]
# Concatenating final output to be written to file.
result = titles + fields
print("Final result to be written: ")
for r in result:
print(r)
# Writing to file.
with open("output.csv", "w", newline="") as outFile:
writer = csv.writer(outFile, delimiter=';',quotechar='|', quoting=csv.QUOTE_MINIMAL)
writer.writerows(result)
Note that the ; delimiter works for European Windows and might not work for you. In this case, use , instead.

This problem can be simplified by iterating through your dict to pull out your keys and values of those keys
count = {'lt60': {'a': 0, 'b': 0, 'c': 0, 'd': 0},
'ge60le90': {'a': 4, 'b': 0, 'c': 0, 'd': 0},
'gt90': {'a': 0, 'b': 1, 'c': 2, 'd': 1} }
# Create outfile
f = open("C:\\Users\\<USER>\\Desktop\\OUT.csv","w")
# Write first row
f.write(",a,b,c,d\n")
# Iterate through keys
for keys in count:
print(keys)
f.write(keys + ",")
KEYS = count[keys]
# Iterate though values
for values in KEYS:
print(KEYS[values])
f.write(str(KEYS[values]) + ",")
f.write("\n")
f.close()

Related

Parsing a distance matrix csv into python dictionary structure

I have a distance matrix laid out like this in a csv file
, A, B, C,
A, 0
B, 3, 0
C, 6, 4, 0
And I would like to parse it into a python dictionary like this...
graph = {'A': {'B': 3, 'C': 6},
'B': {'A': 3, 'C': 4},
'C': {'A': 6, 'B': 4}}
With the file you specified, you will never get that dict in graph. In any case, if you provide the correct CSV file, the code below will result in exactly what you want.
Just pay attention that inside the CSV file, you cannot have a comma in the end of the header row (first row), and you cannot have spaces in the column names (first row). Otherwise, you'll get a weird dict.
import pandas
import io
import math
d = pandas.read_csv('csv_file.csv',sep=',',header=0,index_col=0)
d_dict = d.to_dict() # use d.to_dict(orient='index') for the transpose
graph = { k.strip():{ k2.strip():v2 for k2,v2 in v.items() if not math.isnan(v2) } for k,v in d_dict.items() }
print(graph)
which generates the corresponding dict
{'A': {'A': 0, 'B': 3, 'C': 6},
'B': {'B': 0.0, 'C': 4.0},
'C': {'C': 0.0}}
the csv_file.csv
,A,B,C
A, 0
B, 3, 0
C, 6, 4, 0

Relationship graph in Python

I want to calculate number of friends for each person given a relationship graph without using any libraries. The graph is represented as lists of lists:
graph = [[A,B],[A,C],[C,B],[B,D],[E]]
Expected dictionary output: {'A':2, 'B':3, 'C':2, 'D':1, 'E':0}
Note: Since E has no friends, E should be 0
Straightforward solution without changing input format
>>> graph = [['A', 'B'], ['A', 'C'],['C', 'B'], ['B', 'D'], ['E']]
>>> from collections import defaultdict
>>> friends_counter = defaultdict(int)
>>> for friends in graph:
... for person in friends:
... friends_counter[person] += len(friends) - 1
>>> dict(friends_counter)
{'A': 2, 'B': 3, 'C': 2, 'D': 1, 'E': 0}
You could use a python library specific to graphs called NetworkX. I changed the data to be easier to load.
import networkx as nx
graph = [['A','B'],['A','C'],['C','B'],['B','D']]
G = nx.Graph()
G.add_edges_from(graph)
G.add_node('E')
dict(G.degree)
# {'A': 2, 'B': 3, 'C': 2, 'D': 1, 'E': 0}
Edit: this answer was given before the "without using any libraries" caveat was added.
Got the solution. Is there a better way to do this?
graph = [['A','B'],['A','C'],['C','B'],['B','D'],['E']]
dct ={}
for v in graph:
for x in v:
if x in v:
if x in dct.keys():
dct[x] += 1
else:
dct[x]= len(v)-1
print(dct)
{'A': 2, 'B': 3, 'C': 2, 'D': 1, 'E': 0}
so you can do like this
graph = [["A","B"],["A","C"],["C","B"],["B","D"],["E"]]
ans = {}
for n in graph:
if len(n) == 1:
ans[n[0]] = ans.get(n[0], 0)
else:
l, r = n
ans[l] = ans.get(l, 0) + 1
ans[r] = ans.get(r, 0) + 1
print(ans)
# {'A': 2, 'B': 3, 'C': 2, 'D': 1, 'E': 0}

Create a Dictionary from a Dataframe With the Index as the Keys

df.to_dict() creates a nested dictionary where the headers form the keys, {column:{index:value}}.
Is there an easy way to create a dictionary where the index forms the keys, {index:column:value}}? Or even {index:(column,value)}?
I can create the dictionary and then invert it, but I was wondering if this can be done in a single step.
Transpose the dataframe before you use df.to_dict.
df = pd.DataFrame({'a': [1, 3, 5], 'b': [2, 7, 5]})
print(df)
# a b
# 0 1 2
# 1 3 7
# 2 5 5
print(df.transpose().to_dict())
# {0: {'a': 1, 'b': 2},
# 1: {'a': 3, 'b': 7},
# 2: {'a': 5, 'b': 5}}

Performing circular shif on values in a dictionary

I have to construct a large dictionary which looks something like this
{'A' : {'A' : 1, 'B' : 0, 'C' : 0},
'B' : {'A' : 0, 'B' : 1, 'C' : 0}}
............................
Each inner dictionary is shifted by one position. Is there a way I can automate this process.
I can loop and use np.roll() function if it were ndarray so I am wondering if there's something similiar I could do with dictionaries.
You can use collections.deque for fast dictionary values (list) shifting (deque rotate function) but there is no specific function for dictionary, you should make it yourself, for example:
# shift dct (dict) values by n to right if n is positive
# and to left if n is negative; returns new dictionary
def dict_roll(dct, n):
shift_values = deque(dct.values())
shift_values.rotate(n)
return dict(zip(dct.keys(), shift_values))
Demo:
>>> d = {'A': {'A': 1, 'C': 0, 'B': 0}, 'B': {'A': 0, 'C': 0, 'B': 1}}
>>> for k in d:
... d[k] = dict_roll(d[k], 1)
...
>>> d
{'A': {'A': 0, 'C': 1, 'B': 0}, 'B': {'A': 1, 'C': 0, 'B': 0}}
>>> for k in d:
... d[k] = dict_roll(d[k], 1)
...
>>> d
{'A': {'A': 0, 'C': 0, 'B': 1}, 'B': {'A': 0, 'C': 1, 'B': 0}}
And another solution.
Solution 1:
out = dict()
syms = ['A', 'B', 'C']
for sym_outer in syms:
inner_dict = dict()
for sym_inner in syms:
inner_dict[sym_inner] = 0 if sym_inner != sym_outer else 1
out[sym_outer] = inner_dict
Solution 2:
This is a partial solution, but you get out['A']['A'] == 1 and out['A']['B'] == 0.
from collections import defaultdict
out = defaultdict(lambda: defaultdict(int))
for sym in ['A', 'B', 'C']:
out[sym][sym] = 1
This will create your string in r:
import string
r = {}
a = [1] + [0] * 25
for i in string.ascii_uppercase:
r[i] = dict(zip(string.ascii_uppercase,a))
a = a[-1:] + a[:-1]
print r
Bonus one-liner
If you are using Python 2.7+ or Python 3, then you can get a one-liner using dictionary comprehensions:
import string
{i:{j:1 if i==j else 0 for j in string.ascii_uppercase} for i in string.ascii_uppercase}

How to subtract values from dictionaries

I have two dictionaries in Python:
d1 = {'a': 10, 'b': 9, 'c': 8, 'd': 7}
d2 = {'a': 1, 'b': 2, 'c': 3, 'e': 2}
I want to substract values between dictionaries d1-d2 and get the result:
d3 = {'a': 9, 'b': 7, 'c': 5, 'd': 7 }
Now I'm using two loops but this solution is not too fast
for x,i in enumerate(d2.keys()):
for y,j in enumerate(d1.keys()):
I think a very Pythonic way would be using dict comprehension:
d3 = {key: d1[key] - d2.get(key, 0) for key in d1}
Note that this only works in Python 2.7+ or 3.
Use collections.Counter, iif all resulting values are known to be strictly positive. The syntax is very easy:
>>> from collections import Counter
>>> d1 = Counter({'a': 10, 'b': 9, 'c': 8, 'd': 7})
>>> d2 = Counter({'a': 1, 'b': 2, 'c': 3, 'e': 2})
>>> d3 = d1 - d2
>>> print d3
Counter({'a': 9, 'b': 7, 'd': 7, 'c': 5})
Mind, if not all values are known to remain strictly positive:
elements with values that become zero will be omitted in the result
elements with values that become negative will be missing, or replaced with wrong values. E.g., print(d2-d1) can yield Counter({'e': 2}).
Just an update to Haidro answer.
Recommended to use subtract method instead of "-".
d1.subtract(d2)
When - is used, only positive counters are updated into dictionary.
See examples below
c = Counter(a=4, b=2, c=0, d=-2)
d = Counter(a=1, b=2, c=3, d=4)
a = c-d
print(a) # --> Counter({'a': 3})
c.subtract(d)
print(c) # --> Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6})
Please note the dictionary is updated when subtract method is used.
And finally use dict(c) to get Dictionary from Counter object
Haidro posted an easy solution, but even without collections you only need one loop:
d1 = {'a': 10, 'b': 9, 'c': 8, 'd': 7}
d2 = {'a': 1, 'b': 2, 'c': 3, 'e': 2}
d3 = {}
for k, v in d1.items():
d3[k] = v - d2.get(k, 0) # returns value if k exists in d2, otherwise 0
print(d3) # {'c': 5, 'b': 7, 'a': 9, 'd': 7}

Categories

Resources