{"id":244,"date":"2015-06-26T07:53:04","date_gmt":"2015-06-26T07:53:04","guid":{"rendered":"http:\/\/blog.tiran.info\/?p=244"},"modified":"2015-06-26T07:53:04","modified_gmt":"2015-06-26T07:53:04","slug":"anova-a-un-facteur-avec-oracle","status":"publish","type":"post","link":"https:\/\/blog.tiran.stream\/?p=244","title":{"rendered":"ANOVA \u00e0 un facteur avec Oracle"},"content":{"rendered":"<p style=\"text-align: justify;\">Je suis tomb\u00e9 r\u00e9cemment sur un <a href=\"http:\/\/www.lesechos.fr\/10\/07\/2014\/lesechos.fr\/0203635175441_la-guerre-des-prix-s-intensifie-dans-les-stations-service.htm\" target=\"_blank\">article<\/a> d\u00e9crivant la concurrence acharn\u00e9e entre les grandes surfaces et les stations-service sur le march\u00e9 du carburant.\u00a0Cela m&rsquo;a donn\u00e9 envie d&rsquo;en savoir davantage et surtout de v\u00e9rifier par moi-m\u00eame si cette guerre des prix \u00e9tait \u00ab\u00a0visible\u00a0\u00bb lorsqu&rsquo;on s&rsquo;int\u00e9ressait globalement aux tarifs \u00e0 la pompe.<\/p>\n<p style=\"text-align: justify;\">Les prix de vente des carburants font l&rsquo;objet d&rsquo;un suivi permanent par le minist\u00e8re de l&rsquo;\u00e9conomie qui met \u00e0 disposition un relev\u00e9 quotidien: <a href=\"http:\/\/www.prix-carburants.gouv.fr\/rubrique\/opendata\/\" target=\"_blank\">http:\/\/www.prix-carburants.gouv.fr\/rubrique\/opendata\/<\/a><\/p>\n<p style=\"text-align: justify;\">Une r\u00e9utilisation de ces donn\u00e9es incluant la marque des stations-services (\u00e0 partir des donn\u00e9es GPS j&rsquo;imagine) est accessible via le portail OpenDataSoft:<br \/>\n<a href=\"http:\/\/public.opendatasoft.com\/explore\/dataset\/prix_des_carburants_j_7\/?tab=metas\" target=\"_blank\">http:\/\/public.opendatasoft.com\/explore\/dataset\/prix_des_carburants_j_7\/?tab=metas<\/a><\/p>\n<p style=\"text-align: justify;\">Avec l&rsquo;information de la marque des stations, on peut r\u00e9aliser des groupements en fonction du type de distributeur: \u00ab\u00a0Grande Distribution\u00a0\u00bb (enseignes comme Carrefour, Leclerc etc&#8230;), \u00ab\u00a0Distributeur\u00a0\u00bb (enseignes de vente des soci\u00e9t\u00e9s p\u00e9troli\u00e8res comme Total, BP etc&#8230;), \u00ab\u00a0Distributeur Low-Cost\u00a0\u00bb (enseignes automatis\u00e9es des soci\u00e9t\u00e9s p\u00e9troli\u00e8res comme Total Access et Esso Express) et Autres pour le reste (Distributeurs Ind\u00e9pendants, petites chaines non-affili\u00e9es etc&#8230;). On peut ensuite r\u00e9aliser des comparaisons du prix moyen de vente pour chacun de ces groupes.<\/p>\n<p style=\"text-align: justify;\">Pour cela, j&rsquo;utilise un test <a href=\"https:\/\/fr.wikipedia.org\/wiki\/Analyse_de_la_variance\" target=\"_blank\">ANOVA<\/a> qui permet de d\u00e9terminer s&rsquo;il existe des diff\u00e9rences de moyenne statistiquement significatives entre les \u00e9chantillons (i.e. H0: les \u00e9chantillons sont issus d&rsquo;une m\u00eame population). Comme le test permet de traiter plusieurs groupes simultan\u00e9ment, on \u00e9vite ainsi la multiplication de tests t (et l&rsquo;augmentation associ\u00e9e du risque alpha de premi\u00e8re esp\u00e8ce).<\/p>\n<p style=\"text-align: justify;\">L&rsquo;ANOVA repose sur l&rsquo;\u00e9quation d&rsquo;analyse de variance SCT = SCE + SCR\u00a0avec:<\/p>\n<ul style=\"text-align: justify;\">\n<li>SCT: Somme des Carr\u00e9s Totaux ou Variance Totale<\/li>\n<li>SCE: Somme des Carr\u00e9s des Ecarts Interclasse ou Variance Intergroupes<\/li>\n<li>SCR: Somme des Carr\u00e9s des R\u00e9sidus (Ecarts Intraclasse) ou Variance Intragroupe<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">Les conditions d&rsquo;utilisation du test sont l&rsquo;ind\u00e9pendance, la normalit\u00e9 et l&rsquo;homosc\u00e9dasticit\u00e9 des \u00e9chantillons compar\u00e9s. L&rsquo;ind\u00e9pendance d\u00e9pend du mode op\u00e9ratoire et la normalit\u00e9 est peu probl\u00e9matique si l&rsquo;effectif est grand.<\/p>\n<p style=\"text-align: justify;\">En revanche, la condition d&rsquo;homosc\u00e9dasticit\u00e9 est plus \u00e9pineuse (et ce d&rsquo;autant plus que les effectifs des \u00e9chantillons sont diff\u00e9rents).\u00a0En pratique:<\/p>\n<ul style=\"text-align: justify;\">\n<li style=\"text-align: justify;\">si les plus petits \u00e9chantillons proviennent d&rsquo;une population avec la variance la plus importante, le test devient plus \u00ab\u00a0lib\u00e9ral\u00a0\u00bb = fausse significativit\u00e9<\/li>\n<li style=\"text-align: justify;\">si les plus petits \u00e9chantillons proviennent d&rsquo;une population avec la variance la moins importante, le test devient plus \u00ab\u00a0conservatif\u00a0\u00bb = mauvaise d\u00e9tection<\/li>\n<\/ul>\n<p style=\"text-align: justify;\">La r\u00e8gle approximative est que l&rsquo;ANOVA est robuste pour des \u00e9chantillons dont le rapport de variance n&rsquo;exc\u00e8de pas 4:1. Au-del\u00e0, dans la limite du raisonnable, on peut essayer de compenser en diminuant le niveau alpha du test.<\/p>\n<p style=\"text-align: justify;\">Oracle propose la fonction <a href=\"http:\/\/docs.oracle.com\/database\/121\/SQLRF\/functions189.htm#SQLRF06322\" target=\"_blank\">STATS_ONE_WAY_ANOVA<\/a> pour r\u00e9aliser des test ANOVA a un facteur.<br \/>\nLe fichier de donn\u00e9es utilis\u00e9 dans cette analyse est disponible ici:\u00a0<a href=\"https:\/\/blog.tiran.stream\/wp-content\/uploads\/2015\/06\/prix_des_carburants_j_7.zip\">prix_des_carburants_j_7<\/a><\/p>\n<p style=\"text-align: justify;\"><strong>Chargement des donn\u00e9es via une table externe<\/strong><\/p>\n<pre>SQL&gt; CREATE TABLE exttab_carburants\n  2  (\n  3     Id          NUMBER,\n  4     CP          VARCHAR2 (20),\n  5     Axe         VARCHAR2 (5),\n  6     Adresse     VARCHAR2 (200),\n  7     Ville       VARCHAR2 (50),\n  8     HO          VARCHAR2 (30),\n  9     HF          VARCHAR2 (30),\n 10     JF          VARCHAR2 (200),\n 11     TF          VARCHAR2 (50),\n 12     DF          VARCHAR2 (20),\n 13     FF          VARCHAR2 (20),\n 14     Carburant   VARCHAR2 (50),\n 15     Rupture     VARCHAR2 (30),\n 16     MAJ         VARCHAR2 (30),\n 17     PGazole     VARCHAR2 (30),\n 18     PSP95       VARCHAR2 (30),\n 19     PSP98       VARCHAR2 (30),\n 20     PGPL        VARCHAR2 (30),\n 21     PE10        VARCHAR2 (30),\n 22     PE85        VARCHAR2 (30),\n 23     Services    VARCHAR2 (500),\n 24     Marque      VARCHAR2 (500),\n 25     Nom         VARCHAR2 (500),\n 26     GeoPoint    VARCHAR2 (50)\n 27  )\n 28  ORGANIZATION EXTERNAL\n 29     (TYPE oracle_loader\n 30           DEFAULT DIRECTORY datadir\n 31              ACCESS PARAMETERS\n 32                  (\n 33                  RECORDS DELIMITED BY NEWLINE\n 34                  SKIP 1\n 35                  FIELDS TERMINATED BY ';' OPTIONALLY ENCLOSED BY '\"'\n 36                  MISSING FIELD VALUES ARE NULL)\n 37           LOCATION ('prix_des_carburants_j_7.csv'));\n\nTable created.\n\nSQL&gt;<\/pre>\n<p style=\"text-align: justify;\"><strong>Groupement des donn\u00e9es par une vue<\/strong><\/p>\n<p style=\"text-align: justify;\">On s&rsquo;int\u00e9resse uniquement aux donn\u00e9es r\u00e9centes (de la semaine pass\u00e9e) hors stations d&rsquo;autoroute.<\/p>\n<pre>SQL&gt; CREATE OR REPLACE VIEW CARBURANTS\n  2  AS\n  3     SELECT marque,\n  4            TO_NUMBER (pgazole) prix_gazole,\n  5            CASE\n  6               WHEN marque IN ('Agip',\n  7                               'Esso',\n  8                               'BP',\n  9                               'Avia',\n 10                               'Total',\n 11                               'Elan',\n 12                               'Shell',\n 13                               'Dyneff',\n 14                               'VITO')\n 15               THEN\n 16                  'Distributeur'\n 17               WHEN marque IN ('Intermarch\u00e9',\n 18                               'Syst\u00e8me U',\n 19                               'Auchan',\n 20                               'Leclerc',\n 21                               'Carrefour',\n 22                               'Carrefour Market',\n 23                               'Carrefour Contact',\n 24                               'Atac',\n 25                               'Casino',\n 26                               'Colruyt',\n 27                               'CORA',\n 28                               'G\u00e9ant',\n 29                               'Netto',\n 30                               'Leader Price',\n 31                               'Ecomarch\u00e9',\n 32                               'Intermarch\u00e9 Contact',\n 33                               'Super Casino',\n 34                               'Supermarch\u00e9 Match',\n 35                               'Simply Market',\n 36                               'Shopi')\n 37               THEN\n 38                  'Grande Distribution'\n 39               WHEN marque IN ('Esso Express', 'Total Access')\n 40               THEN\n 41                  'Distributeur Low Cost'\n 42               ELSE\n 43                  'Autre'\n 44            END\n 45               type_distrib\n 46       FROM exttab_carburants\n 47      WHERE     TO_DATE (SUBSTR (maj, 1, 10), 'YYYY-MM-DD') &gt;=\n 48                   TO_DATE ('03\/06\/2015', 'DD\/MM\/YYYY')\n 49            AND pgazole IS NOT NULL\n 50            AND axe != 'A';\n\nView created.\n\nSQL&gt;\n<\/pre>\n<p style=\"text-align: justify;\">On obtient donc 4 classes:<\/p>\n<ul>\n<li style=\"text-align: justify;\">Grande Distribution<\/li>\n<li style=\"text-align: justify;\">Distributeur<\/li>\n<li style=\"text-align: justify;\">Distributeur Low-Cost<\/li>\n<li style=\"text-align: justify;\">Autre<\/li>\n<\/ul>\n<p>La classe \u00ab\u00a0Autre\u00a0\u00bb repr\u00e9sentant une grande h\u00e9t\u00e9rog\u00e9n\u00e9it\u00e9 dans ses membres sera ignor\u00e9e dans la suite.<\/p>\n<p style=\"text-align: justify;\"><strong>V\u00e9rification de l&rsquo;homosc\u00e9dasticit\u00e9<\/strong><\/p>\n<pre>SQL&gt;   SELECT type_distrib, VAR_SAMP (prix_gazole), COUNT (*)\n  2      FROM carburants\n  3     WHERE type_distrib != 'Autre'\n  4  GROUP BY type_distrib;\n\nTYPE_DISTRIB          VAR_SAMP(PRIX_GAZOLE)   COUNT(*)\n--------------------- --------------------- ----------\nDistributeur                     .001094295       1203\nDistributeur Low Cost            .000223032        358\nGrande Distribution              .000717468       3834\n\nSQL&gt;<\/pre>\n<p style=\"text-align: justify;\">Ici, les effectifs sont in\u00e9gaux et le rapport entre les variances min\/max est de 4.9:1.<br \/>\nOn est donc aux limites d&rsquo;applicabilit\u00e9 du test.<\/p>\n<p style=\"text-align: justify;\"><strong>R\u00e9alisation du test<\/strong><\/p>\n<pre>SQL&gt; SELECT STATS_ONE_WAY_ANOVA (type_distrib, prix_gazole, 'SUM_SQUARES_BETWEEN')\n  2            SUM_SQUARES_BETWEEN,\n  3         STATS_ONE_WAY_ANOVA (type_distrib, prix_gazole, 'SUM_SQUARES_WITHIN')\n  4            SUM_SQUARES_WITHIN,\n  5         STATS_ONE_WAY_ANOVA (type_distrib, prix_gazole, 'F_RATIO') F_RATIO,\n  6         STATS_ONE_WAY_ANOVA (type_distrib, prix_gazole, 'SIG') p_value,\n  7           STATS_ONE_WAY_ANOVA (type_distrib,\n  8                                prix_gazole,\n  9                                'SUM_SQUARES_BETWEEN')\n 10         \/ (  STATS_ONE_WAY_ANOVA (type_distrib,\n 11                                   prix_gazole,\n 12                                   'SUM_SQUARES_BETWEEN')\n 13            + STATS_ONE_WAY_ANOVA (type_distrib,\n 14                                   prix_gazole,\n 15                                   'SUM_SQUARES_WITHIN'))\n 16            eta2\n 17    FROM carburants\n 18   WHERE type_distrib != 'Autre';\n\nSUM_SQUARES_BETWEEN SUM_SQUARES_WITHIN    F_RATIO    P_VALUE       ETA2\n------------------- ------------------ ---------- ---------- ----------\n          7.9395189         4.14502067 5164.01356          0 .656998047\n\nSQL&gt;\n<\/pre>\n<p style=\"text-align: justify;\">La valeur p renvoy\u00e9e est de 0. L&rsquo;hypoth\u00e8se H0 est donc rejet\u00e9e et on peut consid\u00e9rer qu&rsquo;il y a bien une diff\u00e9rence de moyenne entre au moins deux groupes.<\/p>\n<p style=\"text-align: justify;\">Outre les valeurs restitu\u00e9es par la fonction, je calcule le <a href=\"http:\/\/fr.wikipedia.org\/wiki\/Rapport_de_corr%C3%A9lation\" target=\"_blank\">rapport de corr\u00e9lation<\/a> eta-2 via la formule SCE\/SCT. Celui-ci indique le degr\u00e9 d&rsquo;association entre le prix moyen et le type de distributeur &#8211; ici, 66% de la variance de prix est \u00ab\u00a0expliqu\u00e9e\u00a0\u00bb par le canal de distribution.<\/p>\n<p style=\"text-align: justify;\">A ce stade, on sait donc que 2 classes au-moins ont un prix moyen statistiquement diff\u00e9rent mais on ne sait pas dire lesquelles. En pratique, pour aller plus loin dans l&rsquo;analyse, il faudrait mettre en \u0153uvre un <a href=\"https:\/\/en.wikipedia.org\/wiki\/Post_hoc_analysis\" target=\"_blank\">test post-hoc<\/a> malheureusement, Oracle n&rsquo;en propose pas en standard.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Je suis tomb\u00e9 r\u00e9cemment sur un article d\u00e9crivant la concurrence acharn\u00e9e entre les grandes surfaces et les stations-service sur le<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[6,14,16],"tags":[],"class_list":["post-244","post","type-post","status-publish","format-standard","hentry","category-oracle","category-statistique","category-tests-dhypotheses"],"_links":{"self":[{"href":"https:\/\/blog.tiran.stream\/index.php?rest_route=\/wp\/v2\/posts\/244","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.tiran.stream\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.tiran.stream\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.tiran.stream\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.tiran.stream\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=244"}],"version-history":[{"count":0,"href":"https:\/\/blog.tiran.stream\/index.php?rest_route=\/wp\/v2\/posts\/244\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.tiran.stream\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=244"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.tiran.stream\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=244"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.tiran.stream\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=244"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}