What would be the easiest/shortest/most-Pythonic way to get the weighted average of a
and b
?
a = (
{
0: {'P': 0.3, 'Z': 0.3, 'N': 0.3},
'P': {'P': 0.9, 'Z': 0.1, 'N': 0.0},
'Z': {'P': 0.1, 'Z': 0.9, 'N': 0.1},
'N': {'P': 0.0, 'Z': 0.1, 'N': 0.9}
},
{
'P': {'A': 0.3, 'C': 0.3, 'T': 0.2, 'G': 0.2},
'Z': {'A': 0.3, 'C': 0.3, 'T': 0.2, 'G': 0.2},
'N': {'A': 0.3, 'C': 0.3, 'T': 0.2, 'G': 0.2}
}
)
b = (
{
0: {'P': 0.3, 'Z': 0.3, 'N': 0.3},
'P': {'P': 0.3, 'Z': 0.3, 'N': 0.3},
'Z': {'P': 0.3, 'Z': 0.3, 'N': 0.3},
'N': {'P': 0.3, 'Z': 0.3, 'N': 0.3}
},
{
'P': {'A': 0.25, 'C': 0.25, 'T': 0.25, 'G': 0.25},
'Z': {'A': 0.25, 'C': 0.25, 'T': 0.25, 'G': 0.25},
'N': {'A': 0.25, 'C': 0.25, 'T': 0.25, 'G': 0.25}
}
)
So that the resulting c = [(a * a_weight) + (b * b_weight) / (a_weight + b_weight)]
should have the same structure (as a
and b
).
Should anyone know the Pythonic answer, thank you.
c
structureFor instance, if a_weight
= b_weight
= 0.5 (a simple average), then c
's first 'P':
line
'P': {'P': (0.9 + 0.3) / 2, 'Z': (0.1 + 0.3) / 2, 'N': (0.0 + 0.3) / 2}
would be an average of
a
's 'P': {'P': 0.9, 'Z': 0.1, 'N': 0.0}
and
b
's 'P': {'P': 0.3, 'Z': 0.3, 'N': 0.3}
.
Basically, just an average of value
s (while every key
stays as is).
I'd make a function that accepts two inputs and converts them recursively according to their type:
def combine(a, b, a_weight, b_weight):
if isinstance(a, tuple):
return tuple(combine(x,y,a_weight,b_weight) for x,y in zip(a,b))
elif isinstance(a, dict):
return dict((k, combine(a[k],b[k],a_weight,b_weight)) for k in a)
#add other data structures here if you need to (e.g. list, set, etc.)
else: #assume a number
return ((a * a_weight) + (b * b_weight)) / (a_weight + b_weight)
The nice thing about this method is that it will keep working even if you change the structure of the inputs.
Note that this code assumes that the structure of a
and b
is the same, the tuples have the same number of elements, and the dictionaries have the same keys. If this is not always the case you'd need to add code to verify this.