As others have pointed out, your comparison operations are skewed between the Frauds
fields and all other fields. Given that the data type appears to be different, I'm going to assume that you're doing the comparison correctly, and it's working as intended.
That said, the numbers you are using to subtract (0.1
) appear surprisingly large in relation to the values you are comparing them with. In one case, your initial value is 0.1, so subtracting 0.1 would result in comparing the new value > 0, which might not be what you intended.
Iterating the keys
You can use the dict.keys()
iterable to get all the keys for one of the dictionaries, and you can use Python's conditional expressions to evaluate your score.
Combine those together and you get:
def score_results(old, new):
""" Return a score based on the number of
'improved' fields of the new results over
the old.
"""
score = 0
for k in new.keys():
if k == 'Frauds':
score += 1 if new[k] > int(old[k] * 1.2) else 0
else:
score += 1 if new[k] > old[k] - 0.1 else 0
# NOTE: did you mean > old[k] * 0.9 ???
return score
Lambdas and defaults and iterables, oh my!
You can shorten this by putting your brain in Python-mode and treating code as data using Python's first-class functions. In this case, we'll make use of the lambda expression syntax, since the things we're doing are so short:
def score_results(old, new):
""" Idem. """
minor_change = lambda o: o - 0.1 # could be o * 0.9??
change_funcs = { 'Frauds': lambda o: int(o * 1.2) }
return sum((1 if new[k] > change_funcs.get(k, minor_change)(old[k]) else 0)
for k in new.keys())
In this version, I used the conditional-expression syntax from above to evaluate either 0 or 1 for each key k
. I used the sum()
built-in to add up the scores. This replaces the for k in new.keys()
loop with an iterable. The iterable I chose was the generator expression that looped over the k in new.keys()
.
I could have used an if
clause in the generator expression to skip over the Frauds
key. But we don't want to skip it, we want to compute it differently. So instead I built a dictionary where I could look up the keys. Every key would have a default behavior, except for special keys, by using the dict.get(key, default)
method. The special keys in this case are Frauds
:
change_funcs.get(k, minor_change)
Once I had the special function (for Frauds) or the default function (minor_change
for everything except Frauds) I could call it:
change_funcs.get(...)(old[k])
And then put it into the comparison with the new key as part of the conditional-expression.
int(bool) -> {0, 1}
Another "shortening" that could be made is to note that Python converts Boolean values to integers by mapping False
to 0
and True
to 1
. So instead of the conditional expression:
1 if cond else 0
we could simply use:
int(cond)
This converts our sum expression to:
return sum(int(new[k] > change_funcs.get(k, minor_change)(old[k])) for k in new.keys())
F1_new > (precision_current-(0.1))
. Shouldn't it beF1_new > (F1_current-(0.1))
? \$\endgroup\$