{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Introduction to statistics for Geoscientists (with Python)\n", "### Lecturer: Gerard Gorman\n", "### Lecture 8: Chi-squared tests and some miscellania\n", "### URL: [http://ggorman.github.io/Introduction-to-stats-for-geoscientists/](http://ggorman.github.io/Introduction-to-stats-for-geoscientists/)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Chi-squared test (or $\\chi^2$ test)\n", "\n", "The Chi-Squared test is used for discrete (categorised) data, e.g.:\n", "\n", "* Foot length – continuous.\n", "* Shoe size – discrete.\n", "\n", "Discrete geological data might be:\n", "\n", "* Fossil type (species A, species B, etc).\n", "* Rock classification (sandstone, limestone, mudstone, etc).\n", "* Fault type (normal, thrust, strike-slip, etc).\n", "\n", "The Chi-squared test provides a way of assessing how likely it is that counts of discrete data fit some expected pattern." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Chi-squared example\n", "\n", "We have many trilobite fossils from one deposit:\n", "\n", "* Fossils are moults.\n", "* Have cranidia, librigena, and pygidia.\n", "* Should have ratio of 1:2:1.\n", "\n", "Does our data depart from this? If it does we can infer a taphonomic bias - probably current-sorting.\n", "\n", "![trilobite](http://www.trilobites.info/cepthopyg.gif)\n", "\n", "![cranidium](http://upload.wikimedia.org/wikipedia/commons/thumb/1/19/Trilobite_cranidium-en.svg/270px-Trilobite_cranidium-en.svg.png)\n", "\n", "\n", "\n", "\n", "\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Chi-squared example\n", "\n", "Chi-squared test requires an observed/expected table of this form:\n", "\n", "| | Observation count | Expected (based on 1:2:1 ratio) |\n", "|:---------|:------------------|:--------------------------------|\n", "|Cranidia | 20 |17.25 |\n", "|Librigena | 32 |34.5 |\n", "|Pygidia | 17 |17.25 |\n", "|Total | 69 |69 |\n", "\n", "Python provides a chi-squared test via the method [scipy.stats.chisquare](http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.chisquare.html), which tests the null hypothesis that the categorical data has the given frequencies." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "p-value = 0.732278624487\n" ] } ], "source": [ "import numpy as np\n", "from scipy import stats\n", "\n", "Obs = np.array([20, 32, 17])\n", "Exp = np.array([17.25, 34.5, 17.25])\n", "s, p = stats.chisquare(Obs, Exp)\n", "print \"p-value = {}\".format(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Therefore we accept the null hypothesis - the data sample has the expected frequencies." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Chi-squared assumptions\n", "\n", "The Chi-squared test has wide applicability. Chi-Squared test quite broadly applicable. There is no requirement for anything to be normal, but:\n", "\n", "* No expected category should be less than 1 (it does not matter what the observed values are).\n", "* No more than one-fifth of expected categories should be less than 5." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Exercise 8.1: Chi-squared Test\n", "\n", "## Determine whether marks classifications for a course are atypical\n", "\n", "Analysis of 2000 overall course marks from ESESIS shows that the typical marks breakdown is as follows:\n", "\n", "Fail: 4.3%\n", "3rd: 9.5%\n", "2ii: 18.4%\n", "2i: 38.4%\n", "1st: 29.4%\n", "\n", "Now consider the following distribution of results from two different groups of students:\n", "\n", "|Grade | Students - group 1| Students - group 2|\n", "|:------|:------------------|:------------------|\n", "|Failed | 3 | 0 |\n", "|3rd | 10 | 8 |\n", "|2ii | 23 | 7 |\n", "|2i | 30 |25 |\n", "|1st | 20 |39 |\n", "\n", "**Consider each group in turn - are their results atypical?**\n", "\n", "## Tip 1: The chi-squared test is used to determine whether counts of discrete observations fit a predetermined pattern of expectations (see lecture notes).\n", "\n", "[scipy.stats.chisquare(Obs,Exp)](http://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.chisquare.html) – carry out a Chi-squared test on arrays Obs (Observed values) and Exp (Expected values)\n", "\n", "Returns a tuple of (s_statistic, p_value), where s_statistic is the value of Chi-squared (as normal you can probably ignore this), and p_value is the (two-tailed) probability of this result occurring by chance (i.e. of the observations actually fitting the expectations). Chi-squared tests are always two tailed – they only ever test differences between observed and expected – there is no concept of ‘direction’ of difference.\n", "\n", "IMPORTANT– the function takes numpy arrays, NOT normal python list. Use numpy array function to convert. Usage example:\n", "\n", "Obs = array([20, 32, 17])\n", "\n", "Exp = array([17.25, 34.5, 17.25])\n", "\n", "s, p = chisquare(Obs, Exp)\n", "\n", "## Tip 2: State your hypothesis.\n", "\n", "H0: Course has expected classification breakdown\n", "\n", "H1: Course classification breakdown does not follow expected pattern\n", "\n", "## Tip 3: To calculate Chi-squared you need a list of expected values.\n", "\n", "Find the total of the input values (you can use the built in sum function to do this), multiply this by each percentage value given above, and divide by 100. \n", "\n", "## Tip 4: Check the test is valid.\n", "\n", "You need to check two things:\n", "\n", "1. None of your expected values should be less than 1.\n", "2. No more than one (i.e. more than 1/5th) of them is less than 5." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# solution here" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Exercise 8.2\n", "\n", "Every day, you visit the JCR, Library Cafe, College Cafe and all the other taste imperial outlets, and count how many Chicken and Bacon baguettes they have on sale; how many Ham and Cheese baguettes there are; and how many Carrot and Hommous baguettes there are. You record the numbers in a nice table:\n", "\n", "|Day\\Baguette | C&B | H&C | C&H |\n", "|:-------------|:-----|:----|:----|\n", "|Monday | 32 | 35 | 38 |\n", "|Tuesday | 20 | 18 | 30 |\n", "|Wednesday | 27 | 29 | 8 |\n", "|Thursday | 16 | 19 | 10 |\n", "|Friday | 22 | 27 | 20 |\n", "\n", "You have procured all this information because you read somewhere that, supposedly, 20 of each type are being added by Taste Imperial each day and that approximately 20 of each are eaten each day. You realise the ideal distribution should be:\n", "\n", "|Day\\Baguette | C&B | H&C | C&H |\n", "|:-------------|:-----|:----|:----|\n", "|Monday | 20 | 20 | 20 |\n", "|Tuesday | 20 | 20 | 20 |\n", "|Wednesday | 20 | 20 | 20 |\n", "|Thursday | 20 | 20 | 20 |\n", "|Friday | 20 | 20 | 20 |\n", "\n", "Perform a chi-squared test and see if reality matches the statistic that you read about.\n", "\n", "(Note: All the above numbers have been invented and may not be anywhere close to the actual values)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# solution here" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.12" } }, "nbformat": 4, "nbformat_minor": 0 }