title: Calculating Precision, Recall and F-score in one pass - python
body: <p><a href="https://en.wikipedia.org/wiki/Precision_and_recall">Accuracy, precision, recall and f-score</a> are measures of a system quality in machine-learning systems. It depends on a confusion matrix of True/False Positives/Negatives.</p>
  
  <p>Given a binary classification task, I have tried the following to get a function that returns accuracy, precision, recall and f-score:</p>
  
  <pre><code>gold = [1] + [0] * 9
  predicted = [1] * 10
  
  def evaluation(gold, predicted):
    true_pos = sum(1 for p,g in zip(predicted, gold) if p==1 and g==1)
    true_neg = sum(1 for p,g in zip(predicted, gold) if p==0 and g==0)
    false_pos = sum(1 for p,g in zip(predicted, gold) if p==1 and g==0)
    false_neg = sum(1 for p,g in zip(predicted, gold) if p==0 and g==1)
    try:
      recall = true_pos / float(true_pos + false_neg)
    except:
      recall = 0
    try:
      precision = true_pos / float(true_pos + false_pos)
    except:
      precision = 0
    try:
      fscore = 2*precision*recall / (precision + recall)
    except:
      fscore = 0
    try:
      accuracy = (true_pos + true_neg) / float(len(gold))
    except:
      accuracy = 0
    return accuracy, precision, recall, fscore
  </code></pre>
  
  <p>But it seems like I have redundantly looped through the dataset 4 times to get the True/False Positives/Negatives.</p>
  
  <p>Also the multiple <code>try-excepts</code> to catch the <code>ZeroDivisionError</code> is a little redundant.</p>
  
  <p><strong>So what is the pythonic way to get the counts of the True/False Positives/Negatives without multiple loops through the dataset?</strong></p>
  
  <p><strong>How do I pythonically catch the <code>ZeroDivisionError</code> without the multiple try-excepts?</strong></p>
  
  <hr>
  
  <p>I could also do the following to count the True/False Positives/Negatives in one loop but <strong>is there an alternative way without the multiple <code>if</code>?</strong>:</p>
  
  <pre><code>for p,g in zip(predicted, gold):
      if p==1 and g==1:
          true_pos+=1
      if p==0 and g==0:
          true_neg+=1
      if p==1 and g==0:
          false_pos+=1
      if p==0 and g==1:
          false_neg+=1
  </code></pre>