How to create a dictionary of permutation values? - python

I need to assign 0 and 1 as values to keys in the dictionaries:
combinations_string_list = [num_list_to_str(i) for i in itertools.product([0, 1], repeat=2)]
all_stategy = []
for i in range(16):
strategy_table = {x: y for x in combinations_string_list for y in [0, 1]}
all_stategy.append(strategy_table)
print(all_stategy)
I got [{'00': 1, '01': 1, '10': 1, '11': 1}, {'00': 1, '01': 1, '10': 1, '11': 1}, {'00': 1, '01': 1, '10': 1, '11': 1}, ...]
but I need [{'00': 0, '01': 0, '10': 0, '11': 0}, {'00': 0, '01': 0, '10': 0, '11': 1}, {'00': 0, '01': 0, '10': 1, '11': 0}, ...] instead.
How can I create this kind of value? Thanks!

You can zip the key sequence ["0", "1"] with each element of the cartesian product to produce input to dict:
>>> [dict(zip(["0", "1"], x)) for x in product([0,1], repeat=2)]
[{'0': 0, '1': 0}, {'0': 0, '1': 1}, {'0': 1, '1': 0}, {'0': 1, '1': 1}]
or
>>> values=[0,1]
>>> [dict(zip(map(str, values), x)) for x in product(values, repeat=2)]

Related

Plot graph in python where the width of each edge denotes the strength or frequency of cooccurrence

I have a dataframe of three classes (0, 1, and 2). After that, I calculate the cooccurrence of the class. Further, the diagonal element is assigned to 0. In conclusion, try to plot a cooccurrence graph with the width of each edge which denotes the strength or frequency of cooccurrence
# Python code demonstrate how to create
# Pandas DataFrame by lists of dicts.
import pandas as pd
import numpy as np
# Initialize data to lists.
data = [{'0': 1, '1': 0, '2': 1},
{'0': 1, '1': 0, '2': 1},
{'0': 1, '1': 1, '2': 0},
{'0': 1, '1': 0, '2': 1},
{'0': 1, '1': 1, '2': 0},
{'0': 0, '1': 0, '2': 1},
{'0': 1, '1': 0, '2': 1},
{'0': 0, '1': 0, '2': 0},
{'0': 1, '1': 1, '2': 1},
{'0': 0, '1': 1, '2': 0},
{'0': 1, '1': 0, '2': 1},
{'0': 0, '1': 1, '2': 0},
{'0': 1, '1': 0, '2': 0},
{'0': 0, '1': 1, '2': 1}]
# Creates DataFrame.
df = pd.DataFrame(data)
# Print the data
df
#Find Co-occurence
df_asint = df.astype(int)
coocc = df_asint.T.dot(df_asint)
coocc
#Assign diagonal=0
np.fill_diagonal(coocc.values,0)
coocc
#plot the graph
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib
A=np.matrix(coocc)
G=nx.from_numpy_matrix(A)
#fig = plt.figure(1, figsize=(10, 80), dpi=30)
f = plt.figure()
plt.axis('off')
nx.draw_networkx(nx.from_pandas_adjacency(coocc),ax=f.add_subplot(111),node_color=["cyan",
"Red","yellow"],node_size=350)
now I would like to plot the width of each edge which denotes the strength or frequency of cooccurrence
The only substantial thing you needed to add was creating a list of weights and passing it to the nx.draw_networkx function as width=weights.
Below is the updated code:
import pandas as pd
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
import matplotlib as mpl
# Initialize data to lists.
data = [{'0': 1, '1': 0, '2': 1},
{'0': 1, '1': 0, '2': 1},
{'0': 1, '1': 1, '2': 0},
{'0': 1, '1': 0, '2': 1},
{'0': 1, '1': 1, '2': 0},
{'0': 0, '1': 0, '2': 1},
{'0': 1, '1': 0, '2': 1},
{'0': 0, '1': 0, '2': 0},
{'0': 1, '1': 1, '2': 1},
{'0': 0, '1': 1, '2': 0},
{'0': 1, '1': 0, '2': 1},
{'0': 0, '1': 1, '2': 0},
{'0': 1, '1': 0, '2': 0},
{'0': 0, '1': 1, '2': 1}]
# Creates DataFrame.
df = pd.DataFrame(data)
# Print the data
df
#Find Co-occurence
df_asint = df.astype(int)
coocc = df_asint.T.dot(df_asint)
coocc
#Assign diagonal=0
np.fill_diagonal(coocc.values,0)
coocc
#plot the graph
A=np.matrix(coocc)
G=nx.from_numpy_matrix(A)
# store the weights in a list
weights = [G[u][v]['weight'] for u,v in G.edges()]
# initialize the figure
fig, ax = plt.subplots()
# draw the graph with edge size given by the weight
nx.draw_networkx(G, ax=ax, width=weights, node_color=["cyan", "Red","yellow"], node_size=350)
# remove the axis
plt.axis('off')

Sum values from nested dictionary - Python

Say I have the following dictionary
counts =
{(0, 0): {'00': 0, '01': 4908, '10': 0, '11': 5092},
(0, 1): {'00': 0, '01': 5023, '10': 0, '11': 4977},
(1, 0): {'00': 0, '01': 5058, '10': 0, '11': 4942},
(1, 1): {'00': 0, '01': 4965, '10': 0, '11': 5035}}
and I want to sum counts[0,0] and counts [0, 1]to get
idealcounts = {'00': 0, '01': 9931, '10': 0, '11': 10069}
How do I extract the counts[0,r] values and then sum them all up?
Thank you for your help.
You can just use collections.Counter and update it with the sub-dictionaries you want:
from collections import Counter
data = {
(0, 0): {'00': 0, '01': 4908, '10': 0, '11': 5092},
(0, 1): {'00': 0, '01': 5023, '10': 0, '11': 4977},
(1, 0): {'00': 0, '01': 5058, '10': 0, '11': 4942},
(1, 1): {'00': 0, '01': 4965, '10': 0, '11': 5035}
}
counts = Counter()
for k in ((0, 0), (0, 1)):
counts.update(Counter(data[k]))
print(counts)
# Counter({'00': 0, '01': 9931, '10': 0, '11': 10069})

increment value in dictionary based on key in another dictionary

I have a masterDict dictionary with keys "1" through "8" with values set to 0
{'1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, '8': 0}
I also have anotherDict that i'm using to find the key containing a value closest to another value (i'm doing this multiple times with different values).
An example of one of those other values would be value1 = 900
An example of anotherDict would be:
{'1': 74, '2': 938, '3': 28, '4': 10, '5': 100, '6': 33, '7': 45, '8': 99}
The code i'm using to find the value closest to value1 in anotherDict is:
closestValue1 = key, value = min(anotherDict.items(), key=lambda (_, v): abs(v - value1))
In this case, closestValue1 returns:
{'2': 938}
How do I take this and increment the key 2 value in masterDict by 1?
So, masterDict would then contain:
{'1': 0, '2': 1, '3': 0, '4': 0, '5': 0, '6':0, '7':0, '8': 0}
master_dict = {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, '8': 0}
another_dict = {'1': 74, '2': 938, '3': 28, '4': 10, '5': 100, '6': 33, '7': 45, '8': 99}
target_val = 900
target_key, _ = min(another_dict.items(), key=lambda x: abs(target_value-x[1]))
master_dict[target_key]+=1
print (master_dict)

Summing values in dictionary of dictionaries

I got something like this:
> d1 = {'System tests': {'failed': 5, 'passed': 0, 'total': 5},
'Func tests': {'failed': 5, 'passed': 0, 'total': 5}}
> d2 = {'System tests': {'failed': 1, 'passed': 1, 'total': 2},
'Func tests': {'failed': 3, 'passed': 2, 'total': 5}}
> d3 = {'System tests': {'failed': 0, 'passed': 0, 'total': 0},
'Func tests': {'failed': 1, 'passed': 0, 'total': 1}}
I would like to sum values 'failed', passed and total into one dictionary
so the output should be like this:
d4 = {'System tests': {'failed': 6, 'passed': 1, 'total': 7},
'Func tests': {'failed': 9, 'passed': 2, 'total': 11}
What is the easiest solution to do such thing?
I can use basic libraries, except collections.
The solution must be generic, for example if some other dictionaries would appear in the future
input:
d1 = {'a': 100, 'b': 200, 'c':300}
d2 = {'a': 300, 'b': 200, 'd':400}
d = {k : d1.get(k, 0) + d2.get(k,0) for k in set(d1.keys()) | set(d2.keys())}
Output:
{'a': 400, 'b': 400, 'c': 300, 'd': 400}
Using Counter and defaultdict that is fairly straight forward like:
Code:
d4 = defaultdict(Counter)
for d in d1, d2, d3:
for k, subd in d.items():
d4[k].update(subd)
Test Code:
d1 = {'System tests': {'failed': 5, 'passed': 0, 'total': 5},
'Func tests': {'failed': 5, 'passed': 0, 'total': 5}}
d2 = {'System tests': {'failed': 1, 'passed': 1, 'total': 2},
'Func tests': {'failed': 3, 'passed': 2, 'total': 5}}
d3 = {'System tests': {'failed': 0, 'passed': 0, 'total': 0},
'Func tests': {'failed': 1, 'passed': 0, 'total': 1}}
from collections import Counter, defaultdict
d4 = defaultdict(Counter)
for d in d1, d2, d3:
for k, subd in d.items():
d4[k].update(subd)
print(d4)
Results:
defaultdict(<class 'collections.Counter'>, {
'System tests': Counter({'total': 7, 'failed': 6, 'passed': 1}),
'Func tests': Counter({'total': 11, 'failed': 9, 'passed': 2})
})
This will give you the output you are looking for, with no libraries.
d4 = {}
for d in d1, d2, d3:
for test, results in d.items():
if test not in d4:
d4[test] = {}
for key, value in results.items():
if key in d4[test]:
d4[test][key] += value
else:
d4[test][key] = value
Result:
{'System tests': {'failed': 6, 'passed': 1, 'total': 7}, 'Func tests': {'failed': 9, 'passed': 2, 'total': 11}}
If you cannot use collections.Counter, another solution is to use reduce
from functools import reduce # reduce was moved here in Python3
def add_dicts(dict_list):
def add(fst, snd):
return {k: fst[k] + snd[k] for k in fst}
return reduce(add, dict_list[1:], dict_list[0])
Using this in your code would look like this.
dict_list = [d1, d2, d3]
d4 = {}
for k in dict_list[0]:
d4[k] = add_dicts([d[k] for d in dict_list])
Although, this assumes all your dict are correctly formated.
You can use zip along with dict.items:
d1 = {'System tests': {'failed': 5, 'passed': 0, 'total': 5},
'Func tests': {'failed': 5, 'passed': 0, 'total': 5}}
d2 = {'System tests': {'failed': 1, 'passed': 1, 'total': 2},
'Func tests': {'failed': 3, 'passed': 2, 'total': 5}}
d3 = {'System tests': {'failed': 0, 'passed': 0, 'total': 0},
'Func tests': {'failed': 1, 'passed': 0, 'total': 1}}
def combine_dicts(*d):
return {a:{i:sum(h[i] for h in [b, c, d]) for i in ['failed', 'passed', 'total']} for [a, b], [_, c], [_, d] in zip(*d)}
print(combine_dicts(d1.items(), d2.items(), d3.items()))
Output:
{'System tests': {'failed': 6, 'total': 7, 'passed': 1}, 'Func tests': {'failed': 9, 'total': 11, 'passed': 2}}

Dynamically join of dictionary

a="90342"
# this used to generate a dict of each char in a and it indexs
modchar=[{i:a.index(i)} for i in a ]
#modchar=[{'9': 0}, {'0': 1}, {'3': 2}, {'4': 3}, {'2': 4}]
# below produce combination now this combination
def combination(x,n):
return list(itertools.combinations(x,n))
combination(modchar,1)
#output [({'9': 0},), ({'0': 1},), ({'3': 2},), ({'4': 3},), ({'2': 4},)]
combination(modchar,2)
#output [({'9': 0}, {'0': 1}), ({'9': 0}, {'3': 2}), ({'9': 0}, {'4': 3}), ({'9': 0}, {'2': 4}), ({'0': 1}, {'3': 2}), ({'0': 1}, {'4': 3}), ({'0': 1}, {'2': 4}), ({'3': 2}, {'4': 3}), ({'3': 2}, {'2': 4}), ({'4': 3}, {'2': 4})]
combination(modchar,3)
#output [({'9': 0}, {'0': 1}, {'3': 2}), ({'9': 0}, {'0': 1}, {'4': 3}), ({'9': 0}, {'0': 1}, {'2': 4}), ({'9': 0}, {'3': 2}, {'4': 3}),....]
if u look at each result in the list first element is tuple of dict.what i want to do is to combine the dictionary inside the tuple and make it as single dict
i have tried
map(lambda x:dict(x[0],**x[1]),list(itertools.combinations(x,n)))
above works only for tuple of two dicts.
how can i produce a code dynamically it should combine all dicts and produce single dict irrespictive of n value in combination(x,n)
expected output: for n=2
[({'9': 0,'0': 1}) ....]
expected output: for n=3
[({'9': 0,'0': 1,'3': 2})..]
Here's a way to do it:
combos = combinations(modchar,3)
def combineDictTuple(dt):
d = {}
for item in dt:
d.update(item)
return d
newCombos = [combineDictTuple(dt) for dt in combos]
# OUTPUT: [{'9': 0, '0': 1, '3': 2}, {'9': 0, '0': 1, '4': 3}, {'9': 0, '0': 1, '2': 4}, {'9': 0, '3': 2, '4': 3}, {'9': 0, '3': 2, '2': 4}, {'9': 0, '2': 4, '4': 3}, {'0': 1, '3': 2, '4': 3}, {'0': 1, '3': 2, '2': 4}, {'0': 1, '2': 4, '4': 3}, {'3': 2, '2': 4, '4': 3}]
This should do what you want:
>>> def update_with_return(d1, d2):
... d1.update(d2)
... return d1
...
>>> reduce(update_with_return, ({'a': 1}, {'b':2}), dict())
{'a': 1, 'b': 2}

Categories