Sebastian Raschka
last updated: 05/25/2014

I would be happy to hear your comments and suggestions.
Please feel free to drop me a note via twitter, email, or google+.

Day 2 - One Python Benchmark per Day

Calculating sample means

Mean functions

In [1]:
# The statistics module has been added to
# the standard library in Python 3.4

import statistics as stats
import numpy as np

def calc_mean(samples):
    return sum(samples)/float(len(samples))

def np_mean(samples):
    return np.mean(samples)

def np_mean_ary(np_array):
    return np.mean(np_array)

def st_mean(samples):
    return stats.mean(samples)

def np_convert_and_mean_ary(samples):
    return np.mean(np.array(samples))

Verifying that functions work correctly

In [2]:
n = 1000
samples = list(range(n))
samples_array = np.arange(n)

assert(st_mean(samples) == np_mean(samples)
       == calc_mean(samples) == np_mean_ary(samples_array) == np_convert_and_mean_ary(samples))


In [3]:
import timeit

funcs = ['st_mean', 'np_mean', 'calc_mean', 'np_mean_ary', 'np_convert_and_mean_ary']
orders_n = [10**n for n in range(1, 6)]
times_n = {f:[] for f in funcs}

for n in orders_n:
    samples = list(range(n))
    for f in funcs:
        if f == 'np_mean_ary':
            samples = np.arange(n)
        times_n[f].append(min(timeit.Timer('%s(samples)' %f, 
                'from __main__ import %s, samples' %f)
                    .repeat(repeat=3, number=1000)))

Setting up the plot

In [4]:
import platform
import multiprocessing

def print_sysinfo():
    print('\nPython version:', platform.python_version())
    print('NumPy version', np.__version__)
    print('compiler:', platform.python_compiler())
    print('\nsystem     :', platform.system())
    print('release    :', platform.release())
    print('machine    :', platform.machine())
    print('processor  :', platform.processor())
    print('interpreter:', platform.architecture()[0])
    print('CPU count  :', multiprocessing.cpu_count())
In [5]:
%matplotlib inline
In [6]:
import matplotlib.pyplot as plt

def plot_timing():

    labels = [('st_mean', 'statistics.mean()'), 
          ('np_mean', 'numpy.mean() on list'),
          ('np_mean_ary', 'numpy.mean() on array'),
          ('calc_mean', 'sum(samples)/len(samples)'),
          ('np_convert_and_mean_ary', 'convert to array then numpy.mean()')

    plt.rcParams.update({'font.size': 12})

    fig = plt.figure(figsize=(10,8))
    for lb in labels:
        plt.plot(orders_n, times_n[lb[0]], 
             alpha=0.5, label=lb[1], marker='o', lw=3)
    plt.xlabel('sample size n')
    plt.ylabel('time per computation in milliseconds [ms]')
    plt.title('Performance of different approaches for calculating sample means')

    max_perf = max( s/c for s,c in zip(times_n['st_mean'],
                                   times_n['np_convert_and_mean_ary']) )
    min_perf = min( s/c for s,c in zip(times_n['st_mean'],
                                   times_n['np_convert_and_mean_ary']) )

    ftext = 'Converting a list to a numpy array and then using numpy.mean() \n is {:.2f}x to '\
        '{:.2f}x faster than statistics.mean() on lists'\
        .format(min_perf, max_perf)
    plt.figtext(.14,.15, ftext, fontsize=11, ha='left')


In [7]:
('\nPython version:', '2.7.5')
('NumPy version', '1.6.2')
('compiler:', 'GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)')
('\nsystem     :', 'Darwin')
('release    :', '13.4.0')
('machine    :', 'x86_64')
('processor  :', 'i386')
('interpreter:', '64bit')
('CPU count  :', 8)

In [7]: