diff --git a/.Rproj.user/32A8B38A/bibliography-index/biblio-files b/.Rproj.user/32A8B38A/bibliography-index/biblio-files new file mode 100644 index 0000000..d75e790 --- /dev/null +++ b/.Rproj.user/32A8B38A/bibliography-index/biblio-files @@ -0,0 +1 @@ +1719449646:C:/Users/appariciop/OneDrive - USherbrooke/Articles Publies ne pas supprimer/_Livres/BolR_MethodesQuantitatives/references.bib diff --git a/.Rproj.user/32A8B38A/bibliography-index/biblio-refblock b/.Rproj.user/32A8B38A/bibliography-index/biblio-refblock new file mode 100644 index 0000000..e69de29 diff --git a/.Rproj.user/32A8B38A/bibliography-index/biblio.json b/.Rproj.user/32A8B38A/bibliography-index/biblio.json new file mode 100644 index 0000000..ac66141 --- /dev/null +++ b/.Rproj.user/32A8B38A/bibliography-index/biblio.json @@ -0,0 +1,3245 @@ +{ + "sources": [ + { + "URL": "https://doi.org/10.1186/s12942-021-00272-2", + "author": [ + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Gelb", + "given": "Jérémy" + }, + { + "family": "Jarry", + "given": "Vincent" + }, + { + "family": "Lesage-Mann", + "given": "Élaine" + } + ], + "container-title": "International journal of health geographics", + "id": "2021_1", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2021 + ] + ] + }, + "page": "1-16", + "title": "Cycling in one of the most polluted cities in the world: Exposure to noise and air pollution and potential adverse health impacts in delhi", + "title-short": "Cycling in one of the most polluted cities in the world", + "type": "article-journal", + "volume": "20" + }, + { + "URL": "https://doi.org/10.5334/jors.300", + "author": [ + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Maignan", + "given": "David" + }, + { + "family": "Gelb", + "given": "Jérémy" + } + ], + "container-title": "Journal of Open Research Software", + "id": "2021_2", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2021 + ] + ] + }, + "title": "VIFECO: An open-source software for counting features on a video", + "title-short": "VIFECO", + "type": "article-journal", + "volume": "9" + }, + { + "URL": "https://doi.org/10.1080/01441647.2021.1895361", + "author": [ + { + "family": "Gelb", + "given": "Jérémy" + }, + { + "family": "Apparicio", + "given": "Philippe" + } + ], + "container-title": "Transport Reviews", + "id": "2021_3", + "issued": { + "date-parts": [ + [ + 2021 + ] + ] + }, + "page": "1-24", + "title": "Cyclists’ exposure to atmospheric and noise pollution: A systematic literature review", + "title-short": "Cyclists’ exposure to atmospheric and noise pollution", + "type": "article-journal" + }, + { + "URL": "https://doi.org/10.4000/cybergeo.36414", + "author": [ + { + "family": "Gelb", + "given": "Jérémy" + }, + { + "family": "Apparicio", + "given": "Philippe" + } + ], + "container-title": "Cybergeo: European Journal of Geography", + "id": "2021_4", + "issued": { + "date-parts": [ + [ + 2021 + ] + ] + }, + "title": "Apport de la classification floue c-means spatiale en géographie: Essai de taxinomie socio-résidentielle et environnementale à lyon", + "title-short": "Apport de la classification floue c-means spatiale en géographie", + "type": "article-journal" + }, + { + "URL": "https://doi.org/10.3390/acoustics2010006", + "author": [ + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Gelb", + "given": "Jérémy" + } + ], + "container-title": "Acoustics", + "id": "2020_1", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2020 + ] + ] + }, + "page": "73-86", + "title": "Cyclists′ exposure to road traffic noise: A comparison of three north american and european cities", + "title-short": "Cyclists′ exposure to road traffic noise", + "type": "article-journal", + "volume": "2" + }, + { + "URL": "https://dx.doi.org/10.3390%2Fijerph17041220", + "author": [ + { + "family": "Buregeya", + "given": "Jean Marie" + }, + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Gelb", + "given": "Jérémy" + } + ], + "container-title": "International Journal of Environmental Research and Public Health", + "id": "2020_2", + "issue": "4", + "issued": { + "date-parts": [ + [ + 2020 + ] + ] + }, + "page": "1220", + "title": "Short-term impact of traffic-related particulate matter and noise exposure on cardiac function", + "type": "article-journal", + "volume": "17" + }, + { + "URL": "https://doi.org/10.3390/atmos11040422", + "author": [ + { + "family": "Gelb", + "given": "Jérémy" + }, + { + "family": "Apparicio", + "given": "Philippe" + } + ], + "container-title": "Atmosphere", + "id": "2020_3", + "issue": "4", + "issued": { + "date-parts": [ + [ + 2020 + ] + ] + }, + "page": "422", + "title": "Modelling cyclists’ multi-exposure to air and noise pollution with low-cost sensors: The case of paris", + "title-short": "Modelling cyclists’ multi-exposure to air and noise pollution with low-cost sensors", + "type": "article-journal", + "volume": "11" + }, + { + "URL": "https://doi.org/10.4000/cybergeo.32391", + "author": [ + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Gelb", + "given": "Jérémy" + }, + { + "family": "Mathieu", + "given": "Marie-Ève" + } + ], + "container-title": "Cybergeo: European Journal of Geography", + "id": "2019_1", + "issued": { + "date-parts": [ + [ + 2019 + ] + ] + }, + "title": "Un atlas-web pour comparer l’exposition individuelle aux pollutions atmosphérique et sonore selon le mode de transport", + "type": "article-journal", + "volume": "903" + }, + { + "URL": "https://doi.org/10.1111/cag.12511", + "author": [ + { + "family": "Delaunay", + "given": "Déborah" + }, + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Séguin", + "given": "Anne-Marie" + }, + { + "family": "Gelb", + "given": "Jérémy" + }, + { + "family": "Carrier", + "given": "Mathieu" + } + ], + "container-title": "The Canadian Geographer/Le Géographe canadien", + "id": "2019_2", + "issue": "2", + "issued": { + "date-parts": [ + [ + 2019 + ] + ] + }, + "page": "184-197", + "title": "L’identification des zones calmes et un diagnostic d’équité environnementale à montréal", + "type": "article-journal", + "volume": "63" + }, + { + "URL": "https://doi.org/10.1016/j.apacoust.2018.12.031", + "author": [ + { + "family": "Gelb", + "given": "Jérémy" + }, + { + "family": "Apparicio", + "given": "Philippe" + } + ], + "container-title": "Applied Acoustics", + "id": "2019_3", + "issued": { + "date-parts": [ + [ + 2019 + ] + ] + }, + "page": "332-343", + "title": "Noise exposure of cyclists in ho chi minh city: A spatio-temporal analysis using non-linear models", + "title-short": "Noise exposure of cyclists in ho chi minh city", + "type": "article-journal", + "volume": "148" + }, + { + "URL": "https://doi.org/10.1016/j.jtrangeo.2018.06.007", + "author": [ + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Gelb", + "given": "Jérémy" + }, + { + "family": "Carrier", + "given": "Mathieu" + }, + { + "family": "Mathieu", + "given": "Marie-Ève" + }, + { + "family": "Kingham", + "given": "Simon" + } + ], + "container-title": "Journal of Transport Geography", + "id": "2018_1", + "issued": { + "date-parts": [ + [ + 2018 + ] + ] + }, + "page": "182-192", + "title": "Exposure to noise and air pollution by mode of transportation during rush hours in montreal", + "type": "article-journal", + "volume": "70" + }, + { + "URL": "https://doi.org/10.1186/s12942-017-0105-9", + "author": [ + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Gelb", + "given": "Jérémy" + }, + { + "family": "Dubé", + "given": "Anne-Sophie" + }, + { + "family": "Kingham", + "given": "Simon" + }, + { + "family": "Gauvin", + "given": "Lise" + }, + { + "family": "Robitaille", + "given": "Éric" + } + ], + "container-title": "International journal of health geographics", + "id": "2017_1", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2017 + ] + ] + }, + "page": "32", + "title": "The approaches to measuring the potential spatial access to urban health services revisited: Distance types and aggregation-error issues", + "title-short": "The approaches to measuring the potential spatial access to urban health services revisited", + "type": "article-journal", + "volume": "16" + }, + { + "URL": "https://doi.org/10.1016/j.jtrangeo.2016.09.014", + "author": [ + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Carrier", + "given": "Mathieu" + }, + { + "family": "Gelb", + "given": "Jérémy" + }, + { + "family": "Séguin", + "given": "Anne-Marie" + }, + { + "family": "Kingham", + "given": "Simon" + } + ], + "container-title": "Journal of Transport Geography", + "id": "2016_1", + "issued": { + "date-parts": [ + [ + 2016 + ] + ] + }, + "page": "63-69", + "title": "Cyclists’ exposure to air pollution and road traffic noise in central city neighbourhoods of montreal", + "type": "article-journal", + "volume": "57" + }, + { + "URL": "http://dx.doi.org/10.1016/j.landurbplan.2012.06.002", + "author": [ + { + "family": "Pham", + "given": "Thi-Thanh-Hien" + }, + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Séguin", + "given": "Anne-Marie" + }, + { + "family": "Landry", + "given": "Shawn" + }, + { + "family": "Gagnon", + "given": "Martin" + } + ], + "container-title": "Landscape and urban planning", + "id": "PhamApparicioSeguin2012", + "issue": "3", + "issued": { + "date-parts": [ + [ + 2012 + ] + ] + }, + "page": "214-224", + "title": "Spatial distribution of vegetation in montreal: An uneven distribution or environmental inequity?", + "title-short": "Spatial distribution of vegetation in montreal", + "type": "article-journal", + "volume": "107" + }, + { + "URL": "http://www.theses.fr/2002LEMA3007", + "author": [ + { + "family": "Apparicio", + "given": "Philippe" + } + ], + "genre": "PhD thesis", + "id": "TheseApparicio", + "issued": { + "date-parts": [ + [ + 2002 + ] + ] + }, + "publisher": "Université du Maine", + "title": "Apport des systèmes d’information géographique à l’étude de l’insertion des HLM dans les quartiers montréalais", + "type": "thesis" + }, + { + "URL": "https://doi.org/10.3917/eg.351.85", + "author": [ + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Séguin", + "given": "Anne-Marie" + } + ], + "container-title": "LEspace geographique", + "id": "apparicio2006", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2006 + ] + ] + }, + "page": "63-85", + "title": "L’insertion des HLM montréalaises dans le milieu social environnant", + "type": "article-journal", + "volume": "35" + }, + { + "URL": "https://doi.org/10.1037/0033-2909.112.1.155", + "author": [ + { + "family": "Cohen", + "given": "Jacob" + } + ], + "container-title": "Psychological bulletin", + "id": "cohen1992", + "issue": "1", + "issued": { + "date-parts": [ + [ + 1992 + ] + ] + }, + "page": "155-159", + "title": "A power primer", + "type": "article-journal", + "volume": "112" + }, + { + "author": [ + { + "family": "Cohen", + "given": "Jacob" + } + ], + "id": "cohen2013", + "issued": { + "date-parts": [ + [ + 2013 + ] + ] + }, + "publisher": "Academic press", + "title": "Statistical power analysis for the behavioral sciences", + "type": "book" + }, + { + "URL": "https://doi.org/10.22237/jmasm/1257035100", + "author": [ + { + "family": "Sawilowsky", + "given": "Shlomo S" + } + ], + "container-title": "Journal of Modern Applied Statistical Methods", + "id": "sawilowsky2009", + "issue": "2", + "issued": { + "date-parts": [ + [ + 2009 + ] + ] + }, + "page": "467-474", + "title": "New effect size rules of thumb", + "type": "article-journal", + "volume": "8" + }, + { + "URL": "https://doi.org/10.1016/j.cstp.2014.06.003", + "author": [ + { + "family": "Carrier", + "given": "Mathieu" + }, + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Séguin", + "given": "Anne-Marie" + }, + { + "family": "Crouse", + "given": "Dan" + } + ], + "container-title": "Case Studies on Transport Policy", + "id": "carrier2014", + "issue": "2", + "issued": { + "date-parts": [ + [ + 2014 + ] + ] + }, + "page": "61-69", + "title": "Ambient air pollution concentration in montreal and environmental equity: Are children at risk at school?", + "title-short": "Ambient air pollution concentration in montreal and environmental equity", + "type": "article-journal", + "volume": "2" + }, + { + "URL": "https://doi.org/10.1056/nejmon1211064", + "author": [ + { + "family": "Messerli", + "given": "Franz H." + } + ], + "container-title": "The new England Journal of Medicine", + "id": "Messerli", + "issue": "16", + "issued": { + "date-parts": [ + [ + 2012 + ] + ] + }, + "page": "1563-1564", + "title": "Chocolate consumption, cognitive function, and nobel laureates", + "type": "article-journal", + "volume": "367" + }, + { + "author": [ + { + "family": "Bressoux", + "given": "Pascal" + } + ], + "id": "bressoux2010", + "issued": { + "date-parts": [ + [ + 2010 + ] + ] + }, + "publisher": "De boeck", + "title": "Modélisation statistique appliquée aux sciences sociales", + "type": "book" + }, + { + "URL": "https://www.frontiersin.org/articles/10.3389/fnhum.2012.00200", + "author": [ + { + "family": "Schwarzkopf", + "given": "Dietrich" + }, + { + "dropping-particle": "de", + "family": "Haas", + "given": "Benjamin" + }, + { + "family": "Rees", + "given": "Geraint" + } + ], + "container-title": "Frontiers in Human Neuroscience", + "id": "Schwarzkopf2012", + "issued": { + "date-parts": [ + [ + 2012 + ] + ] + }, + "page": "200", + "title": "Better ways to improve standards in brain-behavior correlation analysis", + "type": "article-journal", + "volume": "6" + }, + { + "author": [ + { + "family": "Raudenbush", + "given": "Stephen W" + }, + { + "family": "Bryk", + "given": "Anthony S" + } + ], + "id": "raudenbush2002hierarchical", + "issued": { + "date-parts": [ + [ + 2002 + ] + ] + }, + "publisher": "Sage", + "title": "Hierarchical linear models: Applications and data analysis methods", + "title-short": "Hierarchical linear models", + "type": "book", + "volume": "1" + }, + { + "URL": "https://doi.org/10.1007/BF02294395", + "author": [ + { + "family": "Wilcox", + "given": "Rand R" + } + ], + "container-title": "Psychometrika", + "id": "wilcox1994percentage", + "issue": "4", + "issued": { + "date-parts": [ + [ + 1994 + ] + ] + }, + "page": "601-616", + "title": "The percentage bend correlation coefficient", + "type": "article-journal", + "volume": "59" + }, + { + "author": [ + { + "family": "Chambers", + "given": "John M" + } + ], + "id": "chambers1998programming", + "issued": { + "date-parts": [ + [ + 1998 + ] + ] + }, + "publisher": "Springer Science & Business Media", + "title": "Programming with data: A guide to the s language", + "title-short": "Programming with data", + "type": "book" + }, + { + "author": [ + { + "family": "Chambers", + "given": "John M" + } + ], + "id": "chambers1998programming", + "issued": { + "date-parts": [ + [ + 1998 + ] + ] + }, + "publisher": "Springer Science & Business Media", + "title": "Programming with data: A guide to the s language", + "title-short": "Programming with data", + "type": "book" + }, + { + "author": [ + { + "family": "Glass", + "given": "Gene V" + }, + { + "family": "Peckham", + "given": "Percy D" + }, + { + "family": "Sanders", + "given": "James R" + } + ], + "container-title": "Review of educational research", + "id": "glass1972consequences", + "issue": "3", + "issued": { + "date-parts": [ + [ + 1972 + ] + ] + }, + "page": "237-288", + "title": "Consequences of failure to meet assumptions underlying the fixed effects analyses of variance and covariance", + "type": "article-journal", + "volume": "42" + }, + { + "URL": "https://doi.org/10.3102/00346543066004579", + "author": [ + { + "family": "Lix", + "given": "Lisa M" + }, + { + "family": "Keselman", + "given": "Joanne C" + }, + { + "family": "Keselman", + "given": "HJ" + } + ], + "container-title": "Review of educational research", + "id": "lix1996consequences", + "issue": "4", + "issued": { + "date-parts": [ + [ + 1996 + ] + ] + }, + "page": "579-619", + "title": "Consequences of assumption violations revisited: A quantitative review of alternatives to the one-way analysis of variance f test", + "title-short": "Consequences of assumption violations revisited", + "type": "article-journal", + "volume": "66" + }, + { + "author": [ + { + "family": "Pumain", + "given": "Denise" + }, + { + "family": "Béguin", + "given": "Michèle" + } + ], + "id": "pumain1994", + "issued": { + "date-parts": [ + [ + 1994 + ] + ] + }, + "publisher": "Armand Colin", + "title": "La représentation des données géographiques: Statistique et cartographie", + "title-short": "La représentation des données géographiques", + "type": "book" + }, + { + "author": [ + { + "family": "Sanders", + "given": "Lena" + } + ], + "id": "sanders1989analyse", + "issued": { + "date-parts": [ + [ + 1989 + ] + ] + }, + "publisher": "GIP Reclus", + "title": "L’analyse statistique des données en géographie", + "type": "book" + }, + { + "author": [ + { + "family": "Bourdieu", + "given": "Pierre" + } + ], + "container-title": "Handbook of theory and research for the sociology of education", + "id": "bourdieu1986forms", + "issued": { + "date-parts": [ + [ + 1986 + ] + ] + }, + "page": "241-258", + "publisher": "Westport", + "title": "The forms of capital", + "type": "chapter" + }, + { + "URL": "http://dx.doi.org/10.1198/jcgs.2009.07098", + "author": [ + { + "family": "Wickham", + "given": "Hadley" + } + ], + "container-title": "Journal of Computational and Graphical Statistics", + "id": "wickham2010layered", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2010 + ] + ] + }, + "page": "3-28", + "title": "A layered grammar of graphics", + "type": "article-journal", + "volume": "19" + }, + { + "URL": "https://doi.org/10.1002/9780470689646.ch1", + "author": [ + { + "family": "Rose", + "given": "Stuart" + }, + { + "family": "Engel", + "given": "Dave" + }, + { + "family": "Cramer", + "given": "Nick" + }, + { + "family": "Cowley", + "given": "Wendy" + } + ], + "container-title": "Text mining: applications and theory", + "id": "rose2010automatic", + "issued": { + "date-parts": [ + [ + 2010 + ] + ] + }, + "page": "1-20", + "title": "Automatic keyword extraction from individual documents", + "type": "article-journal", + "volume": "1" + }, + { + "author": [ + { + "family": "Sobol", + "given": "IM" + } + ], + "container-title": "Mathematics and Computers in Simulation", + "id": "Sobol1993", + "issue": "4", + "issued": { + "date-parts": [ + [ + 1993 + ] + ] + }, + "page": "407-414", + "title": "Sensitivity estimates for nonlinear mathematical models", + "type": "article-journal", + "volume": "1" + }, + { + "URL": "https://www.jstor.org/stable/2988433", + "author": [ + { + "family": "Joanes", + "given": "DN" + }, + { + "family": "Gill", + "given": "CA" + } + ], + "container-title": "Journal of the Royal Statistical Society: Series D (The Statistician)", + "id": "joanes1998comparing", + "issue": "1", + "issued": { + "date-parts": [ + [ + 1998 + ] + ] + }, + "page": "183-189", + "title": "Comparing measures of sample skewness and kurtosis", + "type": "article-journal", + "volume": "47" + }, + { + "author": [ + { + "family": "Mihalcea", + "given": "Rada" + }, + { + "family": "Tarau", + "given": "Paul" + } + ], + "container-title": "Proceedings of the 2004 conference on empirical methods in natural language processing", + "id": "mihalcea2004textrank", + "issued": { + "date-parts": [ + [ + 2004 + ] + ] + }, + "page": "404-411", + "title": "Textrank: Bringing order into text", + "title-short": "Textrank", + "type": "paper-conference" + }, + { + "URL": "https://doi.org/10.2307/2333709", + "author": [ + { + "family": "Shapiro", + "given": "Samuel Sanford" + }, + { + "family": "Wilk", + "given": "Martin B" + } + ], + "container-title": "Biometrika", + "id": "shapiro1965analysis", + "issue": "3/4", + "issued": { + "date-parts": [ + [ + 1965 + ] + ] + }, + "page": "591-611", + "title": "An analysis of variance test for normality (complete samples)", + "type": "article-journal", + "volume": "52" + }, + { + "author": [ + { + "family": "Razali", + "given": "Nornadiah Mohd" + }, + { + "family": "Wah", + "given": "Yap Bee" + } + ], + "container-title": "Journal of statistical modeling and analytics", + "id": "razali2011power", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2011 + ] + ] + }, + "page": "21-33", + "title": "Power comparisons of shapiro-wilk, kolmogorov-smirnov, lilliefors and anderson-darling tests", + "type": "article-journal", + "volume": "2" + }, + { + "URL": "https://doi.org/10.1080/00949655.2010.520163", + "author": [ + { + "family": "Yap", + "given": "Bee Wah" + }, + { + "family": "Sim", + "given": "Chiaw Hock" + } + ], + "container-title": "Journal of Statistical Computation and Simulation", + "id": "yap2011comparisons", + "issue": "12", + "issued": { + "date-parts": [ + [ + 2011 + ] + ] + }, + "page": "2141-2155", + "title": "Comparisons of various types of normality tests", + "type": "article-journal", + "volume": "81" + }, + { + "author": [ + { + "family": "Field", + "given": "Andy P" + }, + { + "family": "Miles", + "given": "Jeremy" + }, + { + "family": "Field", + "given": "Zoë" + } + ], + "id": "field2012discovering", + "issued": { + "date-parts": [ + [ + 2012 + ] + ] + }, + "publisher": "Thousand Oaks", + "title": "Discovering statistics using r", + "type": "" + }, + { + "author": [ + { + "family": "Tabachnick", + "given": "Barbara G" + }, + { + "family": "Fidell", + "given": "Linda S" + }, + { + "family": "Ullman", + "given": "Jodie B" + } + ], + "id": "tabachnick2007", + "issued": { + "date-parts": [ + [ + 2007 + ] + ] + }, + "publisher": "Pearson", + "title": "Using multivariate statistics", + "type": "book" + }, + { + "URL": "https://doi.org/10.1081/STA-120037438", + "author": [ + { + "family": "Reed", + "given": "William J." + }, + { + "family": "Jorgensen", + "given": "Murray" + } + ], + "container-title": "Communications in Statistics - Theory and Methods", + "id": "William_pareto", + "issue": "8", + "issued": { + "date-parts": [ + [ + 2004 + ] + ] + }, + "page": "1733-1753", + "publisher": "Taylor & Francis", + "title": "The souble pareto-lognormal sistribution: A new parametric model for size distributions", + "title-short": "The souble pareto-lognormal sistribution", + "type": "article-journal", + "volume": "33" + }, + { + "URL": "https://doi.org/10.7202/1063104ar", + "author": [ + { + "family": "De Alvarenga", + "given": "Bernardo" + }, + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Séguin", + "given": "Anne-Marie" + } + ], + "container-title": "Cahiers de géographie du Québec", + "id": "de2018accessibilite", + "issue": "176", + "issued": { + "date-parts": [ + [ + 2018 + ] + ] + }, + "page": "229-246", + "title": "L’accessibilité aux aires de jeux dans les parcs de la communauté métropolitaine de montréal", + "type": "article-journal", + "volume": "62" + }, + { + "URL": "https://onlinelibrary.wiley.com/doi/abs/10.1111/1467-9787.00247", + "author": [ + { + "family": "Reed", + "given": "William J." + } + ], + "container-title": "Journal of Regional Science", + "id": "William_pareto_ville", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2002 + ] + ] + }, + "page": "1-17", + "title": "On the rank-size distribution for human settlements", + "type": "article-journal", + "volume": "42" + }, + { + "author": [ + { + "family": "Lebart", + "given": "Ludovic" + }, + { + "family": "Morineau", + "given": "Alain" + }, + { + "family": "Piron", + "given": "Marie" + } + ], + "id": "lebart1995statistique", + "issued": { + "date-parts": [ + [ + 1995 + ] + ] + }, + "publisher": "Dunod", + "title": "Statistique exploratoire multidimensionnelle", + "type": "book" + }, + { + "URL": "https://medium.com/@srowen/common-probability-distributions-347e6b945ce4", + "accessed": { + "date-parts": [ + [ + 2020, + 9, + 14 + ] + ] + }, + "author": [ + { + "family": "Sean", + "given": "Owen" + } + ], + "id": "SeanOwendist", + "issued": { + "date-parts": [ + [ + 2018 + ] + ] + }, + "title": "Common probability distributions", + "type": "webpage" + }, + { + "ISSN": "00359238", + "URL": "http://www.jstor.org/stable/2344614", + "author": [ + { + "family": "Nelder", + "given": "John A." + }, + { + "family": "Wedderburn", + "given": "Robert W. M." + } + ], + "container-title": "Journal of the Royal Statistical Society. Series A (General)", + "id": "GLMnelder", + "issue": "3", + "issued": { + "date-parts": [ + [ + 1972 + ] + ] + }, + "page": "370-384", + "title": "Generalized linear models", + "type": "article-journal", + "volume": "135" + }, + { + "URL": "http://dx.doi.org/10.1016/j.apgeog.2016.09.023", + "author": [ + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Pham", + "given": "Thi-Thanh-Hien" + }, + { + "family": "Séguin", + "given": "Anne-Marie" + }, + { + "family": "Dubé", + "given": "Jean" + } + ], + "container-title": "Applied Geography", + "id": "apparicio2016spatial", + "issued": { + "date-parts": [ + [ + 2016 + ] + ] + }, + "page": "128-136", + "title": "Spatial distribution of vegetation in and around city blocks on the island of montreal: A double environmental inequity?", + "title-short": "Spatial distribution of vegetation in and around city blocks on the island of montreal", + "type": "article-journal", + "volume": "76" + }, + { + "URL": "https://doi.org/10.2307/1390802", + "author": [ + { + "family": "Dunn", + "given": "Peter K." + }, + { + "family": "Smyth", + "given": "Gordon K." + } + ], + "container-title": "Journal of Computational and Graphical Statistics", + "id": "RandomizedResid", + "issue": "3", + "issued": { + "date-parts": [ + [ + 1996 + ] + ] + }, + "page": "236-244", + "title": "Randomized quantile residuals", + "type": "article-journal", + "volume": "5" + }, + { + "author": [ + { + "family": "Gelman", + "given": "Andrew" + }, + { + "family": "Hill", + "given": "Jennifer" + } + ], + "id": "gelman2006data", + "issued": { + "date-parts": [ + [ + 2006 + ] + ] + }, + "publisher": "Cambridge university press", + "title": "Data analysis using regression and multilevel/hierarchical models", + "type": "book" + }, + { + "URL": "https://royalsocietypublishing.org/doi/abs/10.1098/rsta.1933.0009", + "author": [ + { + "family": "Neyman", + "given": "Jerzy" + }, + { + "family": "Pearson", + "given": "Egon Sharpe" + }, + { + "family": "Pearson", + "given": "Karl" + } + ], + "container-title": "Philosophical Transactions of the Royal Society of London. Series A, Containing Papers of a Mathematical or Physical Character", + "id": "NeymanLemma", + "issue": "694-706", + "issued": { + "date-parts": [ + [ + 1933 + ] + ] + }, + "page": "289-337", + "title": "IX. On the problem of the most efficient tests of statistical hypotheses", + "type": "article-journal", + "volume": "231" + }, + { + "author": [ + { + "family": "Hilbe", + "given": "Joseph M" + } + ], + "id": "hilbe2009logistic", + "issued": { + "date-parts": [ + [ + 2009 + ] + ] + }, + "publisher": "CRC press", + "title": "Logistic regression models", + "type": "book" + }, + { + "author": [ + { + "family": "Zeileis", + "given": "Achim" + } + ], + "id": "zeileis2004econometric", + "issued": { + "date-parts": [ + [ + 2004 + ] + ] + }, + "publisher": "Institut für Statistik und Mathematik", + "title": "Econometric computing with HC and HAC covariance matrix estimators", + "type": "book" + }, + { + "URL": "https://www.jstor.org/stable/2532457", + "author": [ + { + "family": "Brant", + "given": "Rollin" + } + ], + "container-title": "Biometrics", + "id": "brant1990assessing", + "issued": { + "date-parts": [ + [ + 1990 + ] + ] + }, + "page": "1171-1178", + "title": "Assessing proportionality in the proportional odds model for ordinal logistic regression", + "type": "article-journal" + }, + { + "URL": "http://dx.doi.org/10.22381/JSME5420173", + "author": [ + { + "family": "Teubner", + "given": "Timm" + }, + { + "family": "Hawlitschek", + "given": "Florian" + }, + { + "family": "Dann", + "given": "David" + } + ], + "container-title": "Journal of Self-Governance & Management Economics", + "id": "teubner2017price", + "issue": "4", + "issued": { + "date-parts": [ + [ + 2017 + ] + ] + }, + "title": "Price determinants on AirBnB: How reputation pays off in the sharing economy", + "title-short": "Price determinants on AirBnB", + "type": "article-journal", + "volume": "5" + }, + { + "URL": "https://doi.org/10.1016/j.ijhm.2016.12.007", + "author": [ + { + "family": "Wang", + "given": "Dan" + }, + { + "family": "Nicolau", + "given": "Juan L" + } + ], + "container-title": "International Journal of Hospitality Management", + "id": "wang2017price", + "issued": { + "date-parts": [ + [ + 2017 + ] + ] + }, + "page": "120-131", + "title": "Price determinants of sharing economy based accommodation rental: A study of listings from 33 cities on airbnb.com", + "title-short": "Price determinants of sharing economy based accommodation rental", + "type": "article-journal", + "volume": "62" + }, + { + "URL": "http://dx.doi.org/10.3390/su9091635", + "author": [ + { + "family": "Zhang", + "given": "Zhihua" + }, + { + "family": "Chen", + "given": "Rachel JC" + }, + { + "family": "Han", + "given": "Lee D" + }, + { + "family": "Yang", + "given": "Lu" + } + ], + "container-title": "Sustainability", + "id": "zhang2017key", + "issue": "9", + "issued": { + "date-parts": [ + [ + 2017 + ] + ] + }, + "page": "1635", + "title": "Key factors affecting the price of airbnb listings: A geographically weighted approach", + "title-short": "Key factors affecting the price of airbnb listings", + "type": "article-journal", + "volume": "9" + }, + { + "URL": "https://doi.org/10.1371/journal.pone.0166140", + "author": [ + { + "family": "McFadden", + "given": "Brandon R" + } + ], + "container-title": "PloS one", + "id": "mcfadden2016examining", + "issue": "11", + "issued": { + "date-parts": [ + [ + 2016 + ] + ] + }, + "page": "e0166140", + "title": "Examining the gap between science and public opinion about genetically modified food and global warming", + "type": "article-journal", + "volume": "11" + }, + { + "author": [ + { + "literal": "SAS Institute Inc" + } + ], + "id": "Sasmultinom", + "issued": { + "date-parts": [ + [ + 2020 + ] + ] + }, + "note": "Accessed: 2020-10-15", + "publisher": "https://documentation.sas.com/?docsetId=statug&docsetTarget=statug_fmm_examples04.htm&docsetVersion=15.2&locale=en", + "title": "SAS/STAT 15.2 User’s Guide modeling multinomial overdispersion", + "type": "" + }, + { + "author": [ + { + "literal": "SAS Institute Inc" + } + ], + "id": "Saspoiss", + "issued": { + "date-parts": [ + [ + 2020 + ] + ] + }, + "note": "Accessed: 2020-10-15", + "publisher": "https://stats.idre.ucla.edu/sas/output/poisson-regression/", + "title": "SAS/STAT 15.2 User’s Guide poisson regression | SAS annotated output", + "type": "" + }, + { + "author": [ + { + "family": "Cloutier", + "given": "Marie-soleil" + }, + { + "family": "Tremblay", + "given": "Mathieu" + }, + { + "family": "Morency", + "given": "Patrick" + }, + { + "family": "Apparicio", + "given": "Philippe" + } + ], + "container-title": "Recherche Transports Sécurité", + "id": "cloutier2014carrefours", + "issued": { + "date-parts": [ + [ + 2014 + ] + ] + }, + "page": "3-20", + "title": "Carrefours en milieu urbain: Quels risques pour les piétons? Exemple empirique des quartiers centraux de montréal, canada", + "title-short": "Carrefours en milieu urbain", + "type": "article-journal", + "volume": "30" + }, + { + "URL": "https://doi.org/10.3141%2F2302-13", + "author": [ + { + "family": "Anastasopoulos", + "given": "Panagiotis C" + }, + { + "family": "Haddock", + "given": "John E" + }, + { + "family": "Karlaftis", + "given": "Matthew G" + }, + { + "family": "Mannering", + "given": "Fred L" + } + ], + "container-title": "Transportation research record", + "id": "anastasopoulos2012analysis", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2012 + ] + ] + }, + "page": "121-129", + "title": "Analysis of urban travel times: Hazard-based approach to random parameters", + "title-short": "Analysis of urban travel times", + "type": "article-journal", + "volume": "2302" + }, + { + "URL": "https://doi.org/10.1007/s11116-007-9136-6", + "author": [ + { + "family": "Frank", + "given": "Lawrence" + }, + { + "family": "Bradley", + "given": "Mark" + }, + { + "family": "Kavage", + "given": "Sarah" + }, + { + "family": "Chapman", + "given": "James" + }, + { + "family": "Lawton", + "given": "T Keith" + } + ], + "container-title": "Transportation", + "id": "frank2008urban", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2008 + ] + ] + }, + "page": "37-54", + "title": "Urban form, travel time, and cost relationships with tour complexity and mode choice", + "type": "article-journal", + "volume": "35" + }, + { + "URL": "http://dx.doi.org/10.1016/S0196-1152(07)15005-5", + "author": [ + { + "family": "Harlan", + "given": "Sharon L" + }, + { + "family": "Brazel", + "given": "Anthony J" + }, + { + "family": "Jenerette", + "given": "G Darrel" + }, + { + "family": "Jones", + "given": "Nancy S" + }, + { + "family": "Larsen", + "given": "Larissa" + }, + { + "family": "Prashad", + "given": "Lela" + }, + { + "family": "Stefanov", + "given": "William L" + } + ], + "container-title": "Research in Social Problems and Public Policy", + "id": "harlan2007shade", + "issued": { + "date-parts": [ + [ + 2007 + ] + ] + }, + "page": "173-202", + "title": "In the shade of affluence: The inequitable distribution of the urban heat island", + "title-short": "In the shade of affluence", + "type": "article-journal", + "volume": "15" + }, + { + "URL": "https://doi.org/10.1016/j.ufug.2019.04.014", + "author": [ + { + "family": "Sanchez", + "given": "Lino" + }, + { + "family": "Reames", + "given": "Tony G" + } + ], + "container-title": "Urban Forestry & Urban Greening", + "id": "sanchez2019cooling", + "issued": { + "date-parts": [ + [ + 2019 + ] + ] + }, + "page": "126331", + "title": "Cooling detroit: A socio-spatial analysis of equity in green roofs as an urban heat island mitigation strategy", + "title-short": "Cooling detroit", + "type": "article-journal", + "volume": "44" + }, + { + "URL": "https://doi.org/10.1016/j.jenvman.2011.02.006", + "author": [ + { + "family": "Huang", + "given": "Ganlin" + }, + { + "family": "Zhou", + "given": "Weiqi" + }, + { + "family": "Cadenasso", + "given": "ML" + } + ], + "container-title": "Journal of environmental management", + "id": "huang2011everyone", + "issue": "7", + "issued": { + "date-parts": [ + [ + 2011 + ] + ] + }, + "page": "1753-1759", + "title": "Is everyone hot in the city? Spatial pattern of land surface temperatures, land cover and neighborhood socioeconomic characteristics in baltimore, MD", + "type": "article-journal", + "volume": "92" + }, + { + "URL": "https://doi.org/10.2307/2290467", + "author": [ + { + "family": "Fox", + "given": "John" + }, + { + "family": "Monette", + "given": "Georges" + } + ], + "container-title": "Journal of the American Statistical Association", + "id": "fox1992generalized", + "issue": "417", + "issued": { + "date-parts": [ + [ + 1992 + ] + ] + }, + "page": "178-183", + "title": "Generalized collinearity diagnostics", + "type": "article-journal", + "volume": "87" + }, + { + "URL": "https://doi.org/10.1214/009053604000001048", + "author": [ + { + "family": "Gelman", + "given": "Andrew" + } + ], + "container-title": "The annals of statistics", + "id": "gelman2005analysis", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2005 + ] + ] + }, + "page": "1-53", + "title": "Analysis of variance—why it is more important than ever", + "type": "article-journal", + "volume": "33" + }, + { + "author": [ + { + "family": "McElreath", + "given": "Richard" + } + ], + "id": "mcelreath2020statistical", + "issued": { + "date-parts": [ + [ + 2020 + ] + ] + }, + "publisher": "CRC press", + "title": "Statistical rethinking: A bayesian course with examples in r and stan", + "title-short": "Statistical rethinking", + "type": "book" + }, + { + "URL": "https://doi.org/10.1098/rsif.2017.0213", + "author": [ + { + "family": "Nakagawa", + "given": "Shinichi" + }, + { + "family": "Johnson", + "given": "Paul C. D." + }, + { + "family": "Schielzeth", + "given": "Holger" + } + ], + "container-title": "Journal of The Royal Society Interface", + "id": "NakagawaICC", + "issue": "134", + "issued": { + "date-parts": [ + [ + 2017 + ] + ] + }, + "page": "20170213", + "title": "The coefficient of determination R2 and intra-class correlation coefficient from generalized linear mixed-effects models revisited and expanded", + "type": "article-journal", + "volume": "14" + }, + { + "URL": "https://doi.org/10.1016/j.cct.2012.05.004", + "author": [ + { + "family": "Wu", + "given": "Sheng" + }, + { + "family": "Crespi", + "given": "Catherine M" + }, + { + "family": "Wong", + "given": "Weng Kee" + } + ], + "container-title": "Contemporary clinical trials", + "id": "wu2012comparison", + "issue": "5", + "issued": { + "date-parts": [ + [ + 2012 + ] + ] + }, + "page": "869-880", + "title": "Comparison of methods for estimating the intraclass correlation coefficient for binary responses in cancer prevention cluster randomized trials", + "type": "article-journal", + "volume": "33" + }, + { + "author": [ + { + "family": "Stryhn", + "given": "H" + }, + { + "family": "Sanchez", + "given": "J" + }, + { + "family": "Morley", + "given": "P" + }, + { + "family": "Booker", + "given": "C" + }, + { + "family": "Dohoo", + "given": "IR" + } + ], + "container-title": "Proceedings of the 11th international symposium on veterinary epidemiology and economics", + "id": "stryhn2006interpretation", + "issued": { + "date-parts": [ + [ + 2006 + ] + ] + }, + "title": "Interpretation of variance parameters in multilevel poisson regression models", + "type": "paper-conference", + "volume": "702" + }, + { + "URL": "https://doi.org/10.1186/2193-1801-3-40", + "author": [ + { + "family": "Aly", + "given": "Sharif S" + }, + { + "family": "Zhao", + "given": "Jianyang" + }, + { + "family": "Li", + "given": "Ben" + }, + { + "family": "Jiang", + "given": "Jiming" + } + ], + "container-title": "SpringerPlus", + "id": "aly2014reliability", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2014 + ] + ] + }, + "page": "40", + "title": "Reliability of environmental sampling culture results using the negative binomial intraclass correlation coefficient", + "type": "article-journal", + "volume": "3" + }, + { + "URL": "https://www.jstor.org/stable/23076146", + "author": [ + { + "family": "Kosmidis", + "given": "Ioannis" + }, + { + "family": "Firth", + "given": "David" + } + ], + "container-title": "Biometrika", + "id": "kosmidis2011multinomial", + "issue": "3", + "issued": { + "date-parts": [ + [ + 2011 + ] + ] + }, + "page": "755-759", + "title": "Multinomial logit bias reduction via the poisson log-linear model", + "type": "article-journal", + "volume": "98" + }, + { + "author": [ + { + "family": "Burdenski", + "given": "Jr Thomas K" + } + ], + "container-title": "ERIC", + "id": "burdenski2000evaluating", + "issued": { + "date-parts": [ + [ + 2000 + ] + ] + }, + "page": "1-62", + "title": "Evaluating univariate, bivariate, and multivariate normality using graphical procedures", + "type": "article-journal" + }, + { + "URL": "https://doi.org/10.1016/j.tree.2008.10.008", + "author": [ + { + "family": "Bolker", + "given": "Benjamin M" + }, + { + "family": "Brooks", + "given": "Mollie E" + }, + { + "family": "Clark", + "given": "Connie J" + }, + { + "family": "Geange", + "given": "Shane W" + }, + { + "family": "Poulsen", + "given": "John R" + }, + { + "family": "Stevens", + "given": "M Henry H" + }, + { + "family": "White", + "given": "Jada-Simone S" + } + ], + "container-title": "Trends in ecology & evolution", + "id": "bolker2009generalized", + "issue": "3", + "issued": { + "date-parts": [ + [ + 2009 + ] + ] + }, + "page": "127-135", + "title": "Generalized linear mixed models: A practical guide for ecology and evolution", + "title-short": "Generalized linear mixed models", + "type": "article-journal", + "volume": "24" + }, + { + "author": [ + { + "family": "Philibert", + "given": "Mathieu D" + }, + { + "family": "Apparicio", + "given": "Philippe" + } + ], + "container-title": "Géographie de la santé : Un panorama", + "id": "philibert2007statistiques", + "issued": { + "date-parts": [ + [ + 2007 + ] + ] + }, + "page": "111-132", + "publisher": "Economica", + "title": "Statistiques spatiales appliquées à l’analyse de données de santé", + "type": "chapter" + }, + { + "author": [ + { + "family": "Andreae", + "given": "MO" + }, + { + "family": "Fishman", + "given": "J" + }, + { + "family": "Garstang", + "given": "M" + }, + { + "family": "Goldammer", + "given": "JG" + }, + { + "family": "Justice", + "given": "CO" + }, + { + "family": "Levine", + "given": "JS" + }, + { + "family": "Scholes", + "given": "RJ" + }, + { + "family": "Stocks", + "given": "BJ" + }, + { + "family": "Thompson", + "given": "AM" + }, + { + "family": "Van Wilgen", + "given": "B" + } + ], + "container-title": "Global atmospheric-biospheric chemistry", + "id": "andreae1994biomass", + "issued": { + "date-parts": [ + [ + 1994 + ] + ] + }, + "page": "83-101", + "publisher": "Springer", + "title": "Biomass burning in the global environment: First results from the IGAC/BIBEX field campaign STARE/TRACE-a/SAFARI-92", + "title-short": "Biomass burning in the global environment", + "type": "chapter" + }, + { + "URL": "https://doi.org/10.1080%2F00420980120087162", + "author": [ + { + "family": "Atkinson", + "given": "Rowland" + }, + { + "family": "Kintrea", + "given": "Keith" + } + ], + "container-title": "Urban studies", + "id": "atkinson2001disentangling", + "issue": "12", + "issued": { + "date-parts": [ + [ + 2001 + ] + ] + }, + "page": "2277-2298", + "title": "Disentangling area effects: Evidence from deprived and non-deprived neighbourhoods", + "title-short": "Disentangling area effects", + "type": "article-journal", + "volume": "38" + }, + { + "URL": "http://dx.doi.org/10.1016/j.landurbplan.2016.09.001", + "author": [ + { + "family": "Pham", + "given": "Thi-Thanh-Hien" + }, + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Landry", + "given": "Shawn" + }, + { + "family": "Lewnard", + "given": "Joseph" + } + ], + "container-title": "Landscape and Urban Planning", + "id": "apparicio2017disentangling", + "issued": { + "date-parts": [ + [ + 2017 + ] + ] + }, + "page": "422-433", + "title": "Disentangling the effects of urban form and socio-demographic context on street tree cover: A multi-level analysis from montréal", + "title-short": "Disentangling the effects of urban form and socio-demographic context on street tree cover", + "type": "article-journal", + "volume": "157" + }, + { + "URL": "https://doi.org/10.1198/016214504000000980", + "author": [ + { + "family": "Wood", + "given": "Simon N" + } + ], + "container-title": "Journal of the American Statistical Association", + "id": "wood2004stable", + "issue": "467", + "issued": { + "date-parts": [ + [ + 2004 + ] + ] + }, + "page": "673-686", + "title": "Stable and efficient multiple smoothing parameter estimation for generalized additive models", + "type": "article-journal", + "volume": "99" + }, + { + "URL": "https://doi.org/10.1257/jep.31.2.211", + "author": [ + { + "family": "Allcott", + "given": "Hunt" + }, + { + "family": "Gentzkow", + "given": "Matthew" + } + ], + "container-title": "Journal of economic perspectives", + "id": "allcott2017social", + "issue": "2", + "issued": { + "date-parts": [ + [ + 2017 + ] + ] + }, + "page": "211-36", + "title": "Social media and fake news in the 2016 election", + "type": "article-journal", + "volume": "31" + }, + { + "URL": "https://doi.org/10.1371/journal.pone.0224134", + "author": [ + { + "family": "Spyratos", + "given": "Spyridon" + }, + { + "family": "Vespe", + "given": "Michele" + }, + { + "family": "Natale", + "given": "Fabrizio" + }, + { + "family": "Weber", + "given": "Ingmar" + }, + { + "family": "Zagheni", + "given": "Emilio" + }, + { + "family": "Rango", + "given": "Marzia" + } + ], + "container-title": "PloS one", + "id": "spyratos2019quantifying", + "issue": "10", + "issued": { + "date-parts": [ + [ + 2019 + ] + ] + }, + "page": "e0224134", + "title": "Quantifying international human mobility patterns using facebook network data", + "type": "article-journal", + "volume": "14" + }, + { + "URL": "https://doi.org/10.1186/s12942-020-00202-8", + "author": [ + { + "family": "Boulos", + "given": "Maged N Kamel" + }, + { + "family": "Geraghty", + "given": "Estella M" + } + ], + "container-title": "International journal of health geographics", + "id": "boulos2020geographical", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2020 + ] + ] + }, + "page": "1-12", + "title": "Geographical tracking and mapping of coronavirus disease COVID-19/severe acute respiratory syndrome coronavirus 2 (SARS-CoV-2) epidemic and associated events around the world: How 21st century GIS technologies are supporting the global fight against outbreaks and epidemics", + "title-short": "Geographical tracking and mapping of coronavirus disease COVID-19/severe acute respiratory syndrome coronavirus 2 (SARS-CoV-2) epidemic and associated events around the world", + "type": "article-journal", + "volume": "19" + }, + { + "URL": "https://idjs.ca/images/rcsr/archives/V44N1_5-AUDRIN-APPARICIO-SEGUIN.pdf", + "author": [ + { + "family": "Audrin", + "given": "Thomas" + }, + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Séguin", + "given": "Anne-Marie" + } + ], + "container-title": "Canadian Journal of Regional Science/Revue canadienne des sciences régionales", + "id": "audrin2021localisation", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2021 + ] + ] + }, + "page": "22-34", + "title": "La localisation des écoles primaires et le bruit aérien dans la région métropolitaine de toronto: Un diagnostic d’équité environnementale et une analyse des impacts sur la réussite scolaire", + "title-short": "La localisation des écoles primaires et le bruit aérien dans la région métropolitaine de toronto", + "type": "article-journal", + "volume": "44" + }, + { + "URL": "https://www.econometrics-with-r.org/ITER.pdf", + "author": [ + { + "family": "Hanck", + "given": "Christoph" + }, + { + "family": "Arnold", + "given": "Martin" + }, + { + "family": "Gerber", + "given": "Alexander" + }, + { + "family": "Schmelzer", + "given": "Martin" + } + ], + "id": "hanck2019introduction", + "issued": { + "date-parts": [ + [ + 2019 + ] + ] + }, + "title": "Introduction to econometrics with r", + "type": "book" + }, + { + "URL": "https://dx.doi.org/10.1002%2Fwics.1270", + "author": [ + { + "family": "Bair", + "given": "Eric" + } + ], + "container-title": "Wiley Interdisciplinary Reviews: Computational Statistics", + "id": "bair2013semi", + "issue": "5", + "issued": { + "date-parts": [ + [ + 2013 + ] + ] + }, + "page": "349-361", + "title": "Semi-supervised clustering methods", + "type": "article-journal", + "volume": "5" + }, + { + "author": [ + { + "family": "MacQueen", + "given": "James" + } + ], + "collection-number": "14", + "container-title": "Proceedings of the fifth berkeley symposium on mathematical statistics and probability", + "id": "macqueen1967", + "issued": { + "date-parts": [ + [ + 1967 + ] + ] + }, + "page": "281-297", + "publisher": "Oakland, CA, USA", + "title": "Some methods for classification and analysis of multivariate observations", + "type": "paper-conference", + "volume": "1" + }, + { + "author": [ + { + "family": "Aggarwal", + "given": "Charu C" + }, + { + "family": "Hinneburg", + "given": "Alexander" + }, + { + "family": "Keim", + "given": "Daniel A" + } + ], + "container-title": "International conference on database theory", + "id": "aggarwal2001surprising", + "issued": { + "date-parts": [ + [ + 2001 + ] + ] + }, + "page": "420-434", + "publisher": "Springer", + "title": "On the surprising behavior of distance metrics in high dimensional space", + "type": "paper-conference" + }, + { + "author": [ + { + "family": "Chandra", + "given": "Mahalanobis Prasanta" + } + ], + "collection-number": "1", + "container-title": "Proceedings of the national institute of sciences of india", + "id": "chandra1936generalised", + "issued": { + "date-parts": [ + [ + 1936 + ] + ] + }, + "page": "49-55", + "title": "On the generalised distance in statistics", + "type": "paper-conference", + "volume": "2" + }, + { + "URL": "https://doi.org/10.1111/1467-9868.00293", + "author": [ + { + "family": "Tibshirani", + "given": "Robert" + }, + { + "family": "Walther", + "given": "Guenther" + }, + { + "family": "Hastie", + "given": "Trevor" + } + ], + "container-title": "Journal of the Royal Statistical Society: Series B (Statistical Methodology)", + "id": "tibshirani2001estimating", + "issue": "2", + "issued": { + "date-parts": [ + [ + 2001 + ] + ] + }, + "page": "411-423", + "title": "Estimating the number of clusters in a data set via the gap statistic", + "type": "article-journal", + "volume": "63" + }, + { + "URL": "https://doi.org/10.2307/2528823", + "author": [ + { + "family": "Gower", + "given": "John C" + } + ], + "container-title": "Biometrics", + "id": "gower1971general", + "issued": { + "date-parts": [ + [ + 1971 + ] + ] + }, + "page": "857-871", + "title": "A general coefficient of similarity and some of its properties", + "type": "article-journal" + }, + { + "URL": "http://rig.revuesonline.com/article.jsp?articleId=15208", + "author": [ + { + "family": "Apparicio", + "given": "Philippe" + }, + { + "family": "Cloutier", + "given": "Marie-Soleil" + }, + { + "family": "Séguin", + "given": "Anne-Marie" + }, + { + "family": "Ades", + "given": "Josefina" + } + ], + "container-title": "Revue internationale de géomatique", + "id": "apparicio2010accessibilite", + "issue": "3", + "issued": { + "date-parts": [ + [ + 2010 + ] + ] + }, + "page": "363-389", + "title": "Accessibilité spatiale aux parcs urbains pour les enfants et injustice environnementale. Exploration du cas montréalais", + "type": "article-journal", + "volume": "20" + }, + { + "URL": "https://doi.org/10.1037/1082-989x.11.1.54", + "author": [ + { + "family": "Smithson", + "given": "Michael" + }, + { + "family": "Verkuilen", + "given": "Jay" + } + ], + "container-title": "Psychological methods", + "id": "smithson2006better", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2006 + ] + ] + }, + "page": "54", + "title": "A better lemon squeezer? Maximum-likelihood regression with beta-distributed dependent variables", + "type": "article-journal", + "volume": "11" + }, + { + "author": [ + { + "family": "Xie", + "given": "Yihui" + } + ], + "id": "xie2016bookdown", + "issued": { + "date-parts": [ + [ + 2016 + ] + ] + }, + "publisher": "CRC Press", + "title": "Bookdown: Authoring books and technical documents with r markdown", + "title-short": "Bookdown", + "type": "book" + }, + { + "author": [ + { + "family": "Ismay", + "given": "Chester" + }, + { + "family": "Kim", + "given": "Albert Y" + } + ], + "id": "ismay2019statistical", + "issued": { + "date-parts": [ + [ + 2019 + ] + ] + }, + "publisher": "CRC Press", + "title": "Statistical inference via data science: A ModernDive into r and the tidyverse", + "title-short": "Statistical inference via data science", + "type": "book" + }, + { + "author": [ + { + "family": "Roback", + "given": "Paul" + }, + { + "family": "Legler", + "given": "Julie" + } + ], + "id": "roback2021beyond", + "issued": { + "date-parts": [ + [ + 2021 + ] + ] + }, + "publisher": "CRC Press", + "title": "Beyond multiple linear regression: Applied generalized linear models and multilevel models in r", + "title-short": "Beyond multiple linear regression", + "type": "book" + }, + { + "author": [ + { + "family": "Chang", + "given": "Winston" + } + ], + "id": "Chang2018", + "issued": { + "date-parts": [ + [ + 2018 + ] + ] + }, + "publisher": "CRC Press", + "title": "R graphics cookbook, 2nd edition", + "type": "book" + }, + { + "author": [ + { + "family": "Gilles", + "given": "Alain" + }, + { + "family": "Maranda", + "given": "Pierre" + } + ], + "id": "gilles1994elements", + "issued": { + "date-parts": [ + [ + 1994 + ] + ] + }, + "publisher": "McGraw-Hill", + "title": "Éléments de méthodologie et d’analyse statistique pour les sciences sociales", + "type": "book" + }, + { + "author": [ + { + "family": "Pagès", + "given": "Jérôme" + } + ], + "id": "pages2013analyse", + "issued": { + "date-parts": [ + [ + 2013 + ] + ] + }, + "publisher": "EDP sciences", + "title": "Analyse factorielle multiple avec r", + "type": "book" + }, + { + "URL": "https://psycnet.apa.org/doi/10.1037/h0071325", + "author": [ + { + "family": "Hotelling", + "given": "Harold" + } + ], + "container-title": "Journal of educational psychology", + "id": "hotelling1933analysis", + "issue": "6", + "issued": { + "date-parts": [ + [ + 1933 + ] + ] + }, + "page": "417", + "title": "Analysis of a complex of statistical variables into principal components", + "type": "article-journal", + "volume": "24" + }, + { + "author": [ + { + "family": "Benzécri", + "given": "Jean-Paul" + } + ], + "id": "benzecri1973analyse", + "issued": { + "date-parts": [ + [ + 1973 + ] + ] + }, + "publisher": "Dunod", + "title": "L’analyse des données. Tome 1. La taxinomie. Tome 2. L’analyse des correspondances", + "type": "book", + "volume": "2" + }, + { + "author": [ + { + "family": "Pagès", + "given": "Jérôme" + } + ], + "container-title": "Revue de statistique appliquée", + "id": "pages2002analyse", + "issue": "4", + "issued": { + "date-parts": [ + [ + 2002 + ] + ] + }, + "page": "5-37", + "title": "Analyse factorielle multiple appliquée aux variables qualitatives et aux données mixtes", + "type": "article-journal", + "volume": "50" + }, + { + "author": [ + { + "family": "Escofier", + "given": "Brigitte" + } + ], + "container-title": "Cahiers de l’Analyse des Données", + "id": "escofier1979traitement", + "issue": "2", + "issued": { + "date-parts": [ + [ + 1979 + ] + ] + }, + "page": "137-146", + "title": "Traitement simultané de variables qualitatives et quantitatives en analyse factorielle", + "type": "article-journal", + "volume": "4" + }, + { + "author": [ + { + "family": "Escofier", + "given": "Brigitte" + }, + { + "family": "Pagès", + "given": "Jérôme" + } + ], + "container-title": "Dunod, Paris", + "id": "escofier1998analyses", + "issued": { + "date-parts": [ + [ + 1998 + ] + ] + }, + "title": "Analyses factorielles simples et multiples", + "type": "article-journal" + }, + { + "URL": "https://doi.org/10.1177%2F001316446002000116", + "author": [ + { + "family": "Kaiser", + "given": "Henry F" + } + ], + "container-title": "Educational and psychological measurement", + "id": "kaiser1960application", + "issue": "1", + "issued": { + "date-parts": [ + [ + 1960 + ] + ] + }, + "page": "141-151", + "title": "The application of electronic computers to factor analysis", + "type": "article-journal", + "volume": "20" + }, + { + "URL": "http://www.numdam.org/article/RSA_1988__36_1_55_0.pdf", + "author": [ + { + "family": "Rivest", + "given": "Louis-Paul" + }, + { + "family": "Plante", + "given": "Nathalie" + } + ], + "container-title": "Revue de statistique appliquée", + "id": "rivest1988analyse", + "issue": "1", + "issued": { + "date-parts": [ + [ + 1988 + ] + ] + }, + "page": "55-66", + "title": "L’analyse en composantes principales robuste", + "type": "article-journal", + "volume": "36" + }, + { + "URL": "https://doi.org/10.1111/gec3.12373", + "author": [ + { + "family": "McClintock", + "given": "Nathan" + } + ], + "container-title": "Geography Compass", + "id": "mcclintock2018urban", + "issue": "6", + "issued": { + "date-parts": [ + [ + 2018 + ] + ] + }, + "page": "1-16", + "title": "Urban agriculture, racial capitalism, and resistance in the settler-colonial city", + "type": "article-journal", + "volume": "12" + }, + { + "URL": "https://doi.org/10.1016/j.ufug.2021.127171", + "author": [ + { + "family": "Audate", + "given": "Pierre Paul" + }, + { + "family": "Cloutier", + "given": "Geneviève" + }, + { + "family": "Lebel", + "given": "Alexandre" + } + ], + "container-title": "Urban Forestry & Urban Greening", + "id": "audate2021motivations", + "issued": { + "date-parts": [ + [ + 2021 + ] + ] + }, + "page": "127171", + "title": "The motivations of urban agriculture practitioners in deprived neighborhoods: A comparative study of montreal and quito", + "title-short": "The motivations of urban agriculture practitioners in deprived neighborhoods", + "type": "article-journal", + "volume": "62" + }, + { + "URL": "http://dx.doi.org/10.2134/urbanag2015.01.1511", + "author": [ + { + "family": "Bhatt", + "given": "Vikram" + }, + { + "family": "Farah", + "given": "Leila Marie" + } + ], + "container-title": "Urban Agriculture & Regional Food Systems", + "id": "bhatt2016cultivating", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2016 + ] + ] + }, + "page": "1-12", + "title": "Cultivating montreal: A brief history of citizens and institutions integrating urban agriculture in the city", + "title-short": "Cultivating montreal", + "type": "article-journal", + "volume": "1" + }, + { + "URL": "https://doi.org/10.1198/004017004000000563", + "author": [ + { + "family": "Hubert", + "given": "Mia" + }, + { + "family": "Rousseeuw", + "given": "Peter J" + }, + { + "family": "Vanden Branden", + "given": "Karlien" + } + ], + "container-title": "Technometrics", + "id": "hubert2005robpca", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2005 + ] + ] + }, + "page": "64-79", + "title": "ROBPCA: A new approach to robust principal component analysis", + "title-short": "ROBPCA", + "type": "article-journal", + "volume": "47" + }, + { + "URL": "https://doi.org/10.1080/0267257X.1995.9964368", + "author": [ + { + "family": "Bendixen", + "given": "Mike T" + } + ], + "container-title": "Journal of Marketing Management", + "id": "bendixen1995compositional", + "issue": "6", + "issued": { + "date-parts": [ + [ + 1995 + ] + ] + }, + "page": "571-581", + "title": "Compositional perceptual mapping using chi-squared trees analysis and correspondence analysis", + "type": "article-journal", + "volume": "11" + }, + { + "URL": "https://doi.org/10.1080/01621459.1963.10500845", + "author": [ + { + "family": "Ward", + "given": "Joe H" + } + ], + "container-title": "Journal of the American statistical association", + "id": "ward1963hierarchical", + "issue": "301", + "issued": { + "date-parts": [ + [ + 1963 + ] + ] + }, + "page": "236-244", + "title": "Hierarchical grouping to optimize an objective function", + "type": "article-journal", + "volume": "58" + }, + { + "author": [ + { + "family": "Fukuyama", + "given": "Yoshiki" + } + ], + "container-title": "Proc. 5th fuzzy syst. Symp., 1989", + "id": "fukuyama1989", + "issued": { + "date-parts": [ + [ + 1989 + ] + ] + }, + "page": "247-250", + "title": "A new method of choosing the number of clusters for the fuzzy c-mean method", + "type": "paper-conference" + }, + { + "URL": "https://doi.org/10.1109/34.85677", + "author": [ + { + "family": "Xie", + "given": "Xuanli Lisa" + }, + { + "family": "Beni", + "given": "Gerardo" + } + ], + "container-title": "IEEE Transactions on pattern analysis and machine intelligence", + "id": "xie1991validity", + "issue": "8", + "issued": { + "date-parts": [ + [ + 1991 + ] + ] + }, + "page": "841-847", + "title": "A validity measure for fuzzy clustering", + "type": "article-journal", + "volume": "13" + }, + { + "URL": "10.18637/jss.v025.i01", + "author": [ + { + "family": "Lê", + "given": "Sébastien" + }, + { + "family": "Josse", + "given": "Julie" + }, + { + "family": "Husson", + "given": "François" + } + ], + "container-title": "Journal of Statistical Software", + "id": "FactoMineR", + "issue": "1", + "issued": { + "date-parts": [ + [ + 2008 + ] + ] + }, + "page": "1-18", + "title": "FactoMineR: A package for multivariate analysis", + "title-short": "FactoMineR", + "type": "article-journal", + "volume": "25" + } + ], + "project_biblios": [ + "references.bib" + ] +} \ No newline at end of file diff --git a/.Rproj.user/32A8B38A/jobs/48FFD5CC-output.json b/.Rproj.user/32A8B38A/jobs/48FFD5CC-output.json new file mode 100644 index 0000000..8c185fb --- /dev/null +++ b/.Rproj.user/32A8B38A/jobs/48FFD5CC-output.json @@ -0,0 +1,714 @@ +[2,"\n"] +[1,"Rendering:\n"] +[1,"\r[ 1/17] index.qmd\n"] +[1,"\r\n\r\nprocessing file: index.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r |.......... | 20% \r | \r |..................... | 40% [unnamed-chunk-1]"] +[1,"\r | \r |............................... | 60% \r | \r |.......................................... | 80% [unnamed-chunk-2]"] +[1,"\r | \r |....................................................| 100% \r \r\noutput file: index.knit.md\r\n\r\n"] +[1,"\r[ 2/17] 00-auteurs.qmd\n"] +[1,"\r[ 3/17] 01-priseenmainR.qmd\n"] +[1,"\r\n\r\nprocessing file: 01-priseenmainR.qmd\r\n"] +[1,"\r | \r | | 0% \r | \r | | 1% [ma_somme] \r | \r |. | 1% \r | \r |. | 2% [unnamed-chunk-2] "] +[1," [unnamed-chunk-3] \r | \r |. | 3% [unnamed-chunk-4] \r | \r |.. | 4% [unnamed-chunk-5] "] +[1," \r | \r |.. | 5% [unnamed-chunk-6] "] +[1," \r | \r |.. | 6% [unnamed-chunk-7] \r | \r |... | 6% \r | \r |... | 7% [unnamed-chunk-8] [unnamed-chunk-9] "] +[1,"\r | \r |... | 8% [unnamed-chunk-10] \r | \r |.... | 9% [unnamed-chunk-11] "] +[1," \r | \r |.... | 10% [unnamed-chunk-12] \r | \r |.... | 11% [unnamed-chunk-13] \r | \r |..... | 11% [unnamed-chunk-14] "] +[1,"\r | \r |..... | 12% [unnamed-chunk-15] \r | \r |..... | 13% [unnamed-chunk-16] "] +[1,"\r | \r |...... | 13% \r | \r |...... | 14% [unnamed-chunk-17] \r | \r |...... | 15% [unnamed-chunk-18] \r | \r |....... | 16% [unnamed-chunk-19] "] +[1," [unnamed-chunk-20] \r | \r |....... | 17% [unnamed-chunk-21] "] +[1,"\r | \r |....... | 18% \r | \r |........ | 18% [unnamed-chunk-22] \r | \r |........ | 19% [unnamed-chunk-23] \r | \r |........ | 20% [unnamed-chunk-24] "] +[1," \r | \r |......... | 20% [unnamed-chunk-25] \r | \r |......... | 21% [unnamed-chunk-26] "] +[1,"\r | \r |......... | 22% [unnamed-chunk-27] \r | \r |.......... | 23% [unnamed-chunk-28] "] +[1," \r | \r |.......... | 24% [tbl-OperateurMath] [tbl-OperateurRelationnels]"] +[1,"\r | \r |.......... | 25% \r | \r |........... | 25% [tbl-tableOperateurLogi] \r | \r |........... | 26% [unnamed-chunk-32] "] +[1,"\r | \r |........... | 27% [unnamed-chunk-33] "] +[1," \r | \r |............ | 28% [unnamed-chunk-34] \r | \r |............ | 29% [unnamed-chunk-35] [unnamed-chunk-36] "] +[1,"\r | \r |............. | 30% [unnamed-chunk-37] \r | \r |............. | 31% [unnamed-chunk-38] "] +[1," \r | \r |............. | 32% [unnamed-chunk-39] \r | \r |.............. | 32% \r | \r |.............. | 33% [unnamed-chunk-40] "] +[1," [unnamed-chunk-41] \r | \r |.............. | 34% [unnamed-chunk-42] "] +[1,"\r | \r |............... | 35% [unnamed-chunk-43] \r | \r |............... | 36% [unnamed-chunk-44] "] +[1," \r | \r |............... | 37% [unnamed-chunk-45] "] +[1,"\r | \r |................ | 37% \r | \r |................ | 38% [unnamed-chunk-46] [unnamed-chunk-47] "] +[1,"\r | \r |................ | 39% [tbl-tabfirsttable] "] +[1,"\r | \r |................. | 40% [unnamed-chunk-49] \r | \r |................. | 41% [unnamed-chunk-50] "] +[1," \r | \r |................. | 42% [unnamed-chunk-51] \r | \r |.................. | 42% [unnamed-chunk-52] "] +[1,"\r | \r |.................. | 43% [unnamed-chunk-53] \r | \r |.................. | 44% \r | \r |................... | 44% [unnamed-chunk-54] "] +[1," \r | \r |................... | 45% [unnamed-chunk-55] "] +[1," \r | \r |................... | 46% [unnamed-chunk-56] "] +[1," \r | \r |.................... | 47% [unnamed-chunk-57] [unnamed-chunk-58] "] +[1,"\r | \r |.................... | 48% [unnamed-chunk-59] "] +[1,"WARNING: An illegal reflective access operation has occurred\r\nWARNING: Illegal reflective access by org.apache.poi.util.SAXHelper (file:/C:/Users/appariciop/AppData/Local/R/win-library/4.4/xlsxjars/java/poi-ooxml-3.10.1-20140818.jar) to method com.sun.org.apache.xerces.internal.util.SecurityManager.setEntityExpansionLimit(int)\r\nWARNING: Please consider reporting this to the maintainers of org.apache.poi.util.SAXHelper\r\nWARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations\r\nWARNING: All illegal access operations will be denied in a future release\r\n"] +[1,"\r | \r |.................... | 49% \r | \r |..................... | 49% [unnamed-chunk-60] "] +[1," \r | \r |..................... | 50% [tbl-tableduration] "] +[1," \r | \r |..................... | 51% [tbl-Tidyverse] "] +[1," \r | \r |...................... | 51% [unnamed-chunk-63] "] +[1,"\r | \r |...................... | 52% [unnamed-chunk-64] "] +[1,"\r | \r |...................... | 53% [unnamed-chunk-65] \r | \r |....................... | 54% [unnamed-chunk-66] "] +[1," \r | \r |....................... | 55% [unnamed-chunk-67] "] +[1," \r | \r |....................... | 56% [unnamed-chunk-68] "] +[1," \r | \r |........................ | 56% [unnamed-chunk-69] \r | \r |........................ | 57% [unnamed-chunk-70] "] +[1,"\r | \r |........................ | 58% [unnamed-chunk-71] "] +[1,"\r | \r |......................... | 58% \r | \r |......................... | 59% [unnamed-chunk-72] \r | \r |......................... | 60% [unnamed-chunk-73] "] +[1," [unnamed-chunk-74] \r | \r |.......................... | 61% [unnamed-chunk-75] "] +[1,"\r | \r |.......................... | 62% [unnamed-chunk-76] "] +[1," \r | \r |.......................... | 63% [unnamed-chunk-77] "] +[1,"\r | \r |........................... | 63% \r | \r |........................... | 64% [unnamed-chunk-78] "] +[1," [unnamed-chunk-79] "] +[1,"\r | \r |........................... | 65% [unnamed-chunk-80] \r | \r |............................ | 66% [unnamed-chunk-81] "] +[1,"\r | \r |............................ | 67% [unnamed-chunk-82] \r | \r |............................ | 68% [unnamed-chunk-83] "] +[1,"\r | \r |............................. | 68% \r | \r |............................. | 69% [unnamed-chunk-84] [unnamed-chunk-85] "] +[1,"\r | \r |............................. | 70% [unnamed-chunk-86] "] +[1,"\r | \r |.............................. | 71% [unnamed-chunk-87] \r | \r |.............................. | 72% [unnamed-chunk-88] \r | \r |............................... | 73% [fig-fig015] "] +[1," [unnamed-chunk-90] \r | \r |............................... | 74% [unnamed-chunk-91] "] +[1,"\r | \r |............................... | 75% \r | \r |................................ | 75% [unnamed-chunk-92] \r | \r |................................ | 76% [unnamed-chunk-93] "] +[1," \r | \r |................................ | 77% [unnamed-chunk-94] "] +[1," \r | \r |................................. | 78% [unnamed-chunk-95] [unnamed-chunk-96] "] +[1,"\r | \r |................................. | 79% [unnamed-chunk-97] \r | \r |................................. | 80% \r | \r |.................................. | 80% [unnamed-chunk-98] "] +[1," \r | \r |.................................. | 81% [unnamed-chunk-99] "] +[1," \r | \r |.................................. | 82% [unnamed-chunk-100] \r | \r |................................... | 82% [unnamed-chunk-101] \r | \r |................................... | 83% [unnamed-chunk-102] "] +[1,"\r | \r |................................... | 84% [unnamed-chunk-103] \r | \r |.................................... | 85% [unnamed-chunk-104] "] +[1," \r | \r |.................................... | 86% [unnamed-chunk-105] \r | \r |.................................... | 87% [unnamed-chunk-106] "] +[1,"\r | \r |..................................... | 87% [unnamed-chunk-107] \r | \r |..................................... | 88% [unnamed-chunk-108] "] +[1,"\r | \r |..................................... | 89% [unnamed-chunk-109] \r | \r |...................................... | 89% \r | \r |...................................... | 90% [unnamed-chunk-110] \r | \r |...................................... | 91% [unnamed-chunk-111] "] +[1," [unnamed-chunk-112] "] +[1,"\r | \r |....................................... | 92% [unnamed-chunk-113] \r | \r |....................................... | 93% [unnamed-chunk-114] "] +[1," \r | \r |....................................... | 94% [unnamed-chunk-115] \r | \r |........................................ | 94% \r | \r |........................................ | 95% [unnamed-chunk-116] \r | \r |........................................ | 96% [unnamed-chunk-117] "] +[1," [unnamed-chunk-118] \r | \r |......................................... | 97% [unnamed-chunk-119] "] +[1,"\r | \r |......................................... | 98% [unnamed-chunk-120] \r | \r |......................................... | 99% [tbl-tableRessources] "] +[1,"\r | \r |..........................................| 99% \r | \r |..........................................| 100% [quizChapitre01] "] +[1," \r \noutput file: 01-priseenmainR.knit.md\n\n"] +[1,"WARNING: Warning: diff of engine output timed out. No source lines will be available.\n"] +[1,"\r[ 4/17] 02-univarie.qmd\n"] +[1,"\r\n\r\nprocessing file: 02-univarie.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r | | 1% \r | \r |. | 2% [fig-fig251] "] +[1," \r | \r |. | 3% [fig-fig252] "] +[1,"\r | \r |.. | 4% \r | \r |.. | 5% [fig-fig253] "] +[1,"\r | \r |.. | 6% \r | \r |... | 6% [fig-fig254] "] +[1,"\r | \r |... | 7% \r | \r |... | 8% [unnamed-chunk-5] "] +[1,"\r | \r |.... | 9% [fig-fig256] "] +[1,"\r | \r |.... | 10% \r | \r |..... | 11% [fig-fig257] "] +[1,"\r | \r |..... | 12% \r | \r |..... | 13% [fig-fig258] "] +[1,"\r | \r |...... | 13% \r | \r |...... | 14% [fig-fig259] "] +[1,"\r | \r |...... | 15% \r | \r |....... | 16% [fig-fig259b] "] +[1,"\r | \r |....... | 17% [fig-fig260] "] +[1,"\r | \r |........ | 18% \r | \r |........ | 19% [fig-fig261] "] +[1,"\r | \r |........ | 20% \r | \r |......... | 20% [fig-fig262] "] +[1,"\r | \r |......... | 21% \r | \r |......... | 22% [fig-fig263] "] +[1,"\r | \r |.......... | 23% \r | \r |.......... | 24% [fig-fig264] "] +[1," \r | \r |........... | 25% [fig-fig265] "] +[1,"\r | \r |........... | 26% \r | \r |........... | 27% [fig-fig266] "] +[1,"\r | \r |............ | 28% [fig-fig267] "] +[1,"\r | \r |............ | 29% \r | \r |............. | 30% [fig-fig268] "] +[1,"\r | \r |............. | 31% [fig-fig269] "] +[1,"\r | \r |.............. | 32% \r | \r |.............. | 33% [fig-fig270] "] +[1,"\r | \r |.............. | 34% \r | \r |............... | 35% [tbl-RevMoyMed] \r | \r |............... | 36% [tbl-Centiles] "] +[1,"\r | \r |................ | 37% \r | \r |................ | 38% [tbl-datavar] "] +[1,"\r | \r |................ | 39% \r | \r |................. | 39% [tbl-datavar2] "] +[1,"\r | \r |................. | 40% \r | \r |................. | 41% [tbl-resume] "] +[1,"\r | \r |.................. | 42% \r | \r |.................. | 43% [fig-asymetrie] "] +[1," \r | \r |................... | 44% [fig-kurtosis] "] +[1,"\r | \r |................... | 45% \r | \r |................... | 46% [unnamed-chunk-29] "] +[1,"\r | \r |.................... | 46% \r | \r |.................... | 47% [fig-CourbeNormale] "] +[1,"\r | \r |.................... | 48% \r | \r |..................... | 49% [fig-qqplot] "] +[1,"\r | \r |..................... | 50% [tbl-testnormalites] "] +[1,"\r | \r |..................... | 51% \r | \r |...................... | 52% [tbl-calcultestnormalites] "] +[1,"\r | \r |...................... | 53% \r | \r |...................... | 54% [unnamed-chunk-34] \r | \r |....................... | 54% \r | \r |....................... | 55% [unnamed-chunk-35] "] +[1,"\r | \r |....................... | 56% \r | \r |........................ | 57% [unnamed-chunk-36] \r | \r |........................ | 58% [unnamed-chunk-37] "] +[1,"\r | \r |......................... | 59% \r | \r |......................... | 60% [unnamed-chunk-38] \r | \r |......................... | 61% \r | \r |.......................... | 61% [fig-bustrt] "] +[1,"\r | \r |.......................... | 62% \r | \r |.......................... | 63% [fig-bustrt2] "] +[1,"\r | \r |........................... | 64% \r | \r |........................... | 65% [tbl-distribs] \r | \r |............................ | 66% [unnamed-chunk-42] "] +[1,"\r | \r |............................ | 67% \r | \r |............................ | 68% [unnamed-chunk-43] \r | \r |............................. | 69% [unnamed-chunk-44] "] +[1,"\r | \r |............................. | 70% \r | \r |.............................. | 71% [unnamed-chunk-45] \r | \r |.............................. | 72% [fig-accmtl] "] +[1,"\r | \r |............................... | 73% \r | \r |............................... | 74% [fig-accmtldist] "] +[1,"\r | \r |............................... | 75% \r | \r |................................ | 76% [unnamed-chunk-48] \r | \r |................................ | 77% [unnamed-chunk-49] "] +[1,"\r | \r |................................. | 78% \r | \r |................................. | 79% [tbl-AutresTransformation] "] +[1,"\r | \r |................................. | 80% \r | \r |.................................. | 80% [tbl-AutresTransformation2]\r | \r |.................................. | 81% \r | \r |.................................. | 82% [StatDesc1] "] +[1,"\r | \r |................................... | 83% [fig-GcourbeNormale] "] +[1,"\r | \r |................................... | 84% \r | \r |.................................... | 85% [StatDesc2] "] +[1,"\r | \r |.................................... | 86% \r | \r |.................................... | 87% [fig-GTranf] "] +[1,"\r | \r |..................................... | 87% \r | \r |..................................... | 88% [tbl-Frequences] "] +[1,"\r | \r |..................................... | 89% \r | \r |...................................... | 90% [tbl-Frequences2] "] +[1,"\r | \r |...................................... | 91% [fig-GraphiquesFreq1] "] +[1,"\r | \r |....................................... | 92% \r | \r |....................................... | 93% [unnamed-chunk-59] "] +[1,"\r | \r |....................................... | 94% \r | \r |........................................ | 94% [tbl-MoyPondCalcul] "] +[1,"\r | \r |........................................ | 95% \r | \r |........................................ | 96% [tbl-MoyPondParc] \r | \r |......................................... | 97% \r | \r |......................................... | 98% [unnamed-chunk-62] "] +[1," \r | \r |..........................................| 99% [quizChapitre02] "] +[1,"\r | \r |..........................................| 100% \r \r\noutput file: 02-univarie.knit.md\r\n\r\n"] +[1,"WARNING: Warning: diff of engine output timed out. No source lines will be available.\n"] +[1,"\r[ 5/17] 03-magiedesgraphiques.qmd\n"] +[1,"\r\n\r\nprocessing file: 03-magiedesgraphiques.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r | | 1% \r | \r |. | 2% [fig-fig31] "] +[1," \r | \r |.. | 3% [fig-fig32] "] +[1,"\r | \r |.. | 4% \r | \r |.. | 5% [fig-fig33] "] +[1,"\r | \r |... | 6% \r | \r |... | 7% [fig-fig34] "] +[1,"\r | \r |.... | 7% \r | \r |.... | 8% [tbl-geometries] \r | \r |..... | 9% \r | \r |..... | 10% [fig-fig35] "] +[1,"\r | \r |..... | 11% \r | \r |...... | 11% [fig-fig36] "] +[1,"\r | \r |...... | 12% \r | \r |....... | 13% [fig-fig37] "] +[1,"\r | \r |....... | 14% \r | \r |....... | 15% [fig-fig38] "] +[1,"\r | \r |........ | 15% \r | \r |........ | 16% [fig-fig39] "] +[1,"\r | \r |......... | 17% \r | \r |......... | 18% [fig-fig310] "] +[1,"\r | \r |.......... | 19% \r | \r |.......... | 20% [fig-fig311] "] +[1," \r | \r |........... | 21% [fig-fig312] "] +[1,"\r | \r |........... | 22% \r | \r |............ | 23% [fig-fig313] "] +[1,"\r | \r |............ | 24% [fig-fig314] "] +[1,"\r | \r |............. | 25% \r | \r |............. | 26% [fig-fig315] "] +[1,"\r | \r |.............. | 27% \r | \r |.............. | 28% [fig-fig316] "] +[1,"\r | \r |............... | 28% \r | \r |............... | 29% [fig-fig317] "] +[1,"\r | \r |............... | 30% \r | \r |................ | 31% [fig-colorBrewer] "] +[1,"\r | \r |................ | 32% \r | \r |................. | 33% [fig-fig318] "] +[1," \r | \r |................. | 34% [fig-fig320] "] +[1,"\r | \r |.................. | 35% \r | \r |.................. | 36% [fig-fig321] "] +[1,"\r | \r |................... | 37% [fig-fig322] "] +[1,"\r | \r |................... | 38% \r | \r |.................... | 39% [fig-fig323] "] +[1,"\r | \r |.................... | 40% \r | \r |..................... | 41% [fig-fig324] "] +[1," \r | \r |...................... | 42% [fig-fig325] "] +[1,"\r | \r |...................... | 43% \r | \r |...................... | 44% [unnamed-chunk-27]"] +[1,"\r | \r |....................... | 45% \r | \r |....................... | 46% [unnamed-chunk-28]"] +[1,"\r | \r |........................ | 46% \r | \r |........................ | 47% [fig-fig326] "] +[1,"\r | \r |........................ | 48% \r | \r |......................... | 49% [unnamed-chunk-30]\r | \r |......................... | 50% \r | \r |.......................... | 50% [unnamed-chunk-31]"] +[1,"\r | \r |.......................... | 51% \r | \r |........................... | 52% [fig-fig327] \r | \r |........................... | 53% \r | \r |........................... | 54% [fig-fig328] "] +[1,"\r | \r |............................ | 54% \r | \r |............................ | 55% [fig-fig329] "] +[1,"\r | \r |............................. | 56% "] +[1,"\r | \r |............................. | 57% [fig-fig330] "] +[1,"\r | \r |............................. | 58% \r | \r |.............................. | 59% [fig-fig331] "] +[1," \r | \r |............................... | 60% [fig-fig332] "] +[1,"\r | \r |............................... | 61% \r | \r |................................ | 62% [fig-fig333] "] +[1,"\r | \r |................................ | 63% [fig-fig334] "] +[1,"\r | \r |................................. | 64% \r | \r |................................. | 65% [fig-fig335] "] +[1,"\r | \r |.................................. | 66% \r | \r |.................................. | 67% [fig-fig336] "] +[1," \r | \r |................................... | 68% [fig-fig337] "] +[1,"\r | \r |................................... | 69% \r | \r |.................................... | 70% [fig-fig338] "] +[1,"\r | \r |.................................... | 71% \r | \r |.................................... | 72% [fig-fig339] "] +[1,"\r | \r |..................................... | 72% \r | \r |..................................... | 73% [fig-fig340] "] +[1,"\r | \r |...................................... | 74% \r | \r |...................................... | 75% [fig-fig341] "] +[1,"\r | \r |....................................... | 76% [fig-fig342] "] +[1,"\r | \r |....................................... | 77% \r | \r |........................................ | 78% [fig-fig344] "] +[1,"\r | "] +[1,"\r |........................................ | 79% \r | \r |......................................... | 80% [fig-fig345] "] +[1," \r | \r |......................................... | 81% [fig-fig346] "] +[1,"\r | \r |.......................................... | 82% \r | \r |.......................................... | 83% [fig-fig347] "] +[1,"\r | \r |........................................... | 84% \r | \r |........................................... | 85% [fig-fig348] "] +[1,"\r | \r |............................................ | 85% \r | \r |............................................ | 86% [unnamed-chunk-53]"] +[1,"\r | \r |............................................ | 87% \r | \r |............................................. | 88% [fig-fig349] "] +[1,"\r | \r |............................................. | 89% \r | \r |.............................................. | 89% [unnamed-chunk-55]"] +[1,"\r | \r |.............................................. | 90% \r | \r |.............................................. | 91% [fig-fig352] "] +[1,"\r | \r |............................................... | 92% \r | \r |............................................... | 93% [fig-fig353] "] +[1,"\r | \r |................................................ | 93% \r | \r |................................................ | 94% [fig-fig354] "] +[1,"\r | \r |................................................. | 95% \r | \r |................................................. | 96% [fig-fig355] "] +[1,"\r | \r |................................................. | 97% \r | \r |.................................................. | 98% [unnamed-chunk-60]"] +[1," \r | \r |...................................................| 99% [unnamed-chunk-61]\r | \r |...................................................| 100% \r \r\noutput file: 03-magiedesgraphiques.knit.md\r\n\r\n"] +[1,"\r[ 6/17] 04-bivarieeQuantiQuanti.qmd\n"] +[1,"\r\n\r\nprocessing file: 04-bivarieeQuantiQuanti.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r |. | 2% \r | \r |. | 4% [fig-covariance] "] +[1,"\r | \r |.. | 5% \r | \r |... | 7% [unnamed-chunk-2] "] +[1,"\r | \r |... | 9% \r | \r |.... | 11% [fig-coeffPearson] "] +[1,"\r | \r |..... | 13% \r | \r |..... | 15% [tbl-tableIntervallesCorrelation]\r | \r |...... | 16% \r | \r |....... | 18% [fig-coefCorrVar] "] +[1,"\r | \r |....... | 20% \r | \r |........ | 22% [fig-ValExtremes] "] +[1,"\r | \r |......... | 24% \r | \r |......... | 25% [unnamed-chunk-7] "] +[1,"\r | \r |.......... | 27% \r | \r |.......... | 29% [fig-PearsonSpearmanKendall] "] +[1,"\r | \r |........... | 31% \r | \r |............ | 33% [unnamed-chunk-9] "] +[1,"\r | \r |............ | 35% \r | \r |............. | 36% [tbl-robcorr] "] +[1,"\r | \r |.............. | 38% \r | \r |.............. | 40% [unnamed-chunk-11] "] +[1,"\r | \r |............... | 42% \r | \r |................ | 44% [unnamed-chunk-12] "] +[1,"\r | \r |................ | 45% \r | \r |................. | 47% [unnamed-chunk-13] \r | \r |.................. | 49% \r | \r |.................. | 51% [fig-fig9] "] +[1,"\r | \r |................... | 53% \r | \r |.................... | 55% [unnamed-chunk-15] "] +[1,"\r | \r |.................... | 56% \r | \r |..................... | 58% [unnamed-chunk-16] "] +[1,"\r | \r |...................... | 60% \r | \r |...................... | 62% [fig-corrplot1] "] +[1,"\r | \r |....................... | 64% \r | \r |........................ | 65% [fig-corrplot2] "] +[1,"\r | \r |........................ | 67% \r | \r |......................... | 69% [fig-corraleatoire] "] +[1,"\r | \r |.......................... | 71% \r | \r |.......................... | 73% [tbl-regfictives] \r | \r |........................... | 75% \r | \r |........................... | 76% [fig-reg] "] +[1,"\r | \r |............................ | 78% \r | \r |............................. | 80% [fig-reg2] "] +[1,"\r | \r |............................. | 82% \r | \r |.............................. | 84% [tbl-regfictives2] "] +[1,"\r | \r |............................... | 85% \r | \r |............................... | 87% [tbl-computeR] "] +[1,"\r | \r |................................ | 89% \r | \r |................................. | 91% [unnamed-chunk-25] \r | \r |................................. | 93% \r | \r |.................................. | 95% [unnamed-chunk-26] "] +[1,"\r | \r |................................... | 96% \r | \r |................................... | 98% [quizChapitre4] "] +[1,"\r | \r |....................................| 100% \r \r\noutput file: 04-bivarieeQuantiQuanti.knit.md\r\n\r\n"] +[1,"\r[ 7/17] 05-bivarieeQualiQuali.qmd\n"] +[1,"\r\n\r\nprocessing file: 05-bivarieeQualiQuali.qmd\r\n\r | \r | | 0%\r | \r |.. | 5% \r | \r |.... | 10% [tablecontingence] "] +[1,"\r | \r |...... | 14% \r | \r |........ | 19% [unnamed-chunk-2] "] +[1,"\r | \r |.......... | 24% \r | \r |............. | 29% [tbl-EncadreAsso] "] +[1,"\r | \r |............... | 33% \r | \r |................. | 38% [unnamed-chunk-4] \r | \r |................... | 43% \r | \r |..................... | 48% [unnamed-chunk-5] "] +[1,"\r | \r |....................... | 52% \r | \r |......................... | 57% [unnamed-chunk-6] "] +[1,"\r | \r |........................... | 62% \r | \r |............................. | 67% [unnamed-chunk-7] "] +[1,"\r | \r |............................... | 71% \r | \r |.................................. | 76% [tbl-MesuresAssociations]\r | \r |.................................... | 81% \r | \r |...................................... | 86% [fig-VDC] "] +[1,"\r | \r |........................................ | 90% \r | \r |.......................................... | 95% [quizChapitre5] "] +[1,"\r | \r |............................................| 100% \r \r\noutput file: 05-bivarieeQualiQuali.knit.md\r\n\r\n"] +[1,"Registered S3 method overwritten by 'DescTools':\r\n method from \r\n reorder.factor gdata\r\n"] +[1,"\r[ 8/17] 06-bivarieeQualiQuanti.qmd\n"] +[1,"\r\n\r\nprocessing file: 06-bivarieeQualiQuanti.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r |. | 2% \r | \r |.. | 4% [fig-ttest1] "] +[1,"\r | \r |... | 6% \r | \r |.... | 8% [fig-ttest2] "] +[1,"\r | \r |..... | 10% \r | \r |...... | 12% [tbl-convcohen] \r | \r |....... | 14% \r | \r |........ | 16% [unnamed-chunk-4] "] +[1,"\r | \r |......... | 18% \r | \r |.......... | 20% [unnamed-chunk-5] "] +[1,"\r | \r |........... | 22% \r | \r |............ | 24% [unnamed-chunk-6] "] +[1,"\r | \r |............ | 27% \r | \r |............. | 29% [unnamed-chunk-7] "] +[1,"\r | \r |.............. | 31% \r | \r |............... | 33% [unnamed-chunk-8] "] +[1,"\r | \r |................ | 35% \r | \r |................. | 37% [unnamed-chunk-9] \r | \r |.................. | 39% \r | \r |................... | 41% [tbl-aovfictive1] "] +[1,"\r | \r |.................... | 43% \r | \r |..................... | 45% [tbl-aovfictive2] "] +[1,"\r | \r |...................... | 47% \r | \r |....................... | 49% [unnamed-chunk-12] "] +[1,"\r | \r |........................ | 51% \r | \r |......................... | 53% [fig-Anova1a] "] +[1,"\r | \r |.......................... | 55% \r | \r |........................... | 57% [fig-Qqplot] "] +[1,"\r | \r |............................ | 59% \r | \r |............................. | 61% [unnamed-chunk-15] "] +[1,"\r | \r |.............................. | 63% \r | \r |............................... | 65% [unnamed-chunk-16] "] +[1,"\r | \r |................................ | 67% \r | \r |................................. | 69% [unnamed-chunk-17] "] +[1,"\r | \r |.................................. | 71% \r | \r |................................... | 73% [fig-Anova1b] "] +[1,"\r | \r |................................... | 76% \r | \r |.................................... | 78% [fig-Qqplot2] "] +[1,"\r | \r |..................................... | 80% \r | \r |...................................... | 82% [unnamed-chunk-20] \r | \r |....................................... | 84% \r | \r |........................................ | 86% [unnamed-chunk-21] "] +[1,"\r | \r |......................................... | 88% \r | \r |.......................................... | 90% [unnamed-chunk-22] "] +[1,"\r | \r |........................................... | 92% \r | \r |............................................ | 94% [unnamed-chunk-23] "] +[1,"\r | \r |............................................. | 96% \r | \r |.............................................. | 98% [Chapitre6QualiQuanti]"] +[1,"\r | \r |...............................................| 100% \r \r\noutput file: 06-bivarieeQualiQuanti.knit.md\r\n\r\n"] +[1,"\r[ 9/17] 07-regressionlineaire.qmd\n"] +[1,"\r\n\r\nprocessing file: 07-regressionlineaire.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r | | 1% \r | \r | | 2% [tbl-datareg] "] +[1,"\r | \r |. | 2% \r | \r |. | 3% [unnamed-chunk-2] "] +[1,"\r | \r |. | 4% \r | \r |. | 5% [unnamed-chunk-3] "] +[1,"\r | \r |.. | 6% [unnamed-chunk-4] \r | \r |.. | 7% \r | \r |.. | 8% [tbl-dataregmodel2] "] +[1,"\r | \r |... | 9% [unnamed-chunk-6] "] +[1,"\r | \r |... | 10% \r | \r |... | 11% [tbl-CoefStand2] "] +[1,"\r | \r |.... | 12% \r | \r |.... | 13% [unnamed-chunk-8] \r | \r |.... | 14% [unnamed-chunk-9] "] +[1,"\r | \r |..... | 15% \r | \r |..... | 16% [unnamed-chunk-10] \r | \r |..... | 17% [unnamed-chunk-11] "] +[1,"\r | \r |...... | 18% \r | \r |...... | 19% [fig-calculRegPoly2] "] +[1,"\r | \r |...... | 20% [tbl-regmodeleLog] "] +[1,"\r | \r |....... | 21% \r | \r |....... | 22% [fig-EffetMarginalVariableLogEtNon] "] +[1,"\r | \r |....... | 23% \r | \r |....... | 24% [regmodeleDich] \r | \r |........ | 24% \r | \r |........ | 25% [tbl-regmodeleDich2] "] +[1,"\r | \r |........ | 26% \r | \r |........ | 27% [fig-EffetMarginalDich] "] +[1,"\r | \r |......... | 28% [tbl-transfVarQMuettes] "] +[1,"\r | \r |......... | 29% \r | \r |......... | 30% [tbl-ModeleVarPoly1] "] +[1,"\r | \r |.......... | 31% [tbl-ModeleVarPoly2] "] +[1,"\r | \r |.......... | 32% \r | \r |.......... | 33% [tbl-ModeleVarPoly3] "] +[1,"\r | \r |.......... | 34% \r | \r |........... | 35% [fig-EffetMarginalPoly] "] +[1," \r | \r |........... | 36% [tbl-ModeleInteraction1] "] +[1,"\r | \r |........... | 37% \r | \r |............ | 38% [tbl-ModeleInteraction2] "] +[1,"\r | \r |............ | 39% [fig-ModeleInteraction2heat] "] +[1,"\r | \r |............ | 40% \r | \r |............. | 41% [fig-ModeleInteraction2heat2] "] +[1,"\r | \r |............. | 42% \r | \r |............. | 43% [tbl-ModeleInteractionBinaire] "] +[1," \r | \r |.............. | 44% [fig-ModeleInteractionBinaire] "] +[1,"\r | \r |.............. | 45% \r | \r |.............. | 46% [unnamed-chunk-29] "] +[1," \r | \r |............... | 47% [fig-VerifierNormaliteResidus] "] +[1,"\r | \r |............... | 48% \r | \r |............... | 49% [fig-VerifierHomoscedasticite] "] +[1,"\r | \r |............... | 50% \r | \r |................ | 50% [unnamed-chunk-32] "] +[1,"\r | \r |................ | 51% \r | \r |................ | 52% [unnamed-chunk-33] "] +[1,"\r | \r |................ | 53% \r | \r |................. | 54% [unnamed-chunk-34] "] +[1," \r | \r |................. | 55% [unnamed-chunk-35] "] +[1,"\r | \r |................. | 56% \r | \r |.................. | 57% [fig-GraphCookLev] "] +[1," \r | \r |.................. | 58% [unnamed-chunk-37] "] +[1,"\r | \r |.................. | 59% \r | \r |................... | 60% [unnamed-chunk-38] "] +[1,"\r | \r |................... | 61% [unnamed-chunk-39] \r | \r |................... | 62% \r | \r |.................... | 63% [unnamed-chunk-40] "] +[1,"\r | \r |.................... | 64% \r | \r |.................... | 65% [unnamed-chunk-41] "] +[1," \r | \r |..................... | 66% [unnamed-chunk-42] \r | \r |..................... | 67% \r | \r |..................... | 68% [unnamed-chunk-43] "] +[1,"\r | \r |..................... | 69% [fig-VerifierNormaliteResidusDia] "] +[1,"\r | \r |...................... | 70% \r | \r |...................... | 71% [unnamed-chunk-45] "] +[1,"\r | \r |...................... | 72% [fig-DiaHomoscedasticite] "] +[1,"\r | \r |....................... | 73% \r | \r |....................... | 74% [unnamed-chunk-47] \r | \r |....................... | 75% \r | \r |....................... | 76% [unnamed-chunk-48] "] +[1,"\r | \r |........................ | 76% \r | \r |........................ | 77% [fig-DiaGraphCookLev] "] +[1,"\r | \r |........................ | 78% "] +[1,"\r | \r |........................ | 79% [unnamed-chunk-50] \r | \r |......................... | 80% [unnamed-chunk-51] "] +[1,"\r | \r |......................... | 81% \r | \r |......................... | 82% [fig-ResidusCompa] "] +[1,"\r | \r |.......................... | 83% [unnamed-chunk-53] "] +[1,"\r | \r |.......................... | 84% \r | \r |.......................... | 85% [fig-HomosComp] "] +[1,"\r | \r |........................... | 86% \r | \r |........................... | 87% [unnamed-chunk-55] "] +[1," \r | \r |........................... | 88% [fig-EffetMarginalVariablesContinues] "] +[1,"\r | \r |............................ | 89% \r | \r |............................ | 90% [fig-Titi] "] +[1,"\r | \r |............................ | 91% [fig-EffetMarginalVariableLog] "] +[1,"\r | \r |............................. | 92% \r | \r |............................. | 93% [fig-EffetMarginalDichCode] "] +[1,"\r | \r |............................. | 94% [fig-EffetMarginalPolyT] "] +[1,"\r | \r |.............................. | 95% \r | \r |.............................. | 96% [fig-ModeleInteraction2heatex] "] +[1,"\r | \r |.............................. | 97% \r | \r |.............................. | 98% [fig-ModeleInteractionBinaireeffectex]"] +[1,"\r | \r |...............................| 98% \r | \r |...............................| 99% [quizChapitre6] "] +[1,"\r | \r |...............................| 100% \r \r\noutput file: 07-regressionlineaire.knit.md\r\n\r\n"] +[1,"WARNING: Warning: diff of engine output timed out. No source lines will be available.\n"] +[1,"\r[10/17] 08-GLM.qmd\n"] +[1,"\r\n\r\nprocessing file: 08-GLM.qmd\r\n"] +[1,"\r | \r | | 0% \r | \r | | 1% [fig-linearbinom] "] +[1," [fig-linearbinom2] "] +[1,"\r | \r |. | 1% \r | \r |. | 2% [fig-linearbinom3] "] +[1," [tbl-pseudor2] "] +[1,"\r | \r |. | 3% [tbl-confusmat1] "] +[1," [tbl-confusmat2] \r | \r |.. | 4% [tbl-Kappvals] "] +[1," \r | \r |.. | 5% [tbl-confusIndic] [tbl-binomidentity] "] +[1,"\r | \r |.. | 6% [tbl-binomdata] "] +[1," \r | \r |... | 6% [unnamed-chunk-11] "] +[1,"\r | \r |... | 7% [fig-cookdistGLMbinom] "] +[1," \r | \r |... | 8% [unnamed-chunk-13] "] +[1," [fig-cookdistGLMbinom2] "] +[1," \r | \r |.... | 9% [fig-residsimbinomHistoUnif]"] +[1," [unnamed-chunk-16] "] +[1,"\r | \r |.... | 10% [fig-residsimbinom] "] +[1," [unnamed-chunk-18] "] +[1,"\r | \r |.... | 11% \r | \r |..... | 11% [unnamed-chunk-19] "] +[1," \r | \r |..... | 12% [fig-equlibresensispeci] "] +[1," [unnamed-chunk-21] "] +[1," \r | \r |..... | 13% [tbl-confusmatbinom] [tbl-confusmatbinom2] "] +[1,"\r | \r |...... | 14% [unnamed-chunk-24] "] +[1," [fig-paysbinom] "] +[1,"\r | \r |...... | 15% [tbl-coeffbinom] "] +[1," \r | \r |...... | 16% [fig-villebinom] "] +[1,"\r | \r |....... | 16% [fig-agebinom] "] +[1,"\r | \r |....... | 17% [tbl-probitdentity] [tbl-cumuldentity] "] +[1,"\r | \r |....... | 18% [fig-histopriceairbnb] "] +[1," \r | \r |........ | 19% [unnamed-chunk-32] "] +[1," [unnamed-chunk-33] \r | \r |........ | 20% [tbl-variablecumul] "] +[1," [unnamed-chunk-35] "] +[1,"\r | \r |........ | 21% \r | \r |......... | 21% [unnamed-chunk-36] "] +[1," [fig-CookdCotePropor] "] +[1,"\r | \r |......... | 22% [unnamed-chunk-38] \r | \r |......... | 23% [unnamed-chunk-39] "] +[1," \r | \r |.......... | 23% [fig-diagressimcumul] "] +[1," \r | \r |.......... | 24% [unnamed-chunk-41] "] +[1," [fig-diagressimcumul2] "] +[1,"\r | \r |.......... | 25% [unnamed-chunk-43] "] +[1," \r | \r |.......... | 26% [unnamed-chunk-44] "] +[1,"\r | \r |........... | 26% [unnamed-chunk-45] \r | \r |........... | 27% [fig-diagressimcumul3] "] +[1," [unnamed-chunk-47] "] +[1,"\r | \r |........... | 28% [unnamed-chunk-48] "] +[1,"\r | \r |............ | 28% [unnamed-chunk-49] "] +[1,"\r | \r |............ | 29% [unnamed-chunk-50] "] +[1," \r | \r |............ | 30% [unnamed-chunk-51] "] +[1," [unnamed-chunk-52] "] +[1," \r | \r |............. | 31% [unnamed-chunk-53] "] +[1," [tbl-FinalOrdinale] "] +[1,"\r | \r |............. | 32% [fig-predpricecatveg] "] +[1," [tbl-multinomdentity] \r | \r |............. | 33% \r | \r |.............. | 33% [tbl-variablemultinom] "] +[1," \r | \r |.............. | 34% [vifmultinom] "] +[1," [unnamed-chunk-59] "] +[1," \r | \r |.............. | 35% [fig-cookmultinom] "] +[1," [unnamed-chunk-61] "] +[1,"\r | \r |............... | 36% [unnamed-chunk-62] "] +[1," \r | \r |............... | 37% [fig-residusmultinom] "] +[1," [unnamed-chunk-64] \r | \r |............... | 38% [fig-residusmultinom2] "] +[1,"\r | \r |................ | 38% [unnamed-chunk-66] "] +[1,"\r | \r |................ | 39% [fig-residusmultinom3] "] +[1," [unnamed-chunk-68] "] +[1,"\r | \r |................ | 40% [unnamed-chunk-69] "] +[1,"\r | \r |................. | 40% \r | \r |................. | 41% [fig-residusmultinom4] "] +[1," [unnamed-chunk-71] "] +[1," \r | \r |................. | 42% [unnamed-chunk-72] "] +[1," [unnamed-chunk-73] "] +[1,"\r | \r |................. | 43% \r | \r |.................. | 43% [tbl-coeffsmultinom1] [tbl-coeffsmultinom2] \r | \r |.................. | 44% [tbl-coeffsmultinom3] "] +[1," \r | \r |.................. | 45% [tbl-poissondentity] \r | \r |................... | 45% [tbl-variablepoiss] "] +[1,"\r | \r |................... | 46% [fig-distripoissmod] "] +[1," [unnamed-chunk-80] \r | \r |................... | 47% [fig-poisscookdist] "] +[1," \r | \r |................... | 48% [unnamed-chunk-82] "] +[1,"\r | \r |.................... | 48% [fig-poisscookdist2] "] +[1," \r | \r |.................... | 49% [unnamed-chunk-84] [unnamed-chunk-85] "] +[1,"\r | \r |.................... | 50% [fig-surdisppoiss] "] +[1,"\r | \r |..................... | 50% [unnamed-chunk-87] "] +[1,"\r | \r |..................... | 51% [fig-comppoissdistr] "] +[1," \r | \r |..................... | 52% [fig-comppoissdistr2] "] +[1," [fig-simrespoiss] "] +[1,"\r | \r |...................... | 52% \r | \r |...................... | 53% [unnamed-chunk-91] [fig-simrespoiss2] "] +[1,"\r | \r |...................... | 54% [unnamed-chunk-93] "] +[1," "] +[1," [unnamed-chunk-94] \r | \r |...................... | 55% \r | \r |....................... | 55% [unnamed-chunk-95] \r | \r |....................... | 56% [tbl-coeffpoiss] "] +[1," [tbl-nbdentity] "] +[1,"\r | \r |....................... | 57% [fig-cookdistnb] "] +[1," \r | \r |........................ | 57% [unnamed-chunk-99] "] +[1,"\r | \r |........................ | 58% [fig-cookdistnb2] "] +[1," \r | \r |........................ | 59% [fig-diagresnb] "] +[1," [fig-compnbdistr2] "] +[1," \r | \r |........................ | 60% [fig-surdispnb] "] +[1,"\r | \r |......................... | 60% [unnamed-chunk-104] "] +[1,"\r | \r |......................... | 61% [tbl-coeffsnb] "] +[1," [tbl-poisszidentity] "] +[1,"\r | \r |......................... | 62% [unnamed-chunk-107] "] +[1,"\r | \r |.......................... | 62% \r | \r |.......................... | 63% [tbl-poisszadentity] "] +[1," [unnamed-chunk-109] "] +[1," \r | \r |.......................... | 64% [unnamed-chunk-110] [fig-diagzip] "] +[1,"\r | \r |........................... | 65% [unnamed-chunk-112] \r | \r |........................... | 66% [fig-diagzip2] "] +[1," [fig-compzipdistr] "] +[1," \r | \r |........................... | 67% [unnamed-chunk-115] "] +[1," \r | \r |............................ | 67% [unnamed-chunk-116] "] +[1,"\r | \r |............................ | 68% [tbl-zapoisstab1] "] +[1," [tbl-zapoisstab2] "] +[1,"\r | \r |............................ | 69% [tbl-gaussiandentity] "] +[1," \r | \r |............................. | 70% [unnamed-chunk-120] "] +[1," [fig-gausscook] "] +[1," \r | \r |............................. | 71% [unnamed-chunk-122] [fig-gausscook2] "] +[1,"\r | \r |............................. | 72% [fig-gaussresid] "] +[1,"\r | \r |.............................. | 72% [fig-gausssim] "] +[1,"\r | \r |.............................. | 73% [fig-gausssim2] "] +[1," \r | \r |.............................. | 74% [unnamed-chunk-127] [unnamed-chunk-128] "] +[1,"\r | \r |............................... | 74% \r | \r |............................... | 75% [tbl-tableaugauss] "] +[1," [fig-studentdistrib] "] +[1,"\r | \r |............................... | 76% [tbl-studentdentity] "] +[1," \r | \r |............................... | 77% [fig-stucookdist] "] +[1," \r | \r |................................ | 77% [fig-stucookdist2] "] +[1," \r | \r |................................ | 78% [fig-studentresid] "] +[1," [fig-studentresid2] "] +[1,"\r | \r |................................ | 79% [fig-studentresid3] "] +[1," \r | \r |................................. | 79% [unnamed-chunk-137] "] +[1,"\r | \r |................................. | 80% [tbl-glmstudentres] \r | \r |................................. | 81% [tbl-gammadentity] "] +[1," [tbl-variablegamma] \r | \r |.................................. | 82% [fig-gammadatadistrib] "] +[1," [unnamed-chunk-142] "] +[1,"\r | \r |.................................. | 83% [fig-cookdistgamma] "] +[1," [unnamed-chunk-144] "] +[1,"\r | \r |.................................. | 84% [fig-cookdistgamma2] "] +[1,"\r | \r |................................... | 84% \r | \r |................................... | 85% [fig-simdistribgamma] "] +[1," [fig-gammaresids] "] +[1,"\r | \r |................................... | 86% [fig-gammaresids2] "] +[1," [fig-gammaresids3] "] +[1,"\r | \r |.................................... | 87% [fig-dispgamma] "] +[1," \r | \r |.................................... | 88% [unnamed-chunk-151] "] +[1," [fig-arrondgamma] "] +[1," \r | \r |.................................... | 89% [fig-heuresgamma] "] +[1," \r | \r |..................................... | 89% [tbl-coeffsgamma] "] +[1,"\r | \r |..................................... | 90% [fig-distancegamma] "] +[1," [tbl-betaentity] \r | \r |..................................... | 91% [tbl-variablebeta] \r | \r |...................................... | 92% [unnamed-chunk-158] "] +[1," [fig-cookdistbeta] "] +[1," \r | \r |...................................... | 93% [unnamed-chunk-160] [fig-cookdistbeta2] "] +[1,"\r | \r |...................................... | 94% \r | \r |....................................... | 94% [fig-cookdistbeta3] "] +[1," [fig-residsimbeta] "] +[1,"\r | \r |....................................... | 95% [unnamed-chunk-164] "] +[1," \r | \r |....................................... | 96% [fig-residsimbeta2] "] +[1," [fig-residsimbeta3] "] +[1,"\r | \r |........................................ | 97% [fig-residsimbeta4] "] +[1," [unnamed-chunk-168] \r | \r |........................................ | 98% [fig-betaArrond] "] +[1," \r | \r |........................................ | 99% [tbl-coeffsbeta] "] +[1,"\r | \r |.........................................| 99% [fig-betaFR] "] +[1," \r | \r |.........................................| 100% [quizGLM] "] +[1," \r \r\noutput file: 08-GLM.knit.md\r\n\r\n"] +[1,"WARNING: Warning: diff of engine output timed out. No source lines will be available.\n"] +[1,"\r[11/17] 09-GLMM.qmd\n"] +[1,"\r\n\r\nprocessing file: 09-GLMM.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r |. | 1% \r | \r |. | 2% [fig-randominter1] "] +[1,"\r | \r |.. | 4% \r | \r |.. | 5% [fig-randominter2] "] +[1,"\r | \r |... | 6% \r | \r |... | 7% [fig-randominter3] "] +[1,"\r | \r |.... | 8% \r | \r |.... | 9% [fig-randominter5] "] +[1,"\r | \r |..... | 11% \r | \r |..... | 12% [fig-randomslope] "] +[1,"\r | \r |...... | 13% \r | \r |...... | 14% [fig-randomslope2] "] +[1,"\r | \r |....... | 15% \r | \r |....... | 16% [fig-randomslope3] "] +[1,"\r | \r |........ | 18% \r | \r |........ | 19% [fig-fullrandom1] "] +[1,"\r | \r |......... | 20% \r | \r |.......... | 21% [fig-fullrandom2] "] +[1,"\r | \r |.......... | 22% \r | \r |........... | 24% [fig-fullrandom3] "] +[1,"\r | \r |........... | 25% \r | \r |............ | 26% [tbl-fullrandom4] "] +[1,"\r | \r |............ | 27% \r | \r |............. | 28% [fig-diagglmm1] "] +[1,"\r | \r |............. | 29% \r | \r |.............. | 31% [fig-diagglmm2] "] +[1,"\r | \r |.............. | 32% \r | \r |............... | 33% [fig-diagglmm3] "] +[1,"\r | \r |............... | 34% \r | \r |................ | 35% [fig-glmmvariance] "] +[1,"\r | \r |................ | 36% \r | \r |................. | 38% [unnamed-chunk-16] "] +[1,"\r | \r |................. | 39% \r | \r |.................. | 40% [unnamed-chunk-17] "] +[1,"\r | \r |................... | 41% \r | \r |................... | 42% [unnamed-chunk-18] "] +[1,"\r | \r |.................... | 44% \r | \r |.................... | 45% [unnamed-chunk-19] "] +[1,"\r | \r |..................... | 46% \r | \r |..................... | 47% [unnamed-chunk-20] "] +[1,"\r | \r |...................... | 48% \r | \r |...................... | 49% [unnamed-chunk-21] "] +[1,"\r | \r |....................... | 51% \r | \r |....................... | 52% [unnamed-chunk-22] "] +[1,"\r | \r |........................ | 53% \r | \r |........................ | 54% [fig-bottdistrib] "] +[1,"\r | \r |......................... | 55% \r | \r |......................... | 56% [unnamed-chunk-24] "] +[1,"\r | \r |.......................... | 58% \r | \r |.......................... | 59% [fig-randomconstantes1] "] +[1,"\r | \r |........................... | 60% \r | \r |............................ | 61% [unnamed-chunk-26] \r | \r |............................ | 62% \r | \r |............................. | 64% [unnamed-chunk-27] "] +[1,"\r | \r |............................. | 65% \r | \r |.............................. | 66% [fig-randomconstantes2] "] +[1,"\r | \r |.............................. | 67% \r | \r |............................... | 68% [unnamed-chunk-29] "] +[1,"\r | \r |............................... | 69% \r | \r |................................ | 71% [unnamed-chunk-30] "] +[1,"\r | \r |................................ | 72% \r | \r |................................. | 73% [unnamed-chunk-31] "] +[1,"\r | \r |................................. | 74% \r | \r |.................................. | 75% [unnamed-chunk-32] "] +[1,"\r | \r |.................................. | 76% \r | \r |................................... | 78% [unnamed-chunk-33] \r | \r |................................... | 79% \r | \r |.................................... | 80% [fig-glmmvarboot] "] +[1,"\r | \r |..................................... | 81% \r | \r |..................................... | 82% [unnamed-chunk-35] "] +[1,"\r | \r |...................................... | 84% \r | \r |...................................... | 85% [fig-randomconstantes2b]"] +[1,"\r | \r |....................................... | 86% \r | \r |....................................... | 87% [unnamed-chunk-37] "] +[1,"\r | \r |........................................ | 88% \r | \r |........................................ | 89% [unnamed-chunk-38] \r | \r |......................................... | 91% \r | \r |......................................... | 92% [fig-diagbinomglmm1] "] +[1,"\r | \r |.......................................... | 93% \r | \r |.......................................... | 94% [fig-diagbinomglmm2] "] +[1,"\r | \r |........................................... | 95% \r | \r |........................................... | 96% [iagbinomglmm3] "] +[1,"\r | \r |............................................ | 98% \r | \r |............................................ | 99% [quizGLMM] "] +[1,"\r | \r |.............................................| 100% \r \r\noutput file: 09-GLMM.knit.md\r\n\r\n"] +[1,"\r[12/17] 10-Multiniveau.qmd\n"] +[1,"\r\n\r\nprocessing file: 10-Multiniveau.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r |.. | 3% \r | \r |... | 6% [tbl-Multi] "] +[1,"\r | \r |..... | 10% \r | \r |....... | 13% [tbl-ModeleVide] "] +[1,"\r | \r |........ | 16% \r | \r |.......... | 19% [tbl-Modele2] "] +[1,"\r | \r |............ | 23% \r | \r |............. | 26% [tbl-Modele2b] "] +[1,"\r | \r |............... | 29% \r | \r |................ | 32% [tbl-Modele3] "] +[1,"\r | \r |.................. | 35% \r | \r |.................... | 39% [tbl-Modele4] "] +[1,"\r | \r |..................... | 42% \r | \r |....................... | 45% [unnamed-chunk-7] "] +[1,"\r | \r |......................... | 48% \r | \r |.......................... | 52% [unnamed-chunk-8] "] +[1,"\r | \r |............................ | 55% \r | \r |.............................. | 58% [unnamed-chunk-9] "] +[1,"\r | \r |............................... | 61% \r | \r |................................. | 65% [unnamed-chunk-10]"] +[1,"\r | \r |................................... | 68% \r | \r |.................................... | 71% [unnamed-chunk-11]"] +[1,"\r | \r |...................................... | 74% \r | \r |....................................... | 77% [unnamed-chunk-12]"] +[1,"\r | \r |......................................... | 81% \r | \r |........................................... | 84% [unnamed-chunk-13]"] +[1,"\r | \r |............................................ | 87% \r | \r |.............................................. | 90% [unnamed-chunk-14]"] +[1,"\r | \r |................................................ | 94% \r | \r |................................................. | 97% [quizChapitre10] "] +[1,"\r | \r |...................................................| 100% \r \r\noutput file: 10-Multiniveau.knit.md\r\n\r\n"] +[1,"\r[13/17] 11-GAM.qmd\n"] +[1,"\r\n\r\nprocessing file: 11-GAM.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r |. | 1% \r | \r |. | 2% [fig-gam2] "] +[1,"\r | \r |.. | 4% \r | \r |.. | 5% [fig-gam3] "] +[1,"\r | \r |... | 6% \r | \r |... | 7% [fig-gam4] "] +[1,"\r | \r |.... | 9% \r | \r |.... | 10% [fig-gam5] "] +[1,"\r | \r |..... | 11% \r | \r |...... | 12% [fig-gam6] "] +[1,"\r | \r |...... | 14% \r | \r |....... | 15% [fig-gam7] "] +[1,"\r | \r |....... | 16% \r | \r |........ | 17% [fig-gam8] "] +[1,"\r | \r |........ | 19% \r | \r |......... | 20% [fig-gam9] "] +[1,"\r | \r |......... | 21% \r | \r |.......... | 22% [fig-gam10] "] +[1,"\r | \r |........... | 23% \r | \r |........... | 25% [fig-gam11] "] +[1,"\r | \r |............ | 26% \r | \r |............ | 27% [fig-gam12] "] +[1,"\r | \r |............. | 28% \r | \r |............. | 30% [tbl-exemplesplines] "] +[1,"\r | \r |.............. | 31% \r | \r |.............. | 32% [fig-gam13] "] +[1,"\r | \r |............... | 33% \r | \r |................ | 35% [fig-gam14] "] +[1,"\r | \r |................ | 36% \r | \r |................. | 37% [fig-gam15] "] +[1,"\r | \r |................. | 38% \r | \r |.................. | 40% [unnamed-chunk-16] "] +[1,"\r | \r |.................. | 41% \r | \r |................... | 42% [unnamed-chunk-17] "] +[1,"\r | \r |................... | 43% \r | \r |.................... | 44% [unnamed-chunk-18] "] +[1,"\r | \r |..................... | 46% \r | \r |..................... | 47% [unnamed-chunk-19] \r | \r |...................... | 48% \r | \r |...................... | 49% [fig-gam16] "] +[1,"\r | \r |....................... | 51% \r | \r |....................... | 52% [unnamed-chunk-21] "] +[1,"\r | \r |........................ | 53% \r | \r |........................ | 54% [unnamed-chunk-22] "] +[1,"\r | \r |......................... | 56% \r | \r |.......................... | 57% [unnamed-chunk-23] \r | \r |.......................... | 58% \r | \r |........................... | 59% [unnamed-chunk-24] \r | \r |........................... | 60% \r | \r |............................ | 62% [unnamed-chunk-25] "] +[1,"\r | \r |............................ | 63% \r | \r |............................. | 64% [fig-gam17] "] +[1,"\r | \r |............................. | 65% \r | \r |.............................. | 67% [unnamed-chunk-27] "] +[1,"\r | \r |............................... | 68% \r | \r |............................... | 69% [unnamed-chunk-28] "] +[1,"\r | \r |................................ | 70% \r | \r |................................ | 72% [fig-randomconstGAM] "] +[1,"\r | \r |................................. | 73% \r | \r |................................. | 74% [unnamed-chunk-30] \r | \r |.................................. | 75% \r | \r |.................................. | 77% [unnamed-chunk-31] "] +[1,"\r | \r |................................... | 78% \r | \r |.................................... | 79% [fig-randomconstGAM2] "] +[1,"\r | \r |.................................... | 80% \r | \r |..................................... | 81% [fig-randomconstGAM3] "] +[1,"\r | \r |..................................... | 83% \r | \r |...................................... | 84% [unnamed-chunk-34] "] +[1,"\r | \r |...................................... | 85% \r | \r |....................................... | 86% [unnamed-chunk-35] "] +[1,"\r | \r |....................................... | 88% "] +[1,"\r | \r |........................................ | 89% [fig-randomconstcoefGAM]"] +[1,"\r | \r |......................................... | 90% \r | \r |......................................... | 91% [unnamed-chunk-37] "] +[1,"\r | \r |.......................................... | 93% \r | \r |.......................................... | 94% [unnamed-chunk-38] "] +[1,"\r | \r |........................................... | 95% \r | \r |........................................... | 96% [fig-corrrandom] "] +[1,"\r | \r |............................................ | 98% \r | \r |............................................ | 99% [quizGAM] "] +[1,"\r | \r |.............................................| 100% \r \r\noutput file: 11-GAM.knit.md\r\n\r\n"] +[1,"\r[14/17] 12-AnalysesFactorielles.qmd\n"] +[1,"\r\n\r\nprocessing file: 12-AnalysesFactorielles.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r | | 1% [tbl-typesanalysesfactorielles]\r | \r |. | 2% \r | \r |. | 3% [tbl-distanceACPindi] "] +[1," \r | \r |. | 4% [unnamed-chunk-3] "] +[1,"\r | \r |.. | 4% \r | \r |.. | 5% [tbl-dataacp] "] +[1,"\r | \r |.. | 6% [tbl-dataacpValeurPropres] "] +[1,"\r | \r |... | 7% \r | \r |... | 8% [fig-acpgraphvp] "] +[1," \r | \r |... | 9% [tbl-dataacpCoordVars] "] +[1,"\r | \r |.... | 9% \r | \r |.... | 10% [tbl-dataacpMatriceCorr] "] +[1,"\r | \r |.... | 11% [fig-acpgraphvarscoords] "] +[1,"\r | \r |..... | 12% \r | \r |..... | 13% [fig-acp1erplanfactVars] "] +[1," \r | \r |..... | 14% [fig-acp1erplanfactIndiv] "] +[1," \r | \r |...... | 15% [fig-acpcartoindiv] "] +[1,"\r | \r |...... | 16% [unnamed-chunk-13] "] +[1,"\r | \r |...... | 17% \r | \r |....... | 18% [unnamed-chunk-14] "] +[1," \r | \r |....... | 19% [unnamed-chunk-15] "] +[1," \r | \r |........ | 20% [fig-factoextra1] "] +[1,"\r | \r |........ | 21% [unnamed-chunk-17] "] +[1,"\r | \r |........ | 22% \r | \r |......... | 23% [fig-factoextra2] "] +[1," \r | \r |......... | 24% [fig-factoextra3] "] +[1,"\r | \r |......... | 25% \r | \r |.......... | 25% [fig-factoextra4] "] +[1,"\r | \r |.......... | 26% [unnamed-chunk-21] \r | \r |.......... | 27% \r | \r |........... | 28% [fig-factoextra5] "] +[1," \r | \r |........... | 29% [fig-factoextra6] "] +[1,"\r | \r |........... | 30% [unnamed-chunk-24] \r | \r |............ | 31% [fig-acpmesgraphs1] "] +[1,"\r | \r |............ | 32% \r | \r |............ | 33% [unnamed-chunk-26] \r | \r |............. | 33% \r | \r |............. | 34% [fig-acpmesgraphs2] "] +[1,"\r | \r |............. | 35% [fig-acpmesgraphs5] "] +[1,"\r | \r |.............. | 36% [fig-acpmesgraphs6] "] +[1,"\r | \r |.............. | 37% \r | \r |.............. | 38% [tbl-encadreAFCACP1] "] +[1,"\r | \r |............... | 38% \r | \r |............... | 39% [tbl-encadreAFCACP2] "] +[1,"\r | \r |............... | 40% [tbl-afcdataex1] "] +[1,"\r | \r |................ | 41% \r | \r |................ | 42% [tbl-afcProfilsLignesCols] \r | \r |................ | 43% [tbl-afcdataex2] "] +[1," \r | \r |................. | 44% [tbl-MatriceDistKhi] "] +[1,"\r | \r |................. | 45% [tbl-dataAfc] "] +[1,"\r | \r |................. | 46% \r | \r |.................. | 47% [fig-cartovarAFC] "] +[1," \r | \r |.................. | 48% [tbl-dataafckhi2] "] +[1," \r | \r |................... | 49% [tbl-dataafcValeurPropres] "] +[1,"\r | \r |................... | 50% [fig-afcGraphVP] "] +[1,"\r | \r |................... | 51% \r | \r |.................... | 52% [tbl-dataafcCoordVars2] "] +[1," \r | \r |.................... | 53% [tbl-dataafcCoordVars] "] +[1," \r | \r |..................... | 54% [fig-afc1erplanfactVars] "] +[1,"\r | \r |..................... | 55% [fig-afc1erplanfactInds2] "] +[1,"\r | \r |..................... | 56% \r | \r |...................... | 57% [fig-afcAjoutModalites] "] +[1," \r | \r |...................... | 58% [calculAFC] "] +[1," \r | \r |...................... | 59% [fig-factoextraAFC1] "] +[1,"\r | \r |....................... | 60% [fig-acp1erplanfactVars2a] "] +[1,"\r | \r |....................... | 61% \r | \r |....................... | 62% [fig-afc1erplanfactVars2b] "] +[1,"\r | \r |........................ | 62% \r | \r |........................ | 63% [fig-afcAjoutModalites2] "] +[1,"\r | \r |........................ | 64% [fig-afc1erplanfactInds2B] "] +[1,"\r | \r |......................... | 65% [tbl-ACM1] \r | \r |......................... | 66% \r | \r |......................... | 67% [tbl-ACM2] "] +[1,"\r | \r |.......................... | 67% \r | \r |.......................... | 68% [tbl-ACM3] "] +[1,"\r | \r |.......................... | 69% [tbl-dataACM] "] +[1,"\r | \r |........................... | 70% [tbl-ACMValeursPropresTab] "] +[1,"\r | \r |........................... | 71% \r | \r |........................... | 72% [fig-ACMValeursPropresFig] "] +[1," \r | \r |............................ | 73% [tbl-ACMValeursCoordTab] "] +[1,"\r | \r |............................ | 74% [fig-ACMValeursCoordFig1] "] +[1,"\r | \r |............................ | 75% \r | \r |............................. | 75% [fig-ACMValeursCoordFig2] "] +[1,"\r | \r |............................. | 76% \r | \r |............................. | 77% [fig-ACMValeursPlanFacto1] "] +[1," \r | \r |.............................. | 78% [fig-ACMValeursCoordFig3] "] +[1,"\r | \r |.............................. | 79% [tbl-ACMValeursCoordSuppl] "] +[1,"\r | \r |.............................. | 80% \r | \r |............................... | 81% [fig-ACMValeursPlanFactoSupp1] "] +[1," \r | \r |............................... | 82% [fig-ACMordinaleTrajectoire] "] +[1," \r | \r |................................ | 83% [fig-ACMPlanFacto12Ind1] "] +[1,"\r | \r |................................ | 84% [fig-ACMPlanFacto12Ind2] "] +[1,"\r | \r |................................ | 85% \r | \r |................................. | 86% [ACMCodePartie1VPa] "] +[1," \r | \r |................................. | 87% [fig-ACMCodePartie1VPb] "] +[1," \r | \r |................................. | 88% [fig-ACMCodePartie1VPc] "] +[1,"\r | \r |.................................. | 89% [ACMCodePartie2a] \r | \r |.................................. | 90% \r | \r |.................................. | 91% [unnamed-chunk-72] "] +[1,"\r | \r |................................... | 91% \r | \r |................................... | 92% [fig-ACMMiseEnOeuvreVars1] "] +[1," \r | \r |................................... | 93% [fig-ACMMiseEnOeuvreVars2] "] +[1,"\r | \r |.................................... | 94% [fig-ACMMiseEnOeuvreVars3] "] +[1,"\r | \r |.................................... | 95% \r | \r |.................................... | 96% [fig-ACMMiseEnOeuvreVars4] "] +[1,"\r | \r |..................................... | 96% \r | \r |..................................... | 97% [fig-ACMPlanFactoInd1Facto] "] +[1," \r | \r |..................................... | 98% [fig-ACMPlanFactoInd2Facto] "] +[1,"\r | \r |......................................| 99% [quizChapitre12] "] +[1,"\r | \r |......................................| 100% \r \r\noutput file: 12-AnalysesFactorielles.knit.md\r\n\r\n"] +[1,"Messages d'avis :\r\n1: ggrepel: 8 unlabeled data points (too many overlaps). Consider increasing max.overlaps \r\n2: ggrepel: 8 unlabeled data points (too many overlaps). Consider increasing max.overlaps \r\n"] +[1,"WARNING: Warning: diff of engine output timed out. No source lines will be available.\n"] +[1,"\r[15/17] 13-MethodeClassification.qmd\n"] +[1,"\r\n\r\nprocessing file: 13-MethodeClassification.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r | | 1% \r | \r |. | 2% [fig-dist0] "] +[1,"\r | \r |. | 3% \r | \r |.. | 4% [fig-dist1] "] +[1," \r | \r |.. | 5% [fig-impactTransform] "] +[1,"\r | \r |... | 6% \r | \r |... | 7% [fig-dist2] "] +[1,"\r | \r |.... | 8% \r | \r |.... | 9% [fig-dist3] "] +[1,"\r | \r |..... | 10% \r | \r |..... | 11% [tbl-tabdist3] \r | \r |..... | 12% \r | \r |...... | 12% [tbl-dist4] "] +[1,"\r | \r |...... | 13% \r | \r |....... | 14% [tbl-dist5] "] +[1,"\r | \r |....... | 15% \r | \r |....... | 16% [fig-dist6] "] +[1,"\r | \r |........ | 17% \r | \r |........ | 18% [fig-dist7] "] +[1,"\r | \r |......... | 19% [fig-tablvsmat] "] +[1,"\r | \r |.......... | 20% \r | \r |.......... | 21% [fig-kmeans2] "] +[1,"\r | \r |.......... | 22% \r | \r |........... | 23% [fig-kmeans3] "] +[1,"\r | \r |........... | 24% \r | \r |............ | 25% [fig-kmeans4] "] +[1,"\r | \r |............ | 26% \r | \r |............ | 27% [tbl-exampleHclust1DF]"] +[1,"\r | \r |............. | 27% \r | \r |............. | 28% [exampleHclust1] \r | \r |.............. | 29% \r | \r |.............. | 30% [exampleHclust2] "] +[1,"\r | \r |............... | 31% \r | \r |............... | 32% [exampleHclust3] \r | \r |............... | 33% \r | \r |................ | 34% [fig-exampleHclust4] "] +[1,"\r | \r |................ | 35% \r | \r |................. | 35% [exampleHclust5] "] +[1,"\r | \r |................. | 36% \r | \r |................. | 37% [exampleHclust6] "] +[1,"\r | \r |.................. | 38% \r | \r |.................. | 39% [tbl-exampleHclust7] "] +[1,"\r | \r |................... | 40% \r | \r |................... | 41% [fig-exampleHclust8] "] +[1,"\r | \r |.................... | 42% [exampleHclust9] "] +[1,"\r | \r |.................... | 43% \r | \r |..................... | 44% [tbl-exampleHclust10] "] +[1,"\r | \r |..................... | 45% \r | \r |...................... | 46% [unnamed-chunk-26] "] +[1,"\r | \r |...................... | 47% \r | \r |...................... | 48% [unnamed-chunk-27] "] +[1,"\r | \r |....................... | 49% \r | \r |....................... | 50% [fig-kmeansA2] \r | \r |........................ | 50% \r | \r |........................ | 51% [tbl-datageocmeans] "] +[1,"\r | \r |......................... | 52% \r | \r |......................... | 53% [kmeansB] "] +[1,"\r | \r |......................... | 54% \r | \r |.......................... | 55% [fig-kmeansC] "] +[1,"\r | \r |.......................... | 56% \r | \r |........................... | 57% [fig-kmeansD] "] +[1,"\r | \r |........................... | 58% [fig-kmeansE] "] +[1,"\r | \r |............................ | 59% \r | \r |............................ | 60% [kmeansF] \r | \r |............................. | 61% \r | \r |............................. | 62% [fig-kmeansG] "] +[1,"\r | \r |.............................. | 63% \r | \r |.............................. | 64% [fig-kmeansH] "] +[1,"\r | \r |.............................. | 65% \r | \r |............................... | 65% [fig-kmeansI] "] +[1,"\r | \r |............................... | 66% \r | \r |................................ | 67% [kmeansJ] "] +[1,"\r | \r |................................ | 68% \r | \r |................................ | 69% [tbl-kmeansK] "] +[1,"\r | \r |................................. | 70% \r | \r |................................. | 71% [kmeansK2] \r | \r |.................................. | 72% \r | \r |.................................. | 73% [kmeansL] "] +[1,"\r | \r |................................... | 73% \r | \r |................................... | 74% [fig-kmeansM] "] +[1,"\r | \r |................................... | 75% \r | \r |.................................... | 76% [cmeansA] "] +[1,"\r | \r |.................................... | 77% \r | \r |..................................... | 78% [fig-cmeansB] "] +[1,"\r | \r |..................................... | 79% \r | \r |..................................... | 80% [cmeansC] "] +[1,"\r | \r |...................................... | 81% [cmeansC2] "] +[1,"\r | \r |....................................... | 82% \r | \r |....................................... | 83% [fig-cmeansD] "] +[1,"\r | \r |........................................ | 84% \r | \r |........................................ | 85% [fig-cmeansE] "] +[1,"\r | \r |........................................ | 86% \r | \r |......................................... | 87% [cmeansF] "] +[1,"\r | \r |......................................... | 88% \r | \r |.......................................... | 88% [tbl-cmeansG] "] +[1,"\r | \r |.......................................... | 89% \r | \r |.......................................... | 90% [kmeansStab1] \r | \r |........................................... | 91% \r | \r |........................................... | 92% [kmeansStab2] "] +[1,"\r | \r |............................................ | 93% \r | \r |............................................ | 94% [fig-kmeansStab3] "] +[1,"\r | \r |............................................. | 95% \r | \r |............................................. | 96% [fig-kmeansStab4] "] +[1," \r | \r |.............................................. | 97% [fig-kmeansStab5] "] +[1,"\r | \r |.............................................. | 98% \r | \r |...............................................| 99% [quizChapitre13] "] +[1,"\r | \r |...............................................| 100% \r \r\noutput file: 13-MethodeClassification.knit.md\r\n\r\n"] +[1,"WARNING: Warning: diff of engine output timed out. No source lines will be available.\n"] +[1,"Registered S3 method overwritten by 'fclust':\r\n method from \r\n print.fclust e1071\r\n"] +[1,"\r[16/17] 14-Annexes.qmd\n"] +[1,"\r\n\r\nprocessing file: 14-Annexes.qmd\r\n"] +[1,"\r | \r | | 0%\r | \r |.. | 5% \r | \r |..... | 11% [unnamed-chunk-1] "] +[1,"\r | \r |....... | 16% \r | \r |.......... | 21% [tbl-tableCritiqueKhi2]"] +[1,"\r | \r |............ | 26% \r | \r |............... | 32% [unnamed-chunk-3] "] +[1,"\r | \r |................. | 37% \r | \r |................... | 42% [tbl-CritiqueF1] \r | \r |...................... | 47% \r | \r |........................ | 53% [tbl-CritiqueF2] "] +[1,"\r | \r |........................... | 58% \r | \r |............................. | 63% [tbl-CritiqueF3] \r | \r |............................... | 68% \r | \r |.................................. | 74% [unnamed-chunk-7] "] +[1,"\r | \r |.................................... | 79% \r | \r |....................................... | 84% [tbl-tableCritiqueT] \r | \r |......................................... | 89% \r | \r |............................................ | 95% [unnamed-chunk-9] "] +[1,"\r | \r |..............................................| 100% \r \r\noutput file: 14-Annexes.knit.md\r\n\r\n"] +[1,"\r[17/17] references.qmd\n"] +[1,"\n"] +[1,"ERROR: NotFound: Le fichier spécifié est introuvable. (os error 2), rename 'C:\\Users\\appariciop\\OneDrive - USherbrooke\\Articles Publies ne pas supprimer\\_Livres\\BolR_MethodesQuantitatives\\10-Multiniveau.html' -> 'C:\\Users\\appariciop\\OneDrive - USherbrooke\\Articles Publies ne pas supprimer\\_Livres\\BolR_MethodesQuantitatives\\docs\\10-Multiniveau.html'\n\nNotFound: Le fichier spécifié est introuvable. (os error 2), rename 'C:\\Users\\appariciop\\OneDrive - USherbrooke\\Articles Publies ne pas supprimer\\_Livres\\BolR_MethodesQuantitatives\\10-Multiniveau.html' -> 'C:\\Users\\appariciop\\OneDrive - USherbrooke\\Articles Publies ne pas supprimer\\_Livres\\BolR_MethodesQuantitatives\\docs\\10-Multiniveau.html'\n at Object.renameSync (deno:runtime/js/30_fs.js:175:9)\n at renderProject (file:///C:/PROGRA~1/RStudio/RESOUR~1/app/bin/quarto/bin/quarto.js:86829:22)\n at async serveProject (file:///C:/PROGRA~1/RStudio/RESOUR~1/app/bin/quarto/bin/quarto.js:103190:26)\n at async Command.fn (file:///C:/PROGRA~1/RStudio/RESOUR~1/app/bin/quarto/bin/quarto.js:103746:13)\n at async Command.execute (file:///C:/PROGRA~1/RStudio/RESOUR~1/app/bin/quarto/bin/quarto.js:8437:13)\n at async quarto (file:///C:/PROGRA~1/RStudio/RESOUR~1/app/bin/quarto/bin/quarto.js:127539:5)\n at async file:///C:/PROGRA~1/RStudio/RESOUR~1/app/bin/quarto/bin/quarto.js:127557:9\n"] diff --git a/.Rproj.user/32A8B38A/pcs/files-pane.pper b/.Rproj.user/32A8B38A/pcs/files-pane.pper new file mode 100644 index 0000000..e49bdb8 --- /dev/null +++ b/.Rproj.user/32A8B38A/pcs/files-pane.pper @@ -0,0 +1,9 @@ +{ + "sortOrder": [ + { + "columnIndex": 2, + "ascending": true + } + ], + "path": "C:/Users/appariciop/OneDrive - USherbrooke/Articles Publies ne pas supprimer/_Livres/BolR_MethodesQuantitatives" +} \ No newline at end of file diff --git a/.Rproj.user/32A8B38A/pcs/source-pane.pper b/.Rproj.user/32A8B38A/pcs/source-pane.pper new file mode 100644 index 0000000..902cc6f --- /dev/null +++ b/.Rproj.user/32A8B38A/pcs/source-pane.pper @@ -0,0 +1,3 @@ +{ + "activeTab": 0 +} \ No newline at end of file diff --git a/.Rproj.user/32A8B38A/pcs/windowlayoutstate.pper b/.Rproj.user/32A8B38A/pcs/windowlayoutstate.pper new file mode 100644 index 0000000..050c7e5 --- /dev/null +++ b/.Rproj.user/32A8B38A/pcs/windowlayoutstate.pper @@ -0,0 +1,14 @@ +{ + "left": { + "splitterpos": 439, + "topwindowstate": "NORMAL", + "panelheight": 1061, + "windowheight": 1098 + }, + "right": { + "splitterpos": 658, + "topwindowstate": "NORMAL", + "panelheight": 1061, + "windowheight": 1098 + } +} \ No newline at end of file diff --git a/.Rproj.user/32A8B38A/pcs/workbench-pane.pper b/.Rproj.user/32A8B38A/pcs/workbench-pane.pper new file mode 100644 index 0000000..ab5e950 --- /dev/null +++ b/.Rproj.user/32A8B38A/pcs/workbench-pane.pper @@ -0,0 +1,5 @@ +{ + "TabSet1": 3, + "TabSet2": 0, + "TabZoom": {} +} \ No newline at end of file diff --git a/.Rproj.user/32A8B38A/sources/prop/765DDA64 b/.Rproj.user/32A8B38A/sources/prop/765DDA64 new file mode 100644 index 0000000..9d799bf --- /dev/null +++ b/.Rproj.user/32A8B38A/sources/prop/765DDA64 @@ -0,0 +1,6 @@ +{ + "source_window_id": "", + "Source": "Source", + "cursorPosition": "2,173", + "scrollLine": "0" +} \ No newline at end of file diff --git a/.Rproj.user/32A8B38A/sources/prop/INDEX b/.Rproj.user/32A8B38A/sources/prop/INDEX new file mode 100644 index 0000000..b013e98 --- /dev/null +++ b/.Rproj.user/32A8B38A/sources/prop/INDEX @@ -0,0 +1 @@ +C%3A%2FUsers%2Fappariciop%2FOneDrive%20-%20USherbrooke%2FArticles%20Publies%20ne%20pas%20supprimer%2F_Livres%2FBolR_MethodesQuantitatives%2F01-priseenmainR.qmd="765DDA64" diff --git a/.Rproj.user/32A8B38A/sources/session-ce163101/8129FB0C b/.Rproj.user/32A8B38A/sources/session-ce163101/8129FB0C new file mode 100644 index 0000000..9f2e2ee --- /dev/null +++ b/.Rproj.user/32A8B38A/sources/session-ce163101/8129FB0C @@ -0,0 +1,26 @@ +{ + "id": "8129FB0C", + "path": "C:/Users/appariciop/OneDrive - USherbrooke/Articles Publies ne pas supprimer/_Livres/BolR_MethodesQuantitatives/01-priseenmainR.qmd", + "project_path": "01-priseenmainR.qmd", + "type": "quarto_markdown", + "hash": "3311231725", + "contents": "", + "dirty": false, + "created": 1720219020882.0, + "source_on_save": false, + "relative_order": 1, + "properties": { + "source_window_id": "", + "Source": "Source", + "cursorPosition": "2,173", + "scrollLine": "0" + }, + "folds": "", + "lastKnownWriteTime": 1720219104, + "encoding": "UTF-8", + "collab_server": "", + "source_window": "", + "last_content_update": 1720219104059, + "read_only": false, + "read_only_alternatives": [] +} \ No newline at end of file diff --git a/.Rproj.user/32A8B38A/sources/session-ce163101/8129FB0C-contents b/.Rproj.user/32A8B38A/sources/session-ce163101/8129FB0C-contents new file mode 100644 index 0000000..37afc6c --- /dev/null +++ b/.Rproj.user/32A8B38A/sources/session-ce163101/8129FB0C-contents @@ -0,0 +1,1947 @@ +# Prise en main de R {#sec-chap01} + +Dans ce chapitre, nous revenons brièvement sur l’histoire de R et la philosophie qui entoure le logiciel. Nous donnons quelques conseils pour son installation et la mise en place d’un environnement de développement. Nous présentons les principaux objets qui sous-tendent le travail effectué avec R (*DataFrame*, vecteur, matrice, etc.) et comment les manipuler avec des exemples appliqués. Si vous maîtrisez déjà R, nullement besoin de lire ce chapitre! + +::: bloc_package +::: bloc_package-header +::: bloc_package-icon +::: +**Liste des *packages* utilisés dans ce chapitre** +::: +::: bloc_package-body +* Pour importer des fichiers externes : + - `foreign` pour entre autres les fichiers *dbase* et ceux des logiciels SPSS et Stata. + - `sas7bdat` pour les fichiers du logiciel SAS. + - `xlsx` pour les fichiers Excel. +* Pour manipuler des chaînes de caractères et des dates : + - `stringr` pour les chaînes de caractères. + - `lubridate` pour les dates. +* Pour manipuler des données : + - `dplyr` du `tidyverse` propose une grammaire pour manipuler et structurer des données. +::: +::: + + +## Histoire et philosophie de R{#sec-011} + +R est à la fois un langage de programmation et un logiciel libre (sous la licence publique générale GNU) dédié à l'analyse statistique et soutenu par une fondation : _R Foundation for Statistical Computing_. Il est principalement écrit en C et en Fortran, deux langages de programmation de « bas niveau », proches du langage machine. À l'inverse, R est un langage de « haut niveau », car plus proche du langage humain. + + +R a été créé par Ross Ihaka et Robert Gentleman à l'Université d'Auckland en Nouvelle-Zélande. Si vous avez un jour l'occasion de passer dans le coin, une plaque est affichée dans le département de statistique de l'université; ça mérite le détour (@fig-Plaque). Une version expérimentale a été publiée en 1996, mais la première version stable ne date que de 2000. Il s'agit donc d'un logiciel relativement récent si nous le comparons à ses concurrents SPSS (1968), SAS (1976) et Stata (1984). + + +![Lieu de pèlerinage de R](images/Chap01/plaque.jpg){#fig-Plaque width="40%" fig-align="center"} + + +R a cependant réussi à s'imposer tant dans le milieu de la recherche que dans le secteur privé. Pour s'en convaincre, il suffit de lire l'excellent article concernant la popularité des logiciels d'analyse de données tiré du site [r4stats.com](http://r4stats.com/articles/popularity){target="_blank"} (@fig-ArticlesR). + +![Nombre d'articles trouvés sur Google Scholar (source : Robert A. Muenchen)](images/Chap01/r_citations.jpg){#fig-ArticlesR width="50%" fig-align="center"} + +Les nombreux atouts de R justifient largement sa popularité sans cesse croissante : + +* R est un logiciel à code source ouvert (*open source*) et ainsi accessible à tous gratuitement. + +* Le développement du langage R est centralisé, mais la communauté peut créer et partager facilement des *packages*. Les nouvelles méthodes sont ainsi rapidement implémentées comparativement aux logiciels propriétaires. + +* R est un logiciel multiplateforme, fonctionnant sur Linux, Unix, Windows et Mac. + +* Comparativement à ses concurrents, R dispose d'excellentes solutions pour manipuler des données et réaliser des graphiques. + +* R dispose de nombreuses interfaces lui permettant de communiquer, notamment avec des systèmes de bases de données SQL et non SQL (MySQL, PostgresSQL, MongoDB, etc.), avec des systèmes de *big data* (Spark, Hadoop), avec des systèmes d'information géographique (QGIS, ArcGIS) et même avec des services en ligne comme Microsoft Azure ou Amazon AWS. + +* R est un langage de programmation à part entière, ce qui lui donne plus de flexibilité que ses concurrents commerciaux (SPSS, SAS, STATA). Avec R, vous pouvez accomplir de nombreuses tâches : monter un site web, créer un robot collectant des données en ligne, combiner des fichiers PDF, composer des diapositives pour une présentation ou même éditer un livre (comme celui-ci), mais aussi, et surtout, réaliser des analyses statistiques. + +Un des principaux attraits de R est la quantité astronomique de *packages* actuellement disponibles. **Un *package* est un ensemble de nouvelles fonctionnalités développées par des personnes utilisatrices de R et mises à disposition de l'ensemble de la communauté**. Par exemple, le *package* `ggplot2` est dédié à la réalisation de graphiques; les *packages* `data.table` et `dplyr` permettent de manipuler des tableaux de données; le *package* `car` offre de nombreux outils pour faciliter l'analyse de modèles de régressions, etc. Ce partage de *packages* rend accessible à tous des méthodes d'analyses complexes et récentes et favorise grandement la reproductibilité de la recherche. Cependant, ce fonctionnement implique quelques désavantages : + +* Il existe généralement plusieurs *packages* pour effectuer le même type d'analyse, ce qui peut devenir une source de confusion. + +* Certains *packages* cessent d'être mis à jour au fil des années, ce qui nécessite de trouver des solutions de rechange (et ainsi apprendre la syntaxe de nouveaux *packages*). + +* Il est impératif de s'assurer de la fiabilité des *packages* que vous souhaitez utiliser, car n'importe qui peut proposer un *package*. + +Il nous semble important de relativiser d'emblée la portée du dernier point. Il est rarement nécessaire de lire et d'analyser le code source d'un *package* pour s'assurer de sa fiabilité. Nous ne sommes pas des spécialistes de tous les sujets et il peut être extrêmement ardu de comprendre la logique d'un code écrit par une autre personne. Nous vous recommandons donc de privilégier l'utilisation de *packages* qui : + +* ont fait l'objet d'une publication dans une revue à comité de lecture ou qui ont déjà été cités dans des études ayant fait l'objet d'une publication revue par les pairs; + +* font partie de projets comme [ROpensci](https://ropensci.org/){target="_blank"} prônant la vérification par les pairs ou subventionnés par des organisations comme [R Consortium](https://www.r-consortium.org/){target="_blank"}; + +* sont disponibles sur l'un des deux principaux répertoires de *packages* R, soit [CRAN](https://cran.r-project.org/){target="_blank"} et [Bioconductor](https://www.bioconductor.org/){target="_blank"}. + +Toujours pour nuancer notre propos, il convient de distinguer *package* de *package*! Certains d'entre eux sont des ensembles très complexes de fonctions permettant de réaliser des analyses poussées alors que d'autres sont des projets plus modestes dont l'objectif principal est de simplifier le travail des personnes utilisant R. Ces derniers ressemblent à de petites boîtes à outils et font généralement moins l'objet d'une vérification intensive. + +Pour conclure cette section, l'illustration partagée sur Twitter par Darren L Dahly résume avec humour la force du logiciel R et de sa communauté +(@fig-fig03) : R apparaît clairement comme une communauté hétéroclite, mais diversifiée et adaptable. + + +![Métaphore sur les langages et programmes d'analyse statistique](images/Chap01/softwares_and_cars.jpeg){#fig-fig03 width="60%" fig-align="center"} + + +Dans ce livre, nous détaillons les *packages* utilisés dans chaque section avec un encadré spécifique. + + +::: bloc_package +::: bloc_package-header +::: bloc_package-icon +::: + +**Bloc *packages*** +::: + +::: bloc_package-body +Habituellement localisé au début d'un chapitre, il comprend la liste des *packages* R utilisés pour un chapitre. +::: +::: + + +## Environnement de travail{#sec-012} + +Dans cette section, nous vous proposons une visite de l'environnement de travail de R. + +### Installation de R {#sec-0121} + +La première étape pour travailler avec R est bien sûr de l'installer. Pour cela, il suffit de visiter le site web de [CRAN](https://cran.r-project.org/){target="_blank"} et de télécharger la dernière version de R en fonction de votre système d'exploitation : Windows, Linux ou Mac. Une fois installé, si vous démarrez R immédiatement, vous aurez accès à une console, plutôt rudimentaire, attendant sagement vos instructions (@fig-fig05). + +![Console de base de R](images/Chap01/r_console.jpeg){#fig-fig05 width="85%" fig-align="center"} + +Notez que vous pouvez aussi télécharger des versions plus anciennes de R en allant sur ce [lien](https://cran.r-project.org/bin/windows/base/old/){target="_blank"}. Cela peut être intéressant lorsque vous voulez reproduire des résultats d'une autre étude ou que certains *packages* ne sont plus disponibles dans les nouvelles versions. + +### Environnement RStudio{#sec-0122} + +Rares sont les adeptes de R qui préfèrent travailler directement avec la console classique. Nous vous recommandons vivement d'utiliser RStudio, un environnement de développement (*IDE*) dédié à R offrant une intégration très intéressante d'une console, d'un éditeur de texte, d'une fenêtre de visualisation des données et d'une autre pour les graphiques, d'un accès à la documentation, etc. En d'autres termes, si R est un vélo minimaliste, RStudio permet d'y rajouter des freins, des vitesses, un porte-bagages, des garde-boues et une selle confortable. Vous pouvez [télécharger](https://rstudio.com/products/rstudio/download){target="_blank"} et installer RStudio sur Windows, Linux et Mac. La version de base est gratuite, mais l'entreprise qui développe ce logiciel propose aussi des versions commerciales du logiciel qui assurent essentiellement une assistance technique. Il existe d'autres environnements de développement pour travailler avec R (Visual Studio Code, Jupyter, Tinn-R, Radiant, RIDE, etc.), mais RStudio offre à ce jour la meilleure option en termes de facilité d'installation, de prise en main et de fonctionnalités proposées (voir l'interface de RStudio à la @fig-fig06). + + +![Environnement de base de RStudio](images/Chap01/r_studio_01.jpeg){#fig-fig06 width="85%" fig-align="center"} + +Avant d'aller plus loin, notez que : + +* La console actuellement ouverte dans RStudio vous informe de la version de R que vous utilisez. Vous pouvez en effet avoir plusieurs versions de R installées sur votre ordinateur et passer de l'une à l'autre avec RStudio. Pour cela, naviguez dans l'onglet *Tools/Global Options* et dans le volet *General*, puis sélectionnez la version de R que vous souhaitez utiliser. + +* L'aspect de RStudio peut être modifié en naviguant dans l'onglet *Tools/Global Options* et dans le volet *Appearance*. Nous avons une préférence pour le mode sombre avec le style *pastel on dark* (@fig-fig07), mais libre à vous de choisir le style qui vous convient. + + +![RStudio avec le style pastel on dark](images/Chap01/r_studio_02.jpeg){#fig-fig07 width="85%" fig-align="center"} + +Une fois ces détails réglés, vous pouvez ouvrir votre première feuille de code en allant dans l'onglet *File/New File/R Script*. Votre environnement est maintenant découpé en quatre fenêtres (@fig-fig08) : + +1. L'éditeur de code, vous permettant d'écrire le script que vous voulez exécuter et de garder une trace de votre travail. Ce script peut être enregistré sur votre ordinateur avec l'extension **.R**, mais ce n'est qu'un simple fichier texte. + +2. La console vous permettant d'exécuter votre code R et de voir les résultats s'afficher au fur et à mesure. + +3. La fenêtre d'environnement vous montrant les objets, les fonctions et les jeux de données actuellement disponibles dans votre session (chargés dans la mémoire vive). + +4. La fenêtre de l'aide, des graphiques et de l'explorateur de fichiers. Vous pouvez accéder ici à la documentation de R et des *packages* que vous utilisez, aux sorties graphiques que vous produisez et aux dossiers de votre environnement de travail. + + +![Fenêtres de RStudio](images/Chap01/r_studio_03.jpeg){#fig-fig08 width="85%" fig-align="center"} + +Prenons un bref exemple : tapez la syntaxe suivante dans l'éditeur de code (fenêtre 1 à la @fig-fig08) : + +```{r} +#| label: "ma_somme" +ma_somme <- 4+4 +``` + +Sélectionnez ensuite cette syntaxe (mettre en surbrillance avec la souris) et utilisez le raccourci *Ctrl+Entrée* ou cliquez sur le bouton *Run* (avec la flèche verte) pour envoyer cette syntaxe à la console qui l'exécutera immédiatement. Notez que rien ne se passe tant que le code n'est pas envoyé à la console. Il s'agit donc de deux étapes distinctes : écrire son code, puis l'envoyer à la console. Constatez également qu'un objet *ma_somme* est apparu dans votre environnement et que sa valeur est bien 8. Votre console se « souvient » de cette valeur : elle est actuellement stockée dans votre mémoire vive sous le nom de *ma_somme* (@fig-fig09). + + +![Exécuter du code dans RStudio](images/Chap01/r_studio_04.jpeg){#fig-fig09 width="85%" fig-align="center"} + +Pour conclure cette section, nous vous invitons à enregistrer votre première syntaxe R (*File/Save As*) dans un fichier **.R** que vous pouvez appeler `mon_premier_script.R` par exemple. Fermez ensuite RStudio, redémarrez-le et ouvrez (*File/Open File*) votre fichier `mon_premier_script.R`. Vous pouvez constater que votre code est toujours présent, mais que votre environnement est vide tant que vous n'exécutez pas votre syntaxe. En effet, lorsque vous fermez RStudio, l'environnement est vidé pour libérer de la mémoire vive. Cela peut poser problème lorsque certains codes sont très longs à exécuter, nous verrons donc plus tard comment enregistrer l'environnement en cours pour le recharger par la suite. + + +### Installation et chargement un *package*{#sec-0123} + +Dans la section sur la Philosophie de R, nous avons souligné la place centrale jouée par les *packages*. Notez que les termes *paquet* et plus rarement *librairie* sont parfois utilisés en français. Voyons ensemble comment installer un *package*, par exemple celui intitulé `lubridate`, qui nous permettra plus tard de manipuler des données temporelles. + +#### Installation d'un *package* depuis *CRAN*{#sec-01231} + +Pour installer un *package*, il est nécessaire d'être connecté à Internet puisque R va accéder au répertoire de *packages* *CRAN* pour télécharger le *package* et l'installer sur votre machine. Cette opération est réalisée avec la fonction `install.packages`. + +```{r} +#| message: false +#| warning: false +#| eval: false +install.packages("lubridate") +``` + +Notez qu'une fois que le *package* est installé, il demeure disponible localement sur votre ordinateur, à moins de le désinstaller explicitement avec la fonction `remove.packages`. + +#### Installation d'un *package* depuis GitHub{#sec-01232} + +*CRAN* est le répertoire officiel des *packages* de R. Vous pouvez cependant télécharger des *packages* provenant d'autres sources. Très souvent, les *packages* sont disponibles sur le site web [GitHub](https://github.com/){target="_blank"} et nous pouvons même y trouver des versions en développement avec des fonctionnalités encore non intégrées dans la version sur *CRAN*. Reprenons le cas de `lubridate`, mais sur GitHub (il est disponible [ici](https://github.com/tidyverse/lubridate){target="_blank"}). Pour l'installer, nous devons d'abord installer un autre *package* appelé `remotes` (depuis *CRAN*). + +```{r} +#| message: false +#| warning: false +#| eval: false +install.packages("remotes") +``` + +Maintenant que nous disposons de `remotes`, nous pouvons utiliser la fonction d'installation `remotes::install_github` pour directement télécharger `lubridate` depuis GitHub. + +```{r} +#| message: false +#| warning: false +#| eval: false +remotes::install_github("tidyverse/lubridate") +``` + +#### Chargement d'un *package* {#sec-01233} + +Maintenant que `lubridate` est installé, nous pouvons le charger dans notre session actuelle de R et accéder aux fonctions qu'il propose. Pour cela, il suffit d'utiliser la fonction `library`. Conventionnellement, l'appel des *packages* se fait au tout début du script que vous rédigez. Rien ne vous empêche de le faire au fur et à mesure de votre code, mais ce dernier perd alors en lisibilité. Notez que pour chaque nouvelle session (redémarrage de R), il faut recharger les *packages* dont vous avez besoin avec la fonction `library`. + +```{r} +#| message: false +#| warning: false +library(lubridate) +``` + +Si vous obtenez un message d'erreur du type : + +`Error in library(monPackage) : aucun package nommé ‘monPackage’ n'est trouvé` + +Cela signifie que le *package* que vous tentez de charger n'est pas encore installé sur votre ordinateur. Dans ce cas, réessayer de l'installer avec la fonction `install.packages`. Si le problème persiste, vérifiez que vous n'avez pas fait une faute de frappe dans le nom du *package.* Vous pouvez également redémarrer RStudio et réessayer d'installer ce *package*. + +### Aide disponible + +Lorsque vous installez des *packages* dans R, vous téléchargez aussi leur documentation. Tous les *packages* de *CRAN* disposent d'une documentation, ce qui n'est pas forcément vrai pour ceux sur *GitHub*. Dans RStudio, vous pouvez accéder à la documentation des *packages* dans l'onglet **Packages** (@fig-fig010). Vous pouvez utiliser la barre de recherche pour retrouver rapidement un *package* installé. Si vous cliquez sur le nom du *package*, vous accédez directement à sa documentation dans cette fenêtre. + + +![Description des packages](images/Chap01/rstudio_packages.jpeg){#fig-fig010 width="45%" fig-align="center"} + +Vous pouvez également accéder à ces informations en utilisant la syntaxe suivante dans votre console : + +```{r} +#| eval: false +help(package = 'lubridate') +``` + +Souvent, vous aurez besoin d'accéder à la documentation d'une fonction spécifique d'un *package*. Affichons la documentation de la fonction `now` de `lubridate` : + +```{r} +#| eval: false +help(now, package = 'lubridate') +``` + +ou plus simplement : +```{r} +#| eval: false +?lubridate::now +``` + +Vous pouvez aussi utiliser le raccourci suivant. + +```{r} +#| eval: false +?now +``` + +Si vous ne vous souvenez plus à quel *package* la fonction appartient, lancez une recherche en utilisant un double point d'interrogation : + +```{r} +#| eval: false +??now +``` + +Vous découvrirez ainsi que la fonction `now` n'existe pas que dans `lubridate`, ce qui souligne l'importance de bien connaître les *packages* que nous installons et que nous chargeons dans notre session ! + +Maintenant que nous avons fait le tour de l'environnement de travail, nous pouvons passer aux choses sérieuses, soit les bases du langage R. + +## Bases du langage R {#sec-013} + +R est un langage de programmation. Il vous permet de communiquer avec votre ordinateur pour lui donner des tâches à accomplir. Dans cette section, nous abordons les bases du langage. Ce type de section introductive à R est présente dans tous les manuels sur R; elle est donc incontournable. À la première lecture, elle vous semblera probablement aride, et ce, d'autant plus que nous ne réalisons pas d'analyse à proprement parler. Gardez en tête que l'analyse de données requiert au préalable une phase de structuration de ces dernières, opération qui nécessite la maîtrise des notions abordées dans cette section. Nous vous recommandons une première lecture de ce chapitre pour comprendre les manipulations que vous pouvez effectuer avec R, avant de poursuivre avec de la lecture des chapitres suivants dédiés aux analyses statistiques. Vous pourrez revenir consulter cette section au besoin. Notez aussi que la maîtrise des différents objets et des différentes opérations de base de R ne s’acquiert qu'en pratiquant. Vous gagnerez cette expertise au fil de vos prochains codes R, période durant laquelle vous pourrez consulter ce chapitre tel un guide de référence des objets et des notions fondamentales de R. + + +### *Hello World*! {#sec-0131} + +Une introduction à un langage de programmation se doit de commencer par le rite de passage *Hello World*. Il s'agit d'une forme de tradition consistant à montrer aux néophytes comment afficher le message `Hello World` à l'écran avec le langage en question. + +```{r} +print("Hello World") +``` + +Bravo! Vous venez officiellement de faire votre premier pas dans R! + +### Objets et expressions {#sec-0132} + +Dans R, nous passons notre temps à manipuler des **objets** à l'aide d'**expressions**. Prenons un exemple concret : si vous tapez la syntaxe `4 + 3`, vous manipulez deux objets (4 et 3) avec une expression indiquant que vous souhaitez obtenir la somme des deux objets. + +```{r} +4 + 3 +``` + +Cette expression est correcte, R comprend vos indications et effectue le calcul. + +Il est possible d'enregistrer le résultat d'une expression et de le conserver dans un nouvel objet. On appelle cette opération : « déclarer une variable ». + +```{r} +ma_somme <- 4 + 3 +``` + +Concrètement, nous venons de demander à R d'enregistrer le résultat de `4 + 3` dans un espace spécifique de notre mémoire vive. Si vous regardez dans votre fenêtre **Environment**, vous verrez en effet qu'un objet appelé ma_somme est actuellement en mémoire et a pour valeur 7. + +Notez ici que le nom des variables ne peut être composé que de lettres, de chiffres, de points (.) et de tirets bas (_) et doit commencer par une lettre. R est sensible à la casse; en d'autres termes, les variables `Ma_somme`, `ma_sommE`, `ma_SOMME`, et `MA_SOMME` renvoient toutes à un objet différent. Attention donc aux fautes de frappe. Si vous déclarez une variable en utilisant le nom d'une variable existante, la première est écrasée par la seconde : + +```{r} +age <- 35 +age + +age <- 45 +age +``` + +Portez alors attention aux noms de variables que vous utilisez et réutilisez. Réutilisons notre objet `ma_somme` dans une nouvelle expression : + +```{r} +ma_somme2 <- ma_somme + ma_somme +``` + +Avec cette nouvelle expression, nous indiquons à R que nous souhaitons déclarer une nouvelle variable appelée `ma_somme2`, et que cette variable aura pour valeur `ma_somme + ma_somme`, soit `7 + 7`. Sans surprise, `ma_somme2` a pour valeur 14. + +Notez que la mémoire vive (l'environnement) est vidée lorsque vous fermez R. Autrement dit, R perd complètement la mémoire lorsque vous le fermez. Vous pouvez bien sûr recréer vos objets en relançant les mêmes syntaxes. C'est pourquoi vous devez conserver vos feuilles de codes et ne pas seulement travailler dans la console. La console ne garde aucune trace de votre travail. Pensez donc à bien enregistrer votre code! + +Nous verrons dans une prochaine section comment sauvegarder des objets et les recharger dans une session ultérieure de R ([section @sec-017]). Ce type d'opération est pertinent quand le temps de calcul nécessaire à la production de certains objets est très long. + +### Fonctions et arguments {#sec-0_133} + +Dans R, nous manipulons le plus souvent nos objets avec des **fonctions**. Une fonction est elle-même un objet, mais qui a la particularité de pouvoir effectuer des opérations sur d'autres objets. Par exemple, déclarons l'objet `taille` avec une valeur de 175,897 : + +```{r} +taille <- 175.897 +``` + +Nous utilisons la fonction `round`, dont l'objectif est d'arrondir un nombre avec décimales pour obtenir un nombre entier. + +```{r} +round(taille) +``` + +Pour effectuer leurs opérations, les fonctions ont généralement besoin d'**arguments**. Ici, `taille` est un argument passé à la fonction `round`. Si nous regardons la documentation de `round` avec `help(round)` (@fig-fig011), nous constatons que cette fonction prend en réalité deux arguments : *x* et *digits*. Le premier est le nombre que nous souhaitons arrondir et le second est le nombre de décimales à conserver. Nous pouvons lire dans la documentation que la valeur par défaut de *digits* est 0, ce qui explique que `round(taille)` a produit le résultat de 176. + + +![Arguments de la fonction `round`](images/Chap01/help_round.jpeg){#fig-fig011 width="35%" fig-align="center"} + +Réutilisons maintenant la fonction `round`, mais en gardant une décimale : + +```{r} +round(taille, digits = 1) +``` + +Il est aussi possible que certaines fonctions ne requièrent pas d'argument. Par exemple, la fonction `now` indique la date précise (avec l'heure) et n'a besoin d'aucun argument pour le faire : + +```{r} +now() +``` + +Par contre, si nous essayons de lancer la fonction `round` sans argument, nous obtenons une erreur : + +```{r} +#| eval: false +round() +``` + +`Erreur : 0 argument passé à 'round' qui en exige 1 ou 2` + +Le message est très clair, `round` a besoin d'au moins un argument pour fonctionner. Si, au lieu d'un nombre, nous avions donné du texte à la fonction `round`, nous aurions aussi obtenu une erreur : + +```{r} +#| eval: false +round("Hello World") +``` + +`Erreur dans round("Hello World") : argument non numérique pour une fonction mathématique` + +À nouveau le message est très explicite : nous avons passé un argument non numérique à une fonction mathématique. Lisez toujours vos messages d'erreurs : ils permettent de repérer les coquilles et de corriger votre code! + +Nous terminons cette section avec une fonction essentielle, `print`, qui permet d'afficher la valeur d'une variable. + +```{r} +print(ma_somme) +``` + + +### Principaux types de données {#sec-0134} + +Depuis le début de ce chapitre, nous avons déclaré plusieurs variables et essentiellement des données numériques. Dans R, il existe trois principaux types de données de base : + +* Les données numériques qui peuvent être des nombres entiers (appelés *integers*) ou des nombres décimaux (appelés *floats* ou *doubles*), par exemple `15` et `15.3`. + +* Les données de type texte qui sont des chaînes de caractères (appelées *strings*) et déclarées entre guillemets `"abcdefg"`. + +* Les données booléennes (*booleans*) qui peuvent n'avoir que deux valeurs : vrai (`TRUE`) ou faux (`FALSE`). + +Déclarons une variable pour chacun de ces types : + +```{r} +age <- 35 +taille <- 175.5 +adresse <- '4225 rue de la gauchetiere' +proprietaire <- TRUE +``` + +::: bloc_notes +::: bloc_notes-header +::: bloc_notes-icon +::: +**Simples ou doubles quotes?** +::: +::: bloc_notes-body +Pour déclarer des données de type texte, il est possible d'utiliser des quotes simples `'` (apostrophe) ou des quotes doubles `"` (guillemets), cela ne fait aucune différence pour R. Cependant, si la chaîne de caractères que vous créez contient une apostrophe, il est nécessaire d'utiliser des quotes doubles et inversement si votre chaîne de caractère contient des guillemets. + +```{r} +phrase1 <- "J'adore le langage R!" +phrase2 <- 'Je cite : "il est le meilleur langage de statistique".' +``` + +Si la chaîne de caractère contient des guillemets et des apostrophes, il est nécessaire d'utiliser la barre oblique inversée `\` pour indiquer à R que ces apostrophes ou ces guillemets ne doivent pas être considérés comme la fin de la chaîne de caractère. + +```{r} +phrase3 <- "Je cite : \"j'en rêve la nuit\"." +cat(phrase3) +``` + +Les barres obliques inversées ne font pas partie de la chaîne de caractère, ils sont là pour "échapper" les guillemets qui doivent rester dans la chaîne de caractère. Si une chaîne de caractère doit contenir une barre oblique inversée, alors il faut l'échapper également en utilisant une deuxième barre oblique inversée. + +```{r} +phrase4 <- "Une phrase avec une barre oblique inversée : \\" +cat(phrase4) +``` +Faites attention à la coloration syntaxique de RStudio! Elle peut vous aider à repérer facilement une chaîne de caractère qui aurait été interrompue par un guillemet ou une apostrophe mal placés. +::: +::: + +Si vous avez un doute sur le type de données stockées dans une variable, vous pouvez utiliser la fonction `typeof`. Par exemple, cela permet de repérer si des données qui sont censées être numériques sont en fait stockées sous forme de texte comme dans l'exemple ci-dessous. + +```{r} +typeof(age) +typeof(taille) + +# Ici tailletxt est définie comme une chaîne de caractère car la valeur est +# définie entre des guillemets. +tailletxt <- "175.5" +typeof(tailletxt) + +``` + + +Notez également qu'il existe des types pour représenter l'absence de données : + +* pour représenter un objet vide, nous utilisons l'objet `NULL`, + +* pour représenter une donnée manquante, nous utilisons l'objet `NA`, + +* pour représenter un texte vide, nous utilisons une chaîne de caractère de longueur 0, soit `""`. + +```{r} +age2 <- NULL +taille2 <- NA +adresse2 <- '' +``` + +### Opérateurs {#sec-0135} + +Nous avons vu que les fonctions permettent de manipuler des objets. Nous pouvons également effectuer un grand nombre d'opérations avec les opérateurs. + +#### Opérateurs mathématiques {#sec-01351} + +Les opérateurs mathématiques (@tbl-OperateurMath) permettent d'effectuer des calculs avec des données de type numérique. + +```{r} +#| label: tbl-OperateurMath +#| tbl-cap: Opérateurs mathématiques +#| echo: false +#| message: false +#| warning: false + +df <- data.frame( + Operateur = c("`+`" , "`-`" , "`*`" , "`/`", "`^`", "`**`", + "`%%`", "`%/%`"), + Description = c("Addition", 'Soustraction', 'Multiplication', + 'Division', 'Exponentiel', 'Exponentiel', + 'Reste de division', 'Division entière'), + Syntaxe = c("`4 + 4`", "`4 - 3`", "`4 * 3`", "`12 / 4`", + "`4 ^ 3`", '`4 ** 3`', "`15,5 %% 2`", + "`15,5 %/% 2`"), + Resultat = c(8,1,12,3,64,64,1.5,7)) + +knitr::kable(df, + format.args = list(decimal.mark = ',', big.mark = " "), + col.names = c("Opérateur" , "Description" , "Syntaxe" , "Résultat"), + align= c("l", "l", "l", "r") + ) +``` + +#### Opérateurs relationnels {#sec-01352} + +Les opérateurs relationnels (@tbl-OperateurRelationnels) permettent de vérifier des conditions dans R. Ils renvoient un booléen, `TRUE` si la condition est vérifiée et `FALSE` si ce n'est pas le cas. + +```{r} +#| label: tbl-OperateurRelationnels +#| tbl-cap: Opérateurs relationnels +#| echo: false +#| message: false +#| warning: false + +df <- data.frame( + Operateur = c("`==`" , "`!=`" , "`>`" , "`<`", "`>=`", "`<=`"), + Description = c("Égalité", 'Différence', 'Est supérieur ', 'Est inférieur', 'Est supérieur ou égal', 'Est inférieur ou égal'), + Syntaxe = c("`4 == 4`", "`4 != 4`", "`5 > 4`", "`5 < 4`", "`5 >= 4`", '`5 <= 4`'), + Resultat = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE)) + +knitr::kable(df, + format.args = list(decimal.mark = ',', big.mark = " "), + col.names = c("Opérateur" , "Description" , "Syntaxe" , "Résultat"), + align= c("l", "l", "l", "l")) +``` + +#### Opérateurs logiques {#sec-01353} + +Les opérateurs logiques (@tbl-tableOperateurLogi) permettent de combiner plusieurs conditions : + +* L'opérateur **ET** (`&`) permet de vérifier que deux conditions (l'une ET l'autre) sont TRUE. Si l'une des deux est FALSE, il renvoie FALSE. + +* L'opérateur **OU** (`|`) permet de vérifier que l'une des deux conditions est TRUE (l'une OU l'autre). Si les deux sont FALSE, alors il renvoie FALSE. + +* L'opérateur **NOT** (`!`) permet d'inverser une condition. Ainsi, NOT TRUE donne FALSE et NOT FALSE donne TRUE. + + +```{r} +#| label: tbl-tableOperateurLogi +#| tbl-cap: Opérateurs logiques +#| echo: false +#| message: false +#| warning: false +df <- data.frame( + Operateur = c("`&`" , "`|`" , "`!`"), + Description = c("ET", "OU", "NOT"), + Syntaxe = c("`TRUE & FALSE`", "`TRUE | FALSE`", "`! TRUE`"), + Resultat = c(FALSE, TRUE, FALSE)) + +knitr::kable(df, + format.args = list(decimal.mark = ',', big.mark = " "), + col.names = c("Opérateur" , "Description" , "Syntaxe" , "Résultat"), + align= c("l", "l", "l", "l") + ) +``` + +Prenons le temps pour un rapide exemple : + +```{r} + +A <- 4 +B <- 10 +C <- -5 + +# Produit TRUE car A est bien plus petit que B et C est bien plus petit que A +A < B & C < A + +# Produit FALSE car si A est bien plus petit que B, +# B est en revanche plus grand que c +A < B & B < C + +# Produit TRUE car la seconde condition est inversée +A < B & ! B < C + +# Produit TRUE car au moins une des deux conditions est juste +A < B | B < C + +``` + +Notez que l'opérateur **ET** est prioritaire sur l'opérateur **OU** et que les parenthèses sont prioritaires sur tous les opérateurs : + +```{r} +# Produit TRUE car nous commençons par tester A < B puis B < C ce qui donne FALSE +# On obtient ensuite +# FALSE | A > C +# Enfin, A est bien supérieur à C, donc l'une des deux conditions est vraie +A < B & B < C | A > C + +``` + +Notez qu'en arrière-plan, les opérateurs sont en réalité des fonctions déguisées. Il est donc possible de définir de nouveaux comportements pour les opérateurs. Il est par exemple possible d'additionner ou de comparer des objets spéciaux comme des dates, des géométries, des graphes, etc. + +### Structures de données {#sec-0136} + +Jusqu'à présent, nous avons utilisé des objets ne comprenant qu'une seule valeur. Or, des analyses statistiques nécessitent de travailler avec des volumes de données bien plus grands. Pour stocker des valeurs, nous travaillons avec différentes structures de données : les vecteurs, les matrices, les tableaux de données et les listes. + +#### Vecteurs {#sec-01361} + +Les vecteurs sont la brique élémentaire de R. Ils permettent de stocker une série de valeurs **du même type** dans une seule variable. Pour déclarer un vecteur, nous utilisons la fonction `c()` : + +```{r} +ages <- c(35,45,72,56,62) +tailles <- c(175.5,180.3,168.2,172.8,167.6) +adresses <- c('4225 rue de la gauchetiere', + '4223 rue de la gauchetiere', + '4221 rue de la gauchetiere', + '4219 rue de la gauchetiere', + '4217 rue de la gauchetiere') +proprietaires <- c(TRUE, TRUE, FALSE, TRUE, TRUE) +``` + +Nous venons ainsi de déclarer quatre nouvelles variables étant chacune un vecteur de longueur cinq (comprenant chacun cinq valeurs). Ces vecteurs représentent, par exemple, les réponses de plusieurs personnes à un questionnaire. + +::: bloc_attention +::: bloc_attention-header +::: bloc_attention-icon +::: +**Distinction entre un vecteur de type texte et un vecteur de type facteur** +::: + +::: bloc_attention-body +Il existe dans R une subtilité à l'origine de nombreux malentendus : la distinction entre un vecteur de type **texte** et un vecteur de type **facteur**. Dans l'exemple précédent, le vecteur *adresses* est un vecteur de type texte. Chaque nouvelle valeur ajoutée dans le vecteur peut être n'importe quelle nouvelle adresse. Déclarons un nouveau vecteur qui contient cette fois-ci la couleur des yeux de personnes ayant répondu au questionnaire. + +```{r} +couleurs_yeux <- c('marron', 'marron', 'bleu', 'bleu', 'marron', 'vert') +``` + +Contrairement aux adresses, il y a un nombre limité de couleurs que nous pouvons mettre dans ce vecteur. Il est donc intéressant de fixer les valeurs possibles du vecteur pour éviter d'en ajouter de nouvelles par erreur. Pour cela, nous devons convertir ce vecteur texte en vecteur de type facteur, ci-après nommé simplement facteur, avec la fonction `as.factor`. + +```{r} +couleurs_yeux_facteur <- as.factor(couleurs_yeux) +``` + +Notez qu'à présent, nous pouvons ajouter une nouvelle couleur dans le premier vecteur, mais pas dans le second. + +```{r} +couleurs_yeux[7] <- "rouge" +couleurs_yeux_facteur[7] <- "rouge" +``` + +Le message d'erreur nous informe que nous avons tenté d'introduire une valeur invalide dans le facteur. + +Les facteurs peuvent sembler restrictifs et, très régulièrement, nous préférons travailler avec de simples vecteurs de type texte plutôt que des facteurs. Cependant, de nombreuses fonctions d'analyse nécessitent d'utiliser des facteurs, car ils assurent une certaine cohérence dans les données. Il est donc essentiel de savoir passer du texte au facteur avec la fonction `as.factor`. À l'inverse, il est parfois nécessaire de revenir à une variable de type texte avec la fonction `as.character`. + +Notez que des vecteurs numériques peuvent aussi être convertis en facteurs : + +```{r} +tailles_facteur <- as.factor(tailles) +``` + +Cependant, si vous souhaitez reconvertir ce facteur en format numérique, il faudra passer dans un premier temps par le format texte : + +```{r} +as.numeric(tailles_facteur) +``` + +Comme vous pouvez le voir, convertir un facteur en valeur numérique renvoie des nombres entiers. Ceci est dû au fait que les valeurs dans un facteur sont recodées sous forme de nombres entiers, chaque nombre correspondant à une des valeurs originales (appelées niveaux). Si nous convertissons un facteur en valeurs numériques, nous obtenons donc ces nombres entiers. + +```{r} +as.numeric(as.character(tailles_facteur)) +``` + +Morale de l'histoire : ne confondez pas les données de type texte et de type facteur. Dans le doute, vous pouvez demander à R quel est le type d'un vecteur avec la fonction `class`. + +```{r} +class(tailles) +class(tailles_facteur) +class(couleurs_yeux) +class(couleurs_yeux_facteur) +``` +::: +::: + + +Quasiment toutes les fonctions utilisent des vecteurs. Par exemple, nous pouvons calculer la moyenne du vecteur *ages* en utilisant la fonction `mean` présente de base dans R. + +```{r} +mean(ages) +``` + +Cela démontre bien que le vecteur est la brique élémentaire de R! Toutes les variables que nous avons déclarées dans les sections précédentes sont aussi des vecteurs, mais de longueur 1. + +#### Matrices {#sec-01362} + +Il est possible de combiner des vecteurs pour former des matrices. Une matrice est un tableau en deux dimensions (colonnes et lignes) et est généralement utilisée pour représenter certaines structures de données comme des images (pixels), effectuer du calcul matriciel ou plus simplement présenter des matrices de corrélations. Vous aurez rarement à travailler directement avec des matrices, mais il est bon de savoir ce qu'elles sont. Créons deux matrices à partir de nos précédents vecteurs. + +```{r} +matrice1 <- cbind(ages, tailles) +# Afficher la matrice 1 +print(matrice1) +# Afficher les dimensions de la matrice 1 (1er chiffre : lignes; 2e chiffre : colonnes) +print(dim(matrice1)) + +matrice2 <- rbind(ages, tailles) +# Afficher la matrice 2 +print(matrice2) +# Afficher les dimensions de la matrice 2 +print(dim(matrice2)) +``` + +Comme vous pouvez le constater, la fonction `cbind` permet de concaténer des vecteurs comme s'ils étaient les colonnes d'une matrice, alors que `rbind` les combine comme s'ils étaient les lignes d'une matrice. La @fig-fig012 présente graphiquement le passage du vecteur à la matrice. + +![Du vecteur à la matrice](images/Chap01/vecteur_to_matrix.png){#fig-fig012 width="30%" fig-align="center"} + +Notez que vous pouvez transposer une matrice avec la fonction `t`. Si nous essayons maintenant de comparer la matrice 1 à la matrice 2 nous allons avoir une erreur, car elles n'ont pas les mêmes dimensions. + +```{r} +#| eval: false +matrice1 == matrice2 +``` + +`Erreur dans matrice1 == matrice2 : tableaux de tailles inadéquates` + +En revanche, nous pouvons transposer la matrice 1 et refaire cette comparaison : + +```{r} +t(matrice1) == matrice2 +``` + +Le résultat souligne bien que nous avons les mêmes valeurs dans les deux matrices. Il est aussi possible de construire des matrices directement avec la fonction `matrix`, ce que nous montrons dans la prochaine section. + +#### *Arrays* {#sec-01363} + +S'il est rare de travailler avec des matrices, il est encore plus rare de manipuler des *arrays*. Un *array* est une matrice spéciale qui peut avoir plus que deux dimensions. Un cas simple serait un *array* en trois dimensions : lignes, colonnes, profondeur, que nous pourrions représenter comme un cube, ou une série de matrices de mêmes dimensions et empilées. Au-delà de trois dimensions, il devient difficile de les représenter mentalement. Cette structure de données peut être utilisée pour représenter les différentes bandes spectrales d'une image satellitaire. Les lignes et les colonnes délimiteraient les pixels de l'image et la profondeur délimiterait les différentes bandes composant l'image (@fig-fig012). + + +![Un array avec trois dimensions](images/Chap01/array.png){#fig-fig013 width="15%" fig-align="center"} + +Créons un *array* en combinant trois matrices avec la fonction `array`. Chacune de ces matrices est composée respectivement de 1, de 2 et de 3 et a une dimension de 5 x 5. L'*array* final a donc une dimension de 5 x 5 x 3. + +```{r} +mat1 <- matrix(1, nrow = 5, ncol = 5) +mat2 <- matrix(2, nrow = 5, ncol = 5) +mat3 <- matrix(3, nrow = 5, ncol = 5) + +mon_array <- array(c(mat1, mat2, mat3), dim = c(5,5,3)) + +print(mon_array) +``` + + +#### *DataFrames* {#sec-01364} + +S'il est rare de manipuler des matrices et des *arrays*, le *DataFrame* (tableau de données en français) est la structure de données la plus souvent utilisée. Dans cette structure, chaque ligne du tableau représente un individu et chaque colonne représente une caractéristique de cet individu. Ces colonnes ont des noms qui permettent facilement d'accéder à leurs valeurs. Créons un *DataFrame* (@tbl-tabfirsttable) à partir de nos quatre vecteurs et de la fonction `data.frame`. + +```{r} +df <- data.frame( + "age" = ages, + "taille" = tailles, + "adresse" = adresses, + "proprietaire" = proprietaires +) +``` + +```{r} +#| label: tbl-tabfirsttable +#| tbl-cap: Premier DataFrame +#| echo: false +#| message: false +#| warning: false +knitr::kable(df, + format.args = list(decimal.mark = ',', big.mark = " "), + align= c("c", "c", "l", "l") +) +``` + +Dans RStudio, vous pouvez visualiser votre tableau de données avec la fonction `View(df)`. Comme vous pouvez le constater, chaque vecteur est devenu une colonne de votre tableau de données *df*. La @fig-fig013 résume ce passage d'une simple donnée à un *DataFrame* en passant par un vecteur. + + +![De la donnée au DataFrame](images/Chap01/vecteur_to_dataframe.png){#fig-fig013 width="25%" fig-align="center"} + +Plusieurs fonctions de base de R fournissent des informations importantes sur un *DataFrame* : + +* `names` renvoie les noms des colonnes du *DataFrame*; +* `nrow` renvoie le nombre de lignes; +* `ncol` renvoie le nombre de colonnes. + +```{r} +names(df) +nrow(df) +ncol(df) +``` + +Vous pouvez accéder à chaque colonne de *df* en utilisant le symbole `$` ou `[["nom_de_la_colonne"]]`. Recalculons ainsi la moyenne des âges : + +```{r} +mean(df$age) +mean(df[["age"]]) +``` + +#### Listes {#sec-01365} + +La dernière structure de données à connaître est la liste. Elle ressemble à un vecteur, au sens où elle permet de stocker un ensemble d'objets les uns à la suite des autres. Cependant, une liste peut contenir n'importe quel type d'objets. Vous pouvez ainsi construire des listes de matrices, des listes d'*arrays*, des listes mixant des vecteurs, des graphiques, des *DataFrames*, des listes de listes... + +Créons ensemble une liste qui va contenir des vecteurs et des matrices à l'aide de la fonction `list.` + +```{r} +ma_liste <- list(c(1,2,3,4), + matrix(1, ncol = 3, nrow = 5), + matrix(5, ncol = 3, nrow = 7), + 'A' + ) +``` + +Il est possible d'accéder aux éléments de la liste par leur position dans cette dernière en utilisant les doubles crochets `[[ ]]` : + +```{r} +print(ma_liste[[1]]) +print(ma_liste[[4]]) +``` + +Il est aussi possible de donner des noms aux éléments de la liste et d'utiliser le symbole `$` pour y accéder. Créons une nouvelle liste de vecteurs et donnons-leur des noms avec la fonction `names`. + +```{r} +liste2 <- list(c(35, 45, 72, 56, 62), + c(175.5, 180.3, 168.2, 172.8, 167.6), + c(TRUE, TRUE, FALSE, TRUE, TRUE) +) +names(liste2) <- c("age", "taille", "proprietaire") + +print(liste2$age) +``` + +Si vous avez bien suivi, vous devriez avoir compris qu'un *DataFrame* n'est en fait rien d'autre qu'une liste de vecteurs avec des noms! + +Bravo! Vous venez de faire le tour des bases du langage R. Vous allez apprendre désormais à manipuler des données dans des *DataFrames*! + +## Manipulation de données {#sec-014} + +Dans cette section, vous apprendrez à charger et à manipuler des *DataFrames* en vue d'effectuer des opérations classiques de gestion de données. + + +### Chargement d'un *DataFrame* depuis un fichier {#sec-0141} + +Il est rarement nécessaire de créer vos *DataFrames* manuellement. Le plus souvent, vous disposerez de fichiers contenant vos données et utiliserez des fonctions pour les importer dans R sous forme d'un *DataFrame*. Les formats à importer les plus répandus sont : + +* *.csv*, soit un fichier texte dont chaque ligne représente une ligne du tableau de données et dont les colonnes sont séparées par un délimiteur (généralement une virgule ou un point-virgule); + +* *.dbf*, ou fichier *dBase*, souvent associés à des fichiers d'information géographique au format *ShapeFile*; + +* *.xls* et *.xlsx*, soit des fichiers générés par Excel; + +* *.json*, soit un fichier texte utilisant la norme d'écriture propre au langage JavaScript. + +Plus rarement, il se peut que vous ayez à charger des fichiers provenant de logiciels propriétaires : + +* *.sas7bdat* (SAS); +* *.sav* (SPSS); +* *.dta* (STATA). + +Pour lire la plupart de ces fichiers, nous utilisons le *package* `foreign` dédié à l'importation d'une multitude de formats. Nous commençons donc par l'installer (`install.packages("foreign")`). Ensuite, nous chargeons cinq fois le même jeu de données enregistré dans des formats différents (*csv*, *dbf*, *dta*, *sas7bdat* et *xlsx*) et nous mesurons le temps nécessaire pour importer chacun de ces fichiers avec la fonction `Sys.time`. + +#### Lecture d'un fichier *csv* {#sec-01411} + +Pour le format *csv*, il n'est pas nécessaire d'utiliser un *package* puisque R dispose d'une fonction de base pour lire ce format. + +```{r} +#| message: false +#| warning: false +t1 <- Sys.time() +df1 <- read.csv("data/priseenmain/SR_MTL_2016.csv", + header = TRUE, sep = ",", dec = ".", + stringsAsFactors = FALSE) +t2 <- Sys.time() +d1 <- as.numeric(difftime(t2, t1, units = "secs")) +cat("Le DataFrame df1 a ", nrow(df1)," observations", + 'et ', ncol(df1)," colonnes\n") +``` + +Rien de bien compliqué! Notez tout de même que : + +* Lorsque vous chargez un fichier *csv*, vous devez connaître le **délimiteur** (ou **séparateur**), soit le caractère utilisé pour délimiter les colonnes. Dans le cas présent, il s'agit d'une virgule (spécifiez avec l'argument `sep = ","`), mais il pourrait tout aussi bien être un point virgule (`sep = ";"`), une tabulation (`sep = " "`), etc. + +* Vous devez également spécifier le caractère utilisé comme séparateur de décimales. Le plus souvent, ce sera le point (`dec = "."`), mais certains logiciels avec des paramètres régionaux de langue française (notamment Excel) exportent des fichiers *csv* avec des virgules comme séparateur de décimales (utilisez alors `dec = ","`). + +* L'argument `header` indique si la première ligne (l'entête) du fichier comprend ou non les noms des colonnes du jeu de données (avec les valeurs `TRUE` ou `FALSE`). Il arrive que certains fichiers *csv* soient fournis sans entête et que le nom et la description des colonnes soient fournis dans un autre fichier. + +* L'argument `stringsAsFactors` permet d'indiquer à R que les colonnes comportant du texte doivent être chargées comme des vecteurs de type texte et non de type facteur. + +#### Lecture d'un fichier *dbase* {#sec-01412} + +Pour lire un fichier *dbase* (.dbf), nous utilisons la fonction `read.dbf` du *package* `foreign` installé précédemment : + +```{r} +#| message: false +#| warning: false +library(foreign) + +t1 <- Sys.time() +df2 <- read.dbf("data/priseenmain/SR_MTL_2016.dbf") +t2 <- Sys.time() +d2 <- as.numeric(difftime(t2, t1, units = "secs")) +cat("Le DataFrame df2 a ", nrow(df2)," observations", + "et ", ncol(df2)," colonnes\n") +``` + +Comme vous pouvez le constater, nous obtenons les mêmes résultats qu'avec le fichier *csv*. + +#### Lecture d'un fichier *dta* (Stata) {#sec-01413} + +Si vous travaillez avec des collègues utilisant le logiciel Stata, il se peut que ces derniers vous partagent des fichiers *dta*. Toujours en utilisant le *package* `foreign`, vous serez en mesure de les charger directement dans R. + +```{r} +#| message: false +#| warning: false +t1 <- Sys.time() +df3 <- read.dta("data/priseenmain/SR_MTL_2016.dta") +t2 <- Sys.time() +d3 <- as.numeric(difftime(t2, t1, units = "secs")) +cat("Le DataFrame df3 a ", nrow(df3)," observations ", + "et ", ncol(df3), " colonnes\n", sep = "") +``` + + +#### Lecture d'un fichier *sav* (SPSS) {#sec-01414} + +Pour importer un fichier *sav* provenant du logiciel statistique SPSS, utilisez la fonction `read.spss` du *package* `foreign`. + +```{r} +#| message: false +#| warning: false +t1 <- Sys.time() +df4 <- as.data.frame(read.spss("data/priseenmain/SR_MTL_2016.sav")) +t2 <- Sys.time() +d4 <- as.numeric(difftime(t2, t1, units = "secs")) +cat("Le DataFrame df4 a ", nrow(df4)," observations ", + "et ", ncol(df4), " colonnes\n", sep = "") +``` + +#### Lecture d'un fichier *sas7bdat* (SAS) {#sec-01415} + +Pour importer un fichier *sas7bdat* provenant du logiciel statistique SAS, utilisez la fonction `read.sas7bdat` du *package* `sas7bdat`. Installez préalablement le *package* (`install.packages("sas7bdat")`) et chargez-le (`library(sas7bdat)`). + +```{r} +#| message: false +#| warning: false +library(sas7bdat) + +t1 <- Sys.time() +df5 <- read.sas7bdat("data/priseenmain/SR_MTL_2016.sas7bdat") +t2 <- Sys.time() +d5 <- as.numeric(difftime(t2, t1, units = "secs")) +cat("Le DataFrame df5 a ", nrow(df5)," observations ", + "et ", ncol(df5)," colonnes\n", sep = "") +``` + + +#### Lecture d'un fichier *xlsx* (Excel) {#sec-01416} + +Lire un fichier Excel dans R n'est pas toujours une tâche facile. Généralement, nous recommandons d'exporter le fichier en question au format *csv* dans un premier temps, puis de le lire avec la fonction `read.csv` dans un second temps ([section @sec-01411]). + +Il est néanmoins possible de lire directement un fichier *xlsx* avec le *package* `xlsx`. Ce dernier requiert que le logiciel JAVA soit installé sur votre ordinateur (Windows, Mac ou Linux). Si vous utilisez la version 64 bit de R, vous devrez télécharger et installer la version 64 bit de JAVA. Une fois que ce logiciel tiers est installé, il ne vous restera plus qu'à installer (`install.packages("xlsx")`) et charger (`library(xlsx)`) le *package* `xlsx`. Sous windows, il est possible que vous deviez également installer manuellement le *package* `rJava` et indiquer à R où se trouve JAVA sur votre ordinateur. La procédure est détaillée [ici](https://cimentadaj.github.io/blog/2018-05-25-installing-rjava-on-windows-10/installing-rjava-on-windows-10/). + +```{r} +#| message: false +#| warning: false +library(xlsx) + +t1 <- Sys.time() +df6 <- read.xlsx(file="data/priseenmain/SR_MTL_2016.xlsx", + sheetIndex = 1, + as.data.frame = TRUE) +t2 <- Sys.time() +d6 <- as.numeric(difftime(t2, t1, units = "secs")) +cat("Le DataFrame df6 a ", nrow(df6)," observations ", + "et ", ncol(df6)," colonnes\n", sep = "") +``` + +Il est possible d'accélérer significativement la vitesse de lecture d'un fichier *xlsx* en utilisant la fonction `read.xlsx2`. Il faut cependant indiquer à cette dernière le type de données de chaque colonne. Dans le cas présent, les cinq premières colonnes contiennent des données de type texte (`character`), alors que les 43 autres sont des données numériques (`numeric`). Nous utilisons la fonction `rep` afin de ne pas avoir à écrire plusieurs fois *character* et *numeric*. + +```{r} +#| echo: true +#| message: false +#| warning: false +library(xlsx) + +t1 <- Sys.time() +df7 <- read.xlsx2(file="data/priseenmain/SR_MTL_2016.xlsx", + sheetIndex = 1, + as.data.frame = TRUE, + colClasses = c(rep("character",5), rep("numeric",43)) + ) +t2 <- Sys.time() +d7 <- as.numeric(difftime(t2, t1, units = "secs")) +cat("Le DataFrame df6 a ", nrow(df7)," observations ", + "et ", ncol(df7)," colonnes\n", sep = "") +``` + +Si nous comparons les temps d'exécution (@tbl-tableduration), nous constatons que la lecture des fichiers *xlsx* peut être extrêmement longue si nous ne spécifions pas le type des colonnes, ce qui peut devenir problématique pour des fichiers volumineux. Notez également que la lecture d'un fichier *csv* devient de plus en plus laborieuse à mesure que sa taille augmente. Si vous devez un jour charger des fichiers *csv* de plusieurs gigaoctets, nous vous recommandons vivement d'utiliser la fonction `fread` du *package* `data.table` qui est beaucoup plus rapide. + + +```{r} +#| label: tbl-tableduration +#| tbl-cap: Temps nécessaire pour lire les données en fonction du type de fichiers +#| echo: false +#| message: false +#| warning: false +DureeImportation <- data.frame( + "fonction" = c("read.csv" , "read.dbf" , "read.spss" , "read.dta", + 'read.sas7bdat',"read.xlsx" , "read.xlsx2"), + "duree" = c(d1, d2, d3, d4, d5, d6, d7) + +) + +knitr::kable(DureeImportation, + format.args = list(decimal.mark = ',', big.mark = " "), + digits = 2, + col.names = c("Fonction", "Durée (secondes)"), + align= c("r", "l") + ) +``` + +### Manipulation d'un *DataFrame* {#sec-0142} + +Une fois le *DataFrame* chargé, voyons comment il est possible de le manipuler. + +#### Petit mot sur le `tidyverse` {#sec-01421} + +`tidyverse` est un ensemble de *packages* conçus pour faciliter la structuration et la manipulation des données dans R. Avant d'aller plus loin, il est important d'aborder brièvement un débat actuel dans la Communauté R. Entre 2010 et 2020, l'utilisation du `tidyverse` s'est peu à peu répandue. Développé et maintenu par Hadley Wickham, `tidyverse` introduit une philosophie et une grammaire spécifiques qui diffèrent du langage R traditionnel. Une partie de la communauté a pour ainsi dire complètement embrassé le `tidyverse` et de nombreux *packages*, en dehors du `tidyverse`, ont adopté sa grammaire et sa philosophie. À l'inverse, une autre partie de la communauté est contre cette évolution ([voir l'article du blogue suivant](https://blog.ephorie.de/why-i-dont-use-the-tidyverse){target="_blank"}). Les arguments pour et contre `tidyverse` sont résumés dans le (@tbl-Tidyverse). + + +```{r} +#| label: tbl-Tidyverse +#| tbl-cap: Avantages et inconvénients du tidyverse +#| echo: false +#| message: false +#| warning: false + +df <- data.frame( + Pour = c("Simplicité d'écriture et d'apprentissage", + "Ajout de l'opérateur `%>%` permettant d'enchaîner les traitements", + "La meilleure librairie pour réaliser des graphiques : `ggplot2`", + "Crée un écosystème cohérent", + "*Package* en développement et de plus en plus utilisé"), + Contre = c("Nouvelle syntaxe à apprendre", + "Perte de lisibilité avec l'opérateur `->`", + "Remplacement de certaines fonctions de base par d'autres provenant du `tidyverse` lors de son chargement, pouvant créer des erreurs.", + "Ajout d'une dépendance dans le code", + "Philosophie d'évolution agressive, aucune assurance de rétrocompatibilité") +) + +knitr::kable(df, + format.args = list(decimal.mark = ',', big.mark = " "), + col.names = c("Avantage du tidyverse", + "Problème posé par le tidyverse"), + align= c("l", "l"), + col.to.resize = c(1,2), + col.width = "7cm") +``` + + +Le dernier point est probablement le plus problématique. Dans sa volonté d'évoluer au mieux et sans restriction, le *package* `tidyverse` n'offre aucune garantie de rétrocompatibilité. En d'autres termes, des changements importants peuvent être introduits d'une version à l'autre rendant potentiellement obsolète votre ancien code. Nous n'avons pas d'opinion tranchée sur le sujet : `tidyverse` est un outil très intéressant dans de nombreux cas; nous évitons simplement de l'utiliser systématiquement et préférons charger directement des sous-*packages* (comme `dplyr` ou `ggplot2`) du `tidyverse`. Notez que le *package* `data.table` offre une alternative au `tidyverse` dans la manipulation de données. Au prix d'une syntaxe généralement un peu plus complexe, le package `data.table` offre une vitesse de calcul bien supérieure au `tidyverse` et assure une bonne rétrocompatibilité. + + +#### Gestion des colonnes d'un *DataFrame* {#sec-01422} + +Repartons du *DataFrame* que nous avions chargé précédemment en important un fichier *csv*. + +```{r} +#| message: false +#| warning: false +df <- read.csv(file="data/priseenmain/SR_MTL_2016.csv", + header = TRUE, sep = ",", dec = ".", + stringsAsFactors = FALSE) +``` + +##### Sélection d'une colonne {#sec-014221} + +Rappelons qu'il est possible d'accéder aux colonnes dans ce *DataFrame* en utilisant le symbole dollar `$ma_colonne` ou les doubles crochets `[["ma_colonne"]]`. + +```{r} +#| message: false +#| warning: false +# Calcul de la superficie totale de l'Île de Montréal +sum(df$KM2) +sum(df[["KM2"]]) +``` + +##### Sélection de plusieurs colonnes {#sec-014222} + +Il est possible de sélectionner plusieurs colonnes d'un *DataFrame* et de filtrer ainsi les colonnes inutiles. Pour cela, nous pouvons utiliser un vecteur contenant soit les positions des colonnes (1 pour la première colonne, 2 pour la seconde et ainsi de suite), soit les noms des colonnes. + +```{r} +#| message: false +#| warning: false +# Conserver les 5 premières colonnes +df2 <- df[1:5] + +# Conserver les colonnes 1, 5, 10 et 15 +df3 <- df[c(1,5,10,15)] + +# Cela peut aussi être utilisé pour changer l'ordre des champs +df3 <- df[c(10,15,1,5)] + +# Conserver les colonnes 1 à 5, 7 à 12, 17 et 22 +df4 <- df[c(1:5,7:12,17,22)] + +# Conserver les colonnes avec leurs noms +df5 <- df[c("SRIDU" , "KM2" , "Pop2016" , "MaisonIndi" , "LoyerMed")] +``` + +##### Suppression de colonnes {#sec-014223} + +Il est parfois plus intéressant et rapide de supprimer directement des colonnes plutôt que de recréer un nouveau *DataFrame*. Pour ce faire, nous attribuons la valeur `NULL` à ces colonnes. + +```{r} +#| message: false +#| warning: false +# Supprimer les colonnes 2, 3 et 5 +df3[c(2,3,5)] <- list(NULL) + +# Supprimer une colonne avec son nom +df4$OID <- NULL + +# Supprimer plusieurs colonnes par leur nom +df5[c("SRIDU" , "LoyerMed")] <- list(NULL) +``` + +Notez que si vous supprimez une colonne, vous ne pouvez pas revenir en arrière. Il faudra recharger votre jeu de données ou éventuellement relancer les calculs qui avaient produit cette colonne. + +##### Modification du nom des colonnes {#sec-014224} + +Il est possible de changer le nom d'une colonne. Cette opération est importante pour faciliter la lecture du *DataFrame* ou encore s'assurer que l'exportation du *DataFrame* dans un format particulier (tel que *.dbf* qui ne supporte que les noms de colonnes avec moins de 10 caractères) ne posera pas de problème. + +```{r} +#| message: false +#| warning: false +# Voici les noms des colonnes +names(df5) + +# Renommer toutes les colonnes +names(df5) <- c('superficie_km2','population_2016', 'maison_individuelle_prt') +names(df5) + +# Renommer avec dplyr +library(dplyr) +df4 <- rename(df4, "population_2016" = "Pop2016", + "prs_moins_14ans_prt" = "A014", + "prs_15_64_ans_prt" = "A1564", + "prs_65plus_ans_prt" = "A65plus" + ) +``` + + +#### Calcul de nouvelles variables {#sec-01423} + +Il est possible d'utiliser les colonnes de type numérique pour calculer de nouvelles colonnes en utilisant les opérateurs mathématiques vus dans la [section @sec-0135]. Prenons un exemple concret : calculons la densité de population par secteur de recensement dans notre *DataFrame*, puis affichons un résumé de cette nouvelle variable. + +```{r} +#| message: false +#| warning: false +# Calcul de la densité +df$pop_density_2016 <- df$Pop2016 / df$KM2 + +# Statistiques descriptives +summary(df$pop_density_2016) +``` + +Nous pouvons aussi calculer le ratio entre le nombre de maisons et le nombre d'appartements. + +```{r} +#| message: false +#| warning: false + +# Calcul du ratio +df$total_maison <- (df$MaisonIndi + df$MaisJumule + df$MaisRangee + df$AutreMais) +df$total_apt <- (df$AppDuplex + df$App5Moins + df$App5Plus) +df$ratio_maison_apt <- df$total_maison / df$total_apt +``` + +Retenez ici que R applique le calcul à chaque ligne de votre jeu de données et stocke le résultat dans une nouvelle colonne. Cette opération est du calcul vectoriel : toute la colonne est calculée en une seule fois. R est d'ailleurs optimisé pour le calcul vectoriel. + +#### Fonctions mathématiques {#sec-01424} + +R propose un ensemble de fonctions de base pour effectuer du calcul. Voici une liste non exhaustive des principales fonctions : + +* `abs` calcule la valeur absolue de chaque valeur d'un vecteur; + +* `sqrt` calcule la racine carrée de chaque valeur d'un vecteur; + +* `log` calcule le logarithme de chaque valeur d'un vecteur; + +* `exp` calcule l'exponentielle de chaque valeur d'un vecteur; + +* `factorial` calcule la factorielle de chaque valeur d'un vecteur; + +* `round` arrondit la valeur d'un vecteur; + +* `ceiling`, `floor` arrondit à l'unité supérieure ou inférieure de chaque valeur d'un vecteur; + +* `sin`, `asin`, `cos`, `acos`, `tan`, `atan` sont des fonctions de trigonométrie; + +* `cumsum` calcule la somme cumulative des valeurs d'un vecteur. + +Ces fonctions sont des fonctions vectorielles puisqu'elles s'appliquent à tous les éléments d'un vecteur. Si votre vecteur en entrée comprend cinq valeurs, le vecteur en sortie comprendra aussi cinq valeurs. + +À l'inverse, les fonctions suivantes s'appliquent directement à l'ensemble d'un vecteur et ne vont renvoyer qu'une seule valeur : + +* `sum` calcule la somme des valeurs d'un vecteur; + +* `prod` calcule le produit des valeurs d'un vecteur; + +* `min`, `max` renvoient les valeurs maximale et minimale d'un vecteur; + +* `mean`, `median` renvoient la moyenne et la médiane d'un vecteur; + +* `quantile` renvoie les percentiles d'un vecteur. + +#### Fonctions pour manipuler des chaînes de caractères {#sec-01425} + +Outre les données numériques, vous aurez à travailler avec des données de type texte (`string`). Le `tidyverse` avec le *package* `stringr` offre des fonctions très intéressantes pour manipuler ce type de données. Pour un aperçu de toutes les fonctions offertes par `stringr`, référez-vous à sa [*Cheat Sheet*](https://github.com/rstudio/cheatsheets/blob/master/strings.pdf){target="_blank"}. Commençons avec un *DataFrame* assez simple comprenant des adresses et des noms de personnes. + +```{r} +#| message: false +#| warning: false +library(stringr) + +df <- data.frame( + noms = c("Jérémy Toutanplace" , "constant Tinople" , "dino Resto" , "Luce tancil"), + adresses = c('15 rue Levy', '413 Blvd Saint-Laurent', '3606 rue Duké', '2457 route St Marys') +) +``` + +##### Majuscules et minuscules {#sec-014251} + +Pour harmoniser ce *DataFrame*, nous mettons, dans un premier temps, des majuscules à la première lettre des prénoms et des noms des individus avec la fonction `str_to_title`. + +```{r} +#| message: false +#| warning: false +df$noms_corr <- str_to_title(df$noms) +print(df$noms_corr) +``` + +Nous pourrions également tout mettre en minuscules ou tout en majuscules. + +```{r} +#| message: false +#| warning: false +df$noms_min <- tolower(df$noms) +df$noms_maj <- toupper(df$noms) +print(df$noms_min) +print(df$noms_maj) +``` + +##### Remplacement du texte {#sec-014252} + +Les adresses comprennent des caractères accentués. Ce type de caractères cause régulièrement des problèmes d'encodage. Nous pourrions alors décider de les remplacer par des caractères simples avec la fonction `str_replace_all`. + +```{r} +#| message: false +#| warning: false +df$adresses_1 <- str_replace_all(df$adresses,'é','e') +print(df$adresses_1) +``` + +La même fonction peut être utilisée pour remplacer les *St* par *Saint* et les *Blvd* par *Boulevard*. + +```{r} +#| message: false +#| warning: false +df$adresses_2 <- str_replace_all(df$adresses_1,' St ',' Saint ') +df$adresses_3 <- str_replace_all(df$adresses_2,' Blvd ',' Boulevard ') +print(df$adresses_3) +``` + +##### Découpage du texte {#sec-014253} + +Il est parfois nécessaire de découper du texte pour en extraire des éléments. Nous devons alors choisir un caractère de découpage. Dans notre exemple, nous pourrions vouloir extraire les numéros civiques des adresses en sélectionnant le premier espace comme caractère de découpage, et en utilisant la fonction `str_split_fixed`. + +```{r} +#| message: false +#| warning: false +df$num_civique <- str_split_fixed(df$adresses_3, ' ', n=2)[,1] +print(df$num_civique) +``` + +Pour être exact, sachez que pour notre exemple, la fonction `str_split_fixed` renvoie deux colonnes de texte : une avec le texte avant le premier espace, soit le numéro civique, et une avec le reste du texte. Le nombre de colonnes est contrôlé par l'argument `n`. Si `n = 1`, la fonction ne fait aucun découpage; avec `n = 2` la fonction découpe en deux parties le texte avec la première occurrence du délimiteur et ainsi de suite. En ajoutant `[,1]` à la fin, nous indiquons que nous souhaitons garder seulement la première des deux colonnes. + +Il est également possible d'extraire des parties de texte et de ne garder par exemple que les *N* premiers caractères ou les *N* derniers caractères : + +```{r} +#| message: false +#| warning: false +# Ne garder que les 5 premiers caractères +substr(df$adresses_3, start = 1, stop = 5) + +# Ne garder que les 5 derniers caractères +n_caract <- nchar(df$adresses_3) +substr(df$adresses_3, start = n_caract-4, stop = n_caract) +``` + +Notez que les paramètres `start` et `stop` de la fonction `substr` peuvent accepter un vecteur de valeurs. Il est ainsi possible d'appliquer une sélection de texte différente à chaque chaîne de caractères dans notre vecteur en entrée. Nous pourrions par exemple vouloir récupérer tout le texte avant le second espace pour garder uniquement le numéro civique et le type de rue. + +```{r} +#| message: false +#| warning: false +# Étape 1 : récupérer les positions des espaces pour chaque adresses +positions <- str_locate_all(df$adresses_3, " ") +# Étape 2 : récupérer les positions des seconds espaces +sec_positions <- sapply(positions, function(i){ + i[2,1] +}) +# Étape 3 : appliquer le découpage +substr(df$adresses_3, start = 1, stop = sec_positions-1) +``` + + +##### Concaténation du texte {#sec-014254} + +À l'inverse du découpage, il est parfois nécessaire de concaténer des éléments de texte, ce qu'il est possible de réaliser avec la fonction `paste`. + +```{r} +#| message: false +#| warning: false +df$texte_complet <- paste(df$noms_corr, df$adresses_3, sep = " : ") +print(df$texte_complet) +``` + +Le paramètre `sep` permet d'indiquer le ou les caractères à intercaler entre les éléments à concaténer. Notez qu'il est possible de concaténer plus que deux éléments. + +```{r} +#| message: false +#| warning: false +df$ville <- c('Montreal','Montreal','Montreal','Montreal') +paste(df$noms_corr, df$adresses_3, df$ville, sep = ", ") +``` + +Si vous souhaitez concaténer des éléments de texte sans séparateur, la fonction `paste0` peut être plus simple à utiliser. + +```{r} +#| message: false +#| warning: false +paste0("Please conca", "tenate me!") +``` + +#### Manipulation des colonnes de type date {#sec-01426} + +Nous avons vu que les principaux types de données dans R sont le numérique, le texte, le booléen et le facteur. Il existe d'autres types introduits par différents *packages*. Nous abordons ici les types date et heure (*date* and *time*). Pour les manipuler, nous privilégions l'utilisation du *package* `lubridate` du `tidyverse`. Pour illustrer le tout, nous l'utilisons avec un jeu de données ouvertes de la Ville de Montréal représentant les collisions routières impliquant au moins un cycliste survenues après le 1^er^ janvier 2017. + +```{r} +#| message: false +#| warning: false +accidents_df <- read.csv(file="data/priseenmain/accidents.csv", sep = ",") +names(accidents_df) +``` + +Nous disposons de trois colonnes représentant respectivement l'heure, la date et le nombre de victimes impliquées dans la collision. + +##### Du texte à la date {#sec-014261} + +Actuellement, les colonnes `HEURE_ACCDN` et `DT_ACCDN` sont au format texte. Nous pouvons afficher quelques lignes du jeu de données avec la fonction `head` pour visualiser comment elles ont été saisies. + +```{r} +#| message: false +#| warning: false +head(accidents_df, n = 5) +``` + +Un peu de ménage s'impose : les heures sont indiquées comme des périodes d'une heure. Nous utilisons la fonction `str_split_fixed` du *package* `stringr` pour ne garder que la première partie de l'heure (avant le tiret). Ensuite, Nous concaténons l'heure et la date avec la fonction `paste`, puis nous convertissons ce résultat en un objet *date-time*. + +```{r} +#| message: false +#| warning: false +library(lubridate) + +# Étape 1 : découper la colonne Heure_ACCDN +accidents_df$heure <- str_split_fixed(accidents_df$HEURE_ACCDN, "-", n=2)[,1] +# Étape 2 : concaténer l'heure et la date +accidents_df$date_heure <- paste(accidents_df$DT_ACCDN, + accidents_df$heure, + sep = ' ') +# Étape 3 : convertir au format datetime +accidents_df$datetime <- as_datetime(accidents_df$date_heure, + format = "%Y/%m/%d %H:%M:%S") +``` + +Pour effectuer la conversion, nous avons utilisé la fonction `as_datetime` du *package* `lubridate`. Elle prend comme paramètre un vecteur de texte et une indication du format de ce vecteur de texte. Il existe de nombreuses façons de spécifier une date et une heure et l'argument *format* permet d'indiquer celle à utiliser. Dans cet exemple, la date est structurée comme suit : +`année/mois/jour heure:minute:seconde`, ce qui se traduit par le format `%Y/%m/%d %H:%M:%S`. + +* %Y signifie une année indiquée avec quatre caractères : 2017; + +* %m signifie un mois, indiqué avec deux caractères : 01, 02, 03, ... 12; + +* %d signifie un jour, indiqué avec deux caractères : 01, 02, 03, ... 31; + +* %H signifie une heure, au format 24 heures avec deux caractères : 00, 02, ... 23; + +* %M signifie des minutes indiquées avec deux caractères : 00, 02, ... 59; + +* %S signifie des secondes, indiquées avec deux caractères : 00, 02, ... 59. + +Notez que les caractères séparant les années, jours, heures, etc. sont aussi à indiquer dans le format. Dans notre exemple, nous utilisons la barre oblique (`/`) pour séparer les éléments de la date et le deux points (`:`) pour l'heure, et une espace pour séparer la date et l'heure. + +Il existe d'autres nomenclatures pour spécifier un format *datetime* : par exemple, des mois renseignés par leur nom, l'indication AM-PM, etc. Vous pouvez vous référer à la documentation de la fonction `strptime` (`help(strptime)`) pour explorer les différentes nomenclatures et choisir celle qui vous convient. Bien évidemment, il est nécessaire que toutes les dates de votre colonne soient renseignées dans le même format, pour éviter que la fonction ne retourne la valeur `NA` lorsqu'elle ne peut lire le format. Après toutes ces opérations, rejetons un oeil à notre *DataFrame*. + +```{r} +#| message: false +#| warning: false +head(accidents_df, n = 5) +``` + +##### Extraction des informations d'une date {#sec-014262} + +À partir de la nouvelle colonne `datetime`, nous sommes en mesure d'extraire des informations intéressantes comme : + +* le nom du jour de la semaine avec la fonction `weekdays` +```{r} +#| message: false +#| warning: false +accidents_df$jour <- weekdays(accidents_df$datetime) +``` + +* la période de la journée avec les fonctions `am` et `pm` +```{r} +#| message: false +#| warning: false +accidents_df$AM <- am(accidents_df$datetime) +accidents_df$PM <- pm(accidents_df$datetime) +head(accidents_df[c("jour", "AM", "PM")], n=5) +``` + +Il est aussi possible d'accéder aux sous-éléments d'un *datetime* comme l'année, le mois, le jour, l'heure, la minute et la seconde avec les fonctions `year()`, `month()`,`day()`, `hour()`, `minute()` et `second()`. + +##### Calcul d'une durée entre deux *datetime* {#sec-014263} + +Une autre utilisation intéressante du format *datetime* est de calculer des différences de temps. Par exemple, nous pourrions utiliser le nombre de minutes écoulées depuis 7 h comme une variable dans une analyse visant à déterminer le moment critique des collisions routières durant l'heure de pointe du matin. +Pour cela, nous devons créer un *datetime* de référence en concaténant la date de chaque observation, et le temps `07:00:00`, qui est notre point de départ. + +```{r} +#| message: false +#| warning: false +accidents_df$date_heure_07 <- paste(accidents_df$DT_ACCDN, + '07:00:00', + sep = ' ') +accidents_df$ref_datetime <- as_datetime(accidents_df$date_heure_07, + format = "%Y/%m/%d %H:%M:%S") +``` +Il ne nous reste plus qu'à calculer la différence de temps entre la colonne *datetime* et notre temps de référence *ref_datetime*. + +```{r} +#| message: false +#| warning: false +accidents_df$diff_time <- difftime(accidents_df$datetime, + accidents_df$ref_datetime, + units = 'min') +``` + +Notez qu'ici la colonne *diff_time* est d'un type spécial : une différence temporelle (*difftime*). Il faut encore la convertir au format numérique pour l'utiliser avec la fonction `as.numeric`. Par curiosité, réalisons rapidement un histogramme avec la fonction `hist` pour analyser rapidement cette variable d'écart de temps! + +```{r} +#| label: fig-fig015 +#| fig-cap: Répartition temporelle des accidents à vélo +#| warning: false +#| fig.align: "center" +#| out.width: "65%" + +accidents_df$diff_time_num <- as.numeric(accidents_df$diff_time) +hist(accidents_df$diff_time_num, breaks = 50) +``` + +Nous observons clairement deux pics, un premier entre 0 et 100 (entre 7 h et 8 h 30 environ) et un second plus important entre 550 et 650 (entre 16 h et 17 h 30 environ), ce qui correspond sans surprise aux heures de pointe (@fig-fig015). Il est intéressant de noter que plus d'accidents se produisent à l'heure de pointe du soir qu'à celle du matin. + +##### Fuseau horaire {#sec-014264} + +Lorsque nous travaillons avec des données provenant de différents endroits dans le monde ou que nous devons tenir compte des heures d'été et d'hiver, il convient de tenir compte du fuseau horaire. Pour créer une date avec un fuseau horaire, il est possible d'utiliser le paramètre `tz` dans la fonction `as_datetime` et d'utiliser l’identifiant du fuseau approprié. Dans notre cas, les données d'accident ont été collectées à Montréal, qui a un décalage de -5 heures par rapport au temps de référence UTC (+1 heure en été). Le code spécifique de ce fuseau horaire est *EDT*; il est facile de trouver ces codes avec le site web [timeanddate.com](https://www.timeanddate.com/time/map/). + +```{r} +#| message: false +#| warning: false +accidents_df$datetime <- as_datetime(accidents_df$date_heure, + format = "%Y/%m/%d %H:%M:%S", + tz = "EDT") +``` + +#### Recodage des variables {#sec-01427} + +Recoder une variable signifie changer ses valeurs selon une condition afin d'obtenir une nouvelle variable. Si nous reprenons le jeu de données précédent sur les accidents à vélo, nous pourrions vouloir créer une nouvelle colonne nous indiquant si la collision a eu lieu en heures de pointe ou non. Nous obtiendrions ainsi une nouvelle variable avec seulement deux catégories plutôt que la variable numérique originale. Nous pourrions aussi définir quatre catégories avec l'heure de pointe du matin, l'heure de pointe du soir, le reste de la journée et la nuit. + +##### Cas binaire avec `ifelse` {#sec-014271} + +Si nous ne souhaitons créer que deux catégories, le plus simple est d'utiliser la fonction `ifelse`. Cette fonction évalue une condition ([section @sec-0135]) pour chaque ligne d'un *DataFrame* et produit un nouveau vecteur. Créons donc une variable binaire indiquant si une collision a eu lieu durant les heures de pointe ou hors heures de pointe. Nous devons alors évaluer les conditions suivantes : + +Est-ce que l'accident a eu lieu entre 7 h (0) **ET** 9 h (120), **OU** entre 16 h 30 (570) **ET** 18 h 30 (690)? + +```{r} +#| message: false +#| warning: false +table(is.na(accidents_df$diff_time_num)) +``` + +Notons dans un premier temps que nous avons 40 observations sans valeur pour la colonne `diff_time_num`. Il s'agit d'observations pour lesquelles nous ne disposions pas de dates au départ. + +```{r} +#| message: false +#| warning: false +Cond1 <- accidents_df$diff_time_num >= 0 & accidents_df$diff_time_num <= 120 +Cond2 <- accidents_df$diff_time_num >= 570 & accidents_df$diff_time_num <= 690 + +accidents_df$moment_bin <- ifelse(Cond1 | Cond2, + "en heures de pointe", + "hors heures de pointe") +``` + +Comme vous pouvez le constater, la fonction `ifelse` nécessite trois arguments : + +* une condition, pouvant être `TRUE` ou `FALSE`; + +* la valeur à renvoyer si la condition est `FALSE`; + +* la valeur à renvoyer si la condition est `TRUE`. + +Avec la fonction `table`, nous pouvons rapidement visualiser les effectifs des deux catégories ainsi créées : + +```{r} +#| message: false +#| warning: false +table(accidents_df$moment_bin) + +# Vérifier si nous avons toujours seulement 40 NA +table(is.na(accidents_df$moment_bin)) +``` +Les heures de pointe représentent quatre heures de la journée, ce qui nous laisse neuf heures hors heures de pointe entre 7 h et 20 h. + +```{r} +#| message: false +#| warning: false +# Ratio de collisions routières en heures de pointe +(841 / 2414) / (4 / 13) + +# Ratio de collisions routières hors heure de pointe +(1573 / 2414) / (9 / 13) +``` + +En rapportant les collisions aux durées des deux périodes, nous observons une nette surreprésentation des collisions impliquant un vélo pendant les heures de pointe d'environ 13 % comparativement à la période hors des heures de pointe. + +##### Cas multiple avec la `case_when` {#sec-014272} + +Lorsque nous souhaitons créer plus que deux catégories, il est possible soit d'enchaîner plusieurs fonctions `ifelse` (ce qui produit un code plus long et moins lisible), soit d'utiliser la fonction `case_when` du *package* `dplyr` du `tidyverse`. Reprenons notre exemple et créons quatre catégories : + +* en heures de pointe du matin; + +* en heures de pointe du soir; + +* le reste de la journée (entre 7 h et 20 h); + +* la nuit (entre 21 h et 7 h). + +```{r} +#| message: false +#| warning: false +library(dplyr) + +accidents_df$moment_multi <- case_when( + accidents_df$diff_time_num >= 0 & accidents_df$diff_time_num <= 120 ~ "pointe matin", + accidents_df$diff_time_num >= 570 & accidents_df$diff_time_num <= 690 ~ "pointe soir", + accidents_df$diff_time_num > 690 & accidents_df$diff_time_num < 780 ~ "journee", + accidents_df$diff_time_num > 120 & accidents_df$diff_time_num < 570 ~ "journee", + accidents_df$diff_time_num < 0 | accidents_df$diff_time_num >= 780 ~ "nuit" +) + +table(accidents_df$moment_multi) + +# Vérifions encore les NA +table(is.na(accidents_df$moment_multi)) +``` + +La syntaxe de cette fonction est un peu particulière. Elle accepte un nombre illimité (ou presque) d'arguments. Chaque argument est composé d'une condition et d'une valeur à renvoyer si la condition est vraie; ces deux éléments étant reliés par le symbole `~`. Notez que toutes les évaluations sont effectuées dans l'ordre des arguments. En d'autres termes, la fonction teste d'abord la première condition et assigne ses valeurs, puis recommence pour les prochaines conditions. Ainsi, si une observation (ligne du tableau de données) obtient `TRUE` à plusieurs conditions, elle obtient au final la valeur de la dernière condition validée. Dans l'exemple précédent, si la première condition est `accidents_df$diff_time_num >= 0 | accidents_df$diff_time_num <= 120`, alors nous obtenons pour seule valeur en résultat `"pointe matin"` puisque chaque observation a une valeur supérieure à 0 et que nous avons remplacé l'opérateur `&` (ET) par l'opérateur `|` (OU). + +#### Sous-sélection d'un *DataFrame* {#sec-01428} + +Dans cette section, nous voyons comment extraire des sous-parties d'un *DataFrame*. Il est possible de sous-sélectionner des lignes et des colonnes en se basant sur des conditions ou leur index. Pour cela, nous utilisons un jeu de données fourni avec R : le jeu de données **iris** décrivant des fleurs du même nom. + +```{r} +#| message: false +#| warning: false +data("iris") + +# Nombre de lignes et de colonnes +dim(iris) +``` + +##### Sous-sélection des lignes {#sec-014281} + +Sous-sélectionner des lignes par index est relativement simple. Admettons que nous souhaitons sélectionner les lignes 1 à 5, 10 à 25, 37 et 58. + +```{r} +#| message: false +#| warning: false +sub_iris <- iris[c(1:5, 10:25, 37, 58),] +nrow(sub_iris) +``` + +Sous-sélectionner des lignes avec une condition peut être effectué soit avec une syntaxe similaire, soit en utilisant la fonction `subset`. Sélectionnons toutes les fleurs de l'espèce Virginica. + +```{r} +#| message: false +#| warning: false +iris_virginica1 <- iris[iris$Species == "virginica",] +iris_virginica2 <- subset(iris, iris$Species == "virginica") + +# Vérifions que les deux DataFrames ont le même nombre de lignes +nrow(iris_virginica1) == nrow(iris_virginica2) +``` + +Vous pouvez utiliser, dans les deux cas, tous les opérateurs vus dans les sections [-@sec-01351] et [-@sec-01353]. L'enjeu est d'arriver à créer un vecteur booléen final permettant d'identifier les observations à conserver. + +##### Sous-sélection des colonnes {#sec-014282} + +Nous avons déjà vu comment sélectionner des colonnes en utilisant leur nom ou leur index dans la [section @sec-014221]. Ajoutons ici un cas particulier où nous souhaitons sélectionner des colonnes selon une condition. Par exemple, nous pourrions vouloir conserver que les colonnes comprenant le mot *Length*. Pour cela, nous utilisons la fonction `grepl`, permettant de déterminer si des caractères sont présents dans une chaîne de caractères. + +```{r} +#| message: false +#| warning: false +nom_cols <- names(iris) +print(nom_cols) + +test_nom <- grepl("Length", nom_cols, fixed = TRUE) +ok_nom <- nom_cols[test_nom] + +iris_2 <- iris[ok_nom] +print(names(iris_2)) +``` + +Il est possible d'obtenir ce résultat en une seule ligne de code, mais elle est un peu moins lisible. + +```{r} +#| message: false +#| warning: false +iris2 <- iris[names(iris)[grepl("Length", names(iris), fixed = TRUE)]] +``` + +##### Sélection des colonnes et des lignes {#sec-014283} + +Nous avons vu qu'avec les crochets `[]`, nous pouvons extraire les colonnes et les lignes d'un *DataFrame*. Il est possible de combiner les deux opérations simultanément. Pour ce faire, il faut indiquer en premier les index ou la condition permettant de sélectionner une ligne, puis les index ou la condition pour sélectionner les colonnes : `[index_lignes , index_colonnes]`. Sélectionnons cinq premières lignes et les trois premières colonnes du jeu de données iris : + +```{r} +#| message: false +#| warning: false +iris_5x3 <- iris[c(1,2,3,4,5), c(1,2,3)] +print(iris_5x3) +``` + +Combinons nos deux exemples précédents pour sélectionner uniquement les lignes avec des fleurs de l'espèce *virginica*, et les colonnes avec le mot *Length*. + +```{r} +#| message: false +#| warning: false +iris_virginica3 <- iris[iris$Species == "virginica", + names(iris)[grepl("Length", names(iris), fixed = TRUE)]] +head(iris_virginica3, n=5) +``` + +#### Fusion de *DataFrames* {#sec-01429} + +Terminons cette section avec la fusion de *DataFrames*. Nous distinguons deux méthodes répondant à des besoins différents : par ajout ou par jointure. + +##### Fusion de *DataFrames* par ajout {#sec-014291} + +Ajouter deux *DataFrames* peut se faire en fonction de leurs colonnes ou en fonction de leurs lignes. Dans ces deux cas, nous utilisons respectivement les fonctions `cbind` et `rbind`. La @fig-fig016 résume graphiquement le fonctionnement des deux fonctions. + +![Fusion de DataFrames](images/Chap01/rbind_cbind.png){#fig-fig016 width="30%" fig-align="center"} + +Pour que `cbind` fonctionne, il faut que les deux *DataFrames* aient le même nombre de lignes. Pour `rbind`, les deux *DataFrames* doivent avoir le même nombre de colonnes. Prenons à nouveau comme exemple le jeu de données iris. Nous commençons par le séparer en trois sous-jeux de données comprenant chacun une espèce d'iris. Puis, nous fusionnons deux d'entre eux avec la fonction `rbind`. + +```{r} +#| message: false +#| warning: false +iris1 <- subset(iris, iris$Species == "virginica") +iris2 <- subset(iris, iris$Species == "versicolor") +iris3 <- subset(iris, iris$Species == "setosa") + +iris_comb <- rbind(iris2,iris3) +``` + +Nous pourrions aussi extraire dans les deux *DataFrames* les colonnes comprenant le mot *Length* et le mot *Width*, puis les fusionner. + +```{r} +#| message: false +#| warning: false +iris_l <- iris[names(iris)[grepl("Length", names(iris), fixed = TRUE)]] +iris_w <- iris[names(iris)[grepl("Width", names(iris), fixed = TRUE)]] + +iris_comb <- cbind(iris_l,iris_w) +names(iris_comb) +``` + +##### Jointure de *DataFrames* {#sec-014292} + +Une jointure est une opération un peu plus complexe qu'un simple ajout. L'idée est d'associer des informations de plusieurs *DataFrames* en utilisant une colonne (appelée une clef) présente dans les deux jeux de données. Nous distinguons plusieurs types de jointure : + +* Les jointures internes permettant de combiner les éléments communs entre deux *DataFrames* A **et** B. + +* La jointure complète permettant de combiner les éléments présents dans A **ou** B. + +* La jointure à gauche, permettant de ne conserver que les éléments présents dans A même s'ils n'ont pas de correspondance dans B. + +Ces trois jointures sont présentées à la @fig-fig017; pour ces trois cas, la colonne commune se nomme *id*. + + +![Jointure de DataFrames](images/Chap01/merging.png){#fig-fig017 width="30%" fig-align="center"} + +Vous retiendrez que les deux dernières jointures peuvent produire des valeurs manquantes. Pour réaliser ces opérations, nous utilisons la fonction `merge`. Prenons un exemple simple à partir d'un petit jeu de données. + +```{r} +#| message: false +#| warning: false +auteurs <- data.frame( + name = c("Tukey", "Venables", "Tierney", "Ripley", "McNeil", "Apparicio"), + nationality = c("US", "Australia", "US", "UK", "Australia", "Canada"), + retired = c("yes", rep("no", 5))) +livres <- data.frame( + aut = c("Tukey", "Venables", "Tierney", "Ripley", "Ripley", "McNeil" , "Wickham"), + title = c("Exploratory Data Analysis", + "Modern Applied Statistics ...", + "LISP-STAT", + "Spatial Statistics", "Stochastic Simulation", + "Interactive Data Analysis", "R for Data Science")) +``` + +Nous avons donc deux *DataFrames*, le premier décrivant des auteurs et le second des livres. Effectuons une première jointure interne afin de savoir pour chaque livre la nationnalité de son auteur et si ce dernier est à la retraite. + +```{r} +#| message: false +#| warning: false +df1 <- merge(livres, auteurs, #les deux DataFrames + by.x = "aut", by.y = "name", #les noms des colonnes de jointures + all.x = FALSE, all.y = FALSE) +print(df1) +``` + +Cette jointure est interne, car les deux paramètres *all.x* et *all.y* ont pour valeur `FALSE`. Ainsi, nous indiquons à la fonction que nous ne souhaitons ni garder tous les éléments du premier *DataFrame* ni tous les éléments du second, mais uniquement les éléments présents dans les deux. Vous noterez ainsi que le livre "R for Data Science" n'est pas présent dans le jeu de données final, car son auteur "Wickham" ne fait pas partie du *DataFrame* auteurs. De même, l'auteur "Apparicio" n'apparaît pas dans la jointure, car aucun livre dans le *DataFrame* books n'a été écrit par cet auteur. + +Pour conserver tous les livres, nous pouvons effectuer une jointure à gauche en renseignant `all.x = TRUE`. Nous forçons ainsi la fonction à garder tous les livres et à mettre des valeurs vides aux informations manquantes des auteurs. + +```{r} +#| message: false +#| warning: false +df2 <- merge(livres, auteurs, #les deux DataFrames + by.x = "aut", by.y = "name", #les noms des colonnes de jointures + all.x = TRUE, all.y = FALSE) +print(df2) +``` + +Pour garder tous les livres et tous les auteurs, nous pouvons faire une jointure complète en indiquant `all.x = TRUE` et `all.y = TRUE`. + +```{r} +#| message: false +#| warning: false +df3 <- merge(livres, auteurs, #les deux DataFrames + by.x = "aut", by.y = "name", #les noms des colonnes de jointures + all.x = TRUE, all.y = TRUE) +print(df3) +``` + +## Code R bien structuré {#sec-016} + +Terminons ici avec quelques conseils sur la rédaction d’un code R. Bien rédiger son code est essentiel pour trois raisons : + +1. Pouvoir relire et réutiliser son code dans le futur. +2. Permettre à d'autres personnes de bien lire et de réutiliser votre code. +3. Minimiser les risques d'erreurs. + +Ne négligez pas l'importance d'un code bien rédigé et bien documenté, vous vous éviterez ainsi des migraines lorsque vous devrez exhumer du code écrit il y a plusieurs mois. + +Voici quelques lignes directrices peu contraignantes, mais qui devraient vous être utiles : + +1. **Privilégier la clarté à la concision** : il vaut mieux parfois scinder une ligne de code en plusieurs sous-étapes afin de faciliter la lecture de l’opération réalisée. Par exemple, si nous reprenons une ligne de code d’une section précédente où nous sélectionnions l'ensemble des colonnes du jeu de données `iris` comprenant le mot `Length` : +```{r} +#| message: false +#| warning: false +iris_l <- iris[names(iris)[grepl("Length", names(iris), fixed = TRUE)]] +``` + +Nous pouvons simplifier la lecture de ce code en détaillant les différentes étapes comme suit : + +```{r} +#| message: false +#| warning: false +noms_cols <- names(iris) +sel_noms <- noms_cols[grepl("Length", noms_cols, fixed = TRUE)] +iris_l <- iris[sel_noms] +``` + +2. **Documenter et commenter son code le plus possible** : il est possible d'ajouter du texte dans un code R qui ne sera pas exécuté, ce que nous appelons des commentaires. Typiquement, une ligne commençant par un `#` n'est pas interprétée par le logiciel. Utilisez des commentaires le plus souvent possible pour décrire les actions que vous souhaitez effectuer avec votre code. Il sera ainsi plus facile de le relire, de naviguer dedans, mais également de repérer d'éventuelles erreurs. Si nous reprenons l'exemple précédent : + +```{r} +#| message: false +#| warning: false +# Récupération du nom des colonnes dans le DataFrame iris +noms_cols <- names(iris) +# Sélection des colonnes avec les caractères "Length" +sel_noms <- noms_cols[grepl("Length", noms_cols, fixed = TRUE)] +# Extraction des colonnes sélectionnées dans un nouveau DataFrame +iris_l <- iris[sel_noms] +``` + +3. **Éviter le code à rallonge…** : typiquement, essayez de vous limiter à des lignes de code d'une longueur maximale de 80 caractères. Au-delà de ce seuil, il est judicieux de découper votre code en plusieurs lignes. + +4. **Adopter une convention d'écriture** : une convention d'écriture est un ensemble de règles strictes définissant comment un code doit être rédigé. À titre d'exemple, il est parfois recommandé d'utiliser le *lowerCamelCase*, le *UpperCamelCase*, ou encore de séparer les mots par des tirets bas *upper_camel_case*. Un mélange de ces différentes conventions peut être utilisé pour distinguer les variables, les fonctions et les classes. Il peut être difficile de réellement arrêter une telle convention, car les différents *packages* dans R utilisent des conventions différentes. Dans vos propres codes, il est surtout important d'avoir une certaine cohérence et ne pas changer de convention. + +5. **Indenter le code** : l'indentation du code permet de le rendre beaucoup plus lisible. Indenter son code signifie d'insérer, au début de chaque ligne de code, un certain nombre d'espaces permettant d'indiquer à quel niveau de profondeur nous nous situons. Typiquement, lorsque des accolades ou des parenthèses sont ouvertes dans une fonction, une boucle ou une condition, nous rajoutons deux ou quatre espaces en début de ligne. Prenons un exemple très concret : admettons que nous écrivons une fonction affichant un résumé statistique à chaque colonne d'un jeu de données si cette colonne est de type numérique. L'indentation dans cette fonction joue un rôle crucial dans sa lisibilité. +Sans indentation et sans respecter la règle des 80 caractères, nous obtenons ceci : + +```{r} +#| message: false +#| warning: false +summary_all_num_cols <- function(dataset){for(col in names(dataset)){if(class(dataset[[col]] == "numeric")){print(summary(dataset[[col]]))}}} +``` + +Avec de l'indentation et des commentaires, la syntaxe est beaucoup plus lisible puisqu’elle permet de repérer facilement trois niveaux/paliers dans le code : + +```{r} +#| message: false +#| warning: false +# Définition d'une fonction +summary_all_num_cols <- function(dataset){ + # Itération sur chaque colonne de la fonction + for(col in names(dataset)){ + # A chaque itération, testons si la colonne est de type numérique + if(class(dataset[[col]] == "numeric")){ + # Si oui, nous affichons un résumé statistique pour cette colonne + print(summary(dataset[[col]])) + } # Ici nous sortons de la condition (niveau 3) + } # Ici nous sortons de la boucle (niveau 2) +} # Ici nous sortons de la fonction (niveau 1) +``` + +6. **Adopter une structure globale pour vos scripts** : un code R peut être comparé à une recette de cuisine. Si tous les éléments sont dans le désordre et sans structure globale, la recette risque d'être très difficile à suivre. Cette structure risque de changer quelque peu en fonction de la recette ou de l'auteur(e), mais les principaux éléments restent les mêmes. Dans un code R, nous pouvons distinguer plusieurs éléments récurrents que nous vous recommandons d'organiser de la façon suivante : + + a. Charger les différents *packages* **utilisés** par le script. Cela permet dès le début du code de savoir quelles sont les fonctions et méthodes qui seront employées dans le script. Cela limite aussi les risques d'oublier des *packages* qui seraient chargés plus loin dans le code. + + b. Définir les fonctions dont vous aurez besoin en plus de celles présentes dans les *packages.* Idem, placer nos fonctions en début de code évite d'oublier de les charger ou de les chercher quand nous en avons besoin. + + c. Définir le répertoire de travail avec la fonction `setwd` et charger les données nécessaires. + + d. Effectuer au besoin les opérations de manipulation sur les données. + + e. Effectuer les analyses nécessaires en scindant si possible les différentes étapes. Notez également que l'étape de définition des fonctions complémentaires peut être effectuée dans une feuille de code séparée, et l'ensemble de ces fonctions chargées à l'aide de la fonction `source`. De même, si la manipulation des données est conséquente, il est recommandé de l'effectuer avec un code à part, d'enregistrer les données structurées, puis de les charger directement au début de votre code dédié à l'analyse. + +7. **Exploiter les commentaires délimitant les sections dans RStudio** : il est possible d'écrire des commentaires d'une certaine façon pour que l'IDE les détecte comme des délimiteurs de sections. L'intérêt principal est que nous pouvons ensuite facilement naviguer entre ces sections en utilisant RStudio comme montré à la @fig-sectionsRstudio, mais aussi masquer des sections afin de faciliter la lecture du reste du code. Pour délimiter une section, il suffit d'ajouter une ligne de commentaire comprenant quatre fois les caractères `-`, `=` ou `#` à la suite. + + +```{r} +#| echo: true +#| eval: false + +# Voici ma section 1 ---------------------------------- + +# Voici ma section 2 ================================== + +# Voici ma section 3 ################################## + +# Autre exemple pour mieux marquer la rupture dans un code : + +#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#### Titre de ma section 4 #### +#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +``` + +![Navigation dans des sections de codes avec RStudio](images/Chap01/sections_rstudio.png){#fig-sectionsRstudio width="100%" fig-align="center"} + +8. **Adopter une structure globale pour vos projets** : au-delà du script, il est nécessaire de bien structurer vos projets, le plus important étant d'utiliser une structure commune à chaque projet pour vous faciliter le travail. Nous proposons à la @fig-structFolder un exemple de structure assez générale pouvant être utilisée dans la plupart des cas. Elle sépare notamment les données originales des données structurées, ainsi que les fonctions complémentaires et la structuration des données du principal bloc d'analyse. + + +![Structure de dossier recommandée pour un projet avec R](images/Chap01/structurationprojet.png){#fig-structFolder width="50%" fig-align="center"} + + +**Ne négligez jamais l'importance d'un code bien écrit et documenté !** + +## Enregistrement des résultats {#sec-017} + +Comme nous l'avons indiqué précédemment, l'ensemble des objets actuellement chargés dans votre session R sont perdus si vous la fermez. Cela peut être problématique si certains résultats nécessitent de longs temps de calcul ou si vous avez besoin de partager les objets obtenus avec d'autres personnes, mais pas le code pour les obtenir. Il est possible de retrouver les résultats d'une session précédente si ceux-ci ont été enregistrés sur votre disque dur puisque l'action d'enregistrer permet de faire passer vos objets présents dans votre mémoire vive dans des fichiers stockés sur votre disque dur. Vous pouvez pour cela utiliser la fonction `save.image` ou `save`. + +`save.image` enregistre une copie exacte de votre session actuelle avec tous les objets présents dans votre environnement dans un fichier `RData`. La fonction `save` permet d'être plus sélectif et de ne garder que certains objets spécifiques. + +Voici la syntaxe pour enregistrer toute votre session : + +```{r} +#| eval: false +save.image(file = 'chemin/vers/mon/fichier/session.RData', compress = TRUE) +``` + +Vous pouvez aussi utiliser le bouton d'enregistrement dans l'onglet *Environnement* dans RStudio (@fig-saveobj). + + +![Bouton enregistrer la session](images/Chap01/save_session.png){#fig-saveobj width="25%" fig-align="center"} + +Il est recommandé de compresser ces fichiers (`compress = TRUE`) pour minimiser leur taille. Pour n'enregistrer que certains objets (ici `iris` et `noms_cols`), vous pouvez adapter cette syntaxe : + +```{r} +#| eval: false +save(iris, noms_cols, file = 'chemin/vers/mon/fichier/mes_objet.RData', compress = TRUE) +``` + +Pour récupérer ces objets dans une autre session, il suffit d'utiliser la fonction `load` : + +```{r} +#| eval: false +load(file = 'chemin/vers/mon/fichier/mes_objet.RData') +``` + +ou d'utiliser le bouton *ouvrir* de l'onglet *Environnement* dans RStudio (@fig-loadobj). + +![Bouton charger un fichier RDA](images/Chap01/load_session.png){#fig-loadobj width="25%" fig-align="center"} + +## Session de travail {#sec-018} + +Comme vous avez pu le constater dans les sections @sec-017 et @sec-0141, il est nécessaire de connaître les chemins vers les fichiers que vous souhaitez utiliser dans votre code R. Si tous ces fichiers sont organisés dans un même dossier (ce que nous vous recommandons à la @fig-structFolder, il est possible de définir un répertoire de travail avec la fonction `setwd`. +Il est recommandé d'effectuer cette étape au début de votre code R, après le chargement des *packages*. Ainsi, vous n'aurez pas besoin de réécrire à chaque fois le chemin complet pour accéder à vos fichiers. + +```{r} +#| eval: false +# Chemin complet +mes_donnes <- read.csv("C:/projets/articles/2022/mon_projet/data/mes_donnes.csv") +# Utilisation de setwd +setwd("C:/projets/articles/2022/mon_projet") +mes_donnes <- read.csv("data/mes_donnes.csv") +``` + +La fonction `getwd` permet d'afficher le répertoire de travail utilisé actuellement par R. + +Si vous utilisez RStudio, il est possible d'utiliser une petite astuce pour définir comme répertoire de travail le dossier dans lequel se trouve le fichier de code R que vous utilisez actuellement : + +```{r} +#| eval: false +setwd(dirname(rstudioapi::getActiveDocumentContext()$path)) +``` + +Admettons que votre code R se trouve dans un sous dossier appelé *CodeR* de votre répertoire de travail, vous pouvez remonter d'un niveau dans votre arborescence en utilisant la syntaxe suivante : + +```{r} +#| eval: false +setwd(paste0(dirname(rstudioapi::getActiveDocumentContext()$path), "/..")) +``` + +Le double point (`..`) indique que nous souhaitons remonter dans le dossier parent du dossier dans lequel nous se trouvons acutellement. + +Il existe deux solutions de rechange à l'utilisation de `setwd` que certains jugent un peu démodé. + +* La première est le package `here` permettant de spécifier plus facilement des chemins relatifs et de définir un *top-level directory* pour votre projet. +* La seconde est l'utilisation de la fonctionnalité [projects](https://support.rstudio.com/hc/en-us/articles/200526207-Using-Projects) de RStudio. + +## Conclusion et ressources pertinentes {#sec-019} + +Voilà qui conclut ce chapitre sur les bases du langage R. Vous avez maintenant les connaissances nécessaires pour commencer à travailler. N'hésitez pas à revenir sur les différentes sous-sections au besoin! Quelques ressources pertinentes qui pourraient vous être utiles sont aussi reportées au @tbl-tableRessources + + +```{r} +#| label: tbl-tableRessources +#| tbl-cap: Ressources pertinente pour en apprendre plus sur R +#| echo: false +#| message: false +#| warning: false + +df <- data.frame( + Ressource = c("[Rbloggers](https://www.r-bloggers.com){target='_blank'}" , "[CRAN packages by date](https://cran.r-project.org/web/packages/available_packages_by_date.html){target='_blank'}", "[Introduction à R et au TidyVerse](https://juba.github.io/tidyverse/index.html){target='_blank'}", "[Numyard](https://www.youtube.com/user/TheLearnR/featured){target='_blank'}", "[cheatsheets](https://rstudio.com/resources/cheatsheets){target='_blank'}"), + Description = c("Un recueil de nombreux blogues sur R : parfait pour être tenu au courant des nouveautés et faire des découvertes.", "Les derniers packages publiés sur *CRAN* : cela permet de garder un oeil sur les nouvelles fonctionnalités de vos packages préférés.", "Une excellente ressource en français pour en apprendre plus sur le tidyverse.", "Une chaîne YouTube pour revoir les bases de R en vidéo.", "Des feuilles de triche résumant les fonctionnalités de nombreux packages.")) + +knitr::kable(df, + format.args = list(decimal.mark = ',', big.mark = " "), + col.names = c("Ressource" , "Description"), + col.to.resize = c(2,3), + col.width = "6cm") +``` + +## Quiz de révision du chapitre {#sec-0110} + +```{r} +#| label: quizChapitre01 +#| echo: false +#| warning: false +#| results: asis +source("code_complementaire/QuizzFunctions.R") +Chap01Quiz <- quizz("quiz/Chapitre1_manipulerdesdonnees.yml", "Chap01") +render_quizz(Chap01Quiz) +``` diff --git a/.Rproj.user/32A8B38A/sources/session-ce163101/lock_file b/.Rproj.user/32A8B38A/sources/session-ce163101/lock_file new file mode 100644 index 0000000..e69de29 diff --git a/.Rproj.user/shared/notebooks/0721ABFA-01-priseenmainR/1/32A8B38Ace163101/chunks.json b/.Rproj.user/shared/notebooks/0721ABFA-01-priseenmainR/1/32A8B38Ace163101/chunks.json new file mode 100644 index 0000000..97ca6d7 --- /dev/null +++ b/.Rproj.user/shared/notebooks/0721ABFA-01-priseenmainR/1/32A8B38Ace163101/chunks.json @@ -0,0 +1 @@ +{"chunk_definitions":[],"doc_write_time":1720219098} \ No newline at end of file diff --git a/.Rproj.user/shared/notebooks/0721ABFA-01-priseenmainR/1/s/chunks.json b/.Rproj.user/shared/notebooks/0721ABFA-01-priseenmainR/1/s/chunks.json new file mode 100644 index 0000000..97ca6d7 --- /dev/null +++ b/.Rproj.user/shared/notebooks/0721ABFA-01-priseenmainR/1/s/chunks.json @@ -0,0 +1 @@ +{"chunk_definitions":[],"doc_write_time":1720219098} \ No newline at end of file diff --git a/.Rproj.user/shared/notebooks/patch-chunk-names b/.Rproj.user/shared/notebooks/patch-chunk-names new file mode 100644 index 0000000..e69de29 diff --git a/.Rproj.user/shared/notebooks/paths b/.Rproj.user/shared/notebooks/paths new file mode 100644 index 0000000..da201d2 --- /dev/null +++ b/.Rproj.user/shared/notebooks/paths @@ -0,0 +1 @@ +C:/Users/appariciop/OneDrive - USherbrooke/Articles Publies ne pas supprimer/_Livres/BolR_MethodesQuantitatives/01-priseenmainR.qmd="0721ABFA" diff --git a/.quarto/_freeze/01-priseenmainR/execute-results/html.json b/.quarto/_freeze/01-priseenmainR/execute-results/html.json new file mode 100644 index 0000000..c1fdb7b --- /dev/null +++ b/.quarto/_freeze/01-priseenmainR/execute-results/html.json @@ -0,0 +1,16 @@ +{ + "hash": "03fd61bd51504a1c37d989e5bad12bc4", + "result": { + "markdown": "# Prise en main de R {#sec-chap01}\n\nDans ce chapitre, nous revenons brièvement sur l’histoire de R et la philosophie qui entoure le logiciel. Nous donnons quelques conseils pour son installation et la mise en place d’un environnement de développement. Nous présentons les principaux objets qui sous-tendent le travail effectué avec R (*DataFrame*, vecteur, matrice, etc.) et comment les manipuler avec des exemples appliqués. Si vous maîtrisez déjà R, nullement besoin de lire ce chapitre!\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n* Pour importer des fichiers externes :\n - `foreign` pour entre autres les fichiers *dbase* et ceux des logiciels SPSS et Stata.\n - `sas7bdat` pour les fichiers du logiciel SAS.\n - `xlsx` pour les fichiers Excel.\n* Pour manipuler des chaînes de caractères et des dates : \n - `stringr` pour les chaînes de caractères.\n - `lubridate` pour les dates.\n* Pour manipuler des données :\n - `dplyr` du `tidyverse` propose une grammaire pour manipuler et structurer des données.\n:::\n:::\n\n\n## Histoire et philosophie de R{#sec-011}\n\nR est à la fois un langage de programmation et un logiciel libre (sous la licence publique générale GNU) dédié à l'analyse statistique et soutenu par une fondation : _R Foundation for Statistical Computing_. Il est principalement écrit en C et en Fortran, deux langages de programmation de « bas niveau », proches du langage machine. À l'inverse, R est un langage de « haut niveau », car plus proche du langage humain.\n\n\nR a été créé par Ross Ihaka et Robert Gentleman à l'Université d'Auckland en Nouvelle-Zélande. Si vous avez un jour l'occasion de passer dans le coin, une plaque est affichée dans le département de statistique de l'université; ça mérite le détour (@fig-Plaque). Une version expérimentale a été publiée en 1996, mais la première version stable ne date que de 2000. Il s'agit donc d'un logiciel relativement récent si nous le comparons à ses concurrents SPSS (1968), SAS (1976) et Stata (1984).\n\n\n![Lieu de pèlerinage de R](images/Chap01/plaque.jpg){#fig-Plaque width=\"40%\" fig-align=\"center\"}\n\n\nR a cependant réussi à s'imposer tant dans le milieu de la recherche que dans le secteur privé. Pour s'en convaincre, il suffit de lire l'excellent article concernant la popularité des logiciels d'analyse de données tiré du site [r4stats.com](http://r4stats.com/articles/popularity){target=\"_blank\"} (@fig-ArticlesR).\n\n![Nombre d'articles trouvés sur Google Scholar (source : Robert A. Muenchen)](images/Chap01/r_citations.jpg){#fig-ArticlesR width=\"50%\" fig-align=\"center\"}\n\nLes nombreux atouts de R justifient largement sa popularité sans cesse croissante : \n\n* R est un logiciel à code source ouvert (*open source*) et ainsi accessible à tous gratuitement.\n\n* Le développement du langage R est centralisé, mais la communauté peut créer et partager facilement des *packages*. Les nouvelles méthodes sont ainsi rapidement implémentées comparativement aux logiciels propriétaires.\n\n* R est un logiciel multiplateforme, fonctionnant sur Linux, Unix, Windows et Mac.\n\n* Comparativement à ses concurrents, R dispose d'excellentes solutions pour manipuler des données et réaliser des graphiques.\n\n* R dispose de nombreuses interfaces lui permettant de communiquer, notamment avec des systèmes de bases de données SQL et non SQL (MySQL, PostgresSQL, MongoDB, etc.), avec des systèmes de *big data* (Spark, Hadoop), avec des systèmes d'information géographique (QGIS, ArcGIS) et même avec des services en ligne comme Microsoft Azure ou Amazon AWS.\n\n* R est un langage de programmation à part entière, ce qui lui donne plus de flexibilité que ses concurrents commerciaux (SPSS, SAS, STATA). Avec R, vous pouvez accomplir de nombreuses tâches : monter un site web, créer un robot collectant des données en ligne, combiner des fichiers PDF, composer des diapositives pour une présentation ou même éditer un livre (comme celui-ci), mais aussi, et surtout, réaliser des analyses statistiques.\n\nUn des principaux attraits de R est la quantité astronomique de *packages* actuellement disponibles. **Un *package* est un ensemble de nouvelles fonctionnalités développées par des personnes utilisatrices de R et mises à disposition de l'ensemble de la communauté**. Par exemple, le *package* `ggplot2` est dédié à la réalisation de graphiques; les *packages* `data.table` et `dplyr` permettent de manipuler des tableaux de données; le *package* `car` offre de nombreux outils pour faciliter l'analyse de modèles de régressions, etc. Ce partage de *packages* rend accessible à tous des méthodes d'analyses complexes et récentes et favorise grandement la reproductibilité de la recherche. Cependant, ce fonctionnement implique quelques désavantages : \n\n* Il existe généralement plusieurs *packages* pour effectuer le même type d'analyse, ce qui peut devenir une source de confusion.\n\n* Certains *packages* cessent d'être mis à jour au fil des années, ce qui nécessite de trouver des solutions de rechange (et ainsi apprendre la syntaxe de nouveaux *packages*).\n\n* Il est impératif de s'assurer de la fiabilité des *packages* que vous souhaitez utiliser, car n'importe qui peut proposer un *package*.\n\nIl nous semble important de relativiser d'emblée la portée du dernier point. Il est rarement nécessaire de lire et d'analyser le code source d'un *package* pour s'assurer de sa fiabilité. Nous ne sommes pas des spécialistes de tous les sujets et il peut être extrêmement ardu de comprendre la logique d'un code écrit par une autre personne. Nous vous recommandons donc de privilégier l'utilisation de *packages* qui :\n\n* ont fait l'objet d'une publication dans une revue à comité de lecture ou qui ont déjà été cités dans des études ayant fait l'objet d'une publication revue par les pairs;\n\n* font partie de projets comme [ROpensci](https://ropensci.org/){target=\"_blank\"} prônant la vérification par les pairs ou subventionnés par des organisations comme [R Consortium](https://www.r-consortium.org/){target=\"_blank\"};\n\n* sont disponibles sur l'un des deux principaux répertoires de *packages* R, soit [CRAN](https://cran.r-project.org/){target=\"_blank\"} et [Bioconductor](https://www.bioconductor.org/){target=\"_blank\"}.\n\nToujours pour nuancer notre propos, il convient de distinguer *package* de *package*! Certains d'entre eux sont des ensembles très complexes de fonctions permettant de réaliser des analyses poussées alors que d'autres sont des projets plus modestes dont l'objectif principal est de simplifier le travail des personnes utilisant R. Ces derniers ressemblent à de petites boîtes à outils et font généralement moins l'objet d'une vérification intensive.\n\nPour conclure cette section, l'illustration partagée sur Twitter par Darren L Dahly résume avec humour la force du logiciel R et de sa communauté\n(@fig-fig03) : R apparaît clairement comme une communauté hétéroclite, mais diversifiée et adaptable.\n\n\n![Métaphore sur les langages et programmes d'analyse statistique](images/Chap01/softwares_and_cars.jpeg){#fig-fig03 width=\"60%\" fig-align=\"center\"}\n\n\nDans ce livre, nous détaillons les *packages* utilisés dans chaque section avec un encadré spécifique.\n\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n\n**Bloc *packages***\n:::\n\n::: bloc_package-body\nHabituellement localisé au début d'un chapitre, il comprend la liste des *packages* R utilisés pour un chapitre.\n:::\n:::\n\n\n## Environnement de travail{#sec-012}\n\nDans cette section, nous vous proposons une visite de l'environnement de travail de R.\n\n### Installation de R {#sec-0121}\n\nLa première étape pour travailler avec R est bien sûr de l'installer. Pour cela, il suffit de visiter le site web de [CRAN](https://cran.r-project.org/){target=\"_blank\"} et de télécharger la dernière version de R en fonction de votre système d'exploitation : Windows, Linux ou Mac. Une fois installé, si vous démarrez R immédiatement, vous aurez accès à une console, plutôt rudimentaire, attendant sagement vos instructions (@fig-fig05).\n\n![Console de base de R](images/Chap01/r_console.jpeg){#fig-fig05 width=\"85%\" fig-align=\"center\"}\n\nNotez que vous pouvez aussi télécharger des versions plus anciennes de R en allant sur ce [lien](https://cran.r-project.org/bin/windows/base/old/){target=\"_blank\"}. Cela peut être intéressant lorsque vous voulez reproduire des résultats d'une autre étude ou que certains *packages* ne sont plus disponibles dans les nouvelles versions.\n\n### Environnement RStudio{#sec-0122}\n\nRares sont les adeptes de R qui préfèrent travailler directement avec la console classique. Nous vous recommandons vivement d'utiliser RStudio, un environnement de développement (*IDE*) dédié à R offrant une intégration très intéressante d'une console, d'un éditeur de texte, d'une fenêtre de visualisation des données et d'une autre pour les graphiques, d'un accès à la documentation, etc. En d'autres termes, si R est un vélo minimaliste, RStudio permet d'y rajouter des freins, des vitesses, un porte-bagages, des garde-boues et une selle confortable. Vous pouvez [télécharger](https://rstudio.com/products/rstudio/download){target=\"_blank\"} et installer RStudio sur Windows, Linux et Mac. La version de base est gratuite, mais l'entreprise qui développe ce logiciel propose aussi des versions commerciales du logiciel qui assurent essentiellement une assistance technique. Il existe d'autres environnements de développement pour travailler avec R (Visual Studio Code, Jupyter, Tinn-R, Radiant, RIDE, etc.), mais RStudio offre à ce jour la meilleure option en termes de facilité d'installation, de prise en main et de fonctionnalités proposées (voir l'interface de RStudio à la @fig-fig06).\n\n\n![Environnement de base de RStudio](images/Chap01/r_studio_01.jpeg){#fig-fig06 width=\"85%\" fig-align=\"center\"}\n\nAvant d'aller plus loin, notez que : \n\n* La console actuellement ouverte dans RStudio vous informe de la version de R que vous utilisez. Vous pouvez en effet avoir plusieurs versions de R installées sur votre ordinateur et passer de l'une à l'autre avec RStudio. Pour cela, naviguez dans l'onglet *Tools/Global Options* et dans le volet *General*, puis sélectionnez la version de R que vous souhaitez utiliser.\n\n* L'aspect de RStudio peut être modifié en naviguant dans l'onglet *Tools/Global Options* et dans le volet *Appearance*. Nous avons une préférence pour le mode sombre avec le style *pastel on dark* (@fig-fig07), mais libre à vous de choisir le style qui vous convient.\n\n\n![RStudio avec le style pastel on dark](images/Chap01/r_studio_02.jpeg){#fig-fig07 width=\"85%\" fig-align=\"center\"}\n\nUne fois ces détails réglés, vous pouvez ouvrir votre première feuille de code en allant dans l'onglet *File/New File/R Script*. Votre environnement est maintenant découpé en quatre fenêtres (@fig-fig08) : \n\n1. L'éditeur de code, vous permettant d'écrire le script que vous voulez exécuter et de garder une trace de votre travail. Ce script peut être enregistré sur votre ordinateur avec l'extension **.R**, mais ce n'est qu'un simple fichier texte.\n\n2. La console vous permettant d'exécuter votre code R et de voir les résultats s'afficher au fur et à mesure.\n\n3. La fenêtre d'environnement vous montrant les objets, les fonctions et les jeux de données actuellement disponibles dans votre session (chargés dans la mémoire vive).\n\n4. La fenêtre de l'aide, des graphiques et de l'explorateur de fichiers. Vous pouvez accéder ici à la documentation de R et des *packages* que vous utilisez, aux sorties graphiques que vous produisez et aux dossiers de votre environnement de travail.\n\n\n![Fenêtres de RStudio](images/Chap01/r_studio_03.jpeg){#fig-fig08 width=\"85%\" fig-align=\"center\"}\n\nPrenons un bref exemple : tapez la syntaxe suivante dans l'éditeur de code (fenêtre 1 à la @fig-fig08) : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nma_somme <- 4+4\n```\n:::\n\n\nSélectionnez ensuite cette syntaxe (mettre en surbrillance avec la souris) et utilisez le raccourci *Ctrl+Entrée* ou cliquez sur le bouton *Run* (avec la flèche verte) pour envoyer cette syntaxe à la console qui l'exécutera immédiatement. Notez que rien ne se passe tant que le code n'est pas envoyé à la console. Il s'agit donc de deux étapes distinctes : écrire son code, puis l'envoyer à la console. Constatez également qu'un objet *ma_somme* est apparu dans votre environnement et que sa valeur est bien 8. Votre console se « souvient » de cette valeur : elle est actuellement stockée dans votre mémoire vive sous le nom de *ma_somme* (@fig-fig09).\n\n\n![Exécuter du code dans RStudio](images/Chap01/r_studio_04.jpeg){#fig-fig09 width=\"85%\" fig-align=\"center\"}\n\nPour conclure cette section, nous vous invitons à enregistrer votre première syntaxe R (*File/Save As*) dans un fichier **.R** que vous pouvez appeler `mon_premier_script.R` par exemple. Fermez ensuite RStudio, redémarrez-le et ouvrez (*File/Open File*) votre fichier `mon_premier_script.R`. Vous pouvez constater que votre code est toujours présent, mais que votre environnement est vide tant que vous n'exécutez pas votre syntaxe. En effet, lorsque vous fermez RStudio, l'environnement est vidé pour libérer de la mémoire vive. Cela peut poser problème lorsque certains codes sont très longs à exécuter, nous verrons donc plus tard comment enregistrer l'environnement en cours pour le recharger par la suite.\n\n\n### Installation et chargement un *package*{#sec-0123}\n\nDans la section sur la Philosophie de R, nous avons souligné la place centrale jouée par les *packages*. Notez que les termes *paquet* et plus rarement *librairie* sont parfois utilisés en français. Voyons ensemble comment installer un *package*, par exemple celui intitulé `lubridate`, qui nous permettra plus tard de manipuler des données temporelles.\n\n#### Installation d'un *package* depuis *CRAN*{#sec-01231}\n\nPour installer un *package*, il est nécessaire d'être connecté à Internet puisque R va accéder au répertoire de *packages* *CRAN* pour télécharger le *package* et l'installer sur votre machine. Cette opération est réalisée avec la fonction `install.packages`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ninstall.packages(\"lubridate\")\n```\n:::\n\n\nNotez qu'une fois que le *package* est installé, il demeure disponible localement sur votre ordinateur, à moins de le désinstaller explicitement avec la fonction `remove.packages`.\n\n#### Installation d'un *package* depuis GitHub{#sec-01232}\n\n*CRAN* est le répertoire officiel des *packages* de R. Vous pouvez cependant télécharger des *packages* provenant d'autres sources. Très souvent, les *packages* sont disponibles sur le site web [GitHub](https://github.com/){target=\"_blank\"} et nous pouvons même y trouver des versions en développement avec des fonctionnalités encore non intégrées dans la version sur *CRAN*. Reprenons le cas de `lubridate`, mais sur GitHub (il est disponible [ici](https://github.com/tidyverse/lubridate){target=\"_blank\"}). Pour l'installer, nous devons d'abord installer un autre *package* appelé `remotes` (depuis *CRAN*).\n\n\n::: {.cell}\n\n```{.r .cell-code}\ninstall.packages(\"remotes\")\n```\n:::\n\n\nMaintenant que nous disposons de `remotes`, nous pouvons utiliser la fonction d'installation `remotes::install_github` pour directement télécharger `lubridate` depuis GitHub.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nremotes::install_github(\"tidyverse/lubridate\")\n```\n:::\n\n\n#### Chargement d'un *package* {#sec-01233}\n\nMaintenant que `lubridate` est installé, nous pouvons le charger dans notre session actuelle de R et accéder aux fonctions qu'il propose. Pour cela, il suffit d'utiliser la fonction `library`. Conventionnellement, l'appel des *packages* se fait au tout début du script que vous rédigez. Rien ne vous empêche de le faire au fur et à mesure de votre code, mais ce dernier perd alors en lisibilité. Notez que pour chaque nouvelle session (redémarrage de R), il faut recharger les *packages* dont vous avez besoin avec la fonction `library`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(lubridate)\n```\n:::\n\n\nSi vous obtenez un message d'erreur du type : \n\n`Error in library(monPackage) : aucun package nommé ‘monPackage’ n'est trouvé`\n\nCela signifie que le *package* que vous tentez de charger n'est pas encore installé sur votre ordinateur. Dans ce cas, réessayer de l'installer avec la fonction `install.packages`. Si le problème persiste, vérifiez que vous n'avez pas fait une faute de frappe dans le nom du *package.* Vous pouvez également redémarrer RStudio et réessayer d'installer ce *package*.\n\n### Aide disponible\n\nLorsque vous installez des *packages* dans R, vous téléchargez aussi leur documentation. Tous les *packages* de *CRAN* disposent d'une documentation, ce qui n'est pas forcément vrai pour ceux sur *GitHub*. Dans RStudio, vous pouvez accéder à la documentation des *packages* dans l'onglet **Packages** (@fig-fig010). Vous pouvez utiliser la barre de recherche pour retrouver rapidement un *package* installé. Si vous cliquez sur le nom du *package*, vous accédez directement à sa documentation dans cette fenêtre.\n\n\n![Description des packages](images/Chap01/rstudio_packages.jpeg){#fig-fig010 width=\"45%\" fig-align=\"center\"}\n\nVous pouvez également accéder à ces informations en utilisant la syntaxe suivante dans votre console : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nhelp(package = 'lubridate')\n```\n:::\n\n\nSouvent, vous aurez besoin d'accéder à la documentation d'une fonction spécifique d'un *package*. Affichons la documentation de la fonction `now` de `lubridate` : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nhelp(now, package = 'lubridate')\n```\n:::\n\n\nou plus simplement :\n\n::: {.cell}\n\n```{.r .cell-code}\n?lubridate::now\n```\n:::\n\n\nVous pouvez aussi utiliser le raccourci suivant.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n?now\n```\n:::\n\n\nSi vous ne vous souvenez plus à quel *package* la fonction appartient, lancez une recherche en utilisant un double point d'interrogation : \n\n\n::: {.cell}\n\n```{.r .cell-code}\n??now\n```\n:::\n\n\nVous découvrirez ainsi que la fonction `now` n'existe pas que dans `lubridate`, ce qui souligne l'importance de bien connaître les *packages* que nous installons et que nous chargeons dans notre session ! \n\nMaintenant que nous avons fait le tour de l'environnement de travail, nous pouvons passer aux choses sérieuses, soit les bases du langage R.\n\n## Bases du langage R {#sec-013}\n\nR est un langage de programmation. Il vous permet de communiquer avec votre ordinateur pour lui donner des tâches à accomplir. Dans cette section, nous abordons les bases du langage. Ce type de section introductive à R est présente dans tous les manuels sur R; elle est donc incontournable. À la première lecture, elle vous semblera probablement aride, et ce, d'autant plus que nous ne réalisons pas d'analyse à proprement parler. Gardez en tête que l'analyse de données requiert au préalable une phase de structuration de ces dernières, opération qui nécessite la maîtrise des notions abordées dans cette section. Nous vous recommandons une première lecture de ce chapitre pour comprendre les manipulations que vous pouvez effectuer avec R, avant de poursuivre avec de la lecture des chapitres suivants dédiés aux analyses statistiques. Vous pourrez revenir consulter cette section au besoin. Notez aussi que la maîtrise des différents objets et des différentes opérations de base de R ne s’acquiert qu'en pratiquant. Vous gagnerez cette expertise au fil de vos prochains codes R, période durant laquelle vous pourrez consulter ce chapitre tel un guide de référence des objets et des notions fondamentales de R.\n\n\n### *Hello World*! {#sec-0131}\n\nUne introduction à un langage de programmation se doit de commencer par le rite de passage *Hello World*. Il s'agit d'une forme de tradition consistant à montrer aux néophytes comment afficher le message `Hello World` à l'écran avec le langage en question.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nprint(\"Hello World\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"Hello World\"\n```\n:::\n:::\n\n\nBravo! Vous venez officiellement de faire votre premier pas dans R!\n\n### Objets et expressions {#sec-0132}\n\nDans R, nous passons notre temps à manipuler des **objets** à l'aide d'**expressions**. Prenons un exemple concret : si vous tapez la syntaxe `4 + 3`, vous manipulez deux objets (4 et 3) avec une expression indiquant que vous souhaitez obtenir la somme des deux objets.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n4 + 3\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 7\n```\n:::\n:::\n\n\nCette expression est correcte, R comprend vos indications et effectue le calcul.\n\nIl est possible d'enregistrer le résultat d'une expression et de le conserver dans un nouvel objet. On appelle cette opération : « déclarer une variable ».\n\n\n::: {.cell}\n\n```{.r .cell-code}\nma_somme <- 4 + 3\n```\n:::\n\n\nConcrètement, nous venons de demander à R d'enregistrer le résultat de `4 + 3` dans un espace spécifique de notre mémoire vive. Si vous regardez dans votre fenêtre **Environment**, vous verrez en effet qu'un objet appelé ma_somme est actuellement en mémoire et a pour valeur 7.\n\nNotez ici que le nom des variables ne peut être composé que de lettres, de chiffres, de points (.) et de tirets bas (_) et doit commencer par une lettre. R est sensible à la casse; en d'autres termes, les variables `Ma_somme`, `ma_sommE`, `ma_SOMME`, et `MA_SOMME` renvoient toutes à un objet différent. Attention donc aux fautes de frappe. Si vous déclarez une variable en utilisant le nom d'une variable existante, la première est écrasée par la seconde : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nage <- 35\nage\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 35\n```\n:::\n\n```{.r .cell-code}\nage <- 45\nage\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 45\n```\n:::\n:::\n\n\nPortez alors attention aux noms de variables que vous utilisez et réutilisez. Réutilisons notre objet `ma_somme` dans une nouvelle expression : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nma_somme2 <- ma_somme + ma_somme\n```\n:::\n\n\nAvec cette nouvelle expression, nous indiquons à R que nous souhaitons déclarer une nouvelle variable appelée `ma_somme2`, et que cette variable aura pour valeur `ma_somme + ma_somme`, soit `7 + 7`. Sans surprise, `ma_somme2` a pour valeur 14.\n\nNotez que la mémoire vive (l'environnement) est vidée lorsque vous fermez R. Autrement dit, R perd complètement la mémoire lorsque vous le fermez. Vous pouvez bien sûr recréer vos objets en relançant les mêmes syntaxes. C'est pourquoi vous devez conserver vos feuilles de codes et ne pas seulement travailler dans la console. La console ne garde aucune trace de votre travail. Pensez donc à bien enregistrer votre code!\n\nNous verrons dans une prochaine section comment sauvegarder des objets et les recharger dans une session ultérieure de R ([section @sec-017]). Ce type d'opération est pertinent quand le temps de calcul nécessaire à la production de certains objets est très long.\n\n### Fonctions et arguments {#sec-0_133}\n\nDans R, nous manipulons le plus souvent nos objets avec des **fonctions**. Une fonction est elle-même un objet, mais qui a la particularité de pouvoir effectuer des opérations sur d'autres objets. Par exemple, déclarons l'objet `taille` avec une valeur de 175,897 : \n\n\n::: {.cell}\n\n```{.r .cell-code}\ntaille <- 175.897\n```\n:::\n\n\nNous utilisons la fonction `round`, dont l'objectif est d'arrondir un nombre avec décimales pour obtenir un nombre entier.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nround(taille)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 176\n```\n:::\n:::\n\n\nPour effectuer leurs opérations, les fonctions ont généralement besoin d'**arguments**. Ici, `taille` est un argument passé à la fonction `round`. Si nous regardons la documentation de `round` avec `help(round)` (@fig-fig011), nous constatons que cette fonction prend en réalité deux arguments : *x* et *digits*. Le premier est le nombre que nous souhaitons arrondir et le second est le nombre de décimales à conserver. Nous pouvons lire dans la documentation que la valeur par défaut de *digits* est 0, ce qui explique que `round(taille)` a produit le résultat de 176.\n\n\n![Arguments de la fonction `round`](images/Chap01/help_round.jpeg){#fig-fig011 width=\"35%\" fig-align=\"center\"}\n\nRéutilisons maintenant la fonction `round`, mais en gardant une décimale : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nround(taille, digits = 1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 175.9\n```\n:::\n:::\n\n\nIl est aussi possible que certaines fonctions ne requièrent pas d'argument. Par exemple, la fonction `now` indique la date précise (avec l'heure) et n'a besoin d'aucun argument pour le faire : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nnow()\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"2024-07-05 18:38:42 EDT\"\n```\n:::\n:::\n\n\nPar contre, si nous essayons de lancer la fonction `round` sans argument, nous obtenons une erreur :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nround()\n```\n:::\n\n\n`Erreur : 0 argument passé à 'round' qui en exige 1 ou 2`\n\nLe message est très clair, `round` a besoin d'au moins un argument pour fonctionner. Si, au lieu d'un nombre, nous avions donné du texte à la fonction `round`, nous aurions aussi obtenu une erreur : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nround(\"Hello World\")\n```\n:::\n\n\n`Erreur dans round(\"Hello World\") : argument non numérique pour une fonction mathématique`\n\nÀ nouveau le message est très explicite : nous avons passé un argument non numérique à une fonction mathématique. Lisez toujours vos messages d'erreurs : ils permettent de repérer les coquilles et de corriger votre code!\n\nNous terminons cette section avec une fonction essentielle, `print`, qui permet d'afficher la valeur d'une variable.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nprint(ma_somme)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 7\n```\n:::\n:::\n\n\n\n### Principaux types de données {#sec-0134}\n\nDepuis le début de ce chapitre, nous avons déclaré plusieurs variables et essentiellement des données numériques. Dans R, il existe trois principaux types de données de base : \n\n* Les données numériques qui peuvent être des nombres entiers (appelés *integers*) ou des nombres décimaux (appelés *floats* ou *doubles*), par exemple `15` et `15.3`.\n\n* Les données de type texte qui sont des chaînes de caractères (appelées *strings*) et déclarées entre guillemets `\"abcdefg\"`.\n\n* Les données booléennes (*booleans*) qui peuvent n'avoir que deux valeurs : vrai (`TRUE`) ou faux (`FALSE`).\n\nDéclarons une variable pour chacun de ces types : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nage <- 35\ntaille <- 175.5\nadresse <- '4225 rue de la gauchetiere'\nproprietaire <- TRUE\n```\n:::\n\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Simples ou doubles quotes?**\n:::\n::: bloc_notes-body\nPour déclarer des données de type texte, il est possible d'utiliser des quotes simples `'` (apostrophe) ou des quotes doubles `\"` (guillemets), cela ne fait aucune différence pour R. Cependant, si la chaîne de caractères que vous créez contient une apostrophe, il est nécessaire d'utiliser des quotes doubles et inversement si votre chaîne de caractère contient des guillemets.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nphrase1 <- \"J'adore le langage R!\"\nphrase2 <- 'Je cite : \"il est le meilleur langage de statistique\".'\n```\n:::\n\n\nSi la chaîne de caractère contient des guillemets et des apostrophes, il est nécessaire d'utiliser la barre oblique inversée `\\` pour indiquer à R que ces apostrophes ou ces guillemets ne doivent pas être considérés comme la fin de la chaîne de caractère.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nphrase3 <- \"Je cite : \\\"j'en rêve la nuit\\\".\"\ncat(phrase3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nJe cite : \"j'en rêve la nuit\".\n```\n:::\n:::\n\n\nLes barres obliques inversées ne font pas partie de la chaîne de caractère, ils sont là pour \"échapper\" les guillemets qui doivent rester dans la chaîne de caractère. Si une chaîne de caractère doit contenir une barre oblique inversée, alors il faut l'échapper également en utilisant une deuxième barre oblique inversée.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nphrase4 <- \"Une phrase avec une barre oblique inversée : \\\\\"\ncat(phrase4)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nUne phrase avec une barre oblique inversée : \\\n```\n:::\n:::\n\nFaites attention à la coloration syntaxique de RStudio! Elle peut vous aider à repérer facilement une chaîne de caractère qui aurait été interrompue par un guillemet ou une apostrophe mal placés.\n:::\n:::\n\nSi vous avez un doute sur le type de données stockées dans une variable, vous pouvez utiliser la fonction `typeof`. Par exemple, cela permet de repérer si des données qui sont censées être numériques sont en fait stockées sous forme de texte comme dans l'exemple ci-dessous.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ntypeof(age)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"double\"\n```\n:::\n\n```{.r .cell-code}\ntypeof(taille)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"double\"\n```\n:::\n\n```{.r .cell-code}\n# Ici tailletxt est définie comme une chaîne de caractère car la valeur est \n# définie entre des guillemets.\ntailletxt <- \"175.5\"\ntypeof(tailletxt)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"character\"\n```\n:::\n:::\n\n\n\nNotez également qu'il existe des types pour représenter l'absence de données : \n\n* pour représenter un objet vide, nous utilisons l'objet `NULL`,\n\n* pour représenter une donnée manquante, nous utilisons l'objet `NA`,\n\n* pour représenter un texte vide, nous utilisons une chaîne de caractère de longueur 0, soit `\"\"`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nage2 <- NULL\ntaille2 <- NA\nadresse2 <- ''\n```\n:::\n\n\n### Opérateurs {#sec-0135}\n\nNous avons vu que les fonctions permettent de manipuler des objets. Nous pouvons également effectuer un grand nombre d'opérations avec les opérateurs.\n\n#### Opérateurs mathématiques {#sec-01351}\n\nLes opérateurs mathématiques (@tbl-OperateurMath) permettent d'effectuer des calculs avec des données de type numérique.\n\n\n::: {#tbl-OperateurMath .cell tbl-cap='Opérateurs mathématiques'}\n::: {.cell-output-display}\n|Opérateur |Description |Syntaxe | Résultat|\n|:---------|:-----------------|:------------|--------:|\n|`+` |Addition |`4 + 4` | 8,0|\n|`-` |Soustraction |`4 - 3` | 1,0|\n|`*` |Multiplication |`4 * 3` | 12,0|\n|`/` |Division |`12 / 4` | 3,0|\n|`^` |Exponentiel |`4 ^ 3` | 64,0|\n|`**` |Exponentiel |`4 ** 3` | 64,0|\n|`%%` |Reste de division |`15,5 %% 2` | 1,5|\n|`%/%` |Division entière |`15,5 %/% 2` | 7,0|\n:::\n:::\n\n\n#### Opérateurs relationnels {#sec-01352}\n\nLes opérateurs relationnels (@tbl-OperateurRelationnels) permettent de vérifier des conditions dans R. Ils renvoient un booléen, `TRUE` si la condition est vérifiée et `FALSE` si ce n'est pas le cas.\n\n\n::: {#tbl-OperateurRelationnels .cell tbl-cap='Opérateurs relationnels'}\n::: {.cell-output-display}\n|Opérateur |Description |Syntaxe |Résultat |\n|:---------|:---------------------|:--------|:--------|\n|`==` |Égalité |`4 == 4` |TRUE |\n|`!=` |Différence |`4 != 4` |FALSE |\n|`>` |Est supérieur |`5 > 4` |TRUE |\n|`<` |Est inférieur |`5 < 4` |FALSE |\n|`>=` |Est supérieur ou égal |`5 >= 4` |TRUE |\n|`<=` |Est inférieur ou égal |`5 <= 4` |FALSE |\n:::\n:::\n\n\n#### Opérateurs logiques {#sec-01353}\n\nLes opérateurs logiques (@tbl-tableOperateurLogi) permettent de combiner plusieurs conditions :\n\n* L'opérateur **ET** (`&`) permet de vérifier que deux conditions (l'une ET l'autre) sont TRUE. Si l'une des deux est FALSE, il renvoie FALSE.\n\n* L'opérateur **OU** (`|`) permet de vérifier que l'une des deux conditions est TRUE (l'une OU l'autre). Si les deux sont FALSE, alors il renvoie FALSE.\n\n* L'opérateur **NOT** (`!`) permet d'inverser une condition. Ainsi, NOT TRUE donne FALSE et NOT FALSE donne TRUE.\n\n\n\n::: {#tbl-tableOperateurLogi .cell tbl-cap='Opérateurs logiques'}\n::: {.cell-output-display}\n|Opérateur |Description |Syntaxe |Résultat |\n|:---------|:-----------|:-------------------|:--------|\n|`&` |ET |`TRUE & FALSE` |FALSE |\n|`|` |OU |`TRUE | FALSE` |TRUE |\n|`!` |NOT |`! TRUE` |FALSE |\n:::\n:::\n\n\nPrenons le temps pour un rapide exemple : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nA <- 4 \nB <- 10\nC <- -5\n\n# Produit TRUE car A est bien plus petit que B et C est bien plus petit que A\nA < B & C < A\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] TRUE\n```\n:::\n\n```{.r .cell-code}\n# Produit FALSE car si A est bien plus petit que B, \n# B est en revanche plus grand que c\nA < B & B < C\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] FALSE\n```\n:::\n\n```{.r .cell-code}\n# Produit TRUE car la seconde condition est inversée\nA < B & ! B < C\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] TRUE\n```\n:::\n\n```{.r .cell-code}\n# Produit TRUE car au moins une des deux conditions est juste\nA < B | B < C\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] TRUE\n```\n:::\n:::\n\n\nNotez que l'opérateur **ET** est prioritaire sur l'opérateur **OU** et que les parenthèses sont prioritaires sur tous les opérateurs : \n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Produit TRUE car nous commençons par tester A < B puis B < C ce qui donne FALSE\n# On obtient ensuite\n# FALSE | A > C\n# Enfin, A est bien supérieur à C, donc l'une des deux conditions est vraie\nA < B & B < C | A > C\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] TRUE\n```\n:::\n:::\n\n\nNotez qu'en arrière-plan, les opérateurs sont en réalité des fonctions déguisées. Il est donc possible de définir de nouveaux comportements pour les opérateurs. Il est par exemple possible d'additionner ou de comparer des objets spéciaux comme des dates, des géométries, des graphes, etc.\n\n### Structures de données {#sec-0136}\n\nJusqu'à présent, nous avons utilisé des objets ne comprenant qu'une seule valeur. Or, des analyses statistiques nécessitent de travailler avec des volumes de données bien plus grands. Pour stocker des valeurs, nous travaillons avec différentes structures de données : les vecteurs, les matrices, les tableaux de données et les listes.\n\n#### Vecteurs {#sec-01361}\n\nLes vecteurs sont la brique élémentaire de R. Ils permettent de stocker une série de valeurs **du même type** dans une seule variable. Pour déclarer un vecteur, nous utilisons la fonction `c()` : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nages <- c(35,45,72,56,62)\ntailles <- c(175.5,180.3,168.2,172.8,167.6)\nadresses <- c('4225 rue de la gauchetiere',\n '4223 rue de la gauchetiere',\n '4221 rue de la gauchetiere',\n '4219 rue de la gauchetiere',\n '4217 rue de la gauchetiere')\nproprietaires <- c(TRUE, TRUE, FALSE, TRUE, TRUE)\n```\n:::\n\n\nNous venons ainsi de déclarer quatre nouvelles variables étant chacune un vecteur de longueur cinq (comprenant chacun cinq valeurs). Ces vecteurs représentent, par exemple, les réponses de plusieurs personnes à un questionnaire.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Distinction entre un vecteur de type texte et un vecteur de type facteur**\n:::\n\n::: bloc_attention-body\nIl existe dans R une subtilité à l'origine de nombreux malentendus : la distinction entre un vecteur de type **texte** et un vecteur de type **facteur**. Dans l'exemple précédent, le vecteur *adresses* est un vecteur de type texte. Chaque nouvelle valeur ajoutée dans le vecteur peut être n'importe quelle nouvelle adresse. Déclarons un nouveau vecteur qui contient cette fois-ci la couleur des yeux de personnes ayant répondu au questionnaire.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncouleurs_yeux <- c('marron', 'marron', 'bleu', 'bleu', 'marron', 'vert')\n```\n:::\n\n\nContrairement aux adresses, il y a un nombre limité de couleurs que nous pouvons mettre dans ce vecteur. Il est donc intéressant de fixer les valeurs possibles du vecteur pour éviter d'en ajouter de nouvelles par erreur. Pour cela, nous devons convertir ce vecteur texte en vecteur de type facteur, ci-après nommé simplement facteur, avec la fonction `as.factor`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncouleurs_yeux_facteur <- as.factor(couleurs_yeux)\n```\n:::\n\n\nNotez qu'à présent, nous pouvons ajouter une nouvelle couleur dans le premier vecteur, mais pas dans le second.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncouleurs_yeux[7] <- \"rouge\"\ncouleurs_yeux_facteur[7] <- \"rouge\"\n```\n\n::: {.cell-output .cell-output-stderr}\n```\nWarning in `[<-.factor`(`*tmp*`, 7, value = \"rouge\"): niveau de facteur\nincorrect, NAs générés\n```\n:::\n:::\n\n\nLe message d'erreur nous informe que nous avons tenté d'introduire une valeur invalide dans le facteur.\n\nLes facteurs peuvent sembler restrictifs et, très régulièrement, nous préférons travailler avec de simples vecteurs de type texte plutôt que des facteurs. Cependant, de nombreuses fonctions d'analyse nécessitent d'utiliser des facteurs, car ils assurent une certaine cohérence dans les données. Il est donc essentiel de savoir passer du texte au facteur avec la fonction `as.factor`. À l'inverse, il est parfois nécessaire de revenir à une variable de type texte avec la fonction `as.character`.\n\nNotez que des vecteurs numériques peuvent aussi être convertis en facteurs : \n\n\n::: {.cell}\n\n```{.r .cell-code}\ntailles_facteur <- as.factor(tailles)\n```\n:::\n\n\nCependant, si vous souhaitez reconvertir ce facteur en format numérique, il faudra passer dans un premier temps par le format texte : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nas.numeric(tailles_facteur)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 4 5 2 3 1\n```\n:::\n:::\n\n\nComme vous pouvez le voir, convertir un facteur en valeur numérique renvoie des nombres entiers. Ceci est dû au fait que les valeurs dans un facteur sont recodées sous forme de nombres entiers, chaque nombre correspondant à une des valeurs originales (appelées niveaux). Si nous convertissons un facteur en valeurs numériques, nous obtenons donc ces nombres entiers.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nas.numeric(as.character(tailles_facteur))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 175.5 180.3 168.2 172.8 167.6\n```\n:::\n:::\n\n\nMorale de l'histoire : ne confondez pas les données de type texte et de type facteur. Dans le doute, vous pouvez demander à R quel est le type d'un vecteur avec la fonction `class`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nclass(tailles)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"numeric\"\n```\n:::\n\n```{.r .cell-code}\nclass(tailles_facteur)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"factor\"\n```\n:::\n\n```{.r .cell-code}\nclass(couleurs_yeux)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"character\"\n```\n:::\n\n```{.r .cell-code}\nclass(couleurs_yeux_facteur)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"factor\"\n```\n:::\n:::\n\n:::\n:::\n\n\nQuasiment toutes les fonctions utilisent des vecteurs. Par exemple, nous pouvons calculer la moyenne du vecteur *ages* en utilisant la fonction `mean` présente de base dans R.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmean(ages)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 54\n```\n:::\n:::\n\n\nCela démontre bien que le vecteur est la brique élémentaire de R! Toutes les variables que nous avons déclarées dans les sections précédentes sont aussi des vecteurs, mais de longueur 1.\n\n#### Matrices {#sec-01362}\n\nIl est possible de combiner des vecteurs pour former des matrices. Une matrice est un tableau en deux dimensions (colonnes et lignes) et est généralement utilisée pour représenter certaines structures de données comme des images (pixels), effectuer du calcul matriciel ou plus simplement présenter des matrices de corrélations. Vous aurez rarement à travailler directement avec des matrices, mais il est bon de savoir ce qu'elles sont. Créons deux matrices à partir de nos précédents vecteurs.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmatrice1 <- cbind(ages, tailles)\n# Afficher la matrice 1\nprint(matrice1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n ages tailles\n[1,] 35 175.5\n[2,] 45 180.3\n[3,] 72 168.2\n[4,] 56 172.8\n[5,] 62 167.6\n```\n:::\n\n```{.r .cell-code}\n# Afficher les dimensions de la matrice 1 (1er chiffre : lignes; 2e chiffre : colonnes)\nprint(dim(matrice1))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 5 2\n```\n:::\n\n```{.r .cell-code}\nmatrice2 <- rbind(ages, tailles)\n# Afficher la matrice 2\nprint(matrice2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n [,1] [,2] [,3] [,4] [,5]\nages 35.0 45.0 72.0 56.0 62.0\ntailles 175.5 180.3 168.2 172.8 167.6\n```\n:::\n\n```{.r .cell-code}\n# Afficher les dimensions de la matrice 2\nprint(dim(matrice2))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 2 5\n```\n:::\n:::\n\n\nComme vous pouvez le constater, la fonction `cbind` permet de concaténer des vecteurs comme s'ils étaient les colonnes d'une matrice, alors que `rbind` les combine comme s'ils étaient les lignes d'une matrice. La @fig-fig012 présente graphiquement le passage du vecteur à la matrice.\n\n![Du vecteur à la matrice](images/Chap01/vecteur_to_matrix.png){#fig-fig012 width=\"30%\" fig-align=\"center\"}\n\nNotez que vous pouvez transposer une matrice avec la fonction `t`. Si nous essayons maintenant de comparer la matrice 1 à la matrice 2 nous allons avoir une erreur, car elles n'ont pas les mêmes dimensions.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmatrice1 == matrice2\n```\n:::\n\n\n`Erreur dans matrice1 == matrice2 : tableaux de tailles inadéquates`\n\nEn revanche, nous pouvons transposer la matrice 1 et refaire cette comparaison : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nt(matrice1) == matrice2\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n [,1] [,2] [,3] [,4] [,5]\nages TRUE TRUE TRUE TRUE TRUE\ntailles TRUE TRUE TRUE TRUE TRUE\n```\n:::\n:::\n\n\nLe résultat souligne bien que nous avons les mêmes valeurs dans les deux matrices. Il est aussi possible de construire des matrices directement avec la fonction `matrix`, ce que nous montrons dans la prochaine section.\n\n#### *Arrays* {#sec-01363}\n\nS'il est rare de travailler avec des matrices, il est encore plus rare de manipuler des *arrays*. Un *array* est une matrice spéciale qui peut avoir plus que deux dimensions. Un cas simple serait un *array* en trois dimensions : lignes, colonnes, profondeur, que nous pourrions représenter comme un cube, ou une série de matrices de mêmes dimensions et empilées. Au-delà de trois dimensions, il devient difficile de les représenter mentalement. Cette structure de données peut être utilisée pour représenter les différentes bandes spectrales d'une image satellitaire. Les lignes et les colonnes délimiteraient les pixels de l'image et la profondeur délimiterait les différentes bandes composant l'image (@fig-fig012).\n\n\n![Un array avec trois dimensions](images/Chap01/array.png){#fig-fig013 width=\"15%\" fig-align=\"center\"}\n\nCréons un *array* en combinant trois matrices avec la fonction `array`. Chacune de ces matrices est composée respectivement de 1, de 2 et de 3 et a une dimension de 5 x 5. L'*array* final a donc une dimension de 5 x 5 x 3.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmat1 <- matrix(1, nrow = 5, ncol = 5)\nmat2 <- matrix(2, nrow = 5, ncol = 5)\nmat3 <- matrix(3, nrow = 5, ncol = 5)\n\nmon_array <- array(c(mat1, mat2, mat3), dim = c(5,5,3))\n\nprint(mon_array)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n, , 1\n\n [,1] [,2] [,3] [,4] [,5]\n[1,] 1 1 1 1 1\n[2,] 1 1 1 1 1\n[3,] 1 1 1 1 1\n[4,] 1 1 1 1 1\n[5,] 1 1 1 1 1\n\n, , 2\n\n [,1] [,2] [,3] [,4] [,5]\n[1,] 2 2 2 2 2\n[2,] 2 2 2 2 2\n[3,] 2 2 2 2 2\n[4,] 2 2 2 2 2\n[5,] 2 2 2 2 2\n\n, , 3\n\n [,1] [,2] [,3] [,4] [,5]\n[1,] 3 3 3 3 3\n[2,] 3 3 3 3 3\n[3,] 3 3 3 3 3\n[4,] 3 3 3 3 3\n[5,] 3 3 3 3 3\n```\n:::\n:::\n\n\n\n#### *DataFrames* {#sec-01364}\n\nS'il est rare de manipuler des matrices et des *arrays*, le *DataFrame* (tableau de données en français) est la structure de données la plus souvent utilisée. Dans cette structure, chaque ligne du tableau représente un individu et chaque colonne représente une caractéristique de cet individu. Ces colonnes ont des noms qui permettent facilement d'accéder à leurs valeurs. Créons un *DataFrame* (@tbl-tabfirsttable) à partir de nos quatre vecteurs et de la fonction `data.frame`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf <- data.frame(\n \"age\" = ages,\n \"taille\" = tailles,\n \"adresse\" = adresses,\n \"proprietaire\" = proprietaires\n)\n```\n:::\n\n::: {#tbl-tabfirsttable .cell tbl-cap='Premier DataFrame'}\n::: {.cell-output-display}\n| age | taille |adresse |proprietaire |\n|:---:|:------:|:--------------------------|:------------|\n| 35 | 175,5 |4225 rue de la gauchetiere |TRUE |\n| 45 | 180,3 |4223 rue de la gauchetiere |TRUE |\n| 72 | 168,2 |4221 rue de la gauchetiere |FALSE |\n| 56 | 172,8 |4219 rue de la gauchetiere |TRUE |\n| 62 | 167,6 |4217 rue de la gauchetiere |TRUE |\n:::\n:::\n\n\nDans RStudio, vous pouvez visualiser votre tableau de données avec la fonction `View(df)`. Comme vous pouvez le constater, chaque vecteur est devenu une colonne de votre tableau de données *df*. La @fig-fig013 résume ce passage d'une simple donnée à un *DataFrame* en passant par un vecteur.\n\n\n![De la donnée au DataFrame](images/Chap01/vecteur_to_dataframe.png){#fig-fig013 width=\"25%\" fig-align=\"center\"}\n\nPlusieurs fonctions de base de R fournissent des informations importantes sur un *DataFrame* : \n\n* `names` renvoie les noms des colonnes du *DataFrame*;\n* `nrow` renvoie le nombre de lignes;\n* `ncol` renvoie le nombre de colonnes.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nnames(df)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"age\" \"taille\" \"adresse\" \"proprietaire\"\n```\n:::\n\n```{.r .cell-code}\nnrow(df)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 5\n```\n:::\n\n```{.r .cell-code}\nncol(df)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 4\n```\n:::\n:::\n\n\nVous pouvez accéder à chaque colonne de *df* en utilisant le symbole `$` ou `[[\"nom_de_la_colonne\"]]`. Recalculons ainsi la moyenne des âges :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmean(df$age)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 54\n```\n:::\n\n```{.r .cell-code}\nmean(df[[\"age\"]])\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 54\n```\n:::\n:::\n\n\n#### Listes {#sec-01365}\n\nLa dernière structure de données à connaître est la liste. Elle ressemble à un vecteur, au sens où elle permet de stocker un ensemble d'objets les uns à la suite des autres. Cependant, une liste peut contenir n'importe quel type d'objets. Vous pouvez ainsi construire des listes de matrices, des listes d'*arrays*, des listes mixant des vecteurs, des graphiques, des *DataFrames*, des listes de listes...\n\nCréons ensemble une liste qui va contenir des vecteurs et des matrices à l'aide de la fonction `list.`\n\n\n::: {.cell}\n\n```{.r .cell-code}\nma_liste <- list(c(1,2,3,4),\n matrix(1, ncol = 3, nrow = 5),\n matrix(5, ncol = 3, nrow = 7),\n 'A'\n )\n```\n:::\n\n\nIl est possible d'accéder aux éléments de la liste par leur position dans cette dernière en utilisant les doubles crochets `[[ ]]` : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nprint(ma_liste[[1]])\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 1 2 3 4\n```\n:::\n\n```{.r .cell-code}\nprint(ma_liste[[4]])\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"A\"\n```\n:::\n:::\n\n\nIl est aussi possible de donner des noms aux éléments de la liste et d'utiliser le symbole `$` pour y accéder. Créons une nouvelle liste de vecteurs et donnons-leur des noms avec la fonction `names`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nliste2 <- list(c(35, 45, 72, 56, 62), \n c(175.5, 180.3, 168.2, 172.8, 167.6),\n c(TRUE, TRUE, FALSE, TRUE, TRUE)\n)\nnames(liste2) <- c(\"age\", \"taille\", \"proprietaire\")\n\nprint(liste2$age)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 35 45 72 56 62\n```\n:::\n:::\n\n\nSi vous avez bien suivi, vous devriez avoir compris qu'un *DataFrame* n'est en fait rien d'autre qu'une liste de vecteurs avec des noms!\n\nBravo! Vous venez de faire le tour des bases du langage R. Vous allez apprendre désormais à manipuler des données dans des *DataFrames*!\n\n## Manipulation de données {#sec-014}\n\nDans cette section, vous apprendrez à charger et à manipuler des *DataFrames* en vue d'effectuer des opérations classiques de gestion de données.\n\n\n### Chargement d'un *DataFrame* depuis un fichier {#sec-0141}\n\nIl est rarement nécessaire de créer vos *DataFrames* manuellement. Le plus souvent, vous disposerez de fichiers contenant vos données et utiliserez des fonctions pour les importer dans R sous forme d'un *DataFrame*. Les formats à importer les plus répandus sont : \n\n* *.csv*, soit un fichier texte dont chaque ligne représente une ligne du tableau de données et dont les colonnes sont séparées par un délimiteur (généralement une virgule ou un point-virgule);\n\n* *.dbf*, ou fichier *dBase*, souvent associés à des fichiers d'information géographique au format *ShapeFile*;\n\n* *.xls* et *.xlsx*, soit des fichiers générés par Excel;\n\n* *.json*, soit un fichier texte utilisant la norme d'écriture propre au langage JavaScript.\n\nPlus rarement, il se peut que vous ayez à charger des fichiers provenant de logiciels propriétaires : \n\n* *.sas7bdat* (SAS);\n* *.sav* (SPSS);\n* *.dta* (STATA).\n\nPour lire la plupart de ces fichiers, nous utilisons le *package* `foreign` dédié à l'importation d'une multitude de formats. Nous commençons donc par l'installer (`install.packages(\"foreign\")`). Ensuite, nous chargeons cinq fois le même jeu de données enregistré dans des formats différents (*csv*, *dbf*, *dta*, *sas7bdat* et *xlsx*) et nous mesurons le temps nécessaire pour importer chacun de ces fichiers avec la fonction `Sys.time`.\n\n#### Lecture d'un fichier *csv* {#sec-01411}\n\nPour le format *csv*, il n'est pas nécessaire d'utiliser un *package* puisque R dispose d'une fonction de base pour lire ce format.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nt1 <- Sys.time()\ndf1 <- read.csv(\"data/priseenmain/SR_MTL_2016.csv\", \n header = TRUE, sep = \",\", dec = \".\",\n stringsAsFactors = FALSE)\nt2 <- Sys.time()\nd1 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df1 a \", nrow(df1),\" observations\",\n 'et ', ncol(df1),\" colonnes\\n\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLe DataFrame df1 a 951 observations et 48 colonnes\n```\n:::\n:::\n\n\nRien de bien compliqué! Notez tout de même que : \n\n* Lorsque vous chargez un fichier *csv*, vous devez connaître le **délimiteur** (ou **séparateur**), soit le caractère utilisé pour délimiter les colonnes. Dans le cas présent, il s'agit d'une virgule (spécifiez avec l'argument `sep = \",\"`), mais il pourrait tout aussi bien être un point virgule (`sep = \";\"`), une tabulation (`sep = \" \"`), etc.\n\n* Vous devez également spécifier le caractère utilisé comme séparateur de décimales. Le plus souvent, ce sera le point (`dec = \".\"`), mais certains logiciels avec des paramètres régionaux de langue française (notamment Excel) exportent des fichiers *csv* avec des virgules comme séparateur de décimales (utilisez alors `dec = \",\"`).\n\n* L'argument `header` indique si la première ligne (l'entête) du fichier comprend ou non les noms des colonnes du jeu de données (avec les valeurs `TRUE` ou `FALSE`). Il arrive que certains fichiers *csv* soient fournis sans entête et que le nom et la description des colonnes soient fournis dans un autre fichier.\n\n* L'argument `stringsAsFactors` permet d'indiquer à R que les colonnes comportant du texte doivent être chargées comme des vecteurs de type texte et non de type facteur.\n\n#### Lecture d'un fichier *dbase* {#sec-01412}\n\nPour lire un fichier *dbase* (.dbf), nous utilisons la fonction `read.dbf` du *package* `foreign` installé précédemment : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(foreign)\n\nt1 <- Sys.time()\ndf2 <- read.dbf(\"data/priseenmain/SR_MTL_2016.dbf\")\nt2 <- Sys.time()\nd2 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df2 a \", nrow(df2),\" observations\",\n \"et \", ncol(df2),\" colonnes\\n\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLe DataFrame df2 a 951 observations et 48 colonnes\n```\n:::\n:::\n\n\nComme vous pouvez le constater, nous obtenons les mêmes résultats qu'avec le fichier *csv*.\n\n#### Lecture d'un fichier *dta* (Stata) {#sec-01413}\n\nSi vous travaillez avec des collègues utilisant le logiciel Stata, il se peut que ces derniers vous partagent des fichiers *dta*. Toujours en utilisant le *package* `foreign`, vous serez en mesure de les charger directement dans R.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nt1 <- Sys.time()\ndf3 <- read.dta(\"data/priseenmain/SR_MTL_2016.dta\")\nt2 <- Sys.time()\nd3 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df3 a \", nrow(df3),\" observations \",\n \"et \", ncol(df3), \" colonnes\\n\", sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLe DataFrame df3 a 951 observations et 48 colonnes\n```\n:::\n:::\n\n\n\n#### Lecture d'un fichier *sav* (SPSS) {#sec-01414}\n\nPour importer un fichier *sav* provenant du logiciel statistique SPSS, utilisez la fonction `read.spss` du *package* `foreign`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nt1 <- Sys.time()\ndf4 <- as.data.frame(read.spss(\"data/priseenmain/SR_MTL_2016.sav\"))\nt2 <- Sys.time()\nd4 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df4 a \", nrow(df4),\" observations \",\n \"et \", ncol(df4), \" colonnes\\n\", sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLe DataFrame df4 a 951 observations et 48 colonnes\n```\n:::\n:::\n\n\n#### Lecture d'un fichier *sas7bdat* (SAS) {#sec-01415}\n\nPour importer un fichier *sas7bdat* provenant du logiciel statistique SAS, utilisez la fonction `read.sas7bdat` du *package* `sas7bdat`. Installez préalablement le *package* (`install.packages(\"sas7bdat\")`) et chargez-le (`library(sas7bdat)`).\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(sas7bdat)\n\nt1 <- Sys.time()\ndf5 <- read.sas7bdat(\"data/priseenmain/SR_MTL_2016.sas7bdat\")\nt2 <- Sys.time()\nd5 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df5 a \", nrow(df5),\" observations \",\n \"et \", ncol(df5),\" colonnes\\n\", sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLe DataFrame df5 a 951 observations et 48 colonnes\n```\n:::\n:::\n\n\n\n#### Lecture d'un fichier *xlsx* (Excel) {#sec-01416}\n\nLire un fichier Excel dans R n'est pas toujours une tâche facile. Généralement, nous recommandons d'exporter le fichier en question au format *csv* dans un premier temps, puis de le lire avec la fonction `read.csv` dans un second temps ([section @sec-01411]). \n\nIl est néanmoins possible de lire directement un fichier *xlsx* avec le *package* `xlsx`. Ce dernier requiert que le logiciel JAVA soit installé sur votre ordinateur (Windows, Mac ou Linux). Si vous utilisez la version 64 bit de R, vous devrez télécharger et installer la version 64 bit de JAVA. Une fois que ce logiciel tiers est installé, il ne vous restera plus qu'à installer (`install.packages(\"xlsx\")`) et charger (`library(xlsx)`) le *package* `xlsx`. Sous windows, il est possible que vous deviez également installer manuellement le *package* `rJava` et indiquer à R où se trouve JAVA sur votre ordinateur. La procédure est détaillée [ici](https://cimentadaj.github.io/blog/2018-05-25-installing-rjava-on-windows-10/installing-rjava-on-windows-10/).\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(xlsx)\n\nt1 <- Sys.time()\ndf6 <- read.xlsx(file=\"data/priseenmain/SR_MTL_2016.xlsx\",\n sheetIndex = 1,\n as.data.frame = TRUE)\nt2 <- Sys.time()\nd6 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df6 a \", nrow(df6),\" observations \",\n \"et \", ncol(df6),\" colonnes\\n\", sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLe DataFrame df6 a 951 observations et 48 colonnes\n```\n:::\n:::\n\n\nIl est possible d'accélérer significativement la vitesse de lecture d'un fichier *xlsx* en utilisant la fonction `read.xlsx2`. Il faut cependant indiquer à cette dernière le type de données de chaque colonne. Dans le cas présent, les cinq premières colonnes contiennent des données de type texte (`character`), alors que les 43 autres sont des données numériques (`numeric`). Nous utilisons la fonction `rep` afin de ne pas avoir à écrire plusieurs fois *character* et *numeric*.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(xlsx)\n\nt1 <- Sys.time()\ndf7 <- read.xlsx2(file=\"data/priseenmain/SR_MTL_2016.xlsx\",\n sheetIndex = 1, \n as.data.frame = TRUE,\n colClasses = c(rep(\"character\",5), rep(\"numeric\",43))\n )\nt2 <- Sys.time()\nd7 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df6 a \", nrow(df7),\" observations \",\n \"et \", ncol(df7),\" colonnes\\n\", sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLe DataFrame df6 a 951 observations et 48 colonnes\n```\n:::\n:::\n\n\nSi nous comparons les temps d'exécution (@tbl-tableduration), nous constatons que la lecture des fichiers *xlsx* peut être extrêmement longue si nous ne spécifions pas le type des colonnes, ce qui peut devenir problématique pour des fichiers volumineux. Notez également que la lecture d'un fichier *csv* devient de plus en plus laborieuse à mesure que sa taille augmente. Si vous devez un jour charger des fichiers *csv* de plusieurs gigaoctets, nous vous recommandons vivement d'utiliser la fonction `fread` du *package* `data.table` qui est beaucoup plus rapide.\n\n\n\n::: {#tbl-tableduration .cell tbl-cap='Temps nécessaire pour lire les données en fonction du type de fichiers'}\n::: {.cell-output-display}\n| Fonction|Durée (secondes) |\n|-------------:|:----------------|\n| read.csv|0,02 |\n| read.dbf|0,02 |\n| read.spss|0,00 |\n| read.dta|0,01 |\n| read.sas7bdat|0,51 |\n| read.xlsx|12,44 |\n| read.xlsx2|0,47 |\n:::\n:::\n\n\n### Manipulation d'un *DataFrame* {#sec-0142}\n\nUne fois le *DataFrame* chargé, voyons comment il est possible de le manipuler.\n\n#### Petit mot sur le `tidyverse` {#sec-01421}\n\n`tidyverse` est un ensemble de *packages* conçus pour faciliter la structuration et la manipulation des données dans R. Avant d'aller plus loin, il est important d'aborder brièvement un débat actuel dans la Communauté R. Entre 2010 et 2020, l'utilisation du `tidyverse` s'est peu à peu répandue. Développé et maintenu par Hadley Wickham, `tidyverse` introduit une philosophie et une grammaire spécifiques qui diffèrent du langage R traditionnel. Une partie de la communauté a pour ainsi dire complètement embrassé le `tidyverse` et de nombreux *packages*, en dehors du `tidyverse`, ont adopté sa grammaire et sa philosophie. À l'inverse, une autre partie de la communauté est contre cette évolution ([voir l'article du blogue suivant](https://blog.ephorie.de/why-i-dont-use-the-tidyverse){target=\"_blank\"}). Les arguments pour et contre `tidyverse` sont résumés dans le (@tbl-Tidyverse). \n\n\n\n::: {#tbl-Tidyverse .cell tbl-cap='Avantages et inconvénients du tidyverse'}\n::: {.cell-output-display}\n|Avantage du tidyverse |Problème posé par le tidyverse |\n|:-----------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------|\n|Simplicité d'écriture et d'apprentissage |Nouvelle syntaxe à apprendre |\n|Ajout de l'opérateur `%>%` permettant d'enchaîner les traitements |Perte de lisibilité avec l'opérateur `->` |\n|La meilleure librairie pour réaliser des graphiques : `ggplot2` |Remplacement de certaines fonctions de base par d'autres provenant du `tidyverse` lors de son chargement, pouvant créer des erreurs. |\n|Crée un écosystème cohérent |Ajout d'une dépendance dans le code |\n|*Package* en développement et de plus en plus utilisé |Philosophie d'évolution agressive, aucune assurance de rétrocompatibilité |\n:::\n:::\n\n\n\nLe dernier point est probablement le plus problématique. Dans sa volonté d'évoluer au mieux et sans restriction, le *package* `tidyverse` n'offre aucune garantie de rétrocompatibilité. En d'autres termes, des changements importants peuvent être introduits d'une version à l'autre rendant potentiellement obsolète votre ancien code. Nous n'avons pas d'opinion tranchée sur le sujet : `tidyverse` est un outil très intéressant dans de nombreux cas; nous évitons simplement de l'utiliser systématiquement et préférons charger directement des sous-*packages* (comme `dplyr` ou `ggplot2`) du `tidyverse`. Notez que le *package* `data.table` offre une alternative au `tidyverse` dans la manipulation de données. Au prix d'une syntaxe généralement un peu plus complexe, le package `data.table` offre une vitesse de calcul bien supérieure au `tidyverse` et assure une bonne rétrocompatibilité.\n\n\n#### Gestion des colonnes d'un *DataFrame* {#sec-01422}\n\nRepartons du *DataFrame* que nous avions chargé précédemment en important un fichier *csv*.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf <- read.csv(file=\"data/priseenmain/SR_MTL_2016.csv\", \n header = TRUE, sep = \",\", dec = \".\",\n stringsAsFactors = FALSE)\n```\n:::\n\n\n##### Sélection d'une colonne {#sec-014221}\n\nRappelons qu'il est possible d'accéder aux colonnes dans ce *DataFrame* en utilisant le symbole dollar `$ma_colonne` ou les doubles crochets `[[\"ma_colonne\"]]`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Calcul de la superficie totale de l'Île de Montréal\nsum(df$KM2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 4680.543\n```\n:::\n\n```{.r .cell-code}\nsum(df[[\"KM2\"]])\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 4680.543\n```\n:::\n:::\n\n\n##### Sélection de plusieurs colonnes {#sec-014222}\n\nIl est possible de sélectionner plusieurs colonnes d'un *DataFrame* et de filtrer ainsi les colonnes inutiles. Pour cela, nous pouvons utiliser un vecteur contenant soit les positions des colonnes (1 pour la première colonne, 2 pour la seconde et ainsi de suite), soit les noms des colonnes.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Conserver les 5 premières colonnes\ndf2 <- df[1:5]\n\n# Conserver les colonnes 1, 5, 10 et 15\ndf3 <- df[c(1,5,10,15)]\n\n# Cela peut aussi être utilisé pour changer l'ordre des champs\ndf3 <- df[c(10,15,1,5)]\n\n# Conserver les colonnes 1 à 5, 7 à 12, 17 et 22\ndf4 <- df[c(1:5,7:12,17,22)]\n\n# Conserver les colonnes avec leurs noms\ndf5 <- df[c(\"SRIDU\" , \"KM2\" , \"Pop2016\" , \"MaisonIndi\" , \"LoyerMed\")]\n```\n:::\n\n\n##### Suppression de colonnes {#sec-014223}\n\nIl est parfois plus intéressant et rapide de supprimer directement des colonnes plutôt que de recréer un nouveau *DataFrame*. Pour ce faire, nous attribuons la valeur `NULL` à ces colonnes.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Supprimer les colonnes 2, 3 et 5\ndf3[c(2,3,5)] <- list(NULL)\n\n# Supprimer une colonne avec son nom\ndf4$OID <- NULL\n\n# Supprimer plusieurs colonnes par leur nom\ndf5[c(\"SRIDU\" , \"LoyerMed\")] <- list(NULL)\n```\n:::\n\n\nNotez que si vous supprimez une colonne, vous ne pouvez pas revenir en arrière. Il faudra recharger votre jeu de données ou éventuellement relancer les calculs qui avaient produit cette colonne.\n\n##### Modification du nom des colonnes {#sec-014224}\n\nIl est possible de changer le nom d'une colonne. Cette opération est importante pour faciliter la lecture du *DataFrame* ou encore s'assurer que l'exportation du *DataFrame* dans un format particulier (tel que *.dbf* qui ne supporte que les noms de colonnes avec moins de 10 caractères) ne posera pas de problème.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Voici les noms des colonnes\nnames(df5)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"KM2\" \"Pop2016\" \"MaisonIndi\"\n```\n:::\n\n```{.r .cell-code}\n# Renommer toutes les colonnes\nnames(df5) <- c('superficie_km2','population_2016', 'maison_individuelle_prt')\nnames(df5)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"superficie_km2\" \"population_2016\" \n[3] \"maison_individuelle_prt\"\n```\n:::\n\n```{.r .cell-code}\n# Renommer avec dplyr\nlibrary(dplyr)\ndf4 <- rename(df4, \"population_2016\" = \"Pop2016\",\n \"prs_moins_14ans_prt\" = \"A014\",\n \"prs_15_64_ans_prt\" = \"A1564\",\n \"prs_65plus_ans_prt\" = \"A65plus\"\n )\n```\n:::\n\n\n\n#### Calcul de nouvelles variables {#sec-01423}\n\nIl est possible d'utiliser les colonnes de type numérique pour calculer de nouvelles colonnes en utilisant les opérateurs mathématiques vus dans la [section @sec-0135]. Prenons un exemple concret : calculons la densité de population par secteur de recensement dans notre *DataFrame*, puis affichons un résumé de cette nouvelle variable.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Calcul de la densité\ndf$pop_density_2016 <- df$Pop2016 / df$KM2\n\n# Statistiques descriptives\nsummary(df$pop_density_2016)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Min. 1st Qu. Median Mean 3rd Qu. Max. \n 17.45 1946.96 3700.50 5465.03 7918.39 48811.79 \n```\n:::\n:::\n\n\nNous pouvons aussi calculer le ratio entre le nombre de maisons et le nombre d'appartements.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Calcul du ratio\ndf$total_maison <- (df$MaisonIndi + df$MaisJumule + df$MaisRangee + df$AutreMais)\ndf$total_apt <- (df$AppDuplex + df$App5Moins + df$App5Plus)\ndf$ratio_maison_apt <- df$total_maison / df$total_apt\n```\n:::\n\n\nRetenez ici que R applique le calcul à chaque ligne de votre jeu de données et stocke le résultat dans une nouvelle colonne. Cette opération est du calcul vectoriel : toute la colonne est calculée en une seule fois. R est d'ailleurs optimisé pour le calcul vectoriel.\n\n#### Fonctions mathématiques {#sec-01424}\n\nR propose un ensemble de fonctions de base pour effectuer du calcul. Voici une liste non exhaustive des principales fonctions : \n\n* `abs` calcule la valeur absolue de chaque valeur d'un vecteur;\n\n* `sqrt` calcule la racine carrée de chaque valeur d'un vecteur;\n\n* `log` calcule le logarithme de chaque valeur d'un vecteur;\n\n* `exp` calcule l'exponentielle de chaque valeur d'un vecteur;\n\n* `factorial` calcule la factorielle de chaque valeur d'un vecteur;\n\n* `round` arrondit la valeur d'un vecteur;\n\n* `ceiling`, `floor` arrondit à l'unité supérieure ou inférieure de chaque valeur d'un vecteur;\n\n* `sin`, `asin`, `cos`, `acos`, `tan`, `atan` sont des fonctions de trigonométrie;\n\n* `cumsum` calcule la somme cumulative des valeurs d'un vecteur.\n\nCes fonctions sont des fonctions vectorielles puisqu'elles s'appliquent à tous les éléments d'un vecteur. Si votre vecteur en entrée comprend cinq valeurs, le vecteur en sortie comprendra aussi cinq valeurs.\n\nÀ l'inverse, les fonctions suivantes s'appliquent directement à l'ensemble d'un vecteur et ne vont renvoyer qu'une seule valeur :\n\n* `sum` calcule la somme des valeurs d'un vecteur;\n\n* `prod` calcule le produit des valeurs d'un vecteur;\n\n* `min`, `max` renvoient les valeurs maximale et minimale d'un vecteur;\n\n* `mean`, `median` renvoient la moyenne et la médiane d'un vecteur;\n\n* `quantile` renvoie les percentiles d'un vecteur.\n\n#### Fonctions pour manipuler des chaînes de caractères {#sec-01425}\n\nOutre les données numériques, vous aurez à travailler avec des données de type texte (`string`). Le `tidyverse` avec le *package* `stringr` offre des fonctions très intéressantes pour manipuler ce type de données. Pour un aperçu de toutes les fonctions offertes par `stringr`, référez-vous à sa [*Cheat Sheet*](https://github.com/rstudio/cheatsheets/blob/master/strings.pdf){target=\"_blank\"}. Commençons avec un *DataFrame* assez simple comprenant des adresses et des noms de personnes.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(stringr)\n\ndf <- data.frame(\n noms = c(\"Jérémy Toutanplace\" , \"constant Tinople\" , \"dino Resto\" , \"Luce tancil\"),\n adresses = c('15 rue Levy', '413 Blvd Saint-Laurent', '3606 rue Duké', '2457 route St Marys')\n)\n```\n:::\n\n\n##### Majuscules et minuscules {#sec-014251}\n\nPour harmoniser ce *DataFrame*, nous mettons, dans un premier temps, des majuscules à la première lettre des prénoms et des noms des individus avec la fonction `str_to_title`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf$noms_corr <- str_to_title(df$noms)\nprint(df$noms_corr)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"Jérémy Toutanplace\" \"Constant Tinople\" \"Dino Resto\" \n[4] \"Luce Tancil\" \n```\n:::\n:::\n\n\nNous pourrions également tout mettre en minuscules ou tout en majuscules.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf$noms_min <- tolower(df$noms)\ndf$noms_maj <- toupper(df$noms)\nprint(df$noms_min)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"jérémy toutanplace\" \"constant tinople\" \"dino resto\" \n[4] \"luce tancil\" \n```\n:::\n\n```{.r .cell-code}\nprint(df$noms_maj)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"JÉRÉMY TOUTANPLACE\" \"CONSTANT TINOPLE\" \"DINO RESTO\" \n[4] \"LUCE TANCIL\" \n```\n:::\n:::\n\n\n##### Remplacement du texte {#sec-014252}\n\nLes adresses comprennent des caractères accentués. Ce type de caractères cause régulièrement des problèmes d'encodage. Nous pourrions alors décider de les remplacer par des caractères simples avec la fonction `str_replace_all`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf$adresses_1 <- str_replace_all(df$adresses,'é','e')\nprint(df$adresses_1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"15 rue Levy\" \"413 Blvd Saint-Laurent\" \"3606 rue Duke\" \n[4] \"2457 route St Marys\" \n```\n:::\n:::\n\n\nLa même fonction peut être utilisée pour remplacer les *St* par *Saint* et les *Blvd* par *Boulevard*.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf$adresses_2 <- str_replace_all(df$adresses_1,' St ',' Saint ')\ndf$adresses_3 <- str_replace_all(df$adresses_2,' Blvd ',' Boulevard ')\nprint(df$adresses_3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"15 rue Levy\" \"413 Boulevard Saint-Laurent\"\n[3] \"3606 rue Duke\" \"2457 route Saint Marys\" \n```\n:::\n:::\n\n\n##### Découpage du texte {#sec-014253}\n\nIl est parfois nécessaire de découper du texte pour en extraire des éléments. Nous devons alors choisir un caractère de découpage. Dans notre exemple, nous pourrions vouloir extraire les numéros civiques des adresses en sélectionnant le premier espace comme caractère de découpage, et en utilisant la fonction `str_split_fixed`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf$num_civique <- str_split_fixed(df$adresses_3, ' ', n=2)[,1]\nprint(df$num_civique)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"15\" \"413\" \"3606\" \"2457\"\n```\n:::\n:::\n\n\nPour être exact, sachez que pour notre exemple, la fonction `str_split_fixed` renvoie deux colonnes de texte : une avec le texte avant le premier espace, soit le numéro civique, et une avec le reste du texte. Le nombre de colonnes est contrôlé par l'argument `n`. Si `n = 1`, la fonction ne fait aucun découpage; avec `n = 2` la fonction découpe en deux parties le texte avec la première occurrence du délimiteur et ainsi de suite. En ajoutant `[,1]` à la fin, nous indiquons que nous souhaitons garder seulement la première des deux colonnes.\n\nIl est également possible d'extraire des parties de texte et de ne garder par exemple que les *N* premiers caractères ou les *N* derniers caractères : \n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Ne garder que les 5 premiers caractères\nsubstr(df$adresses_3, start = 1, stop = 5)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"15 ru\" \"413 B\" \"3606 \" \"2457 \"\n```\n:::\n\n```{.r .cell-code}\n# Ne garder que les 5 derniers caractères\nn_caract <- nchar(df$adresses_3)\nsubstr(df$adresses_3, start = n_caract-4, stop = n_caract)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \" Levy\" \"urent\" \" Duke\" \"Marys\"\n```\n:::\n:::\n\n\nNotez que les paramètres `start` et `stop` de la fonction `substr` peuvent accepter un vecteur de valeurs. Il est ainsi possible d'appliquer une sélection de texte différente à chaque chaîne de caractères dans notre vecteur en entrée. Nous pourrions par exemple vouloir récupérer tout le texte avant le second espace pour garder uniquement le numéro civique et le type de rue.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Étape 1 : récupérer les positions des espaces pour chaque adresses\npositions <- str_locate_all(df$adresses_3, \" \")\n# Étape 2 : récupérer les positions des seconds espaces\nsec_positions <- sapply(positions, function(i){\n i[2,1]\n})\n# Étape 3 : appliquer le découpage\nsubstr(df$adresses_3, start = 1, stop = sec_positions-1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"15 rue\" \"413 Boulevard\" \"3606 rue\" \"2457 route\" \n```\n:::\n:::\n\n\n\n##### Concaténation du texte {#sec-014254}\n\nÀ l'inverse du découpage, il est parfois nécessaire de concaténer des éléments de texte, ce qu'il est possible de réaliser avec la fonction `paste`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf$texte_complet <- paste(df$noms_corr, df$adresses_3, sep = \" : \")\nprint(df$texte_complet)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"Jérémy Toutanplace : 15 rue Levy\" \n[2] \"Constant Tinople : 413 Boulevard Saint-Laurent\"\n[3] \"Dino Resto : 3606 rue Duke\" \n[4] \"Luce Tancil : 2457 route Saint Marys\" \n```\n:::\n:::\n\n\nLe paramètre `sep` permet d'indiquer le ou les caractères à intercaler entre les éléments à concaténer. Notez qu'il est possible de concaténer plus que deux éléments.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf$ville <- c('Montreal','Montreal','Montreal','Montreal')\npaste(df$noms_corr, df$adresses_3, df$ville, sep = \", \")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"Jérémy Toutanplace, 15 rue Levy, Montreal\" \n[2] \"Constant Tinople, 413 Boulevard Saint-Laurent, Montreal\"\n[3] \"Dino Resto, 3606 rue Duke, Montreal\" \n[4] \"Luce Tancil, 2457 route Saint Marys, Montreal\" \n```\n:::\n:::\n\n\nSi vous souhaitez concaténer des éléments de texte sans séparateur, la fonction `paste0` peut être plus simple à utiliser.\n\n\n::: {.cell}\n\n```{.r .cell-code}\npaste0(\"Please conca\", \"tenate me!\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"Please concatenate me!\"\n```\n:::\n:::\n\n\n#### Manipulation des colonnes de type date {#sec-01426}\n\nNous avons vu que les principaux types de données dans R sont le numérique, le texte, le booléen et le facteur. Il existe d'autres types introduits par différents *packages*. Nous abordons ici les types date et heure (*date* and *time*). Pour les manipuler, nous privilégions l'utilisation du *package* `lubridate` du `tidyverse`. Pour illustrer le tout, nous l'utilisons avec un jeu de données ouvertes de la Ville de Montréal représentant les collisions routières impliquant au moins un cycliste survenues après le 1^er^ janvier 2017.\n\n\n::: {.cell}\n\n```{.r .cell-code}\naccidents_df <- read.csv(file=\"data/priseenmain/accidents.csv\", sep = \",\")\nnames(accidents_df)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"HEURE_ACCDN\" \"DT_ACCDN\" \"NB_VICTIMES_TOTAL\"\n```\n:::\n:::\n\n\nNous disposons de trois colonnes représentant respectivement l'heure, la date et le nombre de victimes impliquées dans la collision.\n\n##### Du texte à la date {#sec-014261}\n\nActuellement, les colonnes `HEURE_ACCDN` et `DT_ACCDN` sont au format texte. Nous pouvons afficher quelques lignes du jeu de données avec la fonction `head` pour visualiser comment elles ont été saisies.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nhead(accidents_df, n = 5)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HEURE_ACCDN DT_ACCDN NB_VICTIMES_TOTAL\n1 16:00:00-16:59:00 2017/11/02 0\n2 06:00:00-06:59:00 2017/01/16 1\n3 18:00:00-18:59:00 2017/04/18 0\n4 11:00:00-11:59:00 2017/05/28 1\n5 15:00:00-15:59:00 2017/05/28 1\n```\n:::\n:::\n\n\nUn peu de ménage s'impose : les heures sont indiquées comme des périodes d'une heure. Nous utilisons la fonction `str_split_fixed` du *package* `stringr` pour ne garder que la première partie de l'heure (avant le tiret). Ensuite, Nous concaténons l'heure et la date avec la fonction `paste`, puis nous convertissons ce résultat en un objet *date-time*.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(lubridate)\n\n# Étape 1 : découper la colonne Heure_ACCDN\naccidents_df$heure <- str_split_fixed(accidents_df$HEURE_ACCDN, \"-\", n=2)[,1]\n# Étape 2 : concaténer l'heure et la date\naccidents_df$date_heure <- paste(accidents_df$DT_ACCDN, \n accidents_df$heure,\n sep = ' ')\n# Étape 3 : convertir au format datetime\naccidents_df$datetime <- as_datetime(accidents_df$date_heure,\n format = \"%Y/%m/%d %H:%M:%S\")\n```\n:::\n\n\nPour effectuer la conversion, nous avons utilisé la fonction `as_datetime` du *package* `lubridate`. Elle prend comme paramètre un vecteur de texte et une indication du format de ce vecteur de texte. Il existe de nombreuses façons de spécifier une date et une heure et l'argument *format* permet d'indiquer celle à utiliser. Dans cet exemple, la date est structurée comme suit : \n`année/mois/jour heure:minute:seconde`, ce qui se traduit par le format `%Y/%m/%d %H:%M:%S`.\n\n* %Y signifie une année indiquée avec quatre caractères : 2017;\n\n* %m signifie un mois, indiqué avec deux caractères : 01, 02, 03, ... 12;\n\n* %d signifie un jour, indiqué avec deux caractères : 01, 02, 03, ... 31;\n\n* %H signifie une heure, au format 24 heures avec deux caractères : 00, 02, ... 23;\n\n* %M signifie des minutes indiquées avec deux caractères : 00, 02, ... 59;\n\n* %S signifie des secondes, indiquées avec deux caractères : 00, 02, ... 59.\n\nNotez que les caractères séparant les années, jours, heures, etc. sont aussi à indiquer dans le format. Dans notre exemple, nous utilisons la barre oblique (`/`) pour séparer les éléments de la date et le deux points (`:`) pour l'heure, et une espace pour séparer la date et l'heure.\n\nIl existe d'autres nomenclatures pour spécifier un format *datetime* : par exemple, des mois renseignés par leur nom, l'indication AM-PM, etc. Vous pouvez vous référer à la documentation de la fonction `strptime` (`help(strptime)`) pour explorer les différentes nomenclatures et choisir celle qui vous convient. Bien évidemment, il est nécessaire que toutes les dates de votre colonne soient renseignées dans le même format, pour éviter que la fonction ne retourne la valeur `NA` lorsqu'elle ne peut lire le format. Après toutes ces opérations, rejetons un oeil à notre *DataFrame*.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nhead(accidents_df, n = 5)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HEURE_ACCDN DT_ACCDN NB_VICTIMES_TOTAL heure date_heure\n1 16:00:00-16:59:00 2017/11/02 0 16:00:00 2017/11/02 16:00:00\n2 06:00:00-06:59:00 2017/01/16 1 06:00:00 2017/01/16 06:00:00\n3 18:00:00-18:59:00 2017/04/18 0 18:00:00 2017/04/18 18:00:00\n4 11:00:00-11:59:00 2017/05/28 1 11:00:00 2017/05/28 11:00:00\n5 15:00:00-15:59:00 2017/05/28 1 15:00:00 2017/05/28 15:00:00\n datetime\n1 2017-11-02 16:00:00\n2 2017-01-16 06:00:00\n3 2017-04-18 18:00:00\n4 2017-05-28 11:00:00\n5 2017-05-28 15:00:00\n```\n:::\n:::\n\n\n##### Extraction des informations d'une date {#sec-014262}\n\nÀ partir de la nouvelle colonne `datetime`, nous sommes en mesure d'extraire des informations intéressantes comme : \n\n* le nom du jour de la semaine avec la fonction `weekdays`\n\n::: {.cell}\n\n```{.r .cell-code}\naccidents_df$jour <- weekdays(accidents_df$datetime)\n```\n:::\n\n\n* la période de la journée avec les fonctions `am` et `pm` \n\n::: {.cell}\n\n```{.r .cell-code}\naccidents_df$AM <- am(accidents_df$datetime)\naccidents_df$PM <- pm(accidents_df$datetime)\nhead(accidents_df[c(\"jour\", \"AM\", \"PM\")], n=5)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n jour AM PM\n1 jeudi FALSE TRUE\n2 lundi TRUE FALSE\n3 mardi FALSE TRUE\n4 dimanche TRUE FALSE\n5 dimanche FALSE TRUE\n```\n:::\n:::\n\n\nIl est aussi possible d'accéder aux sous-éléments d'un *datetime* comme l'année, le mois, le jour, l'heure, la minute et la seconde avec les fonctions `year()`, `month()`,`day()`, `hour()`, `minute()` et `second()`.\n\n##### Calcul d'une durée entre deux *datetime* {#sec-014263}\n\nUne autre utilisation intéressante du format *datetime* est de calculer des différences de temps. Par exemple, nous pourrions utiliser le nombre de minutes écoulées depuis 7 h comme une variable dans une analyse visant à déterminer le moment critique des collisions routières durant l'heure de pointe du matin. \nPour cela, nous devons créer un *datetime* de référence en concaténant la date de chaque observation, et le temps `07:00:00`, qui est notre point de départ.\n\n\n::: {.cell}\n\n```{.r .cell-code}\naccidents_df$date_heure_07 <- paste(accidents_df$DT_ACCDN, \n '07:00:00',\n sep = ' ')\naccidents_df$ref_datetime <- as_datetime(accidents_df$date_heure_07,\n format = \"%Y/%m/%d %H:%M:%S\")\n```\n:::\n\nIl ne nous reste plus qu'à calculer la différence de temps entre la colonne *datetime* et notre temps de référence *ref_datetime*.\n\n\n::: {.cell}\n\n```{.r .cell-code}\naccidents_df$diff_time <- difftime(accidents_df$datetime,\n accidents_df$ref_datetime,\n units = 'min')\n```\n:::\n\n\nNotez qu'ici la colonne *diff_time* est d'un type spécial : une différence temporelle (*difftime*). Il faut encore la convertir au format numérique pour l'utiliser avec la fonction `as.numeric`. Par curiosité, réalisons rapidement un histogramme avec la fonction `hist` pour analyser rapidement cette variable d'écart de temps!\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\naccidents_df$diff_time_num <- as.numeric(accidents_df$diff_time)\nhist(accidents_df$diff_time_num, breaks = 50)\n```\n\n::: {.cell-output-display}\n![Répartition temporelle des accidents à vélo](01-priseenmainR_files/figure-html/fig-fig015-1.png){#fig-fig015 fig-align='center' width=65%}\n:::\n:::\n\n\nNous observons clairement deux pics, un premier entre 0 et 100 (entre 7 h et 8 h 30 environ) et un second plus important entre 550 et 650 (entre 16 h et 17 h 30 environ), ce qui correspond sans surprise aux heures de pointe (@fig-fig015). Il est intéressant de noter que plus d'accidents se produisent à l'heure de pointe du soir qu'à celle du matin.\n\n##### Fuseau horaire {#sec-014264}\n\nLorsque nous travaillons avec des données provenant de différents endroits dans le monde ou que nous devons tenir compte des heures d'été et d'hiver, il convient de tenir compte du fuseau horaire. Pour créer une date avec un fuseau horaire, il est possible d'utiliser le paramètre `tz` dans la fonction `as_datetime` et d'utiliser l’identifiant du fuseau approprié. Dans notre cas, les données d'accident ont été collectées à Montréal, qui a un décalage de -5 heures par rapport au temps de référence UTC (+1 heure en été). Le code spécifique de ce fuseau horaire est *EDT*; il est facile de trouver ces codes avec le site web [timeanddate.com](https://www.timeanddate.com/time/map/).\n\n\n::: {.cell}\n\n```{.r .cell-code}\naccidents_df$datetime <- as_datetime(accidents_df$date_heure,\n format = \"%Y/%m/%d %H:%M:%S\",\n tz = \"EDT\")\n```\n:::\n\n\n#### Recodage des variables {#sec-01427}\n\nRecoder une variable signifie changer ses valeurs selon une condition afin d'obtenir une nouvelle variable. Si nous reprenons le jeu de données précédent sur les accidents à vélo, nous pourrions vouloir créer une nouvelle colonne nous indiquant si la collision a eu lieu en heures de pointe ou non. Nous obtiendrions ainsi une nouvelle variable avec seulement deux catégories plutôt que la variable numérique originale. Nous pourrions aussi définir quatre catégories avec l'heure de pointe du matin, l'heure de pointe du soir, le reste de la journée et la nuit.\n\n##### Cas binaire avec `ifelse` {#sec-014271}\n\nSi nous ne souhaitons créer que deux catégories, le plus simple est d'utiliser la fonction `ifelse`. Cette fonction évalue une condition ([section @sec-0135]) pour chaque ligne d'un *DataFrame* et produit un nouveau vecteur. Créons donc une variable binaire indiquant si une collision a eu lieu durant les heures de pointe ou hors heures de pointe. Nous devons alors évaluer les conditions suivantes : \n\nEst-ce que l'accident a eu lieu entre 7 h (0) **ET** 9 h (120), **OU** entre 16 h 30 (570) **ET** 18 h 30 (690)?\n\n\n::: {.cell}\n\n```{.r .cell-code}\ntable(is.na(accidents_df$diff_time_num))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nFALSE TRUE \n 2414 40 \n```\n:::\n:::\n\n\nNotons dans un premier temps que nous avons 40 observations sans valeur pour la colonne `diff_time_num`. Il s'agit d'observations pour lesquelles nous ne disposions pas de dates au départ.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nCond1 <- accidents_df$diff_time_num >= 0 & accidents_df$diff_time_num <= 120\nCond2 <- accidents_df$diff_time_num >= 570 & accidents_df$diff_time_num <= 690\n\naccidents_df$moment_bin <- ifelse(Cond1 | Cond2,\n \"en heures de pointe\",\n \"hors heures de pointe\")\n```\n:::\n\n\nComme vous pouvez le constater, la fonction `ifelse` nécessite trois arguments : \n\n* une condition, pouvant être `TRUE` ou `FALSE`;\n\n* la valeur à renvoyer si la condition est `FALSE`;\n\n* la valeur à renvoyer si la condition est `TRUE`.\n\nAvec la fonction `table`, nous pouvons rapidement visualiser les effectifs des deux catégories ainsi créées : \n\n\n::: {.cell}\n\n```{.r .cell-code}\ntable(accidents_df$moment_bin)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n en heures de pointe hors heures de pointe \n 841 1573 \n```\n:::\n\n```{.r .cell-code}\n# Vérifier si nous avons toujours seulement 40 NA\ntable(is.na(accidents_df$moment_bin))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nFALSE TRUE \n 2414 40 \n```\n:::\n:::\n\nLes heures de pointe représentent quatre heures de la journée, ce qui nous laisse neuf heures hors heures de pointe entre 7 h et 20 h.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Ratio de collisions routières en heures de pointe\n(841 / 2414) / (4 / 13)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 1.132249\n```\n:::\n\n```{.r .cell-code}\n# Ratio de collisions routières hors heure de pointe\n(1573 / 2414) / (9 / 13)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 0.9412225\n```\n:::\n:::\n\n\nEn rapportant les collisions aux durées des deux périodes, nous observons une nette surreprésentation des collisions impliquant un vélo pendant les heures de pointe d'environ 13 % comparativement à la période hors des heures de pointe.\n\n##### Cas multiple avec la `case_when` {#sec-014272}\n\nLorsque nous souhaitons créer plus que deux catégories, il est possible soit d'enchaîner plusieurs fonctions `ifelse` (ce qui produit un code plus long et moins lisible), soit d'utiliser la fonction `case_when` du *package* `dplyr` du `tidyverse`. Reprenons notre exemple et créons quatre catégories : \n\n* en heures de pointe du matin;\n\n* en heures de pointe du soir;\n\n* le reste de la journée (entre 7 h et 20 h);\n\n* la nuit (entre 21 h et 7 h).\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(dplyr)\n\naccidents_df$moment_multi <- case_when(\n accidents_df$diff_time_num >= 0 & accidents_df$diff_time_num <= 120 ~ \"pointe matin\",\n accidents_df$diff_time_num >= 570 & accidents_df$diff_time_num <= 690 ~ \"pointe soir\",\n accidents_df$diff_time_num > 690 & accidents_df$diff_time_num < 780 ~ \"journee\",\n accidents_df$diff_time_num > 120 & accidents_df$diff_time_num < 570 ~ \"journee\",\n accidents_df$diff_time_num < 0 | accidents_df$diff_time_num >= 780 ~ \"nuit\"\n)\n\ntable(accidents_df$moment_multi)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n journee nuit pointe matin pointe soir \n 1155 418 404 437 \n```\n:::\n\n```{.r .cell-code}\n# Vérifions encore les NA\ntable(is.na(accidents_df$moment_multi))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nFALSE TRUE \n 2414 40 \n```\n:::\n:::\n\n\nLa syntaxe de cette fonction est un peu particulière. Elle accepte un nombre illimité (ou presque) d'arguments. Chaque argument est composé d'une condition et d'une valeur à renvoyer si la condition est vraie; ces deux éléments étant reliés par le symbole `~`. Notez que toutes les évaluations sont effectuées dans l'ordre des arguments. En d'autres termes, la fonction teste d'abord la première condition et assigne ses valeurs, puis recommence pour les prochaines conditions. Ainsi, si une observation (ligne du tableau de données) obtient `TRUE` à plusieurs conditions, elle obtient au final la valeur de la dernière condition validée. Dans l'exemple précédent, si la première condition est `accidents_df$diff_time_num >= 0 | accidents_df$diff_time_num <= 120`, alors nous obtenons pour seule valeur en résultat `\"pointe matin\"` puisque chaque observation a une valeur supérieure à 0 et que nous avons remplacé l'opérateur `&` (ET) par l'opérateur `|` (OU). \n\n#### Sous-sélection d'un *DataFrame* {#sec-01428}\n\nDans cette section, nous voyons comment extraire des sous-parties d'un *DataFrame*. Il est possible de sous-sélectionner des lignes et des colonnes en se basant sur des conditions ou leur index. Pour cela, nous utilisons un jeu de données fourni avec R : le jeu de données **iris** décrivant des fleurs du même nom.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndata(\"iris\")\n\n# Nombre de lignes et de colonnes\ndim(iris)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 150 5\n```\n:::\n:::\n\n\n##### Sous-sélection des lignes {#sec-014281}\n\nSous-sélectionner des lignes par index est relativement simple. Admettons que nous souhaitons sélectionner les lignes 1 à 5, 10 à 25, 37 et 58.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nsub_iris <- iris[c(1:5, 10:25, 37, 58),]\nnrow(sub_iris)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 23\n```\n:::\n:::\n\n\nSous-sélectionner des lignes avec une condition peut être effectué soit avec une syntaxe similaire, soit en utilisant la fonction `subset`. Sélectionnons toutes les fleurs de l'espèce Virginica.\n\n\n::: {.cell}\n\n```{.r .cell-code}\niris_virginica1 <- iris[iris$Species == \"virginica\",]\niris_virginica2 <- subset(iris, iris$Species == \"virginica\")\n\n# Vérifions que les deux DataFrames ont le même nombre de lignes\nnrow(iris_virginica1) == nrow(iris_virginica2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] TRUE\n```\n:::\n:::\n\n\nVous pouvez utiliser, dans les deux cas, tous les opérateurs vus dans les sections [-@sec-01351] et [-@sec-01353]. L'enjeu est d'arriver à créer un vecteur booléen final permettant d'identifier les observations à conserver.\n\n##### Sous-sélection des colonnes {#sec-014282}\n\nNous avons déjà vu comment sélectionner des colonnes en utilisant leur nom ou leur index dans la [section @sec-014221]. Ajoutons ici un cas particulier où nous souhaitons sélectionner des colonnes selon une condition. Par exemple, nous pourrions vouloir conserver que les colonnes comprenant le mot *Length*. Pour cela, nous utilisons la fonction `grepl`, permettant de déterminer si des caractères sont présents dans une chaîne de caractères.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nnom_cols <- names(iris)\nprint(nom_cols)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"Sepal.Length\" \"Sepal.Width\" \"Petal.Length\" \"Petal.Width\" \"Species\" \n```\n:::\n\n```{.r .cell-code}\ntest_nom <- grepl(\"Length\", nom_cols, fixed = TRUE)\nok_nom <- nom_cols[test_nom]\n\niris_2 <- iris[ok_nom]\nprint(names(iris_2))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"Sepal.Length\" \"Petal.Length\"\n```\n:::\n:::\n\n\nIl est possible d'obtenir ce résultat en une seule ligne de code, mais elle est un peu moins lisible.\n\n\n::: {.cell}\n\n```{.r .cell-code}\niris2 <- iris[names(iris)[grepl(\"Length\", names(iris), fixed = TRUE)]]\n```\n:::\n\n\n##### Sélection des colonnes et des lignes {#sec-014283}\n\nNous avons vu qu'avec les crochets `[]`, nous pouvons extraire les colonnes et les lignes d'un *DataFrame*. Il est possible de combiner les deux opérations simultanément. Pour ce faire, il faut indiquer en premier les index ou la condition permettant de sélectionner une ligne, puis les index ou la condition pour sélectionner les colonnes : `[index_lignes , index_colonnes]`. Sélectionnons cinq premières lignes et les trois premières colonnes du jeu de données iris : \n\n\n::: {.cell}\n\n```{.r .cell-code}\niris_5x3 <- iris[c(1,2,3,4,5), c(1,2,3)]\nprint(iris_5x3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Sepal.Length Sepal.Width Petal.Length\n1 5.1 3.5 1.4\n2 4.9 3.0 1.4\n3 4.7 3.2 1.3\n4 4.6 3.1 1.5\n5 5.0 3.6 1.4\n```\n:::\n:::\n\n\nCombinons nos deux exemples précédents pour sélectionner uniquement les lignes avec des fleurs de l'espèce *virginica*, et les colonnes avec le mot *Length*.\n\n\n::: {.cell}\n\n```{.r .cell-code}\niris_virginica3 <- iris[iris$Species == \"virginica\",\n names(iris)[grepl(\"Length\", names(iris), fixed = TRUE)]]\nhead(iris_virginica3, n=5)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Sepal.Length Petal.Length\n101 6.3 6.0\n102 5.8 5.1\n103 7.1 5.9\n104 6.3 5.6\n105 6.5 5.8\n```\n:::\n:::\n\n\n#### Fusion de *DataFrames* {#sec-01429}\n\nTerminons cette section avec la fusion de *DataFrames*. Nous distinguons deux méthodes répondant à des besoins différents : par ajout ou par jointure.\n\n##### Fusion de *DataFrames* par ajout {#sec-014291}\n\nAjouter deux *DataFrames* peut se faire en fonction de leurs colonnes ou en fonction de leurs lignes. Dans ces deux cas, nous utilisons respectivement les fonctions `cbind` et `rbind`. La @fig-fig016 résume graphiquement le fonctionnement des deux fonctions.\n\n![Fusion de DataFrames](images/Chap01/rbind_cbind.png){#fig-fig016 width=\"30%\" fig-align=\"center\"}\n\nPour que `cbind` fonctionne, il faut que les deux *DataFrames* aient le même nombre de lignes. Pour `rbind`, les deux *DataFrames* doivent avoir le même nombre de colonnes. Prenons à nouveau comme exemple le jeu de données iris. Nous commençons par le séparer en trois sous-jeux de données comprenant chacun une espèce d'iris. Puis, nous fusionnons deux d'entre eux avec la fonction `rbind`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\niris1 <- subset(iris, iris$Species == \"virginica\")\niris2 <- subset(iris, iris$Species == \"versicolor\")\niris3 <- subset(iris, iris$Species == \"setosa\")\n\niris_comb <- rbind(iris2,iris3)\n```\n:::\n\n\nNous pourrions aussi extraire dans les deux *DataFrames* les colonnes comprenant le mot *Length* et le mot *Width*, puis les fusionner.\n\n\n::: {.cell}\n\n```{.r .cell-code}\niris_l <- iris[names(iris)[grepl(\"Length\", names(iris), fixed = TRUE)]]\niris_w <- iris[names(iris)[grepl(\"Width\", names(iris), fixed = TRUE)]]\n\niris_comb <- cbind(iris_l,iris_w)\nnames(iris_comb)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"Sepal.Length\" \"Petal.Length\" \"Sepal.Width\" \"Petal.Width\" \n```\n:::\n:::\n\n\n##### Jointure de *DataFrames* {#sec-014292}\n\nUne jointure est une opération un peu plus complexe qu'un simple ajout. L'idée est d'associer des informations de plusieurs *DataFrames* en utilisant une colonne (appelée une clef) présente dans les deux jeux de données. Nous distinguons plusieurs types de jointure : \n\n* Les jointures internes permettant de combiner les éléments communs entre deux *DataFrames* A **et** B.\n\n* La jointure complète permettant de combiner les éléments présents dans A **ou** B.\n\n* La jointure à gauche, permettant de ne conserver que les éléments présents dans A même s'ils n'ont pas de correspondance dans B.\n\nCes trois jointures sont présentées à la @fig-fig017; pour ces trois cas, la colonne commune se nomme *id*.\n\n\n![Jointure de DataFrames](images/Chap01/merging.png){#fig-fig017 width=\"30%\" fig-align=\"center\"}\n\nVous retiendrez que les deux dernières jointures peuvent produire des valeurs manquantes. Pour réaliser ces opérations, nous utilisons la fonction `merge`. Prenons un exemple simple à partir d'un petit jeu de données.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nauteurs <- data.frame(\n name = c(\"Tukey\", \"Venables\", \"Tierney\", \"Ripley\", \"McNeil\", \"Apparicio\"),\n nationality = c(\"US\", \"Australia\", \"US\", \"UK\", \"Australia\", \"Canada\"),\n retired = c(\"yes\", rep(\"no\", 5)))\nlivres <- data.frame(\n aut = c(\"Tukey\", \"Venables\", \"Tierney\", \"Ripley\", \"Ripley\", \"McNeil\" , \"Wickham\"),\n title = c(\"Exploratory Data Analysis\",\n \"Modern Applied Statistics ...\",\n \"LISP-STAT\",\n \"Spatial Statistics\", \"Stochastic Simulation\",\n \"Interactive Data Analysis\", \"R for Data Science\"))\n```\n:::\n\n\nNous avons donc deux *DataFrames*, le premier décrivant des auteurs et le second des livres. Effectuons une première jointure interne afin de savoir pour chaque livre la nationnalité de son auteur et si ce dernier est à la retraite.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf1 <- merge(livres, auteurs, #les deux DataFrames \n by.x = \"aut\", by.y = \"name\", #les noms des colonnes de jointures\n all.x = FALSE, all.y = FALSE)\nprint(df1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n aut title nationality retired\n1 McNeil Interactive Data Analysis Australia no\n2 Ripley Spatial Statistics UK no\n3 Ripley Stochastic Simulation UK no\n4 Tierney LISP-STAT US no\n5 Tukey Exploratory Data Analysis US yes\n6 Venables Modern Applied Statistics ... Australia no\n```\n:::\n:::\n\n\nCette jointure est interne, car les deux paramètres *all.x* et *all.y* ont pour valeur `FALSE`. Ainsi, nous indiquons à la fonction que nous ne souhaitons ni garder tous les éléments du premier *DataFrame* ni tous les éléments du second, mais uniquement les éléments présents dans les deux. Vous noterez ainsi que le livre \"R for Data Science\" n'est pas présent dans le jeu de données final, car son auteur \"Wickham\" ne fait pas partie du *DataFrame* auteurs. De même, l'auteur \"Apparicio\" n'apparaît pas dans la jointure, car aucun livre dans le *DataFrame* books n'a été écrit par cet auteur.\n\nPour conserver tous les livres, nous pouvons effectuer une jointure à gauche en renseignant `all.x = TRUE`. Nous forçons ainsi la fonction à garder tous les livres et à mettre des valeurs vides aux informations manquantes des auteurs.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf2 <- merge(livres, auteurs, #les deux DataFrames \n by.x = \"aut\", by.y = \"name\", #les noms des colonnes de jointures\n all.x = TRUE, all.y = FALSE)\nprint(df2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n aut title nationality retired\n1 McNeil Interactive Data Analysis Australia no\n2 Ripley Spatial Statistics UK no\n3 Ripley Stochastic Simulation UK no\n4 Tierney LISP-STAT US no\n5 Tukey Exploratory Data Analysis US yes\n6 Venables Modern Applied Statistics ... Australia no\n7 Wickham R for Data Science \n```\n:::\n:::\n\n\nPour garder tous les livres et tous les auteurs, nous pouvons faire une jointure complète en indiquant `all.x = TRUE` et `all.y = TRUE`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf3 <- merge(livres, auteurs, #les deux DataFrames \n by.x = \"aut\", by.y = \"name\", #les noms des colonnes de jointures\n all.x = TRUE, all.y = TRUE)\nprint(df3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n aut title nationality retired\n1 Apparicio Canada no\n2 McNeil Interactive Data Analysis Australia no\n3 Ripley Spatial Statistics UK no\n4 Ripley Stochastic Simulation UK no\n5 Tierney LISP-STAT US no\n6 Tukey Exploratory Data Analysis US yes\n7 Venables Modern Applied Statistics ... Australia no\n8 Wickham R for Data Science \n```\n:::\n:::\n\n\n## Code R bien structuré {#sec-016}\n\nTerminons ici avec quelques conseils sur la rédaction d’un code R. Bien rédiger son code est essentiel pour trois raisons :\n\n1. Pouvoir relire et réutiliser son code dans le futur.\n2. Permettre à d'autres personnes de bien lire et de réutiliser votre code.\n3. Minimiser les risques d'erreurs.\n\nNe négligez pas l'importance d'un code bien rédigé et bien documenté, vous vous éviterez ainsi des migraines lorsque vous devrez exhumer du code écrit il y a plusieurs mois.\n\nVoici quelques lignes directrices peu contraignantes, mais qui devraient vous être utiles : \n\n1. **Privilégier la clarté à la concision** : il vaut mieux parfois scinder une ligne de code en plusieurs sous-étapes afin de faciliter la lecture de l’opération réalisée. Par exemple, si nous reprenons une ligne de code d’une section précédente où nous sélectionnions l'ensemble des colonnes du jeu de données `iris` comprenant le mot `Length` : \n\n::: {.cell}\n\n```{.r .cell-code}\niris_l <- iris[names(iris)[grepl(\"Length\", names(iris), fixed = TRUE)]]\n```\n:::\n\n\nNous pouvons simplifier la lecture de ce code en détaillant les différentes étapes comme suit : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nnoms_cols <- names(iris)\nsel_noms <- noms_cols[grepl(\"Length\", noms_cols, fixed = TRUE)]\niris_l <- iris[sel_noms]\n```\n:::\n\n\n2. **Documenter et commenter son code le plus possible** : il est possible d'ajouter du texte dans un code R qui ne sera pas exécuté, ce que nous appelons des commentaires. Typiquement, une ligne commençant par un `#` n'est pas interprétée par le logiciel. Utilisez des commentaires le plus souvent possible pour décrire les actions que vous souhaitez effectuer avec votre code. Il sera ainsi plus facile de le relire, de naviguer dedans, mais également de repérer d'éventuelles erreurs. Si nous reprenons l'exemple précédent : \n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Récupération du nom des colonnes dans le DataFrame iris\nnoms_cols <- names(iris)\n# Sélection des colonnes avec les caractères \"Length\"\nsel_noms <- noms_cols[grepl(\"Length\", noms_cols, fixed = TRUE)]\n# Extraction des colonnes sélectionnées dans un nouveau DataFrame\niris_l <- iris[sel_noms]\n```\n:::\n\n\n3. **Éviter le code à rallonge…** : typiquement, essayez de vous limiter à des lignes de code d'une longueur maximale de 80 caractères. Au-delà de ce seuil, il est judicieux de découper votre code en plusieurs lignes.\n\n4. **Adopter une convention d'écriture** : une convention d'écriture est un ensemble de règles strictes définissant comment un code doit être rédigé. À titre d'exemple, il est parfois recommandé d'utiliser le *lowerCamelCase*, le *UpperCamelCase*, ou encore de séparer les mots par des tirets bas *upper_camel_case*. Un mélange de ces différentes conventions peut être utilisé pour distinguer les variables, les fonctions et les classes. Il peut être difficile de réellement arrêter une telle convention, car les différents *packages* dans R utilisent des conventions différentes. Dans vos propres codes, il est surtout important d'avoir une certaine cohérence et ne pas changer de convention.\n\n5. **Indenter le code** : l'indentation du code permet de le rendre beaucoup plus lisible. Indenter son code signifie d'insérer, au début de chaque ligne de code, un certain nombre d'espaces permettant d'indiquer à quel niveau de profondeur nous nous situons. Typiquement, lorsque des accolades ou des parenthèses sont ouvertes dans une fonction, une boucle ou une condition, nous rajoutons deux ou quatre espaces en début de ligne. Prenons un exemple très concret : admettons que nous écrivons une fonction affichant un résumé statistique à chaque colonne d'un jeu de données si cette colonne est de type numérique. L'indentation dans cette fonction joue un rôle crucial dans sa lisibilité. \nSans indentation et sans respecter la règle des 80 caractères, nous obtenons ceci : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nsummary_all_num_cols <- function(dataset){for(col in names(dataset)){if(class(dataset[[col]] == \"numeric\")){print(summary(dataset[[col]]))}}}\n```\n:::\n\n\nAvec de l'indentation et des commentaires, la syntaxe est beaucoup plus lisible puisqu’elle permet de repérer facilement trois niveaux/paliers dans le code : \n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Définition d'une fonction\nsummary_all_num_cols <- function(dataset){\n # Itération sur chaque colonne de la fonction\n for(col in names(dataset)){\n # A chaque itération, testons si la colonne est de type numérique\n if(class(dataset[[col]] == \"numeric\")){\n # Si oui, nous affichons un résumé statistique pour cette colonne\n print(summary(dataset[[col]]))\n } # Ici nous sortons de la condition (niveau 3)\n } # Ici nous sortons de la boucle (niveau 2)\n} # Ici nous sortons de la fonction (niveau 1)\n```\n:::\n\n\n6. **Adopter une structure globale pour vos scripts** : un code R peut être comparé à une recette de cuisine. Si tous les éléments sont dans le désordre et sans structure globale, la recette risque d'être très difficile à suivre. Cette structure risque de changer quelque peu en fonction de la recette ou de l'auteur(e), mais les principaux éléments restent les mêmes. Dans un code R, nous pouvons distinguer plusieurs éléments récurrents que nous vous recommandons d'organiser de la façon suivante : \n \n a. Charger les différents *packages* **utilisés** par le script. Cela permet dès le début du code de savoir quelles sont les fonctions et méthodes qui seront employées dans le script. Cela limite aussi les risques d'oublier des *packages* qui seraient chargés plus loin dans le code.\n \n b. Définir les fonctions dont vous aurez besoin en plus de celles présentes dans les *packages.* Idem, placer nos fonctions en début de code évite d'oublier de les charger ou de les chercher quand nous en avons besoin.\n \n c. Définir le répertoire de travail avec la fonction `setwd` et charger les données nécessaires.\n \n d. Effectuer au besoin les opérations de manipulation sur les données.\n \n e. Effectuer les analyses nécessaires en scindant si possible les différentes étapes. Notez également que l'étape de définition des fonctions complémentaires peut être effectuée dans une feuille de code séparée, et l'ensemble de ces fonctions chargées à l'aide de la fonction `source`. De même, si la manipulation des données est conséquente, il est recommandé de l'effectuer avec un code à part, d'enregistrer les données structurées, puis de les charger directement au début de votre code dédié à l'analyse.\n\n7. **Exploiter les commentaires délimitant les sections dans RStudio** : il est possible d'écrire des commentaires d'une certaine façon pour que l'IDE les détecte comme des délimiteurs de sections. L'intérêt principal est que nous pouvons ensuite facilement naviguer entre ces sections en utilisant RStudio comme montré à la @fig-sectionsRstudio, mais aussi masquer des sections afin de faciliter la lecture du reste du code. Pour délimiter une section, il suffit d'ajouter une ligne de commentaire comprenant quatre fois les caractères `-`, `=` ou `#` à la suite. \n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Voici ma section 1 ----------------------------------\n\n# Voici ma section 2 ==================================\n\n# Voici ma section 3 ##################################\n\n# Autre exemple pour mieux marquer la rupture dans un code : \n\n#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#### Titre de ma section 4 ####\n#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n```\n:::\n\n\n![Navigation dans des sections de codes avec RStudio](images/Chap01/sections_rstudio.png){#fig-sectionsRstudio width=\"100%\" fig-align=\"center\"}\n\n8. **Adopter une structure globale pour vos projets** : au-delà du script, il est nécessaire de bien structurer vos projets, le plus important étant d'utiliser une structure commune à chaque projet pour vous faciliter le travail. Nous proposons à la @fig-structFolder un exemple de structure assez générale pouvant être utilisée dans la plupart des cas. Elle sépare notamment les données originales des données structurées, ainsi que les fonctions complémentaires et la structuration des données du principal bloc d'analyse.\n\n\n![Structure de dossier recommandée pour un projet avec R](images/Chap01/structurationprojet.png){#fig-structFolder width=\"50%\" fig-align=\"center\"}\n\n\n**Ne négligez jamais l'importance d'un code bien écrit et documenté !**\n\n## Enregistrement des résultats {#sec-017}\n\nComme nous l'avons indiqué précédemment, l'ensemble des objets actuellement chargés dans votre session R sont perdus si vous la fermez. Cela peut être problématique si certains résultats nécessitent de longs temps de calcul ou si vous avez besoin de partager les objets obtenus avec d'autres personnes, mais pas le code pour les obtenir. Il est possible de retrouver les résultats d'une session précédente si ceux-ci ont été enregistrés sur votre disque dur puisque l'action d'enregistrer permet de faire passer vos objets présents dans votre mémoire vive dans des fichiers stockés sur votre disque dur. Vous pouvez pour cela utiliser la fonction `save.image` ou `save`.\n\n`save.image` enregistre une copie exacte de votre session actuelle avec tous les objets présents dans votre environnement dans un fichier `RData`. La fonction `save` permet d'être plus sélectif et de ne garder que certains objets spécifiques.\n\nVoici la syntaxe pour enregistrer toute votre session :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nsave.image(file = 'chemin/vers/mon/fichier/session.RData', compress = TRUE)\n```\n:::\n\n\nVous pouvez aussi utiliser le bouton d'enregistrement dans l'onglet *Environnement* dans RStudio (@fig-saveobj).\n\n\n![Bouton enregistrer la session](images/Chap01/save_session.png){#fig-saveobj width=\"25%\" fig-align=\"center\"}\n\nIl est recommandé de compresser ces fichiers (`compress = TRUE`) pour minimiser leur taille. Pour n'enregistrer que certains objets (ici `iris` et `noms_cols`), vous pouvez adapter cette syntaxe :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nsave(iris, noms_cols, file = 'chemin/vers/mon/fichier/mes_objet.RData', compress = TRUE)\n```\n:::\n\n\nPour récupérer ces objets dans une autre session, il suffit d'utiliser la fonction `load` :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nload(file = 'chemin/vers/mon/fichier/mes_objet.RData')\n```\n:::\n\n\nou d'utiliser le bouton *ouvrir* de l'onglet *Environnement* dans RStudio (@fig-loadobj).\n\n![Bouton charger un fichier RDA](images/Chap01/load_session.png){#fig-loadobj width=\"25%\" fig-align=\"center\"}\n\n## Session de travail {#sec-018}\n\nComme vous avez pu le constater dans les sections @sec-017 et @sec-0141, il est nécessaire de connaître les chemins vers les fichiers que vous souhaitez utiliser dans votre code R. Si tous ces fichiers sont organisés dans un même dossier (ce que nous vous recommandons à la @fig-structFolder, il est possible de définir un répertoire de travail avec la fonction `setwd`.\nIl est recommandé d'effectuer cette étape au début de votre code R, après le chargement des *packages*. Ainsi, vous n'aurez pas besoin de réécrire à chaque fois le chemin complet pour accéder à vos fichiers.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Chemin complet\nmes_donnes <- read.csv(\"C:/projets/articles/2022/mon_projet/data/mes_donnes.csv\")\n# Utilisation de setwd\nsetwd(\"C:/projets/articles/2022/mon_projet\")\nmes_donnes <- read.csv(\"data/mes_donnes.csv\")\n```\n:::\n\n\nLa fonction `getwd` permet d'afficher le répertoire de travail utilisé actuellement par R.\n\nSi vous utilisez RStudio, il est possible d'utiliser une petite astuce pour définir comme répertoire de travail le dossier dans lequel se trouve le fichier de code R que vous utilisez actuellement :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nsetwd(dirname(rstudioapi::getActiveDocumentContext()$path))\n```\n:::\n\n\nAdmettons que votre code R se trouve dans un sous dossier appelé *CodeR* de votre répertoire de travail, vous pouvez remonter d'un niveau dans votre arborescence en utilisant la syntaxe suivante :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nsetwd(paste0(dirname(rstudioapi::getActiveDocumentContext()$path), \"/..\"))\n```\n:::\n\n\nLe double point (`..`) indique que nous souhaitons remonter dans le dossier parent du dossier dans lequel nous se trouvons acutellement.\n\nIl existe deux solutions de rechange à l'utilisation de `setwd` que certains jugent un peu démodé.\n\n* La première est le package `here` permettant de spécifier plus facilement des chemins relatifs et de définir un *top-level directory* pour votre projet.\n* La seconde est l'utilisation de la fonctionnalité [projects](https://support.rstudio.com/hc/en-us/articles/200526207-Using-Projects) de RStudio.\n\n## Conclusion et ressources pertinentes {#sec-019}\n\nVoilà qui conclut ce chapitre sur les bases du langage R. Vous avez maintenant les connaissances nécessaires pour commencer à travailler. N'hésitez pas à revenir sur les différentes sous-sections au besoin! Quelques ressources pertinentes qui pourraient vous être utiles sont aussi reportées au @tbl-tableRessources \n\n\n\n::: {#tbl-tableRessources .cell tbl-cap='Ressources pertinente pour en apprendre plus sur R'}\n::: {.cell-output-display}\n|Ressource |Description |\n|:-------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------|\n|[Rbloggers](https://www.r-bloggers.com){target='_blank'}|Un recueil de nombreux blogues sur R : parfait pour être tenu au courant des nouveautés et faire des découvertes. |\n|[CRAN packages by date](https://cran.r-project.org/web/packages/available_packages_by_date.html){target='_blank'}|Les derniers packages publiés sur *CRAN* : cela permet de garder un oeil sur les nouvelles fonctionnalités de vos packages préférés. |\n|[Introduction à R et au TidyVerse](https://juba.github.io/tidyverse/index.html){target='_blank'}|Une excellente ressource en français pour en apprendre plus sur le tidyverse. |\n|[Numyard](https://www.youtube.com/user/TheLearnR/featured){target='_blank'}|Une chaîne YouTube pour revoir les bases de R en vidéo. |\n|[cheatsheets](https://rstudio.com/resources/cheatsheets){target='_blank'}|Des feuilles de triche résumant les fonctionnalités de nombreux packages. |\n:::\n:::\n\n\n## Quiz de révision du chapitre {#sec-0110}\n\n\n
\n\n\n\n
\n
Avec quelle fonction peut-on sélectionner son répertoire de travail?
\n
Relisez au besoin la [section @sec-018].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Installer RStudio est suffisant pour pouvoir utiliser R.
\n
Relisez au besoin le début de la [section @sec-012].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Un package doit être réinstallé à chaque fois que l'on souhaite l'utiliser.
\n
Relisez au besoin la [section @sec-0123].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
La brique de données élémentaire dans R est :
\n
Relisez au besoin la [section @sec-0136].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Un vecteur peut contenir :
\n
Relisez au besoin la [section @sec-0136].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
La jointure et la concaténation de DataFrames désignent exactement la même opération.
\n
Relisez au besoin la [section @sec-01429].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Comparativement à une jointure complète, une jointure interne génère un DataFrame avec :
\n
Relisez le deuxième encadré à la [section @sec-014292].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n\n
\n\n
\n
\n", + "supporting": [ + "01-priseenmainR_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/01-priseenmainR_files/figure-html/fig-fig015-1.png b/.quarto/_freeze/01-priseenmainR/figure-html/fig-fig015-1.png similarity index 100% rename from docs/01-priseenmainR_files/figure-html/fig-fig015-1.png rename to .quarto/_freeze/01-priseenmainR/figure-html/fig-fig015-1.png diff --git a/.quarto/_freeze/02-univarie/execute-results/html.json b/.quarto/_freeze/02-univarie/execute-results/html.json new file mode 100644 index 0000000..8a7b38d --- /dev/null +++ b/.quarto/_freeze/02-univarie/execute-results/html.json @@ -0,0 +1,16 @@ +{ + "hash": "fc8324434d2e9132cbe9ccdb87e15a5e", + "result": { + "markdown": "# Statistiques descriptives univariées {#sec-chap02}\n\nComprendre la notion de variable et de ses différents types est essentiel en statistiques. En effet, en fonction du type de variable à l'étude, les méthodes de statistique exploratoire ou inférentielle sont différentes. Nous distinguons ainsi cinq types de variables : nominale, ordinale, discrète, continue et semi-quantitative. Aussi, nous abordons un concept central de la statistique : les distributions. Finalement, dans ce chapitre, nous présentons les différentes statistiques descriptives univariées qui peuvent s’appliquer à ces types de variables.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes quantiles-quantiles.\n* Pour créer des distributions :\n - `fitdistrplus` pour générer différentes distributions.\n - `actuar` pour la fonction de densité de Pareto.\n - `gamlss.dist` pour des distributions de Poisson.\n* Pour les statistiques descriptives :\n - `stats` et `moments` pour les statistiques descriptives.\n - `nortest` pour le test de Kolmogorov-Smirnov.\n - `DescTools` pour les tests de Lilliefors, Shapiro-Wilk, Anderson-Darling et Jarque-Bera.\n* Autres *packages* :\n - `Hmisc` et `Weighted.Desc.Stat` pour les statistiques descriptives pondérées.\n - `foreign` pour importer des fichiers externes.\n:::\n:::\n\n## Notion et types de variable {#sec-021}\n\n### Notion de variable {#sec-0211}\n\nD'un point de vue empirique, une variable est une propriété, une caractéristique d'une unité statistique, d'une observation. Il convient alors de bien saisir à quelle unité d'analyse (ou unité d'observation) s'appliquent les valeurs d'une variable : des personnes, des ménages, des municipalités, des entreprises, etc. Par exemple, pour des individus, l'*âge*, le *genre* ou encore le *revenu* sont autant de caractéristiques qui peuvent être mesurées à partir de variables. Autrement dit, une variable permet de mesurer un phénomène (dans un intervalle de valeurs, c'est-à-dire de manière quantitative) ou de le qualifier (avec plusieurs catégories, c'est-à-dire de manière qualitative).\n\nD'un point de vue plus théorique, une variable permet d'opérationnaliser un concept en sciences sociales [@gilles1994elements, p.30], soit une « idée générale et abstraite que se fait l'esprit humain d'un objet de pensée concret ou abstrait, et qui lui permet de rattacher à ce même objet les diverses perceptions qu'il en a, et d'en organiser les connaissances » ([Larousse](https://www.larousse.fr/dictionnaires/francais/concept/17875?q=concept#17749){target=\"_blank\"}). En effet, la construction d'un modèle théorique suppose d'opérationnaliser différents concepts et d'établir les relations qu'ils partagent entre eux. Or, l'opérationnalisation d'un concept nécessite soit de mesurer (dans un intervalle de valeurs, c'est-à-dire de manière quantitative), soit de qualifier (avec plusieurs catégories, c'est-à-dire de manière qualitative) un phénomène. \n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Maîtriser la définition des variables que vous utilisez : un enjeu crucial! **\n:::\n::: bloc_attention-body\nNe pas maîtriser la définition d'une variable revient à ne pas bien saisir la caractéristique ou encore le concept sous-jacent qu'elle tente de mesurer. Si vous exploitez des données secondaires – par exemple, issues d'un recensement de population ou d'une enquête longitudinale ou transversale –, il faut impérativement lire les définitions des variables que vous souhaitez utiliser. Ne pas le faire risque d'aboutir à :\n\n* Une mauvaise opérationnalisation de votre modèle théorique, même si votre analyse est bien menée statistiquement parlant. Autrement dit, vous risquez de ne pas sélectionner les bonnes variables : prenons un exemple concret. Vous avez construit un modèle théorique dans lequel vous souhaitez inclure un concept sur la langue des personnes. Dans le recensement canadien de 2016, plusieurs variables relatives à la langue sont disponibles : [connaissance des langues officielles, langue parlée à la maison, langue maternelle, première langue officielle parlée, connaissance des langues non officielles et langue de travail] (https://www12.statcan.gc.ca/census-recensement/2016/ref/guides/003/98-500-x2016003-fra.cfm). La sélection de l'une de ces variables doit être faite de manière rigoureuse, c'est-à-dire en lien avec votre cadre théorique et suite à une bonne compréhension des définitions des variables. Dans une étude sur le marché du travail, nous sélectionnerions probablement la variable *sur la connaissance des langues officielles du Canada*, afin d'évaluer son effet sur l'employabilité, toutes choses étant égales par ailleurs. Dans une autre étude portant sur la réussite ou la performance scolaire, il est probable que nous utiliserions la *langue maternelle*.\n\n* Une mauvaise interprétation et discussion de vos résultats en lien avec votre cadre théorique.\n\n* Une mauvaise identification des pistes de recherche.\n\nFinalement, la définition d'une variable peut évoluer à travers plusieurs recensements de population : la société évolue, les variables aussi! Par conséquent, si vous comptez utiliser plusieurs années de recensement dans une même étude, assurez-vous que les définitions des variables sont similaires d'un jeu de données à l'autre et qu'elles mesurent ainsi la même chose. \n\n**Comprendre les variables utilisées dans un article scientifique : un exercice indispensable dans l'élaboration d'une revue de littérature**\n\nUne lecture rigoureuse d'un article scientifique suppose, entre autres, de bien comprendre les concepts et les variables mobilisés. Il convient alors de lire attentivement la section méthodologique (pas uniquement la section des résultats ou pire, celle du résumé), sans quoi vous risquez d'aboutir à une revue de littérature approximative. \nAyez aussi un **regard critique** sur les variables utilisées en lien avec le cadre théorique. Certains concepts sont très difficiles à traduire en variables; leurs opérationnalisations (mesures) peuvent ainsi faire l'objet de vifs débats au sein de la communauté scientifique. Très succinctement, c'est notamment le cas du concept de capital social. D'une part, les définitions et ancrages sont bien différents selon Bourdieu (sociologue, ancrage au niveau des individus) et Putman (politologue, ancrage au niveau des collectivités); d'autre part, aucun consensus ne semble clairement se dégager quant à la définition de variables permettant de mesurer le capital social efficacement (de manière quantitative). \n\n**Variable de substitution (*proxy variable* en anglais)**\n\nNous faisons la moins pire des recherches! En effet, les données disponibles sont parfois imparfaites pour répondre avec précision à une question de recherche; nous pouvons toujours les exploiter, tout en signalant honnêtement leurs faiblesses et limites, et ce, tant pour les données que pour les variables utilisées.\n\n* Des bases de données peuvent être en effet imparfaites. Par exemple, en criminologie, lorsqu'une étude est basée sur l'exploitation de données policières, la limite du **chiffre noir** est souvent signalée : les données policières comprennent uniquement les crimes et délits découverts par la police et occultent ainsi les crimes non découverts; ils ne peuvent ainsi refléter la criminalité réelle sur un territoire donné.\n\n* Des variables peuvent aussi être imparfaites. Dans un jeu de données, il est fréquent qu'une variable ne soit pas disponible ou qu'elle n'ait tout simplement pas été mesurée. Nous cherchons alors une variable de substitution (*proxy*) pour la remplacer. Prenons un exemple concret portant sur l'exposition des cyclistes à la pollution atmosphérique ou au bruit environnemental. L'un des principaux facteurs d'exposition à ces pollutions est le trafic routier : plus ce dernier est élevé, plus les cyclistes risquent de rouler dans un environnement bruyant et pollué. Toutefois, il est rare de disposer de mesures du trafic en temps réel qui nécessitent des comptages de véhicules pendant le trajet des cyclistes (par exemple, à partir de vidéos captées par une caméra fixée sur le guidon). Pour pallier l'absence de mesures directes, plusieurs auteur(e)s utilisent des variables de substitution de la densité du trafic, comme la typologie des types d'axes (primaire, secondaire, tertiaire, rue locale, etc.), supposant ainsi qu'un axe primaire supporte un volume de véhicules supérieur à un axe secondaire.\n:::\n:::\n\n### Types de variables {#sec-0212}\nNous distinguons habituellement les variables qualitatives (nominale ou ordinale) des variables quantitatives (discrète ou continue). Comme illustré à la @fig-univarie1, plusieurs mécanismes différents visent à qualifier, à classer, à compter ou à mesurer afin de caractériser les unités statistiques (observations) d'une population ou d'un échantillon.\n\n![Types de variables](images/Chap02/figure1.jpg){#fig-univarie1 width=\"70%\" fig-align=\"center\"}\n\n\n#### Variables qualitatives {#sec-02121}\n\n**Une variable nominale** permet de **qualifier** des observations (individus) à partir de plusieurs catégories dénommées modalités. Par exemple, la variable _couleur des yeux_ pourrait comprendre les modalités _bleu_, _marron_, _vert_, _noir_ tandis que le *type de famille* comprendrait les modalités _couple marié_, _couple en union libre_ et _famille monoparentale_.\n\n**Une variable ordinale** permet de **classer** des observations à partir de plusieurs modalités hiérarchisées. L'exemple le plus connu est certainement l'échelle de Likert, très utilisée dans les sondages évaluant le degré d'accord d'une personne à une affirmation avec les modalités suivantes : *tout à fait d'accord*, *d'accord*, *ni en désaccord ni d'accord*, *pas d'accord* et *pas du tout d'accord*. Une multitude de variantes sont toutefois possibles pour classer la fréquence d'un phénomène (*très souvent*, *souvent*, *parfois*, *rarement*, *jamais*), l'importance accordée à un phénomène (*pas du tout important*, *peu important*, *plus ou moins important*, *important*, *très important*) ou la proximité perçue d'un lieu (*très éloigné*, *loin*, *plus ou moins proche*, *proche*, *très proche*).\n\nEn fonction du nombre de modalités qu'elle comprend, une variable qualitative (nominale ou ordinale) est soit **dichotomique (binaire)** (deux modalités), soit **polytomique** (plus de deux modalités). Par exemple, dans le recensement canadien, le *sexe* est une variable binaire (avec les modalités *sexe masculin*, *sexe féminin*), tandis que le *genre* est une variable polytomique (avec les modalités *genre masculin*, *genre féminin* et *diverses identités de genre*).\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Fréquences pour des variables nominales et ordinales**\n:::\n::: bloc_attention-body\nLes variables nominales et ordinales sont habituellement encodées avec des valeurs numériques entières (par exemple, 1 pour _couple marié_, 2 pour _couple en union libre_ et 3 pour _famille monoparentale_). Toutefois, aucune opération arithmétique (moyenne ou écart-type par exemple) n'est possible sur ces valeurs. Dans R, nous utilisons un facteur pour attribuer un intitulé à chacune des valeurs numériques de la variable qualitative :\n\n`df$Famille <- factor(df$Famille, c(1,2,3), \nlabels = c(\"couple marié\" , \"couple en union libre\", \"famille monoparentale\"))`\n\nNous calculons toutefois les fréquences des différentes modalités pour une variable nominale ou ordinale. Il est aussi possible de calculer la médiane sur une variable ordinale.\n:::\n:::\n\n\n\n#### Variables quantitatives {#sec-02122}\n\n**Une variable discrète** permet de **compter** un phénomène dans un ensemble fini de valeurs, comme le nombre d'accidents impliquant un ou une cycliste à une intersection sur une période de cinq ans ou encore le nombre de vélos en libre-service disponibles à une station. Il existe ainsi une variable binaire sous-jacente : la présence ou non d'un accident à l'intersection ou la disponibilité d'un vélo ou non à la station pour laquelle nous opérons un comptage. Habituellement, une variable discrète ne peut prendre que des valeurs entières (sans décimale), comme le nombre de personnes fréquentant un parc.\n\n**Une variable continue** permet de **mesurer** un phénomène avec un nombre infini de valeurs réelles (avec décimales) dans un intervalle donné. Par exemple, une variable relative à la distance de dépassement d'un ou d'une cycliste par un véhicule motorisé pourrait varier de 0 à 5 mètres ($X \\in \\left[0,5\\right]$); toutefois, cette distance peut être de 0,759421 ou de 4,785612 mètres. Le nombre de décimales de la valeur réelle dépend de la précision et de la fiabilité de la mesure. Pour un capteur de distance de dépassement, le nombre de décimales dépend de la précision du lidar ou du sonar de l'appareil; aussi, l'utilisation de trois décimales – soit une précision au millimètre – est largement suffisante pour mesurer la distance de dépassement. De plus, une variable continue est soit une variable d'intervalle, soit une variable de rapport. Les **variables d'intervalle** ont une échelle relative, c'est-à-dire que les intervalles entre les valeurs de la variable ne sont pas constants; elles n'ont pas de vrai zéro. Autrement dit, ce type de variable a une échelle relative avec un zéro arbitraire. Ces valeurs peuvent être manipulées uniquement par addition et soustraction et non par multiplication et division. La variable d'intervalle la plus connue est certainement celle de la température. S'il fait 10 degrés Celsius à Montréal et 30 °C à Mumbai (soit 50 et 86 degrés en Fahrenheit), nous pouvons affirmer qu'il y a 20 °C ou 36 °F d'écart entre les deux villes, mais ne pouvons pas affirmer qu'il fait trois fois plus chaud à Mumbai. Presque toutes les mesures statistiques sur une variable d'intervalle peuvent être calculées, excepté le coefficient de variation et la moyenne géométrique puisqu'il n'y a pas de vrai zéro ni d'intervalles constants entre les valeurs. À l'inverse, les **variables de rapport** ont une échelle absolue, c'est-à-dire que les intervalles entre les valeurs sont constants et elles ont un vrai zéro. Elles peuvent ainsi être manipulées par addition, soustraction, multiplication et division. Par exemple, le prix d'un produit exprimé dans une unité monétaire ou la distance exprimée dans le système métrique sont des variables de rapport. Un vélo dont le prix affiché est de 1000 \\$ est bien deux fois plus cher qu'un autre à 500 \\$, une piste cyclable hors rue à 25 mètres du tronçon routier le plus proche est bien quatre fois plus proche qu'une autre à 100 mètres.\n\n**Une variable semi-quantitative**, appelée aussi variable quantitative ordonnée, est une variable discrète ou continue dont les valeurs ont été regroupées en classes hiérarchisées. Par exemple, l'âge est une variable continue pouvant être transformée avec les groupes d'âge ordonnés suivants : *moins 25 ans*, *25 à 44 ans*, *45 à 64 ans* et *65 ans et plus*.\n\n\n## Types de données {#sec-022}\n\nDifférents types de données sont utilisés en sciences sociales. L'objectif ici n'est pas de les décrire en détail, mais plutôt de donner quelques courtes définitions. En fonction de votre question de recherche et des bases des données disponibles, il s'agit de sélectionner le ou les types de données les plus appropriés à votre étude.\n\n### Données secondaires *versus* données primaires {#sec-0221}\n\nLes **données secondaires** sont des données qui existent déjà au début de votre projet de recherche : nul besoin de les collecter, il suffit de les exploiter! Une multitude de données de recensements ou d'enquêtes de Statistique Canada sont disponibles et largement exploitées en sciences sociales (par exemple, l'enquête nationale auprès des ménages – ENM, l'enquête sur la dynamique du marché du travail et du revenu – EDTR, l'enquête longitudinale auprès des immigrants – ELIC, etc.). \n\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Accès aux microdonnées**\n:::\n::: bloc_notes-body\nAu Canada, les personnes qui font de la recherche, qui étudient ou qui enseignent, ont accès aux microdonnées des enquêtes de Statistique Canada dans les centres de données de recherche (CDR). Vous pouvez consulter le moteur de recherche du Réseau canadien des Centres de données de recherche (https://crdcn.org/fr/donn%C3%A9es) afin d'explorer les différentes enquêtes disponibles.\n\nAu Québec, l'accès à ces enquêtes est possible dans les différentes antennes du Centre interuniversitaire québécois de statistiques sociales de Statistique Canada (https://www.ciqss.org/).\n:::\n:::\n\nPar opposition, les **données primaires** n'existent pas quand vous démarrez votre projet : vous devez les collecter spécifiquement pour votre étude! Par exemple, une chercheuse souhaitant analyser l'exposition des cyclistes au bruit et à la pollution dans une ville donnée doit réaliser une collecte de données avec idéalement plusieurs personnes participantes (équipées de différents capteurs), et ce, sur plusieurs jours. \nUne collecte de données primaires peut aussi être réalisée avec une enquête par sondage. Brièvement, réaliser une collecte de données primaires nécessite différentes phases complexes comme la définition de la méthode de collecte et de la population à l'étude, l’estimation de la taille de l'échantillon, la validation des outils de collecte avec une phase de test, la réalisation de la collecte, la structuration, la gestion et l'exploitation de données collectées. Finalement, dans le milieu académique, une collecte de données primaires auprès d'individus doit être approuvée par le comité d'éthique de la recherche de l'université à laquelle est affiliée la personne responsable du projet de recherche.\n\n### Données transversales *versus* données longitudinales {#sec-0222}\nLes **données transversales** sont des mesures pour une période relativement courte. L’exemple classique est un jeu de données constitué des variables extraites d’un recensement de population pour une année donnée (comme celui de 2016 de Statistique Canada). \n\nLes **données longitudinales**, appelées aussi données par panel, sont des mesures répétées pour plusieurs observations au cours du temps (*N* observations pour *T* dates). Par exemple, des observations pourraient être des pays, les dates pourraient être différentes années (de 1990 à 2019) pour lesquelles différentes variables seraient disponibles (population totale, taux d’urbanisation, produit intérieur brut par habitant, émissions de gaz à effet de serre par habitant, etc.).\n\n### Données spatiales versus données aspatiales {#sec-0223}\n\nLes observations des **données spatiales** sont des unités spatiales géoréférencées. Elles peuvent être par exemple :\n\n* des points *(x, y)* ou *(lat-long)* représentant des entreprises avec plusieurs variables (adresse, date de création, nombre d'employés, secteurs d'activité, etc.);\n\n* les lignes représentant des tronçons de rues pour lesquels plusieurs variables sont disponibles (type de rue, longueur en mètres, nombre de voies, débit journalier moyen annuel, etc.);\n\n* des polygones délimitant des régions ou des arrondissements pour lesquels une multitude de variables sociodémographiques et socioéconomiques sont disponibles;\n \n* les pixels des bandes spectrales d'une image satellite.\n\nÀ l’inverse, aucune information spatiale n’est disponible pour des **données aspatiales**. \n\n\n### Données individuelles *versus* données agrégées {#sec-0224}\n\nComme son nom l'indique, pour des **données individuelles**, chaque observation correspond à un individu. Les microdonnées de recensements ou d'enquêtes, par exemple, sont des données individuelles pour lesquelles toute une série de variables est disponible. Une étude analysant les caractéristiques de chaque arbre d'un quartier nécessite aussi des données individuelles : l'information doit être disponible pour chaque arbre. Pour les microdonnées des recensements canadiens, « chaque enregistrement au niveau de la personne comprend des identifiants (comme les identifiants du ménage et de la famille), des variables géographiques et des variables directes et dérivées tirées du questionnaire » ([Statistique Canada](https://www150.statcan.gc.ca/n1/pub/12-002-x/2012001/article/11642-fra.htm){target=\"_blank\"}). Comme signalé plus haut, ces microdonnées de recensements ou d'enquêtes sont uniquement accessibles dans les centres de données de recherche (CDR).\n\nLes données individuelles peuvent être **agrégées** à un niveau supérieur. Prenons le cas de microdonnées d'un recensement. Les informations disponibles pour chaque individu sont agrégées par territoire géographique (province, région économique, division de recensement, subdivision de recensement, région et agglomération de recensement, secteurs de recensement, aires de diffusion, etc.) en fonction du lieu de résidence des individus. Des sommaires statistiques – basés sur la moyenne, la médiane, la somme ou la proportion de chacune des variables mesurées au niveau individuel (âge, sexe, situation familiale, revenu, etc.) – sont alors construits pour ces différents découpages géographiques ([Statistique Canada](https://www.statcan.gc.ca/fra/idd/trousse/section5#a4){target=\"_blank\"}).\n\nL'agrégation n'est pas nécessairement géographique. En éducation, il est fréquent de travailler avec des données concernant les élèves, mais agrégées au niveau des écoles. La @fig-univarie1b donne un exemple simple d'agrégation de données individuelles.\n\n![Exemple d'agrégation de données individuelles](images/Chap02/aggregation.png){#fig-univarie1b width=\"65%\" fig-align=\"center\"}\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Erreur écologique et erreur atomiste**: attention aux interprétations abusives\n:::\n::: bloc_attention-body\nIl convient d'être prudent dans l'analyse des données agrégées. Très fréquente en géographie, l'**erreur écologique** (*ecological fallacy* en anglais) est une mauvaise interprétation des résultats. Elle consiste à attribuer des constats obtenus à partir de données agrégées pour un territoire aux individus qui forment la population de ce territoire. À l'inverse, attribuer des résultats à partir de données individuelles à des territoires est une **erreur atomiste**.\n\nPrenons un exemple concret tiré d'une étude récente sur la localisation des écoles primaires et le bruit aérien dans la région métropolitaine de Toronto [@audrin2021localisation]. Un des objectifs de cette étude est de vérifier si les écoles primaires (ns = 1420) avec des niveaux de bruit aérien élevés présentent des niveaux de réussite scolaire plus faibles. Les résultats de leur étude démontrent que les enfants scolarisés dans les écoles primaires avec à des niveaux élevés de bruit aérien sont issus de milieux plus défavorisés et ont plus souvent une langue maternelle autre que la langue d'enseignement. Aussi, les écoles avec des niveaux de bruit aérien élevés présentent des niveaux de réussite scolaire plus faibles. \n\nToutefois, étant donné que les variables sur la réussite scolaire sont mesurées au niveau de l'école (soit les pourcentages d’élèves ayant atteint ou dépassé la norme provinciale en lecture, en écriture et en mathématique, respectivement pour la 3^e^ année et la 6^e^ année) et non au niveau individuel, nous ne pouvons pas conclure que le bruit aérien à un impact significatif sur la réussite scolaire des élèves :\n\n« Nous avons pu démontrer que les écoles primaires localisées dans la zone NEF 25 présentent des taux de réussite plus faibles. Rappelons toutefois qu’une association obtenue avec des données agrégées ne peut pas nous permettre de conclure à une influence directe au niveau individuel, car l’agrégation des données entraîne une perte d’information. Cette erreur d’interprétation dite erreur écologique (*ecological fallacy*) tend à laisser penser que les associations entre les groupes s’appliquent à chaque individu (Robinson, 1950). Nos résultats gagneraient à être corroborés à partir d’analyses reposant sur des données individuelles ».\n:::\n:::\n\n\nPour le cas de l'agrégation géographique, il convient alors de bien comprendre la hiérarchie des régions géographiques délimitées par l’organisme ou l’agence ayant la responsabilité de produire, de gérer et de diffuser les données des recensements et des enquêtes, puis de sélectionner le découpage géographique qui répond le mieux à votre question de recherche.\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\nHiérarchie et définitions des régions géographiques du recensement canadien\n:::\n::: bloc_astuce-body\n* la [hiérarchie des régions géographiques normalisées pour la diffusion](https://www12.statcan.gc.ca/census-recensement/2016/ref/dict/figures/f1_1-fra.cfm)\n\n* le [glossaire illustré](https://www150.statcan.gc.ca/n1/pub/92-195-x/92-195-x2016001-fra.htm) des régions géographiques\n\n* [les différents profils du recensement de 2021](https://www12.statcan.gc.ca/census-recensement/2021/dp-pd/prof/index.cfm?Lang=F) à télécharger pour les différentes régions géographiques.\n:::\n:::\n\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Les différents types de données abordés ci-dessus ne sont pas exclusifs.**\n:::\n::: bloc_notes-body\nPar exemple, des données pour des régions administratives extraites de plusieurs recensements sont en fait des données secondaires, spatiales, agrégées et longitudinales. \n\nDes données sur la pollution atmosphérique et sonore collectées à vélo (avec différents capteurs et un GPS) sont des données spatiales primaires.\n:::\n:::\n\n\n\n\n## Statistique descriptive et statistique inférentielle {#sec-023}\n\n### Population, échantillon et inférence {#sec-0231}\n\nLes notions de **population** et d'**échantillon** sont essentielles en statistique puisqu'elles sont le socle de l'inférence statistique.\nUn échantillon est un **sous-ensemble représentatif** d'une population donnée. Prenons un exemple concret : une chercheuse veut comprendre la mobilité des personnes étudiant dans une université. Bien entendu, elle ne peut interroger toutes les personnes étudiantes de son université. Elle devra donc s’assurer d'obtenir un échantillon de taille suffisante et représentatif de la population étudiante. Une fois les données collectées (avec un sondage par exemple), elle pourra utiliser des techniques inférentielles pour analyser la mobilité des personnes interrogées. Si son échantillon est représentatif, les résultats obtenus pourront être inférés – c'est-à-dire généralisés, extrapolés – à l’ensemble de la population.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Les méthodes d’échantillonnage**\n:::\n::: bloc_aller_loin-body\nNous n’abordons pas ici les méthodes d’échantillonnage. Sachez toutefois qu’il existe plusieurs méthodes probabilistes pour constituer un échantillon, notamment de manière aléatoire, systématique, stratifiée, par grappes. Consultez par exemple cette [publication de Statistique Canada](https://www150.statcan.gc.ca/n1/edu/power-pouvoir/ch13/prob/5214899-fra.htm).\n:::\n:::\n\nAutre exemple, une autre chercheuse souhaite comprendre les facteurs influençant le sentiment de sécurité des cyclistes dans un quartier. De nouveau, elle ne peut pas enquêter sur l'ensemble des cyclistes du quartier et devra constituer un échantillon représentatif. Par la suite, la mise en œuvre de techniques inférentielles lui permettra d'identifier les caractéristiques individuelles (âge, sexe, habiletés à vélo, etc.) et de l'environnement urbain (types de voies empruntés, niveaux de trafic, de pollution, de bruit, etc.) ayant des effets significatifs sur le sentiment de sécurité. Si l'échantillon est représentatif, les résultats pourront être généralisés à l'ensemble des cyclistes du quartier.\n\n\n### Deux grandes familles de méthodes statistiques {#sec-0232}\n\nNous distinguons habituellement deux grandes familles de méthodes statistiques : la statistique descriptive et exploratoire et la statistiques inférentielle et confirmatoire. Il existe de nombreuses définitions de ces deux branches de la statistique, celles proposées de Lebart et al. [-@lebart1995statistique] étant parmi les plus abouties :\n\n* « **La statistique descriptive et exploratoire** : elle permet, par des résumés et des graphiques plus ou moins élaborés, de décrire des ensembles de données statistiques, d’établir des relations entre les variables sans faire jouer de rôle privilégié à une variable particulière. Les conclusions ne portent dans cette phase de travail que sur les données étudiées, sans être inférées à une population plus large. L’analyse exploratoire s’appuie essentiellement sur des notions élémentaires telles que des indicateurs de moyenne et de dispersion, sur des représentations graphiques. [...]\n\n* **La statistique inférentielle et confirmatoire** : elle permet de valider ou d’infirmer, à partir de tests statistiques ou de modèles probabilistes, des hypothèses formulées a priori (ou après une phase exploratoire), et d’extrapoler, c’est-à-dire d’étendre certaines propriétés d’un échantillon à une population plus large. Les conclusions obtenues à partir des données vont au-delà de ces données. La statistique confirmatoire fait surtout appel aux méthodes dites explicatives et prévisionnelles, destinées, comme leurs noms l’indiquent, à expliquer puis à prévoir, suivant des règles de décision, une variable privilégiée à l’aide d’une ou plusieurs variables explicatives (régressions multiples et logistiques, analyse de variance, analyse discriminante, segmentation, etc.) » [@lebart1995statistique, p.209].\n\n\n## Notion de distribution {#sec-024}\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Les distributions : une notion centrale en statistique**\n:::\n::: bloc_objectif-body\nPrenez le temps de lire cette section à tête reposée et assurez-vous de bien comprendre chaque idée avant de passer à la suivante. N’hésitez pas à y revenir plusieurs fois si nécessaire, car la compréhension de ces concepts est essentielle pour utiliser adéquatement les méthodes que nous abordons dans ce livre.\n:::\n:::\n\n### Définition générale\n\nEn probabilité, nous nous intéressons aux résultats d’expériences. Du point de vue de la théorie des probabilités, lancer un dé, mesurer la pollution atmosphérique, compter le nombre de collisions à une intersection, et demander à une personne d’évaluer son sentiment de sécurité sur une échelle de 1 à 10 sont autant d’expériences pouvant produire des résultats.\n\n**Une distribution est un modèle mathématique permettant d’associer pour chaque résultat possible d’une expérience la probabilité d’obtenir ce résultat**. D'un point de vue pratique, si nous disposons de la distribution régissant l’expérience : « mesurer la concentration d’ozone à Montréal à 13 h en été », nous pouvons calculer la probabilité de mesurer une valeur inférieure à 15 μg/m^3^.\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Loi de probabilité et distribution**\n:::\n::: bloc_attention-body\nL'utilisation que nous faisons ici du terme « distribution » est un anglicisme (éhonté diront certaines personnes). En effet, en français, la définition précédente est plus proche du terme « loi de probabilité ». Cependant, la quasi-totalité de la documentation sur R est en anglais et, dans la pratique, ces deux termes ont tendance à se confondre. Nous avons donc fait le choix de poursuivre avec ce terme dans le reste du livre.\n:::\n:::\n\nUne distribution est toujours définie dans un intervalle en dehors duquel elle n'est définie; les valeurs dans cet intervalle sont appelées **l’espace d’échantillonnage**. Il s’agit donc des valeurs possibles que peut produire l’expérience. La somme des probabilités de l’ensemble des valeurs de l’espace d’échantillonnage est 1 (100 %). Intuitivement, cela signifie que si nous réalisons l’expérience, nous obtenons nécessairement un résultat, et que la somme des probabilités est répartie entre tous les résultats possibles de l’expérience. En langage mathématique, nous disons que l’intégrale de la fonction de densité d'une distribution est 1 dans son intervalle de définition.\n\nPrenons un exemple concret avec l’expérience suivante : tirer à pile ou face avec une pièce de monnaie non truquée. Si l’on souhaite décrire la probabilité d’obtenir pile ou face, nous pouvons utiliser une distribution qui aura comme espace d’échantillonnage [pile; face] et ces deux valeurs auront chacune comme probabilité 0,5. Il est facile d’étendre cet exemple au cas d’un dé à six faces. La distribution de probabilité décrivant l’expérience « lancer le dé » a pour espace d’échantillonnage [1,2,3,4,5,6], chacune de ces valeurs étant associée à la probabilité de 1/6.\n\nChacune des deux expériences précédentes est régie par une distribution appartenant à la famille des distributions **discrètes**. Elles servent à représenter des expériences dont le nombre de valeurs possibles est fini. Par opposition, la seconde famille de distributions regroupe les distributions **continues**, décrivant des expériences dont le nombre de résultats possibles est en principe infini. Par exemple, mesurer la taille d’une personne adulte sélectionnée au hasard peut produire en principe un nombre infini de valeurs. Les distributions sont utiles pour décrire les résultats potentiels d’une expérience. Reprenons notre exemple du dé. Nous savons que chaque face a une chance sur six d’être tirée au hasard. Nous pouvons représenter cette distribution avec un graphique (@fig-fig251). \n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution théorique d'un lancer de dé](02-univarie_files/figure-html/fig-fig251-1.png){#fig-fig251 fig-align='center' width=50%}\n:::\n:::\n\n\nNous avons donc sous les yeux un modèle statistique décrivant le comportement attendu d’un dé, soit sa distribution **théorique**. Cependant, si nous effectuons dix fois l’expérience (nous collectons donc un échantillon), nous obtiendrons une distribution différente de cette distribution théorique (@fig-fig252).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution empirique d'un lancer de dé (n = 10)](02-univarie_files/figure-html/fig-fig252-1.png){#fig-fig252 fig-align='center' width=50%}\n:::\n:::\n\n\nIl s'agit de la distribution **empirique**. Chaque échantillon aura sa propre distribution empirique. Cependant, comme le prédit la loi des grands nombres : si une expérience est répétée un grand nombre de fois, la probabilité empirique d’un résultat se rapproche de la probabilité théorique à mesure que le nombre de répétitions augmente. Du point de vue de la théorie des probabilités, chaque échantillon correspond à un ensemble de tirages aléatoires effectués à partir de la distribution théorique du phénomène étudié. \n\nPour nous en convaincre, collectons trois échantillons de lancer de dé de respectivement 30, 100 et 1000 observations (@fig-fig253). Comme le montre la @fig-fig252, nous connaissons la distribution théorique qui régit cette expérience.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution empirique d'un lancer de dé](02-univarie_files/figure-html/fig-fig253-1.png){#fig-fig253 fig-align='center' width=70%}\n:::\n:::\n\nNous constatons bien qu’au fur et à mesure que la taille de l’échantillon augmente, nous tendons vers la distribution théorique.\n\nCette relation a été étudiée pour la première fois au XVIII^e^ siècle par le mathématicien Daniel Bernoulli, qui a montré que la probabilité que la moyenne d’une distribution empirique soit éloignée de la moyenne de la distribution théorique dont elle est tirée diminuait lorsque nous augmentons le nombre des tirages et donc la taille de l’échantillon. Un autre mathématicien, Siméon-Denis Poisson, a fait connaître cette relation sous le nom de « loi des grands nombres ».\n\nLes distributions théoriques sont utilisées pour modéliser des phénomènes réels et sont à la base de presque tous les tests statistiques d'inférence fréquentiste ou bayésienne. En pratique, la question que nous nous posons le plus souvent est : quelle distribution théorique peut le mieux décrire le phénomène empirique à l’étude? Pour répondre à cette question, deux approches sont possibles :\n\n* Considérant la littérature existante sur le sujet, les connaissances accumulées et la nature de la variable étudiée, sélectionner des distributions théoriques pouvant vraisemblablement correspondre au phénomène mesuré.\n\n* Comparer visuellement ou à l’aide de tests statistiques la distribution empirique de la variable et diverses distributions théoriques pour trouver la plus adaptée.\n\nIdéalement, le choix d’une distribution théorique devrait reposer sur ces deux méthodes combinées.\n\n### Anatomie d'une distribution\n\nUne distribution (ou loi de probabilité) est une fonction. Il est possible de la représenter à l’aide d’une formule mathématique (appelée **fonction de masse** pour les distributions discrètes et **fonction de densité** pour les distributions continues) associant chaque résultat possible de l'expérience régie par la distribution à la probabilité d'observer ce résultat. Prenons un premier exemple concret avec la distribution théorique associée au lancer de pièce de monnaie : la distribution de **Bernoulli**. Sa formule est la suivante :\n\n$$\nf(x ; p)=\\left\\{\\begin{array}{ll}\nq=1-p & \\text { si } x=0 \\\\\np & \\text { si } x=1\n\\end{array}\\right.\n$$ {#eq-Bernoulli}\n\navec *p* la probabilité d’obtenir $x = 1$ (pile), et $1 – p$ la probabilité d’avoir $x = 0$ (face). La distribution de Bernoulli ne dépend que d’un paramètre : *p*. Avec différentes valeurs de *p*, nous pouvons obtenir différentes formes pour la distribution de Bernoulli. Si *p* = 1/2, la distribution de Bernoulli décrit parfaitement l’expérience : obtenir pile à un lancer de pièce de monnaie. Si *p* = 1/6, elle décrit alors l’expérience : obtenir 4 (tout comme n’importe quelle valeur de 1 à 6) à un lancer de dé. Pour un exemple plus appliqué, la distribution de Bernoulli est utilisée en analyse spatiale pour étudier la concentration d’accidents de la route ou de crimes en milieu urbain. À chaque endroit du territoire, il est possible de calculer la probabilité qu’un tel évènement ait lieu ou non en modélisant les données observées au moyen de la loi de Bernoulli.\nLa distribution continue la plus simple à décrire est certainement la distribution **uniforme**. Il s’agit d’une distribution un peu spéciale puisqu’elle attribue la même probabilité à toutes ses valeurs dans son espace d’échantillonnage. Elle est définie sur l’intervalle $[-\\infty; +\\infty]$ et a la fonction de densité suivante : \n\n$$\nf(x ; \\mathrm{a} ; \\mathrm{b})=\\left\\{\\begin{array}{cc}\n\\frac{1}{a-b} & \\text { si } a \\geq x \\geq b \\\\\n0 & \\text { sinon }\n\\end{array}\\right.\n$$ {#eq-Uniforme}\n\nLa fonction de densité de la distribution uniforme a donc deux paramètres, *a* et *b*, représentant respectivement les valeurs maximale et minimale au-delà desquelles les valeurs ont une probabilité 0 d’être obtenues. Pour avoir une meilleure intuition de ce que décrit une fonction de densité, il est intéressant de la représenter avec un graphique (@fig-fig254). Notez que sur ce graphique, l'axe des ordonnées n'indique pas précisément la probabilité associée à chaque valeur, car celle-ci est infinitésimale. Il sert uniquement à représenter la valeur de la fonction de densité de la distribution pour chaque valeur de x.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distributions uniformes continues](02-univarie_files/figure-html/fig-fig254-1.png){#fig-fig254 fig-align='center' width=60%}\n:::\n:::\n\n\nNous observons clairement que toutes les valeurs de *x* entre *a* et *b* ont la même probabilité pour chacune de trois distributions uniformes présentées dans le graphique. Plus l’étendue est grande ($a-b$), plus l’espace d’échantillonnage est grand et plus la probabilité totale est répartie dans cet espace. Cette distribution est donc idéale pour décrire un phénomène pour lequel chaque valeur a autant de chance de se produire qu’une autre. Prenons pour exemple un cas fictif avec un jeu de hasard qui vous proposerait la situation suivante : en tirant sur la manette d’une machine à sous, un nombre est tiré aléatoirement entre -60 et +50. Si le nombre est négatif, vous perdez de l’argent et inversement si le nombre est positif. Nous pouvons représenter cette situation avec une distribution uniforme continue et l’utiliser pour calculer quelques informations essentielles : \n\n1. Selon cette distribution, quelle est la probabilité de gagner de l’argent lors d’un tirage (x > 0)? \n\n2. Quelle est la probabilité de perdre de l’argent (x < 0)?\n\n3. Si je perds moins de 30 $ au premier tirage, quelle est la probabilité que j'ai de récupérer au moins ma mise au second tirage (x > 30)?\n\nIl est assez facile de calculer ces probabilités en utilisant la fonction `punif` dans R. Concrètement, cela permet de calculer l’intégrale de la fonction de masse sur un intervalle donné.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Probabilité d'obtenir une valeur supérieure ou égale à 0\npunif(0, min = -60, max = 50)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 0.5454545\n```\n:::\n\n```{.r .cell-code}\n# Probabilité d'obtenir une valeur inférieure à 0\npunif(0, min = -60, max = 50, lower.tail = FALSE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 0.4545455\n```\n:::\n\n```{.r .cell-code}\n# Probabilité d'obtenir une valeur supérieure à 30\npunif(30, min = -60, max = 50, lower.tail = FALSE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 0.1818182\n```\n:::\n:::\n\n\nLes paramètres permettent donc d’ajuster la fonction de masse ou de densité d’une distribution afin de lui permettre de prendre des formes différentes. Certains paramètres changent la localisation de la distribution (la déplacer vers la droite ou la gauche de l’axe des X), d’autres changent son degré de dispersion (distribution pointue ou aplatie) ou encore sa forme (symétrie). Les différents paramètres d’une distribution correspondent donc à sa carte d’identité et donnent une idée précise sur sa nature.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Fonction de répartition, de survie et d'intensité**\n:::\n::: bloc_aller_loin-body\nSi les fonctions de densité ou de masse d'une distribution sont le plus souvent utilisées pour décrire une distribution, d'autres types de fonctions peuvent également être employées et disposent de propriétés intéressantes.\n\n1. La fonction de répartition : il s'agit d'une fonction décrivant le cumul de probabilités d'une distribution. Cette fonction a un minimum de zéro qui est obtenu pour la plus petite valeur de l'espace d'échantillonnage de la distribution, et un maximum d'un pour la plus grande valeur de ce même espace. Formellement, la fonction de répartition ($F$) est l’intégrale de la fonction de densité ($f$).\n\n$$F(x) = \\int_{-\\infty}^{x}f(u)du$$\n2. La fonction de survie : soit l'inverse additif de la fonction de répartition ($R$)\n\n$$R(x) = 1-F(x)$$\n3. La fonction de d'intensité, soit le quotient de la fonction de densité et de la fonction de survie ($D$).\n$$D(x) = \\frac{f(x)}{D(x)}$$\nCes fonctions jouent notamment un rôle central dans la modélisation des phénomènes qui régissent la survenue des événements, par exemple la mort, les accidents de la route ou les bris d’équipement.\n:::\n:::\n\n### Principales distributions\n\nIl existe un très grand nombre de distributions théoriques et parmi elles, de nombreuses sont en fait des cas spéciaux d’autres distributions. Pour un petit aperçu du « bestiaire », vous pouvez faire un saut à la page [*Univariate Distribution Relationships*](http://www.math.wm.edu/~leemis/chart/UDR/UDR.html){target='_blank'}, qui liste près de 80 distributions. \n\nNous nous concentrons ici sur une sélection de dix-huit distributions très répandues en sciences sociales. La @fig-distribs présente graphiquement leurs fonctions de masse et de densité présentées dans cette section. Notez que ces graphiques correspondent tous à une forme possible de chaque distribution. En modifiant leurs paramètres, il est possible de produire une figure très différente. Les distributions discrètes sont représentées avec des graphiques en barre, et les distributions continues avec des graphiques de densité.\n\n![Dix-huit distributions essentielles, figure inspirée de @SeanOwendist](images/Chap02/all_distributions.png){#fig-distribs width=\"95%\" fig-align=\"center\"}\n\n\n#### Distribution uniforme discrète\nNous avons déjà abordé cette distribution dans les exemples précédents. Elle permet de décrire un phénomène dont tous les résultats possibles ont exactement la même probabilité de se produire. L’exemple classique est bien sûr un lancer de dé.\n\n#### Distribution de Bernoulli\nLa distribution de Bernoulli permet de décrire une expérience pour laquelle deux résultats sont possibles. Son espace d’échantillonnage est donc $[0; 1]$. Sa fonction de masse est la suivante : \n\n$$\nf(x ; p)=\\left\\{\\begin{array}{ll}\nq=1-p & \\text { si } x=0 \\\\\np & \\text { si } x=1\n\\end{array}\\right.\n$$ {#eq-BernoulliB}\n\navec *p* la probabilité d’obtenir $x = 1$ (réussite) et donc $1 – p$ la probabilité d’avoir $x = 0$ (échec). La distribution de Bernoulli ne dépend que d’un paramètre : *p*, contrôlant la probabilité de réussite de l’expérience. Notez que si $p = 1/2$, alors la distribution de Bernoulli est également une distribution uniforme. Un exemple d’application de la distribution de Bernoulli en études urbaines est la modélisation de la survie d’un ou d'une cycliste (1 pour survie, 0 pour décès) lors d’une collision avec un véhicule motorisé, selon une vitesse donnée.\n\n#### Distribution binomiale\n\nLa distribution binomiale est utilisée pour caractériser la somme de variables aléatoires (expériences) suivant chacune une distribution de Bernoulli. Un exemple simple est l’accumulation des lancers d’une pièce de monnaie. Si nous comptons le nombre de fois où nous obtenons pile, cette expérience est décrite par une distribution binomiale. Son espace d’échantillonnage est donc $[0; +\\infty[$ (limité aux nombres entiers). Sa fonction de masse est la suivante : \n\n$$\nf(x ; n )=\\binom{n}{x}p^x(1-p)^{n-x}\n$$ {#eq-Binomial}\n\navec *x* le nombre de tirages réussis sur *n* essais avec une probabilité *p* de réussite à chaque tirage (@fig-fig256). Pour reprendre l’exemple précédent concernant les accidents de la route, une distribution binomiale permettrait de représenter la distribution du nombre de cyclistes ayant survécu sur dix personnes à vélo impliquées dans un accident avec une voiture à une intersection. \n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution binomiale](02-univarie_files/figure-html/fig-fig256-1.png){#fig-fig256 fig-align='center' width=95%}\n:::\n:::\n\n\n#### Distribution géométrique\n\nLa distribution géométrique permet de représenter le nombre de tirages qu'il faut faire avec une distribution de Bernoulli avant d’obtenir une réussite. Par exemple, avec un lancer de dé, l’idée serait de compter le nombre de lancers nécessaires avant de tomber sur un 6. Son espace d’échantillonnage est donc $[1; +\\infty[$ (limité aux nombres entiers). Sa distribution de masse est la suivante : \n\n$$\nf(x; p)= (1-p)^xp\n$$ {#eq-geometrique}\n\navec *x* le nombre de tentatives avant d’obtenir une réussite, $f(x)$ la probabilité que le premier succès n’arrive qu’après *x* tentatives et *p* la probabilité de réussite à chaque tentative (@fig-fig257). Cette distribution est notamment utilisée en marketing pour modéliser le nombre d’appels nécessaires avant de réussir une vente.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution géométrique](02-univarie_files/figure-html/fig-fig257-1.png){#fig-fig257 fig-align='center' width=95%}\n:::\n:::\n\n\n#### Distribution binomiale négative\n\nLa distribution binomiale négative est proche de la distribution géométrique. Elle permet de représenter le nombre de tentatives nécessaires afin d’obtenir un nombre *n* de réussites $[1; +\\infty[$ (limité aux nombres entiers positifs). Sa formule est la suivante : \n\n$$\nf(x; n; p)=\\left(\\begin{array}{c}\nx+n-1 \\\\\nn\n\\end{array}\\right) p^{n}(1-p)^{x}\n$$ {#eq-binomialnegative}\n\navec *x* le nombre de tentatives avant d’obtenir *n* réussites et *p* la probabilité d’obtenir une réussite à chaque tentative (@fig-fig258). Cette distribution pourrait être utilisée pour modéliser le nombre de questionnaires *x* à envoyer pour une enquête pour obtenir au moins *n* réponses, sachant que la probabilité d’une réponse est *p*.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution binomiale négative](02-univarie_files/figure-html/fig-fig258-1.png){#fig-fig258 fig-align='center' width=95%}\n:::\n:::\n\n\n#### Distribution de Poisson\n\nLa distribution de Poisson est utilisée pour modéliser des comptages. Son espace d’échantillonnage est donc $[0; +\\infty[$ (limité aux nombres entiers positifs). Par exemple, il est possible de compter à une intersection le nombre de collisions entre des automobilistes et des cyclistes sur une période donnée. Cet exemple devrait vous faire penser à la distribution binomiale vue plus haut. En effet, il est possible de noter chaque rencontre entre une voiture et un ou une cycliste et de considérer que leur collision est une « réussite » (0 : pas d’accidents, 1 : accident). Cependant, ce type de données est fastidieux à collecter comparativement au simple comptage des accidents. La distribution de Poisson a une fonction de densité avec un seul paramètre généralement noté $\\lambda$ (lambda) et est décrite par la formule suivante : \n\n$$\nf(x; \\lambda)=\\frac{\\lambda^{x}}{x !} e^{-\\lambda}\n$$ {#eq-poisson}\navec *x* le nombre de cas, *f(x)* la probabilité d’obtenir *x* sachant $\\lambda$. $\\lambda$ peut être vu comme le taux moyen d’occurrences (nombre d’évènements divisé par la durée totale de l’expérience). Il permet à la fois de caractériser le centre et la dispersion de la distribution. Notez également que plus le paramètre $\\lambda$ augmente, plus la distribution de Poisson tend vers une distribution normale.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution de Poisson](02-univarie_files/figure-html/fig-fig259-1.png){#fig-fig259 fig-align='center' width=95%}\n:::\n:::\n\n\n#### Distribution de Poisson avec excès de zéros {#sec-poissonzero}\n\nIl arrive régulièrement qu’une variable de comptage mesurée produise un très grand nombre de zéros. Prenons pour exemple le nombre de seringues de drogue injectable par tronçon de rue ramassées sur une période d’un mois. À l’échelle de toute une ville, un très grand nombre de tronçons n’auront tout simplement aucune seringue et dans ce contexte, la distribution classique de Poisson n’est pas adaptée. Nous lui préférons alors une autre distribution : la distribution de Poisson avec excès de zéros (ou distribution de Pólya) qui inclut un paramètre contrôlant la forte présence de zéros. Sa fonction de densité est la suivante : \n\n$$\nf(x; \\lambda; p)=(1-p)\\frac{\\lambda^{x}}{x !} e^{-\\lambda}\n$$ {#eq-poissonzi}\n\nPlus exactement, la distribution de Poisson avec excès de zéro (*zero-inflated* en anglais) est une combinaison de deux processus générant des zéros. En effet, un zéro peut être produit par la distribution de Poisson proprement dite (aussi appelé vrai zéro) ou alors par le processus générant les zéros excédentaires dans le jeu de données, capturé par la probabilité *p* (faux zéro). *p* est donc le paramètre contrôlant la probabilité d’obtenir un zéro, indépendamment du phénomène étudié.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution de Poisson avec excès de zéros](02-univarie_files/figure-html/fig-fig259b-1.png){#fig-fig259b fig-align='center' width=95%}\n:::\n:::\n\n\n#### Distribution gaussienne\nPlus communément appelée la distribution normale, la distribution gaussienne est utilisée pour représenter des variables continues centrées sur leur moyenne. Son espace d’échantillonnage est $]-\\infty; +\\infty[$. Cette distribution joue un rôle central en statistique. Selon la formule consacrée, cette distribution résulte de la superposition d’un très grand nombre de petits effets fortuits indépendants. C’est ce qu’exprime formellement le théorème central limite qui montre que la somme d’un grand nombre de variables aléatoires tend généralement vers une distribution normale. Autrement dit, lorsque nous répétons une même expérience et que nous conservons les résultats de ces expériences, la distribution du résultat de ces expériences tend vers la normalité. Cela s’explique par le fait qu’en moyenne, chaque répétition de l’expérience produit le même résultat, mais qu’un ensemble de petits facteurs aléatoires viennent ajouter de la variabilité dans les données collectées. Prenons un exemple concret : si nous plantons une centaine d’arbres simultanément dans un parc avec un degré d’ensoleillement identique et que nous leur apportons les mêmes soins pendant dix ans, la distribution de leurs tailles suivra une distribution normale. Un ensemble de facteurs aléatoires (composition du sol, exposition au vent, aléas génétiques, passage de nuages, etc.) auront affecté différemment chaque arbre, ajoutant ainsi un peu de hasard dans leur taille finale. Cette dernière est cependant davantage affectée par des paramètres majeurs (comme l'espèce, l'ensoleillement, l'arrosage, etc.), et est donc centrée autour d’une moyenne.\nLa fonction de densité de la distribution normale est la suivante :\n\n$$\nf(x ; \\mu ; \\sigma)=\\frac{1}{\\sigma \\sqrt{2 \\pi}} e^{-\\frac{1}{2}\\left(\\frac{x-\\mu}{\\sigma}\\right)^{2}}\n$$ {#eq-gaussien}\n\navec *x* une valeur dont nous souhaitons connaître la probabilité, *f(x)* sa probabilité, $\\mu$ (mu) la moyenne de la distribution normale (paramètre de localisation) et $\\sigma$ (sigma) son écart-type (paramètre de dispersion). Cette fonction suit une courbe normale ayant une forme de cloche. Notez que :\n\n* 68,2 % de la masse de la distribution normale est comprise dans l’intervalle $[\\mu- \\sigma≤x≤ \\mu+ \\sigma]$ \n* 95,4 % dans l’intervalle $[\\mu- 2\\sigma≤x≤ \\mu+ 2\\sigma]$\n* 99,7 % dans l’intervalle $[\\mu- 3\\sigma≤x≤ \\mu+ 3\\sigma]$\n\nAutrement dit, dans le cas d’une distribution normale, il est très invraisemblable d’observer des données situées à plus de trois écarts types de la moyenne. Ces différentes égalités sont vraies **quelles que soient les valeurs de la moyenne et de l'écart-type**.\nNotez ici que lorsque $\\mu = 0$ et $\\sigma = 1$, nous obtenons la loi normale générale (ou centrée réduite) ([section @sec-02552]).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution gaussienne](02-univarie_files/figure-html/fig-fig260-1.png){#fig-fig260 fig-align='center' width=70%}\n:::\n:::\n\n\n#### Distribution gaussienne asymétrique\n\nLa distribution normale asymétrique (*skew-normal*) est une extension de la distribution gaussienne permettant de lever la contrainte de symétrie de la simple distribution gaussienne. Son espace d’échantillonnage est donc $]-\\infty; +\\infty[$. Sa fonction de densité est la suivante :\n\n$$\nf(x;\\xi;\\omega;\\alpha) = \\frac{2}{\\omega \\sqrt{2 \\pi}} e^{-\\frac{(x-\\xi)^{2}}{2 \\omega^{2}}} \\int_{-\\infty}^{\\alpha\\left(\\frac{x-\\xi}{\\omega}\\right)} \\frac{1}{\\sqrt{2 \\pi}} e^{-\\frac{t^{2}}{2}} d t\n$$ {#eq-skewgaussien}\n\navec $\\xi$ (xi) le paramètre de localisation, $\\omega$ (omega) le paramètre de dispersion (ou d’échelle) et $\\alpha$ (alpha) le paramètre de forme (contrôlant le degré de symétrie). Si $\\alpha = 0$, alors la distribution normale asymétrique est une distribution normale ordinaire. Ce type de distribution est très utile lorsque nous souhaitons modéliser une variable pour laquelle nous savons que des valeurs plus extrêmes s’observeront d’un côté ou de l’autre de la distribution. Les revenus totaux annuels des personnes ou des ménages sont de très bons exemples puisqu’ils sont distribués généralement avec une asymétrie positive : bien qu’une moyenne existe, il y a généralement plus de personnes ou de ménages avec des revenus très faibles que de personnes ou de ménages avec des revenus très élevés.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution gaussienne asymétrique](02-univarie_files/figure-html/fig-fig261-1.png){#fig-fig261 fig-align='center' width=70%}\n:::\n:::\n\n\n#### Distribution log-normale\n\nAu même titre que la distribution normale asymétrique, la distribution log-normale est une version asymétrique de la distribution normale. Son espace d’échantillonnage est $]0; +\\infty[$. Cela signifie que cette distribution ne peut décrire que des données continues et positives. Sa fonction de densité est la suivante : \n\n$$\nf(x ; \\mu ; \\sigma)=\\frac{1}{x \\sigma \\sqrt{2 \\pi}} e^{-\\left(\\frac{(\\ln x-\\mu)^{2}}{2 \\sigma^{2}}\\right)}\n$$ {#eq-loggaussien}\n\nÀ la différence la distribution *skew-normal*, la distribution log-normale ne peut avoir qu’une asymétrie positive (étirée vers la droite). Elle est cependant intéressante puisqu’elle ne compte que deux paramètres ($\\mu$ et $\\sigma$), ce qui la rend plus facile à ajuster. À nouveau, une distribution log-normale peut être utilisée pour décrire les revenus totaux annuels des individus ou des ménages ou les revenus d’emploi. Elle est aussi utilisée en économie sur les marchés financiers pour représenter les cours des actions et des biens (ces derniers ne pouvant pas être inférieurs à 0).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution log-gaussienne](02-univarie_files/figure-html/fig-fig262-1.png){#fig-fig262 fig-align='center' width=70%}\n:::\n:::\n\n\nPlus spécifiquement, la distribution log-normale est une transformation de la distribution normale. Comme son nom l'indique, elle permet de décrire le logarithme d'une variable aléatoire suivant une distribution normale.\n\n#### Distribution de Student {#sec-024311}\n\nLa distribution de Student joue un rôle important en statistique. Elle est par exemple utilisée lors du test *t* pour calculer le degré de significativité du test. Comme la distribution gaussienne, la distribution de Student a une forme de cloche, est centrée sur sa moyenne et définie sur $]-\\infty; +\\infty[$. Elle se distingue de la distribution normale principalement par le rôle que joue son troisième paramètre, $\\nu$ : le nombre de degrés de liberté, contrôlant le poids des queues de la distribution. Une petite valeur de $\\nu$ signifie que la distribution a des « queues plus lourdes » (*heavy tails* en anglais). Entendez par-là que les valeurs extrêmes ont une plus grande probabilité d’occurrence : \n\n$$\np(x ; \\nu ; \\hat{\\mu} ; \\hat{\\sigma})=\\frac{\\Gamma\\left(\\frac{\\nu+1}{2}\\right)}{\\Gamma\\left(\\frac{\\nu}{2}\\right) \\sqrt{\\pi \\nu} \\hat{\\sigma}}\\left(1+\\frac{1}{\\nu}\\left(\\frac{x-\\hat{\\mu}}{\\hat{\\sigma}}\\right)^{2}\\right)^{-\\frac{\\nu+1}{2}}\n$$ {#eq-student}\n\navec $\\mu$ le paramètre de localisation, $\\sigma$ le paramètre de dispersion (qui n’est cependant pas un écart-type comme pour la distribution normale) et $\\nu$ le nombre de degrés de liberté. Plus $\\nu$ est grand, plus la distribution de Student tend vers une distribution normale. Ici, la lettre grecque $\\Gamma$ représente la fonction mathématique gamma (à ne pas confondre avec la distribution Gamma). Un exemple d’application en études urbaines est l’exposition au bruit environnemental de cyclistes. Cette distribution s’approcherait certainement d’une distribution normale, mais les cyclistes croisent régulièrement des secteurs peu bruyants (parcs, rues résidentielles, etc.) et des secteurs très bruyants (artères majeures, zones industrielles, etc.), plus souvent que ce que prévoit une distribution normale, justifiant le choix d'une distribution de Student.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution de Student](02-univarie_files/figure-html/fig-fig263-1.png){#fig-fig263 fig-align='center' width=70%}\n:::\n:::\n\n\n#### Distribution de Cauchy\n\nLa distribution de Cauchy est également une distribution symétrique définie sur l’intervalle $]-\\infty; +\\infty[$. Elle a comme particularité d'être plus aplatie que la distribution de Student (d’avoir des queues potentiellement plus lourdes). Elle est notamment utilisée pour modéliser des phénomènes extrêmes comme les précipitations maximales annuelles, les niveaux d’inondations maximaux annuels ou les seuils critiques de perte pour les portefeuilles financiers. Il est également intéressant de noter que le quotient de deux variables indépendantes normalement distribuées suit une distribution de Cauchy. Sa fonction de densité est la suivante : \n\n$$\n\\frac{1}{\\pi \\gamma}\\left[\\frac{\\gamma^{2}}{\\left(x-x_{0}\\right)^{2}+\\gamma^{2}}\\right]\n$$ {#eq-cauchy}\n\nElle dépend donc de deux paramètres : $x_0$, le paramètre de localisation indiquant le pic de la distribution et $\\gamma$, un paramètre de dispersion.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution de Cauchy](02-univarie_files/figure-html/fig-fig264-1.png){#fig-fig264 fig-align='center' width=70%}\n:::\n:::\n\n\n#### Distribution du khi-deux\n\nLa distribution du khi-deux est utilisée dans de nombreux tests statistiques. Par exemple, le test du khi-deux de Pearson est utilisé pour comparer les écarts au carré entre des fréquences attendues et observées de deux variables qualitatives.\nLa distribution du khi-deux décrit plus généralement la somme des carrés d’un nombre *k* de variables indépendantes normalement distribuées. Il est assez rare de modéliser un phénomène à l’aide d’une distribution du khi-deux, mais son omniprésence dans les tests statistiques justifie qu’elle soit mentionnée ici. Cette distribution est définie sur l’intervalle $[0; +\\infty[$ et a pour fonction de densité : \n\n$$\nf(x;k) = \\frac{1}{2^{k / 2} \\Gamma(k / 2)} x^{k / 2-1} e^{-x / 2}\n$$ {#eq-chi2}\n\nLa distribution du khi-deux n’a qu’un paramètre *k*, représentant donc le nombre de variables mises au carré et dont nous faisons la somme pour obtenir la distribution du khi-deux.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution du khi-deux](02-univarie_files/figure-html/fig-fig265-1.png){#fig-fig265 fig-align='center' width=70%}\n:::\n:::\n\n\n#### Distribution exponentielle\n\nLa distribution exponentielle est une version continue de la distribution géométrique. Pour cette dernière, nous nous intéressons au nombre de tentatives nécessaires pour obtenir un résultat positif, soit une dimension discrète. Pour la distribution exponentielle, cette dimension discrète est remplacée par une dimension continue. L’exemple le plus intuitif est sûrement le cas du temps. Dans ce cas, la distribution exponentielle sert à modéliser le temps d’attente nécessaire pour qu’un évènement se produise. Il peut aussi s’agir d’une force que nous appliquons jusqu’à ce qu’un matériau cède. Cette distribution est donc définie sur l’intervalle [0; +$\\infty$[ et a pour fonction de densité :\n\n$$\nf(x;\\lambda) = \\lambda e^{-\\lambda x}\n$$ {#eq-exponentiel}\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution exponentielle](02-univarie_files/figure-html/fig-fig266-1.png){#fig-fig266 fig-align='center' width=70%}\n:::\n:::\n\n\nLa distribution exponentielle est conceptuellement proche de la distribution de Poisson. La distribution de Poisson régit le nombre des événements qui surviennent au cours d’un laps de temps donné. La distribution exponentielle peut servir à modéliser le temps qui s’écoule entre deux événements. \n\n#### Distribution Gamma {#sec-024315}\n\nLa distribution Gamma peut être vue comme la généralisation d’un grand nombre de distributions. Ainsi, les distributions exponentielle et du khi-deux peuvent être vues comme des cas particuliers de la distribution Gamma. Cette distribution est définie sur l’intervalle ]0; +$\\infty$[ (notez que le 0 est exclu) et sa fonction de densité est la suivante : \n\n$$\nf(x ; \\alpha; \\beta)=\\frac{\\beta^{\\alpha} x^{\\alpha-1} e^{-\\beta x}}{\\Gamma(\\alpha)}\n$$ {#eq-gamma}\n\nElle comprend donc deux paramètres : $\\alpha$ et $\\beta$. Le premier est le paramètre de forme et le second un paramètre d’échelle (à l’inverse d’un paramètre de dispersion, plus sa valeur est petite, plus la distribution est dispersée). Notez que cette distribution ne dispose pas d’un paramètre de localisation. Du fait de sa flexibilité, cette distribution est largement utilisée, notamment pour la modélisation des temps d’attente avant un évènement, de la taille des réclamations d’assurance, des quantités de précipitations, etc.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution Gamma](02-univarie_files/figure-html/fig-fig267-1.png){#fig-fig267 fig-align='center' width=70%}\n:::\n:::\n\n\n#### Distribution bêta {#sec-024316}\n\nLa distribution bêta est définie sur l’intervalle [0; 1], elle est donc énormément utilisée pour modéliser des variables étant des proportions ou des probabilités.\n\nLa distribution bêta a été élaborée pour modéliser la superposition d’un très grand nombre de petits effets fortuits qui ne sont pas indépendants et notamment pour étudier l’effet de la réalisation d’un événement aléatoire sur la probabilité des tirages subséquents. Elle a aussi une utilité pratique en statistique, car elle peut être combinée avec d’autres distributions (distribution bêta binomiale, bêta négative binomiale, etc.). Un autre usage plus rare mais intéressant est la modélisation de la fraction du temps représentée par une tâche dans le temps nécessaire à la réalisation de deux tâches de façon séquentielle. Cela est dû au fait que la distribution d’une distribution Gamma *g1* divisée par la somme de *g1* et d’une autre distribution Gamma *g2* suit une distribution bêta. Un exemple concret est, par exemple, la fraction du temps effectué à pied dans un déplacement multimodal. La distribution de bêta a la fonction de densité suivante : \n\n$$\nf(x;\\alpha;\\beta) = \\frac{1}{\\mathrm{B}(\\alpha, \\beta)} x^{\\alpha-1}(1-x)^{\\beta-1}\n$$ {#eq-beta}\n\nElle a donc deux paramètres $\\alpha$ et $\\beta$ contrôlant tous les deux la forme de la distribution. Cette caractéristique lui permet d’avoir une très grande flexibilité et même d’adopter des formes bimodales. $B$ correspond à la fonction mathématique Beta : ne pas la confondre avec la distribution Beta et le paramètre Beta ($\\beta$) de cette même distribution.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution bêta](02-univarie_files/figure-html/fig-fig268-1.png){#fig-fig268 fig-align='center' width=70%}\n:::\n:::\n\n\n#### Distribution de Weibull\n\nLa distribution de Weibull est directement liée à la distribution exponentielle, cette dernière étant en fait un cas particulier de distribution Weibull. Elle sert donc souvent à modéliser une quantité *x* (souvent le temps) à accumuler pour qu’un évènement se produise. La distribution de Weibull est définie sur l’intervalle [0; +$\\infty$[ et a la fonction de densité suivante : \n\n$$\nf(x;\\lambda) = \\frac{k}{\\lambda} (\\frac{x}{\\lambda})^{k-1} e^{-(\\frac{x}{\\lambda})^k}\n$$ {#eq-weibull}\n\n$\\lambda$ est le paramètre de dispersion (analogue à celui d’une distribution exponentielle classique) et *k* le paramètre de forme. Pour bien comprendre le rôle de *k*, prenons un exemple : la propagation d’un champignon d’un arbre à son voisin. Si $k<1$, le risque instantané que l’évènement modélisé se produise diminue avec le temps (en d’autres termes, plus le temps passe, plus petite devient la probabilité d’être contaminé). Si $k=1$, alors le risque instantané que l’évènement se produise reste identique dans le temps (la loi de Weibull se résume alors à une loi exponentielle). Si $k > 1$, alors le risque instantané que l’évènement se produise augmente avec le temps (la probabilité pour un arbre d'être contaminé s'il ne l’a pas déjà été — pas seulement le risque cumulé — augmente en fonction du temps). La distribution de Weibull est très utilisée en analyse de survie, en météorologie, en ingénierie des matériaux et dans la théorie des valeurs extrêmes.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution de Weibull](02-univarie_files/figure-html/fig-fig269-1.png){#fig-fig269 fig-align='center' width=70%}\n:::\n:::\n\n\n#### Distribution Pareto\n\nCette distribution a été élaborée par Vilfredo Pareto pour donner une forme mathématique à ce qui porte aujourd’hui le nom de principe de Pareto et que nous exprimons souvent de manière imagée — dans une société donnée, 20 % des individus possèdent 80 % de la richesse —, mais qui est plus justement exprimée en écrivant que, de manière générale, dans toute société, la plus grande partie du capital est détenue par une petite fraction de la population. Elle est définie sur l’intervalle $[x_m; +\\infty[$ avec la fonction de densité suivante : \n\n$$\nf(x;x_m;k) = (\\frac{x_m}{x})^k\n$$ {#eq-pareto}\n\nElle comprend donc deux paramètres, $x_m$ étant un paramètre de localisation (décalant la distribution vers la droite ou vers la gauche) et $k$ un paramètre de forme. Plus $k$ augmente, plus la probabilité prédite par la distribution décroît rapidement.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution de Pareto](02-univarie_files/figure-html/fig-fig270-1.png){#fig-fig270 fig-align='center' width=70%}\n:::\n:::\n\n\nAu-delà de la question de la répartition de la richesse, la distribution de Pareto peut également être utilisée pour décrire la répartition de la taille des villes [@William_pareto_ville], [la popularité des hommes sur Tinder](https://medium.com/@worstonlinedater/tinder-experiments-ii-guys-unless-you-are-really-hot-you-are-probably-better-off-not-wasting-your-2ddf370a6e9a){target=\"_blank\"} ou la taille des fichiers échangés sur Internet [@William_pareto]. Pour ces trois exemples, nous avons les situations suivantes : de nombreuses petites villes, profils peu attractifs, petits fichiers échangés et à l'inverse très peu de grandes villes, profils très attractifs, gros fichiers échangés.\n\nLa loi de Pareto est liée à la loi exponentielle. Si une variable aléatoire suit une loi de Pareto, le logarithme du quotient de cette variable et de son paramètre de localisation est une variable aléatoire qui suit une loi exponentielle.\n\n#### Cas particuliers\n\nSachez également qu’il existe des distributions « plus exotiques » que nous n’abordons pas ici, mais auxquelles vous pourriez être confrontés un jour :\n\n* Les distributions sphériques, servant à décrire des données dont le 0 est équivalent à la valeur maximale. Par exemple, des angles puisque 0 et 360 degrés sont identiques.\n\n* Les distributions composées (*mixture distributions*), permettant de modéliser des phénomènes issus de la superposition de plusieurs distributions. Par exemple, la distribution de la taille de l'ensemble des êtres humains est en réalité une superposition de deux distributions gaussiennes, une pour chaque sexe, puisque ces deux distributions n’ont pas la même moyenne ni le même écart-type.\n\n* Les distributions multivariées permettant de décrire des phénomènes multidimensionnels. Par exemple, la réussite des élèves en français et en mathématique pourrait être modélisée par une distribution gaussienne bivariée plutôt que deux distributions distinctes. Ce choix serait pertinent si nous présumons que ces deux variables sont corrélées plutôt qu'indépendantes.\n\n* Les distributions censurées décrivant des variables pour lesquelles les données sont issues d'un tirage « censuré ». En d'autres termes, la variable étudiée varie sur une certaine étendue, mais du fait du processus de tirage (collecte des données), les valeurs au-delà de certaines limites sont censurées. Un bon exemple est la mesure de la pollution sonore avec un capteur incapable de détecter des niveaux sonores en dessous de 55 décibels. Il arrive parfois en ville que les niveaux sonores descendent plus bas que ce seuil, mais les données collectées ne le montrent pas. Dans ce contexte, il est important d’utiliser des versions censurées des distributions présentées précédemment. Les observations au-delà de la limite sont conservées dans l’analyse, mais nous ne disposons que d’une information partielle à leur égard (elles sont au-delà de la limite).\n\n* Les distributions tronquées, souvent confondues avec les distributions censurées, décrivent des situations où des données au-delà d’une certaine limite sont impossibles à collecter et retirées simplement de l’analyse.\n\n### Conclusion sur les distributions\n\nVoilà qui conclut cette exploration des principales distributions à connaître. L’idée n’est bien sûr pas de toutes les retenir par cœur (et encore moins les formules mathématiques), mais plutôt de se rappeler dans quels contextes elles peuvent être utiles. Vous aurez certainement besoin de relire cette section avant d’aborder le [chapitre @sec-chap08] portant sur les modèles linéaires généralisés (GLM).\nWikipédia dispose d’informations très détaillées sur chaque distribution si vous avez besoin d’informations complémentaires. Pour un tour d’horizon plus exhaustif des distributions, vous pouvez aussi faire un tour sur les projets [ProbOnto](https://sites.google.com/site/probonto/home){target=\"_blank\"} et [*the ultimate probability distribution explorer*](https://blog.wolfram.com/2013/02/01/the-ultimate-univariate-probability-distribution-explorer/){target=\"_blank\"}. \n\n\n## Statistiques descriptives sur des variables quantitatives {#sec-025}\n\n### Paramètres de tendance centrale {#sec-0251}\n\nTrois mesures de tendance centrale permettent de résumer rapidement une variable quantitative :\n\n* La **moyenne arithmétique** est simplement la somme des données d'une variable divisée par le nombre d'observations (*n*), soit $\\frac{\\sum_{i=1}^n x_i}{n}$ notée $\\mu$ (prononcé *mu*) pour des données pour une population et $\\bar{x}$ (prononcé *x barre*) pour un échantillon.\n\n* La **médiane** est la valeur qui coupe la distribution d'une variable d'une population ou d'un échantillon en deux parties égales. Autrement dit, 50 % des valeurs des observations lui sont supérieures et 50 % lui sont inférieures.\n\n* Le **mode** est la valeur la plus fréquente parmi un ensemble d'observations pour une variable. Il s'applique ainsi à des variables discrètes (avec un nombre fini de valeurs discrètes dans un intervalle donné) et non à des variables continues (avec un nombre infini de valeurs réelles dans un intervalle donné). Prenons deux variables : l'une discrète relative au nombre d'accidents par intersection (avec $X \\in \\left[0,20\\right]$) et l'autre continue relative à la distance de dépassement (en mètres) d'une personne à vélo par une personne conduisant un véhicule motorisé (avec $X \\in \\left[0,5\\right]$). Pour la première, le mode – la valeur la plus fréquente – est certainement 0. Pour la seconde, identifier le mode n'est pas pertinent puisqu'il peut y avoir un nombre infini de valeurs entre 0 et 5 mètres.\n\n**Il convient de ne pas confondre moyenne et médiane!** Dans le @tbl-RevMoyMed, nous avons reporté les valeurs moyennes et médianes des revenus des ménages pour les municipalités de l'île de Montréal en 2015. Par exemple, les 8685 ménages résidant à Wesmount disposaient en moyenne d'un revenu de 295 099 \\$; la moitié de ces 8685 ménages avaient un revenu inférieur à 100 153 \\$ et l'autre moitié un revenu supérieur à cette valeur (médiane). Cela démontre clairement que la moyenne peut être grandement affectée par des valeurs extrêmes (faibles ou fortes). Autrement dit, plus l'écart entre les valeurs de la moyenne et la médiane est important, plus les données de la variable sont inégalement réparties. À Westmount, soit la municipalité la plus nantie de l'île de Montréal, les valeurs extrêmes sont des ménages avec des revenus très élevés tirant fortement la moyenne vers le haut. À l'inverse, le faible écart entre les valeurs moyenne et médiane dans la municipalité de Montréal-Est (58 594 \\$ versus 50 318 \\$) souligne que les revenus des ménages sont plus également répartis. Cela explique que pour comparer les revenus totaux ou d'emploi entre différents groupes (selon le sexe, le groupe d'âge, le niveau d'éducation, la municipalité ou région métropolitaine, etc.), nous privilégions habituellement l'utilisation des revenus médians.\n\n\n::: {#tbl-RevMoyMed .cell tbl-cap='Revenus moyens et médians des ménages en dollars, municipalités de l\\'île de Montréal, 2015'}\n::: {.cell-output-display}\n|Municipalité | Nombre de ménages| Revenu moyen| Revenu médian|\n|:-----------------------|-----------------:|------------:|-------------:|\n|Baie-D'Urfé | 1 330| 171 390| 118 784|\n|Beaconsfield | 6 660| 187 173| 123 392|\n|Côte-Saint-Luc | 13 490| 94 570| 58 935|\n|Dollard-Des Ormeaux | 17 210| 102 104| 78 981|\n|Dorval | 8 390| 89 952| 64 689|\n|Hampstead | 2 470| 250 497| 122 496|\n|Kirkland | 6 685| 144 676| 115 381|\n|Montréal | 779 805| 69 047| 50 227|\n|Montréal-Est | 1 730| 58 594| 50 318|\n|Montréal-Ouest | 1 850| 159 374| 115 029|\n|Mont-Royal | 7 370| 205 309| 109 540|\n|Pointe-Claire | 12 380| 100 294| 80 242|\n|Sainte-Anne-de-Bellevue | 1 960| 102 969| 67 200|\n|Senneville | 345| 203 790| 116 224|\n|Westmount | 8 685| 295 099| 100 153|\n:::\n:::\n\n\n### Paramètres de position {#sec-0252}\n\nLes paramètres de position permettent de diviser une distribution en _n_ parties égales.\n\n* Les **quartiles** qui divisent une distribution en quatre parties (25 %) :\n + Q1 (25 %), soit le quartile inférieur ou premier quartile;\n + Q2 (50 %), soit la médiane;\n + Q3 (75 %), soit le quartile supérieur ou troisième quartile.\n* Les **quintiles** qui divisent une distribution en cinq parties égales (20 %).\n* Les **déciles** (de D1 à D9) qui divisent une distribution en dix parties égales (10 %).\n* Les **centiles** (de C1 à C99) qui divisent une distribution en cent parties égales (1 %).\n\nEn cartographie, les quartiles et les quintiles sont souvent utilisés pour discrétiser une variable quantitative (continue ou discrète) en quatre ou cinq classes et plus rarement, en dix classes (déciles). Avec les quartiles, les bornes des classes qui comprennent chacune 25 % des unités spatiales sont définies comme suit : [Min à Q1], [Q1 à Q2], [Q2 à Q3] et [Q3 à Max]. La méthode de discrétisation selon les quartiles ou quintiles permet de repérer, en un coup d'œil, à quelle tranche de 25 % ou de 20 % des données appartient chacune des unités spatiales. Cette méthode de discrétisation est aussi utile pour comparer plusieurs cartes et vérifier si deux phénomènes sont ou non colocalisés [@pumain1994]. En guise d'exemple, les pourcentages de personnes à faible revenu et de locataires par secteur de recensement ont clairement des distributions spatiales très semblables dans la région métropolitaine de Montréal en 2016 (@fig-univarie2).\n\n\n![Exemples de cartographie avec une discrétisation selon les quantiles](images/Chap02/figure2.jpg){#fig-univarie2 width=\"85%\" fig-align=\"center\"}\n\nUne lecture attentive des valeurs des centiles permet de repérer la présence de valeurs extrêmes, voire aberrantes, dans un jeu de données. Il n'est donc pas rare de les voir reportées dans un tableau de statistiques descriptives d'un article scientifique, et ce, afin de décrire succinctement les variables à l'étude. Par exemple, dans une étude récente comparant les niveaux d'exposition au bruit des cyclistes dans trois villes [@2020_1], les auteurs reportent à la fois les valeurs moyennes et celles de plusieurs centiles. Globalement, la lecture des valeurs moyennes permet de constater que, sur la base des données collectées, les cyclistes sont plus exposés au bruit à Paris qu'à Montréal et Copenhague (73,4 dB(A) contre 70,7 et 68,4, @tbl-Centiles). Compte tenu de l'échelle logarithmique du bruit, la différence de 5 dB(A) entre les valeurs moyennes du bruit de Copenhague et de Paris peut être considérée comme une multiplication de l'énergie sonore par plus de 3. Pour Paris, l'analyse des quartiles montre que durant 25 % du temps des trajets à vélo (plus de 63 heures de collecte), les participantes et participants ont été exposés à des niveaux de bruit soit inférieurs à 69,1 dB(A) (premier quartile), soit supérieurs à 74 dB(A) (troisième quartile). Quant à l'analyse des centiles, elle permet de constater que durant 5 % et 10 % du temps, les participantes et participants étaient exposés à des niveaux de bruit très élevés, dépassant 75 dB(A) (C90 = 76 et C90 = 77,2).\n\n\n::: {#tbl-Centiles .cell tbl-cap='Stastistiques descriptives de l\\'exposition au bruit des cyclistes par minute dans trois villes (dB(A), Laeq 1min)'}\n::: {.cell-output-display}\n|Statistiques | Copenhague| Montréal| Paris|\n|:-----------------------|----------:|--------:|-------:|\n|N | 6 212,0| 4 723,0| 3 793,0|\n|Moyenne de bruit | 68,4| 70,7| 73,4|\n|Centiles | | | |\n|1 | 57,5| 59,2| 62,3|\n|5 | 59,1| 61,1| 65,0|\n|10 | 60,3| 62,3| 66,5|\n|25 (premier quartile) | 62,7| 64,5| 69,1|\n|50 (médiane) | 66,0| 67,7| 71,6|\n|75 (troisième quartile) | 69,2| 71,0| 74,0|\n|90 | 71,9| 73,7| 76,0|\n|95 | 73,3| 75,2| 77,2|\n|99 | 76,5| 78,9| 81,0|\n:::\n:::\n\n\n\n### Paramètres de dispersion {#sec-0253}\nCinq principales mesures de dispersion permettent d'évaluer la variabilité des valeurs d'une variable quantitative : l'étendue, l'écart interquartile, la variance, l'écart-type et le coefficient de variation. Notez d'emblée que cette dernière mesure ne s'applique pas à des variables d'intervalle ([section @sec-02122]).\n\n* **L'étendue** est la différence entre les valeurs minimale et maximale d'une variable, soit l'intervalle des valeurs dans lequel elle a été mesurée. Il convient d'analyser avec prudence cette mesure puisqu'elle inclut dans son calcul des valeurs potentiellement extrêmes, voire aberrantes (faibles ou fortes).\n\n* **L'intervalle ou écart interquartile** est la différence entre les troisième et premier quartiles (Q3 − Q1). Il représente ainsi une mesure de la dispersion des valeurs de 50 % des observations centrales de la distribution. Plus la valeur de l'écart interquartile est élevée, plus la dispersion des 50 % des observations centrales est forte. Contrairement à l'étendue, cette mesure élimine l'influence des valeurs extrêmes puisqu'elle ne tient pas compte des 25 % des observations les plus faibles [Min à Q1] et des 25 % des observations les plus fortes [Q3 à Max]. Graphiquement, l'intervalle interquartile est représenté à l'aide d'une boîte à moustaches (*boxplot* en anglais) : plus l'intervalle interquartile est grand, plus la boîte est allongée (@fig-univarie3).\n\n![Graphique en violon, boîte à moustaches et intervalle interquartile](images/Chap02/figure3.jpg){#fig-univarie3 width=\"30%\" fig-align=\"center\"}\n\n\n* **La variance** est la somme des déviations à la moyenne au carré (numérateur) divisée par le nombre d'observations pour une population ($\\sigma^2$) ou divisée par le nombre d'observations moins une ($s^2$) pour un échantillon (@eq-variance). Puisque les déviations à la moyenne sont mises au carré, la valeur de la variance (tout comme celle de l'écart-type) est toujours positive. Plus sa valeur est élevée, plus les observations sont dispersées autour de la moyenne. La variance représente ainsi l'écart au carré moyen des observations à la moyenne. \n\n* **L'écart-type** est la racine carrée de la variance (@eq-ecartype). Rappelez-vous que la variance est calculée à partir des déviations à la moyenne mises au carré. Étant donné que l'écart-type est la racine carrée de la variance, il est donc évalué dans la même unité que la variable, contrairement à la variance. Bien entendu, comme pour la variance, plus la valeur de l'écart-type est élevée, plus la distribution des observations autour de la moyenne est dispersée.\n\n$$ \n\\sigma^2=\\frac{\\sum_{i=1}^n (x_{i}-\\mu)^2}{n} \\text{ ou } s^2=\\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})^2}{n-1}\n$$ {#eq-variance}\n\n$$\n\\sigma=\\sqrt{\\sigma^2}=\\sqrt{\\frac{\\sum_{i=1}^n (x_{i}-\\mu)^2}{n}} \\text{ ou } s=\\sqrt{s^2}=\\sqrt{\\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})^2}{n-1}}\n$$ {#eq-ecartype}\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Formules des variances et des écarts-types**\n:::\n::: bloc_notes-body\nLes formules des variances et des écarts-types pour une population et un échantillon sont très similaires : seul le dénominateur change avec $n$ *versus* $n-1$ observations. Par conséquent, plus le nombre d'observations de votre jeu de données est important, plus l'écart entre ces deux mesures de dispersion pour une population et un échantillon est minime.\n\nComme dans la plupart des logiciels de statistique, les fonctions de base `var` et `sd` de R calculent la variance et l'écart-type pour un échantillon ($n-1$ au dénominateur). Si vous souhaitez les calculer pour une population, adaptez la syntaxe ci-dessous dans laquelle `df$var1` représente la variable intitulée `var1` présente dans un *DataFrame* nommé `df`.\n\n`var.p <- mean((df$var1 - mean(df$var1))^2)` \n\n`sd.p <- sqrt(mean((df$var1 - mean(df$var1))^2))` \n:::\n:::\n\n* **Le coefficient de variation (CV)** est le rapport entre l'écart-type et la moyenne, représentant ainsi une standardisation de l'écart-type ou, en d'autres termes, une mesure de dispersion relative (@eq-cv). L'écart-type étant exprimé dans l'unité de mesure de la variable, il ne peut pas être utilisé pour comparer les dispersions de variables exprimées des unités de mesure différentes (par exemple, en pourcentage, en kilomètres, en dollars, etc.). Pour y remédier, nous utilisons le coefficient de variation : une variable est plus dispersée qu'une autre si la valeur de son CV est plus élevée. Certaines personnes préfèrent multiplier la valeur du CV par 100 : l'écart-type est alors exprimé en pourcentage de la moyenne.\n\n\n$$ \nCV=\\frac{\\sigma}{\\mu} \\text{ ou } CV=\\frac{s^2}{\\bar{x}}\n$$ {#eq-cv}\n\n\nIllustrons comment calculer les cinq mesures de dispersion précédemment décrites à partir de valeurs fictives pour huit observations (colonne intitulée $x_i$ au @tbl-datavar). Les différentes statistiques reportées dans ce tableau sont calculées comme suit :\n\n* La **moyenne** est la somme divisée par le nombre d'observations, soit $\\mbox{248/8}=\\mbox{31}$.\n\n* L'**étendue** est la différence entre les valeurs maximale et minimale, soit $\\mbox{40}-\\mbox{22}=\\mbox{30}$.\n\n* Les quartiles coupent la distribution en quatre parties égales. Avec huit observations triées par ordre croissant, **le premier quartile** est égal à la valeur de la deuxième observation (soit 25), la **médiane** à celle de la quatrième (30), le **troisième quartile** à celle de la sixième (35).\n\n* **L'écart interquartile** est la différence entre Q3 et Q1, soit $\\mbox{35}-\\mbox{25}=\\mbox{10}$.\n\n* La seconde colonne du tableau est l'écart à la moyenne ($x_i-\\bar{x}$), soit $\\mbox{22} - \\mbox{31} = -\\mbox{9}$ pour l'observation *1*; la somme de ces écarts est toujours égale à 0. La troisième colonne est cette déviation mise au carré ($(x_i-\\bar{x})^2$), soit $-\\mbox{9}^2 = \\mbox{81}$, toujours pour l'observation *1*. La somme de ces déviations à la moyenne au carré (268) représente le numérateur de la variance (@eq-variance). En divisant cette somme par le nombre d'observations, nous obtenons la **variance pour une population** ($\\mbox{268}/\\mbox{8}=\\mbox{33,5}$) tandis que la **variance d'un échantillon** est égale à $\\mbox{268}/(\\mbox{8}-\\mbox{1})=\\mbox{38,29}$.\n\n* L'écart-type est la racine carrée de la variance (@eq-ecartype), soit $\\sigma=\\sqrt{\\mbox{33,5}}=\\mbox{5,79}$ et $s=\\sqrt{\\mbox{38,29}}=\\mbox{6,19}$.\n\n* Finalement, les valeurs des coefficients de variation (@eq-cv) sont de $\\mbox{5,79}/\\mbox{31}=\\mbox{0,19}$ pour une population et $\\mbox{6,19}/\\mbox{31}=\\mbox{0,20}$ pour un échantillon. \n\n\n\n::: {#tbl-datavar .cell tbl-cap='Calcul des mesures de dispersion sur des données fictives'}\n::: {.cell-output-display}\n|Observation | $x_i$| $x_i-\\bar{x}$ | $(x_i-\\bar{x})^2$|\n|:-----------------------------------------|------:|:-------------:|-----------------:|\n|1 | 22,00| -9 | 81,0|\n|2 | 25,00| -6 | 36,0|\n|3 | 27,00| -4 | 16,0|\n|4 | 30,00| -1 | 1,0|\n|5 | 32,00| 1 | 1,0|\n|6 | 35,00| 4 | 16,0|\n|7 | 37,00| 6 | 36,0|\n|8 | 40,00| 9 | 81,0|\n|**Statistique** | | | |\n|N | 8,00| | |\n|Somme | 248,00| 0 | 268,0|\n|Moyenne ($\\bar{x}$ ou $\\mu$) | 31,00| 0 | 33,5|\n|Étendue | 18,00| | |\n|Premier quartile | 25,00| | |\n|Troisième quartile | 35,00| | |\n|Intervalle interquartile | 10,00| | |\n|Variance (population, $\\sigma^2$) | 33,50| | |\n|Écart-type (population, $\\sigma$) | 5,79| | |\n|Variance (échantillon, $s^2$) | 38,29| | |\n|Écart-type (échantillon, $s$) | 6,19| | |\n|Coefficient de variation ($\\sigma / \\mu$) | 0,19| | |\n|Coefficient de variation ($s / \\bar{x}$) | 0,20| | |\n:::\n:::\n\n\nLe @tbl-datavar2 vise à démontrer, à partir de trois variables, comment certaines mesures de dispersion sont sensibles à l'unité de mesure et/ou aux valeurs extrêmes. \n\nConcernant **l'unité de mesure**, nous avons créé deux variables *A* et *B*, où *B* étant simplement *A* multipliée par 10. Pour *A*, les valeurs de la moyenne, de l'étendue et de l'intervalle interquartile sont respectivement 31, 18 et 10. Sans surprise, celles de *B* sont multipliées par 10 (310, 180, 100). La variance étant la moyenne des déviations à la moyenne au carré, elle est égale à 33,50 pour *A* et donc à $\\mbox{33,50}\\times10^2=\\mbox{3350}$ pour *B*; l'écart-type de *B* est égal à celui de *A* multiplié par 10. Cela démontre que l'étendue, l'intervalle interquartile, la variance et l'écart-type sont des mesures de dispersion dépendantes de l'unité de mesure. Par contre, étant donné que le coefficient de variation (CV) est le rapport de l'écart-type avec la moyenne, il a la même valeur pour *A* et *B*, ce qui démontre que le CV est bien une mesure de dispersion relative permettant de comparer des variables exprimées dans des unités de mesure différentes.\n\nConcernant **la sensibilité aux valeurs extrêmes**, nous avons créé la variable *C* pour laquelle seule la huitième observation a une valeur différente (40 pour *A* et 105 pour *B*). Cette valeur de 105 pourrait être soit une valeur extrême positive mesurée, soit une valeur aberrante (par exemple, si l'unité de mesure était un pourcentage variant de 0 à 100 %). Cette valeur a un impact important sur la moyenne (31 contre 39,12) et l'étendue (18 contre 83) et corollairement sur la variance (33,50 contre 641,86), l'écart-type (5,79 contre 25,33) et le coefficient de variation (0,19 contre 0,65). Par contre, comme l'intervalle interquartile est calculé sur 50 % des observations centrales ($\\mbox{Q3}-\\mbox{Q1}$), il n'est pas affecté par cette valeur extrême.\n\n\n\n::: {#tbl-datavar2 .cell tbl-cap='Illustration de la sensibilité des mesures de dispersion à l\\'unité de mesure et aux valeurs extrêmes'}\n::: {.cell-output-display}\n|Observation | A| B| C|\n|:-----------------------------------------|-----:|--------:|------:|\n|1 | 22,00| 220,00| 22,00|\n|2 | 25,00| 250,00| 25,00|\n|3 | 27,00| 270,00| 27,00|\n|4 | 30,00| 300,00| 30,00|\n|5 | 32,00| 320,00| 32,00|\n|6 | 35,00| 350,00| 35,00|\n|7 | 37,00| 370,00| 37,00|\n|8 | 40,00| 400,00| 105,00|\n|**Statistique** | | | |\n|Moyenne ($\\mu$) | 31,00| 310,00| 39,12|\n|Étendue | 18,00| 180,00| 83,00|\n|Intervalle interquartile | 10,00| 100,00| 10,00|\n|Variance (population, $\\sigma^2$) | 33,50| 3 350,00| 641,86|\n|Écart-type (population, $\\sigma$) | 5,79| 57,88| 25,33|\n|Coefficient de variation ($\\sigma / \\mu$) | 0,19| 0,19| 0,65|\n:::\n:::\n\n::: {#tbl-resume .cell tbl-cap='Résumé de la sensibilité de la moyenne et des mesures de dispersion'}\n::: {.cell-output-display}\n|Statistique | Unité de mesure | Valeurs extrêmes |\n|:------------------------|:---------------:|:----------------:|\n|Moyenne | X | X |\n|Étendue | X | X |\n|Intervalle interquartile | X | |\n|Variance | X | X |\n|Écart-type | X | X |\n|Coefficient de variation | | X |\n:::\n:::\n\n\n\n### Paramètres de forme {#sec-0254}\n\n#### Vérification de la normalité d'une variable quantitative\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Normalité d'une variable**\n:::\n::: bloc_objectif-body\nDe nombreuses méthodes statistiques qui sont abordées dans les chapitres suivants – entre autres, la corrélation de Pearson, les test *t* et l'analyse de variance, les régressions simple et multiple – requièrent que la variable quantitative suive une **distribution normale** (nommée aussi **distribution gaussienne**).\n\nDans cette sous-section, nous décrivons trois démarches pour vérifier si la distribution d'une variable est normale : les coefficients d'asymétrie et d'aplatissement (*skewness* et *kurtosis* en anglais), les graphiques (histogramme avec courbe normale et diagramme quantile-quantile), les tests de normalité (tests de Shapiro-Wilk, de Kolmogorov-Smirnov, de Lilliefors, d'Anderson-Darling et de Jarque-Bera).\n\n**Il est vivement recommandé de réaliser les trois démarches!**\n:::\n:::\n\nUne distribution est normale quand elle est symétrique et mésokurtique (@fig-FormeDistr).\n\n![Formes d'une distribution et coefficients d'asymétrie et d'aplatissement](images/Chap02/FormeDistribution.jpg){#fig-FormeDistr width=\"70%\" fig-align=\"center\"}\n\n##### Vérification de la normalité avec les coefficients d'asymétrie et d'aplatissement\n\n**Une distribution est dite symétrique** quand la moyenne arithmétique est au centre de la distribution, c'est-à-dire que les observations sont bien réparties de part et d'autre de la moyenne qui est alors égale à la médiane et au mode (nous utilisons uniquement le mode pour une variable discrète et non pour une variable continue). Pour évaluer l'asymétrie, nous utilisons habituellement le coefficient d'asymétrie (*skewness* en anglais). \n\nSachez toutefois qu'il existe trois façons (formules) pour le calculer [@joanes1998comparing] : $g_1$ est la formule classique (@eq-SkewType1), disponible dans R avec la fonction `skewness` du *package* `moments`), $G_1$ est une version ajustée (@eq-SkewType2), utilisée dans les logiciels SAS et SPSS notamment) et $b_1$ est une autre version ajustée (@eq-SkewType3), utilisée par les logiciels MINITAB et BMDP). Nous verrons qu'avec les *packages* `DescTools` ou `e1071`, il est possible de calculer ces trois méthodes. Aussi, pour de grands échantillons ($n>100$), il y a très peu de différences entre les résultats produits par ces trois formules [@joanes1998comparing]. Quelle que soit la formule utilisée, le coefficient d'asymétrie s'interprète comme suit (@fig-asymetrie) :\n\n* Quand la valeur du *skewness* est négative, la **distribution est asymétrique négative**. La distribution est alors tirée à gauche par des valeurs extrêmes faibles, mais peu nombreuses. Nous employons souvent l'expression *la queue de distribution* est étirée vers la gauche. La moyenne est alors inférieure à la médiane.\n\n* Quand la valeur du *skewness* est égale à 0, **la distribution est symétrique** (la médiane est égale à la moyenne). Pour une variable discrète, les valeurs du mode, de la moyenne et de la médiane sont égales.\n\n* Quand la valeur du *skewness* est positive, la **distribution est symétrique positive**. La distribution est alors tirée à droite par des valeurs extrêmes fortes, mais peu nombreuses. La queue de distribution est alors étirée vers la droite et la moyenne est supérieure à la médiane. En sciences sociales, les variables de revenu (totaux ou d'emploi, des individus ou des ménages) ont souvent des distributions asymétriques positives : la moyenne est affectée par quelques observations avec des valeurs de revenu très élevées et est ainsi supérieure à la médiane. En études urbaines, la densité de la population pour des unités géographiques d'une métropole donnée (secteur de recensement par exemple) a aussi souvent une distribution asymétrique positive : quelques secteurs de recensement au centre de la métropole sont caractérisés par des valeurs de densité très élevées qui tirent la distribution vers la droite.\n\n$$ \ng_1=\\frac{ \\frac{1}{n} \\sum_{i=1}^n(x_i-\\bar{x})^3} { \\left[\\frac{1}{n}\\sum_{i=1}^n(x_i-\\bar{x})^2\\right] ^\\frac{3}{2}}\n$$ {#eq-SkewType1}\n\n$$ \nG_1= \\frac{\\sqrt{n(n-1)}}{n-2} g_1\n$$ {#eq-SkewType2}\n\n$$\nb_1= \\left( \\frac{n-1}{n} \\right) ^\\frac{3}{2} g_1\n$$ {#eq-SkewType3}\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Asymétrie d'une distribution](02-univarie_files/figure-html/fig-asymetrie-1.png){#fig-asymetrie fig-align='center' width=100%}\n:::\n:::\n\n\n\n**Pour évaluer l'aplatissement d'une distribution**, nous utilisons le coefficient d’aplatissement (*kurtosis* en anglais). Là encore, il existe trois formules pour le calculer (équations [-@eq-KurtType1], [-@eq-KurtType2], [-@eq-KurtType3]) qui renvoient des valeurs très semblables pour de grands échantillons [@joanes1998comparing]. Cette mesure s'interprète comme suit (@fig-asymetrie) :\n\n* Quand la valeur du *kurtosis* est négative, la **distribution est platikurtique**. La distribution est dite plate, c'est-à-dire que la valeur de l'écart-type est importante (comparativement à une distribution normale), signalant une grande dispersion des valeurs de part et d'autre la moyenne.\ns\n* Quand la valeur du *kurtosis* est égale à 0, **la distribution est mésokurtique**, ce qui est typique d'une distribution normale.\n\n* Quand la valeur du *kurtosis* est positive, la **distribution est leptokurtique**, signalant que l'écart-type (la dispersion des valeurs) est plutôt faible. Autrement dit, la dispersion des valeurs autour de la moyenne est faible.\n\n$$\ng_2=\\frac{\\frac{1}{n}\\sum_{i=1}^n(x_i-\\bar{x})^4} {\\left( \\frac{1}{n}\\sum_{i=1}^n(x_i-\\bar{x})^2\\right)^2}-3\n$$ {#eq-KurtType1}\n\n$$ \nG_2 = \\frac{n-1}{(n-2)(n-3)} \\{(n+1) g_2 + 6\\}\n$$ {#eq-KurtType2}\n\n$$ \nb_2 = (g_2 + 3) (1 - 1/n)^2 - 3\n$$ {#eq-KurtType3}\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Applatissement d'une distribution](02-univarie_files/figure-html/fig-kurtosis-1.png){#fig-kurtosis fig-align='center' width=100%}\n:::\n:::\n\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Kurtosis normalisé**\n:::\n::: bloc_attention-body\nRegardez attentivement les équations [-@eq-KurtType1], [-@eq-KurtType2], [-@eq-KurtType3]; vous remarquez que pour $g_2$ et $b_2$, il y a une soustraction de 3 et une addition 6 pour $G_2$. Nous parlons alors de *kurtosis* normalisé (*excess kurtosis* en anglais). Pour une distribution normale, il prend la valeur de 0, comparativement à la valeur de 3 pour un *kurtosis* non normalisé. Par conséquent, avant de calculer le *kurtosis*, il convient de s'assurer que la fonction que vous utilisez implémente une méthode de calcul normalisée (donnant une valeur de 0 pour une distribution normale). Par exemple, la fonction `Kurt` du *package* `DescTools` calcule les trois formules normalisées tandis que la fonction `kurtosis` du *package* `moments` renvoie un *kurtosis* non normalisé.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(DescTools)\nlibrary(moments)\n# Générer une variable normalement distribuée avec 1000 observations\nNormale <- rnorm(1500,0,1)\nround(DescTools::Kurt(Normale),3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] -0.066\n```\n:::\n\n```{.r .cell-code}\nround(moments::kurtosis(Normale),3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 2.938\n```\n:::\n:::\n\n:::\n:::\n\n##### Vérification de la normalité avec des graphiques\n\nLes graphiques sont un excellent moyen de vérifier visuellement si une distribution est normale ou pas. Bien entendu, les histogrammes, que nous avons déjà largement utilisés, sont un incontournable. À titre de rappel, ils permettent de représenter la forme de la distribution des données (@fig-CourbeNormale). Un autre type de graphique intéressant est le **diagramme quantile-quantile** (*Q-Q plot* en anglais), qui permet de comparer la distribution d'une variable avec une distribution gaussienne (normale). Trois éléments composent ce graphique comme illustré à la @fig-qqplot :\n\n* les points, représentant les observations de la variable;\n* la distribution gaussienne (normale), représentée par une ligne;\n* l'intervalle de confiance à 95 % de la distribution normale (en marron sur la figure).\n\nQuand la variable est normalement distribuée, les points sont situés le long de la ligne. Plus les points localisés en dehors de l'intervalle de confiance (bande marron) sont nombreux, plus la variable est alors anormalement distribuée.\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Histogrammes et courbe normale](02-univarie_files/figure-html/fig-CourbeNormale-1.png){#fig-CourbeNormale fig-align='center' width=90%}\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Diagrammes quantile-quantile](02-univarie_files/figure-html/fig-qqplot-1.png){#fig-qqplot fig-align='center' width=90%}\n:::\n:::\n\n\n##### Vérification de la normalité avec des tests de normalité {#sec-025413}\n\nCinq principaux tests d'hypothèse permettent de vérifier la normalité d'une variable : les tests de **Kolmogorov-Smirnov** (KS), de **Lilliefors** (LF), de **Shapiro-Wilk** (SW), d'**Anderson-Darling** et de **Jarque-Bera** (JB). Sachez toutefois qu'il y en a d'autres non discutés ici (tests d’Agostino–Pearson, de Cramer–von Mises, de Ryan-Joiner, de Shapiro–Francia, etc.). Pour les formules et une description détaillée de ces tests, vous pouvez consulter Razali et al. [-@razali2011power] ou Yap et Sim [-@yap2011comparisons]. **Quel test choisir?** Plusieurs auteur(e)s ont comparé ces différents tests à partir de plusieurs échantillons, et ce, en faisant varier la forme de la distribution et le nombre d'observations [@razali2011power;@yap2011comparisons]. Selon Razali et al. [-@razali2011power], le meilleur test semble être celui de Shapiro-Wilk, puis ceux d'Anderson-Darling, de Lilliefors et de Kolmogorov-Smirnov. Yap et Sim [-@yap2011comparisons] concluent aussi que le Shapiro-Wilk semble être le plus performant.\n\nQuoi qu'il en soit, ces cinq tests postulent que la variable suit une distribution gaussienne (hypothèse nulle, H~0~). \n\nCela signifie que si la valeur de *p* associée à la valeur de chacun des tests est inférieure ou égale au seuil alpha choisi (habituellement $\\alpha=\\mbox{0,05}$), la distribution est anormale. À l'inverse, si $p>\\mbox{0,05}$, la distribution est normale.\n\n\n::: {#tbl-testnormalites .cell tbl-cap='Différents tests d\\'hypothèse pour la normalité'}\n::: {.cell-output-display}\n|Test |Propriétés et interprétation |Fonction R |\n|:------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------------|\n|Kolmogorov-Smirnov |Plus sa valeur est proche de zéro, plus la distribution est normale. L'avantage de ce test est qu'il peut être utilisé pour vérifier si une variable suit la distribution de n'importe quelle loi (autre que la loi normale). |`ks.test` du *package* `stats` |\n|Lilliefors |Ce test est une adaptation du test de Kolmogorov-Smirnov. Plus sa valeur est proche de zéro, plus la distribution est normale. |`lillie.test` du *package* `nortest` |\n|Shapiro-Wilk |Si la valeur de la statistique de Shapiro-Wilk est proche de 1, alors la distribution est normale; anormale quand elle est inférieure à 1. |`shapiro.test` du *package* `stats` |\n|Anderson-Darling |Ce test est une modification du test de Cramer-von Mises (CVM). Il peut être aussi utilisé pour tester d'autres distributions (uniforme, log-normale, exponentielle, Weibull, distribution de Pareto généralisée, logistique, etc.). |`ad.test` du *package* `stats` |\n|Jarque-Bera |Basé sur un test du type multiplicateur de Lagrange, ce test utilise dans son calcul les valeurs du *Skewness* et du *Kurtosis*. Plus sa valeur s'approche de 0, plus la distribution est normale. Ce test est surtout utilisé pour vérifier si les résidus d'un modèle de régression linéaire sont normalement distribués; nous y reviendrons dans le chapitre sur la régression multiple. Il s'écrit $JB=\\frac{1}{6} \\left({g_1}^2+\\frac{{g_1}^2}{4} \\right)$ avec $g_1$ et $g_2$ qui sont respectivement les valeurs du *skewness* et du *kurtosis* de la variable (voir les équations [-@eq-SkewType1] et [-@eq-KurtType1]. |`JarqueBeraTest` du *package* `DescTools` |\n:::\n:::\n\n\nDans le @tbl-calcultestnormalites sont reportées les valeurs des différents tests pour les cinq types de distribution générés à la @fig-CourbeNormale. Sans surprise, pour l'ensemble des tests, la valeur de *p* est inférieure à 0,05 pour la distribution normale.\n\n\n::: {#tbl-calcultestnormalites .cell tbl-cap='Tests de normalité pour différentes distributions'}\n::: {.cell-output-display}\n| | | Normale| Asymétrie négative| Asymétrie positive| Leptokurtique| Platikurtique|\n|:----|:-----------------------|-------:|------------------:|------------------:|-------------:|-------------:|\n|S |Skewness | -0,019| 1,091| -1,522| 1,018| -0,058|\n|K |Kurtosis | -0,108| 1,091| 3,841| 10,560| -0,949|\n|KS |Kolmogorov-Smirnov (KS) | 0,029| 0,113| 0,107| 0,083| 0,054|\n|LF |Lilliefors (LF) | 0,029| 0,113| 0,107| 0,083| 0,054|\n|SW |Shapiro-Wilk (SW) | 0,998| 0,918| 0,881| 0,900| 0,974|\n|AD |Anderson-Darling (AD) | 0,370| 11,045| 13,573| 7,334| 2,332|\n|JB |Jarque-Bera (JB) | 0,040| 157,701| 570,327| 4 261,705| 14,034|\n|KS.p |KS (valeur p) | 0,791| 0,000| 0,000| 0,002| 0,112|\n|LF.p |LF (valeur p) | 0,384| 0,000| 0,000| 0,000| 0,002|\n|SW.p |SW (valeur p) | 0,702| 0,000| 0,000| 0,000| 0,000|\n|AD.p |AD (valeur p) | 0,424| 0,000| 0,000| 0,000| 0,000|\n|JB.p |JB (valeur p) | 0,980| 0,000| 0,000| 0,000| 0,001|\n:::\n:::\n\n\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Des tests restrictifs...**\n:::\n::: bloc_attention-body\nLa plupart des auteurs s'entendent sur le fait que ces tests sont très restrictifs : plus la taille de votre échantillon est importante, plus les tests risquent de vous signaler que vos distributions sont anormales (à la lecture des valeurs de *p*).\n\nCertains conseillent même de ne pas les utiliser quand $n>200$ et de vous fier uniquement aux graphiques (histogramme et diagramme Q-Q)!\n\n:::\n:::\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Combiner plusieurs méthodes pour vérifier la normalité d'une variable**\n:::\n::: bloc_astuce-body\nBref, vérifier la normalité d'une variable n'est pas une tâche si simple. De nouveau, nous vous conseillons vivement de :\n\n* Construire les graphiques pour analyser visuellement la forme de la distribution (histogramme avec courbe normale et diagramme Q-Q).\n\n* Calculer le *skewness* et le *kurtosis*.\n\n* Calculer plusieurs tests (minimalement Shapiro-Wilk et Kolmogorov-Smirnov).\n\n* Accorder une importance particulière aux graphiques lorsque vous traitez de grands échantillons ($n>200$).\n:::\n:::\n\n\n#### Tests pour d'autres formes de distribution{#sec-02adjdistrib}\n\nComme nous l'avons vu, la distribution normale n'est que l'une des multiples distributions existantes. Dans de nombreuses situations, elle ne sera pas adaptée pour décrire vos variables. La démarche à adopter pour trouver une distribution adaptée est la suivante : \n\n1. Définissez la nature de votre variable : identifier si elle est discrète ou continue et l'intervalle dans lequel elle est définie. Une variable dont les valeurs sont positives ou négatives ne peut pas être décrite avec une distribution Gamma par exemple (à moins de la décaler).\n\n2. Explorez votre variable : affichez son histogramme et son graphique de densité pour avoir une vue générale de sa morphologie.\n\n3. Présélectionnez un ensemble de distributions candidates en tenant compte des observations précédentes. Vous pouvez également vous reporter à la littérature existante sur votre sujet d'étude pour inclure d'autres distributions. Soyez flexible! Une variable strictement positive pourrait tout de même avoir une forme normale. De même, une variable décrivant des comptages suffisamment grands pourrait être mieux décrite par une distribution normale qu'une distribution de Poisson.\n\n4. Tentez d'ajuster chacune des distributions retenues à vos données et comparez les qualités d'ajustements pour retenir la plus adaptée.\n\nPour ajuster une distribution à un jeu de données, il faut trouver les valeurs des paramètres de cette distribution qui lui permettent d'adopter une forme la plus proche possible des données. Nous appelons cette opération **ajuster un modèle**, puisque la distribution théorique est utilisée pour modéliser les données. L'ajustement des paramètres est un problème d'optimisation que plusieurs algorithmes sont capables de résoudre (*gradient descent*, *Newton-Raphson method*, *Fisher scoring*, etc.). Dans R, le *package* `fitdistrplus` permet d'ajuster pratiquement n'importe quelle distribution à des données en offrant plusieurs stratégies d'optimisation grâce à la fonction `fitdist`. Il suffit de disposer d'une fonction représentant la distribution de densité ou de masse de la distribution en question, généralement noté `dnomdeladistribution` (`dnorm`, `dgamma`, `dpoisson`, etc.) dans R. Notez que certains *packages* comme `VGAM` ou `gamlss.dist` ajoutent un grand nombre de fonctions de densité et de masse à celles déjà disponibles de base dans R.\n\nPour comparer l'ajustement de plusieurs distributions théoriques à des données, trois approches doivent être combinées : \n\n* Observer graphiquement l'ajustement de la courbe théorique à l'histogramme des données. Cela permet d'éliminer au premier coup d'œil les distributions qui ne correspondent pas.\n\n* Comparer les *loglikelihood*. Le *loglikelihood* est un score d'ajustement des distributions aux données. Pour faire simple, plus le *loglikelihood* est grand, plus la distribution théorique est proche des données. Référez-vous à l'encadré suivant pour une description plus en profondeur du *loglikelihood*.\n\n* Utiliser le test de Kolmogorov-Smirnov pour déterminer si une distribution particulière est mieux ajustée pour les données.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Qu'est-ce que le _loglikelihood_**? \n:::\n::: bloc_aller_loin-body\nLe *loglikelihood* est une mesure de l'ajustement d'un modèle à des données. Il est utilisé à peu près partout en statistique. Comprendre sa signification est donc un exercice important pour développer une meilleure intuition du fonctionnement général de nombreuses méthodes. Si les concepts de fonction de densité et de fonction de masse vous semblent encore flous, reportez-vous à la [section @sec-024] sur les distributions dans un premier temps.\n\nAdmettons que nous disposons d'une variable continue *v* que nous tentons de modéliser avec une distribution *d* (il peut s'agir de n'importe quelle distribution). *d* a une fonction de densité avec laquelle il est possible de calculer, pour chacune des valeurs de *v*, la probabilité d'être observée selon le modèle *d*.\n\nPrenons un exemple concret dans R. Admettons que nous avons une variable comprenant 10 valeurs (oui, c'est un petit échantillon, mais c'est pour faire un exemple simple).\n\n\n::: {.cell}\n\n```{.r .cell-code}\nv <- c(5,8,7,8,10,4,7,6,9,7)\nmoyenne <- mean(v)\necart_type <- sd(v)\n```\n:::\n\n\nEn calculant la moyenne et l'écart-type de la variable, nous obtenons les paramètres d'une distribution normale que nous pouvons utiliser pour représenter les données observées. En utilisant la fonction `dnorm` (la fonction de densité de la distribution normale), nous pouvons calculer la probabilité d'observer chacune des valeurs de *v* selon cette distribution normale.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nprobas <- dnorm(v, moyenne, ecart_type)\ndf <- data.frame(valeur = v,\n proba = probas)\nprint(df)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n valeur proba\n1 5 0.11203710\n2 8 0.19624888\n3 7 0.22228296\n4 8 0.19624888\n5 10 0.06009897\n6 4 0.04985613\n7 7 0.22228296\n8 6 0.18439864\n9 9 0.12689976\n10 7 0.22228296\n```\n:::\n:::\n\nNous observons ainsi que les valeurs 7 et 8 sont très probables selon le modèle alors que les valeurs 4 et 10 sont très improbables.\n\nLe *likelihood* est simplement le produit de toutes ces probabilités. Il s'agit donc de **la probabilité conjointe** d'avoir observé toutes les valeurs de *v* **sous l'hypothèse** que *d* est la distribution produisant ces valeurs. Si *d* décrit efficacement *v*, alors le *likelihood* est plus grand que si *d* ne décrit pas efficacement *v*. Il s'agit d'une forme de raisonnement par l'absurde : après avoir observé *v*, nous calculons la probabilité d'avoir observé *v* (*likelihood*) si notre modèle *d* était vrai. Si cette probabilité est très basse, alors c'est que notre modèle est mauvais puisqu'on a bien observé *v*.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlikelihood_norm <- prod(probas)\nprint(likelihood_norm)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 3.322759e-09\n```\n:::\n:::\n\nCependant, multiplier un grand nombre de valeurs inférieures à zéro tend à produire des chiffres infiniment petits et donc à complexifier grandement le calcul. Nous préférons donc utiliser le *loglikelihood* : l'idée étant transformer les probabilités obtenues avec la fonction *log* puis d'additionner leurs résultats, puisque $log(xy) = log(x)+log(y)$. \n\n\n::: {.cell}\n\n```{.r .cell-code}\nloglikelihood_norm <- sum(log(probas))\nprint(loglikelihood_norm)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] -19.52247\n```\n:::\n:::\n\nComparons ce *loglikelihood* à celui d'un second modèle dans lequel nous utilisons toujours la distribution normale, mais avec une moyenne différente (faussée en ajoutant +3) : \n\n\n::: {.cell}\n\n```{.r .cell-code}\nprobas2 <- dnorm(v, moyenne+3, ecart_type)\nloglikelihood_norm2 <- sum(log(probas2))\nprint(loglikelihood_norm2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] -33.53631\n```\n:::\n:::\n\nCe second *loglikehood* est plus faible, indiquant clairement que le premier modèle est plus adapté aux données.\n:::\n:::\n\nPassons à la pratique avec deux exemples.\n\n##### Temps de retard des bus de la ville de Toronto\n\nAnalysons les temps de retard pris par les bus de la ville de Toronto lorsqu'un évènement perturbe la circulation. Ce jeu de données est disponible sur le [site des données ouvertes de la Ville de Toronto](https://open.toronto.ca/catalogue/?search=bus%20delay&sort=score%20desc){target=\"_blank\"}. Compte tenu de la grande quantité d'observations, nous avons fait le choix de nous concentrer sur les évènements ayant eu lieu durant le mois de janvier 2019. Puisque la variable étudiée est une durée exprimée en minutes, elle est strictement positive (supérieure à 0), car un bus avec zéro minute de retard est à l'heure! Nous considérons également qu'un bus ayant plus de 150 minutes de retard (2 heures 30) n'est tout simplement pas passé (personne ne risque d'attendre 2 heures 30 pour prendre son bus). Commençons par charger les données et observer leur distribution empirique.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggplot2)\n# charger le jeu de données\ndata_trt_bus <- read.csv('data/univariee/bus-delay-2019_janv.csv', sep =';')\n# retirer les observations aberrantes\ndata_trt_bus <- subset(data_trt_bus, data_trt_bus$Min.Delay > 0 &\n data_trt_bus$Min.Delay < 150)\n# représenter la distribution empirique du jeu de données\nggplot(data = data_trt_bus) + \n geom_histogram(aes(x = Min.Delay, y = ..density..), bins = 40)+\n geom_density(aes(x = Min.Delay), color = \"blue\", bw = 2, size = 0.8)+\n labs(x = \"temps de retard (en minutes)\",\n y = \"\")\n```\n\n::: {.cell-output-display}\n![Distribution empirique des temps de retard des bus à Toronto en janvier 2019](02-univarie_files/figure-html/fig-bustrt-1.png){#fig-bustrt fig-align='center' width=65%}\n:::\n:::\n\n\nCompte tenu de la forme de la distribution empirique et de sa nature, quatre distributions sont envisageables : \n\n* La distribution Gamma, strictement positive et asymétrique, est aussi une généralisation de la distribution exponentielle utilisée pour modéliser des temps d'attente. Pour des raisons similaires, nous pouvons aussi retenir la distribution de Weibull et la distribution log-normale. Nous écartons ici la distribution normale asymétrique puisque le jeu de données n'a clairement pas une forme normale au départ.\n\n* La distribution de Pareto, strictement positive et permettant de représenter ici le fait que la plupart des retards durent moins de 10 minutes, mais que quelques retards sont également beaucoup plus longs.\n\nCommençons par ajuster les quatre distributions avec la fonction `fitdist` du *package* `fitdistrplus` et représentons-les graphiquement pour éliminer les moins bons candidats. Nous utilisons également le *package* `actuar` pour la fonction de densité de Pareto (`dpareto`).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(fitdistrplus)\nlibrary(actuar)\nlibrary(ggpubr)\n# ajustement des modèles\nmodel_gamma <- fitdist(data_trt_bus$Min.Delay, distr = \"gamma\")\nmodel_weibull <- fitdist(data_trt_bus$Min.Delay, distr = \"weibull\")\nmodel_lognorm <- fitdist(data_trt_bus$Min.Delay, distr = \"lnorm\")\nmodel_pareto <- fitdist(data_trt_bus$Min.Delay, distr = \"pareto\", \n start = list(shape = 1, scale = 1),\n method = \"mse\") # différentes méthodes d'optimisation\n# réalisation des graphiques\nplot1 <- ggplot(data = data_trt_bus) + \n geom_histogram(aes(x = Min.Delay, y = ..density..), bins = 40)+\n stat_function(fun = dgamma, color = \"red\", size = 0.8, \n args = as.list(model_gamma$estimate))+\n labs(x = \"temps de retard (en minutes)\",\n y = \"\",\n subtitle = \"Modèle Gamma\")\nplot2 <- ggplot(data = data_trt_bus) + \n geom_histogram(aes(x = Min.Delay, y = ..density..), bins = 40)+\n stat_function(fun = dweibull, color = \"red\", linewidth = 0.8, \n args = as.list(model_weibull$estimate))+\n labs(x = \"temps de retard (en minutes)\",\n y = \"\",\n subtitle = \"Modèle Weibull\")\nplot3 <- ggplot(data = data_trt_bus) + \n geom_histogram(aes(x = Min.Delay, y = ..density..), bins = 40)+\n stat_function(fun = dlnorm, color = \"red\", linewidth = 0.8, \n args = as.list(model_lognorm$estimate))+\n labs(x = \"temps de retard (en minutes)\",\n y = \"\",\n subtitle = \"Modèle log-normal\")\nplot4 <- ggplot(data = data_trt_bus) + \n geom_histogram(aes(x = Min.Delay, y = ..density..), bins = 40)+\n stat_function(fun = dpareto, color = \"red\", linewidth = 0.8, \n args = as.list(model_pareto$estimate))+\n labs(x = \"temps de retard (en minutes)\",\n y = \"\",\n subtitle = \"Modèle Pareto\")\nggarrange(plotlist = list(plot1, plot2, plot3, plot4),\n ncol = 2, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Comparaison des distributions ajustées aux données de retard des bus](02-univarie_files/figure-html/fig-bustrt2-1.png){#fig-bustrt2 fig-align='center' width=65%}\n:::\n:::\n\n\nVisuellement, nous constatons que la distribution de Pareto est un mauvais choix. Pour les trois autres distributions, la comparaison des valeurs de *loglikelihood* s'impose (@tbl-distribs).\n\n\n::: {#tbl-distribs .cell tbl-cap='Comparaison des LogLikelihood des trois distributions'}\n::: {.cell-output-display}\n|Distribution | LogLikelihood|\n|:------------|-------------:|\n|Gamma | -23 062,56|\n|Weibull | -23 195,54|\n|log-normal | -23 375,74|\n:::\n:::\n\nLe plus grand *logLikelihood* est obtenu par la distribution Gamma qui s'ajuste donc le mieux à nos données. Pour finir, nous pouvons tester formellement, avec le test de Kolmogorov-Smirnov, si les données proviennent bien de cette distribution Gamma.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nparams <- as.list(model_gamma$estimate)\nks.test(data_trt_bus$Min.Delay,\n y = pgamma, shape = params$shape, rate = params$rate)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tAsymptotic one-sample Kolmogorov-Smirnov test\n\ndata: data_trt_bus$Min.Delay\nD = 0.099912, p-value < 2.2e-16\nalternative hypothesis: two-sided\n```\n:::\n:::\n\n\nComme la valeur de *p* est inférieure à 0,05, nous ne pouvons pas accepter l'hypothèse que notre jeu de données suit effectivement une loi de Gamma. Considérant le nombre d'observations et le fait que de nombreux temps d'attente sont identiques (ce à quoi le test est très sensible), ce résultat n'est pas surprenant. La distribution Gamma reste cependant la distribution qui représente le mieux nos données. Nous pouvons estimer grâce, à cette distribution, la probabilité qu'un bus ait un retard de plus de 10 minutes de la façon suivante : \n\n\n::: {.cell}\n\n```{.r .cell-code}\npgamma(10, shape = params$shape, rate = params$rate, lower.tail = FALSE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 0.5409424\n```\n:::\n:::\n\n\nce qui correspond à 54 % de chance. \n\nPour moins de 10 minutes : \n\n::: {.cell}\n\n```{.r .cell-code}\npgamma(10, shape = params$shape, rate = params$rate, lower.tail = TRUE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 0.4590576\n```\n:::\n:::\n\n\nsoit 46 %.\n\nUn dernier exemple avec la probabilité qu'un retard dépasse 45 minutes : \n\n\n::: {.cell}\n\n```{.r .cell-code}\npgamma(45, shape = params$shape, rate = params$rate, lower.tail = FALSE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 0.01348194\n```\n:::\n:::\n\nSoit seulement 1,3 %. \n\nPar conséquent, si un matin à Toronto votre bus a plus de 45 minutes de retard, bravo, vous êtes tombé sur une des très rares occasions où un tel retard se produit!\n\n##### Accidents de vélo à Montréal\n\nLe second jeu de données représente le nombre d'accidents de la route impliquant un vélo sur les intersections dans les quartiers centraux de Montréal (@fig-accmtl). Le jeu de données complet est disponible sur le site des [données ouvertes](http://donnees.ville.montreal.qc.ca/dataset/collisions-routieres){target=\"_blank\"} de la Ville de Montréal. Puisque ces données correspondent à des comptages, la première distribution à envisager est la distribution de Poisson. Cependant, puisque nous aurons également un grand nombre d'intersections sans accident, il serait judicieux de tester la distribution de Poisson avec excès de zéro.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggplot2)\n# charger le jeu de données\ndata_accidents <- read.csv('data/univariee/accidents_mtl.csv', sep =',')\ncounts <- data.frame(table(data_accidents$nb_accident))\nnames(counts) <- c(\"nb_accident\",'frequence')\ncounts$nb_accident <- as.numeric(as.character(counts$nb_accident))\ncounts$prop <- counts$frequence / sum(counts$frequence)\n# représenter la distribution empirique du jeu de donnée\nggplot(data = counts) + \n geom_bar(aes(x = nb_accident, weight = frequence), width = 0.5)+\n labs(x = \"nombre d'accidents\",\n y = \"fréquence\")\n```\n\n::: {.cell-output-display}\n![Distribution empirique du nombre d'accidents par intersection impliquant un ou une cycliste à Montréal en 2017 dans les quartiers centraux](02-univarie_files/figure-html/fig-accmtl-1.png){#fig-accmtl fig-align='center' width=65%}\n:::\n:::\n\nNous avons effectivement de nombreux zéros, alors essayons d'ajuster nos deux distributions à ce jeu de données. Dans la @fig-accmtldist, les barres grises représentent la distribution empirique du jeu de données et les barres rouges, les distributions théoriques ajustées. Nous utilisons ici le *package* `gamlss.dist` pour avoir la fonction de masse d'une distribution de Poisson avec excès de zéros.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(gamlss.dist)\n# Ajuster le modèle de poisson\nmodel_poisson <- fitdist(data_accidents$nb_accident, distr = \"pois\")\n# Ajuster le modèle de poisson avec excès de zéros\nmodel_poissonzi <- fitdist(data_accidents$nb_accident, \"ZIP\",\n start = list(mu = 4, sigma = 0.15), # valeurs pour faciliter la convergence\n optim.method = \"L-BFGS-B\", # méthode d'optimisation recommandée dans la documentation\n lower = c(0.00001, 0.00001), # valeurs minimales des deux paramètres\n upper = c(Inf, 1)# valeurs maximales des deux paramètres\n )\ndfpoisson <- data.frame(x=c(0:10),\n y = dpois(0:10, model_poisson$estimate)\n )\nplot1 <- ggplot() + \n geom_bar(aes(x = nb_accident, weight = prop), width = 0.6, data = counts)+\n geom_bar(aes(x = x, weight = y), width = 0.15, data = dfpoisson, fill = \"red\")+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n labs(subtitle = \"Modèle de Poisson\",\n x = \"nombre d'accidents\",\n y = \"\")\ndfpoissonzi <- data.frame(x=c(0:10),\n y = dZIP(0:10, model_poissonzi$estimate[[1]],\n model_poissonzi$estimate[[2]])\n )\nplot2 <- ggplot() + \n geom_bar(aes(x = nb_accident, weight = prop), width = 0.6, data = counts)+\n geom_bar(aes(x = x, weight = y), width = 0.15, data = dfpoissonzi, fill = \"red\")+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n labs(subtitle = \"Modèle de Poisson avec excès de zéro\",\n x = \"nombre d'accident\",\n y = \"\")\nggarrange(plotlist = list(plot1, plot2), ncol = 2)\n```\n\n::: {.cell-output-display}\n![Ajustement des distributions de Poisson et Poisson avec excès de zéros](02-univarie_files/figure-html/fig-accmtldist-1.png){#fig-accmtldist fig-align='center' width=65%}\n:::\n:::\n\n\nVisuellement, comme nous pouvons l'observer à la @fig-accmtldist), le modèle avec excès de zéro semble s'imposer. Nous pouvons vérifier cette impression avec la comparaison des *loglikelihood*.\n\n::: {.cell}\n\n```{.r .cell-code}\nprint(model_poisson$loglik)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] -989.83\n```\n:::\n\n```{.r .cell-code}\nprint(model_poissonzi$loglik)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] -931.8778\n```\n:::\n\n```{.r .cell-code}\n#afficher les paramètres ajustés\nmodel_poisson$estimate\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n lambda \n0.1991963 \n```\n:::\n\n```{.r .cell-code}\nmodel_poissonzi$estimate\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n mu sigma \n0.6690301 0.7022605 \n```\n:::\n:::\n\nNous avons donc la confirmation que le modèle de Poisson avec excès de zéros est mieux ajusté. Nous apprenons donc que 70 % (sigma = 0,70) des intersections sont en fait exclues du phénomène étudié (probablement parce que très peu de cyclistes les utilisent ou parce qu'elles sont très peu accidentogènes) et que pour les autres, le taux d'accidents par année en 2017 était de 0,67 (*mu* = 0,669, *mu* signifiant $\\lambda$ pour le *package* `gamlss`). À nouveau, nous pouvons effectuer un test formel avec le fonction `ks.test`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nparams <- as.list(model_poissonzi$estimate)\nks.test(data_accidents$nb_accident,\n y = pZIP, mu = params$mu, sigma = params$sigma)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tAsymptotic one-sample Kolmogorov-Smirnov test\n\ndata: data_accidents$nb_accident\nD = 0.85476, p-value < 2.2e-16\nalternative hypothesis: two-sided\n```\n:::\n:::\n\n\nEncore une fois, nous devons rejeter l'hypothèse selon laquelle le test suit une distribution de Poisson avec excès de zéros. Ces deux exemples montrent à quel point ce test est restrictif.\n\n### Transformation des variables {#sec-0255}\n\n#### Transformations visant à atteindre la normalité {#sec-02551}\n\nComme énoncé au début de cette section, plusieurs méthodes statistiques nécessitent que la variable quantitative soit normalement distribuée. C'est notamment le cas de l'analyse de variance et des tests *t* (abordés dans les chapitres suivants) qui fournissent des résultats plus robustes lorsque la variable est normalement distribuée. Plusieurs transformations sont possibles, les plus courantes étant la racine carrée, le logarithme et l'inverse de la variable. Selon plusieurs auteur(e)s (notamment, les statisticiennes Barbara G. Tabacknick et Linda S. Fidell [-@tabachnick2007, p.89]), en fonction du type (positive ou négative) et du degré d'asymétrie, les transformations suivantes sont possibles afin d'améliorer la normalité de la variable :\n\n* Asymétrie positive modérée : la racine carrée de la variable *X* avec la fonction `sqrt(df$x)`. \n* Asymétrie positive importante : le logarithme de la variable avec `log10(df$x)`.\n* Asymétrie positive sévère : l'inverse de la variable avec `1/(df$x)`.\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Transformation avec des variables avec des valeurs négatives**\n:::\n::: bloc_astuce-body\nPour une valeur égale ou inférieure à 0, nous ne pouvons pas calculer une racine carrée ou un logarithme. Par conséquent, il convient de décaler simplement la distribution vers la droite afin de s'assurer qu'il n'y ait plus de valeurs négatives ou égales à 0 :\n\n* `sqrt(df$x - min(df$x+1))`pour une asymétrie positive avec des valeurs négatives ou égales à 0.\n* `log(df$x - min(df$x+1))`pour une asymétrie positive avec des valeurs négatives ou égales à 0.\n\nPar exemple, si la valeur minimale de la variable est égale à -10, la valeur minimale de variable décalée sera ainsi de 11.\n\n\n* Asymétrie négative modérée : `sqrt(max(df$x+1) - df$x)`\n* Asymétrie négative importante : `log(max(df$x+1) - df$x)`\n* Asymétrie négative sévère : `1/(max(df$x+1) - df$x)`\n:::\n:::\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Transformation des variables pour atteindre la normalité : ce n'est pas toujours la panacée!**\n:::\n::: bloc_attention-body\nLa transformation des données fait et fera encore longtemps débat à la fois parmi les statisticien(ne)s, et les personnes utilisatrices débutantes ou avancées des méthodes quantitatives. Field et al. [-@field2012discovering, p.193] résument le tout avec humour : « to transform or not transform, that is the question ».\n\n**Avantages de la transformation**\n\n* L'obtention de *résultats plus robustes*.\n\n* Dans une régression linéaire multiple, la transformation de la variable dépendante peut *remédier au non-respect des hypothèses de base liées à la régression* (linéarité et homoscédasticité des erreurs, absence de valeurs aberrantes, etc.).\n\n**Inconvénients de la transformation**\n\n* *Une variable transformée est plus difficile à interpréter* puisque cela change l'unité de mesure de la variable. Prenons un exemple concret : vous souhaitez comparer les moyennes de revenu de deux groupes *A* et *B*. Vous obtenez une différence de 15 000 $, soit une valeur facile à interpréter. Par contre, si la variable a été préalablement transformée en logarithme, il est possible que vous obteniez une différence de 9, ce qui est beaucoup moins parlant. Aussi, en transformant la variable en *log*, vous ne comparez plus les moyennes arithmétiques des deux groupes, mais plutôt leurs moyennes géométriques [@field2012discovering, p.193].\n\n* *Pourquoi perdre la forme initiale de la distribution du phénomène à expliquer?* Il est possible, pour de nombreuses méthodes de choisir la distribution que nous souhaitons utiliser, il n'est donc pas nécessaire de toujours se limiter à la distribution normale. Par exemple, dans les modèles de régression généralisés (GLM), nous pourrions indiquer que la variable indépendante suit une distribution de Student plutôt que de vouloir à tout prix la rendre normale. De même, certains tests non paramétriques permettent d'analyser des variables ne suivant pas une distribution normale.\n\n**Démarche à suivre avant et après la transformation**\n\n* *La transformation est-elle nécessaire?* Ne transformez jamais une variable sans avoir analysé rigoureusement sa forme (histogramme avec courbe normale, *skewness* et *kurtosis*, tests de normalité).\n\n* *D'autres options à la transformation d'une variable dépendante (VD) sont-elles envisageables?* Identifiez la forme de la distribution de la VD et utilisez au besoin un modèle GLM adapté à cette distribution. Autrement dit, ne transformez pas automatiquement votre VD simplement pour l'introduire dans une régression linéaire multiple.\n\n* *La transformation a-t-elle un apport significatif?* Premièrement, vérifiez si la transformation utilisée (logarithme, racine carrée, inverse, etc.) améliore la normalité de la variable. Ce n'est pas toujours le cas, parfois c'est pire! Prenez soin de comparer les histogrammes, les valeurs de *skewness*, de *kurtosis* et des différents tests de normalité avant et après la transformation. Deuxièmement, comparez les résultats de vos analyses statistiques sans et avec transformation, et ce, dans une démarche coût-avantage. Vos résultats sont-ils bien plus robustes? Par exemple, un R^2^ qui passe de 0,597 à 0,602 (avant et après la transformation des variables) avec des associations significatives similaires, mais qui sont plus difficiles à interpréter (du fait des transformations), n'est pas forcément un gain significatif. La modélisation en sciences sociales ne vise pas à prédire la trajectoire d'un satellite ou l'atterrissage d'un engin sur Mars! La précision à la quatrième décimale n'est pas une condition! Par conséquent, un modèle un peu moins robuste, mais plus facile à interpréter est parfois préférable.\n:::\n:::\n\n#### Autres types de transformations {#sec-02552}\n\nLes trois transformations les plus couramment utilisées sont :\n\n* **La côte $z$** (*z score* en anglais) qui consiste à soustraire à chaque valeur sa moyenne (soit un centrage), puis à la diviser par son écart-type (soit une réduction) (@eq-scorez). Par conséquent, nous parlons aussi de variable centrée réduite qui a comme propriétés intéressantes une moyenne égale à 0 et un écart-type égal à 1 (la variance est aussi égale à 1 puisque 1^2^ = 1). Nous verrons que cette transformation est largement utilisée dans les méthodes de classification ([chapitre @sec-chap13]) et les méthodes factorielles ([chapitre @sec-chap12]).\n\n$$\nz= \\frac{x_i-\\mu}{\\sigma}\n$$ {#eq-scorez}\n\n\n* **La transformation en rang** qui consiste simplement à trier une variable en ordre croissant, puis à affecter le rang de chaque observation de 1 à $n$. Cette transformation est très utilisée quand la variable est très anormalement distribuée, notamment pour calculer le coefficient de corrélation de Spearman ([section @sec-0433]) et certains tests non paramétriques (sections [-@sec-0612] et [-@sec-0622]). \n\n* **La transformation sur une échelle de 0 à 1** (ou de 0 à 100) qui consiste à soustraite à chaque observation la valeur minimale et à diviser le tout par l'étendue (@eq-t01). \n\n$$\nX_{\\in\\lbrack0-1\\rbrack}= \\frac{x_i-max}{max-min} \\text{ ou } X_{\\in\\lbrack0-100\\rbrack}= \\frac{x_i-min}{max-min}\\times100\n$$ {#eq-t01}\n\n\n\n::: {#tbl-AutresTransformation .cell tbl-cap='Illustration des trois transformations'}\n::: {.cell-output-display}\n|Observation | $x_i$| Côte $z$| Rang | 0 à 1|\n|:-----------|-----:|--------:|:----:|-----:|\n|1 | 22,00| -1,45| 1 | 0,00|\n|2 | 27,00| -0,65| 3 | 0,28|\n|3 | 25,00| -0,97| 2 | 0,17|\n|4 | 30,00| -0,16| 4 | 0,44|\n|5 | 37,00| 0,97| 7 | 0,83|\n|6 | 32,00| 0,16| 5 | 0,56|\n|7 | 35,00| 0,65| 6 | 0,72|\n|8 | 40,00| 1,45| 8 | 1,00|\n|Moyenne | 31,00| 0,00| | |\n|Écart-type | 6,19| 1,00| | |\n:::\n:::\n\n\nPour un *DataFrame*, nommé *df*, comprenant une variable *X*, la syntaxe ci-dessous illustre comment obtenir quatre transformations (côte $z$, rang, 0 à 1 et 0 à 100).\n\n\n::: {#tbl-AutresTransformation2 .cell}\n\n```{.r .cell-code}\ndf2 <- data.frame(X = c(22,27,25,30,37,32,35,40))\n\n# Transformation centrée réduite : côte Z\ndf2$zX <- (df2$X-mean(df2$X))/sd(df2$X)\n# ou encore avec la fonction scale\ndf2$zX <- scale(df2$X, center = TRUE, scale = TRUE)\n\n# Transformation en rang avec la fonction rank\ndf2$rX <- rank(df2$X)\n\n# Transformation de 0 à 1 ou de 0 à 100\ndf2$X01 <- (df2$X-min(df2$X))/(max(df2$X)-min(df2$X))\ndf2$X0100 <- (df2$X-min(df2$X))/(max(df2$X)-min(df2$X))*100\n```\n:::\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Utilité des transformations**\n:::\n::: bloc_aller_loin-body\nCes trois transformations sont parfois utilisées pour générer un indice composite à partir de plusieurs variables ou encore dans une analyse de sensibilité avec les indices de Sobol [-@Sobol1993].\n:::\n:::\n\n### Mise en œuvre dans R {#sec-0256}\nIl existe une multitude de *packages* dédiés au calcul des statistiques descriptives univariées. Par parcimonie, nous en utiliserons uniquement trois : `DescTools`, `nortest` et `stats`. Libre à vous de faire vos recherches sur Internet pour utiliser d'autres *packages* au besoin. Les principales fonctions que nous utilisons ici sont :\n\n* `summary` : pour obtenir un résumé sommaire des statistiques descriptives (minimum, Q1, Q2, Q3, maximum)\n* `mean` : moyenne\n* `min` : minimum\n* `max` : maximum\n* `range` : minimum et maximum\n* `quantile` : quartiles\n* `quantile((x, probs = seq(.0, 1, by = .2))` : quintiles\n* `quantile((x, probs = seq(.0, 1, by = .1))` : déciles\n* `var` : variance\n* `sd` : écart-type\n* `Skew` du *package* `DescTools` : coefficient d'asymétrie\n* `Kurt` du *package* `DescTools` : coefficient d'aplatissement\n* `ks.test(x, \"pnorm\", mean=mean(x), sd=sd(x))` du *package* `nortest` : test de Kolmogorov-Smirnov\n* `shapiro.test` du *package* `DescTools` : test de Shapiro-Wilk\n* `lillie.test` du *package* `DescTools` : du package `nortest` : test de Lilliefors\n* `ad.test` du *package* `DescTools` : test d'Anderson-Darling\n* `JarqueBeraTest` du *package* `DescTools` : test de Jarque-Bera\n\n\n#### Application à une seule variable {#sec-02561}\n\nAdmettons que vous voulez obtenir des statistiques pour une seule variable présente dans un *DataFrame* (`dataMTL$PctFRev`) :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(DescTools)\nlibrary(stats)\nlibrary(nortest)\n\n# Importation du fichier csv dans un DataFrame\ndataMTL <- read.csv(\"data/univariee/DataSR2016.csv\")\n# Tableau sommaire pour la variable PctFRev\nsummary(dataMTL$PctFRev)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Min. 1st Qu. Median Mean 3rd Qu. Max. \n 1.846 11.242 15.471 16.822 20.229 68.927 \n```\n:::\n\n```{.r .cell-code}\n# PARAMÈTRES DE TENDANCE CENTRALE\nmean(dataMTL$PctFRev) # Moyenne\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 16.82247\n```\n:::\n\n```{.r .cell-code}\nmedian(dataMTL$PctFRev) # Médiane\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 15.471\n```\n:::\n\n```{.r .cell-code}\n# PARAMÈTRES DE POSITION\n# Quartiles\nquantile(dataMTL$PctFRev)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 0% 25% 50% 75% 100% \n 1.8460 11.2420 15.4710 20.2285 68.9270 \n```\n:::\n\n```{.r .cell-code}\n# Quintiles\nquantile(dataMTL$PctFRev, probs = seq(.0, 1, by = .2))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 0% 20% 40% 60% 80% 100% \n 1.846 10.294 13.626 16.918 21.756 68.927 \n```\n:::\n\n```{.r .cell-code}\n# Déciles\nquantile(dataMTL$PctFRev, probs = seq(.0, 1, by = .1))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100% \n 1.846 8.402 10.294 12.172 13.626 15.471 16.918 18.868 21.756 26.854 68.927 \n```\n:::\n\n```{.r .cell-code}\n# Percentiles personnalisés avec apply\nquantile(dataMTL$PctFRev, probs = c(0.01,.05,0.10,.25,.50,.75,.90,.95,.99))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 1% 5% 10% 25% 50% 75% 90% 95% 99% \n 5.2290 7.1470 8.4020 11.2420 15.4710 20.2285 26.8540 31.7530 45.6010 \n```\n:::\n\n```{.r .cell-code}\n# PARAMÈTRES DE DISPERSION\nrange(dataMTL$PctFRev) # Min et Max\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 1.846 68.927\n```\n:::\n\n```{.r .cell-code}\n# Étendue\nmax(dataMTL$PctFRev)-min(dataMTL$PctFRev)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 67.081\n```\n:::\n\n```{.r .cell-code}\n# Écart interquartile\nquantile(dataMTL$PctFRev)[4]-quantile(dataMTL$PctFRev)[2]\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 75% \n8.9865 \n```\n:::\n\n```{.r .cell-code}\nvar(dataMTL$PctFRev) # Variance\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 66.62482\n```\n:::\n\n```{.r .cell-code}\nsd(dataMTL$PctFRev) # Écart-type\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 8.162403\n```\n:::\n\n```{.r .cell-code}\nsd(dataMTL$PctFRev) / mean(dataMTL$PctFRev) # CV\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 0.4852083\n```\n:::\n\n```{.r .cell-code}\n# PARAMÈTRES DE FORME\nSkew(dataMTL$PctFRev) # Skewness\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 1.67367\n```\n:::\n\n```{.r .cell-code}\nKurt(dataMTL$PctFRev) # Kurtosis\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 4.858815\n```\n:::\n\n```{.r .cell-code}\n# TESTS D'HYPOTHÈSE SUR LA NORMALITÉ\n# K-Smirnov\nks.test(dataMTL$PctFRev, \"pnorm\", mean=mean(dataMTL$PctFRev), sd=sd(dataMTL$PctFRev))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tAsymptotic one-sample Kolmogorov-Smirnov test\n\ndata: dataMTL$PctFRev\nD = 0.10487, p-value = 1.646e-09\nalternative hypothesis: two-sided\n```\n:::\n\n```{.r .cell-code}\nshapiro.test(dataMTL$PctFRev) \n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tShapiro-Wilk normality test\n\ndata: dataMTL$PctFRev\nW = 0.88748, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\nlillie.test(dataMTL$PctFRev) \n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tLilliefors (Kolmogorov-Smirnov) normality test\n\ndata: dataMTL$PctFRev\nD = 0.10487, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\nad.test(dataMTL$PctFRev) \n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tAnderson-Darling normality test\n\ndata: dataMTL$PctFRev\nA = 21.072, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\nJarqueBeraTest(dataMTL$PctFRev) \n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tRobust Jarque Bera Test\n\ndata: dataMTL$PctFRev\nX-squared = 2173.1, df = 2, p-value < 2.2e-16\n```\n:::\n:::\n\n\nPour construire un histogramme avec la courbe normale, consultez la [section @sec-03213] ou la syntaxe ci-dessous.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nmoyenne <- mean(dataMTL$PctFRev)\necart_type <- sd(dataMTL$PctFRev)\n\nggplot(data = dataMTL) +\n geom_histogram(aes(x = PctFRev, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = \"personnes à faible revenu (%)\", y = \"densité\")+\n stat_function(fun = dnorm, args = list(mean = moyenne, sd = ecart_type), \n color = \"#e63946\", linewidth = 1.2, linetype = \"dashed\")\n```\n\n::: {.cell-output-display}\n![Histogramme avec courbe normale](02-univarie_files/figure-html/fig-GcourbeNormale-1.png){#fig-GcourbeNormale fig-align='center' width=65%}\n:::\n:::\n\n\n#### Application à plusieurs variables {#sec-02562}\n\nPour obtenir des sorties de statistiques descriptives pour plusieurs variables, nous vous conseillons :\n\n* de créer un vecteur avec les noms des variables (*VarsSelect* dans la syntaxe ci-dessous);\n* d'utiliser ensuite les fonctions `sapply` et `apply.`\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Noms des variables du DataFrame\nnames(dataMTL)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n [1] \"CTNAME\" \"PopTotal\" \"HabKm2\" \n [4] \"PctFRev\" \"TxChomage\" \"PctImmigrant\" \n [7] \"PctImgRecent\" \"PctMenage1pers\" \"PctFamilleMono\" \n[10] \"PctLangueMaternelleFR\" \"PctLangueMaternelleAN\" \"PctLangueMaternelleAU\"\n```\n:::\n\n```{.r .cell-code}\n# Vecteur pour trois variables\nVarsSelect <- c(\"HabKm2\", \"TxChomage\", \"PctFRev\" )\n\n# Tableau sommaire pour les 3 variables\nsummary(dataMTL[VarsSelect])\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev \n Min. : 18 Min. : 1.942 Min. : 1.846 \n 1st Qu.: 1980 1st Qu.: 5.482 1st Qu.:11.242 \n Median : 3773 Median : 7.130 Median :15.471 \n Mean : 5513 Mean : 7.743 Mean :16.822 \n 3rd Qu.: 7916 3rd Qu.: 9.391 3rd Qu.:20.229 \n Max. :50282 Max. :26.882 Max. :68.927 \n```\n:::\n\n```{.r .cell-code}\n# PARAMÈTRES DE TENDANCE CENTRALE\nsapply(dataMTL[VarsSelect], mean) # Moyenne\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev \n5512.830705 7.743329 16.822470 \n```\n:::\n\n```{.r .cell-code}\nsapply(dataMTL[VarsSelect], median) # Médiane\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev \n 3773.000 7.130 15.471 \n```\n:::\n\n```{.r .cell-code}\n# PARAMÈTRES DE POSITION\n# Quartiles\nsapply(dataMTL[VarsSelect], quantile)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev\n0% 18.0 1.9420 1.8460\n25% 1980.5 5.4825 11.2420\n50% 3773.0 7.1300 15.4710\n75% 7915.5 9.3910 20.2285\n100% 50282.0 26.8820 68.9270\n```\n:::\n\n```{.r .cell-code}\n# Quintiles\napply(dataMTL[VarsSelect], 2, function(x) quantile(x, probs = seq(.0, 1, by = .2)))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev\n0% 18 1.942 1.846\n20% 1525 5.116 10.294\n40% 2953 6.422 13.626\n60% 4971 7.973 16.918\n80% 9509 10.000 21.756\n100% 50282 26.882 68.927\n```\n:::\n\n```{.r .cell-code}\n# Déciles\napply(dataMTL[VarsSelect], 2, function(x) quantile(x, probs = seq(.0, 1, by = .1)))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev\n0% 18 1.942 1.846\n10% 455 4.369 8.402\n20% 1525 5.116 10.294\n30% 2298 5.780 12.172\n40% 2953 6.422 13.626\n50% 3773 7.130 15.471\n60% 4971 7.973 16.918\n70% 6918 8.909 18.868\n80% 9509 10.000 21.756\n90% 13055 11.749 26.854\n100% 50282 26.882 68.927\n```\n:::\n\n```{.r .cell-code}\n# Percentiles personnalisés avec apply\napply(dataMTL[VarsSelect], 2, \n function(x) quantile(x, probs = c(0.01,.05,0.10,.25,.50,.75,.90,.95,.99)))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev\n1% 58.5 2.9665 5.2290\n5% 178.0 3.8980 7.1470\n10% 455.0 4.3690 8.4020\n25% 1980.5 5.4825 11.2420\n50% 3773.0 7.1300 15.4710\n75% 7915.5 9.3910 20.2285\n90% 13055.0 11.7490 26.8540\n95% 15355.0 13.8400 31.7530\n99% 18578.5 17.1920 45.6010\n```\n:::\n\n```{.r .cell-code}\n# PARAMÈTRES DE DISPERSION\nsapply(dataMTL[VarsSelect], range) # Min et Max\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev\n[1,] 18 1.942 1.846\n[2,] 50282 26.882 68.927\n```\n:::\n\n```{.r .cell-code}\n# Étendue\nsapply(dataMTL[VarsSelect], max) - sapply(dataMTL[VarsSelect], min)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev \n50264.000 24.940 67.081 \n```\n:::\n\n```{.r .cell-code}\n# Écart interquartile\nsapply(dataMTL[VarsSelect], quantile)[4,] - sapply(dataMTL[VarsSelect], quantile)[2,]\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev \n5935.0000 3.9085 8.9865 \n```\n:::\n\n```{.r .cell-code}\nsapply(dataMTL[VarsSelect], var) # Variance\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev \n2.633462e+07 9.880932e+00 6.662482e+01 \n```\n:::\n\n```{.r .cell-code}\nsapply(dataMTL[VarsSelect], sd) # Écart-type\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev \n5131.726785 3.143395 8.162403 \n```\n:::\n\n```{.r .cell-code}\n# Coefficient de variation\nsapply(dataMTL[VarsSelect], sd) / sapply(dataMTL[VarsSelect], mean)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev \n0.9308696 0.4059488 0.4852083 \n```\n:::\n\n```{.r .cell-code}\n# PARAMÈTRES DE FORME\nsapply(dataMTL[VarsSelect], Skew) # Skewness\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev \n 1.967468 1.280216 1.673670 \n```\n:::\n\n```{.r .cell-code}\nsapply(dataMTL[VarsSelect], Kurt) # Kurtosis\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage PctFRev \n 8.546403 2.892443 4.858815 \n```\n:::\n\n```{.r .cell-code}\n# TESTS D'HYPOTHÈSE POUR LA NORMALITÉ\n# K-Smirnov\napply(dataMTL[VarsSelect], 2, function(x) ks.test(x, \"pnorm\", mean=mean(x), sd=sd(x)))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n$HabKm2\n\n\tAsymptotic one-sample Kolmogorov-Smirnov test\n\ndata: x\nD = 0.14899, p-value < 2.2e-16\nalternative hypothesis: two-sided\n\n\n$TxChomage\n\n\tAsymptotic one-sample Kolmogorov-Smirnov test\n\ndata: x\nD = 0.080183, p-value = 9.778e-06\nalternative hypothesis: two-sided\n\n\n$PctFRev\n\n\tAsymptotic one-sample Kolmogorov-Smirnov test\n\ndata: x\nD = 0.10487, p-value = 1.646e-09\nalternative hypothesis: two-sided\n```\n:::\n\n```{.r .cell-code}\nsapply(dataMTL[VarsSelect], shapiro.test) # Shapiro-Wilk\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage \nstatistic 0.8385086 0.9235146 \np.value 5.648795e-30 1.451222e-21 \nmethod \"Shapiro-Wilk normality test\" \"Shapiro-Wilk normality test\"\ndata.name \"X[[i]]\" \"X[[i]]\" \n PctFRev \nstatistic 0.8874803 \np.value 1.00278e-25 \nmethod \"Shapiro-Wilk normality test\"\ndata.name \"X[[i]]\" \n```\n:::\n\n```{.r .cell-code}\nsapply(dataMTL[VarsSelect], lillie.test) # Lilliefors\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 \nstatistic 0.148988 \np.value 5.689619e-58 \nmethod \"Lilliefors (Kolmogorov-Smirnov) normality test\"\ndata.name \"X[[i]]\" \n TxChomage \nstatistic 0.0801829 \np.value 7.758887e-16 \nmethod \"Lilliefors (Kolmogorov-Smirnov) normality test\"\ndata.name \"X[[i]]\" \n PctFRev \nstatistic 0.1048704 \np.value 7.43257e-28 \nmethod \"Lilliefors (Kolmogorov-Smirnov) normality test\"\ndata.name \"X[[i]]\" \n```\n:::\n\n```{.r .cell-code}\nsapply(dataMTL[VarsSelect], ad.test) # Anderson-Darling\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage \nstatistic 36.40276 14.9237 \np.value 3.7e-24 3.7e-24 \nmethod \"Anderson-Darling normality test\" \"Anderson-Darling normality test\"\ndata.name \"X[[i]]\" \"X[[i]]\" \n PctFRev \nstatistic 21.07194 \np.value 3.7e-24 \nmethod \"Anderson-Darling normality test\"\ndata.name \"X[[i]]\" \n```\n:::\n\n```{.r .cell-code}\nsapply(dataMTL[VarsSelect], JarqueBeraTest) # Jarque-Bera\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 TxChomage \nstatistic 4270.113 639.2741 \nparameter 2 2 \np.value 0 0 \nmethod \"Robust Jarque Bera Test\" \"Robust Jarque Bera Test\"\ndata.name \"X[[i]]\" \"X[[i]]\" \n PctFRev \nstatistic 2173.082 \nparameter 2 \np.value 0 \nmethod \"Robust Jarque Bera Test\"\ndata.name \"X[[i]]\" \n```\n:::\n:::\n\n\n#### Transformation d'une variable dans R {#sec-02563}\n\nLa syntaxe ci-dessous illustre trois exemples de transformation (logarithme, racine carrée et inverse de la variable). Rappelez-vous qu'il faut comparer les valeurs de *skewness* et de *kurtosis* et des tests de Shapiro-Wilk avant et après les transformations pour identifier celle qui est la plus efficace.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggpubr)\n\n# Importation du fichier csv dans un DataFrame\ndataMTL <- read.csv(\"data/univariee/DataSR2016.csv\")\n\n# Noms des variables du DataFrame\nnames(dataMTL)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n [1] \"CTNAME\" \"PopTotal\" \"HabKm2\" \n [4] \"PctFRev\" \"TxChomage\" \"PctImmigrant\" \n [7] \"PctImgRecent\" \"PctMenage1pers\" \"PctFamilleMono\" \n[10] \"PctLangueMaternelleFR\" \"PctLangueMaternelleAN\" \"PctLangueMaternelleAU\"\n```\n:::\n\n```{.r .cell-code}\n# Transformations\ndataMTL$HabKm2_log <- log10(dataMTL$HabKm2)\ndataMTL$HabKm2_sqrt <- sqrt(dataMTL$HabKm2)\ndataMTL$HabKm2_inv <- 1/dataMTL$HabKm2\n\n# Vecteur pour la variable et les trois transformations\nVarsSelect <- c(\"HabKm2\", \"HabKm2_log\", \"HabKm2_sqrt\", \"HabKm2_inv\")\n\n# Paramètres de forme\nsapply(dataMTL[VarsSelect], Skew) # Skewness\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 HabKm2_log HabKm2_sqrt HabKm2_inv \n 1.9674683 -1.2071326 0.4179037 8.2536901 \n```\n:::\n\n```{.r .cell-code}\nsapply(dataMTL[VarsSelect], Kurt) # Kurtosis\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 HabKm2_log HabKm2_sqrt HabKm2_inv \n 8.54640302 1.55670769 0.04563433 82.85604898 \n```\n:::\n\n```{.r .cell-code}\n# TESTS D'HYPOTHÈSE SUR LA NORMALITÉ\nsapply(dataMTL[VarsSelect], shapiro.test) \n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HabKm2 HabKm2_log \nstatistic 0.8385086 0.9113234 \np.value 5.648795e-30 4.11156e-23 \nmethod \"Shapiro-Wilk normality test\" \"Shapiro-Wilk normality test\"\ndata.name \"X[[i]]\" \"X[[i]]\" \n HabKm2_sqrt HabKm2_inv \nstatistic 0.9771699 0.2530266 \np.value 4.638049e-11 8.324983e-52 \nmethod \"Shapiro-Wilk normality test\" \"Shapiro-Wilk normality test\"\ndata.name \"X[[i]]\" \"X[[i]]\" \n```\n:::\n\n```{.r .cell-code}\n# Histogrammes avec courbe normale\nGraph1 <- ggplot(data = dataMTL) +\n geom_histogram(aes(x = HabKm2, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = expression(\"Habitants au km\"^2), \n y = \"densité\")+\n stat_function(fun = dnorm, \n args = list(mean = mean(dataMTL$HabKm2), \n sd = sd(dataMTL$HabKm2)), \n color = \"#e63946\", linewidth = 1.2)\n\nGraph2 <- ggplot(data = dataMTL) +\n geom_histogram(aes(x = HabKm2_log, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = expression(\"Logarithme d'habitants au km\"^2),\n y = \"densité\")+\n stat_function(fun = dnorm, \n args = list(mean = mean(dataMTL$HabKm2_log), \n sd = sd(dataMTL$HabKm2_log)), \n color = \"#e63946\", linewidth = 1.2)\n\nGraph3 <- ggplot(data = dataMTL) +\n geom_histogram(aes(x = HabKm2_sqrt, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = expression(\"Racine carrée d'habitants au km\"^2),\n y = \"densité\")+\n stat_function(fun = dnorm, \n args = list(mean = mean(dataMTL$HabKm2_sqrt), \n sd = sd(dataMTL$HabKm2_sqrt)), \n color = \"#e63946\", linewidth = 1.2)\n\nGraph4 <- ggplot(data = dataMTL) +\n geom_histogram(aes(x = HabKm2_inv, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = expression(\"Inverse d'habitants au km\"^2),\n y = \"densité\")+\n stat_function(fun = dnorm, \n args = list(mean = mean(dataMTL$HabKm2_inv), \n sd = sd(dataMTL$HabKm2_inv)), \n color = \"#e63946\", linewidth = 1.2)\n\nggarrange(plotlist = list(Graph1, Graph2, Graph3, Graph4), ncol = 2, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Histogramme des transformations](02-univarie_files/figure-html/fig-GTranf-1.png){#fig-GTranf fig-align='center' width=75%}\n:::\n:::\n\n\nLa variable *HabKm2* est asymétrique positive et leptokurtique. Les valeurs des statistiques de forme et du test de Shapiro-Wilk ainsi que les histogrammes semblent démontrer que la transformation la plus efficace est la racine carrée. Si la variable originale est asymétrique positive, sa transformation logarithmique est par contre asymétrique négative. Cela démontre que la transformation logarithmique n'est pas toujours la panacée.\n\n## Statistiques descriptives sur des variables qualitatives et semi-qualitatives {#sec-026}\n\n### Fréquences {#sec-0261}\n\nEn guise de rappel, les variables nominales, ordinales et semi-quantitatives comprennent plusieurs modalités pour lesquelles plusieurs types de fréquences sont généralement calculées. Pour illustrer le tout, nous avons extrait du recensement de 2016 de Statistique Canada les effectifs des modalités de la variable sur le principal mode de transport utilisé pour les déplacements domicile-travail, et ce, pour la subdivision de recensement (MRC) de l'île de Montréal (@tbl-Frequences). Les différents types de fréquences sont les suivantes :\n\n* Les fréquences absolues simples (**FAS**) ou fréquences observées représentent le nombre d'observations pour chacune des modalités. Par exemple, sur 857 540 personnes réalisant des trajets domicile-travail (ligne totale), seulement 30 645 optent pour le vélo, alors que 427 530 conduisent un véhicule motorisé (automobile, camion ou fourgonnette) comme principal mode de transport.\n\n* Les fréquences relatives simples (**FRS**) sont les proportions de chaque modalité sur le total ($\\mbox{30 645}/\\mbox{857 540}=\\mbox{0,036}$); leur somme est égale à 1. Elles peuvent bien entendu être exprimées en pourcentage ($\\mbox{30 645}/\\mbox{857 540} \\times \\mbox{100}=\\mbox{3,57}$); leur somme est alors égale à 100 %. Par exemple, 3,7 % de ces personnes utilisent le vélo comme mode de transport principal.\n\n* Les fréquences absolues cumulées (**FAC**) représentent la fréquence observée (FAS) de la modalité à laquelle sont additionnées celles qui la précèdent. La valeur de la FAC pour la dernière est donc égale au total.\n\n* À partir des fréquences absolues cumulées (FAC), il est alors possible de calculer les fréquences relatives cumulées (**FRC**) en proportion ($\\mbox{453 930}/\\mbox{857 540} = \\mbox{0,529}$) et en pourcentage ($\\mbox{453 930} / \\mbox{857 540} \\times \\mbox{100}= \\mbox{52,93}$). Par exemple, plus de la moitié des personnes utilisent l'automobile comme mode de transport principal (passagère ou conductrice).\n\n\n::: {#tbl-Frequences .cell tbl-cap='Différents types de fréquences sur une variable qualitative ou semi-qualitative'}\n::: {.cell-output-display}\n|Mode de transport | FAS| FRS| FRS (%)| FAC| FRC| FRC (%)|\n|:-------------------------------------|-------:|-----:|-------:|-------:|-----:|-------:|\n|Véhicule motorisé (conducteur(trice)) | 427 530| 0,499| 49,86| 427 530| 0,499| 49,86|\n|Véhicule motorisé (passager(ère)) | 26 400| 0,031| 3,08| 453 930| 0,529| 52,93|\n|Transport en commun | 295 860| 0,345| 34,50| 749 790| 0,874| 87,43|\n|À pied | 69 410| 0,081| 8,09| 819 200| 0,955| 95,53|\n|Bicyclette | 30 645| 0,036| 3,57| 849 845| 0,991| 99,10|\n|Autre moyen | 7 695| 0,009| 0,90| 857 540| 1,000| 100,00|\n|Total | 857 540| 1,000| 100,00| | | |\n:::\n:::\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Les fréquences cumulées : peu pertinentes pour les variables nominales**\n:::\n::: bloc_attention-body\nLe calcul et l'analyse des fréquences cumulées (absolues et relatives) sont très souvent inutiles pour les variables nominales.\n\nPar exemple, au @tbl-Frequences, la fréquence cumulée relative (en %) est de 87,43 % pour la troisième ligne. Cela signifie que 87,43 % des navetteur(ve)s se déplacent en véhicule motorisé (personne conductrice ou passagère) ou en transport en commun. Par contre, si la troisième modalité avait été *à pied*, le pourcentage aurait été de 61,02 ($\\mbox{52,93}+\\mbox{8,09}$). Si vous souhaitez calculer les fréquences cumulées sur une variable nominale, assurez-vous que l'ordre des modalités vous convient et de le modifier au besoin. Sinon, abstenez-vous de les calculer!\n\n\n**Les fréquences cumulées : très utiles pour l'analyse des variables ordinales ou semi-quantitatives**\n\nPour des modalités hiérarchisées (variable ordinale ou semi-quantitative), l'analyse des fréquences cumulées (absolues et relatives) est par contre très intéressante. Par exemple, au @tbl-Frequences2, elle permet de constater rapidement que sur l'île de Montréal, plus du quart de la population à moins de 25 ans (27,91 %) et 83,33 %, moins de 65 ans.\n:::\n:::\n\n\n::: {#tbl-Frequences2 .cell tbl-cap='Différents types de fréquences sur une variable semi-qualitative'}\n::: {.cell-output-display}\n|Groupes d'âge | FAS| FRS| FRS (%)| FAC| FRC| FRC (%)|\n|:--------------|---------:|-----:|-------:|---------:|-----:|-------:|\n|0 à 14 ans | 304 470| 0,157| 15,68| 304 470| 0,157| 15,68|\n|15 à 24 ans | 237 555| 0,122| 12,23| 542 025| 0,279| 27,91|\n|25 à 44 ans | 582 150| 0,300| 29,98| 1 124 175| 0,579| 57,89|\n|45 à 64 ans | 494 205| 0,254| 25,45| 1 618 380| 0,833| 83,33|\n|65 à 84 ans | 271 560| 0,140| 13,98| 1 889 940| 0,973| 97,32|\n|85 ans et plus | 52 100| 0,027| 2,68| 1 942 040| 1,000| 100,00|\n|Total | 1 942 040| 1,000| 100,00| | | |\n:::\n:::\n\n\nDifférents graphiques peuvent être construits pour illustrer la répartition des observations : les graphiques en barres (verticales et horizontales) avec les fréquences absolues et les diagrammes circulaires ou en anneau pour les fréquences relatives (@fig-GraphiquesFreq1). Ces graphiques seront présentés plus en détail dans le chapitre suivant.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Différents graphiques pour représenter les fréquences absolues et relatives](02-univarie_files/figure-html/fig-GraphiquesFreq1-1.png){#fig-GraphiquesFreq1 fig-align='center' width=75%}\n:::\n:::\n\n\n### Mise en œuvre dans R {#sec-0262}\n\nLa syntaxe ci-dessous permet de calculer les différentes fréquences présentées au @tbl-Frequences2. Notez que pour les fréquences cumulées, nous utilisons la fonction `cumsum`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Vecteur pour les noms des modalités\nModalite <- c(\"0 à 14 ans\",\n \"15 à 24 ans\",\n \"25 à 44 ans\",\n \"45 à 64 ans\",\n \"65 à 84 ans\",\n \"85 ans et plus\")\n# Vecteur pour les fréquences absolues simples (FAS)\nNavetteurs <- c(304470,237555,582150,494205,271560,52100)\n# Somme des FAS\nsumFAS <- sum(Navetteurs)\n# Construction du DataFrame avec les deux vecteurs\ndf <- data.frame(\n GroupeAge = Modalite, \n FAS = Navetteurs,\n FRS = Navetteurs / sumFAS, \n FRSpct = Navetteurs / sumFAS * 100,\n FAC = cumsum(Navetteurs),\n FRC = cumsum(Navetteurs) / sumFAS,\n FRCpct = cumsum(Navetteurs) / sumFAS * 100\n )\ndf\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n GroupeAge FAS FRS FRSpct FAC FRC FRCpct\n1 0 à 14 ans 304470 0.15677844 15.677844 304470 0.1567784 15.67784\n2 15 à 24 ans 237555 0.12232240 12.232240 542025 0.2791008 27.91008\n3 25 à 44 ans 582150 0.29976211 29.976211 1124175 0.5788629 57.88629\n4 45 à 64 ans 494205 0.25447725 25.447725 1618380 0.8333402 83.33402\n5 65 à 84 ans 271560 0.13983234 13.983234 1889940 0.9731725 97.31725\n6 85 ans et plus 52100 0.02682746 2.682746 1942040 1.0000000 100.00000\n```\n:::\n:::\n\n\n## Statistiques descriptives pondérées : pour aller plus loin {#sec-027}\n\nDans la [section @sec-025], les différentes statistiques descriptives sur des variables quantitatives – paramètres de tendance centrale, de position, de dispersion et de forme – ont été largement abordées. Il est possible de calculer ces différentes statistiques en tenant compte d’une pondération. La statistique descriptive pondérée la plus connue est certainement la moyenne arithmétique pondérée. Son calcul est très simple. Pour chaque observation, deux valeurs sont disponibles : \n\n* $x_i$, soit la valeur de la variable $X$ pour l'observation $i$\n* $w_i$, soit la valeur de la pondération pour $i$.\n\nPrenez soin de comparer les deux équations ci-dessous (à gauche, la moyenne arithmétique; à droite, la moyenne arithmétique pondérée). Vous constaterez rapidement qu'il suffit de multiplier chaque observation par sa pondération (numérateur) et de diviser ce produit par la somme des pondérations (dénominateur; et non par $n$, soit le nombre d’observations comme pour la moyenne arithmétique non pondérée). \n\n$$ \n\\bar{x}=\\frac{\\sum_{i=1}^n x_i}{n} \\text { versus } \\bar{m}=\\frac{\\sum_{i=1}^n w_ix_i}{\\sum_{i=1}^nw_i}\n$$ {#eq-moypond}\n\n\n\n::: {#tbl-MoyPondCalcul .cell tbl-cap='Calcul de la moyenne pondérée'}\n::: {.cell-output-display}\n|Observation | $x_i$| $w_i$| $x_i \\times w_i$|\n|:----------------|-----:|-----:|----------------:|\n|1 | 200| 20| 4 000|\n|2 | 225| 80| 18 000|\n|3 | 275| 50| 13 750|\n|4 | 300| 200| 60 000|\n|Somme | 1 000| 350| 95 750|\n|Moyenne | 250| | |\n|Moyenne pondérée | | | 274|\n:::\n:::\n\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Calcul d’autres statistiques descriptives pondérées**\n:::\n::: bloc_notes-body\nNous ne reportons pas ici les formules des versions pondérées de toutes les statistiques descriptives. Retenez toutefois le principe suivant permettant de les calculer à partir de l’exemple du @tbl-MoyPondCalcul. Pour la variable *X*, dupliquons respectivement 20, 80, 50, 200 fois les observations 1 à 4. Si nous calculons la moyenne arithmétique sur ces valeurs dupliquées, alors cette valeur est identique à celle de la moyenne arithmétique pondérée. Le même principe reposant sur la duplication des valeurs s'applique à l'ensemble des statistiques descriptives.\n:::\n:::\n\nDans un article récent, Alvarenga et al. [-@de2018accessibilite] évaluent l'accessibilité aux aires de jeux dans les parcs de la Communauté métropolitaine de Montréal (CMM). Pour les 881 secteurs de recensement de la CMM, ils ont calculé la distance à pied à l'aire de jeux la plus proche à travers le réseau de rues. Ce résultat, cartographié à la @fig-ParcCMM), permet d'avancer le constat suivant : « la quasi-totalité des secteurs de recensement de l’agglomération de Montréal présente des distances de l’aire de jeux la plus proche inférieures à 500 m, alors que les secteurs situés à plus d’un kilomètre d’une aire de jeux sont très majoritairement localisés dans les couronnes\nnord et sud de la CMM » [@de2018accessibilite, p.238].\n\nPour chaque secteur de recensement, Alvarenga et al. [-@de2018accessibilite] disposent des données suivantes :\n\n* $x_i$, soit la distance à l'aire de jeux la plus proche pour le secteur de recensement *i*;\n* $w_i$, la pondération, soit le nombre d'enfants de moins de dix ans.\n\nIl est alors possible de calculer les statistiques descriptives de la proximité à l'aire de jeux la plus proche en tenant compte du nombre d'enfants résidant dans chaque secteur de recensement (@tbl-MoyPondParc). Cet exercice permet de conclure que : « [...] globalement, les enfants ont une bonne accessibilité aux aires de jeux sur le territoire de la CMM. [...] Les enfants sont en moyenne à un peu plus de 500 m de l’aire de jeux la plus proche (moyenne = 559; médiane = 512). Toutefois, les valeurs percentiles extrêmes signalent que respectivement 10 % et 5 % des enfants résident à près de 800 m et à plus de 1000 m de l’aire de jeux la plus proche » [-@de2018accessibilite, p.236].\n\n\n![Accessibilité aux aires de jeux par secteur de recensement, Communauté métropolitaine de Montréal, 2016](images/Chap02/BivarieeFigureParc.jpg){#fig-ParcCMM width=\"85%\" fig-align=\"center\"}\n\n\n::: {#tbl-MoyPondParc .cell tbl-cap='Statistiques de l\\'aire de jeux la plus proche, par secteur de recensement, pondérées par la population de moins de 10 ans'}\n::: {.cell-output-display}\n| | N | Moyenne | P5 | P10 | Q1 | Médiane | Q3 | P90 | P95 |\n|:----|:---:|:-------:|:---:|:---:|:---:|:-------:|:---:|:---:|:-----:|\n|Parc | 881 | 559 | 282 | 327 | 408 | 512 | 640 | 799 | 1 006 |\n:::\n:::\n\n\nDe nombreux *packages* sont disponibles pour calculer des statistiques pondérées, dont notamment `Weighted.Desc.Stat` et `Hmisc` utilisés dans la syntaxe ci-dessous.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(foreign)\nlibrary(Hmisc)\nlibrary(Weighted.Desc.Stat)\n\ndf <- read.dbf(\"data/bivariee/SR_AireJeux_PopMoins10.dbf\")\n\nhead(df, n = 5)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n SRNOM PopMoins10 AireJeux\n1 0659.06 380 600.1921\n2 0410.02 390 324.4396\n3 0863.01 325 524.3323\n4 0734.05 875 574.6682\n5 0073.00 100 352.9505\n```\n:::\n\n```{.r .cell-code}\n# xi (variable) et wi (pondération)\nx <- df$AireJeux\nw <- df$PopMoins10\n\n# Calcul des paramètres de position\n# Moyenne\nHmisc::wtd.mean(x, w)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 559.8026\n```\n:::\n\n```{.r .cell-code}\nWeighted.Desc.Stat::w.mean(x, w)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 559.8026\n```\n:::\n\n```{.r .cell-code}\n# Quartiles et percentile\nHmisc::wtd.quantile(x, weights=w, probs=c(.05, .10, .25, .50, .75, .90, .95))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 5% 10% 25% 50% 75% 90% 95% \n 281.3623 327.3056 406.0759 511.5880 639.4813 798.6559 1011.5493 \n```\n:::\n\n```{.r .cell-code}\n# Paramètres de dispersion avec le package Weighted.Desc.Stat\n# Variance, écart-type et coefficient de variation\nw.var(x, w)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 82818.18\n```\n:::\n\n```{.r .cell-code}\nw.sd(x, w)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 287.7815\n```\n:::\n\n```{.r .cell-code}\nw.cv(x, w)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 0.5140767\n```\n:::\n\n```{.r .cell-code}\n# Paramètres de forme avec le package Weighted.Desc.Stat\n# Skewness et kurtosis \nw.skewness(x, w)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 4.735351\n```\n:::\n\n```{.r .cell-code}\nw.kurtosis(x, w)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 41.17146\n```\n:::\n:::\n\n\n\n## Quiz de révision du chapitre {#sec-028}\n\n\n
\n\n\n\n
\n
Le mode de transport (auto, vélo, marche, transport en commun) est :
\n
Relisez au besoin la [section @sec-0212].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Laquelle de ces deux options est la bonne?
\n
Relisez au besoin le début de la [section @sec-012].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Des données collectées sur le terrain avec un GPS sont des données primaires spatiales.
\n
Relisez au besoin la [section @sec-022].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
L'erreur écologique consiste à :
\n
Relisez au besoin la [section @sec-0224].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Laquelle de ces deux options est la bonne?
\n
Relisez au besoin la [section @sec-024].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quels sont les trois paramètres de tendance centrale?
\n
Relisez au besoin la [section @sec-0251].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quels sont les paramètres de position?
\n
Relisez au besoin la [section @sec-0252].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quels sont les paramètres de dispersion?
\n
Relisez au besoin la [section @sec-0253].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Comment vérifie-t-on qu'une variable est normalement distribuée?
\n
Relisez au besoin la [section @sec-0254].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Le centrage et la réduction d'une variable consistent à :
\n
Relisez au besoin la [section @sec-02552].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n\n
\n\n
\n
\n", + "supporting": [ + "02-univarie_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/.quarto/_freeze/02-univarie/figure-html/fig-CourbeNormale-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-CourbeNormale-1.png new file mode 100644 index 0000000..623bcf6 Binary files /dev/null and b/.quarto/_freeze/02-univarie/figure-html/fig-CourbeNormale-1.png differ diff --git a/docs/02-univarie_files/figure-html/fig-GTranf-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-GTranf-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-GTranf-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-GTranf-1.png diff --git a/docs/02-univarie_files/figure-html/fig-GcourbeNormale-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-GcourbeNormale-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-GcourbeNormale-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-GcourbeNormale-1.png diff --git a/docs/02-univarie_files/figure-html/fig-GraphiquesFreq1-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-GraphiquesFreq1-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-GraphiquesFreq1-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-GraphiquesFreq1-1.png diff --git a/docs/02-univarie_files/figure-html/fig-accmtl-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-accmtl-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-accmtl-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-accmtl-1.png diff --git a/docs/02-univarie_files/figure-html/fig-accmtldist-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-accmtldist-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-accmtldist-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-accmtldist-1.png diff --git a/.quarto/_freeze/02-univarie/figure-html/fig-asymetrie-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-asymetrie-1.png new file mode 100644 index 0000000..bd0988f Binary files /dev/null and b/.quarto/_freeze/02-univarie/figure-html/fig-asymetrie-1.png differ diff --git a/docs/02-univarie_files/figure-html/fig-bustrt-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-bustrt-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-bustrt-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-bustrt-1.png diff --git a/docs/02-univarie_files/figure-html/fig-bustrt2-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-bustrt2-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-bustrt2-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-bustrt2-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig251-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig251-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig251-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig251-1.png diff --git a/.quarto/_freeze/02-univarie/figure-html/fig-fig252-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig252-1.png new file mode 100644 index 0000000..8e7c9a2 Binary files /dev/null and b/.quarto/_freeze/02-univarie/figure-html/fig-fig252-1.png differ diff --git a/.quarto/_freeze/02-univarie/figure-html/fig-fig253-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig253-1.png new file mode 100644 index 0000000..ac0a35c Binary files /dev/null and b/.quarto/_freeze/02-univarie/figure-html/fig-fig253-1.png differ diff --git a/docs/02-univarie_files/figure-html/fig-fig254-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig254-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig254-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig254-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig256-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig256-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig256-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig256-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig257-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig257-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig257-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig257-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig258-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig258-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig258-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig258-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig259-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig259-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig259-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig259-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig259b-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig259b-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig259b-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig259b-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig260-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig260-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig260-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig260-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig261-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig261-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig261-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig261-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig262-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig262-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig262-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig262-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig263-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig263-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig263-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig263-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig264-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig264-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig264-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig264-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig265-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig265-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig265-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig265-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig266-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig266-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig266-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig266-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig267-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig267-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig267-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig267-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig268-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig268-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig268-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig268-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig269-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig269-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig269-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig269-1.png diff --git a/docs/02-univarie_files/figure-html/fig-fig270-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-fig270-1.png similarity index 100% rename from docs/02-univarie_files/figure-html/fig-fig270-1.png rename to .quarto/_freeze/02-univarie/figure-html/fig-fig270-1.png diff --git a/.quarto/_freeze/02-univarie/figure-html/fig-kurtosis-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-kurtosis-1.png new file mode 100644 index 0000000..1e53c30 Binary files /dev/null and b/.quarto/_freeze/02-univarie/figure-html/fig-kurtosis-1.png differ diff --git a/.quarto/_freeze/02-univarie/figure-html/fig-qqplot-1.png b/.quarto/_freeze/02-univarie/figure-html/fig-qqplot-1.png new file mode 100644 index 0000000..abdcb6b Binary files /dev/null and b/.quarto/_freeze/02-univarie/figure-html/fig-qqplot-1.png differ diff --git a/.quarto/_freeze/03-magiedesgraphiques/execute-results/html.json b/.quarto/_freeze/03-magiedesgraphiques/execute-results/html.json new file mode 100644 index 0000000..32baa5b --- /dev/null +++ b/.quarto/_freeze/03-magiedesgraphiques/execute-results/html.json @@ -0,0 +1,20 @@ +{ + "hash": "a01efd9a0d5a071a4916a4cef9a0e2ff", + "result": { + "markdown": "# Magie des graphiques {#sec-chap03}\n\nDans ce chapitre, nous découvrons les incroyables capacités graphiques de R. Pour ce faire, nous couvrons en profondeur les fonctionnalités du *package* `ggplot2` du `tidyverse`. Selon nous, il s'agit de loin du meilleur *package* pour réaliser des graphiques.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques.\n - `ggthemes` pour utiliser des thèmes complémentaires pour les graphiques. \n* Pour les couleurs : \n - `RColorBrewer` pour accéder à des palettes de couleurs.\n* Pour les graphiques spéciaux : \n - `chorddiag` pour construire des graphiques d'accord.\n - `fmsb` pour construire des graphiques en radar.\n - `treemap` pour construire une carte proportionnelle.\n - `wordcloud2` et `textrank` pour construire un nuage de mots.\n* Pour les cartes : \n - `classInt` pour calculer les intervalles des classes.\n - `ggspatial` pour afficher une échelle avec `ggplot2`.\n - `tmap` pour la cartographie.\n* Autres *packages* : \n - `dplyr` et `reshape2` pour manipuler des données.\n - `pdftools` pour extraire les textes des fichiers *pdf*.\n - `udpipe` pour obtenir des dictionnaires linguistiques.\n - `sf` pour manipuler des *simple feature collections*.\n:::\n:::\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Qu'est-ce que la visualisation de données?**\n:::\n::: bloc_notes-body\nLa représentation visuelle de données consiste à transposer des informations en une représentation graphique facilitant la lecture de ces dernières. Il s'agit autant d'un ensemble de méthodes, d'un art que d'un moyen de communication. Voici deux exemples marquants avant de détailler ce propos.\n\nLa première illustration permet de visualiser le volume de plastique que représente la consommation d'eau en bouteille : 480 milliards de bouteilles vendues en 10 ans! Ce chiffre astronomique est inimaginable. En revanche, une [montagne de plastique](https://graphics.reuters.com/ENVIRONMENT-PLASTIC/0100B275155/index.html){target='_blank'} de 2400 mètres surplombant Manhattan marque davantage les esprits.\n\nLe [second graphique](https://www.maplecroft.com/insights/analysis/84-of-worlds-fastest-growing-cities-face-extreme-climate-change-risks/){target='_blank'} représente quatre informations pour 234 villes à travers le monde : \n\n* la croissance démographique (axe des abscisses),\n\n* la vulnérabilité au changement climatique (axe des ordonnées),\n\n* la taille des villes (taille des cercles),\n\n* le continent sur lequel est localisée chaque ville (couleur des cercles).\n\nLe graphique est à la fois très accrocheur et esthétique. En un coup d'œil, nous constatons que les villes avec une forte croissance démographique sont aussi les plus vénérables (lecture des deux axes) et qu'elles sont surtout localisées en Afrique et secondairement en Asie (en rouge et orange), quelle que soit leur taille (taille du cercle). À l'inverse, les villes européennes et américaines (en bleu) sont beaucoup moins vulnérables aux changements climatiques et une croissance démographique plus faible, qu'elles soient de petites, de moyennes ou de grandes villes.\n\nSouvent négligée, la visualisation de données est perçue comme une tâche triviale : il s'agit simplement de représenter une donnée sous forme d'un graphique, car c'est l'option la plus pratique ou qui prend le moins d'espace. Pourtant, les avantages de la visualisation des données sont nombreux. Par exemple, la visualisation de données intègre aujourd'hui des supports dynamiques comme des animations, des figures interactives ou des applications web. R offre d'ailleurs des possibilités très intéressantes en la matière avec des *packages* comme `shiny`, `plotly` ou `leaflet`. Toutefois, nous ne couvrons pas ici ces méthodes plus récentes en visualisation des données qui devraient faire l'objet d'un autre livre.\n\n**Les principaux avantages de la visualisation des données** : \n\n* **Analyse exploratoire des données** (*exploratory data analysis - EDA* en anglais). Visualiser des données est crucial pour détecter des problèmes en tout genre (données manquantes, valeurs extrêmes ou aberrantes, non-respect de conditions d'application de tests statistiques, etc.), mais aussi pour repérer de nouvelles associations entre les variables.\n\n* **Communication de vos résultats**. La raison d'être d'un graphique est de livrer un message clair relatif à un résultat obtenu suite à une analyse rigoureuse de vos données. Si votre graphique n'apporte aucune information claire, il vaut mieux ne pas le présenter, ni le diffuser. Les représentations ne sont pas neutres. Les couleurs et les formes ont des significations particulières en fonction de la culture et du contexte. Posez-vous donc toujours la question : à quel public est destiné le message? Évitez de surcharger vos visualisations de données, sinon l'essence du message sera perdue.\n\n* **Aide à la décision**. Une illustration (graphique ou carte) peut être un outil facilitant la prise de décisions. \n:::\n:::\n\n## Philosophie du ggplot2 {#sec-031}\n\nLe *package* `ggplot2` fait partie du `tidyverse` et dispose d'une logique de fonctionnement particulière. Cette dernière se nomme *The Grammar of Graphics* (les deux G sont d'ailleurs à l'origine du nom `ggplot2`), proposée par Hadley Wickham (le créateur du `tidyverse`!) dans un article intitulé *A layered grammar of graphics* [@wickham2010layered]. Nous proposons de synthétiser ici les concepts et principes centraux qui sous-tendent la production de graphiques avec `ggplot2`.\n\n### Grammaire {#sec-0311}\n\nHadley Wickham propose une grammaire pour unifier la création de graphiques. L'idée est donc de dépasser les simples dénominations comme un nuage de points, un diagramme en boîte, un graphique en ligne, etc., pour comprendre ce qui relie tous ces graphiques. Ces éléments communs et centraux sont les géométries, les échelles et systèmes de coordonnées, et les annotations (@fig-fig30) : \n\n![Trois composantes d'un graphique, adapté de @wickham2010layered](images/Chap03/composantes.png){#fig-fig30 width=\"70%\" fig-align=\"center\"}\n\n* Les **géométries** sont les formes utilisées pour représenter les données. Il peut s'agir de points, de lignes, de cercles, de rectangles, d'arcs de cercle, etc. \n\n* Les **échelles et systèmes de coordonnées** permettent de contrôler la localisation des éléments dans un graphique en convertissant les données depuis leur échelle originale (dollars, kilomètres, pourcentages, etc.) vers l'échelle du graphique (pixels).\n\n* Les **annotations** recoupent l'ensemble des informations complémentaires ajoutées au graphique comme son titre et sous-titre, la source des données, la mention sur les droits d'auteurs, etc.\n\nEn plus de ces trois éléments, il est bien sûr nécessaire de disposer de **données**. Ces dernières sont assignées à des dimensions du graphique pour être représentées (notamment les axes *X* et *Y* et la couleur). Cette étape est appelée **aesthetics mapping** dans `ggplot2`.\n\nLorsque nous combinons des données, leur assignation a des dimensions, un type de géométries, des échelles et un système de coordonnées, nous obtenons un **calque** (*layer* en anglais). Un graphique peut comprendre plusieurs calques comme nous le verrons dans les prochaines sections.\n\nPrenons un premier exemple très simple et construisons un nuage de points à partir du jeu de données *iris* fourni de base dans R. Nous représentons la relation qui existe entre la longueur et la largeur des sépales de ces fleurs. Pour commencer, nous devons charger le *package* `ggplot2` et instancier un graphique avec la fonction `ggplot`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggplot2)\ndata(iris)\nnames(iris)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"Sepal.Length\" \"Sepal.Width\" \"Petal.Length\" \"Petal.Width\" \"Species\" \n```\n:::\n\n```{.r .cell-code}\nggplot()\n```\n\n::: {.cell-output-display}\n![Base d'un graphique](03-magiedesgraphiques_files/figure-html/fig-fig31-1.png){#fig-fig31 fig-align='center' width=65%}\n:::\n:::\n\n\nPour le moment, le graphique est vide (@fig-fig31). La seconde étape consiste à lui ajouter des données (au travers du paramètre `data`) et à définir les dimensions à associer aux données (avec le paramètre `mapping` et la fonction `aes()`). Dans notre cas, nous voulons utiliser les coordonnées *X* pour représenter la largeur des sépales, et les coordonnées *Y* pour représenter la longueur des sépales. Enfin, nous souhaitons représenter les observations par des points, nous utiliserons donc la géométrie `geom_point`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n geom_point()\n```\n\n::: {.cell-output-display}\n![Ajout des dimensions au graphique](03-magiedesgraphiques_files/figure-html/fig-fig32-1.png){#fig-fig32 fig-align='center' width=65%}\n:::\n:::\n\n\nCe graphique ne comprend qu'un seul calque avec une géométrie de type point (@fig-fig32). Chaque calque est ajouté avec l'opérateur `+` qui permet de superposer des calques, le dernier apparaissant au-dessus des autres. Les arguments `mapping` et `data` sont définis ici dans la fonction `ggplot` et sont donc appliqués à tous les calques qui composent le graphique. Il est aussi possible de définir `mapping` et `data` au sein des fonctions des géométries : \n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris)\n```\n\n::: {.cell-output-display}\n![Autre spécification des arguments mapping et data](03-magiedesgraphiques_files/figure-html/fig-fig33-1.png){#fig-fig33 fig-align='center' width=65%}\n:::\n:::\n\n\nLa troisième étape consiste à ajouter au graphique des annotations. Pour notre cas, il faudrait ajouter un titre, un sous-titre et des intitulés plus clairs pour les axes *X* et *Y*, ce qu'il est possible de faire avec la fonction `labs` (@fig-fig34).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\")\n```\n\n::: {.cell-output-display}\n![Ajout de titres](03-magiedesgraphiques_files/figure-html/fig-fig34-1.png){#fig-fig34 fig-align='center' width=65%}\n:::\n:::\n\n\n### Types de géométries {#sec-0312}\n\nLe *package* `ggplot2` permet d'utiliser un très grand nombre de géométries différentes. Dans le @tbl-geometries, nous avons reporté les principales géométries disponibles afin que vous puissiez vous faire une idée du « bestiaire » existant. Il ne s'agit que d'un extrait des principales fonctions. Sachez qu'il existe aussi des *packages* proposant des géométries supplémentaires pour compléter `ggplot2`.\n\n\n::: {#tbl-geometries .cell tbl-cap='Principales géométries proposées par `ggplot2`'}\n::: {.cell-output-display}\n|Géométrie |Fonction |\n|:------------------|:----------------|\n|Point |`geom_point` |\n|Ligne |`geom_line` |\n|Chemin |`geom_path` |\n|Boîte à moustaches |`geom_boxplot` |\n|Diagramme violon |`geom_violin` |\n|Histogramme |`geom_histogram` |\n|Barre |`geom_bar` |\n|Densité |`geom_density` |\n|Texte |`geom_label` |\n|Barre d'erreur |`geom_errorbar` |\n|Surface |`geom_ribbon` |\n:::\n:::\n\n\n\n### Habillage {#sec-0313}\n\nDans le premier exemple, nous avons montré comment ajouter le titre, le sous-titre et les titres des axes sur un graphique. Il est aussi possible d'ajouter du texte sous le graphique (généralement la source des données avec l'argument `caption`) et des annotations textuelles (`annotate`). Pour ces dernières, il convient de spécifier leur localisation (coordonnées `x` et `y`) et le texte à intégrer (`label`); elles sont ensuite ajoutées au graphique avec l'opérateur `+`. Ajoutons deux annotations pour identifier deux fleurs spécifiques.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") +\n annotate(\"text\", x = 6.7, y = 2.5, # position de la note\n label = \"une virginica\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\") + \n annotate(\"text\", x = 5.7, y = 4.4, # position de la note\n label = \"une setosa\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\") \n```\n\n::: {.cell-output-display}\n![Ajout d'annotations textuelles](03-magiedesgraphiques_files/figure-html/fig-fig35-1.png){#fig-fig35 fig-align='center' width=65%}\n:::\n:::\n\n\nComme vous pouvez le constater, de nombreux paramètres permettent de contrôler le style des annotations. Pour avoir la liste des arguments disponibles, n'hésitez pas à afficher l'aide de la fonction : `help(annotate)`.\n\nEn plus des annotations de type texte, il est possible d'ajouter des annotations de type géométrique. Nous pourrions ainsi délimiter une boîte encadrant les fleurs de l'espère setosa.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nsetosas <- subset(iris, iris$Species == \"setosa\")\nsepal.length_extent <- c(min(setosas$Sepal.Length), max(setosas$Sepal.Length))\nsepal.width_extent <- c(min(setosas$Sepal.Width), max(setosas$Sepal.Width))\n\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") +\n annotate(\"text\", x = 6.7, y = 2.5, # position de la note\n label = \"une virginica\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\") + \n annotate(\"text\", x = 5.7, y = 4.4, # position de la note\n label = \"une setosa\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\") +\n annotate(\"rect\", \n ymin = sepal.width_extent[[1]],\n ymax = sepal.width_extent[[2]],\n xmin = sepal.length_extent[[1]],\n xmax = sepal.length_extent[[2]],\n fill = rgb(0.7,0.7,0.7,.5), # remplissage transparent à 50%\n color = \"black\") # contour de couleur verte\n```\n\n::: {.cell-output-display}\n![Ajout d'annotations géométriques](03-magiedesgraphiques_files/figure-html/fig-fig36-1.png){#fig-fig36 fig-align='center' width=65%}\n:::\n:::\n\n\nComme le dernier calque ajouté au graphique est le rectangle, vous noterez qu'il recouvre tous les calques existant, y compris les précédentes annotations. Pour corriger cela, il suffit de changer l'ordre des calques.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot() +\n annotate(\"rect\", \n ymin = sepal.width_extent[[1]],\n ymax = sepal.width_extent[[2]],\n xmin = sepal.length_extent[[1]],\n xmax = sepal.length_extent[[2]],\n fill = rgb(0.7,0.7,0.7,.5), # remplissage transparent à 50%\n color = \"green\") + # contour de couleur verte\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") +\n\n annotate(\"text\", x = 6.7, y = 2.5, # position de la note\n label = \"une virginica\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\") + \n annotate(\"text\", x = 5.7, y = 4.4, # position de la note\n label = \"une setosa\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\")\n```\n\n::: {.cell-output-display}\n![Gestion de l'ordre des annotations](03-magiedesgraphiques_files/figure-html/fig-fig37-1.png){#fig-fig37 fig-align='center' width=65%}\n:::\n:::\n\n\n### Utilisation des thèmes\n\nDe nombreux autres éléments peuvent être modifiés dans un graphique comme les paramètres des polices, l'arrière-plan, la grille de repères, etc. Il peut être fastidieux de paramétrer tous ces éléments. Une option intéressante est d'utiliser des thèmes déjà préconstruits. Le *package* `ggplot2` propose une dizaine de thèmes : constatons leur impact sur le graphique précédent.\n\n* Le thème classique (`theme_classic`) (@fig-fig38)\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_classic()\n```\n\n::: {.cell-output-display}\n![Thème classique](03-magiedesgraphiques_files/figure-html/fig-fig38-1.png){#fig-fig38 fig-align='center' width=65%}\n:::\n:::\n\n\n* Le thème gris (`theme_gray`) (@fig-fig39)\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_gray()\n```\n\n::: {.cell-output-display}\n![Thème gris](03-magiedesgraphiques_files/figure-html/fig-fig39-1.png){#fig-fig39 fig-align='center' width=65%}\n:::\n:::\n\n\n* Le thème noir et blanc (`theme_bw`) (@fig-fig310)\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_bw()\n```\n\n::: {.cell-output-display}\n![Thème noir et blanc](03-magiedesgraphiques_files/figure-html/fig-fig310-1.png){#fig-fig310 fig-align='center' width=65%}\n:::\n:::\n\n\n* Le thème minimal (`theme_minimal`) (@fig-fig311)\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_minimal()\n```\n\n::: {.cell-output-display}\n![Thème minimal](03-magiedesgraphiques_files/figure-html/fig-fig311-1.png){#fig-fig311 fig-align='center' width=65%}\n:::\n:::\n\n\nIl est aussi possible d'utiliser le *package* `ggthemes` qui apporte des thèmes complémentaires intéressants dont : \n\n* Le thème *tufte* (`theme_tufte`, à l'ancienne...) (@fig-fig312)\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggthemes)\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_tufte()\n```\n\n::: {.cell-output-display}\n![Thème tufte](03-magiedesgraphiques_files/figure-html/fig-fig312-1.png){#fig-fig312 fig-align='center' width=65%}\n:::\n:::\n\n\n* Le thème *economist* (`theme_economist`, inspiré de la revue du même nom) (@fig-fig313)\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_economist()\n```\n\n::: {.cell-output-display}\n![Thème economist](03-magiedesgraphiques_files/figure-html/fig-fig313-1.png){#fig-fig313 fig-align='center' width=65%}\n:::\n:::\n\n\n* Le thème *solarized* (`theme_solarized`, plus original) (@fig-fig314)\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_solarized()\n```\n\n::: {.cell-output-display}\n![Thème solarized](03-magiedesgraphiques_files/figure-html/fig-fig314-1.png){#fig-fig314 fig-align='center' width=65%}\n:::\n:::\n\n\nIl en existe bien d'autres et vous pouvez composer vos propres thèmes. N'hésitez pas à explorer la documentation de `ggplot2` et de `ggthemes` pour en apprendre plus!\n\n### Composition d'une figure avec plusieurs graphiques {#sec-0314}\n\nIl est très fréquent de vouloir combiner plusieurs graphiques dans une même figure. Deux cas se distinguent : \n\n1. Les données pour les différents graphiques proviennent du même *DataFrame* et peuvent être distinguées selon une variable catégorielle. L'objectif est alors de dupliquer le même graphique, mais pour des sous-groupes de données. Dans ce cas, nous recommandons d'utiliser la fonction `facet_wrap` de `ggplot2`.\n\n2. Les graphiques sont complètement indépendants. Dans ce cas, nous recommandons d'utiliser la fonction `ggarrange` du *package* `ggpubr`.\n\n#### `ggplot2` et ses facettes {#sec-03141}\n\nNous pourrions souhaiter réaliser une figure composite avec le jeu de données *iris* et séparer notre nuage de points en trois graphiques distincts selon l'espèce des iris (@fig-fig315). Pour cela, il faut au préalable convertir la variable *espèce* en facteur.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\niris$Species_fac <- as.factor(iris$Species)\n\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") +\n facet_wrap(vars(Species_fac), ncol = 2)\n```\n\n::: {.cell-output-display}\n![Graphique à facettes](03-magiedesgraphiques_files/figure-html/fig-fig315-1.png){#fig-fig315 fig-align='center' width=65%}\n:::\n:::\n\nNotez que le nom de la variable (ici `Species_fac`) doit être spécifié au sein d'une sous-fonction `vars` : `vars(Species_fac)`. Nous aurions aussi pu réaliser le graphique sur une seule ligne en spécifiant `ncol = 3` (@fig-fig316).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") +\n facet_wrap(vars(Species_fac), ncol = 3)\n```\n\n::: {.cell-output-display}\n![Graphique à facettes en une ligne](03-magiedesgraphiques_files/figure-html/fig-fig316-1.png){#fig-fig316 fig-align='center' width=65%}\n:::\n:::\n\n\n#### Arrangement des graphiques {#sec-03142}\n\nLa solution avec les facettes est très pratique, mais également très limitée puisqu'elle ne permet pas de créer une figure avec des graphiques combinant plusieurs types de géométries. `ggarrange` du *package* `ggpubr` permet tout simplement de combiner des graphiques déjà existant. Créons deux nuages de points comparant plusieurs variables en fonction de l'espèce des iris, puis combinons-les (@fig-fig317). Attribuons également aux points une couleur en fonction de l'espèce des fleurs, afin de mieux les distinguer en associant la variable `Species` au paramètre `color`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggpubr)\n\nplot1 <- ggplot(data = iris) +\n geom_point(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +\n labs(subtitle = \"Caractéristiques des sépales\",\n x = \"Longueur\", \n y = \"Largeur\",\n color = \"Espèce\")\n\nplot2 <- ggplot(data = iris) +\n geom_point(aes(x = Petal.Length, y = Petal.Width, color = Species)) +\n labs(subtitle = \"Caractéristiques des pétales\",\n x = \"Longueur\", \n y = \"Largeur\",\n color = \"Espèce\")\n\nliste_plots <- list(plot1, plot2)\ncomp_plot <- ggarrange(plotlist = liste_plots, ncol = 2, nrow = 1,\n common.legend = TRUE, legend = \"bottom\") #gérer la légende\n\nannotate_figure(comp_plot,\n top = text_grob(\"Morphologie des sépales et pétales des iris\",\n face = \"bold\", size = 12, just = \"center\"),\n bottom = text_grob(\"Source : jeu de données iris\",\n face = \"italic\", size = 8, just = \"left\")\n )\n```\n\n::: {.cell-output-display}\n![Figure avec plusieurs graphiques avec ggarrange](03-magiedesgraphiques_files/figure-html/fig-fig317-1.png){#fig-fig317 fig-align='center' width=65%}\n:::\n:::\n\n\nQuatre étapes sont nécessaires : \n\n1. Créer les graphiques et les enregistrer dans des objets (ici *plot1* et *plot2*).\n2. Encapsuler ces objets dans une liste (ici *liste_plots*).\n3. Composer la figure finale avec la fonction `ggarrange`.\n4. Ajouter les annotations à la figure composite.\n\nL'argument `common.legend` permet d'indiquer à la fonction `ggarrange` de regrouper les légendes des deux graphiques. Dans notre cas, les deux graphiques ont les mêmes légendes, il est donc judicieux de les regrouper. L'argument `legend` contrôle la position de la légende et peut prendre les valeurs : *top*, *bottom*, *left*, *right* ou *none* (absence de légende). La fonction `annotate_figure` permet d'ajouter des éléments de texte au-dessus, au-dessous et sur les cotés de la figure composite.\n\n### Couleur {#sec-0315}\n\nDans un graphique, la couleur peut être utilisée à la fois pour représenter une variable quantitative (dégradé de couleur ou mise en classes), ou une variable qualitative (couleur par catégorie). Dans `ggplot2`, il est possible d'attribuer une couleur au contour des géométries avec l'argument `color` et au remplissage avec l'argument `fill`. Il est possible de spécifier une couleur de trois façons dans R : \n\n* En utilisant le nom de la couleur dans une chaîne de caractère : `\"chartreuse4\"`. R dispose de 657 noms de couleurs prédéfinis. Pour tous les afficher, utilisez la fonction `colors()`, qui permet de les visualiser (@fig-colors).\n\n![Couleurs de base](images/Chap03/all_colors.png){#fig-colors width=\"100%\" fig-align=\"center\"}\n\n* En indiquant le code hexadécimal de la couleur. Il s'agit d'une suite de six lettres et de chiffres précédée par un dièse : `\"#99ff33\"`.\n\n* En utilisant une notation RGB (rouge, vert, bleu, transparence). Cette notation doit contenir quatre nombres entre 0 et 1 (0 % et 100 %), indiquant respectivement la quantité de rouge, de vert, de bleu et la transparence. Ces quatre nombres sont donnés comme argument à la fonction `rgb` : `rgb(0.6, 1, 0.2, 0)`.\n\nLe choix des couleurs est un problème plus complexe que la manière de les spécifier. Il existe d'ailleurs tout un pan de la sémiologie graphique dédié à la question du choix et de l'association des couleurs. Une première ressource intéressante est [ColorBrewer](https://colorbrewer2.org/#type=sequential&scheme=BuGn&n=3){target=\"_blank\"}. Il s'agit d'une sélection de palettes de couleurs particulièrement efficaces et dont certaines sont même adaptées pour les personnes daltoniennes (@fig-colorBrewer). Il est possible d'accéder directement aux palettes dans R grâce au *package* `RColorBrewer` et la fonction `brewer.pal` : \n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(RColorBrewer)\ndisplay.brewer.all()\n```\n\n::: {.cell-output-display}\n![Palette de couleurs de ColorBrewer](03-magiedesgraphiques_files/figure-html/fig-colorBrewer-1.png){#fig-colorBrewer fig-align='center' width=85%}\n:::\n:::\n\n\nUne autre ressource pertinente est le site web [coolors.co](https://coolors.co/palettes/trending){target=\"_blank\"} qui propose de nombreuses palettes à portée de clic.\n\n## Principaux graphiques {#sec-032}\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Construire des graphiques avec `ggplot2`**\n:::\n::: bloc_objectif-body\nPuisque vous avez désormais une certaine connaissance des bases de la grammaire des graphiques implémentées par `ggplot2`, vous apprendrez dans les sous-sections suivantes à construire les principaux graphiques que vous utiliserez régulièrement ou que vous présenterez dans un article scientifique.\n:::\n:::\n\n### Histogramme {#sec-0321}\n\nL'histogramme permet de décrire graphiquement la forme de la distribution d'une variable. Pour le réaliser, nous utilisons la fonction `geom_histogram`. Le paramètre le plus important est le nombre de barres (`bins`) qui composent l'histogramme. Plus ce nombre est grand, plus l'histogramme est précis et, à l'inverse, plus il est petit, plus l'histogramme est simplifié. En revanche, il faut éviter d'utiliser un nombre de barres trop élevé comparativement au nombre d'observations disponibles dans le jeu de données, sinon l'histogramme risque d'avoir plein de trous.\n\n#### Histogramme simple {#sec-03211}\n\nGénérons quatre variables ayant respectivement une distribution gaussienne, Student, Gamma et bêta, puis réalisons un histogramme pour chacune de ces variables et combinons-les avec la fonction `ggarrange` (@fig-fig318).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndistribs <- data.frame(\n gaussien = rnorm(1000, mean = 5, sd = 1.5),\n gamma = rgamma(1000, shape = 2, rate = 12),\n beta = rbeta(1000, shape1 = 5, shape2 = 1, ncp = 2),\n student = rt(1000, ncp = 20, df = 5)\n)\n\nplot1 <- ggplot(data = distribs) +\n geom_histogram(aes(x = gaussien), bins = 50, color = \"#343a40\", fill = \"#e63946\")+\n labs(y = \"fréquences\")+ylim(c(0,130))\n\nplot2 <- ggplot(data = distribs) +\n geom_histogram(aes(x = gamma), bins = 50, color = \"#343a40\", fill = \"#f1faee\")+\n labs(y = \"fréquences\")+ylim(c(0,130))\n\nplot3 <- ggplot(data = distribs) +\n geom_histogram(aes(x = beta), bins = 50, color = \"#343a40\", fill = \"#a8dadc\")+\n labs(y = \"fréquences\")+ylim(c(0,130))\n\nplot4 <- ggplot(data = distribs) +\n geom_histogram(aes(x = student), bins = 50, color = \"#343a40\", fill = \"#1d3557\")+\n labs(y = \"fréquences\")+ylim(c(0,130))\n\nhistogrammes <- list(plot1, plot2, plot3, plot4)\n\nggarrange(plotlist = histogrammes, ncol = 2, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Histogrammes](03-magiedesgraphiques_files/figure-html/fig-fig318-1.png){#fig-fig318 fig-align='center' width=65%}\n:::\n:::\n\n\n\nNotez que cette syntaxe est très lourde. Dans le cas présent, il serait plus judicieux d'utiliser la fonction `facet_wrap`. Pour cela, nous devons au préalable empiler nos données, ce qui signifie changer la forme du *DataFrame* actuel, qui comprend quatre colonnes (gaussien, Gamma, bêta et student) et 1000 observations, pour qu'il n'ait plus que deux colonnes (la valeur originale et le nom de l'ancienne colonne) et 4000 observations. La @fig-fig319 décrit graphiquement ce processus qui peut être effectué avec la fonction `melt` du *package* `reshape2`.\n\n![Empiler les données d'un DataFrame](images/Chap03/melting.png){#fig-fig319 width=\"30%\" fig-align=\"center\"}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(reshape2)\n\n# Faire fondre le jeu de données\nmelted_distribs <- melt(distribs, measure.vars = c(\"gaussien\", \"gamma\",\n \"beta\" , \"student\"))\n# Renommer les colonnes du nouveau DataFrame\nnames(melted_distribs) <- c(\"distribution\", \"valeur\")\n# Convertir la variable catégorielle en facteur\nmelted_distribs$distribution <- as.factor(melted_distribs$distribution)\n\nggplot(data = melted_distribs)+\n geom_histogram(aes(x = valeur, fill = distribution), bins = 50, color = \"#343a40\") +\n ylim(c(0,130)) + \n labs(x = \"valeur\", \n y = \"fréquences\")+\n scale_fill_manual(values = c(\"#e63946\" , \"#f1faee\" , \"#a8dadc\" , \"#1d3557\"))+\n facet_wrap(vars(distribution), ncol = 2, scales = \"free\")+\n theme(legend.position = \"none\")\n```\n\n::: {.cell-output-display}\n![Histogrammes à facettes](03-magiedesgraphiques_files/figure-html/fig-fig320-1.png){#fig-fig320 fig-align='center' width=65%}\n:::\n:::\n\n\n#### Histogramme de densité {#sec-03212}\n\nLes histogrammes que nous venons de construire utilisent la fréquence des observations pour délimiter la hauteur des barres. Il est possible de changer ce comportement pour plutôt utiliser la densité. L'intérêt est notamment de se rapprocher encore de la définition d'une distribution puisqu'avec cette configuration, la somme totale de la surface de l'histogramme est égale à 1. La hauteur de chaque barre représente alors la probabilité d'obtenir l'étendue de valeurs représentées par cette barre. Prenons pour exemple la variable avec la distribution normale que nous venons de voir.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nplot1 <- ggplot(data = distribs) +\n geom_histogram(aes(x = gaussien, y = after_stat(density)),\n bins = 30, color = \"#343a40\", fill = \"#1d3557\")+\n labs(x = \"gaussien\", y = \"densité\")\n\nplot2 <- ggplot(data = distribs) +\n geom_histogram(aes(x = gaussien, y = ..count..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\")+\n labs(x = \"gaussien\", y = \"fréquences\")\n\nggarrange(plotlist = list(plot1, plot2), ncol = 2)\n```\n\n::: {.cell-output .cell-output-stderr}\n```\nWarning: The dot-dot notation (`..count..`) was deprecated in ggplot2 3.4.0.\nℹ Please use `after_stat(count)` instead.\n```\n:::\n\n::: {.cell-output-display}\n![Histogrammes de densité](03-magiedesgraphiques_files/figure-html/fig-fig321-1.png){#fig-fig321 fig-align='center' width=65%}\n:::\n:::\n\n\nLe graphique de droite (fréquence) nous indique donc que plus de 60 observations ont une valeur d'environ 5 (entre 4,76 et 5,34, compte tenu de la largeur de la barre), ce qui se traduit par une probabilité de presque 30 % d'obtenir cette valeur en tirant une observation au hasard dans le jeu de données.\n\n#### Histogramme avec courbe de distribution {#sec-03213}\n\nLes histogrammes sont souvent utilisés pour vérifier graphiquement si une distribution empirique s'approche d'une courbe normale. Pour cela, nous ajoutons sur l'histogramme de la variable empirique la forme qu'aurait une distribution normale parfaite en utilisant la moyenne et l'écart type de la distribution empirique. Pour créer cette figure dans `ggplot2`, il suffit d'utiliser la fonction `stat_function` pour créer un nouveau calque. Il est aussi possible d'ajouter une ligne verticale (`geom_vline`) pour indiquer la moyenne de la distribution.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nmoyenne <- mean(distribs$gaussien)\necart_type <- sd(distribs$gaussien)\n\nggplot(data = distribs) +\n geom_histogram(aes(x = gaussien, y = after_stat(density)),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = \"gaussien\", \n y = \"densité\")+\n stat_function(fun = dnorm, args = list(mean = moyenne, sd = ecart_type), \n color = \"#e63946\", linewidth = 1.2, linetype = \"dashed\") +\n geom_vline(xintercept = moyenne, color = \"red\", linetype = 1)+\n annotate(\"text\", x = round(moyenne,2)+0.5, y = 0.31, hjust = 'left',\n label = paste('moyenne : ', round(moyenne,2), sep=''))\n```\n\n::: {.cell-output-display}\n![Histogramme et courbe normale](03-magiedesgraphiques_files/figure-html/fig-fig322-1.png){#fig-fig322 fig-align='center' width=65%}\n:::\n:::\n\n\nDans notre cas, nous savons que notre variable est normalement distribuée (car produite avec la fonction `rnorm`), et nous pouvons constater la grande proximité entre l'histogramme et la courbe normale.\n\n#### Histogramme avec coloration des valeurs extrêmes {#sec-03214}\n\nIl peut être nécessaire d'attirer le regard sur certaines parties de l'histogramme, comme sur des valeurs extrêmes. Si nous reprenons notre distribution de Student, nous pouvons clairement distinguer un ensemble de valeurs fortes à droite de la distribution. Nous pourrions, dans notre cas, considérer que des valeurs au-delà de 50 constituent des cas extrêmes que nous souhaitons représenter dans une autre couleur. Pour cela, nous devons créer une variable catégorielle nous permettant de distinguer ces cas particuliers.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndistribs$cas_extreme <- ifelse(distribs$student >=50, \"extrême\", \"normale\")\n\nggplot(data = distribs) +\n geom_histogram(aes(x = student, y = ..count.., fill = cas_extreme),\n bins = 30, color = \"#343a40\")+\n scale_fill_manual(\"\", values = c(\"#a8dadc\" , \"#e63946\"))+\n labs(title = \"Distribution de Student\", x = \"valeur\", y = \"fréquence\")\n```\n\n::: {.cell-output-display}\n![Histogramme coloré](03-magiedesgraphiques_files/figure-html/fig-fig323-1.png){#fig-fig323 fig-align='center' width=65%}\n:::\n:::\n\n\n### Graphique de densité {#sec-0322}\n\nL'histogramme est utilisé pour approximer graphiquement la distribution d'une variable. Sa principale limite est de représenter la variable de façon discontinue. Une option intéressante est d'utiliser une version lissée de l'histogramme, soit le graphique de densité. Cette opération de lissage est réalisée le plus souvent à partir de fonctions kernel. Reconstruisons notre figure avec les quatre distributions, mais en utilisant cette fois-ci des graphiques de densité.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = melted_distribs)+\n geom_density(aes(x = valeur, fill = distribution), color = \"#343a40\") +\n scale_fill_manual(values = c(\"#e63946\" , \"#f1faee\" , \"#a8dadc\" , \"#1d3557\"))+\n facet_wrap(vars(distribution), ncol = 2, scales = \"free\")+\n theme(legend.position = \"none\")\n```\n\n::: {.cell-output-display}\n![Graphiques de densité à facette](03-magiedesgraphiques_files/figure-html/fig-fig324-1.png){#fig-fig324 fig-align='center' width=65%}\n:::\n:::\n\n\nLes graphiques de densité sont souvent utilisés pour comparer la distribution d'une variable pour plusieurs sous-groupes d'une population. Si nous reprenons le jeu de données *iris*, nous pouvons comparer les longueurs de sépales en fonction des espèces. Nous constatons ainsi que les setosas ont une nette tendance à avoir des sépales plus courts et qu'à l'inverse, les virginicas ont les sépales généralement les plus longs.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = iris)+\n geom_density(aes(x = Sepal.Length, fill = Species), \n color = \"#343a40\", alpha = 0.4)+\n labs(x = \"Longueur de sépales\",\n y = \"\",\n fill = \"Espèce\")\n```\n\n::: {.cell-output-display}\n![Graphiques de densité superposés](03-magiedesgraphiques_files/figure-html/fig-fig325-1.png){#fig-fig325 fig-align='center' width=65%}\n:::\n:::\n\n\n\n### Nuage de points {#sec-0323}\n\nUn nuage de points est un outil très intéressant pour visualiser la relation existante entre deux variables. Prenons un exemple concret et analysons le volume de CO~2~ produit annuellement par habitant en comparaison avec le niveau d'urbanisation dans l'ensemble des pays à travers le monde. Nous avons extrait ces données sur le site web de la [Banque mondiale](https://donnees.banquemondiale.org/indicateur){target=\"_blank\"}, puis nous les avons structurés dans un fichier *csv*.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndata_co2 <- read.csv(\"data/graphique/world_urb_co2.csv\", encoding = \"UTF-8\")\nnames(data_co2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"country_code\" \"year\" \"Population\" \"Urbanisation\" \"CO2_kt\" \n[6] \"Country.Name\" \"CO2t_hab\" \"region7\" \"region23\" \n```\n:::\n:::\n\n\n#### Nuage de points simple {#sec-03231}\n\nCommençons par un nuage de points simple avec l'ensemble des données.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab))+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Nuage de points simple](03-magiedesgraphiques_files/figure-html/fig-fig326-1.png){#fig-fig326 fig-align='center' width=65%}\n:::\n:::\n\n\nÀ la première lecture de ce graphique, nous observons immédiatement un ensemble de points étranges dont le volume de CO~2~ par habitant annuel est au-dessus de 150 tonnes et dont le niveau d'urbanisation est proche de 50 %. Isolons ces données pour observer de quoi il s'agit.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncas_etrange <- subset(data_co2, data_co2$CO2t_hab >= 150)\nprint(cas_etrange$Country.Name)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n [1] \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\"\n[10] \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\"\n[19] \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\" \"Aruba\"\n```\n:::\n:::\n\n\nIl s'agit d'une petite île néerlandaise des Caraïbes nommée Aruba disposant d'une faible population, mais avec des activités très polluantes (raffinerie et extraction d'or). Nous faisons ici le choix de retirer ces observations puisqu'elles sont assez peu représentatives de la tendance mondiale. Cette démarche si simple relève ainsi de l'analyse exploratoire des données! Sans ce graphique, nous n'aurions probablement jamais identifié ces cas problématiques.\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndata_co2 <- subset(data_co2, data_co2$CO2t_hab <= 150)\n```\n:::\n\n\nReconstruisons le nuage de points maintenant que ces données aberrantes ont été retirées.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ngraphique <- ggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab))+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n:::\n\n\nVoilà qui est mieux! Cependant, le grand nombre de points restant rend la lecture du graphique assez difficile puisqu'ils se superposent. Une première option à envisager, dans ce cas, est à la fois d'ajouter de la transparence aux points et de réduire leur taille : \n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab), alpha = 0.2, size = 0.5)+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\n::: {.cell-output-display}\n![Nuage de points simple avec transparence](03-magiedesgraphiques_files/figure-html/fig-fig328-1.png){#fig-fig328 fig-align='center' width=65%}\n:::\n:::\n\n\n\n#### Nuage de points avec densité {#sec-03232}\n\nBien que la transparence nous aide un peu à distinguer les secteurs du graphique avec le plus de points, il serait plus efficace d'abandonner la géométrie des points pour la remplacer par une géométrie de densité en deux dimensions. Une première approche consiste à diviser l'espace du graphique en petits carrés et à compter le nombre de points tombant dans chaque carré (en somme, un histogramme en deux dimensions).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = data_co2)+\n geom_bin2d(aes(x = Urbanisation, y = CO2t_hab), bins = 50) +\n scale_fill_continuous(type = \"viridis\") +\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n fill = \"Effectif\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\n::: {.cell-output-display}\n![Nuage de points simple](03-magiedesgraphiques_files/figure-html/fig-fig329-1.png){#fig-fig329 fig-align='center' width=65%}\n:::\n:::\n\n\nNous observons ainsi une forte concentration dans le bas du graphique; les pays avec des rejets annuels de CO~2~ supérieurs à 15 tonnes par habitant sont relativement rares. Pour les personnes préférant les représentations plus élaborées, il est aussi possible de diviser l'espace du graphique avec des hexagones en utilisant le *package* `hexbin`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = data_co2)+\n geom_hex(aes(x = Urbanisation, y = CO2t_hab), bins = 50) +\n scale_fill_continuous(type = \"viridis\") +\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n fill = \"Effectif\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\n::: {.cell-output-display}\n![Densité en deux dimensions par hexagones](03-magiedesgraphiques_files/figure-html/fig-fig330-1.png){#fig-fig330 fig-align='center' width=65%}\n:::\n:::\n\n\nEnfin, il est aussi possible de réaliser une version lissée de ces graphiques avec une fonction kernel en deux dimensions (`stat_density_2d`) : \n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = data_co2)+\n stat_density_2d(aes(x = Urbanisation, y = CO2t_hab, fill = ..density..), \n geom = \"raster\", n = 50, contour = FALSE) +\n scale_fill_continuous(type = \"viridis\") +\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n fill = \"densité\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")+\n ylim(0,25)\n```\n\n::: {.cell-output-display}\n![Densité lissée en deux dimensions](03-magiedesgraphiques_files/figure-html/fig-fig331-1.png){#fig-fig331 fig-align='center' width=65%}\n:::\n:::\n\n\n#### Nuage de points et droite de régression {#sec-03233}\n\nAfin de faire ressortir une éventuelle relation entre les variables représentées sur les deux axes, il est possible d'afficher la droite de régression sur le graphique entre X et Y. Cette opération s'effectue avec la fonction `geom_smooth`.\n\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab), alpha = 0.2, size = 0.5)+\n geom_smooth(aes(x = Urbanisation, y = CO2t_hab), method = lm, color = \"red\")+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\n::: {.cell-output-display}\n![Nuage de points avec droite de régression](03-magiedesgraphiques_files/figure-html/fig-fig332-1.png){#fig-fig332 fig-align='center' width=65%}\n:::\n:::\n\n\nNotez que l'argument `method = lm` permet d'indiquer que nous souhaitons utiliser une régression linéaire (*linear model*) pour tracer la géométrie (une droite de régression). La droite semble bien indiquer une relation positive entre les deux variables : une augmentation de l'urbanisation serait associée à une augmentation de la production annuelle de CO~2~ par habitant. Nous pourrions également vérifier si une relation non linéaire serait plus adaptée au jeu de données. Dans notre cas, une relation quadratique pourrait produire un meilleur ajustement.\n\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab), alpha = 0.2, size = 0.7)+\n geom_smooth(aes(x = Urbanisation, y = CO2t_hab), method = lm, \n color = \"red\", formula = y ~ I(x**2))+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\n::: {.cell-output-display}\n![Nuage de points avec droite de régression quadratique](03-magiedesgraphiques_files/figure-html/fig-fig333-1.png){#fig-fig333 fig-align='center' width=65%}\n:::\n:::\n\n\nLa régression quadratique (avec *x* au carré) nous indique ainsi que l'impact du niveau d'urbanisation est plus important à mesure que ce niveau augmente. Vous pouvez également constater que la courbe ne prédit pas de valeurs négatives comparativement à la droite précédente. Il est également possible d'ajuster une courbe sans choisir au préalable sa forme (dans le cas précédent $x^2$) en utilisant une méthode d'ajustement local appelée *loess*.\n\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab), alpha = 0.2, size = 0.5)+\n geom_smooth(aes(x = Urbanisation, y = CO2t_hab), method = loess, \n color = \"red\")+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\n::: {.cell-output-display}\n![Nuage de points avec droite de régression non linéaire](03-magiedesgraphiques_files/figure-html/fig-fig334-1.png){#fig-fig334 fig-align='center' width=65%}\n:::\n:::\n\n\nLa relation non linéaire révèle davantage d'informations : l'augmentation de l'urbanisation est associée à une augmentation de l'émission de CO~2~ par habitant uniquement jusqu'à 75 % d'urbanisation; au-delà de ce seuil, la relation ne tient plus. Ces résultats semblent cohérents avec l'évolution classique de l'économie d'un pays passant progressivement d'une économie agricole, à une économie industrialisée et finalement une économie de services.\n\n### Graphique en ligne {#sec-0324}\n\nUn graphique en ligne permet de représenter l'évolution d'une variable, généralement dans le temps. Dans le jeu de données précédent, nous disposons des émissions de CO~2~ par habitant de nombreux pays sur plusieurs années. Nous pouvons ainsi représenter l'évolution des émissions pour chaque pays avec un graphique en ligne. Pour éviter de le surcharger, cet exercice est réalisé uniquement sur les pays de l'Europe de l'Ouest.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# conversion de la variable year textuelle en variable numérique\ndata_co2$an <- as.numeric(data_co2$year)\n# extraction des données d'Europe de l'Ouest\ndata_europe <- subset(data_co2, data_co2$region23 == \"Europe de l'Ouest\")\n# choix des valeurs pour l'axe des x\nx_ticks <- seq(1960,2020,10)\n\nggplot(data = data_europe)+\n geom_path(aes(x = an, y = CO2t_hab, color = Country.Name))+\n labs(x = \"Années\",\n y = \"Tonnes de CO2 par année et par habitant\",\n color = \"Pays\",\n title = \"Évolution de la production de CO2 par habitant\") +\n scale_x_continuous(breaks = x_ticks, labels = x_ticks)+\n theme_tufte()\n```\n\n::: {.cell-output-display}\n![Graphique en ligne](03-magiedesgraphiques_files/figure-html/fig-fig335-1.png){#fig-fig335 fig-align='center' width=65%}\n:::\n:::\n\n\nNous remarquons notamment qu'aucune donnée, avant 2005, n'est disponible pour le Liechtenstein.\n\n#### Barre d'erreur et en bande {#sec-03241}\n\nSur un graphique, il est souvent pertinent de représenter l'incertitude que nous avons sur nos données. Cela peut être fait à l'aide de barres d'erreur ou à l'aide de polygones délimitant les marges d'incertitude. En guise d'exemple, admettons que les données précédentes sont fiables à plus ou moins 10 %. En d'autres termes, la valeur d'émission de CO~2~ annuelle serait relativement incertaine et pourrait se situer dans un intervalle de 10 % autour de la valeur fournie par la Banque mondiale. Nous obtenons ainsi une borne inférieure (valeur donnée - 10 %) et une borne supérieure (valeur donnée + 10 %). Nous pouvons facilement calculer ces bornes et les faire apparaître dans notre graphique précédent.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndata_europe$borne_basse <- data_europe$CO2t_hab - 0.1 * data_europe$CO2t_hab\ndata_europe$borne_haute <- data_europe$CO2t_hab + 0.1 * data_europe$CO2t_hab\n\nggplot(data = data_europe)+\n geom_point(aes(x = an, y = CO2t_hab, color = Country.Name), size = 0.7)+\n geom_errorbar(aes(x = an, ymin = borne_basse, ymax = borne_haute, color = Country.Name))+\n labs(x = \"Années\",\n y = \"Tonnes de CO2 par année et par habitant\",\n color = \"Pays\",\n title = \"Évolution de la production de CO2 par habitant\") +\n scale_x_continuous(breaks = x_ticks, labels = x_ticks)+\n theme_tufte()\n```\n\n::: {.cell-output-display}\n![Graphique en ligne avec barres d'erreur](03-magiedesgraphiques_files/figure-html/fig-fig336-1.png){#fig-fig336 fig-align='center' width=65%}\n:::\n:::\n\n\nCes barres d'erreurs indiquent notamment qu'il n'y a finalement aucun écart significatif entre la Belgique, les Pays-Bas et l'Allemagne à partir des années 1990. Une autre option de représentation est d'utiliser des polygones avec la fonction `geom_ribbon`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = data_europe)+\n geom_path(aes(x = an, y = CO2t_hab, color = Country.Name), size = 0.7)+\n geom_ribbon(aes(x = an, ymin = borne_basse, ymax = borne_haute,\n fill = Country.Name), alpha = 0.4)+\n labs(x = \"Années\",\n y = \"Tonnes de CO2 par année et par habitant\",\n color = \"Pays\",\n title = \"Évolution de la production de CO2 par habitant\") +\n scale_x_continuous(breaks = x_ticks, labels = x_ticks)+\n theme_tufte()+\n guides(fill = FALSE, scale = \"none\")\n```\n\n::: {.cell-output .cell-output-stderr}\n```\nWarning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.\nℹ Please use `linewidth` instead.\n```\n:::\n\n::: {.cell-output .cell-output-stderr}\n```\nWarning: The `` argument of `guides()` cannot be `FALSE`. Use \"none\" instead as\nof ggplot2 3.3.4.\n```\n:::\n\n::: {.cell-output-display}\n![Graphique en ligne avec marge d'erreur](03-magiedesgraphiques_files/figure-html/fig-fig337-1.png){#fig-fig337 fig-align='center' width=65%}\n:::\n:::\n\n\nLe message du graphique est le même. Notez que nous avons utilisé ici la fonction `guides` pour retirer de la légende les couleurs associées au remplissage des marges d'erreur. Ces couleurs sont les mêmes que celles des lignes et il n'est pas utile de dédoubler la légende. De nombreuses méthodes statistiques produisent des résultats accompagnés d'une mesure de l'incertitude associée à ces résultats. Représenter cette incertitude est crucial pour que le lecteur puisse délimiter la portée des conclusions de vos analyses.\n\n### Boîte à moustaches {#sec-0325}\n\nLes boîtes à moustaches (*box plot* en anglais) sont des graphiques permettant de comparer les moyennes et les intervalles interquartiles d'une variable continue selon plusieurs groupes d'une population. Si nous reprenons notre exemple précédent, nous pourrions comparer, en fonction de la région du monde, la moyenne de production annuelle de CO~2~ par habitant. Pour cela, il suffit d'utiliser la fonction `geom_boxplot`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Retirer les observations n'étant pas associées à une région\ndata_co2_comp <- subset(data_co2, is.na(data_co2$region7) == FALSE)\n\nggplot(data = data_co2_comp)+\n geom_boxplot(aes(y = region7, x = CO2t_hab))+\n labs(x = \"Tonnes de CO2 par an et habitant\", y = \"Région\")\n```\n\n::: {.cell-output-display}\n![Boîtes à moustaches](03-magiedesgraphiques_files/figure-html/fig-fig338-1.png){#fig-fig338 fig-align='center' width=65%}\n:::\n:::\n\n\nLa barre centrale d'une boîte représente la moyenne. Les extrémités de la boîte représentent le premier et le troisième quartile. Plus une boîte est allongée, plus les situations sont diversifiées pour les observations appartenant au groupe représenté par la boîte. Au contraire, une boîte étroite indique un groupe homogène. Notez qu'en inversant les variables dans les axes *X* et *Y*, nous obtiendrions des boîtes à moustaches verticales. Cependant, les noms des régions étant assez longs, cela nécessiterait d'avoir un graphique très large. Améliorons quelque peu le rendu de ce graphique en ajoutant des titres.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = data_co2_comp)+\n geom_boxplot(aes(y = region7, x = CO2t_hab))+\n xlim(c(0,50))+\n labs(x = \"Tonnes de CO2 par an et habitant\",\n y = \"Région\")\n```\n\n::: {.cell-output-display}\n![Boîtes à moustaches améliorées](03-magiedesgraphiques_files/figure-html/fig-fig339-1.png){#fig-fig339 fig-align='center' width=65%}\n:::\n:::\n\n\nLes points noirs sur le graphique représentent des valeurs extrêmes, soit des observations situées à plus de 1,5 intervalle interquartile d'une extrémité de la boîte. Pour mieux rendre compte de la densité d'observations le long de chaque boîte à moustaches, il est possible de les représenter directement avec la fonction `geom_jitter`.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Boîtes à moustaches avec observations](03-magiedesgraphiques_files/figure-html/fig-fig340-1.png){#fig-fig340 fig-align='center' width=65%}\n:::\n:::\n\nNotez que pour éviter que les valeurs extrêmes identifiées par la fonction `geom_boxplot` se superposent avec les points représentant les observations, nous les avons supprimées avec l'argument `outlier.shape = NA`.\n\n### Graphique en violon {#sec-0326}\n\nLes boîtes à moustaches donnent des informations pertinentes sur le centre et la dispersion d'une variable en fonction de sous groupes de la population. Cependant, une grande partie de l'information reste masquée par la représentation sous forme de boîte. Une solution est de remplacer la simple boîte par la distribution de la variable étudiée. Nous obtenons ainsi des graphiques en violon (`geom_violin`). Considérant les très grands écarts que nous avons observés entre les régions avec les boîtes à moustaches, il est préférable de tracer les graphiques en violon en excluant les régions Afrique Sub-Saharienne et Asie du Sud.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Retirons les observations de régions que nous ne souhaitons pas garder\ndata_co2_comp <- subset(data_co2, (! data_co2$region7 %in% \n c(\"Sub-Saharan Africa\", \"South Asia\")) \n & is.na(data_co2$region7) == FALSE)\n\nggplot(data = data_co2_comp)+\n geom_violin(aes(y = region7, x = CO2t_hab))+\n xlim(c(0,50))+\n labs(x = \"Tonnes de CO2 par année et par habitant\",\n y = \"\")+\n geom_vline(xintercept = 12, linetype = 'dashed', color = \"blue\")\n```\n\n::: {.cell-output-display}\n![Graphiques en violon](03-magiedesgraphiques_files/figure-html/fig-fig341-1.png){#fig-fig341 fig-align='center' width=65%}\n:::\n:::\n\n\nCes distributions permettent notamment de souligner que deux groupes distincts se retrouvent en Amérique du Nord. L'un dont les émissions annuelles de CO~2~ par habitant sont inférieures à 12 tonnes (ligne bleue) et l'autre pour lequel elles sont supérieures. En explorant les données, nous constatons que les Bermudes appartiennent au groupe Amérique du Nord, mais ont des niveaux d'émission inférieurs à ceux du Canada et des États-Unis, ce qui explique cette distribution bimodale. Cette information était masquée avec les boîtes à moustaches. Finalement, il est aussi possible de superposer un graphique en violon et une boîte à moustaches pour bénéficier des avantages des deux.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot(data = data_co2_comp)+\n geom_violin(aes(y = region7, x = CO2t_hab))+\n geom_boxplot(aes(y = region7, x = CO2t_hab), width = 0.15)+\n xlim(c(0,50))+\n labs(x = \"Tonnes de CO2 par année et par habitant\",\n y = \"\")\n```\n\n::: {.cell-output-display}\n![Graphiques en violon et boîtes à moustaches](03-magiedesgraphiques_files/figure-html/fig-fig342-1.png){#fig-fig342 fig-align='center' width=65%}\n:::\n:::\n\n\n### Graphique en barres {#sec-0327}\n\nLes graphiques en barres permettent de représenter des quantités (hauteur des barres) réparties dans des catégories (une barre par catégorie). Nous proposons ici un exemple avec des données de déplacements issues de l'*Enquête origine-destination 2017 - Région Québec-Lévis*, au niveau des grands secteurs. La @fig-fig342, tirée du [rapport](https://www.transports.gouv.qc.ca/fr/ministere/Planification-transports/enquetes-origine-destination/quebec/2017/Documents/EOD17_faits_saillants_VF.pdf) intitulé *La mobilité des personnes dans la région de Québec-Lévis (Volet Enquête-ménages : faits saillants)* délimite ces grands secteurs.\n\n![Grands secteurs de Québec](images/Chap03/carte_secteurs.jpg){#fig-fig343 width=\"100%\" fig-align=\"center\"}\n\nNous représentons pour chaque secteur le nombre moyen de déplacements entrant et sortant un jour de semaine en heures de pointe. Les données sont présentées sous forme d'une matrice carrée (avec autant de lignes que de colonnes). L'intersection de la ligne A et de la colonne C indique le nombre de personnes partant du secteur A pour se rendre au secteur C. À l'inverse, l'intersection de la ligne C et de la colonne A indique le nombre de personnes partant du secteur C pour se rendre au secteur A. En sommant les valeurs de chaque ligne, nous obtenons le nombre total de départs par secteur tandis que le nombre d'arrivées est la somme de chaque colonne. Ces opérations peuvent simplement être effectuées avec les fonctions `rowSums` et `colSums`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Chargement des données\nmatriceOD <- read.csv('data/graphique/Quebec_2017_OD_MJ.csv',\n header = FALSE, sep = ';') # fichier csv sans entête\n\n# Calcul des sommes en lignes et en colonnes\ntot_depart <- rowSums(matriceOD)\ntot_arrivee <- colSums(matriceOD)\n\n# Création d'un DataFrame avec les valeurs et les noms des secteurs\ndf <- data.frame(depart = tot_depart,\n arrivee = tot_arrivee, \n secteur = c('Arr. de Beauport (Québec)',\n 'Arr. de Charlesbourg (Québec)',\n 'Arr. des Rivières (Québec)',\n 'Arr. de la Cité-Limoilou (Québec)',\n 'Arr. de la Haute-Saint-Charles (Québec)',\n 'Arr. de Sainte-Foy-Sillery-Cap-Rouge (Québec)',\n 'Arr.de Desjardins (Lévis)',\n 'Arr. des Chutes–de-la-Chaudière-Est (Lévis)',\n 'Arr. des Chutes de la Chaudière-Ouest (Lévis)',\n 'Ceinture Nord',\n 'Ceinture Sud',\n 'Hors Territoire'),\n code = c('A','B','C','D','E','F','G','H','I','J','K','X'))\n\n# Création des deux graphiques en barre\nplot1 <- ggplot(data = df)+\n geom_bar(aes(x = code, weight = depart))+\n labs(subtitle = \"Départs\",\n x = \"total\",\n y = \"\")\n\nplot2 <- ggplot(data = df)+\n geom_bar(aes(x = code, weight = arrivee))+\n labs(subtitle = \"Arrivées\",\n x = \"total\",\n y = \"\")\n\n# Stocker les graphiques dans une liste et composer une figure\nlist_plot <- list(plot1, plot2)\ntot_plot <- ggarrange(plotlist = list_plot, ncol = 1)\n\n# Création d'une légende pour associer le code de chaque secteur \n# à son nom. Pour cela nous concaténons en premier les lettres et les noms.\n# Nous fusionnons ensuite le tout en les séparant par le symbole \\n représentant \n# un saut de ligne.\nnom_secteurs <- paste(df$code, df$secteur, sep= ' : ')\nstring_names <- paste(nom_secteurs, collapse = '\\n')\n\ntitre <- \"Déplacements journaliers moyens en heures de pointe\"\n# Production finale de la figure\nannotate_figure(tot_plot,\n top = text_grob(titre, face = \"bold\", size = 11, just = \"left\"),\n right = text_grob(string_names, face = \"italic\", size = 8,\n just = \"left\", x = 0.05) # position du texte\n )\n```\n\n::: {.cell-output-display}\n![Graphiques en barre simples](03-magiedesgraphiques_files/figure-html/fig-fig344-1.png){#fig-fig344 fig-align='center' width=75%}\n:::\n:::\n\n\nPlutôt que de représenter les arrivées et les départs dans deux graphiques séparés, il est possible de les empiler dans un même graphique en barres. Nous devons au préalable « faire fondre nos données » avec la fonction `melt`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Faire fondre le jeu de données (empiler les colonnes depart et arrivee)\nmelted_df <- melt(df, id.vars = c('code'), measure.vars = c('depart','arrivee'))\nnames(melted_df) <- c('code','deplacement','effectif')\n# Ajouter les accents dans la colonne déplacement\nmelted_df$deplacement <- ifelse(melted_df$deplacement == 'depart', 'départs', 'arrivées')\n# Comparaison du format original et du format \"fondu\"\nhead(df)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n depart arrivee secteur code\nV1 49241 34777 Arr. de Beauport (Québec) A\nV2 48909 36344 Arr. de Charlesbourg (Québec) B\nV3 48044 67198 Arr. des Rivières (Québec) C\nV4 63132 108138 Arr. de la Cité-Limoilou (Québec) D\nV5 57367 30859 Arr. de la Haute-Saint-Charles (Québec) E\nV6 86504 112379 Arr. de Sainte-Foy-Sillery-Cap-Rouge (Québec) F\n```\n:::\n\n```{.r .cell-code}\nhead(melted_df)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n code deplacement effectif\n1 A départs 49241\n2 B départs 48909\n3 C départs 48044\n4 D départs 63132\n5 E départs 57367\n6 F départs 86504\n```\n:::\n\n```{.r .cell-code}\n# Réalisation du graphique\nplot1 <- ggplot(data = melted_df)+\n geom_bar(aes(x = code, weight = effectif, fill = deplacement), color = '#e3e3e3')+\n scale_fill_manual(values = c(\"#e63946\" , \"#1d3557\"))+\n labs(title = titre,\n y = \"Effectifs\",\n x = \"\",\n fill = \"Déplacements\")\n\nannotate_figure(plot1, right = text_grob(string_names, face = \"italic\", size = 7,\n just = \"left\", x = 0.05)) # position du texte)\n```\n\n::: {.cell-output-display}\n![Graphique en barre empilée](03-magiedesgraphiques_files/figure-html/fig-fig345-1.png){#fig-fig345 fig-align='center' width=65%}\n:::\n:::\n\n\n### Graphique circulaire {#sec-0328}\n\nUne option directe au graphique en barres est le graphique ou diagramme circulaire, appelé aussi graphique en tarte (pour les personnes à la dent sucrée) ou en camembert (pour celles amatrices de fromage). Il est suffisamment connu et utilisé pour qu'aucune présentation ne s'impose. Pour être exact, un graphique en tarte n'est rien d'autre qu'un graphique en barres dont le système de coordonnées a été modifié. Cela impose cependant de calculer à l'avance la position des étiquettes que nous souhaitons ajouter sur le graphique. Reprenons les données de production mondiale de CO~2~ et calculons les productions totales par région géographique en 2015.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(dplyr)\n\n# Extraire les données de 2018 pour lesquelles nous connaissons la région\ndata_co2_2015 <- subset(data_co2, data_co2$year == \"2015\" & ! is.na(data_co2$region7))\n\n# Effectuer la somme du CO2 par région\nco2_2015 <- data_co2_2015 %>% \n group_by(region7) %>% \n summarise(total_co2 = sum(CO2_kt, na.rm = TRUE))\n\n# Attribuer un code à chaque région pour faciliter la lecture\nco2_2015$code <- c(\"A\" , \"B\" , \"C\" , \"D\" , \"E\" , \"F\" , \"G\")\n\n# Modifier l'ordre des données, calculer les proportions et la position des labels\ndf <- co2_2015 %>% \n arrange(desc(code)) %>%\n mutate(prop = total_co2 / sum(co2_2015$total_co2) *100) %>%\n mutate(ypos = cumsum(prop)- 0.5*prop )\n\n# Préparer la légende (pourcentages et vrais noms)\nnom_region <- rev(paste(df$code, \" : \", df$region7, \"(\", round(df$prop,1),\"%)\"))\nstring_region <- paste(nom_region, collapse = '\\n')\n\n# Construire le graphique\nplot1 <- ggplot(df, aes(x = \"\", y = prop, fill = code)) +\n geom_bar(stat = \"identity\", width=1, color = \"white\") +\n coord_polar(\"y\", start=0) +\n theme_void() + \n theme(legend.position = \"none\") +\n geom_text(aes(y = ypos, label = code), color = \"white\", size=3) +\n scale_fill_grey()+\n labs(title = \"Proportion du CO2 émis en 2015\")\n\n# Ajouter la légende\nannotate_figure(plot1, right = text_grob(string_region, face = \"italic\", size = 9,\n just = \"left\", x = 0.05)) # position du texte)\n```\n\n::: {.cell-output-display}\n![Graphique en tarte](03-magiedesgraphiques_files/figure-html/fig-fig346-1.png){#fig-fig346 fig-align='center' width=65%}\n:::\n:::\n\n\nSi à la place de la géométrie `geom_bar`, vous utilisez `geom_rect`, vous pouvez convertir votre graphique en tarte en graphique en anneau (ou en beigne, pour les personnes à la dent sucrée) : \n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Calculer la limite inférieure et supérieure du beigne\ndf$ymax <- cumsum(df$prop)\ndf$ymin <- c(0, head(df$ymax, n=-1))\n\n# Construire le graphique\nplot1 <- ggplot(df, aes(ymax = ymax, ymin = ymin, \n xmax = 4, xmin = 3,\n y = prop, fill = code)) +\n geom_rect(stat = \"identity\", color = \"white\") +\n coord_polar(\"y\", start=0) +\n theme_void() + \n theme(legend.position = \"none\") +\n geom_text(aes(x = 3.5, y = ypos, label = code), color = \"white\", size=3) +\n scale_fill_grey()+\n xlim(c(2,4))+\n labs(title = \"Proportion du CO2 émis en 2015\")\n\n# Ajouter la légende\nannotate_figure(plot1, right = text_grob(string_region, face = \"italic\", size = 8,\n just = \"left\", x = 0.05)) # position du texte)\n```\n\n::: {.cell-output-display}\n![Graphique en anneau](03-magiedesgraphiques_files/figure-html/fig-fig347-1.png){#fig-fig347 fig-align='center' width=65%}\n:::\n:::\n\n\n## Graphiques spéciaux {#sec-033}\n\nDans cette dernière section, nous abordons des graphiques plus rarement utilisés. Ils sont toutefois très utiles dans certains contextes du fait de leur capacité à synthétiser des informations complexes.\n\n### Graphique en radar {#sec-0331}\n\nLes graphiques en radar (ou en toile d'araignée) sont utilisés pour comparer une série de variables continues pour plusieurs observations ou groupes d'observations. Chaque variable est associée à un axe et chaque observation est représentée avec un polygone. Prenons l'exemple de données relatives aux logements par secteur de recensement dans la région métropolitaine de Montréal en 2016. Nous pourrions souhaiter comparer la moyenne des pourcentages des différents types de logements pour les régions des Laurentides, de la Montérégie, de Laval, de Longueuil et de Montréal. Malheureusement, `ggplot2` ne permet pas de dessiner des graphiques en radar satisfaisants, nous devons donc utiliser le *package* `fmsb`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(fmsb)\n\ndata <- read.csv('data/bivariee/sr_rmr_mtl_2016.csv', header = TRUE, encoding = 'UTF-8')\n\n# Agréger les données au niveau des régions en calculant la moyenne des pourcentages\nvariables <- c(\"MaisonIndi\" , \"App5Plus\" , \"MaisRangee\" , \"AppDuplex\" , \"Proprio\" , \"Locataire\")\n\ndata_region <- data[c(\"Region\", variables)] %>% \n group_by(Region) %>%\n summarise_all(.funs = list(mean))\n\n# Gérer le nom des colonnes pour ajuster les données aux besoins de \n# la fonction radachart\nnew_names <- c(\"Region\", paste(variables,\"_mean\", sep = \"\"))\nnames(data_region) <- new_names\ndata_region <- data.frame(data_region)\nrownames(data_region) <- data_region$Region\ndata_region$Region <- NULL\n\n# Ajouter deux lignes aux données avec les valeurs maximales et minimales \n# de chaque colonne. Ces informations aideront la fonction radachart à\n# dessiner chacun des axes du radar\ndata_chart <- rbind(apply(data_region, MARGIN = 2, FUN = max),\n apply(data_region, MARGIN = 2, FUN = min),\n data_region\n )\n\n# Choisir les couleurs pour l'intérieur des polygones (avec transparence)\ncouleurs <- c(\n rgb(0.94, 0.28, 0.44, 0.25),\n rgb(1.00, 0.82, 0.40, 0.25),\n rgb(0.02, 0.84, 0.63, 0.25),\n rgb(0.07, 0.54, 0.70, 0.25),\n rgb(0.03, 0.23, 0.30, 0.25)\n)\n\n# Choisir les couleurs pour l'intérieur des polygones (sans transparence)\ncouleurs_contour <- c(\n rgb(0.94, 0.28, 0.44),\n rgb(1.00, 0.82, 0.40),\n rgb(0.02, 0.84, 0.63),\n rgb(0.07, 0.54, 0.70),\n rgb(0.03, 0.23, 0.30)\n)\n\n# Dessiner du graphique\nradarchart(data_chart,\n title = \"Comparaison des types de logements dans la RMR\",\n pcol = couleurs_contour, pfcol = couleurs,\n plwd = 2, plty = 1,\n cglcol = \"grey\", cglty = 1, axislabcol=\"grey\", cglwd=0.8,\n vlcex = 0.8,\n vlabels = c(\"maison individuelle\", \"immeuble d'appartements\",\n \"maison \\nen rangée\", \"duplex\",\n \"propriétaire\", \"locataire\")\n )\n\n# Ajouter une légende\nlegend(x = 1.3, y = 1, legend = rownames(data_chart[-c(1,2),]), bty = \"n\", \n pch=20 , col=couleurs , text.col = \"black\", cex = 0.9, pt.cex = 1.5)\n```\n\n::: {.cell-output-display}\n![Graphique en anneau](03-magiedesgraphiques_files/figure-html/fig-fig348-1.png){#fig-fig348 fig-align='center' width=65%}\n:::\n:::\n\n\nÀ la lecture du graphique, nous constatons rapidement que l'île de Montréal a une situation très différente des trois autres régions. Laval se distingue également avec une part importante de logements dans des immeubles d'appartements. Ce type de graphique a pour objectif d'orienter le regard sur de potentielles différences dans un contexte multidimensionnel, mais il présente quelques inconvénients : \n\n* Les échelles de chaque axe sont différentes. Il est donc essentiel de se rapporter aux valeurs exactes pour estimer si les écarts sont importants en termes absolus.\n\n* La superposition de plusieurs polygones peut rendre la lecture difficile. Une solution envisageable est de réaliser un graphique par polygone, mais cela prend beaucoup de place dans un document.\n\n* L'utilisation de polygones donne parfois de fausses impressions d'écarts. Dans le précédent graphique, l'œil est attiré en bas à gauche par le polygone de Montréal qui est très différent des autres. Cependant, les écarts sur l'axe *maison en rangée* sont relativement petits comparativement à l'axe *locataire* situé à l'opposé.\n\n### Diagramme d'accord {#sec-0332}\n\nLes diagrammes d'accord (*chord diagram* en anglais) sont utilisés pour représenter des échanges ou des connexions entre des entités. Il peut s'agir par exemple de marchandises importées / exportées entre pays, des messages envoyés entre personnes via un réseau social, de flux de population, etc. Reprenons nos données de l'*Enquête origine-destination 2017 - Région Québec-Lévis* pour illustrer le tout. Nous utilisons le *package* `chorddiag`, très facile d'utilisation et produisant des graphiques interactifs, pour faciliter grandement la lecture de ce type de graphique. Cependant, ce *package* ne fait pas partie du répertoire CRAN, nous devons l'installer directement depuis *github* avec la fonction `devtools::install_github`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndevtools::install_github('mattflor/chorddiag')\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(chorddiag)\n\n# Chargement des données\nmatriceOD <- read.csv('data/graphique/Quebec_2017_OD_MJ.csv',\n header = FALSE, sep = ';') # fichier csv sans entête\n\n# Transformation du DataFrame en matrice\nmatriceOD <- as.matrix(matriceOD)\ncodes <- c('A','B','C','D','E','F','G','H','I','J','K','X')\nsecteurs <- c('Arr. de Beauport',\n 'Arr. de Charlesbourg',\n 'Arr. des Rivières',\n 'Arr. de la Cité-Limoilou',\n 'Arr. de la Haute-St-Charles',\n 'Arr. de Sainte-Foy-Sillery-Cap-Rouge',\n 'Arr.de Desjardins',\n 'Arr. des Chutes–de-la-Chaudière-Est',\n 'Arr. Les Chutes de la-Chaudière-Ouest',\n 'Ceinture Nord',\n 'Ceinture Sud',\n 'Hors Territoire')\n\n# Ajout de noms aux colonnes et aux lignes de la matrice\nrownames(matriceOD) <- secteurs\ncolnames(matriceOD) <- secteurs\n\n# Nous supprimons les trois secteurs Ceinture Nord, Sud et Hors territoire \n# qui comprennent de toute façon peu de déplacements\nmat <- matriceOD[1:8, 1:8]\n\n# Choix aléatoire de couleurs pour les lignes\n# col <- sample(colors(), nrow(mat), replace = FALSE)\n\n# Choix de couleurs \ncol <- c(\"#a491d3\", \"#818aa3\", \"#C5DCA0\", \"#F5F2B8\",\n \"#F9DAD0\", \"#F45B69\", \"#22181C\", \"#5A0001\")\n\n# Réalisation du graphique : sortie HTLM\nif(knitr::is_html_output()){\n chorddiag(mat, groupColors = col, showTicks = FALSE,\n type = 'bipartite', chordedgeColor = 'white',\n groupnameFontsize = 12, groupnamePadding = 5)\n}\n```\n\n::: {#fig-fig349 .cell-output-display}\n```{=html}\n
\n\n```\n\n\nDiagramme d'accord\n:::\n:::\n\nLe graphique permet de remarquer que la plupart des flux s’effectuent au sein d’un même secteur. La majorité des déplacements se font au sein du secteur Sainte-Foy (segment rouge central). Nous pouvons cependant constater que les secteurs des Rivières, de la Cité-Limoilou et de la Haute-Saint-Charles attirent une plus grande quantité et diversité de flux. Si vous lisez ce livre dans un navigateur web (et pas au format *pdf*), le graphique est interactif! En plaçant votre souris sur un lien, vous verrez s'afficher le nombre de déplacements qu'il représente.\n\n### Nuage de mots {#sec-0333}\n\nUn nuage de mots est un graphique utilisé en analyse de texte pour représenter les mots les plus importants d'un document. Mesurer l'importance des termes dans un document est une discipline à part entière (*Natural Language Processing*). Nous proposons un simple exemple ici avec la méthode *TextRank* (basée sur la théorie des graphes) proposée par @mihalcea2004textrank et implémentée dans le *package* `textrank`. Nous avons également besoin des *packages* `udpipe` (fournissant des dictionnaires linguistiques), `RColorBrewer` (pour sélectionner une palette de couleurs) et `wordcloud2` (pour générer le graphique). En guise d'exemple, nous avons choisi d'extraire les textes de deux schémas d'aménagement et de développement (SAD), ceux des agglomérations de Québec et de Montréal en vigueur en 2020. Il s'agit de deux documents de planification définissant les lignes directrices de l'organisation physique du territoire des municipalités régionales de comté (MRC) ou des agglomérations. Pour ces deux documents, nous nous concentrons sur le chapitre portant sur les grandes orientations d'aménagement et de développement, soit les pages 30 à 135 pour Québec et 30 à 97 pour Montréal. Pour extraire les textes des fichiers *pdf*, nous utilisons le *package* `pdftools`.\n\nNous devons donc réaliser les étapes suivantes pour produire le nuage de mots : \n\n1. Extraire les sections qui nous intéressent des fichiers *pdf*.\n2. Extraire le texte de ces sections.\n3. Retirer les caractères représentant les sauts de lignes et les sauts de paragraphes (`\\n` et `\\r`).\n4. Concaténer tout le texte en une seule longue chaîne de caractère.\n5. Utiliser un dictionnaire pour déterminer la nature des mots du texte (nom, adjectif, verbe, etc.).\n6. Utiliser l'algorithme *TextRank* pour identifier les mots clefs.\n7. Nettoyer les erreurs potentielles parmi les mots clefs.\n8. Construire le nuage de mots.\n\nNotez que toutes ces étapes de nettoyage ne seraient pas nécessaires si nous utilisions un simple fichier texte comme point de départ. Cependant, comme il est plus courant de rencontrer des fichiers *pdf*, cet exercice est donc davantage révélateur de la difficulté réelle de la réalisation d'un nuage de mots.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(wordcloud2)\nlibrary(udpipe)\nlibrary(RColorBrewer)\nlibrary(pdftools)\nlibrary(textrank)\n\n# Étape 1 : extraire les sections pertinentes des fichiers pdf\nextrait_qc <- pdf_subset(\"data/graphique/SAD_quebec.pdf\", pages = c(30:135),\n output = \"data/graphique/SAD_quebec_ext.pdf\")\nextrait_mtl <- pdf_subset(\"data/graphique/SAD_montreal.pdf\", pages = c(30:97),\n output = \"data/graphique/SAD_montral_ext.pdf\")\n\n# Étape 2 : extraire le texte des fichiers pdf sous forme de vecteur de texte\nfile_qc <- pdf_text(extrait_qc)\nfile_mtl <- pdf_text(extrait_mtl)\n\n# Étape 3 : retirer les sauts de lignes et les paragraphes\nfile_qc <- gsub(\"\\r\" , \"\", x = file_qc)\nfile_qc <- gsub(\"\\n\" , \"\", x = file_qc)\n\nfile_mtl <- gsub(\"\\r\" , \"\", x = file_mtl)\nfile_mtl <- gsub(\"\\n\" , \"\", x = file_mtl)\n\n# Étape 4 : créer une seule longue chaîne de caractères\n# à partir des vecteurs de texte\ntext_qc <- paste(file_qc, collapse = \" \")\ntext_mtl <- paste(file_mtl, collapse = \" \")\n\n# charger le modèle linguistique français\nmodel <- udpipe_load_model('data/graphique/french-sequoia-ud-2.4-190531.udpipe')\n\n# pour télécharger le modèle si ce n'est pas encore fait : \n# model <- udpipe_download_model(\"french-sequoia\")\n# model <- udpipe_load_model(model)\n\n# Étape 5 : analyse de la nature des mots du texte avec le dictionnaire fr\n# Nous obtenons des DataFrames décrivant les mots des textes\nannote_qc <- udpipe_annotate(model, text_qc)\ndf_qc <- data.frame(annote_qc)\n\nannote_mtl <- udpipe_annotate(model, text_mtl)\ndf_mtl <- data.frame(annote_mtl)\n\n# Étape 6 : utilisation de la méthode TextRank\nstats_qc <- textrank_keywords(df_qc$lemma,\n relevant = df_qc$upos %in% c(\"NOUN\", \"ADJ\"), ngram_max = 2)\n\nstats_mtl <- textrank_keywords(df_mtl$lemma,\n relevant = df_mtl$upos %in% c(\"NOUN\" , \"ADJ\"), ngram_max = 2)\n\n# Étape 7 : nettoyer les coquilles dans les mots clefs \n# Note : nous faisons ici le choix de garder des mots clefs uniques (ngram == 1)\n# Il serait aussi possible de garder des associations de plusieurs mots\ndfstats_qc <- subset(stats_qc$keywords, stats_qc$keywords$ngram == 1 &\n nchar(stats_qc$keywords$keyword)>2)\ndfstats_qc$keyword <- gsub(\"d’\" , \"\", dfstats_qc$keyword, fixed = TRUE)\ndfstats_qc$keyword <- gsub(\"l’\" , \"\", dfstats_qc$keyword, fixed = TRUE)\n\ndfstats_mtl <- subset(stats_mtl$keywords, stats_mtl$keywords$ngram == 1 &\n nchar(stats_mtl$keywords$keyword)>2)\ndfstats_mtl$keyword <- gsub(\"d’\" , \"\", dfstats_mtl$keyword, fixed = TRUE)\ndfstats_mtl$keyword <- gsub(\"l’\" , \"\", dfstats_mtl$keyword, fixed = TRUE)\n\n# Étape 8 : réaliser les nuages de mots\ncouleurs <- sample(brewer.pal(12, \"Paired\")) # mise en désordre des couleurs\n\nwordcloud2(data = dfstats_mtl[c(\"keyword\", \"freq\")],\n color = couleurs, size = 0.5, shuffle = FALSE)\n\nwordcloud2(data = dfstats_qc[c(\"keyword\", \"freq\")],\n color = couleurs, size = 0.6, shuffle = FALSE)\n```\n:::\n\n\n![Nuage de mots pour le SAD de Montréal](images/Chap03/nuage_mtl.png){#fig-fig350 width=\"85%\" fig-align=\"center\"}\n\n![Nuage de mots pour le SAD de Québec](images/Chap03/nuage_qc.png){#fig-fig351 width=\"85%\" fig-align=\"center\"}\n\nNotez qu'à chaque génération du nuage de mots, vous obtiendrez une disposition différente. N'hésitez pas à en essayer plusieurs jusqu'à ce que vous trouviez celle qui vous semble optimale.\n\n### Carte proportionnelle {#sec-0334}\n\nUne carte proportionnelle ou carte à cases (*treemap* en anglais) est un graphique permettant de représenter une quantité partagée entre plusieurs observations structurées dans une hiérarchie de groupe. Le jeu de données portant sur les émissions de CO~2~ se prête tout à fait à une représentation par *treemap*. La variable de quantité est bien sûr les émissions de CO~2~ par pays; ces pays sont regroupés dans un premier ensemble de régions (découpage en 23 régions), qui elles-mêmes sont regroupées dans des régions plus larges (découpage en sept régions). Pour construire un *treemap*, nous allons utilisons le *package* `treemap`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(treemap)\nlibrary(RColorBrewer)\n\n# extraire les données de CO2 en 2015\ndata_co2_2015 <- subset(data_co2, data_co2$year == \"2015\" & ! is.na(data_co2$region7))\n\n# construire le treemap\n\ntreemap(data_co2_2015, index = c(\"region7\" , \"region23\"),\n vSize = \"CO2_kt\", type = \"index\",\n title = \"CO2 rejetés par pays en 2015\",\n fontsize.labels=c(12,8), # taille des étiquettes \n fontcolor.labels=c(\"white\" , \"black\"), # couleur des étiquettes\n fontface.labels=c(2,1), # style des polices\n bg.labels = 0, # arrière-plan des étiquettes\n align.labels=list(\n c(\"center\", \"center\"), \n c(\"right\", \"bottom\")\n ), # localisation des étiquettes dans les boîtes\n overlap.labels=0.5, # tolérance de superposition\n inflate.labels = FALSE, # agrandir la taille des étiquettes ou non\n palette = brewer.pal(7,'Paired')\n)\n```\n\n::: {.cell-output-display}\n![Treemap](03-magiedesgraphiques_files/figure-html/fig-fig352-1.png){#fig-fig352 fig-align='center' width=90%}\n:::\n:::\n\n\n## Cartes {#sec-034}\n\nToute comme un graphique, une carte est aussi une illustration visuelle. Avec la généralisation des données géographiques, il peut être utile de savoir représenter ce type de données. Si R n'est pas un logiciel de cartographie, il est possible de réaliser des cartes assez facilement, directement avec `ggplot2`. Nous avons cependant une préférence pour le *package* `tmap`, qui propose de nombreuses fonctionnalités. Pour tracer des cartes, `tmap` et `ggplot2` ont besoin d'utiliser un format de données comprenant la géométrie (polygones, lignes ou points), la localisation et le système de projection des entités spatiales étudiées. Le format de fichier le plus courant pour ce type de données est le *shapefile* (*.shp*), mais vous pourrez parfois croiser des fichiers *geojson* (*.js*), ou encore *geopackages* (*.gpkg*). Pour lire ces fichiers, il est possible d'utiliser la fonction `readOGR` du *package* `rgdal`, ou la fonction `st_read` du *package* `sf`. Notez ici que ces deux fonctions ne produisent pas de *DataFrame*, mais respectivement un *SpatialDataFrame* et un objet `sf` (*spatial feature collection*). Sans entrer dans les détails, sachez que deux *packages* permettent de manipuler des objets spatiaux dans R : le traditionnel `sp` (avec les *SpatialDataFrames*) et le plus récent `sf` (avec les *spatial feature collections*). Il est assez facile de convertir un objet de `sp` vers `sf` (et inversement) et cette opération est souvent nécessaire, car de nombreux *packages* dédiés à l'analyse spatiale utilisent l'un ou l'autre des formats. Dans le cas de `tmap`, des objets `sp` et `sf` peuvent être utilisés sans distinction. En revanche, pour cartographier directement avec `ggplot2`, il est plus facile d'utiliser un objet de type `sf`. Toutefois, nous vous recommandons fortement d'utiliser le *package* `sf`, puisque `sp` (et son format *SpatialDataFrame*) est progressivement délaissé dans R.\n\nUne carte thématique permet de représenter la répartition spatiale de variables qualitatives ou quantitatives. Nous la distinguons des cartes topographiques, dont l'objectif est de représenter la localisation d'objets spécifiques (route, habitation, rivière, lac, etc.). La première est relativement facile à construire dans R, car elle se limite à quelques symboles relativement simples. Pour la seconde, nous préférons généralement utiliser un logiciel comme [QGIS](https://qgis.org/en/site/){target=\"_blank\"}.\n\nCréons une carte thématique à partir des données de densité de végétation sur l'île de Montréal avec les *packages* `ggplot2` puis `tmap`.\n\nAvec `ggplot2`, nous avons aussi besoin des *packages* `classInt` pour calculer les intervalles des classes et `ggsn` pour afficher une échelle.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(sf)\nlibrary(classInt)\nlibrary(ggspatial)\n\n# Chargement des données\nspatialdf <- st_read(\"data/bivariee/IlotsVeg2006.shp\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nReading layer `IlotsVeg2006' from data source \n `C:\\Users\\appariciop\\OneDrive - USherbrooke\\Articles Publies ne pas supprimer\\_Livres\\BolR_MethodesQuantitatives\\data\\bivariee\\IlotsVeg2006.shp' \n using driver `ESRI Shapefile'\nSimple feature collection with 10213 features and 12 fields\nGeometry type: MULTIPOLYGON\nDimension: XY\nBounding box: xmin: 267518.7 ymin: 5029292 xmax: 306663.7 ymax: 5062652\nProjected CRS: NAD83 / MTM zone 8\n```\n:::\n\n```{.r .cell-code}\n# Création d'une discrétisation en 7 classes égales\nvalues <- c(max(spatialdf$ArbPct)+0.01, spatialdf$ArbPct)\n\nquant <- classIntervals(values, n = 7,\n style = \"quantile\",\n intervalClosure = 'right')\n\nspatialdf$class_col <- cut(spatialdf$ArbPct, breaks = quant$brks, right = FALSE)\n\n# Cartographie avec ggplot2\nggplot(data = spatialdf) + \n geom_sf(aes(fill = class_col), color = rgb(0,0,0,0))+\n scale_fill_brewer(palette = \"Greens\")+\n labs(title = \"Végétation dans les îlos de recensement\",\n 'fill' = 'Densité de la canopée (%)')+\n theme(axis.line=element_blank(), axis.text.x = element_blank(),\n axis.text.y = element_blank(), axis.ticks=element_blank(),\n axis.title.x = element_blank(), axis.title.y = element_blank(),\n panel.background=element_blank(),\n panel.border=element_blank(), panel.grid.major=element_blank(),\n panel.grid.minor=element_blank(), plot.background=element_blank(),\n legend.key.size = unit(0.5, \"cm\"))+\n annotation_scale()\n```\n\n::: {.cell-output-display}\n![Carte thématique avec ggplot2](03-magiedesgraphiques_files/figure-html/fig-fig353-1.png){#fig-fig353 fig-align='center' width=85%}\n:::\n:::\n\n\nIl est possible d'arriver à un résultat similaire avec `tmap` avec moins de code! \n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(tmap)\n\ncolors <- brewer.pal(7,\"Greens\")\ntm_shape(spatialdf) +\n tm_polygons(\"ArbPct\", palette = colors, border.alpha = 0,\n n = 7, style = 'quantile',\n title = \"Densité de la canopée (%)\")+\n tm_scale_bar(breaks = c(0,5,10)) + \n tm_layout(title = \"Végétation dans les îlos de recensement\",\n attr.outside = TRUE, frame = FALSE)\n```\n\n::: {.cell-output-display}\n![Carte thématique avec tmap](03-magiedesgraphiques_files/figure-html/fig-fig354-1.png){#fig-fig354 fig-align='center' width=85%}\n:::\n:::\n\n\nLes graphiques créés par `tmap` ne peuvent malheureusement pas être combinés avec la fonction `ggarrange`, mais `tmap` dispose de sa propre fonction `tmap_arrange` si vous souhaitez combiner plusieurs cartes.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(tmap)\ncolors <- brewer.pal(7,\"Greens\")\ncolors2 <- brewer.pal(7,\"Reds\")\n\ncarte1 <- tm_shape(spatialdf) +\n tm_polygons(\"ArbPct\", palette = colors, border.alpha = 0,\n n = 7, \n\t\t\tstyle = \"quantile\",\n title = \"Densité de la canopée (%)\") +\n tm_scale_bar(breaks = c(0,5,10)) + \n tm_layout(attr.outside = TRUE, frame = FALSE)\n\ncarte2 <- tm_shape(spatialdf) +\n tm_polygons(\"LogDens\", palette = colors2, border.alpha = 0,\n n = 7, \n\t\t\tstyle = \"quantile\",\n title = \"Densité de logement\") + \n tm_scale_bar(breaks = c(0,5,10)) + \n tm_layout(attr.outside = TRUE, frame = FALSE)\n\ntmap_arrange(carte1, carte2, ncol = 2)\n```\n\n::: {.cell-output-display}\n![Combiner des cartes avec tmap](03-magiedesgraphiques_files/figure-html/fig-fig355-1.png){#fig-fig355 fig-align='center' width=85%}\n:::\n:::\n\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n\n**Construction de cartes : aller plus loin avec `tmap`...**\n:::\n\n::: bloc_aller_loin-body\nPour explorer les multitudes possibilités du *package* `tmap`, nous vous recommandons les ressources suivantes :\n\n- [La section intitulée *Cartographie avec R*](https://serieboldr.github.io/MethodesAnalyseSpatiale/01-ManipulationDonneesSpatiales.html#sec-016) du manuel [*Méthodes d’analyse spatiale : un grand bol d’R*](https://serieboldr.github.io/MethodesAnalyseSpatiale/).\n\n- L'excellente vignette intitulée [*`tmap`: get started!*](https://cran.r-project.org/web/packages/tmap/vignettes/tmap-getstarted.html)\n\n- [*Visualizing Spatial Data in R with tmap*](http://www.wvview.org/os_sa/10_Maps_with_tmap.html#visualizing-spatial-data-in-r-with-tmap).\n\n- [*Making Maps with R*](https://bookdown.org/nicohahn/making_maps_with_r5/docs/introduction.html).\n\n- Le chapitre [*Making maps with R*](https://geocompr.robinlovelace.net/adv-map.html) du livre [*Geocomputation with R*](https://geocompr.robinlovelace.net/index.html).\n:::\n:::\n\n\n\n## Exportation des graphiques {#sec-035}\n\nTous les graphiques que nous avons construits dans ce chapitre peuvent être exportés assez facilement. Dans RStudio, vous pouvez directement cliquer sur le bouton *Export* (@fig-fig356) pour enregistrer votre figure au format image ou au format *pdf* (vectoriel). Notez qu'avec la seconde option, vous pourrez retoucher votre graphique avec un logiciel externe comme *Inkscape* ou *Illustrator*.\n\n![Exporter un graphique dans RStudio](images/Chap03/export.jpg){#fig-fig356 width=\"40%\" fig-align=\"center\"}\n\nLorsque vous créez un graphique avec `ggplot2`, il est aussi possible de l'exporter avec la fonction `ggsave`. Cette fonctionnalité est très pratique lorsque vous souhaitez automatiser la production de graphiques et ne pas avoir à tous les exporter à la main.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndata(iris)\n\nplot1 <- ggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris)\n\nggsave(filename = 'graphique.pdf',\n path = 'mon/dossier',\n plot = plot1,\n width = 10, height = 10, units = \"cm\")\n```\n:::\n\nPour les graphiques n'étant pas réalisés avec `ggplot2`, la solution de remplacement à la fonction `ggsave` est l'ensemble de fonctions `png`, `bmp`, `jpeg`, `tiff` et `pdf`, qui permettent d'exporter n'importe quel graphique dans ces différents formats. Le processus comprend trois étapes : \n\n1. Ouvrir une connexion vers le fichier dans lequel le graphique sera exporté avec une des fonctions `png`, `bmp`, `jpeg`, `tiff` et `pdf`.\n\n2. Réaliser son graphique comme si nous souhaitions l'afficher dans RSudio. Il n'apparaîtra cependant pas, car il sera écrit dans le fichier en question à la place.\n\n3. Fermer la connexion au fichier avec la fonction `dev.off` pour définitivement enregistrer le graphique.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndata(iris)\n\n# 1. Ouvrir la connexion\npng(filename = 'mon/dossier/graphique.png')\n\n# 2. Afficher le graphique\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris)\n\n# 3. fermer la connexion\ndev.off()\n```\n:::\n\n\n## Conclusion sur les graphiques {#sec-036}\n\nVous avez pu constater que les capacités de représentation graphique de R sont vastes et pourtant nous n'avons qu'observé la partie émergée de l'iceberg dans ce chapitre. Il est également possible de réaliser une visualisation en 3D dans R (`plot3D`, `rgl`), d'animer des graphiques pour en faire des *GIF* ou des vidéos (`gganimate`), de rendre des graphiques interactifs, ou même de construire des plateformes de visualisation de données disponibles en ligne (`shiny`). Vous continuerez à découvrir de nouvelles formes de représentations au fur et à mesure de votre pratique, en apprenant de nouvelles méthodes nécessitant des visualisations spécifiques.\n\nVoici également deux références très utiles qui nous ont notamment aidé à construire ce chapitre : \n\n* [The R Graph Gallery](https://www.r-graph-gallery.com/){target=\"_blank\"}, probablement **LE** site web proposant le plus de matériel sur la réalisation des graphiques dans R.\n* [Data to viz](https://www.data-to-viz.com/){target=\"_blank\"}, si vous ne savez pas quel graphique pourrait le mieux correspondre à vos données, Data to viz est là pour vous aider. Vous y trouverez un arbre de décision pour vous indiquer quel graphique utiliser dans quelle situation, ainsi que de nombreux conseils sur la visualisation de données.\n", + "supporting": [ + "03-magiedesgraphiques_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": { + "include-in-header": [ + "\r\n\r\n\r\n\r\n\r\n\r\n" + ] + }, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-colorBrewer-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-colorBrewer-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-colorBrewer-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-colorBrewer-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig31-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig31-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig31-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig31-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig310-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig310-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig310-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig310-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig311-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig311-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig311-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig311-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig312-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig312-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig312-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig312-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig313-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig313-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig313-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig313-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig314-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig314-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig314-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig314-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig315-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig315-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig315-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig315-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig316-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig316-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig316-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig316-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig317-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig317-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig317-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig317-1.png diff --git a/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig318-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig318-1.png new file mode 100644 index 0000000..bfe33ce Binary files /dev/null and b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig318-1.png differ diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig32-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig32-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig32-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig32-1.png diff --git a/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig320-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig320-1.png new file mode 100644 index 0000000..3b4ffad Binary files /dev/null and b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig320-1.png differ diff --git a/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig321-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig321-1.png new file mode 100644 index 0000000..8ffaca8 Binary files /dev/null and b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig321-1.png differ diff --git a/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig322-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig322-1.png new file mode 100644 index 0000000..fc0047f Binary files /dev/null and b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig322-1.png differ diff --git a/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig323-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig323-1.png new file mode 100644 index 0000000..92e9a42 Binary files /dev/null and b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig323-1.png differ diff --git a/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig324-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig324-1.png new file mode 100644 index 0000000..5af1ad0 Binary files /dev/null and b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig324-1.png differ diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig325-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig325-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig325-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig325-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig326-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig326-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig326-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig326-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig328-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig328-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig328-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig328-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig329-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig329-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig329-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig329-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig33-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig33-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig33-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig33-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig330-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig330-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig330-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig330-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig331-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig331-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig331-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig331-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig332-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig332-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig332-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig332-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig333-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig333-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig333-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig333-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig334-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig334-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig334-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig334-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig335-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig335-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig335-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig335-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig336-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig336-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig336-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig336-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig337-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig337-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig337-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig337-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig338-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig338-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig338-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig338-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig339-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig339-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig339-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig339-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig34-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig34-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig34-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig34-1.png diff --git a/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig340-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig340-1.png new file mode 100644 index 0000000..ba575a8 Binary files /dev/null and b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig340-1.png differ diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig341-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig341-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig341-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig341-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig342-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig342-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig342-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig342-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig344-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig344-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig344-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig344-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig345-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig345-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig345-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig345-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig346-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig346-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig346-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig346-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig347-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig347-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig347-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig347-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig348-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig348-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig348-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig348-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig35-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig35-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig35-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig35-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig352-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig352-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig352-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig352-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig353-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig353-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig353-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig353-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig354-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig354-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig354-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig354-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig355-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig355-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig355-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig355-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig36-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig36-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig36-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig36-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig37-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig37-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig37-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig37-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig38-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig38-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig38-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig38-1.png diff --git a/docs/03-magiedesgraphiques_files/figure-html/fig-fig39-1.png b/.quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig39-1.png similarity index 100% rename from docs/03-magiedesgraphiques_files/figure-html/fig-fig39-1.png rename to .quarto/_freeze/03-magiedesgraphiques/figure-html/fig-fig39-1.png diff --git a/.quarto/_freeze/04-bivarieeQuantiQuanti/execute-results/html.json b/.quarto/_freeze/04-bivarieeQuantiQuanti/execute-results/html.json new file mode 100644 index 0000000..33f05b4 --- /dev/null +++ b/.quarto/_freeze/04-bivarieeQuantiQuanti/execute-results/html.json @@ -0,0 +1,16 @@ +{ + "hash": "f66025bbcfa3a25d920d34aeb04bf5d9", + "result": { + "markdown": "# Relation linéaire entre deux variables quantitatives {#sec-chap04}\n\nDans le cadre de ce chapitre, nous présentons les trois principales méthodes permettant d'explorer la relation linéaire entre deux variables quantitatives, soit la covariance, la corrélation et la régression linéaire simple.\n\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes quantiles-quantiles.\n* Pour manipuler des données : \n - `dplyr` notamment pour les fonctions `group_by`, `summarize` et les pipes %>%.\n* Pour les corrélations : \n - `boot` pour réaliser des corrélations avec *bootstrap*.\n - `correlation`, de l'ensemble de packages `easy_stats`, offrant une large panoplie de mesures de corrélation.\n - `corrplot` pour créer des graphiques de matrices de corrélation.\n - `Hmisc` pour calculer des corrélations de Pearson et Spearman.\n - `ppcor` pour calculer des corrélations partielles.\n - `psych` pour obtenir une matrice de corrélation (Pearson, Spearman et Kendall), les intervalles de confiance et les valeurs de *p*.\n - `stargazer` pour créer de beaux tableaux d’une matrice de corrélation en HTML, en LaTeX ou en ASCII.\n* Autres *packages* :\n - `foreign` pour importer des fichiers externes.\n - `MASS` pour générer des échantillons normalement distribués.\n - `stargazer` pour imprimer des tableaux.\n:::\n:::\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Deux variables continues varient-elles dans le même sens ou bien en sens contraire?**\n:::\n::: bloc_objectif-body\nRépondre à cette question est une démarche exploratoire classique en sciences sociales puisque les données socioéconomiques sont souvent associées linéairement. En d'autres termes, lorsque l'une des deux variables tant à augmenter, l'autre augmente également ou diminue systématiquement.\n\nEn études urbaines, nous pourrions vouloir vérifier si certaines variables socioéconomiques sont associées positivement ou négativement à des variables environnementales jugées positives (comme la couverture végétale ou des mesures d’accessibilité spatiale aux parcs) ou négatives (pollutions atmosphériques et sonores). \n\nPar exemple, au niveau des secteurs de recensement d’une ville canadienne, nous pourrions vouloir vérifier si le revenu médian des ménages et le coût moyen du loyer varient dans le même sens que la couverture végétale; ou encore s'ils varient en sens inverse des niveaux moyens de dioxyde d’azote ou de bruit routier.\n\nPour évaluer la linéarité entre deux variables continues, deux statistiques descriptives sont utilisées : la **covariance** ([section @sec-042]) et la **corrélation** ([section @sec-043]).\n:::\n:::\n\n\n## Bref retour sur le postulat de la relation linéaire {#sec-041}\n\nVérifier le postulat de la linéarité consiste à évaluer si deux variables quantitatives varient dans le même sens ou bien en sens contraire. Toutefois, la relation entre deux variables quantitatives n’est pas forcément linéaire. En guise d'illustration, la @fig-fig2 permet de distinguer quatre types de relations :\n\n* Le cas **a** illustre une relation linéaire positive entre les deux variables puisqu’elles vont dans le même sens. Autrement dit, quand les valeurs de *X* augmentent, celles de *Y* augmentent aussi. En guise d'exemple, pour les secteurs de recensement d'une métropole donnée, il est fort probable que le coût moyen du loyer soit associé positivement avec le revenu médian des ménages. Graphiquement parlant, il est clair qu'une droite dans ce nuage de points résumerait efficacement la relation entre ces deux variables.\n\n* Le cas **b** illustre une relation linéaire négative entre les deux variables puisqu’elles vont en sens inverse. Autrement dit, quand les valeurs de *X* augmentent, celles de *Y* diminuent, et inversement. En guise d'exemple, pour les secteurs de recensement d'une métropole donnée, il est fort probable que le revenu médian des ménages soit associé négativement avec le taux de chômage. De nouveau, une droite résumerait efficacement cette relation.\n\n* Pour le cas **c**, il y a une relation entre les deux variables, mais qui n’est pas linéaire. Le nuage de points entre les deux variables prend d’ailleurs une forme parabolique qui traduit une relation curvilinéaire. Concrètement, nous observons une relation positive jusqu'à un certain seuil, puis une relation négative. \n \n* Pour le cas **d**, la relation entre les deux variables est aussi curvilinéaire; d'abord négative, puis positive.\n\n\n![Relations linéaires et curvilinéaires entre deux variables continues](images/Chap04/LineaireCurvilineaire.jpg){#fig-fig2 width=\"85%\" fig-align=\"center\"}\n\nPrenons un exemple concret pour illustrer le cas **c**. Dans une étude portant sur l'équité environnementale et la végétation à Montréal, Pham *et al.* [-@PhamApparicioSeguin2012] ont montré qu'il existe une relation curvilinéaire entre l'âge médian des bâtiments résidentiels (axe des abscisses) et les couvertures végétales (axes des ordonnées) :\n\n* La couverture de la végétation totale et celle des arbres augmentent quand l'âge médian des bâtiments croît jusqu'à atteindre un pic autour de 60 ans (autour de 1950). Nous pouvons supposer que les secteurs récemment construits, surtout ceux dans les banlieues, présentent des niveaux de végétation plus faibles. Au fur et à mesure que le quartier vieillit, les arbres plantés lors du développement résidentiel deviennent matures — canopée plus importante –, d'où l'augmentation des valeurs de la couverture végétale totale et de celle des arbres.\n\n* Par contre, dans les secteurs développés avant les années 1950, la densité du bâti est plus forte, laissant ainsi moins de place pour la végétation, ce qui explique une diminution des variables relatives à la couverture végétale (@fig-fig3).\n\n\n![Exemples de relations curvilinéaires](images/Chap04/ExRelCurvi.jpg){#fig-fig3 width=\"65%\" fig-align=\"center\"}\n\nDans les sous-sections suivantes, nous décrivons deux statistiques descriptives et exploratoires – la covariance ([section @sec-042]) et la corrélation ([section @sec-043]) – utilisées pour évaluer la **relation linéaire** entre deux variables continues (cas **a** et **b** à la @fig-fig2). Ces deux mesures permettent de mesurer le degré d'association entre deux variables, sans que l'une soit la variable dépendante (variable à expliquer) et l'autre, la variable indépendante (variable explicative). Puis, nous décrivons la régression linéaire simple ([section @sec-044]) qui permet justement de prédire une variable dépendante (_Y_) à partir d'une variable indépendante (_X_).\n\n## Covariance {#sec-042}\n\n### Formulation {#sec-0421} \n\nLa covariance (@eq-cov), écrite $cov(x,y)$, est égale à la moyenne du produit des écarts des valeurs des deux variables par rapport à leurs moyennes respectives :\n\n\n$$\ncov(x,y) = \\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})(y_{i}-\\bar{y})}{n-1} = \\frac{covariation}{n-1}\n$$ {#eq-cov}\n\navec $n$ étant le nombre d’observations; $\\bar{x}$ et $\\bar{y}$ (prononcez x et y barre) étant les moyennes respectives des variables *X* et *Y*.\n\n### Interprétation {#sec-0422} \n\nLe numérateur de l'@eq-cov représente la covariation, soit la somme du produit des déviations des valeurs $x_{i}$ et $y_{i}$ par rapport à leurs moyennes respectives ($\\bar{x}$ et $\\bar{y}$). La covariance est donc la covariation divisée par le nombre d’observations, soit la moyenne de la covariation. Sa valeur peut être positive ou négative : \n\n* Positive quand les deux variables varient dans le même sens, c'est-à-dire lorsque les valeurs de la variable _X_ s'éloignent de la moyenne, les valeurs de _Y_ s'éloignent aussi dans le même sens; et elle est négative pour une situation inverse. \n\n* Quand la covariance est égale à 0, il n’y a pas de relation entre les variables _X_ et _Y_. Plus sa valeur absolue est élevée, plus la relation entre les deux variables *X* et *Y* est importante. \n \nAinsi, la covariance correspond à un centrage des variables, c’est-à-dire à soustraire à chaque valeur de la variable sa moyenne correspondante. L'inconvénient majeur de l'utilisation de la covariance est qu'elle est tributaire des unités de mesure des deux variables. Par exemple, si nous calculons la covariance entre le pourcentage de personnes à faible revenu et la densité de population (habitants au km^2^) au niveau des secteurs de recensement de la région métropolitaine de Montréal, nous obtenons une valeur de covariance de 33 625. En revanche, si la densité de population est exprimée en milliers d'habitants au km^2^, la valeur de la covariance sera de 33,625, alors que la relation linéaire entre les deux variables reste la même comme illustré à la @fig-covariance. Pour remédier à ce problème, nous privilégions l'utilisation du coefficient de corrélation.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Covariance et unités de mesure](04-bivarieeQuantiQuanti_files/figure-html/fig-covariance-1.png){#fig-covariance fig-align='center' width=75%}\n:::\n:::\n\n\n\n## Corrélation {#sec-043}\n\n### Formulation {#sec-0431} \nLe coefficient de corrélation de Pearson ($r$) est égal à la covariance (numérateur) divisée par le produit des écarts-types des deux variables *X* et *Y* (dénominateur). Il représente une standardisation de la covariance. Autrement dit, le coefficient de corrélation repose sur un centrage (moyenne = 0) et une réduction (variance = 1) des deux variables, c’est-à-dire qu'il faut soustraire de chaque valeur sa moyenne correspondante et la diviser par son écart-type. Il correspond ainsi à la moyenne du produit des deux variables centrées réduites. Il s'écrit alors :\n\n$$\nr_{xy} = \\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})(y_{i}-\\bar{y})}{(n-1)\\sqrt{\\sum_{i=1}^n(x_i - \\bar{x})^2(y_i - \\bar{y})^2}}=\\sum_{i=1}^n\\frac{Zx_iZy_i}{n-1}\n$$ {#eq-cor}\n\navec $n$ étant le nombre d’observations; $\\bar{x}$ et $\\bar{y}$ étant les moyennes respectives des variables *X* et *Y*.\n\nLa syntaxe ci-dessous démontre que le coefficient de corrélation de Pearson est bien égal à la moyenne du produit de deux variables centrées réduites.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"MASS\")\nN <- 1000 # nombre d'observations\nmoy_x <- 50 # moyenne de x\nmoy_y <- 40 # moyenne de y\nsd_x <- 10 # écart-type de x\nsd_y <- 8 # écart-type de y\nrxy <- .80 # corrélation entre X et Y\n## création de deux variables fictives normalement distribuées et corrélées entre elles\n# Création d'une matrice de covariance\ncov <- matrix(c(sd_x^2, rxy*sd_x*sd_y, rxy*sd_x*sd_y, sd_y^2), nrow = 2)\n# Création du tableau de données avec deux variables\ndf1 <- as.data.frame(mvrnorm(N, c(moy_x, moy_y), cov))\n# Centrage et réduction des deux variables\ndf1$zV1 <- scale(df1$V1, center = TRUE, scale = TRUE)\ndf1$zV2 <- scale(df1$V2, center = TRUE, scale = TRUE)\n# Corrélation de Pearson\ncor1 <- cor(df1$V1, df1$V2)\ncor2 <- sum(df1$zV1*df1$zV2) / (nrow(df1)-1)\ncat(\"Corrélation de Pearson = \", round(cor1,5),\n \"\\nMoyenne du produit des variables centrées réduites =\", round(cor2,5))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nCorrélation de Pearson = 0.78657 \nMoyenne du produit des variables centrées réduites = 0.78657\n```\n:::\n:::\n\n\n\n### Interprétation {#sec-0432} \n\nLe coefficient de corrélation $r$ varie de −1 à 1 avec :\n\n* 0 quand il n’y a pas de relation linéaire entre les variables _X_ et _Y_;\n* −1 quand il y a une relation linéaire négative parfaite;\n* 1 quand il y a une relation linéaire positive parfaite (@fig-coeffPearson). \n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Relations entre deux variables continues et coefficients de corrélation de Pearson](04-bivarieeQuantiQuanti_files/figure-html/fig-coeffPearson-1.png){#fig-coeffPearson fig-align='center' width=75%}\n:::\n:::\n\n\nConcrètement, le signe du coefficient de corrélation indique si la relation est positive ou négative et la valeur absolue du coefficient indique le degré d’association entre les deux variables. Reste à savoir comment déterminer qu’une valeur de corrélation est faible, moyenne ou forte. En sciences sociales, nous utilisons habituellement les intervalles de valeurs reportés au @tbl-tableIntervallesCorrelation. Toutefois, ces seuils sont tout à fait arbitraires. En effet, dépendamment de la discipline de recherche (sciences sociales, sciences de la santé, sciences physiques, etc.) et des variables à l’étude, l’interprétation d’une valeur de corrélation peut varier. Par exemple, en sciences sociales, une valeur de corrélation de 0,2 est considérée comme très faible alors qu’en sciences de la santé, elle pourrait être considérée comme intéressante. À l’opposé, une valeur de 0,9 en sciences physiques pourrait être considérée comme faible. Il convient alors d’utiliser ces intervalles avec précaution.\n\n\n::: {#tbl-tableIntervallesCorrelation .cell tbl-cap='Intervalles pour l’interprétation du coefficient de corrélation habituellement utilisés en sciences sociales'}\n::: {.cell-output-display}\n|Corrélation |Négative |Positive |\n|:-----------|:--------------|:------------|\n|Faible |de −0,3 à 0,0 |de 0,0 à 0,3 |\n|Moyenne |de −0,5 à −0,3 |de 0,3 à 0,5 |\n|Forte |de −1,0 à −0,5 |de 0,5 à 1,0 |\n:::\n:::\n\n\nLe coefficient de corrélation mis au carré représente le coefficient de détermination et indique la proportion de la variance de la variable _Y_ expliquée par la variable _X_ et inversement. Par exemple, un coefficient de corrélation de −0,70 signale que 49 % de la variance de la variable de _Y_ est expliquée par _X_ (@fig-coefCorrVar).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Coefficient de corrélation et proportion de la variance expliquée](04-bivarieeQuantiQuanti_files/figure-html/fig-coefCorrVar-1.png){#fig-coefCorrVar fig-align='center' width=75%}\n:::\n:::\n\n\n**Condition d'application.** L'utilisation du coefficient de corrélation de Pearson nécessite que les deux variables continues soient normalement distribuées et qu'elles ne comprennent pas de valeurs aberrantes ou extrêmes. D’ailleurs, plus le nombre d’observations est réduit, plus la présence de valeurs extrêmes a une répercussion importante sur le résultat du coefficient de corrélation de Pearson. En guise d’exemple, dans le nuage de points à gauche de la @fig-ValExtremes, il est possible d’identifier des valeurs extrêmes qui se démarquent nettement dans le jeu de données : six observations avec une densité de population supérieure à 20 000 habitants au km^2^ et deux observations avec un pourcentage de 65 ans et plus supérieur à 55 %. Si l'on supprime ces observations (ce qui est défendable dans ce contexte) – soit moins d'un pour cent des observations du jeu de données initial –, la valeur du coefficient de corrélation passe de −0,158 à −0,194, signalant une augmentation du degré d'association entre les deux variables.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Illustation de l’effet des valeurs extrêmes sur le coefficient de Pearson](04-bivarieeQuantiQuanti_files/figure-html/fig-ValExtremes-1.png){#fig-ValExtremes fig-align='center' width=75%}\n:::\n:::\n\n\n\n### Corrélations pour des variables anormalement distribuées (coefficient de Spearman, tau de Kendall) {#sec-0433} \n\nLorsque les variables sont fortement anormalement distribuées, le coefficient de corrélation de Pearson est peu adapté pour analyser leurs relations linéaires. Il est alors conseillé d'utiliser deux statistiques non paramétriques : principalement, le coefficient de corrélation de Spearman (_rho_) et secondairement, le tau ($\\tau$) de Kendall, qui varient aussi tous deux de −1 à 1. \nCalculé sur les rangs des deux variables, le **coefficient de Spearman** est le rapport entre la covariance des deux variables de rangs sur les écarts-types des variables de rangs. En d'autres termes, il représente simplement le coefficient de Pearson calculé sur les rangs des deux variables :\n\n$$\nr_{xy} = \\frac{cov(rg_{x}, rg_{y})}{\\sigma_{rg_{x}}\\sigma_{rg_{y}}}\n$$ {#eq-spearman}\n\nLa syntaxe ci-dessous démontre clairement que le coefficient de Spearman est bien le coefficient de Pearson calculé sur les rangs ([section @sec-0431]).\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\n# Transformation des deux variables en rangs\ndf$HabKm2_rang <- rank(df$HabKm2)\ndf$A65plus_rang <- rank(df$A65plus)\n# Coefficient de Spearman avec la fonction cor et la méthode spearman\ncat(\"Coefficient de Spearman = \", \n round(cor(df$HabKm2, df$A65plus, method = \"spearman\"),5))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nCoefficient de Spearman = -0.11953\n```\n:::\n\n```{.r .cell-code}\n# Coefficient de Pearson sur les variables transformées en rangs\ncat(\"Coefficient de Pearson calculé sur les variables transformées en rangs = \", \n round(cor(df$HabKm2_rang, df$A65plus_rang, method = \"pearson\"),5))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nCoefficient de Pearson calculé sur les variables transformées en rangs = -0.11953\n```\n:::\n\n```{.r .cell-code}\n# Vérification avec l'équation\ncat(\"Covariance divisée par le produit des écarts-types sur les rangs :\",\n round(cov(df$HabKm2_rang, df$A65plus_rang) / (sd(df$HabKm2_rang)*sd(df$A65plus_rang)),5))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nCovariance divisée par le produit des écarts-types sur les rangs : -0.11953\n```\n:::\n:::\n\n\nLe **tau de Kendall** est une autre mesure non paramétrique calculée comme suit :\n\n$$\n\\tau = \\frac{n_{c}-n_{d}}{\\frac{1}{2}n(n-1)}\n$$ {#eq-tau}\n\navec $n_{c}$ et $n_{d}$ qui sont respectivement les nombres de paires d'observations **c**oncordantes et **d**iscordantes; et le dénominateur étant le nombre total de paires d'observations. Des paires sont dites concordantes quand les valeurs des deux observations vont dans le même sens pour les deux variables ($x_{i}>x_{j}$ et $y_{i}>y_{j}$ ou $x_{i}x_{j}$ et $y_{i}y_{j}$). Contrairement au calcul du coefficient de Spearman, celui du tau Kendall peut être chronophage : plus le nombre d'observations est élevé, plus les temps de calcul et la mémoire utilisée sont importants. En effet, avec _n_ = 1000, le nombre de paires d'observations (${\\mbox{0,5}\\times n(n-1)}$) est de 499 500, contre près de 50 millions avec _n_ = 10 000 (49 995 000).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Comparaison des coefficients de Pearson, Spearman et Kendall sur deux variables anormalement distribuées](04-bivarieeQuantiQuanti_files/figure-html/fig-PearsonSpearmanKendall-1.png){#fig-PearsonSpearmanKendall fig-align='center' width=75%}\n:::\n:::\n\n\nÀ la lecture des deux histogrammes à la @fig-PearsonSpearmanKendall, il est clair que les variables *densité de population* et *pourcentage de personnes ayant 65 ou plus* sont très anormalement distribuées. Dans ce contexte, l'utilisation du coefficient de Pearson peut nous amener à mésestimer la relation existant entre les deux variables. Notez que les coefficients de Spearman et de Kendall sont tous les deux plus faibles.\n\n### Corrélations robustes (*Biweight midcorrelation*, *Percentage bend correlation* et la corrélation *pi* de Shepherd) {#sec-0434}\n\nDans l'exemple donné à la @fig-ValExtremes, nous avions identifié des valeurs extrêmes et les avons retiré du jeu de données. Cette pratique peut tout à fait se justifier quand les données sont erronées (un capteur de pollution renvoyant une valeur négative, un questionnaire rempli par un mauvais plaisantin, etc.), mais parfois les cas extrêmes font partie du phénomène à analyser. Dans ce contexte, les identifier et les retirer peut paraître arbitraire. Une solution plus élégante est d'utiliser des méthodes dites **robustes**, c'est-à-dire moins sensibles aux valeurs extrêmes. Pour les corrélations, la *Biweight midcorrelation* [@wilcox1994percentage] est au coefficient de Pearson ce que la médiane est à la moyenne. Il est donc pertinent de l'utiliser pour des jeux de données présentant potentiellement des valeurs extrêmes. Elle est calculée comme suit : \n\n$$\n\\begin{aligned}\n&u_{i} = \\frac{x_{i} - med(x)}{9 \\times (med(|x_{i} - med(x)|))} \\text{ et } v_{i} = \\frac{y_{i} - med(y)}{9 \\times (med(|y_{i} - med(y)|))}\\\\\n&w_{i}^{(x)} = (1 - u_{i}^2)^2 I(1 - |u_{i}|) \\text{ et } w_{i}^{(y)} = (1 - v_{i}^2)^2 I(1 - |v_{i}|)\\\\\n&I(x) = \n\\begin{cases}\n1, \\text{si } x = 1\\\\\n0, \\text{sinon}\n\\end{cases}\\\\\n&\\tilde{x}_{i} = \\frac{(x_{i} - med(x))w_{i}^{(x)}}{\\sqrt{(\\sum_{j=1}^m)[(x_{j} - med(x))w_{j}^{(x)}]^2}} \\text{ et } \\tilde{y}_{i} = \\frac{(y_{i} - med(y))w_{i}^{(y)}}{\\sqrt{(\\sum_{j=1}^m)[(y_{j} - med(y))w_{j}^{(y)}]^2}}\\\\\n&bicor(x,y) = \\sum_{i=1}^m \\tilde{x_i}\\tilde{y_i}\n\\end{aligned}\n$$ {#eq-bicor}\n\n\nComme le souligne l'@eq-bicor, la *Biweight midcorrelation* est basée sur les écarts à la médiane, plutôt que sur les écarts à la moyenne.\n\nAssez proche de la *Biweight midcorrelation*, la *Percentage bend correlation* se base également sur la médiane des variables *X* et *Y*. Le principe général est de donner un poids plus faible dans le calcul de cette corrélation à un certain pourcentage des observations (20 % sont généralement recommandés) dont la valeur est éloignée de la médiane. Pour une description complète de la méthode, vous pouvez lire l'article de @wilcox1994percentage.\n\nEnfin, une autre option est l'utilisation de la corrélation $pi$ de Sherphred [@Schwarzkopf2012]. Il s'agit simplement d'une méthode en deux étapes. Premièrement, les valeurs extrêmes sont identifiées à l'aide d'une approche par *bootstrap* utilisant la distance de Mahalanobis (calculant les écarts multivariés entre les observations). Deuxièmement, le coefficient de *Spearman* est calculé sur les observations restantes.\n\nAppliquons ces corrélations aux données précédentes. Notez que ce simple code d'une dizaine de lignes permet d'explorer rapidement la corrélation entre deux variables selon six mesures de corrélation.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"correlation\")\ndf1 <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\nmethods <- c(\"Pearson\" , \"Spearman\" , \"Biweight\" , \"Percentage\" , \"Shepherd\")\nrs <- lapply(methods, function(m){\n test <- correlation::cor_test(data = df1, x = \"Hab1000Km2\", y = \"A65plus\", method = m, ci=0.95)\n return(c(test$r, test$CI_low, test$CI_high))\n })\ndfCorr <- data.frame(do.call(rbind, rs))\nnames(dfCorr) <- c(\"r\" , \"IC_2.5\" , \"IC_97.5\")\ndfCorr$method <- methods\n\n# Impression du tableau avec le package stargazer\nlibrary(stargazer)\nstargazer(dfCorr, type = \"text\", summary = FALSE, rownames = FALSE, align = FALSE, digits = 3,\n title = \"Comparaison de différentes corrélations pour les deux variables\")\n```\n:::\n\n::: {#tbl-robcorr .cell tbl-cap='Comparaison de différentes corrélations pour les deux variables'}\n::: {.cell-output-display}\n| r| IC 2,5 %| IC 97,5 %|Méthode |\n|------:|--------:|---------:|:----------|\n| -0.158| -0.219| -0.095|Pearson |\n| -0.120| -0.184| -0.055|Spearman |\n| -0.137| -0.199| -0.074|Biweight |\n| -0.174| -0.235| -0.111|Percentage |\n| -0.121| -0.187| -0.054|Shepherd |\n:::\n:::\n\n\nIl est intéressant de mentionner que ces trois corrélations sont rarement utilisées malgré leur pertinence dans de nombreux cas d'application. Nous faisons face ici à un cercle vicieux dans la recherche : les méthodes les plus connues sont les plus utilisées, car elles sont plus facilement acceptées par la communauté scientifique. Des méthodes plus élaborées nécessitent davantage de justification et de discussion, ce qui peut conduire à de multiples sessions de corrections/resoumissions pour qu'un article soit accepté, malgré le fait qu'elles puissent être plus adaptées au jeu de données à l'étude.\n\n### Significativité des coefficients de corrélation {#sec-0435} \n\nQuelle que soit la méthode utilisée, il convient de vérifier si le coefficient de corrélation est ou non statistiquement différent de 0. En effet, nous travaillons la plupart du temps avec des données d'échantillonnage, et très rarement avec des populations complètes. En collectant un nouvel échantillon, aurions-nous obtenu des résultats différents? Le calcul de ce degré de significativité permet de quantifier le niveau de certitude quant à l'existence d'une corrélation entre les deux variables, positive ou négative. Cet objectif est réalisé en calculant la valeur de _t_ et le nombre de degrés de liberté : $t=\\sqrt{\\frac{n-2}{1-r^2}}$ et $dl = n-2$ avec $r$ et $n$ étant respectivement le coefficient de corrélation et le nombre d'observations. De manière classique, nous utiliserons la table des valeurs critiques de la distribution de $t$ : si la valeur de $t$ est supérieure à la valeur critique (avec _p_ = 0,05 et le nombre de degrés de liberté), alors le coefficient est significatif à 5 %. En d'autres termes, si la vraie corrélation entre les deux variables (calculable uniquement à partir des populations complètes) était 0, alors la probabilité de collecter notre échantillon serait inférieure à 5 %. Dans ce contexte, nous pouvons raisonnablement rejeter l'hypothèse nulle (corrélation de 0). \n\nLa courte syntaxe ci-dessous illustre comment calculer la valeur de $t$, le nombre de degrés de liberté et la valeur de _p_ pour une corrélation donnée.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\nr <- cor(df$A65plus, df$LogTailInc) # Corrélation\nn <- nrow(df) # Nombre d'observations\ndl <- nrow(df)-2 # degrés de liberté\nt <- r*sqrt((n-2)/(1-r^2)) # Valeur de T\np <- 2*(1-pt(abs(t), dl)) # Valeur de p\ncat(\"\\nCorrélation =\", round(r, 4), \n \"\\nValeur de t =\", round(t, 4),\n \"\\nDegrés de liberté =\", dl,\n \"\\np = \", round(p, 4)) \n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCorrélation = -0.0693 \nValeur de t = -2.1413 \nDegrés de liberté = 949 \np = 0.0325\n```\n:::\n:::\n\n\nPlus simplement, la fonction `cor.test` permet d'obtenir en une seule ligne de code le coefficient de corrélation, l'intervalle de confiance à 95 % et les valeurs de _t_ et de _p_, comme illustré dans la syntaxe ci-dessous. Si l'intervalle de confiance est à cheval sur 0, c'est-à-dire que la borne inférieure est négative et la borne supérieure positive, alors le coefficient de corrélation n'est pas significatif au seuil choisi (95 % habituellement). Dans l'exemple ci-dessous, la relation linéaire entre les deux variables est significativement négative avec une corrélation de Pearson de −0,158 (*p* = 0,000) et un intervalle de confiance à 95 % de −0,219 à −0,095.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Intervalle de confiance à 95 %\ncor.test(df$HabKm2, df$A65plus, conf.level = .95)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tPearson's product-moment correlation\n\ndata: df$HabKm2 and df$A65plus\nt = -4.9318, df = 949, p-value = 9.616e-07\nalternative hypothesis: true correlation is not equal to 0\n95 percent confidence interval:\n -0.2194457 -0.0954687\nsample estimates:\n cor \n-0.1580801 \n```\n:::\n\n```{.r .cell-code}\n# Vous pouvez accéder à chaque sortie de la fonction cor.test comme suit :\np <- cor.test(df$HabKm2, df$A65plus)\ncat(\"Valeur de corrélation = \", round(p$estimate,3), \"\\n\",\n \"Intervalle à 95 % = [\", round(p$conf.int[1],3), \" \", round(p$conf.int[2],3), \"]\", \"\\n\",\n \"Valeur de t = \", round(p$statistic,3), \"\\n\",\n \"Valeur de p = \", round(p$p.value,3),\"\\n\", sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nValeur de corrélation = -0.158\nIntervalle à 95 % = [-0.219 -0.095]\nValeur de t = -4.932\nValeur de p = 0\n```\n:::\n\n```{.r .cell-code}\n# Corrélation de Spearman\ncor.test(df$HabKm2, df$A65plus, method = \"spearman\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tSpearman's rank correlation rho\n\ndata: df$HabKm2 and df$A65plus\nS = 160482182, p-value = 0.0002202\nalternative hypothesis: true rho is not equal to 0\nsample estimates:\n rho \n-0.1195333 \n```\n:::\n\n```{.r .cell-code}\n# Corrélation de Kendall\ncor.test(df$HabKm2, df$A65plus, method = \"kendall\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tKendall's rank correlation tau\n\ndata: df$HabKm2 and df$A65plus\nz = -3.7655, p-value = 0.0001662\nalternative hypothesis: true tau is not equal to 0\nsample estimates:\n tau \n-0.08157061 \n```\n:::\n:::\n\n\nOn pourra aussi modifier l'intervalle de confiance, par exemple à 90 % ou 99 %. L'intervalle de confiance et le seuil de significativité doivent être définis avant l'étude. Leur choix doit s'appuyer sur les standards de la littérature du domaine étudié, du niveau de preuve attendu et de la quantité de données.\n\n::: {.cell}\n\n```{.r .cell-code}\n# Intervalle à 90 %\ncor.test(df$HabKm2, df$A65plus, method = \"pearson\", conf.level = .90)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tPearson's product-moment correlation\n\ndata: df$HabKm2 and df$A65plus\nt = -4.9318, df = 949, p-value = 9.616e-07\nalternative hypothesis: true correlation is not equal to 0\n90 percent confidence interval:\n -0.2096826 -0.1055995\nsample estimates:\n cor \n-0.1580801 \n```\n:::\n\n```{.r .cell-code}\n# Intervalle à 99 %\ncor.test(df$HabKm2, df$A65plus, method = \"pearson\", conf.level = .99)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tPearson's product-moment correlation\n\ndata: df$HabKm2 and df$A65plus\nt = -4.9318, df = 949, p-value = 9.616e-07\nalternative hypothesis: true correlation is not equal to 0\n99 percent confidence interval:\n -0.23839910 -0.07561336\nsample estimates:\n cor \n-0.1580801 \n```\n:::\n:::\n\n\n**Corrélation et _bootstrap_.** Il est possible d'estimer la corrélation en mobilisant la notion de _bootstrap_, soit des méthodes d'inférence statistique basées sur des réplications des données initiales par rééchantillonnage. Concrètement, la méthode du _bootstrap_ permet une mesure de la corrélation avec un intervalle de confiance à partir de _r_ réplications, comme illustré à partir de la syntaxe ci-dessous.\n\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(\"boot\")\ndf <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\n# Fonction pour la corrélation\ncorrelation <- function(df, i, X, Y, cor.type = \"pearson\"){\n # Paramètres de la fonction :\n # data : DataFrame\n # X et Y : noms des variables X et Y\n # cor.type : type de corrélation : c(\"pearson\" , \"spearman\" , \"kendall\")\n # i : indice qui sera utilisé par les réplications (à ne pas modifier)\n cor(df[[X]][i], df[[Y]][i], method=cor.type)\n}\n# Calcul du Bootstrap avec 5000 réplications\ncorBootstraped <- boot(data = df, # nom du tableau\n statistic = correlation, # appel de la fonction à répliquer \n R = 5000, # nombre de réplications\n X = \"A65plus\",\n Y = \"HabKm2\", \n cor.type = \"pearson\")\n# Histogramme pour les valeurs de corrélation issues du Bootstrap\nplot(corBootstraped)\n# Corrélation \"bootstrapée\"\ncorBootstraped\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nORDINARY NONPARAMETRIC BOOTSTRAP\n\n\nCall:\nboot(data = df, statistic = correlation, R = 5000, X = \"A65plus\", \n Y = \"HabKm2\", cor.type = \"pearson\")\n\n\nBootstrap Statistics :\n original bias std. error\nt1* -0.1580801 -0.0006694822 0.04048709\n```\n:::\n\n```{.r .cell-code}\n# Intervalle de confiance du bootstrap à 95 %\nboot.ci(boot.out = corBootstraped, conf = 0.95, type = \"all\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nBOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS\nBased on 5000 bootstrap replicates\n\nCALL : \nboot.ci(boot.out = corBootstraped, conf = 0.95, type = \"all\")\n\nIntervals : \nLevel Normal Basic \n95% (-0.2368, -0.0781 ) (-0.2407, -0.0839 ) \n\nLevel Percentile BCa \n95% (-0.2322, -0.0755 ) (-0.2209, -0.0531 ) \nCalculations and Intervals on Original Scale\n```\n:::\n\n```{.r .cell-code}\n# Comparaison de l'intervalle classique basé sur la valeur de T\np <- cor.test(df$HabKm2, df$A65plus)\ncat(round(p$estimate,5), \" [\", round(p$conf.int[1],4), \" \", round(p$conf.int[2],4), \"]\", sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n-0.15808 [-0.2194 -0.0955]\n```\n:::\n\n::: {.cell-output-display}\n![Histogramme pour les valeurs de corrélation issues du Bootstrap](04-bivarieeQuantiQuanti_files/figure-html/fig-fig9-1.png){#fig-fig9 fig-align='center' width=75%}\n:::\n:::\n\n\nLe _bootstrap_ renvoie un coefficient de corrélation de Pearson de −0,158. Les intervalles de confiance obtenus à partir des différentes méthodes d'estimation (normale, basique, pourcentage et BCa) ne sont pas à cheval sur 0, indiquant que le coefficient est significatif à 5 %.\n\n### Corrélation partielle {#sec-0436} \n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Relation entre deux variables une fois prise en compte une autre variable dite de contrôle**\n:::\n::: bloc_objectif-body\nLa corrélation partielle permet d'évaluer la relation linéaire entre deux variables quantitatives continues, après avoir contrôlé une ou plusieurs autres variables quantitatives (dites variables de contrôle).\n\nEn études urbaines, nous pourrions vouloir vérifier si deux variables sont ou non associées après avoir contrôlé la densité de population ou encore la distance au centre-ville.\n:::\n:::\n\n\nLe coefficient de corrélation partielle peut être calculé pour plusieurs mesures de corrélation (notamment, Pearson, Spearman et Kendall). Variant aussi de −1 à 1, il est calculé comme suit :\n\n$$\nr_{ABC} = \\frac{r_{AB}-r_{AC}r_{BC}}{\\sqrt{(1-r_{AC}^2)(1-r_{BC}^2)}}\n$$ {#eq-corpartielle}\n\navec _A_ et _B_ étant les deux variables pour lesquelles nous souhaitons évaluer la relation linéaire, une fois contrôlée la variable _C_; $r$ étant le coefficient de corrélation (Pearson, Spearman ou Kendall) entre deux variables.\n\nDans l'exemple ci-dessous, nous voulons estimer la relation linéaire entre le pourcentage de personnes à faible revenu et la couverture végétale au niveau des îlots de l'île de Montréal, une fois contrôlée la densité de population. En effet, plus cette dernière est forte, plus la couverture végétale est faible ($r$ de Pearson = −0,563). La valeur du $r$ de Pearson s'élève à −0,513 entre le pourcentage de personnes à faible revenu dans la population totale de l'îlot et la couverture végétale. Une fois la densité de population contrôlée, elle chute à −0,316. Pour calculer la corrélation partielle, nous pouvons utiliser la fonction `pcor.test` du package `ppcor`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"foreign\")\nlibrary(\"ppcor\")\ndfveg <- read.dbf(\"data/bivariee/IlotsVeg2006.dbf\")\n# Corrélation entre les trois variables\nround(cor(dfveg[, c(\"VegPct\", \"Pct_FR\" , \"LogDens\")], method = \"p\"), 3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n VegPct Pct_FR LogDens\nVegPct 1.000 -0.513 -0.563\nPct_FR -0.513 1.000 0.513\nLogDens -0.563 0.513 1.000\n```\n:::\n\n```{.r .cell-code}\n# Corrélation partielle avec la fonction pcor.test entre :\n# la couverture végétale de l'îlot (%) et\n# le pourcentage de personnes à faible revenu\n# une fois contrôlée la densité de population\npcor.test(dfveg$Pct_FR, dfveg$VegPct, dfveg$LogDens, method = \"p\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n estimate p.value statistic n gp Method\n1 -0.3155194 8.093159e-235 -33.59772 10213 1 pearson\n```\n:::\n\n```{.r .cell-code}\n# Calcul de la corrélation partielle avec la formule\ncorAB <- cor(dfveg$VegPct, dfveg$Pct_FR, method = \"p\")\ncorAC <- cor(dfveg$VegPct, dfveg$LogDens, method = \"p\")\ncorBC <- cor(dfveg$Pct_FR, dfveg$LogDens, method = \"p\")\nCorP <- (corAB - (corAC*corBC)) / sqrt((1-corAC^2)*(1-corBC^2))\ncat(\"Corr. partielle avec ppcor = \", \n round(pcor.test(dfveg$Pct_FR, dfveg$VegPct, dfveg$LogDens, method=\"p\")$estimate,5),\n \"\\nCorr. partielle (formule) = \", round(CorP, 5))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nCorr. partielle avec ppcor = -0.31552 \nCorr. partielle (formule) = -0.31552\n```\n:::\n:::\n\n\n### Mise en œuvre dans R {#sec-0437}\n\nComme vous l'aurez compris, il est possible d'arriver au même résultat par différents moyens. Pour calculer les corrélations, nous avons utilisé jusqu'à présent les fonctions de base `cor` et `cor.test`. Il est aussi possible de recourir à des fonctions d'autres _packages_, dont notamment :\n\n* `Hmisc`, dont la fonction `rcorr` permet de calculer des corrélations de Pearson et de Spearman (mais non celle de Kendall) avec les valeurs de _p_.\n\n* `psych`, dont la fonction `corr.test` permet d'obtenir une matrice de corrélation (Pearson, Spearman et Kendall), les intervalles de confiance et les valeurs de _p_.\n\n* `stargazer` pour créer de beaux tableaux d'une matrice de corrélation en *HTML*, en *LaTeX* ou en ASCII.\n\n* `apaTables` pour créer un tableau avec une matrice de corrélation dans un fichier Word.\n\n* `correlation` pour aller plus loin et explorer les corrélations bayésiennes, robustes, non linéaires ou multiniveaux.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf1 <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\nlibrary(\"Hmisc\")\nlibrary(\"stargazer\")\nlibrary(\"apaTables\")\nlibrary(\"dplyr\")\n# Corrélations de Pearson et Spearman et valeurs de p \n# avec la fonction rcorr de Hmisc pour deux variables\nHmisc::rcorr(df1$RevMedMen, df1$Locataire, type = \"pearson\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n x y\nx 1.00 -0.78\ny -0.78 1.00\n\nn= 951 \n\n\nP\n x y \nx 0\ny 0 \n```\n:::\n\n```{.r .cell-code}\nHmisc::rcorr(df1$RevMedMen, df1$Locataire, type = \"spearman\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n x y\nx 1.00 -0.91\ny -0.91 1.00\n\nn= 951 \n\n\nP\n x y \nx 0\ny 0 \n```\n:::\n\n```{.r .cell-code}\n# Matrice de corrélation avec la fonction rcorr de Hmisc pour plus de variables\n# Nous créons au préalable un vecteur avec les noms des variables à sélectionner\nVars <- c(\"RevMedMen\" , \"Locataire\", \"LogTailInc\" , \"A65plus\" , \"ImgRec\", \"HabKm2\", \"FaibleRev\")\nHmisc::rcorr(df1[, Vars] %>% as.matrix())\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n RevMedMen Locataire LogTailInc A65plus ImgRec HabKm2 FaibleRev\nRevMedMen 1.00 -0.78 -0.46 -0.07 -0.46 -0.49 -0.74\nLocataire -0.78 1.00 0.56 0.00 0.64 0.71 0.88\nLogTailInc -0.46 0.56 1.00 -0.07 0.82 0.48 0.62\nA65plus -0.07 0.00 -0.07 1.00 -0.06 -0.16 -0.01\nImgRec -0.46 0.64 0.82 -0.06 1.00 0.56 0.68\nHabKm2 -0.49 0.71 0.48 -0.16 0.56 1.00 0.64\nFaibleRev -0.74 0.88 0.62 -0.01 0.68 0.64 1.00\n\nn= 951 \n\n\nP\n RevMedMen Locataire LogTailInc A65plus ImgRec HabKm2 FaibleRev\nRevMedMen 0.0000 0.0000 0.0441 0.0000 0.0000 0.0000 \nLocataire 0.0000 0.0000 0.9594 0.0000 0.0000 0.0000 \nLogTailInc 0.0000 0.0000 0.0325 0.0000 0.0000 0.0000 \nA65plus 0.0441 0.9594 0.0325 0.0682 0.0000 0.6796 \nImgRec 0.0000 0.0000 0.0000 0.0682 0.0000 0.0000 \nHabKm2 0.0000 0.0000 0.0000 0.0000 0.0000 0.0000 \nFaibleRev 0.0000 0.0000 0.0000 0.6796 0.0000 0.0000 \n```\n:::\n\n```{.r .cell-code}\n# Avec la fonction corr.test du package psych pour avoir la matrice de corrélation\n# (Pearson, Spearman et Kendall), les intervalles de confiance et les valeurs de p\nprint(psych::corr.test(df[, Vars], \n method = \"kendall\", \n ci = TRUE, alpha = 0.05), short = FALSE) \n```\n\n::: {.cell-output .cell-output-stdout}\n```\nCall:psych::corr.test(x = df[, Vars], method = \"kendall\", alpha = 0.05, \n ci = TRUE)\nCorrelation matrix \n RevMedMen Locataire LogTailInc A65plus ImgRec HabKm2 FaibleRev\nRevMedMen 1.00 -0.74 -0.43 -0.03 -0.41 -0.45 -0.79\nLocataire -0.74 1.00 0.45 -0.03 0.47 0.56 0.75\nLogTailInc -0.43 0.45 1.00 -0.01 0.59 0.41 0.51\nA65plus -0.03 -0.03 -0.01 1.00 -0.02 -0.08 0.01\nImgRec -0.41 0.47 0.59 -0.02 1.00 0.50 0.52\nHabKm2 -0.45 0.56 0.41 -0.08 0.50 1.00 0.50\nFaibleRev -0.79 0.75 0.51 0.01 0.52 0.50 1.00\nSample Size \n[1] 951\nProbability values (Entries above the diagonal are adjusted for multiple tests.) \n RevMedMen Locataire LogTailInc A65plus ImgRec HabKm2 FaibleRev\nRevMedMen 0.0 0.00 0.0 1.00 0 0.00 0\nLocataire 0.0 0.00 0.0 1.00 0 0.00 0\nLogTailInc 0.0 0.00 0.0 1.00 0 0.00 0\nA65plus 0.4 0.37 0.7 0.00 1 0.07 1\nImgRec 0.0 0.00 0.0 0.58 0 0.00 0\nHabKm2 0.0 0.00 0.0 0.01 0 0.00 0\nFaibleRev 0.0 0.00 0.0 0.77 0 0.00 0\n\n Confidence intervals based upon normal theory. To get bootstrapped values, try cor.ci\n raw.lower raw.r raw.upper raw.p lower.adj upper.adj\nRvMdM-Loctr -0.77 -0.74 -0.71 0.00 -0.78 -0.69\nRvMdM-LgTlI -0.49 -0.43 -0.38 0.00 -0.51 -0.36\nRvMdM-A65pl -0.09 -0.03 0.04 0.40 -0.11 0.05\nRvMdM-ImgRc -0.46 -0.41 -0.35 0.00 -0.48 -0.33\nRvMdM-HbKm2 -0.50 -0.45 -0.39 0.00 -0.52 -0.37\nRvMdM-FblRv -0.81 -0.79 -0.76 0.00 -0.82 -0.75\nLoctr-LgTlI 0.40 0.45 0.50 0.00 0.38 0.52\nLoctr-A65pl -0.09 -0.03 0.03 0.37 -0.11 0.05\nLoctr-ImgRc 0.42 0.47 0.52 0.00 0.39 0.54\nLoctr-HbKm2 0.51 0.56 0.60 0.00 0.49 0.62\nLoctr-FblRv 0.72 0.75 0.78 0.00 0.71 0.79\nLgTlI-A65pl -0.08 -0.01 0.05 0.70 -0.09 0.06\nLgTlI-ImgRc 0.54 0.59 0.63 0.00 0.52 0.65\nLgTlI-HbKm2 0.36 0.41 0.46 0.00 0.34 0.48\nLgTlI-FblRv 0.46 0.51 0.56 0.00 0.44 0.58\nA65pl-ImgRc -0.08 -0.02 0.05 0.58 -0.10 0.06\nA65pl-HbKm2 -0.14 -0.08 -0.02 0.01 -0.17 0.00\nA65pl-FblRv -0.05 0.01 0.07 0.77 -0.05 0.07\nImgRc-HbKm2 0.46 0.50 0.55 0.00 0.43 0.57\nImgRc-FblRv 0.47 0.52 0.57 0.00 0.45 0.59\nHbKm2-FblRv 0.46 0.50 0.55 0.00 0.43 0.57\n```\n:::\n\n```{.r .cell-code}\n# Création d'un tableau pour une matrice de corrélation\n# changer le paramètre type pour 'html' or 'latex' si souhaité\np <- cor(df1[, Vars], method=\"pearson\")\nstargazer(p, title = \"Correlation Matrix\", type = \"text\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCorrelation Matrix\n=========================================================================\n RevMedMen Locataire LogTailInc A65plus ImgRec HabKm2 FaibleRev\n-------------------------------------------------------------------------\nRevMedMen 1 -0.785 -0.461 -0.065 -0.458 -0.489 -0.743 \nLocataire -0.785 1 0.562 -0.002 0.645 0.708 0.879 \nLogTailInc -0.461 0.562 1 -0.069 0.816 0.475 0.622 \nA65plus -0.065 -0.002 -0.069 1 -0.059 -0.158 -0.013 \nImgRec -0.458 0.645 0.816 -0.059 1 0.561 0.678 \nHabKm2 -0.489 0.708 0.475 -0.158 0.561 1 0.642 \nFaibleRev -0.743 0.879 0.622 -0.013 0.678 0.642 1 \n-------------------------------------------------------------------------\n```\n:::\n\n```{.r .cell-code}\n# Créer un tableau avec la matrice de corrélation \n# dans un fichier Word (.doc)\napaTables::apa.cor.table(df1[, c(\"RevMedMen\" , \"Locataire\" , \"LogTailInc\")], \n filename = \"data/bivariee/TitiLaMatrice.doc\",\n show.conf.interval = TRUE,\n landscape = TRUE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\nMeans, standard deviations, and correlations with confidence intervals\n \n\n Variable M SD 1 2 \n 1. RevMedMen 66065.50 26635.27 \n \n 2. Locataire 45.05 26.33 -.78** \n [-.81, -.76] \n \n 3. LogTailInc 5.54 4.82 -.46** .56** \n [-.51, -.41] [.52, .60]\n \n\nNote. M and SD are used to represent mean and standard deviation, respectively.\nValues in square brackets indicate the 95% confidence interval.\nThe confidence interval is a plausible range of population correlations \nthat could have caused the sample correlation (Cumming, 2014).\n * indicates p < .05. ** indicates p < .01.\n \n```\n:::\n:::\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Une image vaut mille mots, surtout pour une matrice de corrélation!**\n:::\n::: bloc_astuce-body\nLe package `corrplot` vous permet justement de construire de belles figures avec une matrice de corrélation (figures [-@fig-corrplot1] et [-@fig-corrplot2]). L'intérêt de ce type de figure est de repérer rapidement des associations intéressantes lorsque nous calculons les corrélations entre un grand nombre de variables.\n:::\n:::\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(\"corrplot\")\nlibrary(\"ggpubr\")\ndf1 <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\nVars <- c(\"RevMedMen\" , \"Locataire\", \"LogTailInc\" , \"A65plus\" , \"ImgRec\", \"HabKm2\", \"FaibleRev\")\np <- cor(df1[, Vars], method=\"pearson\")\ncouleurs <- colorRampPalette(c(\"#053061\", \"#2166AC\" , \"#4393C3\", \"#92C5DE\",\n \"#D1E5F0\", \"#FFFFFF\", \"#FDDBC7\", \"#F4A582\",\n \"#D6604D\", \"#B2182B\", \"#67001F\"))\ncorrplot::corrplot(p, addrect = 3, method=\"number\",\n diag = FALSE, col=couleurs(100))\n```\n\n::: {.cell-output-display}\n![Matrice de corrélation avec corrplot (chiffres)](04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot1-1.png){#fig-corrplot1 fig-align='center' width=60%}\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nfig2 <- corrplot.mixed(p, lower=\"number\", lower.col = \"black\", \n upper = \"ellipse\", upper.col=couleurs(100))\n```\n\n::: {.cell-output-display}\n![Matrice de corrélation avec corrplot (chiffres et ellipses)](04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot2-1.png){#fig-corrplot2 fig-align='center' width=60%}\n:::\n:::\n\n\n\n### Comment rapporter des valeurs de corrélations? {#sec-0438}\n\nBien qu'il n'y ait pas qu'une seule manière de reporter des corrélations, voici quelques lignes directrices pour vous guider : \n\n* Signaler si la corrélation est faible, modérée ou forte.\n\n* Indiquer si la corrélation est positive ou négative. Toutefois, ce n'est pas une obligation, car nous pouvons rapidement le constater avec le signe du coefficient.\n\n* Mettre le *r* et le *p* en italique et en minuscules.\n\n* Deux décimales uniquement pour le $r$ (sauf si une plus grande précision se justifie dans le domaine d'étude).\n\n* Trois décimales pour la valeur de *p*. Si elle est inférieure à 0,001, écrire plutôt *p* < 0,001.\n\n* Indiquer éventuellement le nombre de degrés de liberté, soit $r(dl)=...$\n\nVoici des exemples :\n\n* La corrélation entre les variables *revenu médian des ménages* et *pourcentage de locataires* est fortement négative (*r* = −0,78, *p* < 0,001).\n\n* La corrélation entre les variables *revenu médian des ménages* et *pourcentage de locataires* est forte (*r*(949) = −0,78, *p* < 0,001).\n\n* La corrélation entre les variables *densité de population* et *revenu médian des ménages* est modérée (*r* = −0,49, *p* < 0,001).\n\n* La corrélation entre les variables *densité de population* et *pourcentage de 65 ans et plus* n'est pas significative (*r* = −0,08, *p* = 0,07).\n\nPour un texte en anglais, référez-vous à : [https://www.socscistatistics.com/tutorials/correlation/default.aspx](https://www.socscistatistics.com/tutorials/correlation/default.aspx){target=\"_blank\"}.\n\n## Régression linéaire simple {#sec-044}\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Comment expliquer et prédire une variable continue en fonction d'une autre variable?**\n:::\n::: bloc_objectif-body\nRépondre à cette question relève de la statistique inférentielle. Il s'agit en effet d'établir une équation simple du type $Y = a + bX$ pour expliquer et prédire les valeurs d'une variable dépendante (*Y*) à partir d'une variable indépendante (*X*). L'équation de la régression est construite grâce à un jeu de données (un échantillon). À partir de cette équation, il est possible de prédire la valeur attendue de *Y* pour n'importe quelle valeur de *X*. Nous appelons cette équation un modèle, car elle cherche à représenter la réalité de façon simplifiée.\n\nLa régression linéaire simple relève ainsi de la statistique inférentielle et se distingue ainsi de la **covariance** ([section @sec-042]) et de la **corrélation** ([section @sec-043]) qui relèvent quant à eux de la statistique bivariée descriptive et exploratoire. \n\nPar exemple, la régression linéaire simple pourrait être utilisée pour expliquer les notes d'un groupe d'étudiants et d'étudiantes à un examen (variable dépendante *Y*) en fonction du nombre d'heures consacrées à la révision des notes de cours (variable indépendante *X*). Une fois l'équation de régression déterminée et si le modèle est efficace, nous pourrons prédire les notes des personnes inscrites au cours la session suivante en fonction du temps qu'ils ou qu'elles prévoient passer à étudier, et ce, avant l'examen. \n\nFormulons un exemple d'application de la régression linéaire simple en études urbaines. Dans le cadre d'une étude sur les îlots de chaleur urbains, la température de surface (variable dépendante) pourrait être expliquée par la proportion de la superficie de l'îlot couverte par de la végétation (variable indépendante). Nous supposons alors que plus cette proportion est importante, plus la température est faible et inversement, soit une relation linéaire négative. Si le modèle est efficace, nous pourrions prédire la température moyenne des îlots d'une autre municipalité pour laquelle nous ne disposons pas d'une carte de température, et repérer ainsi les îlots de chaleur potentiels. Bien entendu, il est peu probable que nous arrivions à prédire efficacement la température moyenne des îlots avec uniquement la couverture végétale comme variable explicative. En effet, bien d'autres caractéristiques de la forme urbaine peuvent influencer ce phénomène comme la densité du bâti, la couleur des toits, les occupations du sol présentes, l'effet des canyons urbains, etc. Il faudrait alors inclure non pas une, mais plusieurs variables explicatives (indépendantes).\n\nAinsi, nous distinguons la **régression linéaire simple** (une seule variable indépendante) de la **régression linéaire multiple** (plusieurs variables indépendantes); cette dernière est largement abordée au [chapitre @sec-chap07].\n:::\n:::\n\nDans cette section, nous décrivons succinctement la régression linéaire simple. Concrètement, nous voyons comment déterminer la droite de régression, interpréter ses différents paramètres du modèle et évaluer la qualité d'ajustement du modèle. Nous n'abordons ni les hypothèses liées au modèle de régression linéaire des moindres carrés ordinaires (MCO) ni les conditions d'application. Ces éléments sont expliqués au [chapitre @sec-chap07], consacré à la régression linéaire multiple.\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Corrélation, régression simple et causalité : attention aux raccourcis!**\n:::\n::: bloc_attention-body\nSi une variable *X* explique et prédit efficacement une variable *Y*, cela ne veut pas dire pour autant qu'*X* cause *Y*. Autrement dit, la corrélation, soit le degré d'association entre deux variables, ne signifie pas qu'il existe un lien de causalité entre elles.\n\nPremièrement, la variable explicative (*X*, indépendante) doit absolument précéder la variable à expliquer (*Y*, dépendante). Par exemple, l'âge (*X*) peut influencer le sentiment de sécurité (*Y*). Mais, le sentiment de sécurité ne peut en aucun cas influencer l'âge. Par conséquent, l'âge ne peut conceptuellement pas être la variable dépendante dans cette relation.\n\nDeuxièmement, bien qu'une variable puisse expliquer efficacement une autre variable, elle peut être un **facteur confondant**. Prenons deux exemples bien connus :\n\n* Avoir les doigts jaunes est associé au cancer du poumon. Bien entendu, les doigts jaunes ne causent pas le cancer : c'est un facteur confondant puisque fumer augmente les risques du cancer du poumon et jaunit aussi les doigts.\n\n* Dans un article intitulé *Chocolate Consumption, Cognitive Function, and Nobel Laureates*, Messerli [-@Messerli] a trouvé une corrélation positive entre la consommation de chocolat par habitant et le nombre de prix Nobel pour dix millions d'habitants pour 23 pays. Ce résultat a d'ailleurs été rapporté par de nombreux médias, sans pour autant que Messerli [-@Messerli] et les journalistes concluent à un lien de causalité entre les deux variables :\n\n - [Radio Canada](https://ici.radio-canada.ca/nouvelle/582457/chocolat-consommateurs-nobels)\n\n - [La Presse](https://www.lapresse.ca/vivre/sante/nutrition/201210/11/01-4582347-etude-plus-un-pays-mange-de-chocolat-plus-il-a-de-prix-nobel.php)\n\n - [Le Point](https://www.lepoint.fr/insolite/le-chocolat-dope-aussi-l-obtention-de-prix-nobel-12-10-2012-1516159_48.php). \n\nLes chercheurs et les chercheuses savent bien que la consommation de chocolat ne permet pas d'obtenir des résultats intéressants et de les publier dans des revues prestigieuses; c'est plutôt le café ! Plus sérieusement, il est probable que les pays les plus riches investissent davantage dans la recherche et obtiennent ainsi plus de prix Nobel. Dans les pays les plus riches, il est aussi probable que l'on consomme plus de chocolat, considéré comme un produit de luxe dans les pays les plus pauvres.\n\nPour approfondir le sujet sur la confusion entre corrélation, régression simple et causalité, vous pouvez visionner cette courte [vidéo ludique de vulgarisation](https://www.youtube.com/embed/A-_naeATJ6o).\n\nL'association entre deux variables peut aussi être simplement le fruit du hasard. Si nous explorons de très grandes quantités de données (avec un nombre impressionnant d'observations et de variables), soit une démarche relevant du forage ou de la fouille de données (*data mining* en anglais), le hasard fera que nous risquons d'obtenir des corrélations surprenantes entre certaines variables. Prenons un exemple concret : admettons que nous ayons collecté 100 variables et que nous calculons les corrélations entre chaque paire de variables. Nous obtenons une matrice de corrélation de 100 x 100, à laquelle nous pouvons enlever la diagonale et une moitié de la matrice, ce qui nous laisse un total de 4950 corrélations différentes. Admettons que nous choisissions un seuil de significativité de 5 %, nous devons alors nous attendre à ce que le hasard produise des résultats significatifs dans 5 % des cas. Sur 4950 corrélations, cela signifie qu'environ 247 corrélations seront significatives, et ce, indépendamment de la nature des données. Nous pouvons aisément illustrer ce fait avec la syntaxe suivante :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"Hmisc\")\nnbVars <- 100 # nous utilisons 100 variables générées aléatoirement pour l'expérience\nnbExperiment <- 1000 # nous reproduirons 1000 fois l'expérience avec les 100 variables\n# Le nombre de variables significatives par expérience est enregistré dans Results\nResults <- c()\n# Itérons pour chaque expérimentation (1000 fois)\nfor(i in 1:nbExperiment){\n Datas <- list()\n # Générons 100 variables aléatoires normalement distribuées\n for (j in 1:nbVars){\n Datas[[j]] <- rnorm(150)\n }\n DF <- do.call(\"cbind\", datas)\n # Calculons la matrice de corrélation pour les 100 variables\n cor_mat <- rcorr(DF)\n # Comptons combien de fois les corrélations étaient significatives\n Sign <- table(cor_mat$P<0.05)\n NbPairs <- Sign[[\"TRUE\"]]/2\n # Ajoutons les résultats dans Results\n Results <- c(Results, NbPairs)\n}\n# Transformons Results en un DataFrame\ndf <- data.frame(Values = Results)\n# Affichons le résultat dans un graphique\nggplot(df, aes(x = Values)) + \n geom_histogram(aes(y =..density..), \n colour = \"black\", \n fill = \"white\") +\n stat_function(fun = dnorm, args = list(mean = mean(df$Values), \n sd = sd(df$Values)), color = \"blue\")+\n geom_vline(xintercept = mean(df$Values), color = \"red\", size = 1.2)+\n annotate(\"text\", x=0, y = 0.028, \n label = paste(\"Nombre moyen de corrélations significatives\\n\n sur 1000 réplications : \",\n round(mean(df$Values),0), sep = \"\"), hjust=\"left\")+\n xlab(\"Nombre de corrélations significatives\")+\n ylab(\"densité\")\n```\n:::\n\n\n![Corrélations significatives obtenues aléatoirement](images/Chap04/ReplicationHist.png){#fig-replicationhist width=\"50%\" fig-align=\"center\"}\n\n:::\n:::\n\n### Principe de base de la régression linéaire simple {#sec-0441}\nLa régression linéaire simple vise à déterminer une droite (une fonction linéaire) qui résume le mieux la relation linéaire entre une variable dépendante (*Y*) et une variable indépendante (*X*) :\n$$\n\\widehat{y_i} = \\beta_{0} + \\beta_{1}x_{i}\n$$ {#eq-regsimple}\n\navec $\\widehat{y_i}$ et $x_{i}$ qui sont respectivement la valeur prédite de la variable dépendante et la valeur de la variable indépendante pour l'observation $i$. $\\beta_{0}$ est la constante (*intercept* en anglais) et représente la valeur prédite de la variable *Y* quand *X* est égale à 0. $\\beta_{1}$ est le coefficient de régression pour la variable *X*, soit la pente de la droite. Ce coefficient nous informe sur la relation entre les deux variables : s’il est positif, la relation est positive; s’il est négatif, la relation est négative; s'il est proche de 0, la relation est nulle (la droite est alors horizontale). Plus la valeur absolue de $\\beta_{1}$ est élevée, plus la pente est forte et plus la variable *Y* varie à chaque changement d’une unité de la variable *X*.\n\nConsidérons un exemple fictif de dix municipalités d'une région métropolitaine pour lesquelles nous disposons de deux variables : le pourcentage de personnes occupées se rendant au travail principalement à vélo et la distance entre chaque municipalité et le centre-ville de la région métropolitaine (@tbl-regfictives).\n\n\n\n::: {#tbl-regfictives .cell tbl-cap='Données fictives sur l\\'utilisation du vélo par municipalité'}\n::: {.cell-output-display}\n|Municipalité | Vélo | KMCV|\n|:------------|:----:|------:|\n|A | 12,5 | 14,135|\n|B | 13,5 | 10,065|\n|C | 15,8 | 7,762|\n|D | 15,9 | 11,239|\n|E | 17,6 | 7,706|\n|F | 18,5 | 7,195|\n|G | 21,2 | 7,953|\n|H | 23,0 | 4,293|\n|I | 25,3 | 5,225|\n|J | 30,2 | 2,152|\n:::\n:::\n\n\nD'emblée, à la lecture du nuage de points (@fig-reg), nous décelons une forte relation linéaire négative entre les deux variables : plus la distance entre la municipalité et le centre-ville de la région métropolitaine augmente, plus le pourcentage de cyclistes est faible, ce qui est confirmé par le coefficient de corrélation (*r* = −0,90). La droite de régression (en rouge à la @fig-reg) qui résume le mieux la relation entre `Vélo` (variable dépendante) et `KmCV` (variable indépendante) s'écrit alors : **Vélo = 30,603 − 1,448 x KmCV**.\n\nLa valeur du coefficient de régression ($\\beta_{1}$) est de −1,448. Le signe de ce coefficient décrit une relation négative entre les deux variables. Ainsi, à chaque ajout d'une unité de la distance entre la municipalité et le centre-ville (exprimée en kilomètres), le pourcentage de cyclistes diminue de 1,448. Retenez que l'unité de mesure de la variable dépendante est très importante pour bien interpréter le coefficient de régression. En effet, si la distance au centre-ville n'était pas exprimée en kilomètres, mais plutôt en mètres, $\\beta_1$ serait égal à −0,001448. Dans la même optique, l'ajout de 10 km de distance entre une municipalité et le centre-ville fait diminuer le pourcentage de cyclistes de −14,48 points de pourcentage.\n\nAvec, cette équation de régression, il est possible de prédire le pourcentage de cyclistes pour n'importe quelle municipalité de la région métropolitaine. Par exemple, pour des distances de 5, 10 ou 20 kilomètres, les pourcentages de cyclistes seraient de :\n\n* $\\widehat{y_i} = \\mbox{30,603} + (\\mbox{-1,448} \\times \\mbox{5 km) = 23,363}$\n* $\\widehat{y_i} = \\mbox{30,603} + (\\mbox{-1,448} \\times \\mbox{10 km) = 8,883}$\n* $\\widehat{y_i} = \\mbox{30,603} + (\\mbox{-1,448} \\times \\mbox{20 km) = 1,643}$\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Relation linéaire entre l'utilisation du vélo et la distance au centre-ville](04-bivarieeQuantiQuanti_files/figure-html/fig-reg-1.png){#fig-reg fig-align='center' width=65%}\n:::\n:::\n\n\n\n### Formulation de la droite de régression des moindres carrés ordinaires {#sec-0442}\nReste à savoir comment sont estimés les différents paramètres de l'équation, soit $\\beta_0$ et $\\beta_1$. À la @fig-reg2, les points noirs représentent les valeurs observées ($y_i$) et les points bleus, les valeurs prédites ($\\widehat{y_i}$) par l'équation du modèle. Les traits noirs verticaux représentent, pour chaque observation $i$, l'écart entre la valeur observée et la valeur prédite, dénommé résidu ($\\epsilon_i$, prononcez epsilon de _i_ ou plus simplement le résidu pour _i_ ou le terme d'erreur de _i_). Si un point est au-dessus de la droite de régression, la valeur observée est alors supérieure à la valeur prédite ($y_i > \\widehat{y_i}$) et inversement, si le point est au-dessous de la droite ($y_i < \\widehat{y_i}$). Plus cet écart ($\\epsilon_i$) est important, plus l'observation s'éloigne de la prédiction du modèle et, par extension, moins bon est le modèle. Au @tbl-regfictives2, vous constaterez que la somme des résidus est égale à zéro. La méthode des moindres carrés ordinaires (MCO) vise à minimiser les écarts au carré entre les valeurs observées ($y_i$) et prédites ($\\beta_0+\\beta_1 x_i$, soit $\\widehat{y_i}$) :\n\n$$\nmin\\sum_{i=1}^n{(y_i-(\\beta_0+\\beta_1 x_i))^2}\n$$ {#eq-mco}\n\nPour minimiser ces écarts, le coefficient de régression $\\beta_1$ représente le rapport entre la covariance entre *X* et *Y* et la variance de *Y* (@eq-b1), tandis que la constante $\\beta_0$ est la moyenne de la variable *Y* moins le produit de la moyenne de *X* et de son coefficient de régression (@eq-b0).\n\n$$\n\\beta_1 = \\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})(y_{i}-\\bar{y})}{\\sum_{i=1}^n (x_i-\\bar{x})^2} = \\frac{cov(X,Y)}{var(X)}\n$$ {#eq-b1}\n\n$$\n\\beta_0 = \\widehat{Y}-\\beta_1 \\widehat{X}\n$$ {#eq-b0}\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Droite de régression, valeurs observées, prédites et résidus](04-bivarieeQuantiQuanti_files/figure-html/fig-reg2-1.png){#fig-reg2 fig-align='center' width=65%}\n:::\n:::\n\n::: {#tbl-regfictives2 .cell tbl-cap='Valeurs observées, prédites et résidus'}\n::: {.cell-output-display}\n|Municipalité | Vélo | KmCV| Valeur prédite| Résidu| Résidu au carré|\n|:------------|:----:|------:|--------------:|------:|---------------:|\n|A | 12,5 | 14,135| 10,138| 2,362| 5,579|\n|B | 13,5 | 10,065| 16,031| -2,531| 6,406|\n|C | 15,8 | 7,762| 19,365| -3,565| 12,709|\n|D | 15,9 | 11,239| 14,331| 1,569| 2,462|\n|E | 17,6 | 7,706| 19,446| -1,846| 3,408|\n|F | 18,5 | 7,195| 20,186| -1,686| 2,843|\n|G | 21,2 | 7,953| 19,089| 2,111| 4,456|\n|H | 23,0 | 4,293| 24,388| -1,388| 1,927|\n|I | 25,3 | 5,225| 23,038| 2,262| 5,117|\n|J | 30,2 | 2,152| 27,488| 2,712| 7,355|\n|Somme | -- | --| --| 0,000| 52,262|\n:::\n:::\n\n\n### Mesure de la qualité d'ajustement du modèle {#sec-0443}\nLes trois mesures les plus courantes pour évaluer la qualité d'ajustement d'un modèle de régression linéaire simple sont l'erreur quadratique moyenne (*root-mean-square error* en anglais, *RMSE*), le coefficient de détermination (*R^2^*) et la statistique *F* de Fisher. Pour mieux appréhender le calcul de ces trois mesures, rappelons que l'équation de régression s'écrit : \n\n$$\ny_i = \\beta_0 + \\beta_1 x_1+ \\epsilon_i \\Rightarrow Y= \\beta_0 + \\beta_1 X + \\epsilon\n$$ {#eq-reg2}\n\nElle comprend ainsi une partie de *Y* qui est expliquée par le modèle et une autre partie non expliquée, soit $\\epsilon$, appelée habituellement le terme d'erreur. Ce terme d'erreur pourrait représenter d'autres variables explicatives qui n'ont pas été prises en compte pour prédire la variable indépendante ou une forme de variation aléatoire inexplicable présente lors de la mesure.\n\n$$\nY = \\underbrace{\\beta_0 + \\beta_1 X}_{\\mbox{partie expliquée par le modèle}}+ \\underbrace{\\epsilon}_{\\mbox{partie non expliquée}}\n$$ {#eq-reg3}\n\n\nPar exemple, pour la municipalité *A* au @tbl-regfictives2, nous avons : $y_A = \\widehat{y}_A - \\epsilon_A \\Rightarrow \\mbox{12,5} = \\mbox{10,138}+\\mbox{2,362}$. Souvenez-vous que la variance d'une variable est la somme des écarts à la moyenne, divisée par le nombre d'observations. Par extension, il est alors possible de décomposer la variance de *Y* comme suit :\n\n$$\n\\underbrace{\\sum_{i=1}^n (y_{i}-\\bar{y})^2}_{\\mbox{variance de Y}} = \\underbrace{\\sum_{i=1}^n (\\widehat{y}_i-\\bar{y})^2}_{\\mbox{var. expliquée}} + \\underbrace{\\sum_{i=1}^n (y_{i}-\\widehat{y})^2}_{\\mbox{var. non expliquée}} \\Rightarrow \nSCT = SCE + SCR\n$$ {#eq-reg4}\n\n\navec :\n\n* *SCT* est la somme des écarts au carré des valeurs observées à la moyenne (_total sum of squares_ en anglais)\n\n* *SCE* est la somme des écarts au carré des valeurs prédites à la moyenne (_regression sum of squares_ en anglais)\n\n* *SCR* est la somme des carrés des résidus (_sum of squared errors_ en anglais).\n\nAutrement dit, la variance totale est égale à la variance expliquée plus la variance non expliquée. Au @tbl-computeR, vous pouvez repérer les valeurs de *SCT*, *SCE* et *SCR* et constater que 279,30 = 227,04 + 52,26 et 27,93 = 22,70 + 5,23.\n\n\n::: {#tbl-computeR .cell tbl-cap='Calcul du coefficient de détermination'}\n::: {.cell-output-display}\n|Municipalité | $y_i$| $\\widehat{y}_i$| $\\epsilon_i$| $(y_i-\\bar{y})^2$| $(\\widehat{y}_i-y_i)^2$| $\\epsilon_i^2$|\n|:------------|------:|---------------:|------------:|-----------------:|-----------------------:|--------------:|\n|A | 12,50| 10,14| 2,36| 46,92| 84,86| 5,58|\n|B | 13,50| 16,03| -2,53| 34,22| 11,02| 6,41|\n|C | 15,80| 19,37| -3,57| 12,60| 0,00| 12,71|\n|D | 15,90| 14,33| 1,57| 11,90| 25,19| 2,46|\n|E | 17,60| 19,45| -1,85| 3,06| 0,01| 3,41|\n|F | 18,50| 20,19| -1,69| 0,72| 0,70| 2,84|\n|G | 21,20| 19,09| 2,11| 3,42| 0,07| 4,46|\n|H | 23,00| 24,39| -1,39| 13,32| 25,38| 1,93|\n|I | 25,30| 23,04| 2,26| 35,40| 13,60| 5,12|\n|J | 30,20| 27,49| 2,71| 117,72| 66,22| 7,36|\n|N | 10,00| --| --| --| --| --|\n|Somme | 193,50| --| 0,00| 279,30| 227,04| 52,26|\n|Moyenne | 19,35| --| 0,00| 27,93| 22,70| 5,23|\n:::\n:::\n\n\n\n**Calcul de l'erreur quadratique moyenne**\n\nLa somme des résidus au carré (*SCR*) divisée par le nombre d'observations représente donc le carré moyen des erreurs (en anglais, *mean square error - MSE*), soit la variance résiduelle du modèle (52,26 / 10 = 5,23). Plus sa valeur est faible, plus le modèle est efficace pour prédire la variable indépendante. L'erreur quadratique moyenne (en anglais, *root-mean-square error - RMSE*) est simplement la racine carrée de la somme des résidus au carré divisée par le nombre d'observations ($n$) :\n\n$$\nRMSE = \\sqrt{\\frac{\\sum_{i=1}^n (y_{i}-\\widehat{y})^2}{n}}\n$$ {#eq-reg5}\n\n\nElle représente ainsi une **mesure absolue des erreurs** qui est exprimée dans l'unité de mesure de la variable dépendante. Dans le cas présent, nous avons : $\\sqrt{5,23}=2,29$. Cela signifie qu'en moyenne, l'écart absolu (ou erreur absolue) entre les valeurs observées et prédites est de 2,29 points de pourcentage. De nouveau, une plus faible valeur de **RMSE** indique un meilleur ajustement du modèle. Mais surtout, le RMSE permet d'évaluer avec quelle précision le modèle prédit la variable dépendante. Il est donc particulièrement important si l'objectif principal du modèle est de prédire des valeurs sur un échantillon d'observations pour lequel la variable dépendante est inconnue.\n\n**Calcul du coefficient de détermination**\n\nNous avons largement démontré que la variance totale est égale à la variance expliquée plus la variance non expliquée. La qualité du modèle peut donc être évaluée avec le coefficient de détermination (*R^2^*), soit le rapport entre les variances expliquée et totale : \n\n$$\nR^2 = \\frac{SCE}{SCT} \\mbox{ avec } R^2 \\in \\left[0,1\\right]\n$$ {#eq-reg6}\n\n\nComparativement au RMSE qui est une mesure absolue, le coefficient de détermination est une **mesure relative** qui varie de 0 à 1. Il exprime la proportion de la variance de *Y* qui est expliquée par la variable *X*; autrement dit, plus sa valeur est élevée, plus *X* influence/est capable de prédire *Y*. Dans le cas présent, nous avons : R^2^ = 227,04 / 279,3 = 0,8129, ce qui signale que 81,3 % de la variance du pourcentage de cyclistes est expliquée par la distance entre la municipalité et le centre-ville de la région métropolitaine. Tel que signalé dans la [section @sec-0432], la racine carrée du coefficient de détermination (*R^2^*) est égale au coefficient de corrélation ($r$) entre les deux variables. \n\n**Calcul de la statistique _F_ de Fisher**\n\nLa statistique _F_ de Fisher permet de vérifier la significativité globale du modèle.\n\n$$\nF = (n-2)\\frac{R^2}{1-R^2} = (n-2)\\frac{SCE}{SCR}\n$$ {#eq-reg7}\n\n\nL'hypothèse nulle (*H~0~* avec $\\beta_1=0$) est rejetée si la valeur calculée de *F* est supérieure à la valeur critique de la table *F* avec *1, n-2* degrés de liberté et un seuil $\\alpha$ (*p* = 0,05 habituellement) (voir la table des valeurs critiques de *F*, [section @sec-142]). Notez que nous utilisons rarement la table *F* puisqu'avec la fonction `pf(f obtenu, 1, n-2, lower.tail = FALSE)`, nous obtenons obtient directement la valeur de *p* associée à la valeur de *F*. Concrètement, si le test _F_ est significatif (avec *p* < 0,05), plus la valeur de *F* est élevée, plus le modèle est efficace (et plus le *R^2^* sera également élevé).\n\nNotez que la fonction `summary` renvoie les résultats du modèle, dont notamment le test _F_ de Fisher.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# utiliser la fonction summary\nsummary(modele)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCall:\nlm(formula = Velo ~ KmCV, data = data)\n\nResiduals:\n Min 1Q Median 3Q Max \n-3.5652 -1.8062 0.0906 2.2241 2.7125 \n\nCoefficients:\n Estimate Std. Error t value Pr(>|t|) \n(Intercept) 30.6032 2.0729 14.763 4.36e-07 ***\nKmCV -1.4478 0.2456 -5.895 0.000364 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\nResidual standard error: 2.556 on 8 degrees of freedom\nMultiple R-squared: 0.8129,\tAdjusted R-squared: 0.7895 \nF-statistic: 34.75 on 1 and 8 DF, p-value: 0.0003637\n```\n:::\n:::\n\n\nDans le cas présent, $F = (10 - 2)\\frac{\\mbox{0,8129}}{\\mbox{1-0,8129}} = (10-2)\\frac{\\mbox{227,04}}{\\mbox{52,26}} = \\mbox{34,75}$ avec une valeur de $\\mbox{p < 0,001}$. Par conséquent, le modèle est significatif.\n\n### Mise en œuvre dans R {#sec-0444}\nComment calculer une régression linéaire simple dans R. Rien de plus simple avec la fonction `lm(formula = y ~ x, data= DataFrame)`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf1 <- read.csv(\"data/bivariee/Reg.csv\", stringsAsFactors = FALSE)\n## Création d'un objet pour le modèle\nmonmodele <- lm(Velo ~ KmCV, df1)\n## Résultats du modèle avec la fonction summary\nsummary(monmodele)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCall:\nlm(formula = Velo ~ KmCV, data = df1)\n\nResiduals:\n Min 1Q Median 3Q Max \n-3.5652 -1.8062 0.0906 2.2241 2.7125 \n\nCoefficients:\n Estimate Std. Error t value Pr(>|t|) \n(Intercept) 30.6032 2.0729 14.763 4.36e-07 ***\nKmCV -1.4478 0.2456 -5.895 0.000364 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\nResidual standard error: 2.556 on 8 degrees of freedom\nMultiple R-squared: 0.8129,\tAdjusted R-squared: 0.7895 \nF-statistic: 34.75 on 1 and 8 DF, p-value: 0.0003637\n```\n:::\n\n```{.r .cell-code}\n## Calcul du MSE et du RMSE\nMSE <- mean(monmodele$residuals^2)\nRMSE <- sqrt(MSE)\ncat(\"MSE = \", round(MSE, 2), \"; RMSE = \", round(RMSE,2), sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nMSE = 5.23; RMSE = 2.29\n```\n:::\n:::\n\n\n### Comment rapporter une régression linéaire simple {#sec-0445}\n\nNous avons calculé une régression linéaire simple pour prédire le pourcentage d'actifs occupés utilisant le vélo pour se rendre au travail en fonction de la distance entre la municipalité et le centre-ville de la région métropolitaine (en kilomètres). Le modèle obtient un *F* de Fisher significatif (*F*(1,8) = 34,75, *p* < 0,001) et un *R^2^* de 0,813. Le pourcentage de cyclistes peut être prédit par l'équation suivante : 30,603 - 1,448 x (distance au centre-ville en km).\n\n## Quiz de révision du chapitre {#sec-045}\n\n\n
\n\n\n\n
\n
D'après le nuage de points, les variables X et Y partagent une relation :
\n\"\"\n
Relisez au besoin la [section @sec-041].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
D'après le nuage de points, les deux variables partagent une relation :
\n\"\"\n
Relisez au besoin la [section @sec-041].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
La valeur de la covariance peut être positive ou négative. Plus sa valeur absolue est élevée :
\n\"\"\n
Relisez au besoin la [section @sec-0422].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Les coefficients de corrélation (Pearson, Speaman, etc.) varient de à :
\n
Relisez au besoin la [section @sec-0433].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Cette statistique est tributaire des unités de mesure des deux variables. Cet inconvénient s'applique à :
\n
Relisez au besoin la [section @sec-0422].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
À la lecture du nuage de points, la corrélation de Pearson entre les deux variables est proche de :
\n\"\"\n
Relisez au besoin la [section @sec-041].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Le coefficient de Spearman est le coefficient de Pearson calculé sur des variables transformées en :
\n
Relisez au besoin la [section @sec-0433].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Dans une régression linéaire, le résidu pour une observation est :
\n
Relisez au besoin la [section @sec-0442].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Le coefficient de détermination (R2) varie de :
\n
Relisez au besoin la [section @sec-0443].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Un facteur confondant est une sorte de fondant au chocolat?
\n
Relire le deuxième encadré à la [section @sec-044].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n\n
\n\n
\n
\n", + "supporting": [ + "04-bivarieeQuantiQuanti_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/04-bivarieeQuantiQuanti_files/figure-html/fig-PearsonSpearmanKendall-1.png b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-PearsonSpearmanKendall-1.png similarity index 100% rename from docs/04-bivarieeQuantiQuanti_files/figure-html/fig-PearsonSpearmanKendall-1.png rename to .quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-PearsonSpearmanKendall-1.png diff --git a/docs/04-bivarieeQuantiQuanti_files/figure-html/fig-ValExtremes-1.png b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-ValExtremes-1.png similarity index 100% rename from docs/04-bivarieeQuantiQuanti_files/figure-html/fig-ValExtremes-1.png rename to .quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-ValExtremes-1.png diff --git a/docs/04-bivarieeQuantiQuanti_files/figure-html/fig-coefCorrVar-1.png b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-coefCorrVar-1.png similarity index 100% rename from docs/04-bivarieeQuantiQuanti_files/figure-html/fig-coefCorrVar-1.png rename to .quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-coefCorrVar-1.png diff --git a/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-coeffPearson-1.png b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-coeffPearson-1.png new file mode 100644 index 0000000..25fefa2 Binary files /dev/null and b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-coeffPearson-1.png differ diff --git a/docs/04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot1-1.png b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-corrplot1-1.png similarity index 100% rename from docs/04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot1-1.png rename to .quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-corrplot1-1.png diff --git a/docs/04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot2-1.png b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-corrplot2-1.png similarity index 100% rename from docs/04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot2-1.png rename to .quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-corrplot2-1.png diff --git a/docs/04-bivarieeQuantiQuanti_files/figure-html/fig-covariance-1.png b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-covariance-1.png similarity index 100% rename from docs/04-bivarieeQuantiQuanti_files/figure-html/fig-covariance-1.png rename to .quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-covariance-1.png diff --git a/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-fig9-1.png b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-fig9-1.png new file mode 100644 index 0000000..f9257dc Binary files /dev/null and b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-fig9-1.png differ diff --git a/docs/04-bivarieeQuantiQuanti_files/figure-html/fig-reg-1.png b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-reg-1.png similarity index 100% rename from docs/04-bivarieeQuantiQuanti_files/figure-html/fig-reg-1.png rename to .quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-reg-1.png diff --git a/docs/04-bivarieeQuantiQuanti_files/figure-html/fig-reg2-1.png b/.quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-reg2-1.png similarity index 100% rename from docs/04-bivarieeQuantiQuanti_files/figure-html/fig-reg2-1.png rename to .quarto/_freeze/04-bivarieeQuantiQuanti/figure-html/fig-reg2-1.png diff --git a/.quarto/_freeze/05-bivarieeQualiQuali/execute-results/html.json b/.quarto/_freeze/05-bivarieeQualiQuali/execute-results/html.json new file mode 100644 index 0000000..c57d2e9 --- /dev/null +++ b/.quarto/_freeze/05-bivarieeQualiQuali/execute-results/html.json @@ -0,0 +1,16 @@ +{ + "hash": "9361e3dfa14db72e20c714644da9110d", + "result": { + "markdown": "# Relation entre deux variables qualitatives {#sec-chap05}\n\nDans le cadre de ce chapitre, nous présentons les deux principales méthodes permettant d'explorer les associations entre deux variables qualitatives : la construction d'un tableau de contingence et le test du khi-deux ($\\chi^2$, appelé aussi khi carré).\n\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* `gmodels` pour construire des tableaux de contingence.\n* `vcd` pour construire un graphique pour un tableau de contingence.\n* `DescTools` pour calculer le khi-deux de Mantel-Haenszel.\n* `stargazer` pour imprimer des tableaux.\n:::\n:::\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Deux variables qualitatives sont-elles associées entre elles?** \n:::\n::: bloc_objectif-body\nPlus spécifiquement, certaines modalités d'une variable qualitative sont-elles associées significativement à certaines modalités d'une autre variable qualitative?\n\nPrenons l'exemple de deux variables qualitatives : l'une intitulée *groupe d'âge* comprenant trois modalités (15 à 29 ans, 30 à 44 ans, 45 à 64 ans); l'autre intitulée *mode de transport habituel pour se rendre au travail* comprenant quatre modalités (véhicule motorisé, transport en commun, vélo, marche). \n\nComparativement aux deux autres groupes, nous pourrions supposer que les jeunes se déplacent proportionnellement plus en modes de transport actif (vélo et marche) et en transport en commun. À l'inverse, il est possible que les 45 à 64 ans se déplacent majoritairement en véhicules motorisés.\n\nPour vérifier l'existence d'associations significatives entre les modalités de deux variables qualitatives, il est possible de construire un **tableau de contingence** ([section @sec-051]), puis de réaliser le **test du khi-deux** ([section @sec-052]).\n:::\n:::\n\n## Construction de tableau de contingence {#sec-051}\n\nLes données du tableau de contingence suivant décrivent 279 projets d'habitation à loyer modique (HLM) dans l'ancienne ville de Montréal, croisant les modalités de la période de construction (en colonne) et de la taille (en ligne) des projets HLM [@TheseApparicio]. Les différents éléments du tableau sont décrits ci-dessous.\n\n* **Les fréquences observées** (*Count* au tableau ci-dessous), nommées communément $f_{ij}$, correspondent aux observations appartenant à la fois à la *i^e^* modalité de la variable en ligne et à la *j^e^* modalité de la variable en colonne. À titre d’exemple, nous comptons 14 projets HLM construits entre 1985 et 1989 comprenant moins de 25 logements.\n\n* **Les marges** du tableau sont les totaux pour chaque modalité en ligne ($n_{i.}$) et en colonne ($n_{j.}$). En guise d’exemple, sur les 279 projets HLM, 53 comprennent de 25 à 49 logements et 56 ont été construites entre 1968 et 1974. Bien entendu, la somme des marges en ligne ($n_{i.}$) est égale au nombre total d'observations ($n_{ij}$), tout comme la somme de marges en colonne ($n_{.j}$).\n\n* **Trois pourcentages** sont disponibles (total, en ligne, en colonne; *Total Percent*, *Row Percent* et *Column Percent* au tableau ci-dessous). Ils sont respectivement la fréquence observée divisée par le nombre d'observations ($f_{ij}/n_{ij}\\times100$), par la marge en ligne ($f_{ij}/n_{i.} \\times 100$) et en colonne ($f_{ij}/n_{.j}\\times100$). En guise d'exemple, 5 % des 279 projets HLM ont été construites entre 1985 et 1989 et comprennent moins de 25 logements (pourcentage total, soit 14 / 279 × 100). Aussi, plus de la moitié des habitations de moins de 25 logements ont été construits entre 1990 et 1994 (pourcentage en ligne, 41 / 80 × 100). Finalement, près de 36 % des logements construits avant 1975 ont 100 logements et plus (20 / 56 × 100).\n\n* **Les fréquences théoriques** (*Expected Values* au tableau ci-dessous), représentent les valeurs que l'on devrait observer théoriquement s'il y avait indépendance entre les modalités des deux variables; autrement dit, si la répartition des deux modalités des deux variables était dû au hasard. Pour le croisement de deux modalités, la fréquence théorique est égale au produit des marges divisé par le nombre total d'observations ($ft_{ij} = (n_{i.}n_{.j})/n_{ij}$). Par exemple, la fréquence théorique pour le croisement des modalités *moins de 25 logements* et *avant 1975* est égale à : (80 × 56) / 279 = 16,06. Nous observons ici que la valeur théorique (16,06) est bien supérieure à la valeur réelle (6). Nous avons donc moins de projets HLM de moins de 25 logements avant 1975 auxquels nous pourrions nous attendre du hasard.\n\n* **La déviation** (*Residual* au tableau ci-dessous) est la différence entre la fréquence observée et la fréquence théorique ($f_{ij}-ft_{ij}$). Plus la déviation est grande, plus nous nous écartons d'une situation d'indépendance entre les deux modalités *i* et *j*. La somme des déviations sur une ligne ou sur une colonne est nulle. Si la déviation *ij* est nulle, la fréquence théorique est égale à la fréquence observée, ce qui signifie qu’il y a indépendance entre les modalités *i* et *j*. Une déviation positive traduit, quant à elle, une attraction entre les modalités *i* et *j* ou, autrement dit, une surreprésentation du phénomène *ij*; tandis qu’une déviation négative renvoie à une répulsion entre les modalités *i* et *j*, soit une sous-représentation du phénomène *ij*. Dans le cas précédent, nous observions six habitations de moins de 25 logements construits avant 1975 et une fréquence théorique de 16,06. La déviation est donc -10,06, soit une sous-représentation du phénomène.\n\n* **La contribution au khi-deux** (*Chi-square contribution* au tableau ci-dessous) est égale à la déviation au carré divisée par la fréquence théorique : $\\chi_{ij}^2 = (f_{ij}-ft_{ij})^2/ft_{ij}$. Plus sa valeur est forte, plus il y a association entre les deux modalités. La somme des contributions au khi-deux représente le khi-deux total pour l'ensemble du tableau de contingence (ici à 63,54), que nous aborderons dans la section suivante.\n\n\n\n::: {.cell}\n::: {.cell-output .cell-output-stdout}\n```\n\n Cell Contents\n|-------------------------|\n| Count |\n| Expected Values |\n| Chi-square contribution |\n| Row Percent |\n| Column Percent |\n| Total Percent |\n| Residual |\n|-------------------------|\n\nTotal Observations in Table: 279 \n\n | TabKhi2$Periode \nTabKhi2$Taille | Av. 1975 | 1975-79 | 1980-84 | 1985-89 | 1990-94 | Row Total | \n---------------|-----------|-----------|-----------|-----------|-----------|-----------|\n < 25 log. | 6 | 11 | 8 | 14 | 41 | 80 | \n | 16.06 | 13.76 | 13.76 | 13.48 | 22.94 | | \n | 6.30 | 0.55 | 2.41 | 0.02 | 14.22 | | \n | 7.50% | 13.75% | 10.00% | 17.50% | 51.25% | 28.67% | \n | 10.71% | 22.92% | 16.67% | 29.79% | 51.25% | | \n | 2.15% | 3.94% | 2.87% | 5.02% | 14.70% | | \n | -10.06 | -2.76 | -5.76 | 0.52 | 18.06 | | \n---------------|-----------|-----------|-----------|-----------|-----------|-----------|\n 25-49 | 10 | 5 | 8 | 8 | 22 | 53 | \n | 10.64 | 9.12 | 9.12 | 8.93 | 15.20 | | \n | 0.04 | 1.86 | 0.14 | 0.10 | 3.05 | | \n | 18.87% | 9.43% | 15.09% | 15.09% | 41.51% | 19.00% | \n | 17.86% | 10.42% | 16.67% | 17.02% | 27.50% | | \n | 3.58% | 1.79% | 2.87% | 2.87% | 7.89% | | \n | -0.64 | -4.12 | -1.12 | -0.93 | 6.80 | | \n---------------|-----------|-----------|-----------|-----------|-----------|-----------|\n 50-99 | 20 | 21 | 22 | 21 | 15 | 99 | \n | 19.87 | 17.03 | 17.03 | 16.68 | 28.39 | | \n | 0.00 | 0.92 | 1.45 | 1.12 | 6.31 | | \n | 20.20% | 21.21% | 22.22% | 21.21% | 15.15% | 35.48% | \n | 35.71% | 43.75% | 45.83% | 44.68% | 18.75% | | \n | 7.17% | 7.53% | 7.89% | 7.53% | 5.38% | | \n | 0.13 | 3.97 | 4.97 | 4.32 | -13.39 | | \n---------------|-----------|-----------|-----------|-----------|-----------|-----------|\n 100 et + | 20 | 11 | 10 | 4 | 2 | 47 | \n | 9.43 | 8.09 | 8.09 | 7.92 | 13.48 | | \n | 11.83 | 1.05 | 0.45 | 1.94 | 9.77 | | \n | 42.55% | 23.40% | 21.28% | 8.51% | 4.26% | 16.85% | \n | 35.71% | 22.92% | 20.83% | 8.51% | 2.50% | | \n | 7.17% | 3.94% | 3.58% | 1.43% | 0.72% | | \n | 10.57 | 2.91 | 1.91 | -3.92 | -11.48 | | \n---------------|-----------|-----------|-----------|-----------|-----------|-----------|\n Column Total | 56 | 48 | 48 | 47 | 80 | 279 | \n | 20.07% | 17.20% | 17.20% | 16.85% | 28.67% | | \n---------------|-----------|-----------|-----------|-----------|-----------|-----------|\n\n \nStatistics for All Table Factors\n\n\nPearson's Chi-squared test \n------------------------------------------------------------\nChi^2 = 63.54291 d.f. = 12 p = 5.063109e-09 \n\n\n \n Minimum expected frequency: 7.917563 \n```\n:::\n:::\n\n\n## Test du khi-deux {#sec-052}\nAvec le test du khi-deux, nous postulons qu'il y a indépendance entre les modalités des deux variables qualitatives, soit l'hypothèse nulle (*H~0~*). Puis, nous calculons le nombre de degrés de liberté : $DL = (n-1)(l-1)$, avec $l$ et $n$ étant respectivement les nombres de modalités en ligne et en colonne. Pour notre tableau de contingence, nous avons 12 degrés de liberté : $(4-1)(5-1)=12$. \n\nÀ partir du nombre de degrés de liberté et d'un seuil critique de significativité (prenons 5 % ici), nous pouvons trouver la valeur critique de khi-deux dans la table des valeurs critiques du khi-deux, soit 21,03 ([section @sec-141]). Puisque la valeur du khi-deux calculée dans le tableau de contingence (63,54) est bien supérieure à celle obtenue dans le tableau des valeurs critiques (21,03), nous pouvons rejeter l'hypothèse d'indépendance au seuil de 5 %. Autrement dit, si les deux variables n'étaient pas associées, nous aurions eu moins de 5 % de chances de collecter des données avec ce niveau d'association, ce qui nous permet de rejeter l'hypothèse nulle (absence d'association). Notez que le test reste significatif avec des seuils de 1 % (*p* = 0,01) et 0,1 % (*p* = 0,001) puisque les valeurs critiques sont de 26,22 et de 32,91.\n\nBien entendu, une fois que nous connaissons le nombre de degrés de liberté, nous pouvons directement calculer les valeurs critiques pour différents seuils de signification et éviter ainsi de recourir à la table du du khi-deux. Dans la même veine, nous pouvons aussi calculer la valeur de *p* d'un tableau de contingence en spécifiant le nombre de degrés de liberté et la valeur du khi-deux obtenue.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncat(\"Valeurs critiques du khi-deux avec le nombre de degrés de liberté\", \"\\n\",\n round(qchisq(p=0.95, df=12, lower.tail = FALSE),3), \"avec p=0,05\", \"\\n\",\n round(qchisq(p=0.99, df=12, lower.tail = FALSE),3), \"avec p=0,01\", \"\\n\",\n round(qchisq(p=0.999, df=12, lower.tail = FALSE),3), \"avec p=0,0001\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nValeurs critiques du khi-deux avec le nombre de degrés de liberté \n 5.226 avec p=0,05 \n 3.571 avec p=0,01 \n 2.214 avec p=0,0001\n```\n:::\n\n```{.r .cell-code}\ncat(\"Valeur de p du khi-deux obtenu (63,54291) avec 12 degrés de liberté :\", \"\\n\",\n pchisq(q=63.54291, df=12, lower.tail = FALSE))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nValeur de p du khi-deux obtenu (63,54291) avec 12 degrés de liberté : \n 5.063101e-09\n```\n:::\n:::\n\n\n\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n\n**Autres mesures d'association**\n:::\n\n::: bloc_aller_loin-body\nOutre le khi-deux, d'autres mesures d'association permettent de mesurer le degré d'association entre deux variables qualitatives. Les plus courantes sont reportées dans le @tbl-EncadreAsso. À des fins de comparaison, le khi-deux décrit précédemment est aussi reporté sur la première ligne du tableau.\n\n\n\n::: {#tbl-EncadreAsso .cell tbl-cap='Autres mesures d\\'association entre deux variables qualitatives'}\n::: {.cell-output-display}\nTable: Autres mesures d'association entre deux variables qualitatives\n\nStatistique Formule Propriété et interprétation \n----------------------------------- ------------------------------------------------------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\nKhi-deux $\\chi^2 = \\sum \\frac{(f_{ij}-ft_{ij})^2}{ft_{ij}}$ Mesure classique du khi-deux calculée à partir des différences entre les fréquences observées et attendues. Valeur de *p* disponible. \nRatio de vraisemblance du khi-deux $G^2 = 2 \\sum f_{ij} \\ln{(\\frac{f_{ij}}{ft_{ij}})}$ Calculé à partir du ratio entre les fréquences observées et attendues. Valeur de *p* disponible. \nkhi-deux de Mantel-Haenszel $Q_{MH}=(N−1)r^2$ avec *r* étant le coefficient de corrélation entre les deux variables qualitatives; par exemple, entre les valeurs des modalités de 1 à 5 de la variable *période de construction* et celles de 1 à 4 de la variable *taille du projet* HLM. Ce coefficient est très utile quand les deux variables qualitatives ne sont pas nominales, mais **ordinales**. Valeur de *p* disponible. \nCorrélation polychorique Obtenue itérativement par \\n maximum de vraisemblance Dans le même esprit que le khi-deux de Mantel-Haenszel, la corrélation polychorique s'applique à deux variables **ordinales**. Plus spécifiquement, elle formule le postulat que deux variables théoriques normalement distribuées ont été mesurées de façon approximative avec deux échelles ordinales. Par exemple, en psychologie, le sentiment de bien-être et le sentiment de sécurité peuvent être conceptualisés comme deux variables continues normalement distribuées. Cependant, les mesurer directement est très difficile, nous avons donc recours à des échelles de Likert allant de 1 à 10. Pour cet exemple, il est pertinent d'utiliser la corrélation polychorique. Comme pour une corrélation de Pearson, la corrélation polychorique varie de -1 à 1, une valeur négative indiquant une relation inverse entre les deux variables théoriques et inversement. Valeur de *p* disponible. \nCoefficient Phi $\\phi=\\sqrt{\\frac{\\chi^2}{n}}$ Simplement le khi-deux divisé par le nombre d'observations. Si les deux variables qualitatives comprennent deux modalités chacune alors $\\phi$ varie de −1 à 1; sinon, de 0 à $min(\\sqrt{c-1}, \\sqrt{l-1})$ avec *c* et *l* étant le nombre de modalités en colonne et en ligne. Par conséquent, ce coefficient est surtout utile pour les tableaux comprenant deux modalités pour chacune des variables. Pas de valeur de *p* disponible. \nV de Cramer $V=\\sqrt{\\frac{\\chi^2/n}{min(c-1,l-1)}}$ Il représente un ajustement du coefficient Phi et varie de 0 à 1. Plus sa valeur est forte, plus les deux variables sont associées. À la lecture des deux formules, vous constaterez que, pour un tableau de 2x2, la valeur du V de Carmer sera égale à celle du Coefficient Phi. Pas de valeur de *p* disponible.\n:::\n:::\n\n:::\n:::\n\n\n\n\n## Mise en œuvre dans R {#sec-053}\n\nPour calculer le khi-deux entre deux variables qualitatives, nous utilisons la fonction de base : \n\n`chisq.test(x = ..., y = ...)` qui renvoie le nombre de degrés de liberté, les valeurs du khi-deux et de *p*.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Importation du csv\ndataHLM <- read.csv(\"data/bivariee/hlm.csv\")\n# Calcul du khi-deux avec la fonction de base chisq.test\nchisq.test(x = dataHLM$Taille, y = dataHLM$Periode)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tPearson's Chi-squared test\n\ndata: dataHLM$Taille and dataHLM$Periode\nX-squared = 63.543, df = 12, p-value = 5.063e-09\n```\n:::\n:::\n\n\nPour la construction du tableau de contingence, deux options sont possibles dépendamment de la structure de votre tableau de données. Premier cas de figure : votre tableau comprend une ligne par observation avec les différentes modalités dans deux colonnes (ici *Periode* et *Taille*). Dans la syntaxe ci-dessous, pour chacune des deux variables qualitatives, nous créons un facteur afin de spécifier un intitulé à chaque modalité (`factor(levels =c(....), labels = c(..)`). Puis, nous utilisons la fonction `CrossTable` du *package* `gmodels`. Pour obtenir les fréquences théoriques, les contributions locales au khi-deux et les déviations, nous spécifions les options suivantes : `expected = TRUE, chisq=TRUE, resid=TRUE`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"gmodels\")\n# Premiers enregistrements du tableau\nhead(dataHLM)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Periode Taille\n1 5 1\n2 5 1\n3 5 2\n4 5 1\n5 5 1\n6 5 2\n```\n:::\n\n```{.r .cell-code}\n# La variable Periode comprend 5 modalités (de 1 à 5)\ntable(dataHLM$Periode)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n 1 2 3 4 5 \n56 48 48 47 80 \n```\n:::\n\n```{.r .cell-code}\n# La variable Taille comprend 4 modalités (de 1 à 4)\ntable(dataHLM$Taille)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n 1 2 3 4 \n80 53 99 47 \n```\n:::\n\n```{.r .cell-code}\n# Création d'un facteur pour les cinq modalités de la période de construction\ndataHLM$Periode <- factor(dataHLM$Periode, \n levels = c(1,2,3,4,5), \n labels = c(\"<1975\", \n \"1975-1979\", \n \"1980-1984\", \n \"1985-1989\", \n \"1990-1994\"))\n# Création d'un facteur pour les quatre modalités de la taille des habitations\ndataHLM$Taille <- factor(dataHLM$Taille, \n levels = c(1,2,3,4), \n labels = c(\"<25 log.\", \n \"25-49\", \n \"50-99\", \n \"100 et +\"))\n# Pour construire un tableau de contingence, nous utilisons \n# la fonction CrossTable du package gmodels. \n# Les deux lignes ci-dessous sont mises en commentaire pour ne pas répéter le tableau.\n# CrossTable(x=dataHLM$Taille, y = dataHLM$Periode, digits = 2,\n# expected = TRUE, chisq = TRUE, resid = TRUE, format=\"SPSS\")\n```\n:::\n\n\nDeuxième cas de figure : vous disposez déjà d'un tableau de contingence, soit les fréquences observées ($f_{ij}$). Nous n'utilisons donc pas la fonction `CrossTable`, mais directement la fonction `chisq.test`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Importation des données\ndf1 <- read.csv(\"data/bivariee/data_transport.csv\", stringsAsFactors = FALSE)\ndf1 # Visualisation du tableau\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n ModeTransport Homme Femme\n1 Automobile, camion ou fourgonnette - conducteur 689400 561830\n2 Automobile, camion ou fourgonnette - passager 21315 40010\n3 Transport en commun 181435 238330\n4 A pied 43715 54360\n5 Bicyclette 24295 13765\n6 Autre moyen 8395 6970\n```\n:::\n\n```{.r .cell-code}\nMatrice <- as.matrix(df1[, c(\"Homme\" , \"Femme\")])\ndimnames(Matrice) <- list(unique(df1$ModeTransport), Sexe=c(\"Homme\" , \"Femme\"))\n# Notez que vous pouvez saisir vos données directement si vous avez peu d'observations\nFemme <- c(689400, 21315, 181435, 43715, 24295, 8395) # Vecteur de valeurs pour les femmes\nHomme <- c(561830, 40010, 238330, 54360, 13765, 6970) # Vecteur de valeurs pour les hommes\nMatrice <- as.table(cbind(Femme, Homme)) # Création du tableau\n# Nom des deux variables et de leurs modalités respectives\ndimnames(Matrice) <- list(Transport=c(\"Automobile (conducteur)\",\n \"Automobile (passager)\",\n \"Transport en commun\", \n \"À pied\",\n \"Bicyclette\",\n \"Autre moyen\"),\n Sexe=c(\"Homme\" , \"Femme\"))\n# Test du khi-deux\ntest <- chisq.test(Matrice)\nprint(test)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tPearson's Chi-squared test\n\ndata: Matrice\nX-squared = 29134, df = 5, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\n# Fréquences observées (Fij)\ntest$observed\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Sexe\nTransport Homme Femme\n Automobile (conducteur) 689400 561830\n Automobile (passager) 21315 40010\n Transport en commun 181435 238330\n À pied 43715 54360\n Bicyclette 24295 13765\n Autre moyen 8395 6970\n```\n:::\n\n```{.r .cell-code}\n# Fréquences théoriques (FTij)\nround(test$expected,0)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Sexe\nTransport Homme Femme\n Automobile (conducteur) 643313 607917\n Automobile (passager) 31530 29795\n Transport en commun 215820 203945\n À pied 50425 47650\n Bicyclette 19568 18492\n Autre moyen 7900 7465\n```\n:::\n\n```{.r .cell-code}\n# Déviations (Fij - FTij)\nround(test$observed-test$expected,0)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Sexe\nTransport Homme Femme\n Automobile (conducteur) 46087 -46087\n Automobile (passager) -10215 10215\n Transport en commun -34385 34385\n À pied -6710 6710\n Bicyclette 4727 -4727\n Autre moyen 495 -495\n```\n:::\n\n```{.r .cell-code}\n# Contributions au khi-deux\nround((test$observed-test$expected)^2/test$expected,2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Sexe\nTransport Homme Femme\n Automobile (conducteur) 3301.74 3493.98\n Automobile (passager) 3309.37 3502.05\n Transport en commun 5478.22 5797.18\n À pied 892.81 944.80\n Bicyclette 1141.71 1208.19\n Autre moyen 31.04 32.85\n```\n:::\n\n```{.r .cell-code}\n# Marges en ligne et en colonne\ncolSums(Matrice)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Homme Femme \n968555 915265 \n```\n:::\n\n```{.r .cell-code}\nrowSums(Matrice)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nAutomobile (conducteur) Automobile (passager) Transport en commun \n 1251230 61325 419765 \n À pied Bicyclette Autre moyen \n 98075 38060 15365 \n```\n:::\n\n```{.r .cell-code}\n# Grand total\nsum(Matrice)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 1883820\n```\n:::\n\n```{.r .cell-code}\n# Pourcentages\nround(Matrice/sum(Matrice)*100,2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Sexe\nTransport Homme Femme\n Automobile (conducteur) 36.60 29.82\n Automobile (passager) 1.13 2.12\n Transport en commun 9.63 12.65\n À pied 2.32 2.89\n Bicyclette 1.29 0.73\n Autre moyen 0.45 0.37\n```\n:::\n\n```{.r .cell-code}\n# Pourcentages en ligne\nround(Matrice/rowSums(Matrice)*100,2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Sexe\nTransport Homme Femme\n Automobile (conducteur) 55.10 44.90\n Automobile (passager) 34.76 65.24\n Transport en commun 43.22 56.78\n À pied 44.57 55.43\n Bicyclette 63.83 36.17\n Autre moyen 54.64 45.36\n```\n:::\n\n```{.r .cell-code}\n# Pourcentages en colonne\nround(Matrice/colSums(Matrice)*100,2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Sexe\nTransport Homme Femme\n Automobile (conducteur) 71.18 58.01\n Automobile (passager) 2.33 4.37\n Transport en commun 18.73 24.61\n À pied 4.78 5.94\n Bicyclette 2.51 1.42\n Autre moyen 0.92 0.76\n```\n:::\n:::\n\n\nPour obtenir les autres mesures d'association (@tbl-MesuresAssociations), nous pourrons utiliser la syntaxe suivante :\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf1 <- read.csv(\"data/bivariee/hlm.csv\")\n# Fonction pour calculer les autres mesures d'association\nAutresMesuresKhi2 <- function(x, y){\n testChi2 <- chisq.test(x, y) # Calcul du khi-deux\n n <- sum(testChi2$observed) # Nombre d'observations\n nc <- ncol(testChi2$observed) # Nombre de colonnes\n l <- nrow(testChi2$observed) # Nombre de lignes\n dl <- (nc-1)*(l-1) # Nombre de degrés de libertés\n chi2 <- testChi2$statistic # Valeur du khi-deux\n Pchi2 <- testChi2$p.value # P pour le khi-deux\n \n #Ratio de vraisemblance du khi-deux\n G <- 2*sum(testChi2$observed*log(testChi2$observed/testChi2$expected)) # G2\n PG <- pchisq(G, df=dl, lower.tail = FALSE) # P pour le G22\n \n # khi-deux de Mantel-Haenszel avec le package DescTools\n MHTest <- DescTools::MHChisqTest(testChi2$observed)\n MH <- MHTest$statistic\n PMH <- MHTest$p.value\n \n # Coefficient de correlation polychorique\n df1 <- data.frame(\"x\" = as.factor(x),\n \"y\" = as.factor(y))\n polychoricCorr <- correlation::cor_test(df1,\"x\" , \"y\", method = \"polychoric\")\n polyR <- polychoricCorr$rho\n polyP <- polychoricCorr$p\n\n # Coefficient Phi et V de Cramer\n phi <- sqrt(chi2/n)\n vc <- sqrt(chi2/(n*min(nc-1,l-1)))\n \n # Tableau pour les résultats\n dfsortie <- data.frame(\n Statistique = c(\"Khi-deux\", \n \"Ratio de vraisemblance du khi-deux\", \n \"Khi-deux de Mantel-Haenszel\",\n \"Corrélation Polychorique\",\n \"Coefficient de Phi\",\n \"V de Cramer\"), \n Valeur = round(c(chi2, G, MH, polyR, phi, vc),3), \n P = round(c(Pchi2, PG, PMH, polyP , NA, NA),10))\n return(dfsortie)\n}\n\ndfkhi2 <- AutresMesuresKhi2(df1$Periode, df1$Taille)\n\n# Impression du tableau avec le package stargazer\nlibrary(stargazer)\nstargazer(dfkhi2, type = \"text\", summary = FALSE, rownames = FALSE, align = FALSE, digits = 3,\n title = \"Mesures d'association entre les deux variables qualitatives\")\n```\n:::\n\n::: {#tbl-MesuresAssociations .cell tbl-cap='Mesures d\\'association entre deux variables qualitatives'}\n::: {.cell-output-display}\n|Statistique | Valeur| P|\n|:-----------------------------------|------:|--:|\n|Khi-deux | 63.543| 0|\n|Ratio de vraisemblance du khi-deux | 67.286| 0|\n|Khi-deux de Mantel-Haenszel | 48.486| 0|\n|Corrélation Polychorique | -0.479| 0|\n|Coefficient de Phi | 0.477| |\n|V de Cramer | 0.276| |\n:::\n:::\n\n\n## Interprétation d'un tableau de contingence {#sec-054}\n\nNous vous proposons une démarche très simple pour vérifier l'association entre deux variables qualitatives avec les deux étapes suivantes :\n\n* Nous posons l'hypothèse nulle (*H~0~*), soit l'indépendance entre les deux variables. \n\n* Si la valeur du khi-deux total du tableau de contingence est inférieure à la valeur critique du khi-deux avec *p* = 0,05 et le nombre de degrés de liberté de la table des valeurs critiques de khi-deux, alors il y a bien indépendance. La valeur de *p* est alors supérieure à 0,05. **L'analyse s'arrête donc là!** Autrement dit, il n'est pas nécessaire d'analyser le contenu de votre tableau de contingence puisqu'il n'y a pas d'association significative entre les modalités des deux variables. Vous pouvez simplement signaler que selon les résultats du test du khi-deux, il n'y a pas d'association significative entre les deux variables ($\\chi$ = ... avec *p* = ...).\n\n* S'il y a dépendance ($khi_{observé}^2 > khi_{critique}^2$), trouvez les cellules *ij* où les contributions au khi-deux sont les plus fortes, c'est-à-dire où les associations entre les modalités *i* de la variable en ligne et les modalités *j* de la variable en colonne sont les plus marquées. Pour ces cellules, le phénomène *ij* est surreprésenté si la déviation est positive ou sous-représenté si la déviation est négative. Commentez ces associations et utilisez les pourcentages en ligne ou en colonne pour appuyer vos propos.\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Repérer les contributions au khi-deux les plus importantes**\n:::\n::: bloc_astuce-body\nPour repérer rapidement les cellules où les contributions au khi-deux sont les plus fortes, vous pouvez construire un graphique avec la fonction `mosaic` du *package* `vcd`. À la @fig-VDC, la taille des rectangles représente les effectifs entre les deux modalités tandis que les associations sont représentées comme suit : \nen gris lorsqu'elles ne sont pas significatives, en rouge pour des déviations significatives et négatives et en bleu pour des déviations significatives et positives.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(vcd)\nmosaic(~ Taille+Periode, \n data = dataHLM, shade = TRUE, legend = TRUE,\n labeling = labeling_border(rot_labels = c(45, 90),\n just_labels = c(\"left\", \"center\")))\n```\n\n::: {.cell-output-display}\n![Figure avec la fonction mosaic du package vcd](05-bivarieeQualiQuali_files/figure-html/fig-VDC-1.png){#fig-VDC fig-align='center' width=65%}\n:::\n:::\n\n:::\n:::\n\n**Exemple d'interprétation.** « Les résultats du test du khi-deux signalent qu'il existe des associations entre les modalités de la taille et de la période de construction des projets d'habitation ($\\chi$ = 63,5, *p* < 0,001). Les fortes contributions au khi-deux et le signe positif ou négatif des déviations correspondantes permettent de repérer cinq associations majeures entre les modalités de taille et de période de construction des projets HLM : **1)** la répulsion entre les projets d’habitation de moins de 25 logements et la période de construction 1964-1974; **2)** l’attraction entre les projets d’habitation de 100 logements et plus et la période de construction de 1969-1974; **3)** l’attraction entre les projets d’habitation de moins de 25 logements et la période de construction de 1990-1994; **4)** la répulsion entre les projets d’habitation de 50 à 99 logements et la période de construction 1990-1994; **5)** la répulsion entre les projets d’habitation de 100 logements et plus et la période de construction 1990-1994.\nOn observe donc une tendance bien marquée dans l’évolution du type de construction entre 1970 et 1994 : entre 1969 et 1974, on a construit de grandes habitations dépassant souvent 100 logements; du milieu des années 1970 à la fin des années 1980, on privilégie la construction d’habitations de taille plus modeste, entre 50 et 100 logements; tandis qu’au début des années 1990, on opte plutôt pour des habitations de taille réduite (moins de 50 logements). Quelques chiffres à l’appui : sur les 56 habitations réalisées entre 1969 et 1974, 20 ont plus de 100 logements, 20 comprennent entre 50 et 99 logements et seules 10 ont moins de 25 logements. Près de la moitié des habitations construites entre 1975 et 1989 regroupent 50 à 99 logements (43,8 % pour la période 1975-1979, 45,8 % pour 1980-1984 et 44,7 % pour 1985-1989). Par contre, 51 % des habitations érigés à partir de 1990 disposent de moins de 25 logements » (@TheseApparicio, p. 117-118). Notez que cette évolution décroissante est aussi soutenue par le coefficient négatif de la corrélation polychorique.\n\nVous pouvez aussi construire un graphique pour appuyer vos constats, soit avec les pourcentages en ligne ou en colonne (@fig-hml tirée de @TheseApparicio).\n\n\n![Taille des projets d'habitation à loyer modique selon la période de construction](images/Chap05/figurehlm.png){#fig-hml width=\"80%\" fig-align=\"center\"}\n\n\n**Comment rapporter succinctement les résultats d'un test du khi-deux?**\n\nLe test du khi-deux a été réalisé pour examiner la relation entre la taille et la période de construction des habitations HLM. Cette relation est significative : $\\chi^2$(12, N = 279) = 63,5, *p* < 0,001. Plus les projets ont été construites récemment, plus ils sont de taille réduite.\n\nPour un texte en anglais, consultez [https://www.socscistatistics.com/tutorials/chisquare/default.aspx](https://www.socscistatistics.com/tutorials/chisquare/default.aspx){target=\"_blank\"}.\n\n## Quiz de révision du chapitre {#sec-055}\n\n\n
\n\n\n\n
\n
Pour analyser la relation entre deux variables qualitatives, vous utilisez :
\n
Relisez au besoin l'introduction du [chapitre @sec-chap05].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Dans un tableau de contingence, quels sont les éléments disponibles?
\n
Relisez au besoin la [section @sec-051].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
La corrélation polychorique est particulièrement bien adaptée pour mesurer l'association entre deux variables qualitatives :
\n
Relisez au besoin l'encadré à la [section @sec-052].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
S'il y a indépendance entre les deux variables qualitatives (khi-deux observé inférieur au khi-deux critique), il n'est pas nécessaire d'analyser en détail le tableau de contingence.
\n
Relisez au besoin la [section @sec-054].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n\n
\n\n
\n
\n", + "supporting": [ + "05-bivarieeQualiQuali_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/05-bivarieeQualiQuali_files/figure-html/fig-VDC-1.png b/.quarto/_freeze/05-bivarieeQualiQuali/figure-html/fig-VDC-1.png similarity index 100% rename from docs/05-bivarieeQualiQuali_files/figure-html/fig-VDC-1.png rename to .quarto/_freeze/05-bivarieeQualiQuali/figure-html/fig-VDC-1.png diff --git a/.quarto/_freeze/06-bivarieeQualiQuanti/execute-results/html.json b/.quarto/_freeze/06-bivarieeQualiQuanti/execute-results/html.json new file mode 100644 index 0000000..55831df --- /dev/null +++ b/.quarto/_freeze/06-bivarieeQualiQuanti/execute-results/html.json @@ -0,0 +1,16 @@ +{ + "hash": "1ee2be6b842462e24a956458133044c8", + "result": { + "markdown": "# Relation entre une variable qualitative et une variable quantitative {#sec-chap06}\n\nDans le cadre de ce chapitre, nous présentons les principales méthodes permettant d'explorer les associations entre une variable quantitative et une variable qualitative avec deux modalités (tests de Student, de Welch et de Wilcoxon) ou avec plus de deux modalités (ANOVA et test de Kruskal-Wallis).\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l’unique!\n - `ggpubr` pour combiner des graphiques.\n* Pour manipuler des données : \n - `dplyr`, avec les fonctions `group_by`, `summarize` et les pipes `%>%`.\n* Pour les test *t* : \n - `sjstats` pour réaliser des tests *t* pondérés.\n - `effectsize` pour calculer les tailles d'effet de tests *t*.\n* Pour la section sur les ANOVA : \n - `car` pour les ANOVA classiques.\n - `lmtest` pour le test de Breusch-Pagan d'homogénéité des variances.\n - `rstatix` intégrant de nombreux tests classiques (comme le test de Shapiro) avec `tidyverse`.\n* Autre *package* : \n - `foreign` pour importer des fichiers externes.\n:::\n:::\n\n\n## Relation entre une variable quantitative et une variable qualitative à deux modalités {#sec-061}\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Les moyennes de deux groupes de population sont-elles significativement différentes?**\n:::\n::: bloc_objectif-body\nNous souhaitons ici comparer deux groupes de population en fonction d'une variable continue. \nPar exemple, pour deux échantillons respectivement d'hommes et de femmes travaillant dans le même secteur d'activité, nous pourrions souhaiter vérifier si les moyennes des salaires des hommes et des femmes sont différentes et ainsi vérifier la présence ou l'absence d'une iniquité systématique. En études urbaines, dans le cadre d'une étude sur un espace public, nous pourrions vouloir vérifier si la différence des moyennes du sentiment de sécurité des femmes et des hommes est significative (c'est-à-dire différente de 0).\n\n**Pour un même groupe, la moyenne de la différence d'un phénomène donné mesuré à deux moments est-elle ou non égale à zéro?** \n\nAutrement dit, nous cherchons à comparer un même groupe d'individus avant et après une expérimentation ou dans deux contextes différents. Prenons un exemple d'application en études urbaines. Dans le cadre d'une étude sur la perception des risques associés à la pratique du vélo en ville, 50 personnes utilisant habituellement l'automobile pour se rendre au travail sont recrutées. L'expérimentation pourrait consister à leur donner une formation sur la pratique du vélo en ville et à les accompagner quelques jours durant leurs déplacements domicile-travail. Nous évaluerons la différence de leurs perceptions des risques associés à la pratique du vélo sur une échelle de 0 à 100 avant et après l'expérimentation. Nous pourrions supposer que la moyenne des différences est significativement négative, ce qui indiquerait que la perception du risque a diminué après l'expérimentation; autrement dit, la perception du risque serait plus faible en fin de période. \n:::\n:::\n\n\n\n### Test *t* et ses différentes variantes {#sec-0611}\n\nLe **t de Student**, appelé aussi **test _t_** (*t-test* en anglais), est un test paramétrique permettant de comparer les moyennes de deux groupes (échantillons), qui peuvent être indépendantes ou non :\n\n* **Échantillons indépendants (dits non appariés)** : les observations de deux groupes qui n'ont aucun lien entre eux. Par exemple, nous souhaitons vérifier si les moyennes du sentiment de sécurité des hommes et des femmes, ou encore si, les moyennes des loyers entre deux villes sont statistiquement différentes. Ainsi, les tailles des deux échantillons peuvent être différentes ($n_a \\neq n_b$).\n\n* **Échantillons dépendants (dits appariés)** : les individus des deux groupes sont les mêmes et sont donc associés par paires. Autrement dit, nous avons deux séries de valeurs de taille identique $n_a = n_b$ et $n_{ai}$ est le même individu que $n_{bi}$. Ce type d'analyse est souvent utilisée en études cliniques : pour $n$ individus, nous disposons d'une mesure quantitative de leur état de santé pour deux séries (l'une avant le traitement, l'autre une fois le traitement terminé). Cela permet de comparer les mêmes individus avant et après un traitement; nous parlons alors d'étude, d'expérience ou d'analyse pré-post. Concrètement, nous cherchons à savoir si la moyenne des différences des observations avant et après est significativement différente de 0. Si c'est le cas, nous pouvons conclure que l'expérimentation a eu un impact sur le phénomène mesuré (variable continue). Ce type d'analyse pré-post peut aussi être utilisé pour évaluer l'impact du réaménagement d'un espace public (rue commerciale, place publique, parc, etc.). Par exemple, nous pourrions questionner le même échantillon de commerçant(e)s ou personnes l'utilisant avant et après le réaménagement d'une artère commerciale.\n\n**Condition d'application**. Pour utiliser les tests de Student et de Welch, la variable continue doit être normalement distribuée. Si elle est fortement anormale, nous utiliserons le test non paramétrique de Wilcoxon ([section @sec-0612]). Il existe trois principaux tests pour comparer les moyennes de deux groupes :\n\n* Test de Student (test *t*) avec échantillons indépendants et variances similaires (méthode *pooled*). Les variances de deux groupes sont semblables quand leur ratio varie de 0,5 à 2, soit $\\mbox{0,5}< (S^2_{X_A}/S^2_{X_B})<\\mbox{2}$.\n\n* Test de Welch (appelé aussi Satterthwaite) avec échantillons indépendants quand les variances des deux groupes sont dissemblables.\n\n* Test de Student (test *t*) avec échantillons dépendants.\n\nIl s'agit de vérifier si les moyennes des deux groupes sont statistiquement différentes avec les étapes suivantes :\n\n* Nous posons l'hypothèse nulle (*H~0~*), soit que les moyennes des deux groupes *A* et *B* ne sont pas différentes ($\\bar{X}_{A}=\\bar{X}_{B}$) ou, autrement dit, la différence des deux moyennes est nulle ($\\bar{X}_{A}-\\bar{X}_{B}=0$). L'hypothèse alternative (*H~1~*) est donc $\\bar{X}_{A}\\ne\\bar{X}_{B}$.\n\n* Nous calculons la valeur de *t* et le nombre de degrés de liberté. La valeur de *t* est négative quand la moyenne du groupe A est inférieure au groupe B et inversement.\n\n* Nous comparons la valeur absolue de *t* ($\\mbox{|t|}$) avec celle issue de la table des valeurs critiques de T ([section @sec-132]) avec le bon nombre de degrés de liberté et en choisissant un degré de signification (habituellement, *p* = 0,05). Si $\\mbox{|t|}$ est supérieure à la valeur *t* critique, alors les moyennes sont statistiquement différentes au degré de signification retenu.\n\n* Si les moyennes sont statistiquement différentes, nous pouvons calculer la taille de l'effet.\n\n\n**Cas 1. Test de Student pour des échantillons indépendants avec des variances similaires (méthode *pooled*).** La valeur de *t* est le ratio entre la différence des moyennes des deux groupes (numérateur) et l'erreur type groupée des deux échantillons (dénominateur) :\n\n$$\nt = \\frac{\\bar{X}_{A}-\\bar{X}_{B}}{\\sqrt{\\frac{S^2_p}{n_A}+\\frac{S^2_p}{n_B}}}\\mbox{ avec } S^2_p = \\frac{(n_A-1)S^2_{X_A}+(n_B-1)S^2_{X_B}}{n_A+n_B-2}\n$$ {#eq-cas1pooled}\n\n\navec $n_A$,$n_B$, $S^2_{X_A}$ et $S^2_{X_B}$ étant respectivement les nombres d'observations et les variances pour les groupes *A* et *B*, $S^2_p$ étant la variance groupée des deux échantillons et $n_A+n_B-2$ étant le nombre de degrés de liberté.\n\n**Cas 2. Test de Welch pour des échantillons indépendants (avec variances dissemblables).** Le test de Welch est très similaire au test de Student; seul le calcul de la valeur de _t_ est différent, pour tenir compte des variances respectives des groupes :\n\n$$\nt = \\frac{\\bar{X}_{A}-\\bar{X}_{B}}{\\sqrt{\\frac{S^2_{X_A}}{n_A}+\\frac{S^2_{X_B}}{n_B}}} \\mbox{ et } dl = \\frac{ \\left( \\frac{S^2_{X_A}}{n_A}+\\frac{S^2_{X_B}}{n_B} \\right)^2} {\\frac{S^4_{X_A}}{n^2_A(n_A-1)}+\\frac{S^4_{X_B}}{n^2_B(n_B-1)}}\n$$ {#eq-cas2welch}\n\nDans la syntaxe ci-dessous, nous avons écrit une fonction dénommée `test_independants` permettant de calculer les deux tests pour des échantillons indépendants. Dans cette fonction, vous pouvez repérer comment sont calculés les moyennes, les nombres d'observations et les variances pour les deux groupes, le nombre de degrés de liberté et les valeurs de *t* et de *p* pour les deux tests. Puis, nous avons créé aléatoirement deux jeux de données relativement à la vitesse de déplacement de cyclistes utilisant un vélo personnel ou un vélo en libre-service (généralement plus lourd) :\n\n* Au cas 1, 60 cyclistes utilisant un vélo personnel roulant en moyenne à 18 km/h (écart-type de 1,5) et 50 autres utilisant un système de vélopartage avec une vitesse moyenne de 15 km/h (écart-type de 1,5).\n\n* Au cas 2, 60 cyclistes utilisant un vélo personnel roulant en moyenne à 16 km/h (écart-type de 3) et 50 autres utilisant un système de vélopartage avec une vitesse moyenne de 15 km/h (écart-type de 1,5). Ce faible écart des moyennes, combiné à une plus forte variance réduit la significativité de la différence entre les deux groupes.\n\nD'emblée, l'analyse visuelle des boîtes à moustaches (@fig-ttest1) signale qu'au cas 1, contrairement au cas 2, les groupes sont plus homogènes (boîtes plus compactes) et les moyennes semblent différentes (les boîtes sont centrées différemment sur l'axe des ordonnées). Cela est confirmé par les résultats des tests.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(\"ggplot2\")\nlibrary(\"ggpubr\")\n# fonction ------------------\ntstudent_independants <- function(A, B){\n x_a <- mean(A) # Moyenne du groupe A\n x_b <- mean(B) # Moyenne du groupe B\n var_a <- var(A) # Variance du groupe A\n var_b <- var(B) # Variance du groupe B\n sd_a <- sqrt(var_a) # Écart-type du groupe A\n sd_b <- sqrt(var_b) # Écart-type du groupe B\n ratio_v <- var_a / var_b # ratio des variances\n n_a <- length(A) # nombre d'observation du groupe A\n n_b <- length(B) # nombre d'observation du groupe B\n \n # T-test (variances égales)\n dl_test <- n_a+n_b-2 # degrés de liberté\n PooledVar <- (((n_a-1)*var_a)+((n_b-1)*var_b))/dl_test\n t_test <- (x_a-x_b) / sqrt(((PooledVar/n_a)+(PooledVar/n_b)))\n p_test <- 2*(1-(pt(abs(t_test), dl_test))) \n # Test Welch-Sattherwaite (variances inégales)\n t_welch <- (x_a-x_b) / sqrt( (var_a/n_a) + (var_b/n_b))\n dl_num = ((var_a/n_a) + (var_b/n_b))^2\n dl_dem = ((var_a/n_a)^2/(n_a-1)) + ((var_b/n_b)^2/(n_b-1))\n dl_welch = dl_num / dl_dem # degrés de liberté\n p_welch <- 2*(1-(pt(abs(t_welch), dl_welch))) \n \n cat(\"\\n groupe A (n = \", n_a,\"), moy = \", round(x_a,1),\", \n variance = \", round(var_a,1),\", écart-type = \", round(sd_a,1),\n \"\\n groupe B (n = \", n_b,\"), moy = \", round(x_b,1),\", \n variance = \", round(var_b,1),\", écart-type = \", round(sd_b,1),\n \"\\n ratio variance = \", round(ratio_v,2),\n \"\\n t-test (variances égales): t(dl = \", dl_test, \") = \", round(t_test,4),\n \", p = \", round(p_test,6),\n \"\\n t-Welch (variances inégales): t(dl = \", round(dl_welch,3), \") = \",\n round(t_welch,4), \", p = \", round(p_welch,6), sep = \"\") \n \n if (ratio_v > 0.5 && ratio_v < 2) {\n cat(\"\\n Variances semblables. Utilisez le test de Student!\")\n p <- p_test\n } else {\n cat(\"\\n Variances dissemblables. Utilisez le test de Welch-Satterwaithe!\")\n p <- p_welch\n }\n \n if (p <=.05){\n cat(\"\\n Les moyennes des deux groupes sont significativement différentes.\")\n } else {\n cat(\"\\n Les moyennes des deux groupes ne sont pas significativement différentes.\")\n }\n}\n# CAS 1 : données fictives ------------------\n# Création du groupe A : 60 observations avec une vitesse moyenne de 18 et un écart-type de 1,5\nVelo1A <- rnorm(60,18,1.5)\n# Création du groupe B : 50 observations avec une vitesse moyenne de 15 et un écart-type de 1,5\nVelo1B <- rnorm(50,15,1.5)\ndf1 <- data.frame(\n vitesse = c(Velo1A,Velo1B), \n type = c(rep(\"Vélo personnel\", length(Velo1A)), rep(\"Vélopartage\", length(Velo1B)))\n)\nboxplot1 <- ggplot(data = df1, mapping=aes(x = type, y = vitesse, colour = type)) +\n geom_boxplot(width=0.2)+\n ggtitle(\"Données fictives (cas 1)\")+\n xlab(\"Type de vélo\")+\n ylab(\"Vitesse de déplacement (km/h)\")+\n theme(legend.position = \"none\")\n# CAS 2 : données fictives ------------------\n# Création du groupe A : 60 observations avec une vitesse moyenne de 18 et un écart-type de 3\nVelo2A <- rnorm(60,16,3)\n# Création du groupe B : 50 observations avec une vitesse moyenne de 15 et un écart-type de 1,5\nVelo2B <- rnorm(50,15,1.5)\ndf2 <- data.frame(\n vitesse = c(Velo2A,Velo2B), \n type = c(rep(\"Vélo personnel\", length(Velo2A)), rep(\"Vélopartage\", length(Velo2B)))\n)\nboxplot2 <- ggplot(data = df2, mapping=aes(x = type, y = vitesse, colour = type)) +\n geom_boxplot(width=0.2)+\n ggtitle(\"Données fictives (cas 2)\")+\n xlab(\"Type de vélo\")+\n ylab(\"Vitesse de déplacement (km/h)\")+\n theme(legend.position = \"none\")\nggarrange(boxplot1, boxplot2, ncol = 2, nrow = 1)\n# Appel de la fonction pour le cas 1\ntstudent_independants(Velo1A, Velo1B)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n groupe A (n = 60), moy = 18, \n variance = 3, écart-type = 1.7\n groupe B (n = 50), moy = 15, \n variance = 2.1, écart-type = 1.4\n ratio variance = 1.46\n t-test (variances égales): t(dl = 108) = 9.7652, p = 0\n t-Welch (variances inégales): t(dl = 107.995) = 9.9354, p = 0\n Variances semblables. Utilisez le test de Student!\n Les moyennes des deux groupes sont significativement différentes.\n```\n:::\n\n```{.r .cell-code}\n# Appel de la fonction pour le cas 2\ntstudent_independants(Velo2A, Velo2B)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n groupe A (n = 60), moy = 15.6, \n variance = 11.7, écart-type = 3.4\n groupe B (n = 50), moy = 14.9, \n variance = 2, écart-type = 1.4\n ratio variance = 5.72\n t-test (variances égales): t(dl = 108) = 1.3623, p = 0.175933\n t-Welch (variances inégales): t(dl = 82.013) = 1.4531, p = 0.150022\n Variances dissemblables. Utilisez le test de Welch-Satterwaithe!\n Les moyennes des deux groupes ne sont pas significativement différentes.\n```\n:::\n\n::: {.cell-output-display}\n![Boîtes à moustaches sur des échantillons fictifs non appariés](06-bivarieeQualiQuanti_files/figure-html/fig-ttest1-1.png){#fig-ttest1 fig-align='center' width=75%}\n:::\n:::\n\n\n\n#### Principe de base et formulation pour des échantillons dépendants (appariés) {#sec-06111}\n\nNous disposons de plusieurs personnes pour lesquelles nous avons mesuré un phénomène (variable continue) à deux temps différents : généralement avant et après une expérimentation (analyse pré-post). Il s'agit de vérifier si la moyenne des différences des observations avant et après la période est différente de 0. Pour ce faire, nous réalisons les étapes suivantes :\n\n* Nous posons l'hypothèse nulle (*H~0~*), soit que la moyenne des différences entre les deux séries est égale à 0 ($\\bar{D} = 0$ avec $d = {x}_{t_1}- {x}_{t_2}$). L'hypothèse alternative (*H~1~*) est donc $\\bar{D} \\ne 0$. Notez que nous pouvons tester une autre valeur que 0.\n\n* Nous calculons la valeur de *t* et le nombre de degrés de liberté. La valeur de *t* est négative quand la moyenne des différences entre ${X}_{t_1}$ et ${X}_{t_2}$ est négative et inversement.\n\n* Nous comparons la valeur absolue de *t* ($\\mbox{|t|}$) avec celle issue de la table des valeurs critiques de T avec le nombre de degrés de liberté et en choisissant un degré de signification (habituellement, *p* = 0,05). Si $\\mbox{|t|}$ est supérieure à la valeur *t* critique, alors les moyennes sont statistiquement différentes au degré de signification retenu.\n\nPour le test de Student avec des échantillons appariés, la valeur de *t* se calcule comme suit :\n\n$$\nt = \\frac{\\bar{D}-\\mu_0}{\\sigma_D / \\sqrt{n}}\n$$ {#eq-ttestapparie}\n\n\navec $\\bar{D}$ étant la moyenne des différences entre les observations appariées de la série A et de la série B, $\\sigma_D$ l'écart des différences, *n* le nombre d'observations, et finalement $\\mu_0$ la valeur de l'hypothèse nulle que nous voulons tester (habituellement 0). Bien entendu, il est possible de fixer une autre valeur pour $\\mu_0$ : par exemple, avec $\\mu_0 = 10$, nous chercherions ainsi à vérifier si la moyenne des différences est significativement différente de 10. Le nombre de degrés de liberté est égal à $n-1$.\n\nDans la syntaxe ci-dessous, nous avons écrit une fonction dénommée `tstudent_dependants` permettant de réaliser le test de Student pour des échantillons appariés. Dans cette fonction, vous pouvez repérer comment sont calculés la différence entre les observations pairées, la moyenne et l'écart-type de cette différence, puis le nombre de degrés de liberté, les valeurs de *t* et de *p* pour les deux tests.\n\nPour illustrer l'utilisation de la fonction, nous avons créé aléatoirement deux jeux de données. Imaginons que ces données décrivent 50 personnes utilisant habituellement l'automobile pour se rendre au travail. Pour ces personnes, nous avons généré des valeurs du risque perçu de l'utilisation du vélo (de 0 à 100), et ce, avant et après une période de 20 jours ouvrables durant lesquels elles devaient impérativement se rendre au travail à vélo.\n\n* Au cas 1, les valeurs de risque ont une moyenne de 70 avant l'expérimentation et de 50 après l'expérimentation, avec des écarts-types de 5.\n\n* Au cas 2, les valeurs de risque ont une moyenne de 70 avant et de 66 après, avec des écarts-types de 5.\n\nD'emblée, l'analyse visuelle des boîtes à moustaches (@fig-ttest2) pairées montre que la perception du risque semble avoir nettement diminué après l'expérimentation pour le cas 1, mais pas pour le cas 2. Cela est confirmé par les résultats des tests.\n\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(\"ggplot2\")\nlibrary(\"ggpubr\")\ntstudent_dependants <- function(A, B, mu = 0){\n d <- A-B # différences entre les observations pairées\n moy <- mean(d) # Moyenne des différences\n e_t <- sd(d) # Écart-type des différences\n n <- length(A) # nombre d'observations\n dl <- n-1 # nombre de degrés de liberté (variances égales)\n \n t <- (moy- mu) / (e_t/sqrt(n)) # valeur de t\n p <- 2*(1-(pt(abs(t), dl)))\n \n cat(\"\\n groupe A : moy = \", round(mean(A),1),\", var = \", \n round(var(A),1),\", sd = \", round(sqrt(var(A)),1),\n \"\\n groupe B : moy = \", round(mean(B),1),\", var = \", \n round(var(B),1),\", sd = \", round(sqrt(var(B)),1),\n \"\\n Moyenne des différences = \", round(mean(moy),1),\n \"\\n Ecart-type des différences = \", round(mean(e_t),1),\n \"\\n t(dl = \", dl, \") = \", round(t,2),\n \", p = \", round(p,3), sep = \"\")\n \n if (p <=.05){\n cat(\"\\n La moyenne des différences entre les échantillons est significative\")\n }\n else{\n cat(\"\\n La moyenne des différences entre les échantillons n'est pas significative\")\n }\n}\n# CAS 1 : données fictives ------------------\nAvant1 <- rnorm(50,70,5)\nApres1 <- rnorm(50,50,5)\ndf1 <- data.frame(Avant=Avant1, Apres=Apres1)\nboxplot1 <- ggpaired(df1, cond1 = \"Avant\", cond2 = \"Apres\", fill = \"condition\", \n palette = \"jco\", \n xlab = \"\", ylab = \"Sentiment de sécurité\", \n title = \"Données fictives (cas 1)\")\n# CAS 2 : données fictives ------------------\nAvant2 <- rnorm(50,70,5)\nApres2 <- rnorm(50,66,5)\ndf2 <- data.frame(Avant=Avant2, Apres=Apres2)\nboxplot2 <- ggpaired(df2, cond1 = \"Avant\", cond2 = \"Apres\", fill = \"condition\",\n palette = \"jco\", \n xlab = \"\", ylab = \"Sentiment de sécurité\", \n title = \"Données fictives (cas 2)\")\nggarrange(boxplot1, boxplot2, ncol = 2, nrow = 1)\n# Test t : appel de la fonction tstudent_dependants\ntstudent_dependants(Avant1, Apres1, mu = 0)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n groupe A : moy = 71, var = 21, sd = 4.6\n groupe B : moy = 50.7, var = 24.1, sd = 4.9\n Moyenne des différences = 20.3\n Ecart-type des différences = 5.9\n t(dl = 49) = 24.35, p = 0\n La moyenne des différences entre les échantillons est significative\n```\n:::\n\n```{.r .cell-code}\ntstudent_dependants(Avant2, Apres2, mu = 0)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n groupe A : moy = 67.4, var = 21.7, sd = 4.7\n groupe B : moy = 65.4, var = 18.4, sd = 4.3\n Moyenne des différences = 2.1\n Ecart-type des différences = 6\n t(dl = 49) = 2.41, p = 0.02\n La moyenne des différences entre les échantillons est significative\n```\n:::\n\n::: {.cell-output-display}\n![Boites à moustaches sur des échantillons fictifs appariés](06-bivarieeQualiQuanti_files/figure-html/fig-ttest2-1.png){#fig-ttest2 fig-align='center' width=75%}\n:::\n:::\n\n\n\n#### Mesure de la taille de l'effet {#sec-06112}\n\nLa taille de l'effet permet d'évaluer la magnitude (force) de l'effet d'une variable (ici la variable qualitative à deux modalités) sur une autre (ici la variable continue). Dans le cas d'une comparaison de moyennes (avec des échantillons pairés ou non), pour mesurer la taille de l'effet, nous utilisons habituellement le *d* de Cohen ou encore le *g* de Hedges; le second étant un ajustement du premier. Notez que nous analysons la taille de l'effet uniquement si le test de Student ou de Welch s'est révélé significatif (p < 0,05).\n\n**Pourquoi utiliser le *d* de Cohen?** Deux propriétés en font une mesure particulièrement intéressante. Premièrement, elle est facile à calculer puisque *d* est le ratio entre la différence de deux moyennes de groupes (A, B) et l'écart-type combiné des deux groupes. Deuxièmement, *d* représente ainsi une mesure standardisée de la taille de l'effet; elle permet ainsi l'évaluation de la taille de l'effet indépendamment de l'unité de mesure de la variable continue. Concrètement, cela signifie que, quelle que soit l'unité de mesure de la variable continue *X*, *d* est toujours exprimée en unité d'écart-type de *X*. Cette propriété facilite ainsi grandement les comparaisons entre des valeurs de *d* calculées sur différentes combinaisons de variables (au même titre que le coefficient de variation ou le coefficient de corrélation, par exemple). Pour des échantillons indépendants de tailles différentes, le *d* de Cohen s'écrit : \n\n\n$$\n\\frac{\\bar{X}_{A}-\\bar{X}_{B}}{\\sqrt{\\frac{(n_A-1)S^2_A+(n_B-1)S^2_B}{n_A+n_B-2}}}\n$$ {#eq-dcohen}\n\navec $n_A$, $n_B$, $S^2_{X_A}$ et $S^2_{X_B}$ étant respectivement les nombres d'observations et les variances pour les groupes *A* et *B*, $S^2_p$.\n\nSi les échantillons sont de tailles identiques ($n_A=n_B$), alors *d* s'écrit :\n\n\n$$\nd = \\frac{\\bar{X}_{A}-\\bar{X}_{B}}{\\sqrt{(S^2_A+\\S^2_B)/2}} = \\frac{\\bar{X}_{A}-\\bar{X}_{B}}{(\\sigma_A+\\sigma_B)/2}\n$$ {#eq-dcohen2}\n\n\navec $\\sigma_A$ et $\\sigma_B$ étant les écarts-types des deux groupes (rappel : l'écart-type est la racine carrée de la variance).\n\nLe *g* de Hedge est simplement une correction de *d*, particulièrement importante quand les échantillons sont de taille réduite.\n\n$$\ng = d- \\left(1- \\frac{3}{4(n_A+n_B)-9} \\right)\n$$ {#eq-ghedge}\n\n\nMoins utilisé en sciences sociales, mais surtout en études cliniques, le delta de Glass est simplement la différence des moyennes des deux groupes indépendants (numérateur) sur l'écart-type du deuxième groupe (dénominateur). Dans une étude clinique, nous avons habituellement un groupe qui subit un traitement (groupe de traitement) et un groupe qui reçoit un placebo (groupe de contrôle ou groupe témoin). L'effet de taille est ainsi évalué par rapport au groupe de contrôle : \n\n$$\n\\Delta = \\frac{\\bar{X}_{A}-\\bar{X}_{B}}{\\sigma_B}\n$$ {#eq-dDelta}\n\nFinalement, pour des échantillons dépendants (pairés), le delta de Glass s'écrit : $d = \\bar{D}/{\\sigma_D}$ avec $\\bar{D}$ et $\\sigma_D$ étant la moyenne et l'écart-type des différences entre les observations.\n\n**Comment interpréter le *d* de Cohen?** Un effet est considéré comme faible avec $\\lvert d \\rvert$ à 0,2, modéré à 0,50 et fort à 0,80 [@cohen1992]. Notez que ces seuils ne sont que des conventions pour vous guider à interpréter la mesure de Cohen. D'ailleurs, dans son livre intitulé *Statistical power analysis for the behavioral sciences*, il écrit : « all conventions are arbitrary. One can only demand of them that they not be unreasonable » [@cohen2013]. Plus récemment, Sawilowsky [-@sawilowsky2009] a ajouté d'autres seuils à ceux proposés par Cohen (@tbl-convcohen).\n\n\n::: {#tbl-convcohen .cell tbl-cap='Conventions pour l’interprétation du *d* de Cohen'}\n::: {.cell-output-display}\n|Sawilowsky |Cohen |\n|:-----------------|:------------|\n|0,1 : Très faible | |\n|0,2 : Faible |0,2 : Faible |\n|0,5 : Moyen |0,5 : Moyen |\n|0,8 : Fort |0,8 : Fort |\n|1,2 : Très fort | |\n|2,0 : Énorme | |\n:::\n:::\n\n\n\n#### Mise en œuvre dans R {#sec-06113}\n\nNous avons écrit précédemment les fonctions `tstudent_independants` et `tstudent_dependants` uniquement pour décomposer les différentes étapes de calcul des tests de Student et de Welch. Heureusement, il existe des fonctions de base (`t.test` et `var.test`) qui permettent de réaliser l'un ou l'autre de ces deux tests avec une seule ligne de code.\n\nLa fonction `t.test` permet ainsi de calculer les tests de Student et de Welch :\n\n* `t.test(x ~ y, data=, mu = 0, paired = FALSE, var.equal = FALSE, conf.level = 0.95)` ou `t.test(x =, y =, mu = 0, paired = FALSE, var.equal = FALSE, conf.level = 0.95)`. \n\n* Le paramètre `paired` est utilisé pour spécifier si les échantillons sont dépendants (`paired = TRUE`) ou indépendants (`paired = FALSE`).\n\n* Le paramètre `var.equal` est utilisé pour spécifier si les variances sont égales pour le test de Student (`var.equal = TRUE`) ou dissemblables pour le test de Welch (`var.equal = FALSE`).\n\n* `var.test(x, y)` ou `var.test(x ~ y, data=)` pour vérifier au préalable si les variances sont égales ou non et choisir ainsi un *t* de Student ou un *t* de Welch.\n\nLes fonctions `cohens_d` et `hedges_g` du *package* `effectsize` renvoient respectivement les mesures de *d* de Cohen et du *g* de Hedge :\n\n* `cohens_d(x ~ y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)` ou `cohens_d(x, y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)`\n\n* `hedges_g(x ~ y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)` ou `hedges_g(x, y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)`\n\n* `glass_delta(x ~ y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)` ou `glass_delta(x, y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)`\n\n\nNotez que pour toutes ces fonctions, deux écritures sont possibles :\n\n* `x ~ y, data=` avec un `DataFrame` dans lequel `x` est une variable continue et `y` et un facteur binaire\n\n* `x, y` qui sont tous deux des vecteurs numériques (variable continue).\n\n**Exemple de test pour des échantillons indépendants**\n\nLa @fig-locataires représente la cartographie du pourcentage de locataires par secteur de recensement (SR) pour la région métropolitaine de recensement de Montréal (RMR) en 2016, soit une variable continue. L'objectif est de vérifier si la moyenne de ce pourcentage des SR de l'agglomération de Montréal est significativement différente de celles de SR hors de l'agglomération. \n\n\n![Pourcentage de locataires par secteur de recensement, région métropolitaine de recensement de Montréal, 2016](images/Chap06/FigureLocataires.jpg){#fig-locataires width=\"90%\" fig-align=\"center\"}\n\nLes résultats de la syntaxe ci-dessous signalent que le pourcentage de locataires par SR est bien supérieur dans l'agglomération (moyenne = 59,7 %; écart-type = 21,4 %) qu'en dehors de l'agglomération de Montréal (moyenne = 27,3 %; écart-type = 20,1 %). Cette différence de 32,5 points de pourcentage est d'ailleurs significative et très forte (*t* = -23,95; *p* < 0,001, d de Cohen = 1,54).\n\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(\"foreign\")\nlibrary(\"effectsize\")\nlibrary(\"ggplot2\")\nlibrary(\"dplyr\")\n# Importation du fichier\ndfRMR <- read.dbf(\"data/bivariee/SRRMRMTL2016.dbf\")\n# Définition d'un facteur binaire \ndfRMR$Montreal <- factor(dfRMR$Montreal, \n levels = c(0,1), \n labels = c(\"Hors de Montréal\" , \"Montréal\"))\n# Comparaison des moyennes ------------------------\n# Boites à moustaches (boxplot)\nggplot(data = dfRMR, mapping=aes(x = Montreal, y = Locataire, colour = Montreal)) +\n geom_boxplot(width=0.2)+\n theme(legend.position = \"none\")+\n xlab(\"Zone\")+ ylab(\"Pourcentage de locataires\")+\n ggtitle(\"Locataires par secteur de recensement\", \n subtitle = \"région métropolitaine de recensement de Montréal, 2016\")\n```\n\n::: {.cell-output-display}\n![](06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-4-1.png){fig-align='center' width=75%}\n:::\n\n```{.r .cell-code}\n# Nombre d'observations, moyennes et écarts-types pour les deux échantillons\ngroup_by(dfRMR, Montreal) %>%\n summarise(\n n = n(),\n moy = mean(Locataire, na.rm = TRUE),\n ecarttype = sd(Locataire, na.rm = TRUE)\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# A tibble: 2 × 4\n Montreal n moy ecarttype\n \n1 Hors de Montréal 430 27.3 20.1\n2 Montréal 521 59.7 21.4\n```\n:::\n\n```{.r .cell-code}\n# Nous vérifions si les variances sont égales avec la fonction var.test\n# quand la valeur de P est inférieure à 0,05 alors les variances diffèrent\nv <- var.test(Locataire ~ Montreal, alternative = 'two.sided', conf.level = .95, data = dfRMR)\nprint(v)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tF test to compare two variances\n\ndata: Locataire by Montreal\nF = 0.88156, num df = 429, denom df = 520, p-value = 0.1739\nalternative hypothesis: true ratio of variances is not equal to 1\n95 percent confidence interval:\n 0.7361821 1.0573195\nsample estimates:\nratio of variances \n 0.8815563 \n```\n:::\n:::\n\nLe test indique que nous n'avons aucune raison de rejeter l'hypothèse nulle selon laquelle les variances sont égales. Pour l'île de Montréal, l'écart-type est de 21,4; il est de 20,1 hors de l'île, soit une différence négligeable.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Calcul du T de Student ou du T de Welch\np <- v$p.value\nif(p >= 0.05){\n cat(\"\\n Les variances ne diffèrent pas!\",\n \"\\n Nous utilisons le test de Student avec l'option var.equal = TRUE\", sep = \"\")\n t.test(Locataire ~ Montreal, # variable continue ~ facteur binaire \n data = dfRMR, # nom du DataFrame\n conf.level = .95, # intervalle de confiance pour la valeur de t\n var.equal = TRUE) # variances égales\n} else {\n cat(\"\\n Les variances diffèrent!\",\n \"\\n Nous utilisons le test de Welch avec l'option var.equal = FALSE\", sep = \"\")\n t.test(Locataire ~ Montreal, # variable continue ~ facteur binaire \n data = dfRMR, # nom du DataFrame\n conf.level = .95, # intervalle de confiance pour la valeur de t\n var.equal = FALSE) # variances différentes\n}\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n Les variances ne diffèrent pas!\n Nous utilisons le test de Student avec l'option var.equal = TRUE\n```\n:::\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tTwo Sample t-test\n\ndata: Locataire by Montreal\nt = -23.95, df = 949, p-value < 2.2e-16\nalternative hypothesis: true difference in means between group Hors de Montréal and group Montréal is not equal to 0\n95 percent confidence interval:\n -35.11182 -29.79341\nsample estimates:\nmean in group Hors de Montréal mean in group Montréal \n 27.27340 59.72601 \n```\n:::\n\n```{.r .cell-code}\n# Effet de taille à analyser uniquement si le test est significatif\ncohens_d(Locataire ~ Montreal, data = dfRMR, paired = FALSE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nCohen's d | 95% CI\n--------------------------\n-1.56 | [-1.71, -1.41]\n\n- Estimated using pooled SD.\n```\n:::\n\n```{.r .cell-code}\nhedges_g(Locataire ~ Montreal, data = dfRMR, paired = FALSE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nHedges' g | 95% CI\n--------------------------\n-1.56 | [-1.70, -1.41]\n\n- Estimated using pooled SD.\n```\n:::\n:::\n\nNotez que les valeurs du *d* de Cohen et du *g* de Hedge sont très semblables; rappelons que le second est une correction du premier pour des échantillons de taille réduite. Avec 951 observations, nous disposons d'un échantillon suffisamment grand pour que cette correction soit négligeable.\n\n**Exemple de syntaxe pour un test de Student pour des échantillons dépendants**\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(\"ggpubr\")\nlibrary(\"dplyr\")\nPre <- c(79,71,81,83,77,74,76,74,79,70,66,85,69,69,82,\n 69,81,70,83,68,77,76,77,70,68,80,65,65,75,84)\nPost <- c(56,47,40,45,49,51,54,47,44,54,42,56,45,45,48,\n 55,59,58,56,41,56,51,45,55,49,49,48,43,60,50)\n# Première façon de faire un tableau : avec deux colonnes Avant et Après\ndf1 <- data.frame(Avant=Pre, Apres=Post)\nhead(df1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Avant Apres\n1 79 56\n2 71 47\n3 81 40\n4 83 45\n5 77 49\n6 74 51\n```\n:::\n\n```{.r .cell-code}\nggpaired(df1, cond1 = \"Avant\", cond2 = \"Apres\", fill = \"condition\", palette = \"jco\",\n xlab = \"\", ylab = \"Variable continue\")\n```\n\n::: {.cell-output-display}\n![](06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-1.png){fig-align='center' width=75%}\n:::\n\n```{.r .cell-code}\n# Nombre d'observations, moyennes et écart-types\ncat(nrow(df1), \" observations\",\n \"\\nPOST. moy = \", round(mean(df1$Avant),1), \", e.t. = \", round(sd(df1$Avant),1),\n \"\\nPRE. moy = \", round(mean(df1$Apres),1), \", e.t. = \", round(sd(df1$Apres),1), sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n30 observations\nPOST. moy = 74.8, e.t. = 6.1\nPRE. moy = 49.9, e.t. = 5.7\n```\n:::\n\n```{.r .cell-code}\nt.test(Pre, Post, paired = TRUE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tPaired t-test\n\ndata: Pre and Post\nt = 18.701, df = 29, p-value < 2.2e-16\nalternative hypothesis: true mean difference is not equal to 0\n95 percent confidence interval:\n 22.11740 27.54926\nsample estimates:\nmean difference \n 24.83333 \n```\n:::\n\n```{.r .cell-code}\n# Deuxième façon de faire un tableau : avec une colonne pour la variable continue\n# et une autre pour la variable qualitative\nn <- length(Pre)*2\ndf2 <- data.frame(\n id=(1:n),\n participant=(1:length(Pre)),\n risque=c(Pre, Post)\n )\ndf2$periode <- ifelse(df2$id <= length(Pre), \"Pré\", \"Post\")\nhead(df2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n id participant risque periode\n1 1 1 79 Pré\n2 2 2 71 Pré\n3 3 3 81 Pré\n4 4 4 83 Pré\n5 5 5 77 Pré\n6 6 6 74 Pré\n```\n:::\n\n```{.r .cell-code}\n# nombre d'observations, moyennes et écarts-types pour les deux échantillons\ngroup_by(df2, periode) %>%\n summarise(\n n = n(),\n moy = mean(risque, na.rm = TRUE),\n et = sd(risque, na.rm = TRUE)\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# A tibble: 2 × 4\n periode n moy et\n \n1 Post 30 49.9 5.67\n2 Pré 30 74.8 6.10\n```\n:::\n\n```{.r .cell-code}\nggpaired(data = df2, x = \"periode\", y = \"risque\", fill = \"periode\",\n xlab = \"\", ylab = \"Variable continue\")\n```\n\n::: {.cell-output-display}\n![](06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-2.png){fig-align='center' width=75%}\n:::\n\n```{.r .cell-code}\nPre <- subset(df2, periode == \"Pré\")$risque\nPost <- subset(df2, periode == \"Post\")$risque\nt.test(Pre, Post, paired = TRUE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tPaired t-test\n\ndata: Pre and Post\nt = 18.701, df = 29, p-value < 2.2e-16\nalternative hypothesis: true mean difference is not equal to 0\n95 percent confidence interval:\n 22.11740 27.54926\nsample estimates:\nmean difference \n 24.83333 \n```\n:::\n:::\n\n\n#### Comparaison des moyennes pondérées {#sec-06114}\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Moyennes pondérées**\n:::\n::: bloc_objectif-body\nEn études urbaines et en géographie, le recours aux données agrégées (non individuelles) est fréquent, par exemple au niveau des secteurs de recensement (comprenant généralement entre 2500 à 8000 habitants). Dans ce contexte, un secteur de recensement plus peuplé devrait avoir un poids plus important dans l'analyse. Il est possible d'utiliser les versions pondérées des tests présentés précédemment. Prenons deux exemples pour illustrer le tout :\n\n* Pour chaque secteur de recensement des îles de Montréal et de Laval, nous avons calculé la distance au parc le plus proche à travers le réseau de rues avec un système d'information géographique (SIG). Nous souhaitons vérifier si les personnes âgées de moins de 15 ans résidant sur l'île de Montréal bénéficient en moyenne d'une meilleure accessibilité au parc.\n\n* Dans une étude sur la concentration de polluants atmosphériques dans l'environnement autour des écoles primaires montréalaises, Carrier *et al.* [-@carrier2014] souhaitaient vérifier si les élèves fréquentant les écoles les plus défavorisées sont plus exposé(e)s au dioxyde d'azote (NO~2~) dans leur milieu scolaire. Pour ce faire, ils ont réalisé un test _t_ sur un tableau avec comme observations les écoles primaires et trois variables : la moyenne de NO~2~ (variable continue), les quintiles extrêmes d'un indice de défavorisation (premier et dernier quintiles, variable qualitative) et le nombre d'élèves par école (variable pour la pondération).\n\nPour réaliser un test *t* pondéré, nous pouvons utiliser la fonction `t_test` du package `sjstats`.\n:::\n:::\n\n\nEn guise d'exemple appliqué, dans la syntaxe ci-dessous, nous avons refait le même test *t* que précédemment (`Locataire ~ Montreal`) en pondérant chaque secteur de recensement par le nombre de logements qu'il comprend.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"sjstats\")\nlibrary(\"dplyr\")\n# Calcul des statistiques pondérées\ngroup_by(dfRMR, Montreal) %>%\n summarise(\n n = sum(Logement),\n MoyPond = weighted_mean(Locataire, Logement),\n ecarttypePond = weighted_sd(Locataire, Logement)\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# A tibble: 2 × 4\n Montreal n MoyPond ecarttypePond\n \n1 Hors de Montréal 856928 28.4 19.9\n2 Montréal 870354 60.0 20.8\n```\n:::\n\n```{.r .cell-code}\n# Test t non pondéré\nt.test(Locataire ~ Montreal, dfRMR, \n var.equal = TRUE, conf.level = .95)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tTwo Sample t-test\n\ndata: Locataire by Montreal\nt = -23.95, df = 949, p-value < 2.2e-16\nalternative hypothesis: true difference in means between group Hors de Montréal and group Montréal is not equal to 0\n95 percent confidence interval:\n -35.11182 -29.79341\nsample estimates:\nmean in group Hors de Montréal mean in group Montréal \n 27.27340 59.72601 \n```\n:::\n\n```{.r .cell-code}\n# Test t pondérée\nsjstats::t_test(dfRMR, \n select = \"Locataire\", \n by = \"Montreal\", \n weights = \"Logement\",\n mu = 0,\n paired = FALSE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# Two-Sample t-test (weighted)\n\n Data: Locataire by Montreal\n Group 1: Hors de Montréal (n = 856928, mean = 28.40)\n Group 2: Montréal (n = 870354, mean = 60.00)\n Alternative hypothesis: true difference in means is not equal to 0\n\n t = -23.88, Cohen's d = -0.81 (large effect), df = 928.3, p < .001\n```\n:::\n:::\n\n\n#### Comment rapporter un test de Student ou de Welch? {#sec-06115}\n\nPour les différentes versions du test, il est important de rapporter les valeurs de _t_ et de _p_, les moyennes et écarts-types des groupes. Voici quelques exemples.\n\n**Test de Student ou de Welch pour échantillons indépendants**\n\n* Dans la région métropolitaine de Montréal en 2005, le revenu total des femmes (moyenne = 29 117 dollars; écart-type = 258 022) est bien inférieur à celui des hommes (moyenne = 44 463; écart-type = 588 081). La différence entre les moyennes des deux sexes (-15 345) en faveur des hommes est d’ailleurs significative (*t* = -27,09; *p* < 0,001).\n\n* Il y un effet significatif selon le sexe (*t* = -27,09; *p* < 0,001), le revenu total des hommes (moyenne = 44 463; écart-type = 588 081) étant bien supérieur à celui des femmes (moyenne = 29 117; écart-type = 258 022).\n\n* 50 personnes se rendent au travail à vélo (moyenne = 33,7; écart-type = 8,5) contre 60 en automobile (moyenne = 34; écart-type = 8,7). Il n'y a pas de différence significative entre les moyennes d'âge des deux groupes (*t*(108) = -0,79; *p* = 0,427).\n\n\n**Test de Student échantillons dépendants (pairés)**\n\n* Nous constatons une diminution significative de la perception du risque après l'activité (moyenne = 49,9; écart-type = 5,7) comparativement à avant (moyenne = 74,8; écart-type = 6,1), avec une différence de -24,8 (*t*(29) = -18,7; *p* < 0,001).\n\n* Les résultats du pré-test (moyenne = 49,9; écart-type = 5,7) et du post-test (moyenne = 74,8; écart-type = 6,1) montrent qu'il y une diminution significative de la perception du risque (*t*(29) = -18,7; *p* < 0,001).\n\nPour un texte en anglais, consultez\n[https://www.socscistatistics.com/tutorials/ttest/default.aspx](https://www.socscistatistics.com/tutorials/ttest/default.aspx){target=\"_blank\"}.\n\n\n### Test non paramétrique de Wilcoxon {#sec-0612}\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Test non paramétrique de Wilcoxon**\n:::\n::: bloc_objectif-body\nSi la variable continue est fortement anormalement distribuée, il est déconseillé d'utiliser les tests de Student et de Welch. Nous privilégions le test des rangs signés de Wilcoxon (*Wilcoxon rank-sum test* en anglais). Attention, il est aussi appelé test U de Mann-Whitney. Ce test permet alors de vérifier si les deux groupes présentent des médianes différentes.\n\nPour ce faire, nous utilisons la fonction `wilcox.test` dans laquelle le paramètre `paired` permet de spécifier si les échantillons sont indépendants ou non (`FALSE` ou `TRUE`).\n:::\n:::\n\nDans l'exemple suivant, nous analysons le pourcentage de locataires dans les secteurs de recensement de la région métropolitaine de Montréal. Plus spécifiquement, nous comparons ce pourcentage entre les secteurs présents sur l'île et les secteurs hors de l'île. Il s'agit donc d'un test avec des échantillons indépendants.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"foreign\")\nlibrary(\"dplyr\")\n###############################\n# Échantillons indépendants\n###############################\ndfRMR <- read.dbf(\"data/bivariee/SRRMRMTL2016.dbf\")\n# Définition d'un facteur binaire \ndfRMR$Montreal <- factor(dfRMR$Montreal, \n levels = c(0,1), \n labels = c(\"Hors de Montréal\" , \"Montréal\"))\n# Calcul du nombre d'observations, des moyennes et \n# des écarts-types des rangs pour les deux échantillons\ngroup_by(dfRMR, Montreal) %>%\n summarise(\n n = n(),\n moy_rang = mean(rank(Locataire), na.rm = TRUE),\n med_rang = median(rank(Locataire), na.rm = TRUE),\n ecarttype_rang = sd(rank(Locataire), na.rm = TRUE)\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# A tibble: 2 × 5\n Montreal n moy_rang med_rang ecarttype_rang\n \n1 Hors de Montréal 430 216. 216. 124.\n2 Montréal 521 261 261 151.\n```\n:::\n\n```{.r .cell-code}\n# Test des rangs signés de Wilcoxon sur des échantillons indépendants\nwilcox.test(Locataire ~ Montreal, dfRMR)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tWilcoxon rank sum test with continuity correction\n\ndata: Locataire by Montreal\nW = 33716, p-value < 2.2e-16\nalternative hypothesis: true location shift is not equal to 0\n```\n:::\n:::\n\n\nNous observons bien ici une différence significative entre le pourcentage de locataires des secteurs de recensement sur l'île (rang médian = 216) et ceux en dehors de l'île (rang médian = 261).\n\nPour le second exemple, nous générons deux jeux de données au hasard représentant une mesure d'une variable pré-traitement (*pre*) et post-traitement (*post*) pour un même échantillon.\n\n::: {.cell}\n\n```{.r .cell-code}\n###############################\n# Échantillons dépendants\n###############################\npre <- sample(60:80, 50, replace = TRUE)\npost <- sample(30:65, 50, replace = TRUE)\ndf1 <- data.frame(Avant=pre, Apres=post)\n# Nombre d'observations, moyennes et écart-types\ncat(nrow(df1), \" observations\",\n \"\\nPOST. median = \", round(median(df1$Avant), 1), \n \", moy = \", round(mean(df1$Avant), 1),\n \"\\nPRE. median = \", round(median(df1$Apres), 1), \n \", moy = \", round(mean(df1$Apres), 1), sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n50 observations\nPOST. median = 73, moy = 71.8\nPRE. median = 53, moy = 51.3\n```\n:::\n\n```{.r .cell-code}\nwilcox.test(df1$Avant, df1$Apres, paired = TRUE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tWilcoxon signed rank test with continuity correction\n\ndata: df1$Avant and df1$Apres\nV = 1275, p-value = 7.726e-10\nalternative hypothesis: true location shift is not equal to 0\n```\n:::\n:::\n\n\nÀ nouveau, nous obtenons une différence significative entre les deux variables.\n\n**Comment rapporter un test de Wilcoxon?**\n\nLorsque nous rapportons les résultats d'un test de Wilcoxon, il est important de signaler la valeur du test (*W*), le degré de signification (valeur de *p*) et éventuellement la médiane des rangs ou de la variable originale pour les deux groupes. Voici quelques exemples :\n\n* Les résultats du test des rangs signés de Wilcoxon signalent que les rangs de l'île de Montréal sont significativement plus élevés que ceux de l'île de Laval (*W* = 1223, *p* < 0,001).\n\n* Les résultats du test de Wilcoxon signalent que les rangs post-tests sont significativement plus faibles que ceux du pré-test (*W* = 1273,5, *p* < 0,001).\n\n* Les résultats du test de Wilcoxon signalent que la médiane des rangs pré-tests (médiane = 69) est significativement plus forte que celle du post-test (médiane = 50,5) (*W* = 1273,5, *p* < 0,001).\n\n\n## Relation entre une variable quantitative et une variable qualitative à plus de deux modalités {#sec-062}\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Existe-t-il une relation entre une variable continue et une variable qualitative comprenant plus de deux modalités?**\n:::\n::: bloc_objectif-body\nPour répondre à cette question, nous avons recours à deux méthodes : l’analyse de variance – **ANOVA**, _**AN**alysis **O**f **VA**riance_ en anglais – et le test non paramétrique de Kruskal-Wallis. La première permet de vérifier si les moyennes de plusieurs groupes d'une population donnée sont ou non significativement différentes; la seconde, si leurs médianes sont différentes.\n:::\n:::\n\n\n### Analyse de variance {#sec-0621}\n\nL’analyse de variance (ANOVA) est largement utilisée en psychologie, en médecine et en pharmacologie. Prenons un exemple classique en pharmacologie pour tester l'efficacité d'un médicament. Quatre groupes de population sont constitués :\n\n* un premier groupe d'individus pour lequel nous administrons un placebo (un médicament sans substance active), soit le groupe de contrôle ou le groupe témoin;\n\n* un second groupe auquel nous administrons le médicament avec un faible dosage;\n\n* un troisième avec un dosage moyen;\n\n* un quatrième avec un dosage élevé.\n\nLa variable continue permet d'évaluer l'évolution de l'état de santé des individus (par exemple, la variation du taux de globules rouges dans le sang avant et après le traitement). Si le traitement est efficace, nous nous attendons alors à ce que les moyennes des deuxième, troisième et quatrième groupes soient plus élevées que celle du groupe de contrôle. Les différences de moyennes entre les second, troisième et quatrième groupes permettent aussi de repérer le dosage le plus efficace. Si nous n'observons aucune différence significative entre les groupes, cela signifie que l'effet du médicament ne diffère pas de l'effet d'un placébo.\n\nL'ANOVA est aussi très utilisée en études urbaines, principalement pour vérifier si un phénomène urbain varie selon plusieurs groupes d'une population donnée ou de régions géographiques. En guise d'exemple, le recours à l'ANOVA permet de répondre aux questions suivantes :\n\n* Les moyennes des niveaux d'exposition à un polluant atmosphérique (variable continue) varient-elles significativement selon le mode de transport utilisé (automobile, vélo, transport en commun) pour des trajets similaires en heures de pointe?\n\n* Pour une métropole donnée, les moyennes des loyers (variable continue) sont-elles différentes entre les logements de la ville centre versus ceux localisés dans la première couronne et ceux de la seconde couronne?\n\n\n#### Calcul des trois variances pour l'ANOVA {#sec-06211}\n\nL'ANOVA repose sur le calcul de trois variances :\n\n* **la variance totale** (*VT*) de la variable dépendante continue, soit la somme des carrés des écarts à la moyenne de l'ensemble de la population (@eq-anova1);\n\n* la **variance intergroupe** (*Var~inter~*) ou variance expliquée (*VE*), soit la somme des carrés des écarts entre la moyenne de chaque groupe et la moyenne de l’ensemble du jeu de données multipliées par le nombre d’individus appartenant à chacun des groupes (@eq-anova2);\n\n* la **variance intragroupe** (*Var~intra~*) ou variance non expliquée (*VNE*), soit la somme des variances des groupes de la variable indépendante (@eq-anova3).\n\n$$\nVT=\\sum_{i=1}^n (y_{i}-\\overline{y})^2\n$$ {#eq-anova1}\n\n$$\nVar_{inter} \\mbox{ ou } VE=n_{g_1}\\sum_{i\\in{g_1}}(\\overline{y_{g_1}}-\\overline{y})^2 + n_{g_2}\\sum_{i\\in{g_2}}(\\overline{y_{g_2}}-\\overline{y})^2 + ... + n_{g_k}\\sum_{i\\in{g_n}}(\\overline{y_{g_k}}-\\overline{y})^2\n$$ {#eq-anova2}\n\n$$\nVar_{intra} \\mbox{ ou } VNE=\\sum_{i\\in{g_1}}(y_{i}-\\overline{y_{g_1}})^2 + \\sum_{i\\in{g_2}}(y_{i}-\\overline{y_{g_2}})^2 + ... + \\sum_{i\\in{g_n}}(y_{i}-\\overline{y_{g_k}})^2 \n$$ {#eq-anova3}\n\noù $\\overline{y}$ est la moyenne de l'ensemble de la population; $\\overline{y_{g_1}}$, $\\overline{y_{g_2}}$, $\\overline{y_{g_k}}$ sont respectivement les moyennes des groupes 1 à _k_ (_k_ étant le nombre de modalités de la variable qualitative) et $n_{g_1}$,$n_{g_2}$ et $n_{g_k}$ sont les nombres d'observations dans les groupes 1 à _k_.\n\nLa variance totale (*VT*) est égale à la somme de la variance intergroupe (expliquée) et la variance intragroupe (non expliquée) (@eq-anova5). Le ratio entre la variance intergroupe (expliquée) et la variance totale est dénommé *Eta^2^* (@eq-anova6). Il varie de 0 à 1 et exprime la proportion de la variance de la variable continue qui est expliquée par les différentes modalités de la variable qualitative.\n\n$$\nVT = Var_{inter} + Var_{intra} \\mbox{ ou } VT = VNE + VE\n$$ {#eq-anova5}\n\n$$\n\\eta^2= \\frac{Var_{inter}}{VT} \\mbox{ ou } \\eta^2= \\frac{VE}{VT}\n$$ {#eq-anova6}\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**La décomposition de la variance totale : une notion fondamentale en statistique** \n:::\n::: bloc_astuce-body\nLa **variance totale** est égale à la somme des variances intragroupe et intergroupe. Nous verrons qu'elle est aussi utilisée pour évaluer la qualité d'une partition d'une population en plusieurs groupes dans le chapitre sur les méthodes de classification ([chapitre @sec-chap13]). En ANOVA, nous retenons que :\n\n* plus la variance intragroupe est faible, plus les différents groupes sont homogènes;\n\n* plus la variance intergroupe est forte, plus les moyennes des groupes sont différentes et donc plus les groupes sont dissemblables. \n\nAutrement dit, plus la variance intergroupe (**dissimilarité** des groupes) est maximisée et corollairement plus la variance intragroupe (**homogénéité** de chacun des groupes) est minimisée, plus les groupes sont clairement distincts et plus l'ANOVA est performante.\n:::\n:::\n\n\nExaminons un premier jeu de données fictives sur la vitesse de déplacement de cyclistes (variable continue exprimée en km/h) et une variable qualitative comprenant trois groupes de cyclistes utilisant soit un vélo personnel (*n~A~* = 5), soit en libre-service (*n~B~* = 7), soit électrique (*n~C~* = 6) (@tbl-aovfictive1). D'emblée, nous notons que les moyennes de vitesse des trois groupes sont différentes : 17,6 km/h pour les cyclistes avec leur vélo personnel, 12,3 km/h celles et ceux avec des vélos en libre-service et 23,1 km/h pour les cyclistes avec un vélo électrique. Pour chaque observation, la troisième colonne du tableau représente les écarts à la moyenne globale mis au carré, tandis que les colonnes suivantes représentent la déviation au carré de chaque observation à la moyenne de son groupe d'appartenance. Ainsi, pour la première observation, nous avons $(\\mbox{16,900} - \\mbox{17,339})^2 = \\mbox{0,193}$ et $(\\mbox{16,900} - \\mbox{17,580})^2~ = \\mbox{0,462}$. Les valeurs des trois variances sont les suivantes :\n\n* la **variance totale** (*VT*) est donc égale à la somme de la troisième colonne ($\\mbox{424,663}$).\n* la **variance intergroupe** (expliquée, *VE*), elle est égale à $\\mbox{5}\\times(\\mbox{17,580-17,339})^2+\\mbox{7}\\times(\\mbox{12,257-17,339})^2+\\mbox{6}\\times(\\mbox{23,067-17,339})^2 = \\mbox{377,904}$.\n* la **variance intragroupe** (non expliquée, *VNE*) est égale à $\\mbox{11,228+21,537+13,993=46,758}$. \n\nNous avons donc $VT = Var_{inter} + Var_{intra}$, soit $\\mbox{424,663 = 377,904 + 46,758}$ et $\\eta_2 = \\mbox{377,904 / 424,663 = 0,89}$. Cela signale que 89 % de la variance de la vitesse des cyclistes est expliquée par le type de vélo utilisé.\n\n\n::: {#tbl-aovfictive1 .cell tbl-cap='Données fictives et calcul des trois variances (cas 1)'}\n\n```{.r .cell-code}\nVeloA <- c(16.9, 20.4, 16.1, 17.7, 16.8)\nVeloB <- c(13.4, 11.3, 14.0, 12.4, 13.7, 8.5, 12.5)\nVeloC <- c(22.9, 26.0, 23.6, 21.0, 22.3, 22.6)\nmoyA <- mean(VeloA)\nmoyB <- mean(VeloB)\nmoyC <- mean(VeloC)\ngrandmoy <- mean(c(VeloA,VeloB,VeloC))\nnA <- length(VeloA)\nnB <- length(VeloB)\nnC <- length(VeloC)\nn <- nA + nB + nC\nVT <- sum((c(VeloA,VeloB, VeloC)-grandmoy)^2)\nVNE_A <- sum((VeloA-moyA)^2)\nVNE_B <- sum((VeloB-moyB)^2)\nVNE_C <- sum((VeloC-moyC)^2)\nVNE <- VNE_A + VNE_B + VNE_C\nVE <- nA*(moyA-grandmoy)^2 + nB*(moyB-grandmoy)^2 + nC*(moyC-grandmoy)^2\nEta2 <- round(VE / VT, 4)\n \ndf <- data.frame(\n velo = c(rep(\"A. personnel\", length(VeloA)), \n rep(\"B. libre-service\", length(VeloB)),\n rep(\"C. électrique\", length(VeloC))),\n kmh = c(VeloA,VeloB, VeloC))\ndf$VT <- (df$kmh - grandmoy)^2\ndf$VNE_A <- ifelse(df$velo == \"A. personnel\", (df$kmh - moyA)^2, NA)\ndf$VNE_B <- ifelse(df$velo == \"B. libre-service\", (df$kmh - moyB)^2, NA)\ndf$VNE_C <- ifelse(df$velo == \"C. électrique\", (df$kmh - moyC)^2, NA)\ndf_cas1 <- df\ntabl <- df\ntabl$velo <- as.character(tabl$velo)\ntabl[19,1] <- \"grande moyenne\"\ntabl[20,1] <- \"moyenne groupe A\"\ntabl[21,1] <- \"moyenne groupe B\"\ntabl[22,1] <- \"moyenne groupe C \"\ntabl[19,2] <- round(grandmoy,3)\ntabl[20,2] <- round(moyA,3)\ntabl[21,2] <- round(moyB,3)\ntabl[22,2] <- round(moyC,3)\ntabl[23,1] <- \"Variance totale\"\ntabl[24,1] <- \"Variance intragroupe\"\ntabl[23,3] <- sum(tabl$VT, na.rm = TRUE)\ntabl[24,4] <- sum(tabl$VNE_A, na.rm = TRUE)\ntabl[24,5] <- sum(tabl$VNE_B, na.rm = TRUE)\ntabl[24,6] <- sum(tabl$VNE_C, na.rm = TRUE)\ntabl$VT <- round(tabl$VT,3)\ntabl$VNE_A <- round(tabl$VNE_A,3)\ntabl$VNE_B <- round(tabl$VNE_B,3)\ntabl$VNE_C <- round(tabl$VNE_C,3)\nopts <- options(knitr.kable.NA = \"--\")\n\nknitr::kable(tabl, \n caption = \"Données fictives et calcul des trois variances (cas 1)\",\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Type de vélo\",\n \"km/h\",\n \"$(y_{i}-\\\\overline{y})^2$\",\n \"$(y_{i}-\\\\overline{y_{A}})^2$\",\n \"$(y_{i}-\\\\overline{y_{B}})^2$\",\n \"$(y_{i}-\\\\overline{y_{C}})^2$\"\n ),\n align= c(\"l\", \"c\", \"r\", \"r\", \"r\", \"r\")\n)\n```\n\n::: {.cell-output-display}\nTable: Données fictives et calcul des trois variances (cas 1)\n\n|Type de vélo | km/h | $(y_{i}-\\overline{y})^2$| $(y_{i}-\\overline{y_{A}})^2$| $(y_{i}-\\overline{y_{B}})^2$| $(y_{i}-\\overline{y_{C}})^2$|\n|:--------------------|:------:|------------------------:|----------------------------:|----------------------------:|----------------------------:|\n|A. personnel | 16,900 | 0,193| 0,462| --| --|\n|A. personnel | 20,400 | 9,370| 7,952| --| --|\n|A. personnel | 16,100 | 1,535| 2,190| --| --|\n|A. personnel | 17,700 | 0,130| 0,014| --| --|\n|A. personnel | 16,800 | 0,290| 0,608| --| --|\n|B. libre-service | 13,400 | 15,515| --| 1,306| --|\n|B. libre-service | 11,300 | 36,468| --| 0,916| --|\n|B. libre-service | 14,000 | 11,148| --| 3,038| --|\n|B. libre-service | 12,400 | 24,393| --| 0,020| --|\n|B. libre-service | 13,700 | 13,242| --| 2,082| --|\n|B. libre-service | 8,500 | 78,126| --| 14,116| --|\n|B. libre-service | 12,500 | 23,415| --| 0,059| --|\n|C. électrique | 22,900 | 30,926| --| --| 0,028|\n|C. électrique | 26,000 | 75,015| --| --| 8,604|\n|C. électrique | 23,600 | 39,202| --| --| 0,284|\n|C. électrique | 21,000 | 13,404| --| --| 4,271|\n|C. électrique | 22,300 | 24,613| --| --| 0,588|\n|C. électrique | 22,600 | 27,679| --| --| 0,218|\n|grande moyenne | 17,339 | --| --| --| --|\n|moyenne groupe A | 17,580 | --| --| --| --|\n|moyenne groupe B | 12,257 | --| --| --| --|\n|moyenne groupe C | 23,067 | --| --| --| --|\n|Variance totale | -- | 424,663| --| --| --|\n|Variance intragroupe | -- | --| 11,228| 21,537| 13,993|\n:::\n:::\n\n\nExaminons un deuxième jeu de données fictives pour lequel le type de vélo utilisé n'aurait que peu d'effet sur la vitesse des cyclistes (@tbl-aovfictive2). D'emblée, les moyennes des trois groupes semblent très similaires (19,3, 17,9 et 18,7). Les valeurs des trois variances sont les suivantes :\n\n* la **variance totale** (*VT*) est égale à $\\mbox{121,756}$.\n* la **variance intergroupe** (expliquée, *VE*) est égale à $\\mbox{5}\\times(\\mbox{19,300-18,528})^2+\\mbox{7}\\times(\\mbox{17,871-18,528})^2+\\mbox{6}\\times(\\mbox{18,650-18,528})^2 = \\mbox{6,087}$.\n* la **variance intragroupe** (non expliquée, *VNE*) est égale à $\\mbox{9,140+50,254+56,275 = 115,669}$.\n\nNous avons donc $VT = Var_{inter} + Var_{intra}$, soit $\\mbox{121,756 = 6,087 + 115,669}$ et $\\eta_2 = \\mbox{6,087 / 121,756 = 0,05}$. Cela signale que 5 % de la variance de la vitesse des cyclistes est uniquement expliquée par le type de vélo utilisé.\n\n\n::: {#tbl-aovfictive2 .cell tbl-cap='Données fictives et calcul des trois variances (cas 2)'}\n::: {.cell-output-display}\n|Type de vélo | km/h | $(y_{i}-\\overline{y})^2$| $(y_{i}-\\overline{y_{A}})^2$| $(y_{i}-\\overline{y_{B}})^2$| $(y_{i}-\\overline{y_{C}})^2$|\n|:--------------------|:------:|------------------------:|----------------------------:|----------------------------:|----------------------------:|\n|A. personnel | 17,500 | 1,056| 3,24| --| --|\n|A. personnel | 19,000 | 0,223| 0,09| --| --|\n|A. personnel | 19,700 | 1,374| 0,16| --| --|\n|A. personnel | 18,700 | 0,030| 0,36| --| --|\n|A. personnel | 21,600 | 9,439| 5,29| --| --|\n|B. libre-service | 13,700 | 23,307| --| 17,401| --|\n|B. libre-service | 20,800 | 5,163| --| 8,577| --|\n|B. libre-service | 15,100 | 11,750| --| 7,681| --|\n|B. libre-service | 18,800 | 0,074| --| 0,862| --|\n|B. libre-service | 21,500 | 8,834| --| 13,167| --|\n|B. libre-service | 16,500 | 4,112| --| 1,881| --|\n|B. libre-service | 18,700 | 0,030| --| 0,687| --|\n|C. électrique | 16,600 | 3,716| --| --| 4,203|\n|C. électrique | 16,300 | 4,963| --| --| 5,523|\n|C. électrique | 15,600 | 8,572| --| --| 9,303|\n|C. électrique | 20,000 | 2,167| --| --| 1,822|\n|C. électrique | 24,600 | 36,872| --| --| 35,402|\n|C. électrique | 18,800 | 0,074| --| --| 0,022|\n|grande moyenne | 18,528 | --| --| --| --|\n|moyenne groupe A | 19,300 | --| --| --| --|\n|moyenne groupe B | 17,871 | --| --| --| --|\n|moyenne groupe C | 18,650 | --| --| --| --|\n|Variance totale | -- | 121,756| --| --| --|\n|Variance intragroupe | -- | --| 9,14| 50,254| 56,275|\n:::\n:::\n\n\n\n#### Test de Fisher {#sec-06212}\n\nPour vérifier si les moyennes sont statistiquement différentes (autrement dit, si leur différence est significativement différente de 0), nous avons recours au test *F* de Fisher. Pour ce faire, nous posons l'hypothèse nulle (*H~0~*), soit que les moyennes des groupes sont égales; autrement dit que la variable qualitative n'a pas d'effet sur la variable continue (indépendance entre les deux variables). L'hypothèse alternative (*H~1~*) est donc que les moyennes sont différentes. Pour nos deux jeux de données fictives ci-dessus comprenant trois groupes, *H~0~* signifie que $\\overline{y_{A}}=\\overline{y_{B}}=\\overline{y_{C}}$. La statistique *F* se calcule comme suit :\n\n\n$$\nF = \\frac{\\frac{Var{inter}}{k-1}}{\\frac{Var{intra}}{n-k}}\\mbox{ ou } F = \\frac{\\frac{VE}{k-1}}{\\frac{VNE}{n-k}}\n$$ {#eq-anovaF}\n\noù $n$ et $k$ sont respectivement les nombres d'observations et de modalités de la variable qualitative. L'hypothèse nulle (les moyennes sont égales) est rejetée si la valeur du *F* calculé est supérieure à la valeur critique de la table *F* avec les degrés de liberté *(k-1, n-k)* et un seuil \n$\\alpha$ (*p*=0,05 habituellement) (voir la table des valeurs critiques de *F*, [section @sec-132]). Notez que nous utilisons rarement la table *F* puisqu'avec la fonction `aov`, nous obtenons directement la valeur *F* et celle de *p* qui lui est associée. Concrètement, si le test _F_ est significatif (avec *p* < 0,05), plus la valeur de *F* est élevée, plus la différence entre les moyennes est élevée.\n\nAppliquons rapidement la démarche du test *F* à nos deux jeux de données fictives qui comprennent 3 modalités pour la variable qualitative et 18 observations. Avec $\\alpha$ = 0,05, 2 degrés de liberté (3-1) au numérateur et 15 au dénominateur (18-3), la valeur critique de F est de 3,68. Nous en concluons alors que :\n\n* Pour le cas A, le *F* calculé est égal à $\\mbox{(377,904 / 2) / (46,758 / 15) = 60,62}$. Il est supérieur à la valeur *F* critique; les moyennes sont donc statistiquement différentes au seuil 0,05. Autrement dit, nous aurions eu moins de 5 % de chance d'obtenir un échantillon produisant ces résultats si en réalité la différence entre les moyennes était de 0.\n\n* Pour le cas B, le *F* calculé est égal à $\\mbox{(6,087 / 2) / (115,669 / 15) = 0,39}$. Il est inférieur à la valeur *F* critique; les moyennes ne sont donc pas statistiquement différentes au seuil de 0,05.\n\n#### Conditions d'application de l'ANOVA et solutions de rechange {#sec-06213}\n\nTrois conditions d'application doivent être vérifiées avant d'effectuer une analyse de variance sur un jeu de données :\n\n* **Normalité des groupes.** Le test de Fisher repose sur le postulat que les échantillons (groupes) sont normalement distribués. Pour le vérifier, nous avons recours au test de normalité de Shapiro–Wilk ([section @sec-025413]). Rappelez-vous toutefois que ce test est très restrictif, surtout pour de grands échantillons.\n\n* **Homoscédasticité**. La variance dans les échantillons doit être la même (homogénéité des variances). Pour vérifier cette condition, nous utilisons les tests de Levene, de Bartlett ou de Breusch-Pagan.\n\n* **Indépendance des observations (pseudo-réplication).** Chaque individu doit appartenir à un et un seul groupe. En d'autres termes, les observations ne sont pas indépendantes si plusieurs mesures (variable continue) sont faites sur un même individu. Si c'est le cas, nous utiliserons alors une analyse de variance sur des mesures répétées (voir le bloc à la fin du chapitre).\n\n**Quelles sont les conséquences si les conditions d'application ne sont pas respectées?** La non-vérification des conditions d'application cause deux problèmes distincts : elle affecte la puissance du test (sa capacité à détecter un effet, si celui-ci existe réellement) et le taux d'erreur de type 1 (la probabilité de trouver un résultat significatif alors qu'aucune relation n'existe réellement, soit un faux positif) [@glass1972consequences; @lix1996consequences].\n\n* Si la distribution est asymétrique plutôt que centrée (comme pour une distribution normale), la puissance et le taux d'erreur de type 1 sont tous les deux peu affectés, car le test est non orienté (la différence de moyennes peut être négative ou positive).\n\n* Si la distribution est leptocurtique (pointue, avec des extrémités de la distribution plus importantes), le taux d'erreur de type 1 est peu affecté; en revanche, la puissance du test est réduite. L'inverse s'observe si la distribution est platicurtique (aplatie, c'est-à-dire avec des extrémités de la distribution plus réduites.\n\n* Si les groupes ont des variances différentes, le taux d'erreur de type 1 augmente légèrement.\n\n* Si les observations ne sont pas indépendantes, à la fois le taux d'erreur de type 1 et la puissance du test sont fortement affectés.\n\n* Si les échantillons sont petits, les effets présentés ci-dessus sont démultipliés.\n\n* Si plusieurs conditions ne sont pas respectées, les conséquences présentées ci-dessus s'additionnent, voire se combinent.\n\n**Que faire quand les conditions d'application relatives à la normalité ou à l'homoscédasticité ne sont vraiment pas respectées?** Signalons d'emblée que le non-respect de ces conditions ne change rien à la décomposition de la variance (*VT = V~intra~+V~inter~*). Cela signifie que vous pouvez toujours calculer *Eta^2^*. Par contre, le test de Fisher ne peut pas être utilisé, car il est biaisé comme décrit précédemment. Quatre solutions sont envisageables :\n\n* Lorsque les échantillons sont fortement anormalement distribués, certains auteurs vont simplement transformer leur variable en appliquant une fonction logarithme (le plus souvent) ou racine carrée, inverse ou exponentielle, et reporter le test de Fisher calculé sur cette transformation. Attention toutefois! Transformer une variable ne va pas systématiquement la rapprocher d'une distribution normale et complique l'interprétation finale des résultats. Par conséquent, avant de recalculer votre test *F*, il convient de réaliser un test de normalité de Shapiro–Wilk et un test d'homoscédasticité (Levene, Bartlett ou Breusch-Pagan) sur la variable continue transformée.\n\n* Détecter les observations qui contribuent le plus à l'anormalité et à l'hétéroscédasticité (valeurs aberrantes ou extrêmes). Supprimez-les et refaites votre ANOVA en vous assurant que les conditions sont désormais respectées. Notez que supprimer des observations peut être une pratique éthiquement questionnable en statistique. Si vos échantillons sont bien constitués et que la mesure collectée n'est pas erronée, pourquoi donc la supprimer? Si vous optez pour cette solution, prenez soin de comparer les résultats avant et après la suppression des observations. Si les conditions sont respectées après la suppression et que les résultats de l'ANOVA (*Eta^2^* et test *F* de Fisher) sont très semblables, conservez donc les résultats de l'ANOVA initiale et signalez que vous avez procédé aux deux tests.\n\n* Lorsque les variances des groupes sont dissemblables, vous pouvez utiliser le test de Welch pour l'ANOVA au lieu du test *F* de Fisher. \n\n* Dernière solution, lorsque les deux conditions ne sont vraiment pas respectées, utilisez le test non paramétrique de Kruskal-Wallis. Par analogie au *t* de Student, il correspond au test des rangs signés de Wilcoxon. Ce test est décrit dans la section suivante.\n\nVous l'aurez compris, dans de nombreux cas en statistique, les choix méthodologiques dépendent en partie de la subjectivité des chercheur(se)s. Il faut s'adapter au jeu de données et à la culture statistique en vigueur dans votre champ d'études. N'hésitez pas à réaliser plusieurs tests différents pour évaluer la robustesse de vos conclusions et fiez-vous en premier lieu à ceux pour lesquels votre jeu de données est le plus adapté.\n\n### Test non paramétrique de Kruskal-Wallis {#sec-0622}\n\nLe test non paramétrique de Kruskal-Wallis est une solution de rechange à l'ANOVA classique lorsque le jeu de données présente de graves problèmes de normalité et d'hétéroscédasticité. Cette méthode représente une ANOVA appliquée à une variable continue transformée préalablement en rangs. Du fait de la transformation en rangs, nous ne vérifions plus si les moyennes sont différentes, mais bel et bien si les médianes de la variable continue sont différentes. Pour ce faire, nous utiliserons la fonction `kruskal.test`.\n\n### Mise en œuvre dans R {#sec-0623}\n\nDans une étude récente, Apparicio *et al.* [-@2018_1] ont comparé les expositions au bruit et à la pollution atmosphérique aux heures de pointe à Montréal en fonction du mode de transport utilisé. Pour ce faire, trois équipes de trois personnes ont été constituées : une personne à vélo, une autre en automobile et une dernière se déplaçant en transport en commun, équipées de capteurs de pollution, de sonomètres, de vêtements biométriques et d’une montre GPS. Chaque matin, à huit heures précises, les membres de chaque équipe ont réalisé un trajet d'un quartier périphérique de Montréal vers un pôle d'enseignement (université) ou d'emploi localisé au centre-ville. Le trajet inverse était réalisé le soir à 17 h. Au total, une centaine de trajets ont ainsi été réalisés. Des analyses de variance ont ainsi permis de comparer les trois modes (automobile, vélo et transport en commun) en fonction des temps de déplacement, des niveaux d'exposition au bruit, des niveaux d'exposition au dioxyde d'azote et de la dose totale inhalée de dioxyde d'azote. Nous vous proposons ici d'analyser une partie de ces données.\n\n\n#### Première ANOVA : différences entre les temps de déplacement {#sec-06231}\nComme première analyse de variance, nous vérifions si les moyennes des temps de déplacement sont différentes entre les trois modes de transport. \n\nDans un premier temps, nous calculons les moyennes des différents groupes. Nous pouvons alors constater que les moyennes sont très semblables : 37,7 minutes pour l'automobile versus 38,4 et 41,6 pour le vélo et le transport en commun. Aussi, les variances des trois groupes sont relativement similaires.\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"rstatix\")\n# chargement des DataFrames\nload(\"data/bivariee/dataPollution.RData\")\n# Statistiques descriptives pour les groupes (moyenne et écart-type)\ndf_TrajetsDuree %>% # Nom du DataFrame\n group_by(Mode) %>% # Variable qualitative\n get_summary_stats(DureeMinute, type = \"mean_sd\") # Variable continue \n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# A tibble: 3 × 5\n Mode variable n mean sd\n \n1 1. Auto DureeMinute 33 37.7 12.8\n2 2. Velo DureeMinute 33 38.4 15.2\n3 3. TC DureeMinute 33 41.6 11.4\n```\n:::\n:::\n\n\nPour visualiser la distribution des données pour les trois groupes, vous pouvez créer des graphiques de densité et en violon (@fig-Anova1a). La juxtaposition des trois distributions montre que les distributions des valeurs pour les trois groupes sont globalement similaires. Cela est corroboré par le fait que les boîtes du graphique en violon sont situées à la même hauteur. Autrement dit, à la lecture des deux graphiques, il ne semble pas y avoir de différences significatives entre les trois groupes en termes de temps de déplacement.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(\"ggplot2\")\nlibrary(\"ggpubr\")\n# Graphique de densité\nGraphDens <- ggplot(data = df_TrajetsDuree, \n mapping=aes(x = DureeMinute, colour = Mode, fill = Mode)) +\n geom_density(alpha=0.55, mapping=aes(y = ..scaled..))+\n labs(title = \"a. Graphique de densité\",\n x = \"Densité\",\n y = \"Durée du trajet (en minutes)\")\n# Graphique en violon\nGraphViolon <- ggplot(df_TrajetsDuree, aes(x = Mode, y = DureeMinute)) +\n geom_violin(fill = \"white\") +\n geom_boxplot(width=0.1, aes(x = Mode, y = DureeMinute, fill = Mode))+\n labs(title = \"b. Graphique en violon\",\n x = \"Mode de transport\",\n y = \"Durée du trajet (en minutes)\")+\n theme(legend.position = \"none\")\nggarrange(GraphDens, GraphViolon)\n```\n\n::: {.cell-output-display}\n![Graphiques de densité et en violon](06-bivarieeQualiQuanti_files/figure-html/fig-Anova1a-1.png){#fig-Anova1a fig-align='center' width=75%}\n:::\n:::\n\n\nNous pouvons vérifier si les échantillons sont normalement distribués avec la fonction `shapiro_test` du package `rstatix`. À titre de rappel, l'hypothèse nulle (*H~0~*) de ce test est que la distribution est normale. Par conséquent, quand la valeur de *p* associée à la statistique de Shapiro est supérieure à 0,05, alors nous ne pouvons rejeter l'hypothèse d'une distribution normale (autrement dit, la distribution est anormale). À la lecture des résultats ci-dessous, seul le groupe utilisant le transport en commun présente une distribution proche de la normalité (*p* = 0,0504). Ce test étant très restrictif, il est fortement conseillé de visualiser le diagramme quantile-quantile pour chaque groupe (graphique QQ plot) (@fig-Qqplot). Ces graphiques sont utilisés pour déterminer visuellement si une distribution empirique (observée sur des données), s'approche d'une distribution théorique (ici la loi normale). Si effectivement les deux distributions sont proches, les points du diagramme devraient tous tomber sur une ligne droite parfaite. Un intervalle de confiance (représenté ici en gris) peut être construit pour obtenir une interprétation plus nuancée. Dans notre cas, seules deux observations pour le vélo et deux autres pour l'automobile s'éloignent vraiment de la ligne droite. Nous pouvons considérer que ces trois distributions s'approchent d'une distribution normale.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(\"dplyr\")\nlibrary(\"ggpubr\")\nlibrary(\"rstatix\")\n# Condition 1 : normalité des échantillons\n# Test pour la normalité des échantillons (groupes) : test de Shapiro\n df_TrajetsDuree %>% # Nom du DataFrame\n group_by(Mode) %>% # Variable qualitative\n shapiro_test(DureeMinute) # Variable continue \n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# A tibble: 3 × 4\n Mode variable statistic p\n \n1 1. Auto DureeMinute 0.905 0.00729 \n2 2. Velo DureeMinute 0.797 0.0000288\n3 3. TC DureeMinute 0.936 0.0504 \n```\n:::\n\n```{.r .cell-code}\n# Graphiques qqplot pour les groupes\nggqqplot(df_TrajetsDuree, \"DureeMinute\", facet.by = \"Mode\", \n xlab = \"Théorique\", ylab = \"Échantillon\")\n```\n\n::: {.cell-output-display}\n![QQ Plot pour les groupes](06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot-1.png){#fig-Qqplot fig-align='center' width=75%}\n:::\n:::\n\n\nPour vérifier l’hypothèse d’homogénéité des variances, vous pouvez utiliser les tests de Levene, de Bartlett ou de Breusch-Pagan. Les valeurs de *p*, toutes supérieures à 0,05, signalent que la condition d'homogénéité des variances est respectée.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"rstatix\")\nlibrary(\"lmtest\")\nlibrary(\"car\")\n# Condition 2 : homogénéité des variances (homocédasticité)\nleveneTest(DureeMinute ~ Mode, data = df_TrajetsDuree)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLevene's Test for Homogeneity of Variance (center = median)\n Df F value Pr(>F)\ngroup 2 0.2418 0.7857\n 96 \n```\n:::\n\n```{.r .cell-code}\nbartlett.test(DureeMinute ~ Mode, data = df_TrajetsDuree)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tBartlett test of homogeneity of variances\n\ndata: DureeMinute by Mode\nBartlett's K-squared = 2.6718, df = 2, p-value = 0.2629\n```\n:::\n\n```{.r .cell-code}\nbptest(DureeMinute ~ Mode, data = df_TrajetsDuree)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tstudentized Breusch-Pagan test\n\ndata: DureeMinute ~ Mode\nBP = 1.3322, df = 2, p-value = 0.5137\n```\n:::\n:::\n\n\nDeux fonctions peuvent être utilisées pour calculer l'analyse de variance : la fonction de base `aov(variable continue ~ variable qualitative, data = votre DataFrame)` ou bien la fonction `anova_test(variable continue ~ variable qualitative, data = votre DataFrame)` du package `rstatix`. Comparativement à `aov`, l'avantage de la fonction `anova_test` est qu'elle calcule aussi le *Eta^2^*.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"rstatix\")\nlibrary(\"car\")\nlibrary(\"effectsize\")\n# ANOVA avec la fonction aov\naov1 <- aov(DureeMinute ~ Mode, data = df_TrajetsDuree)\nsummary(aov1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Df Sum Sq Mean Sq F value Pr(>F)\nMode 2 287 143.2 0.82 0.444\nResiduals 96 16781 174.8 \n```\n:::\n\n```{.r .cell-code}\n# calcul de Eta2 avec la fonction eta_squared du package effectsize\neffectsize::eta_squared(aov1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# Effect Size for ANOVA\n\nParameter | Eta2 | 95% CI\n-------------------------------\nMode | 0.02 | [0.00, 1.00]\n\n- One-sided CIs: upper bound fixed at [1.00].\n```\n:::\n\n```{.r .cell-code}\n# ANOVA avec la fonction anova_test du package rstatix\nanova_test(DureeMinute ~ Mode, data = df_TrajetsDuree)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nANOVA Table (type II tests)\n\n Effect DFn DFd F p p<.05 ges\n1 Mode 2 96 0.82 0.444 0.017\n```\n:::\n:::\n\n\nLa valeur de *p* associée à la statistique *F* (0,444) nous permet de conclure qu'il n'y a pas de différences significatives entre les moyennes des temps de déplacement des trois modes de transport.\n\n#### Deuxième ANOVA : différences entre les niveaux d'exposition au bruit {#sec-06232}\n\nDans ce second exercice, nous analysons les différences d'exposition au bruit. D'emblée, les statistiques descriptives révèlent que les moyennes sont dissemblables : 66,8 dB(A) pour l’automobile versus 68,8 et 74 pour le vélo et le transport en commun. Aussi, la variance du transport en commun est très différente des autres.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"rstatix\")\n# chargement des DataFrames\nload(\"data/bivariee/dataPollution.RData\")\n# Statistiques descriptives pour les groupes (moyenne et écart-type)\n df_Bruit %>% # Nom du DataFrame\n group_by(Mode) %>% # Variable qualitative\n get_summary_stats(laeq, type = \"mean_sd\") # Variable continue \n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# A tibble: 3 × 5\n Mode variable n mean sd\n \n1 1. Auto laeq 1094 66.8 4.56\n2 2. Velo laeq 1124 68.8 4.29\n3 3. TC laeq 1207 74.0 6.79\n```\n:::\n:::\n\n\nÀ la lecture des graphiques de densité et en violon (@fig-Anova1b), il semble clair que les niveaux d'exposition au bruit sont plus faibles pour les automobilistes et plus élevés pour les cyclistes et surtout les personnes en transport en commun. En outre, la distribution des valeurs d'exposition au bruit dans le transport en commun semble bimodale. Cela s'explique par le fait que les niveaux de bruit sont beaucoup plus élevés dans le métro que dans les autobus.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(\"ggplot2\")\nlibrary(\"ggpubr\")\n# Graphique en densité\nGraphDens <- ggplot(data = df_Bruit, \n mapping=aes(x = laeq, colour = Mode, fill = Mode)) +\n geom_density(alpha=0.55, mapping=aes(y = ..scaled..))+\n labs(title = \"a. graphique de densité\",\n x = \"Exposition au bruit (dB(A))\")\n# Graphique en violon\nGraphViolon <- ggplot(df_Bruit, aes(x = Mode, y = laeq)) +\n geom_violin(fill = \"white\") +\n geom_boxplot(width=0.1, aes(x = Mode, y = laeq, fill = Mode))+\n labs(title = \"b. Graphique en violon\",\n x = \"Mode de transport\",\n y = \"Exposition au bruit (dB(A))\")+\n theme(legend.position = \"none\")\nggarrange(GraphDens, GraphViolon)\n```\n\n::: {.cell-output-display}\n![Graphique de densité et en violon](06-bivarieeQualiQuanti_files/figure-html/fig-Anova1b-1.png){#fig-Anova1b fig-align='center' width=75%}\n:::\n:::\n\n\n\nLe test de Shapiro et les graphiques QQ plot (@fig-Qqplot2) révèlent que les distributions des trois groupes sont anormales. Ce résultat n'est pas surprenant si l'on tient compte de la nature logarithmique de l'échelle décibel.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(\"dplyr\")\nlibrary(\"ggpubr\")\nlibrary(\"rstatix\")\n# Condition 1 : normalité des échantillons\n# Test pour la normalité des échantillons (groupes) : test de Shapiro\ndf_Bruit %>% # Nom du DataFrame\n group_by(Mode) %>% # Variable qualitative\n shapiro_test(laeq) # Variable continue \n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# A tibble: 3 × 4\n Mode variable statistic p\n \n1 1. Auto laeq 0.971 4.92e-14\n2 2. Velo laeq 0.992 5.12e- 6\n3 3. TC laeq 0.966 3.34e-16\n```\n:::\n\n```{.r .cell-code}\n# Graphiques qqplot pour les groupes\nggqqplot(df_Bruit, \"laeq\", facet.by = \"Mode\", xlab = \"Théorique\", ylab = \"Échantillon\")\n```\n\n::: {.cell-output-display}\n![QQ Plot pour les groupes](06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot2-1.png){#fig-Qqplot2 fig-align='center' width=75%}\n:::\n:::\n\n\nEn outre, selon les valeurs des tests de Levene, de Bartlett ou de Breusch-Pagan, les variances ne sont pas égales.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"rstatix\")\nlibrary(\"lmtest\")\nlibrary(\"car\")\n# Condition 2 : homogénéité des variances (homocédasticité)\nleveneTest(laeq ~ Mode, data = df_Bruit)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLevene's Test for Homogeneity of Variance (center = median)\n Df F value Pr(>F) \ngroup 2 190.3 < 2.2e-16 ***\n 3422 \n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n```\n:::\n\n```{.r .cell-code}\nbartlett.test(laeq ~ Mode, data = df_Bruit)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tBartlett test of homogeneity of variances\n\ndata: laeq by Mode\nBartlett's K-squared = 306.64, df = 2, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\nbptest(laeq ~ Mode, data = df_Bruit)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tstudentized Breusch-Pagan test\n\ndata: laeq ~ Mode\nBP = 279.85, df = 2, p-value < 2.2e-16\n```\n:::\n:::\n\n\nÉtant donné que les deux conditions (normalité et homogénéité des variances) ne sont pas respectées, il est préférable d'utiliser un test non paramétrique de Kruskal-Wallis. Calculons toutefois préalablement l'ANOVA classique et l'ANOVA de Welch puisque les variances ne sont pas égales. Les valeurs de *p* des deux tests (Fisher et Welch) signalent que les moyennes d'exposition au bruit sont statistiquement différentes entre les trois modes de transport.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"rstatix\")\n# ANOVA avec la fonction anova_test du package rstatix\nanova_test(laeq ~ Mode, data = df_Bruit)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nANOVA Table (type II tests)\n\n Effect DFn DFd F p p<.05 ges\n1 Mode 2 3422 544.214 6.12e-206 * 0.241\n```\n:::\n\n```{.r .cell-code}\n# ANOVA avec le test de Welch puisque les variances ne sont pas égales\nwelch_anova_test(laeq ~ Mode, data = df_Bruit)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# A tibble: 1 × 7\n .y. n statistic DFn DFd p method \n* \n1 laeq 3425 446. 2 2248. 9.47e-164 Welch ANOVA\n```\n:::\n:::\n\n\nUne fois démontré que les moyennes sont différentes, le test de Tukey est particulièrement intéressant puisqu'il nous permet de repérer les différences de moyennes significatives deux à deux, tout en ajustant les valeurs de *p* obtenues en fonction du nombre de comparaisons effectuées. Ci-dessous, nous constatons que toutes les paires sont statistiquement différentes et que la différence de moyennes entre les automobilistes et les cyclistes est de 1,9 dB(A) et surtout de 7,1 dB(A) entre les automobilistes et les personnes ayant pris le transport en commun.\n\n\n::: {.cell}\n\n```{.r .cell-code}\naov2 <- aov(laeq ~ Mode, data = df_Bruit)\n# Test de Tukey pour comparer les moyennes entre elles\nTukeyHSD(aov2, conf.level = 0.95)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Tukey multiple comparisons of means\n 95% family-wise confidence level\n\nFit: aov(formula = laeq ~ Mode, data = df_Bruit)\n\n$Mode\n diff lwr upr p adj\n2. Velo-1. Auto 1.941698 1.406343 2.477053 0\n3. TC-1. Auto 7.113506 6.587309 7.639703 0\n3. TC-2. Velo 5.171808 4.649307 5.694309 0\n```\n:::\n:::\n\n\nLe calcul du test non paramétrique de Kruskal-Wallis avec la fonction `kruskal.test` démontre aussi que les médianes des groupes sont différentes (*p* < 0,001). De manière comparable au test de Tukey, la fonction `pairwise.wilcox.test` permet aussi de repérer les différences significatives entre les paires de groupes. Pour conclure, tant l'ANOVA que le test non paramétrique de Kruskal-Wallis indiquent que les trois modes de transport sont significativement différents quant à l'exposition au bruit, avec des valeurs plus faibles pour les automobilistes comparativement aux cyclistes et aux personnes ayant pris le transport en commun.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Test de Kruskal-Wallis\nkruskal.test(laeq ~ Mode, data = df_Bruit)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tKruskal-Wallis rank sum test\n\ndata: laeq by Mode\nKruskal-Wallis chi-squared = 784.74, df = 2, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\n# Calcul de la moyenne des rangs pour les trois groupes\ndf_Bruit$laeqRank <- rank(df_Bruit$laeq)\ndf_Bruit %>%\n group_by(Mode) %>%\n get_summary_stats(laeqRank, type = \"mean\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# A tibble: 3 × 4\n Mode variable n mean\n \n1 1. Auto laeqRank 1094 1188.\n2 2. Velo laeqRank 1124 1572.\n3 3. TC laeqRank 1207 2320.\n```\n:::\n\n```{.r .cell-code}\n# Comparaison des groupes avec la fonction pairwise.wilcox.test\npairwise.wilcox.test(df_Bruit$laeq, df_Bruit$Mode, p.adjust.method = \"BH\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tPairwise comparisons using Wilcoxon rank sum test with continuity correction \n\ndata: df_Bruit$laeq and df_Bruit$Mode \n\n 1. Auto 2. Velo\n2. Velo <2e-16 - \n3. TC <2e-16 <2e-16 \n\nP value adjustment method: BH \n```\n:::\n:::\n\n\n### Comment rapporter les résultats d'une ANOVA et du test de Kruskal-Wallis {#sec-0624}\n\nPlusieurs éléments doivent être reportés pour détailler les résultats d'une ANOVA ou d'un test de Kruskal-Wallis : la valeur de *F*, de *W* (dans le cas d'une ANOVA de Welch) ou du χ2 (Kruskal-Wallis), les valeurs de *p*, les moyennes ou médianes respectives des groupes et éventuellement un tableau détaillant les écarts intergroupes obtenus avec les tests de Tukey ou Wilcoxon par paires.\n\n* Les résultats de l'analyse de variance à un facteur démontrent que le mode de transport utilisé n'a pas d'effet significatif sur le temps de déplacement en heures de pointe à Montréal (*F*(2,96) = 0,82, *p* = 0,444). En effet, pour des trajets de dix kilomètres entre un quartier périphérique et le centre-ville, les cyclistes (Moy = 38,4, ET = 15,2) arrivent en moyenne moins d'une minute après les automobilistes (Moy = 37,7, ET = 12,8) et moins de quatre minutes comparativement aux personnes ayant pris le transport en commun (Moy = 41,6, ET = 11,4). \n\n* Les résultats de l'analyse de variance à un facteur démontrent que le mode de transport utilisé a un impact significatif sur le niveau d'exposition en heures de pointe à Montréal (*F*(2,96) = 544, *p* < 0,001 et *Welch*(2,96) = 446, *p* < 0,001). En effet, les personnes en transport en commun (Moy = 74,0, ET = 6,79) et les cyclistes (Moy = 68,8, ET = 4,3) ont des niveaux d'exposition au bruit significativement plus élevés que les automobilistes (Moy = 66,8, ET = 4,56). \n\n* Les résultats du test de Kruskal-Wallis démontrent qu'il existe des différences significatives d'exposition au bruit entre les trois modes de transport (χ2(2) = 784,74, *p* < 0,001) avec des moyennes de rangs de 1094 pour l'automobile, de 1124 pour le vélo et de 1207 pour le transport en commun.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Autres extensions de l'ANOVA**\n:::\n::: bloc_aller_loin-body\nNous avons vu que l'ANOVA permet de comparer les moyennes d'une variable continue à partir d'une variable qualitative comprenant plusieurs modalités (facteur) pour des observations indépendantes. Il y a donc une seule variable dépendante (continue) et une seule variable indépendante. Sachez qu'il existe de nombreuses extensions de l'ANOVA classique : \n\n* **Une ANOVA à deux facteurs**, soit avec une variable dépendante continue et deux variables indépendantes qualitatives (_two-way ANOVA_ en anglais). Nous évaluons ainsi les effets des deux variables (*a*, *b*) et de leur interaction (*ab*) sur une variable continue.\n\n* **Une ANOVA multifacteur** avec une variable dépendante continue et plus de deux variables indépendantes qualitatives. Par exemple, avec trois variables qualitatives pour expliquer la variable continue, nous incluons les effets de chaque variable qualitative (*a*, *b*, *c*), ainsi que de leurs interactions (*ab*, *ac*, *bc*, *abc*).\n\n* **L'analyse de covariance** (**ANCOVA**, _**AN**alysis of **COVA**riance_ en anglais) comprend une variable dépendante continue, une variable indépendante qualitative (facteur) et plusieurs variables indépendantes continues dites covariables. L'objectif est alors de vérifier si les moyennes d'une variable dépendante sont différentes pour plusieurs groupes d'une population donnée, après avoir contrôlé l'effet d'une ou de plusieurs variables continues. Par exemple, pour une métropole donnée, nous pourrions vouloir comparer les moyennes de loyers entre la ville-centre et ceux des première et seconde couronnes (facteur), une fois contrôlée la taille de ces derniers (variable covariée continue). En effet, une partie de la variance des loyers s'explique certainement par la taille des logements.\n\n* **L'analyse de variance multivariée** (**MANOVA**, _**M**ultivariate **AN**alysis **O**f **VA**riance_ en anglais) comprend deux variables dépendantes continues ou plus et une variable indépendante qualitative (facteur). Par exemple, nous souhaiterions comparer les moyennes d'exposition au bruit et à différents polluants (dioxyde d'azote, particules fines, ozone) (variables dépendantes continues) selon le mode de transport utilisé (automobile, vélo, transport en commun), soit le facteur.\n\n* **L'analyse de covariance multivariée** (**MANCOVA**, _**M**ultivariate **AN**alysis of **COVA**riance_ en anglais), soit une analyse qui comprend deux variables dépendantes continues ou plus (comme la MANOVA) et une variable qualitative comme variable indépendante (facteur) et une covariable continue ou plus.\n\nPour le test *t*, nous avons vu qu'il peut s'appliquer soit à deux échantillons indépendants (non appariés), soit à deux échantillons dépendants (appariés). Notez qu'il existe aussi des extensions de l'ANOVA pour des échantillons pairés. Nous parlons alors d'**analyse de variance sur des mesures répétées**. Par exemple, nous pourrions évaluer la perception du sentiment de sécurité relativement à la pratique du vélo d'hiver pour un échantillon de cyclistes ayant décidé de l'adopter récemment, et ce, à plusieurs moments : avant leur première saison, à la fin de leur premier hiver, à la fin de leur second hiver. Autre exemple, nous pourrions sélectionner un échantillon d'individus (100, par exemple) pour lesquels nous évaluerions leurs perceptions de l'environnement sonore dans différents lieux de la ville. Comme pour l'ANOVA classique (échantillons non appariés), il existe des extensions de l'ANOVA sur des mesures répétées permettant d'inclure plusieurs facteurs (groupes de population); nous mesurons alors une variable continue pour plusieurs groupes d'individus à différents moments ou pour des conditions différentes. Il est aussi possible de réaliser une ANOVA pour des mesures répétées avec une ou plusieurs covariables continues. \n\nBref, si l'ANOVA était un roman, elle serait certainement « un monde sans fin » de Ken Follett! Notez toutefois que la SUPERNOVA, la BOSSA-NOVA et le CASANOVA ne sont pas des variantes de l'ANOVA!\n:::\n:::\n\n\n## Conclusion sur la troisième partie {#sec-063}\n\nDans le cadre de cette troisième partie du livre, nous avons abordé les principales méthodes exploratoires et confirmatoires bivariées permettant d’évaluer la relation entre deux variables. La @fig-PrincipalesAnalysesBivariees propose un résumé de ces méthodes.\n\n![Principales méthodes bivariées](images/Chap06/PrincipalesMethoBivariees.jpg){#fig-PrincipalesAnalysesBivariees width=\"65%\" fig-align=\"center\"}\n\n## Quiz de révision du chapitre {#sec-064}\n\n\n
\n\n\n\n
\n
Comment comparer les moyennes de deux groupes?
\n
Relisez au besoin la [section @sec-0611].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Comment comparer les médianes de plus de deux groupes?
\n
Relisez au besoin la [section @sec-0612].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Les observations de deux groupes qui n’ont aucun lien entre eux; les tailles des deux échantillons peuvent être différentes. Cette affirmation s'applique à des
\n
Relisez au besoin le début de la [section @sec-0611].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Lorsque les variances des deux groupes sont dissemblables, quel test utilisez-vous?
\n
Relisez au besoin la [section @sec-0611].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Ces boîtes à moustaches s'appliquent à des :
\n\"\"\n
Relisez au besoin la [section @sec-06111].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Plus la variance intergroupe (dissimilarité des groupes) est maximisée et corollairement plus la variance intragroupe (homogénéité de chacun des groupes) est minimisée, plus les groupes sont clairement distincts et plus l’ANOVA est performante. Selon vous, à la lecture de ces graphiques, l'ANOVA risque-t-elle d'être très performante?
\n\"\"\n
Relisez au besoin la [section @sec-06211].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quelles sont les trois conditions d’application de l’ANOVA?
\n
Relisez au besoin la [section @sec-06213].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Le test non paramétrique de Kruskal-Wallis permet de comparer les médianes de plus de deux groupes.
\n
Relisez au besoin la [section @sec-0622].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Sur quelle(s) variances est basée l'ANOVA?
\n
Relire le deuxième encadré à la [section @sec-06211].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quelles sont les variantes de l'ANOVA?
\n
Relire le deuxième encadré à la [section @sec-0624].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n\n
\n\n
\n
\n", + "supporting": [ + "06-bivarieeQualiQuanti_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/06-bivarieeQualiQuanti_files/figure-html/fig-Anova1a-1.png b/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-Anova1a-1.png similarity index 100% rename from docs/06-bivarieeQualiQuanti_files/figure-html/fig-Anova1a-1.png rename to .quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-Anova1a-1.png diff --git a/docs/06-bivarieeQualiQuanti_files/figure-html/fig-Anova1b-1.png b/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-Anova1b-1.png similarity index 100% rename from docs/06-bivarieeQualiQuanti_files/figure-html/fig-Anova1b-1.png rename to .quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-Anova1b-1.png diff --git a/docs/06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot-1.png b/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-Qqplot-1.png similarity index 100% rename from docs/06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot-1.png rename to .quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-Qqplot-1.png diff --git a/docs/06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot2-1.png b/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-Qqplot2-1.png similarity index 100% rename from docs/06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot2-1.png rename to .quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-Qqplot2-1.png diff --git a/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-ttest1-1.png b/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-ttest1-1.png new file mode 100644 index 0000000..9a2dd35 Binary files /dev/null and b/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-ttest1-1.png differ diff --git a/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-ttest2-1.png b/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-ttest2-1.png new file mode 100644 index 0000000..d027205 Binary files /dev/null and b/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/fig-ttest2-1.png differ diff --git a/docs/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-4-1.png b/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/unnamed-chunk-4-1.png similarity index 100% rename from docs/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-4-1.png rename to .quarto/_freeze/06-bivarieeQualiQuanti/figure-html/unnamed-chunk-4-1.png diff --git a/docs/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-1.png b/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/unnamed-chunk-6-1.png similarity index 100% rename from docs/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-1.png rename to .quarto/_freeze/06-bivarieeQualiQuanti/figure-html/unnamed-chunk-6-1.png diff --git a/docs/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-2.png b/.quarto/_freeze/06-bivarieeQualiQuanti/figure-html/unnamed-chunk-6-2.png similarity index 100% rename from docs/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-2.png rename to .quarto/_freeze/06-bivarieeQualiQuanti/figure-html/unnamed-chunk-6-2.png diff --git a/.quarto/_freeze/07-regressionlineaire/execute-results/html.json b/.quarto/_freeze/07-regressionlineaire/execute-results/html.json new file mode 100644 index 0000000..8461bc2 --- /dev/null +++ b/.quarto/_freeze/07-regressionlineaire/execute-results/html.json @@ -0,0 +1,16 @@ +{ + "hash": "31023bb15e7d1193800c2d9666228c03", + "result": { + "markdown": "# Régression linéaire multiple {#sec-chap07}\n\nDans ce chapitre, nous présentons la méthode de régression certainement la plus utilisée en sciences sociales : la régression linéaire multiple. À titre de rappel, dans la [section @sec-044], nous avons vu que la régression linéaire simple, basée sur la méthode des moindres carrés ordinaires (MCO), permet d’expliquer et de prédire une variable continue en fonction d’une autre variable. Toutefois, quel que soit le domaine d’étude, il est rare que le recours à une seule variable explicative (*X*) permette de prédire efficacement une variable continue (*Y*). La régression linéaire multiple est simplement une extension de la régression linéaire simple : elle permet ainsi de prédire et d'expliquer une variable dépendante (*Y*) en fonction de plusieurs variables indépendantes (explicatives).\n\nPlus spécifiquement, nous abordons ici les principes et les hypothèses de la régression linéaire multiple, comment mesurer la qualité d’ajustement du modèle, introduire des variables explicatives particulières (variable qualitative dichotomique ou polytomique, variable d’interaction, etc.), interpréter les sorties d’un modèle de régression et finalement la mettre en œuvre dans R.\n\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l’unique!\n - `ggpubr` pour combiner les graphiques\n* Pour obtenir les coefficients standardisés : \n - `QuantPsyc` avec la fonction `lm.beta` ([section @sec-0742]).\n* Pour les effets marginaux des variables indépendantes : \n - `ggeffects` avec la fonction `ggpredict` ([section @sec-0774]).\n* Pour vérifier la normalité des résidus : \n - `DescTools` avec les fonctions `Skewness` et `Kurtosis` et `JarqueBeraTest` ([section @sec-0762]).\n* Pour vérifier l'homoscédasticité des résidus : \n - `lmtest` avec la fonction `bptest` pour le test de Breusch-Pagan ([section @sec-07733]).\n* Pour vérifier la multicolinéarité excessive : \n - `car` avec la fonction `vif` ([section @sec-07734]).\n* Autre *package* : \n - `foreign` pour importer des fichiers externes.\n:::\n:::\n\n## Objectifs de la régression linéaire multiple et construction d'un modèle de régression {#sec-071}\n\nSelon Barbara G. Tabachnich et Linda S. Fidell [-@tabachnick2007], un modèle de régression permet de répondre à deux objectifs principaux relevant chacun d'une approche de modélisation particulière.\n\nLa première approche a pour objectif d’identifier les relations entre une variable dépendante (VD) et plusieurs variables indépendantes (VI). Il s’agit alors de déterminer si ces relations sont positives ou négatives, significatives ou non et d'évaluer leur ampleur. La construction du modèle de régression repose alors sur un cadre théorique et la formulation d’hypothèses, sur les relations entre chacune des VI et la VD.\n\nLa seconde approche est exploratoire et très utilisée en forage ou en fouille de données (*data mining* en anglais). Parmi un grand ensemble de variables disponibles dans un jeu de données, elle vise à identifier la ou les variables permettant de prédire le plus efficacement (précisément) une variable dépendante. Parfois, ce type de démarche ne repose ni sur un cadre théorique ni sur la formulation d’hypothèses entre les VI et la VD. Dans des cas extrêmes, on s’intéresse uniquement à la capacité de prédiction du modèle, et ce, sans analyser les associations entre les VI et la VD. L’objectif étant d’obtenir le modèle le plus efficace possible afin de prédire à l’avenir la valeur de la variable dépendante pour des observations pour lesquelles elle est inconnue. Pour ce faire, nous avons recours à des régressions séquentielles (*stepwise regressions*) dans lesquelles les variables peuvent être ajoutées une à une au modèle ou retirées de celui-ci; nous conserverons dans le modèle final uniquement celles qui ont un apport explicatif significatif. Signalons d’emblée que dans le reste du chapitre, comme du livre, nous ne nous étendons pas plus sur cette approche de modélisation, et ce, pour deux raisons. D’une part, cette approche met souvent en évidence des relations significatives entre des variables sans qu’il y ait une relation de causalité entre elles. D'autre part, en sciences sociales, un modèle de régression doit être basé sur un cadre théorique et conceptuel élaboré à la suite à d'une revue de littérature rigoureuse.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Cadre conceptuel et élaboration d'un modèle de régression**\n:::\n::: bloc_attention-body\nPour bien construire un modèle de régression, il convient de définir un cadre conceptuel élaboré à la suite à une revue de littérature sur le sujet de recherche. Ce cadre conceptuel permet d’identifier les dimensions et les concepts clefs permettant d’expliquer le phénomène à l’étude. Par la suite, pour chacun de ces concepts ou les dimensions, il est alors possible 1) d’identifier les différentes variables indépendantes qui sont introduites dans le modèle et 2) de formuler une hypothèse pour chacune d’elles. Par exemple, pour telle ou telle variable explicative, on s’attendra à ce qu’elle fasse augmenter ou diminuer significativement la variable dépendante. De nouveau, la formulation de cette hypothèse doit s'appuyer sur une interprétation théorique de la relation entre la VI et la VD.\n\nPrenons en guise d'exemple une étude récente portant sur la multiexposition des cyclistes au bruit et à la pollution atmosphérique [@2020_3]. Dans cet article, les auteurs s’intéressent aux caractéristiques de l’environnement urbain qui contribuent à augmenter ou réduire l’exposition des cyclistes à la pollution de l’air et au bruit routier. Pour ce faire, une collecte de données primaires a été réalisée avec trois cyclistes dans les rues de Paris du 4 au 7 septembre 2017. Au total, 64 heures et 964 kilomètres ont ainsi été parcourus à vélo afin de maximiser la couverture de la ville de Paris et les types d'environnements urbains traversés.\n\nLeur cadre conceptuel est schématisé à la @fig-cadreconcept. Les deux variables indépendantes (à expliquer) sont l'exposition au dioxyde d'azote (NO~2~) et l'exposition au bruit (mesurée en décibel dB(A)). Avant d'identifier les caractéristiques de l'environnement urbain affectant ces deux expositions, plusieurs facteurs, dits **variables de contrôle**, sont considérés. Par exemple, la concentration de NO~2~ varie en fonction des conditions météorologiques (vent, température et humidité) et de la pollution d'arrière-plan (variant selon le moment de la journée, le jour de la semaine et la localisation géographique au sein de la ville). Ces dimensions ne sont pas le centre d'intérêt direct de l'étude. En effet, les auteurs s'intéressent aux impacts des caractéristiques locales de l'environnement urbain. Pour pouvoir les identifier sans biais, il est nécessaire de contrôler (filtrer) l'ensemble de ces autres facteurs.\n\nDans leur cadre conceptuel, les auteurs regroupent les caractéristiques locales de l'environnement urbain en trois grandes dimensions : les caractéristiques du segment (type de rues ou de voies cyclables empruntés, intersections traversées, pente et vitesse), celles de la forme urbaine (densité résidentielle, végétation, ouverture de la rue et occupations du sol) et celles du trafic (nombre et types de véhicules croisés, congestion et zones 30 km/h). Une fois ce cadre conceptuel construit, il reste alors à identifier les variables qui permettent d'opérationnaliser chacun de concepts retenus.\n\n\n![Exemple de cadre conceptuel](images/Chap07/CadreTheorique.jpg){#fig-cadreconcept width=\"80%\" fig-align=\"center\"}\n\n\n**Notion de variables de contrôle *versus* variables explicatives**\n\nDans un modèle de régression, nous distinguons habituellement trois types de variables : la variable dépendante (*Y*) que nous souhaitons prédire ou expliquer et les variables indépendantes (*X*) qui peuvent être soit des variables de contrôle (*covariates* en anglais), soit des variables explicatives. Les premières sont des facteurs qu'il faut prendre en compte (contrôler) avant d'évaluer nos variables d'intérêt (explicatives). \n\nDans l'exemple précédent, les chercheurs voulaient évaluer l'impact des caractéristiques de l'environnement urbain (variables explicatives) sur les expositions des cyclistes au dioxyde d'azote et au bruit, et ce, une fois contrôlés les effets de facteurs reconnus comme ayant un impact significatif sur la concentration de ces polluants (conditions météorologiques et la pollution d’arrière-plan). Autrement dit, si les variables de contrôle n'avaient pas été prises en compte, l'étude des variables d'intérêt serait biaisée par les effets de ces facteurs qui n'auraient pas été contrôlés. À titre d'exemple, il est possible que les zones de circulation limitées à 30 km/h soient concentrées dans les quartiers centraux et denses de Paris. Dans ces quartiers, la pollution d'arrière-plan a tendance à être supérieure. Si nous ne tenons pas compte de cette pollution d'arrière-plan, nous pourrions arriver à la conclusion que les zones de 30 km/h sont des milieux dans lesquels les cyclistes sont plus exposés à la pollution atmosphérique.\n\n**Construction de modèles de régression imbriqués, incrémentiels**\n\nEn lien avec le cadre conceptuel du modèle, il est fréquent de construire plusieurs modèles emboîtés. Par exemple, à partir du cadre conceptuel (@fig-cadreconcept), les auteurs auraient très bien pu construire quatre modèles :\n\n* un premier avec uniquement les variables de contrôle (modèle A);\n\n* un second incluant les variables de contrôle et les variables explicatives de la dimension des caractéristiques du segment (modèle B);\n\n* un troisième reprenant les variables du modèle B dans lequel sont introduites les variables explicatives relatives à la forme urbaine (modèle C);\n\n* un dernier modèle dans lequel sont ajoutées les variables explicatives relatives aux conditions du trafic (modèle D).\n\nL’intérêt d’une telle approche est qu'elle permet d’évaluer successivement l’apport explicatif de chacune des dimensions du modèle; nous y reviendrons dans la [section @sec-0732].\n\nNous disons alors que deux modèles sont imbriqués lorsque le modèle avec le plus de variables comprend également **toutes** les variables du modèle avec le moins de variables.\n:::\n:::\n\n\n## Principes de base de la régression linéaire multiple {#sec-072}\n\n### Un peu d'équations... {#sec-0721}\n\nLa régression linéaire multiple vise à déterminer une équation qui résume le mieux les relations linéaires entre une variable dépendante (*Y*) et un ensemble de variables indépendantes (*X*). L'équation de régression s'écrit alors :\n\n$$ \ny_i = \\beta_{0} + \\beta_{1}x_{1i} + \\beta_{2}x_{2i} +\\ldots+ \\beta_{k}x_{ki} + \\epsilon_{i}\n$$ {#eq-regmultiple1}\n\navec :\n\n* $y_i$, la valeur de la variable dépendante *Y* pour l'observation *i*\n\n* $\\beta_{0}$, la constante, soit la valeur prédite pour *Y* quand toutes les variables indépendantes sont égales à 0\n\n* $k$ le nombre de variables indépendantes\n\n* $\\beta_{1}$ à $\\beta_{k}$, les coefficients de régression pour les variables indépendantes de 1 à *k* ($X_{1}$ à $X_{k}$)\n\n* $\\epsilon_{i}$, le résidu pour l'observation de *i*, soit la partie de la valeur de $y_i$ qui n'est pas expliquée par le modèle de régression.\n\nNotez qu'il existe plusieurs écritures simplifiées de cette équation. D'une part, il est possible de ne pas indiquer l'observation *i* et de remplacer les lettres grecques *bêta* et *epsilon* ($\\beta$ et $\\epsilon$) par les lettres *b* et *e* :\n\n$$\nY = b_{0} + b_{1}X_{1} + b_{2}X_{2} +\\ldots+ b_{k}X_{k} + e\n$$ {#eq-regmultiple2}\n\nD'autre part, cette équation peut être présentée sous forme matricielle. Rappelez-vous que, pour chacune des *n* observations de l'échantillon, une équation est formulée :\n\n$$\n\\left\\{\\begin{array}{l}\ny_{1}=\\beta_{0}+\\beta_{1} x_{1,1}+\\ldots+\\beta_{p} x_{1, k}+\\varepsilon_{1} \\\\\ny_{2}=\\beta_{0}+\\beta_{1} x_{2,1}+\\ldots+\\beta_{p} x_{2, k}+\\varepsilon_{2} \\\\\n\\cdots \\\\\ny_{n}=\\beta_{0}+a_{1} x_{n, 1}+\\ldots+\\beta_{p} x_{n, k}+\\varepsilon_{n}\n\\end{array}\\right.\n$$ {#eq-regmultiple3}\n\nPar conséquent, sous forme matricielle, l'équation s'écrit :\n\n$$\n\\left(\\begin{array}{c}\ny_{1} \\\\\n\\vdots \\\\\ny_{n}\n\\end{array}\\right)=\\left(\\begin{array}{cccc}\n1 & x_{1,1} & \\cdots & x_{1, k} \\\\\n\\vdots & \\vdots & \\ddots & \\vdots \\\\\n1 & x_{n, 1} & \\cdots & x_{n, k}\n\\end{array}\\right)\\left(\\begin{array}{c}\n\\beta_{0} \\\\\n\\beta_{1} \\\\\n\\vdots \\\\\n\\beta_{k}\n\\end{array}\\right)+\\left(\\begin{array}{c}\n\\varepsilon_{1} \\\\\n\\vdots \\\\\n\\varepsilon_{n}\n\\end{array}\\right)\n$$ {#eq-regmultiple4}\n\nou tout simplement :\n\n$$\nY = X\\beta + \\epsilon\n$$ {#eq-regmultiple5}\n\navec :\n\n* $Y$, un vecteur de dimension $n \\times 1$ pour la variable dépendante, soit une colonne avec *n* observations\n\n* $X$, une matrice de dimension $n \\times (k + 1)$ pour les *k* variables indépendantes, incluant une autre colonne (avec la valeur de 1 pour les *n* observations) pour la constante d'où $k + 1$\n\n* $\\beta$, un vecteur de dimension $k + 1$, soit les coefficients de régression pour les *k* variables et la constante\n\n* $\\epsilon$, un vecteur de dimension $n \\times 1$ pour les résidus.\n \n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Parties expliquée et non expliquée de la régression linéaire multiple**\n:::\n::: bloc_attention-body\nVous aurez compris que, comme pour la régression linéaire simple ([section @sec-044]), l'équation de la régression linéaire multiple comprend aussi une partie expliquée et une autre non expliquée (stochastique) par le modèle :\n$$\nY = \\underbrace{\\beta_{0} + \\beta_{1}X_{i} + \\beta_{2}X_{i} +\\ldots+ \\beta_{k}X_{k}}_{\\mbox{partie expliquée par le modèle}}+ \\underbrace{\\epsilon}_{\\mbox{partie non expliquée (stochastique)}}\n$$ {#eq-regmultiple6}\n\n$$\nY = \\underbrace{X\\beta}_{\\mbox{partie expliquée par le modèle}}+ \\underbrace{\\epsilon}_{\\mbox{partie non expliquée (stochastique)}}\n$$ {#eq-regmultiple8}\n:::\n:::\n\n### Hypothèses de la régression linéaire multiple {#sec-0722}\n\nUn modèle est bien construit s'il respecte plusieurs hypothèses liées à la régression, dont les principales étant :\n\n* **Hypothèse 1**. *La variable dépendante doit être continue et non-bornée*. Quant aux variables indépendantes (VI), elles peuvent être quantitatives (discrètes ou continues) et qualitatives (nominale ou ordinale).\n\n* **Hypothèse 2**. *La variance de chaque VI doit être supérieure à 0*. Autrement dit, toutes les observations ne peuvent avoir la même valeur.\n\n* **Hypothèse 3**. *Indépendance des termes d'erreur*. Les résidus des observations ($\\epsilon_{1}, \\epsilon_{2}, \\ldots, \\epsilon_{n}$) ne doivent pas être corrélés entre eux. Autrement dit, les observations doivent être indépendantes les unes des autres, ce qui n'est souvent pas le cas pour des mesures temporelles. Par exemple, l'application du cadre conceptuel sur la modélisation de l'exposition des cyclistes au bruit et à la pollution atmosphérique (@fig-cadreconcept)) est basée sur des données primaires collectées lors de trajets réalisés à vélo dans une ville donnée. Par conséquent, deux observations qui se suivent ont bien plus de chances de se ressembler – du point de vue des mesures de pollution et des caractéristiques de l'environnement urbain – que deux observations tirées au hasard dans le jeu de données. Ce problème d'autocorrélation temporelle doit être contrôlé, sinon, les coefficients de régression seront biaisés.\n\n* **Hypothèse 4**. *Normalité des résidus* avec une moyenne centrée sur zéro.\n\n* **Hypothèse 5**. *Absence de colinéarité parfaite entre les variables explicatives*. Par exemple, dans un modèle, nous ne pouvons pas introduire à la fois les pourcentages de locataires et de propriétaires, car pour chaque observation, la somme des deux donne 100 %. Nous avons donc une corrélation parfaite entre ces deux variables : le coefficient de corrélation de Pearson entre ces deux variables est égal à 1. Par conséquent, le modèle ne peut pas être estimé avec ces deux variables et l'une des deux est automatiquement ôtée.\n\n* **Hypothèse 6**. *Homoscédasticité des erreurs (ou absence d'hétéroscédasticité)*. Les résidus doivent avoir une variance constante, c'est-à-dire qu'elle doit être la même pour chaque observation. Il y a homoscédasticité lorsqu'il y a une absence de corrélation entre les résidus et les valeurs prédites. Si cette condition n'est pas respectée, nous parlons alors d'hétéroscédasticité.\n\n* **Hypothèse 7**. *Le modèle est bien spécifié*. Un modèle est mal spécifié (construit) quand « une ou plusieurs variables non pertinentes sont incluses dans le modèle » ou « qu’une ou plusieurs variables pertinentes sont exclues du modèle » [@bressoux2010, p.138-139]. Concrètement, l'inclusion d'une variable non pertinente ou l'omission d'une variable peut entraîner une mauvaise estimation des effets des variables explicatives du modèle.\n\nPour connaître les conséquences de la violation de chacune de ces hypothèses, vous pourrez notamment consulter l'excellent ouvrage de Bressoux [-@bressoux2010, p.103-110]. Retenez ici que le non-respect de ces hypothèses produit des coefficients de régression biaisés.\n\n\n## Évaluation de la qualité d’ajustement du modèle {#sec-073}\n\nPour illustrer la régression linéaire multiple, nous utilisons un jeu de données tiré d'un article portant sur la distribution spatiale de la végétation sur l'île de Montréal abordée sous l'angle de l'équité environnementale [@apparicio2016spatial]. Dans cette étude, les auteurs veulent vérifier si certains groupes de population (personnes à faible revenu, minorités visibles, personnes âgées et enfants de moins de 15 ans) ont ou non une accessibilité plus limitée à la végétation urbaine. En d’autres termes, cet article tente de répondre à la question suivante : une fois contrôlées les caractéristiques de la forme urbaine (densité de population et âge du bâti), est-ce que les quatre groupes de population résident dans des îlots urbains avec proportionnellement moins ou plus de végétation?\n\nDans le @tbl-datareg, sont reportées les variables utilisées (calculées au niveau des îlots de l'île de Montréal) introduites dans le modèle de régression : \n\n* le pourcentage de la superficie de l'îlot couverte par de la végétation, soit la variable indépendante (VI);\n\n* deux variables indépendantes de contrôle (VC) relatives à la forme urbaine;\n\n* les pourcentages des quatre groupes de population comme variables indépendantes explicatives (VE).\n\n**Notez que ce jeu de données est utilisé tout au long du chapitre.** L'équation de départ du premier modèle de régression est donc :\n\n`VegPct ~ HABHA + AgeMedian + Pct_014 + Pct_65P + Pct_MV + Pct_FR`\n\n\n::: {#tbl-datareg .cell tbl-cap='Statistiques descriptives pour les variables du modèle'}\n::: {.cell-output-display}\n| |Nom |Intitulé | Type | Moy.| E.-T.| Q1| Q2| Q3|\n|:---------|:---------|:-----------------------------|:----:|----:|-----:|----:|----:|-----:|\n|VegPct |VegPct |Végétation (%) | VD | 35,1| 18,6| 20,3| 33,8| 49,0|\n|HABHA |HABHA |Habitants au km2 | VC | 87,8| 74,0| 36,9| 68,4| 120,5|\n|AgeMedian |AgeMedian |Âge médian des bâtiments | VC | 52,1| 25,2| 37,2| 49,0| 61,0|\n|Pct_014 |Pct_014 |Moins de 15 ans (%) | VE | 15,9| 5,3| 12,5| 15,9| 19,3|\n|Pct_65P |Pct_65P |65 ans et plus (%) | VE | 14,9| 8,3| 9,6| 13,9| 18,2|\n|Pct_MV |Pct_MV |Minorités visibles (%) | VE | 21,0| 16,4| 8,3| 17,2| 29,6|\n|Pct_FR |Pct_FR |Personnes à faible revenu (%) | VE | 23,6| 16,0| 11,1| 21,3| 33,7|\n:::\n:::\n\n\n\n### Mesures de la qualité d'un modèle {#sec-0731}\n\nComme pour la régression linéaire simple ([section @sec-044]), les trois mesures les plus couramment utilisées pour évaluer la qualité d'un modèle sont :\n\n* Le **coefficient de détermination** (R^2^) qui indique la proportion de la variance de la variable dépendante expliquée par les variables indépendantes du modèle (@eq-regmR2). Il varie ainsi de 0 à 1.\n\n* La **statistique de Fisher** qui permet d'évaluer la significativité globale du modèle (@eq-regmFFisher). Dans le cas d'une régression linéaire multiple, l'hypothèse nulle du test *F* est que toutes les valeurs des coefficients de régression des variables indépendantes sont égales à 0; autrement dit, qu'aucune des variables indépendantes n'a d'effet sur la variable dépendante. Tel que décrit à la [section @sec-0443], il est possible d'obtenir une valeur de *p* rattachée à la statistique *F* avec *k* degrés de liberté au dénominateur et *n-k-1* degrés de liberté au numérateur (*k* et *n* étant respectivement le nombre de variables indépendantes et le nombre d'observations). Lorsque la valeur de *p* est inférieure à 0,05, nous pourrons en conclure que le modèle est globalement significatif, c'est-à-dire qu'au moins un coefficient de régression est significativement différent de zéro. Notez qu'il est plutôt rare qu'un modèle de régression, comprenant plusieurs variables indépendantes, soit globalement non significatif (P > 0,05), et ce, surtout s'il est basé sur un cadre conceptuel et théorique solide. Le test de la statistique de Fisher est donc facile à passer et ne constitue pas une preuve absolue de la pertinence du modèle.\n\n* **L'erreur quadratique moyenne (RMSE)** qui indique l'erreur absolue moyenne du modèle exprimée dans l'unité de mesure de la variable dépendante, autrement dit l'écart absolu moyen entre les valeurs observées et prédites du modèle (@eq-regmRMSE). Une valeur élevée indique que le modèle se trompe largement en moyenne et inversement.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Rappel sur la décomposition de la variance et calcul du R^2^, de la statistique *F* et du RMSE**\n:::\n::: bloc_attention-body\nRappelez-vous que la variance totale (SCT) est égale à la somme de la variance expliquée (SCE) par le modèle et de la variance non expliquée (SCR) par le modèle.\n\n$$\n\\underbrace{\\sum_{i=1}^n (y_{i}-\\bar{y})^2}_{\\mbox{variance de Y}} = \\underbrace{\\sum_{i=1}^n (\\widehat{y}_i-\\bar{y})^2}_{\\mbox{var. expliquée}} + \\underbrace{\\sum_{i=1}^n (y_{i}-\\widehat{y})^2}_{\\mbox{var. non expliquée}} \\Rightarrow \nSCT = SCE + SCR\n$$ {#eq-regmVariances}\n\navec :\n\n* $y_{i}$ est la valeur observée de la variable dépendante pour *i*;\n* $\\bar{y}$ est la valeur moyenne de la variable dépendante;\n* $\\widehat{y}_i$ est la valeur prédite de la variable dépendante pour *i*.\n\nÀ partir des trois variances (totale, expliquée et non expliquée), il est alors possible de calculer les trois mesures de la qualité d'ajustement du modèle.\n\n$$\nR^2 = \\frac{\\sum_{i=1}^n (\\widehat{y}_i-\\bar{y})^2}{\\sum_{i=1}^n (y_{i}-\\bar{y})^2} = \\frac{SCE}{SCT} \\mbox{ avec } R^2 \\in \\left[0,1\\right]\n$$ {#eq-regmR2}\n\n$$\nF = \\frac{\\frac{\\sum_{i=1}^n (\\widehat{y}_i-\\bar{y})^2}{k}}{\\frac{\\sum_{i=1}^n (y_{i}-\\widehat{y})^2}{n-k-1}} = \\frac{\\frac{SCE}{k}}{\\frac{SCR}{n-k-1}} = \\frac{\\frac{R^2}{k}} {\\frac{1-R^2}{n-k-1}} = \\frac{(n-k-1)R^2}{k(1-R^2)}\n$$ {#eq-regmFFisher}\n\n$$\nRMSE = \\sqrt{\\frac{\\sum_{i=1}^n (y_{i}-\\widehat{y})^2}{n}} = \\sqrt{\\frac{SCR}{n}}\n$$ {#eq-regmRMSE}\n\n:::\n:::\n\nGlobalement, plus un modèle de régression est efficace, plus les valeurs du R^2^ et de la statistique *F* sont élevées et inversement, plus celle de RMSE est faible. En effet, remarquez qu'à l'@eq-regmFFisher, la statistique *F* peut être obtenue à partir du R^2^; par conséquent, plus la valeur du R^2^ est forte (proche de 1), plus celle de *F* est aussi élevée. Notez aussi que plus un modèle est performant, plus la partie expliquée par le modèle (SCE) est importante et plus celle non expliquée (SCR) est faible; ce qui signifie que plus le R^2^ est proche de 1 (@eq-regmR2), plus le RMSE – calculé à partir du SCR – est faible (@eq-regmRMSE).\n\nLa syntaxe R ci-dessous illustre comment calculer les différentes variances (SCT, SCE et SCR) à partir des valeurs observées et prédites par le modèle, puis les valeurs du R^2^, de *F* et du RMSE. Nous verrons par la suite qu'il est possible d'obtenir directement ces valeurs à partir de la fonction `summary(VotreModele)`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Chargement des données\nload(\"data/lm/DataVegetation.RData\")\n\n# Construction du modèle de régression\nModele1 <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n\n# Nombre d'observations \nn <- nrow(DataFinal)\n# Nombre de variables indépendantes (coefficients moins la constante)\nk <- length(Modele1$coefficients)-1\n# Vecteur pour les valeurs observées\nYobs <- DataFinal$VegPct\n# Vecteur pour les valeurs prédites\nYpredit <- Modele1$fitted.values\n# Variance totale\nSCT <- sum((Yobs-mean(Yobs))^2)\n# Variance expliquée\nSCE <- sum((Ypredit-mean(Yobs))^2)\n# Variance résidelle\nSCR <- sum((Yobs-Ypredit)^2)\n# Calcul du coefficient de détermination (R2)\nR2 <- SCE / SCT\n# Calcul de la valeur de F\nvaleurF <- (R2 / k) /((1-R2)/(n-k-1))\n\ncat(\"R2 =\", round(SCE / SCT,4),\n \"\\nF de Fisher = \", round(valeurF,0),\n \"\\nRMSE =\", round(sqrt(SCR/ n),4)\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nR2 = 0.4182 \nF de Fisher = 1223 \nRMSE = 14.1575\n```\n:::\n:::\n\n\n\n### Comparaison des modèles incrémentiels {#sec-0732}\n\nTel que signalé plus haut, il est fréquent de construire plusieurs modèles de régression imbriqués. Cette démarche est très utile pour évaluer l'apport de l'introduction d'un nouveau bloc de variables dans un modèle. De manière exploratoire, cela permet également de vérifier si l'introduction d'une variable indépendante supplémentaire dans un modèle a ou non un apport significatif et ainsi de décider de la conserver, ou non, dans le modèle final selon le principe de parcimonie. \n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Le principe de parcimonie** \n:::\n::: bloc_notes-body\nLe principe de parcimonie appliqué aux régressions correspond à l'idée qu'il est préférable de disposer d'un **modèle plus simple** que d'un **modèle compliqué** pour expliquer un phénomène si la qualité de leurs prédictions – qualité d’ajustement des deux modèles – est équivalente.\n\nUne première justification de ce principe trouve son origine dans la philosophie des sciences avec le **rasoir d'Ockham**. Il s'agit d'un principe selon lequel il est préférable de privilégier des théories faisant appel à un plus petit nombre d'hypothèses. L'idée centrale étant d'éviter d'apporter des réponses à une question qui soulèveraient davantage de nouvelles questions. Dans le cas d'une régression, nous pourrions être tenté d'ajouter de nombreuses variables indépendantes pour améliorer la capacité de prédiction du modèle. Cette stratégie conduit généralement à observer des relations contraires à nos connaissances entre les variables du modèle, ce qui soulève de nouvelles questions de recherche (pas toujours judicieuses…). Dans notre quotidien, si une casserole tombe de son support, il est plus raisonnable d'imaginer que nous l'avions mal fixée que d'émettre l'hypothèse qu'un fantôme l'a volontairement fait tomber! Cette seconde hypothèse soulève d’autres questions (pas toujours judicieuses…) sur la nature d'un fantôme, son identité, la raison le poussant à agir, etc.\n\nUne seconde justification de ce principe s'observe dans la pratique statistique : des modèles plus complexes ont souvent une plus faible capacité de généralisation. En effet, un modèle complexe et trop bien ajusté aux données observées est souvent incapable d'effectuer des prédictions justes pour de nouvelles données. Ce phénomène est appelé surajustement ou surinterprétation (*overfitting* en anglais). \nLe surajustement résultant de modèles trop complexes entre en conflit direct avec l'enjeu principal de l'inférence en statistique : pouvoir généraliser des observations faites sur un échantillon au reste d'une population.\n\nNotez que ce principe de parcimonie ne signifie pas que vous devez systématiquement retirer toutes les variables non significatives de votre analyse. En effet, il peut y avoir un intérêt théorique à démontrer l'absence de relation entre des variables. Il s'agit plutôt d'une ligne de conduite à garder à l'esprit lors de l'élaboration du cadre théorique et de l'interprétation des résultats.\n:::\n:::\n\nMathématiquement, plus nous ajoutons de variables supplémentaires dans un modèle, plus le R^2^ augmente. On ne peut donc pas utiliser directement le R^2^ pour comparer deux modèles de régression ne comprenant pas le même nombre de variables indépendantes. Nous privilégions alors l'utilisation du R^2^ ajusté qui, comme illustré dans l'@eq-R2ajuste, tient compte à la fois des nombres d'observations et des variables indépendantes utilisées pour construire le modèle.\n\n$$ \nR^2_{\\text {ajusté}}= 1 - \\frac{(1-R^2)(n-1)}{n-k-1} \\mbox{ avec } R^2_{\\text {ajusté}} \\in \\left[0,1\\right]\n$$ {#eq-R2ajuste}\n\nSi le R^2^ ajusté du second modèle est supérieur au premier modèle, cela signifie qu'il y a un gain de la variance expliquée entre le premier et le second modèle. Ce gain est-il pour autant significatif? Pour y répondre, il convient de comparer les valeurs des statistiques *F* des deux modèles. Pour ce faire, nous calculons le *F* incrémentiel et la valeur de *p* qui lui est associé avec comme degrés de liberté, le nombre de variables indépendantes ajoutées ($k_2-k_1$) et $n-k_2-1$. Si la valeur de *p* < 0,05, nous pouvons conclure que le gain de variance expliquée par le second modèle est significatif comparativement au premier modèle (au seuil de 5 %). \n\n$$\nF_{\\text {incrémentiel}}= \\frac{\\frac{R^2_2-R^2_1}{k_2-k_1}} {\\frac{1-R^2_2}{n-k_2-1}}\n$$ {#eq-Fincrementiel}\n\navec $R^2_1$ et $R^2_2$ étant les coefficients de détermination des modèles 1 et 2 et $k_1$ et $k_2$ étant les nombres de variables indépendantes qu'ils comprennent ($k_2 > k_1$).\n\nIllustrons le tout avec deux modèles. Dans la syntaxe R ci-dessous, nous avons construit un premier modèle avec uniquement les variables de contrôle (`modele1`), soit deux variables indépendantes (`HABHA` et `AgeMedian`). Puis, dans un second modèle (`modele2`), nous ajoutons comme variables indépendantes les pourcentages des quatre groupes de population (`Pct_014`, `Pct_65P`, `Pct_MV`, `Pct_FR`). Repérez comment sont calculés les R^2^ ajustés pour les modèles et le *F* incrémentiel.\n\nLe R^2^ ajusté passe de 0,269 à 0,418 des modèles 1 à 2 signalant que l'ajout des quatre variables indépendantes augmente considérablement la variance expliquée. Autrement dit, le second modèle est bien plus performant. Le *F* incrémentiel s'élève à 653,8 et est significatif (*p* < 0,001). Notez que la syntaxe ci-dessous illustre comment calculer les valeurs du R^2^ ajusté et du *F* incrémentiel à partir des équations [-@eq-R2ajuste] et [-@eq-Fincrementiel]. Sachez toutefois qu'il est possible d'obtenir directement le R^2^ ajusté avec la fonction `summary(VotreModele)` et le *F* incrémentiel avec la fonction `anova(modele1, modele2)`. \n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodele1 <- lm(VegPct ~ HABHA+AgeMedian, data = DataFinal)\nmodele2 <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n\n# nombre d'observations pour les deux modèles\nn1 <- length(modele1$fitted.values)\nn2 <- length(modele2$fitted.values)\n\n# nombre de variables indépendantes\nk1 <- length(modele1$coefficients)-1\nk2 <- length(modele2$coefficients)-1\n\n# coefficient de détermination\nR2m1 <- summary(modele1)$r.squared\nR2m2 <- summary(modele2)$r.squared\n\n# coefficient de détermination ajusté\nR2ajustm1 <- 1-(((n1-1)*(1-R2m1)) / (n1-k1-1))\nR2ajustm2 <- 1-(((n2-1)*(1-R2m2)) / (n2-k2-1))\n\n# Statistique F\nFm1 <- summary(modele1)$fstatistic[1]\nFm2 <- summary(modele2)$fstatistic[1]\n\n# F incrémentiel\nFincrementiel <- ((R2m2-R2m1) / (k2 - k1)) / ( (1-R2m2)/(n2-k2-1))\npFinc <- pf(Fincrementiel, k2-k1, n2-k2-1, lower.tail = FALSE)\n\ncat(\"\\nR2 (modèle 1) =\", round(R2m1,4), \n \"; R2 ajusté = \", round(R2ajustm1,4), \n \"; F =\", round(Fm1, 1),\n \"\\nR2 (modèle 2) =\", round(R2m2,4), \n \"; R2 ajusté = \", round(R2ajustm2,4), \n \"; F =\", round(Fm2, 1),\n \"\\nF incrémentiel =\", round(Fincrementiel,1), \n \"; p = \", round(pFinc,3)\n)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nR2 (modèle 1) = 0.2691 ; R2 ajusté = 0.269 ; F = 1879.2 \nR2 (modèle 2) = 0.4182 ; R2 ajusté = 0.4179 ; F = 1222.5 \nF incrémentiel = 653.8 ; p = 0\n```\n:::\n\n```{.r .cell-code}\n# F incrémentiel avec la fonction anova\nanova(modele1, modele2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nAnalysis of Variance Table\n\nModel 1: VegPct ~ HABHA + AgeMedian\nModel 2: VegPct ~ HABHA + AgeMedian + Pct_014 + Pct_65P + Pct_MV + Pct_FR\n Res.Df RSS Df Sum of Sq F Pr(>F) \n1 10207 2570964 \n2 10203 2046427 4 524537 653.8 < 2.2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n```\n:::\n:::\n\n\n\n## Différentes mesures pour les coefficients de régression {#sec-074}\n\nLa fonction `summary(nom du modèle)` permet d'obtenir les résultats du modèle de régression. D'emblée, signalons que le modèle est globalement significatif (*F*(6, 10203) = 1123, *p* = 0,000) avec un R^2^ de 0,4182 indiquant que les variables indépendantes du modèle expliquent 41,82 % de la variance du pourcentage de végétation dans les îlots de l'île de Montréal.\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodelereg <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\nsummary(modelereg)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCall:\nlm(formula = VegPct ~ HABHA + AgeMedian + Pct_014 + Pct_65P + \n Pct_MV + Pct_FR, data = DataFinal)\n\nResiduals:\n Min 1Q Median 3Q Max \n-48.876 -9.757 -0.232 9.499 103.830 \n\nCoefficients:\n Estimate Std. Error t value Pr(>|t|) \n(Intercept) 26.355774 0.882235 29.874 <2e-16 ***\nHABHA -0.070401 0.002202 -31.975 <2e-16 ***\nAgeMedian 0.010790 0.006369 1.694 0.0902 . \nPct_014 1.084478 0.032179 33.702 <2e-16 ***\nPct_65P 0.400531 0.018835 21.265 <2e-16 ***\nPct_MV -0.031112 0.010406 -2.990 0.0028 ** \nPct_FR -0.348256 0.011640 -29.918 <2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\nResidual standard error: 14.16 on 10203 degrees of freedom\nMultiple R-squared: 0.4182,\tAdjusted R-squared: 0.4179 \nF-statistic: 1223 on 6 and 10203 DF, p-value: < 2.2e-16\n```\n:::\n:::\n\n\n### Coefficients de régression : évaluer l'effet des variables indépendantes {#sec-0741}\n\nLes différents résultats pour les coefficients sont reportés au @tbl-dataregmodel2. \n\n**La constante** ($\\beta_0$) est la valeur attendue de la variable dépendante (*Y*) quand les valeurs de toutes les variables indépendantes sont égales à 0. Pour ce modèle, quand les variables indépendantes sont égales à 0, plus du quart de la superficie des îlots serait en moyenne couverte par de la végétation ($\\beta_0$ = 26,36). Notez que la constante n'a pas toujours une interprétation pratique. Il est par exemple très invraisemblable d'avoir un îlot avec de la population dans lequel il n'y aurait aucune personne à faible revenu, aucune personne ne déclarant appartenir à une minorité visible, aucun enfant de moins de 15 ans et aucune personne âgée de 65 ans et plus. La constante a donc avant tout un rôle mathématique dans le modèle.\n\n**Le coefficient de régression** ($\\beta_1$ à $\\beta_k$) indique le changement de la variable dépendante (*Y*) lorsque la variable indépendante augmente d'une unité, toutes choses étant égales par ailleurs. Il permet ainsi d'évaluer l'effet d'une augmentation d'une unité dans laquelle est mesurée la VI sur la VD.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Que signifie l'expression *toutes choses étant égales par ailleurs* pour un coefficient de régression?**\n:::\n::: bloc_attention-body\nAprès l'apprentissage du grec, grâce aux nombreuses équations intégrées au livre, passons au latin! L'expression *toutes choses étant égales par ailleurs* vient du latin *ceteris paribus*, à ne pas confondre avec *c'est terrible Paris en bus* (petite blague formulée par un étudiant ayant suivi le cours *Méthodes quantitatives appliquées en études urbaines* à l'INRS il y a quelques années)! Certains auteurs emploient encore *ceteris paribus* : il est donc possible que vous la retrouviez dans un article scientifique... \n\nPlus sérieusement, l'expression *toutes choses étant égales par ailleurs* signifie que l'on estime l'effet de la variable indépendante sur la variable dépendante, si toutes les autres variables indépendantes restent constantes ou autrement dit, une fois contrôlés tous les autres prédicteurs. \n:::\n:::\n\n\n::: {#tbl-dataregmodel2 .cell tbl-cap='Différentes mesures pour les coefficients'}\n::: {.cell-output-display}\nTable: Différentes mesures pour les coefficients\n\n|Variable | Coef.| Erreur type| Valeur de T| P| coef. 2,5 %| coef. 97,5 %| |\n|:---------|------:|-----------:|-----------:|-----:|-----------:|------------:|---:|\n|Constante | 26,356| 0,882| 29,870| 0,000| 24,626| 28,085| ***|\n|HABHA | -0,070| 0,002| -31,970| 0,000| -0,075| -0,066| ***|\n|AgeMedian | 0,011| 0,006| 1,690| 0,090| -0,002| 0,023| .|\n|Pct_014 | 1,084| 0,032| 33,700| 0,000| 1,021| 1,148| ***|\n|Pct_65P | 0,401| 0,019| 21,260| 0,000| 0,364| 0,437| ***|\n|Pct_MV | -0,031| 0,010| -2,990| 0,003| -0,052| -0,011| **|\n|Pct_FR | -0,348| 0,012| -29,920| 0,000| -0,371| -0,325| ***|\n:::\n:::\n\n\n\nÀ partir des coefficients du @tbl-dataregmodel2, l'équation du modèle de régression s'écrit alors comme suit :\n\n`VegPct = 26,356 − 0,070 HABHA + 0,011 AgeMedian + 1,084 Pct_014 + 0,401 Pct_65P −0,031 Pct_MV − 0,348 Pct_FR + e`\n\n\n**Comment interpréter un coefficient de régression pour une variable indépendante?**\n\nLe signe du coefficient de régression indique si la variable indépendante est associée positivement ou négativement avec la variable dépendante. Par exemple, plus la densité de population est importante à travers les îlots de l'île de Montréal, plus la couverture végétale diminue.\n\nQuant à la valeur absolue du coefficient, elle indique la taille de l'effet du prédicteur. Par exemple, 1,084 signifie que si toutes les autres variables indépendantes restent constantes, alors le pourcentage de végétation dans l'îlot augmente de 1,084 points de pourcentage pour chaque différence d’un point de pourcentage d'enfants de moins de 15 ans. Toutes choses étant égales par ailleurs, une augmentation de 10 % d'enfants dans un îlot entraîne alors une hausse de 10,8 % de la couverture végétale dans l'îlot.\n\nL'analyse des coefficients montre ainsi qu'une fois contrôlées les deux caractéristiques relatives à la forme urbaine (densité de population et âge médian des bâtiments), plus les pourcentages d'enfants et de personnes âgées sont élevés, plus la couverture végétale de l'îlot est importante (B = 1,084 et 0,401), toutes choses étant égales par ailleurs. À l'inverse, de plus grands pourcentages de personnes à faible revenu et de minorités sont associés à une plus faible couverture végétale (B = −0,348 et −0,031).\n\n\n**L'erreur type du coefficient de régression**\n\nL'erreur type d'un coefficient permet d'évaluer son niveau de précision, soit le degré d'incertitude vis-à-vis du coefficient. Succinctement, elle correspond à l'écart-type de l'estimation (coefficient); elle est ainsi toujours positive. Plus la valeur de l'erreur type est faible, plus l'estimation du coefficient est précise. Notez toutefois qu'il n'est pas judicieux de comparer les erreurs types des coefficients pour des variables exprimées dans des unités de mesure différentes. \n\nComme nous le verrons plus loin, l'utilité principale de l'erreur type est qu'elle permet de calculer la valeur de *t* et l'intervalle de confiance du coefficient de régression.\n\n\n### Coefficients de régression standardisés : repérer les variables les plus importantes du modèle {#sec-0742}\n\nUn coefficient de régression est exprimé dans les unités de mesure des variables indépendante (VI) et dépendante (VD) : une augmentation d’une unité de la VI a un effet de $\\beta$ (valeur de coefficient) unité de mesure sur la VD, toutes choses étant égales par ailleurs. Prenons l’exemple d’un modèle fictif dans lequel une variable indépendante mesurée en mètres obtient un coefficient de régression de 0,000502. Si cette variable était exprimée en kilomètres et non en mètres, son coefficient serait alors de 0,502 ($0,000502 \\times 1000 = 0,502$). Cela explique que pour certaines variables, il est souvent préférable de modifier l'unité de mesure, particulièrement pour les variables de distance ou de revenu. Par exemple, dans un modèle de régression, nous introduisons habituellement une variable de revenu par tranche de mille dollars ou le loyer mensuel par tranche de cent dollars, puisque les coefficients du revenu ou de loyer exprimé en dollars risquent d'être extrêmement faibles. Concrètement, cela signifie que nous divisons la variable *revenu* par 1000 et celle du *loyer* par 100 avant de l'introduire dans le modèle.\n\nDu fait de leur unités de mesure souvent différentes, vous aurez compris que nous ne pouvons pas comparer directement les coefficients de régression afin de repérer la ou les variables indépendantes (*X*) qui ont les effets (impacts) les plus importants sur la variable dépendante (*Y*). Pour remédier à ce problème, nous utilisons les **coefficients de régression standardisés**. Ces coefficients standardisés sont simplement les valeurs de coefficients de régression qui seraient obtenus si toutes les variables du modèle (VD et VI) étaient préalablement centrées réduites (soit avec une moyenne égale à 0 et un écart-type égal à 1; consultez la [section @sec-02552] pour un rappel). Puisque toutes les variables du modèle sont exprimées en écarts-types, les coefficients standardisés permettent ainsi d'évaluer **l'effet relatif** des VI sur la VD. Cela permet ainsi de repérer la ou les variables les plus « importantes » du modèle.\n\n**L'interprétation d'un coefficient de régression standardisé est donc la suivante : il indique le changement en termes d'unités d'écart-type de la variable dépendante (Y) à chaque ajout d'un écart-type de la variable indépendante, toutes choses étant égales par ailleurs**. \n\n\nLe coefficient de régression standardisé peut être aussi facilement calculé en utilisant les écarts-types des deux variables VI et VD :\n\n$$\n\\beta_{z}= \\beta \\frac{s_x}{s_y}\n$$ {#eq-CoefStand}\n\nLa syntaxe R ci-dessous illustre trois façons d'obtenir les coefficients standardisés :\n\n* en centrant et réduisant préalablement les variables avec la fonction `scale` avant de construire le modèle avec la fonction `lm`;\n\n* en calculant les écarts-types de VD et de VI et en appliquant l'@eq-CoefStand;\n\n* avec la fonction `lm.beta` du *package* `QuantPsyc`. Cette dernière méthode est moins « verbeuse » (deux lignes de code uniquement), mais nécessite de charger un *package* supplémentaire.\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Modèle de régression\nModele1 <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n\n# Méthode 1 : lm sur des variables centrées réduites\nModeleZ <- lm(scale(VegPct) ~ scale(HABHA)+scale(AgeMedian)+\n scale(Pct_014)+scale(Pct_65P)+\n scale(Pct_MV)+scale(Pct_FR), data = DataFinal)\ncoefs <- ModeleZ$coefficients\ncoefs[1:length(coefs)]\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n (Intercept) scale(HABHA) scale(AgeMedian) scale(Pct_014) \n 3.721649e-16 -2.806891e-01 1.467299e-02 3.093456e-01 \n scale(Pct_65P) scale(Pct_MV) scale(Pct_FR) \n 1.788453e-01 -2.755087e-02 -3.004544e-01 \n```\n:::\n\n```{.r .cell-code}\n# Méthode 2 : à partir de l'équation\n# Écart-type de la variable dépendante\nVDet <- sd(DataFinal$VegPct)\ncat(\"Écart-type de Y =\", round(VDet,3))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nÉcart-type de Y = 18.562\n```\n:::\n\n```{.r .cell-code}\n# Écarts-types des variables indépendantes\nVI <- c(\"HABHA\" , \"AgeMedian\" , \"Pct_014\" , \"Pct_65P\" , \"Pct_MV\" , \"Pct_FR\")\nVIet <- sapply(DataFinal[VI], sd)\n# Coefficients de régression du modèle sans la constante\ncoefs <- Modele1$coefficients[1:length(VIet)+1]\n# Coefficients de régression du modèle\ncoefstand <- coefs * (VIet / VDet)\ncoefstand\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HABHA AgeMedian Pct_014 Pct_65P Pct_MV Pct_FR \n-0.28068906 0.01467299 0.30934560 0.17884535 -0.02755087 -0.30045437 \n```\n:::\n\n```{.r .cell-code}\n# Méthode 3 : avec la fonction lm.beta du package QuantPsyc\nlibrary(QuantPsyc)\nlm.beta(lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n HABHA AgeMedian Pct_014 Pct_65P Pct_MV Pct_FR \n-0.28068906 0.01467299 0.30934560 0.17884535 -0.02755087 -0.30045437 \n```\n:::\n:::\n\n::: {#tbl-CoefStand2 .cell tbl-cap='Calcul des coefficients standardisés'}\n::: {.cell-output-display}\n| |Variable dépendante | Écart-type| Coef.| Coef. standardisé|\n|:---------|:-------------------|----------:|------:|-----------------:|\n|HABHA |HABHA | 74,008| -0,070| -0,281|\n|AgeMedian |AgeMedian | 25,241| 0,011| 0,015|\n|Pct_014 |Pct_014 | 5,295| 1,084| 0,309|\n|Pct_65P |Pct_65P | 8,289| 0,401| 0,179|\n|Pct_MV |Pct_MV | 16,438| -0,031| -0,028|\n|Pct_FR |Pct_FR | 16,015| -0,348| -0,300|\n:::\n:::\n\n\nPar exemple, pour la variable `Pct_014`, le coefficient de régression standardisé est égal à : \n\n$$\n\\beta_{z}= 1,084 \\times \\frac{5,295}{18,562}=0,309\n$$ {#eq-CoefStand2}\n\navec 1,084 étant le coefficient de régression de `Pct_014`, 5,295 et 18,562 étant respectivement les écarts-types de `Pct_014` (variable indépendante) et de `VegPct` (variable dépendante).\n\nAu @tbl-CoefStand2, nous constatons que la valeur absolue du coefficient de régression pour `HABHA` est inférieure à celle de `Pct_65P` (−0,070 *versus* 0,401), ce qui n'est pas le cas pour leur coefficient standardisé (−0,281 *versus* 0,179). Rappelez-vous aussi que nous ne pouvons pas directement comparer les effets de ces deux variables à partir des coefficients de régression puisqu'elles sont exprimées dans des unités de mesure différentes : `HABHA` est exprimée en habitants par hectare et `Pct_65P` en pourcentage. À la lecture des coefficients standardisés, nous pouvons en conclure que la variable `HABHA` a un effet relatif plus important que `Pct_65P` (−0,281 *versus* 0,179).\n\n### Significativité des coefficients de régression : valeurs de *t* et de *p* {#sec-0743}\n\nUne fois les coefficients de régression obtenus, il convient de vérifier s'ils sont ou non significativement différents de 0. Si le coefficient de régression d'une variable indépendante est significativement différent de 0, nous concluons que la variable a un effet significatif sur la variable dépendante, toutes choses étant égales par ailleurs. Pour ce faire, il suffit de calculer la valeur de *t* qui est simplement le coefficient de régression divisé par son erreur type.\n\n$$\nt=\\frac{\\beta_k - 0}{s(\\beta_k)} \n$$ {#eq-ValeurT}\n\navec $s(\\beta_k)$ étant l'erreur type du coefficient de régression. Notez que dans l'@eq-ValeurT, nous indiquons habituellement $-0$, pour signaler que l'on veut vérifier si le coefficient est différent de 0. En guise d'exemple, au @tbl-dataregmodel2, la valeur de *t* de la variable `HABHA` est bien égale à :\n\n$\\mbox{−0,070401 / 0,002202 = −31,975}$.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Démarche pour vérifier si un coefficient est significativement différent de 0**\n:::\n::: bloc_attention-body\n1. Poser l'hypothèse nulle (*H~0~*) stipulant que le coefficient est égal à 0, soit $H_0 : \\beta_k = 0$. L'hypothèse alternative (*H~1~*) est que le coefficient est différent de 0, soit $H_1 : B_k \\neq 0$.\n\n2. Calculer la valeur de *t*, soit le coefficient de régression divisé par son erreur type (@eq-ValeurT).\n\n3. Calculer le nombre de degrés de liberté, soit $dl = n − k - 1$, *n* et *k* étant respectivement les nombres d'observations et de variables indépendantes.\n\n4. Choisir un seuil de signification alpha (5 %, 1 % ou 0,1 %, soit *p* = 0,05, 0,01 ou 0,01).\n\n5. Trouver la valeur critique de *t* dans la table T de Student ([section @sec-143]) avec *p* et le nombre de degrés de liberté (*dl*).\n\n6. Valider ou réfuter l'hypothèse nulle (*H~0~*) :\n\n - si la valeur de *t* est inférieure à la valeur critique de *t* avec *dl* et le seuil choisi, nous confirmons *H~0~* : le coefficient n'est pas significativement différent de 0.\n\n - si la valeur de *t* est supérieure à la valeur critique de *t* avec *dl* et le seuil choisi, nous réfutons l'hypothèse nulle, et choisissons l'hypothèse alternative (*H~1~*) stipulant que le coefficient est significativement différent de 0.\n\n\n**Valeurs critiques de la valeur de *t* à retenir!**\n\nLorsque le nombre de degrés de liberté (*n − k - 1*) est très important (supérieur à 2500), et donc le nombre d'observations de votre jeu de données, nous retenons habituellement les valeurs critiques suivantes : **1,65 (*p* = 0,10), 1,96 (*p* = 0,05)**, **2,58 (*p* = 0,01)** et **3,29 (*p*=0,001)**. Concrètement, cela signifie que :\n\n* une valeur de *t* supérieure à 1,96 ou inférieure à -1,96 nous informe que la relation entre la variable indépendante et la variable dépendante est significative positivement ou négativement au seuil de 5 %. Autrement dit, vous avez moins de 5 % de chances de vous tromper en affirmant que le coefficient de régression est bien significativement différent de 0.\n\n* une valeur de *t* supérieure à 2,58 ou inférieure à -2,58 nous informe que la relation entre la variable indépendante et la variable dépendante est significative positivement ou négativement au seuil de 5 %. Autrement dit, vous avez moins de 1 % de chances de vous tromper en affirmant que le coefficient de régression est bien significativement différent de 0.\n\n* une valeur de *t* supérieure à 3,29 ou inférieure à -3,29 nous informe que la relation entre la variable indépendante et la variable dépendante est significative positivement ou négativement au seuil de 5 %. Autrement dit, vous avez moins de 0,1 % de chances de vous tromper en affirmant que le coefficient de régression est bien significativement différent de 0.\n\nConcrètement, retenez et utilisez les seuils de $\\pm\\mbox{1,96}$, $\\pm\\mbox{2,58}$ et $\\pm\\mbox{3,29}$ pour repérer les variables significatives positivement ou négativement aux seuils respectifs de 0,5, 0,1 et 0,001.\n\n**Que signifient les seuils 0,10, 0,05 et 0,001?**\n\nL'interprétation exacte des seuils de significativité des coefficients d'une régression est quelque peu alambiquée, mais mérite de s'y attarder. En effet, indiquer qu'un coefficient est significatif est souvent perçu comme un argument fort pour une théorie, il est donc nécessaire d'avoir du recul et de bien comprendre ce que l'on entend par **significatif**. \n\nSi un coefficient est significatif au seuil de 5 % dans notre modèle, cela signifie que si, pour l’ensemble d’une population, la valeur du coefficient est de 0 en réalité, alors nous avions moins de 5 % de chances de collecter un échantillon (pour cette population) ayant produit un coefficient aussi fort que celui que nous observons dans notre propre échantillon. Par conséquent, il serait très invraisemblable que le coefficient soit 0 puisque nous avons effectivement collecté un tel échantillon. Il s'agit d'une forme d'argumentation par l'absurde propre à la statistique fréquentiste. \n\nNotez que si 100 études étaient conduites sur le même sujet et dans les mêmes conditions, nous nous attendrions à ce que 5 d'entre elles trouvent un coefficient significatif, du fait de la variation des échantillons. Ce constat souligne le fait que la recherche est un effort collectif et qu'une seule étude n'est pas suffisante pour trancher sur un sujet. Les revues systématiques de la littérature sont donc des travaux particulièrement importants pour la construction du consensus scientifique.\n\n**Ne pas confondre significativité et effet de la variable indépendante**\n\nAttention, un coefficient significatif n’est pas toujours intéressant! Autrement dit, bien qu’il soit significatif à un seuil donné (par exemple, *p* = 0,05), cela ne veut pas dire pour autant qu’il ait un effet important sur la variable dépendante. Il faut donc analyser simultanément les valeurs de *p* et des coefficients de régression.\nAfin de mieux saisir l'effet d'un coefficient significatif, il est intéressant de représenter graphiquement l’effet marginal d’une variable indépendante (VI) sur une variable dépendante (VD), une fois contrôlées les autres VI du modèle de régression ([section @sec-0774]).\n:::\n:::\n\nPrenons deux variables indépendantes du @tbl-dataregmodel2 – `HABHA` et `AgeMedian` – et vérifions si leurs coefficients de régression respectifs (−0,070 et 0,011) sont significatifs. Appliquons la démarche décrite dans l'encadré ci-dessus :\n\n1. Nous posons l'hypothèse nulle stipulant que la valeur de ces deux coefficients est égale à 0, soit $H_0 : \\beta_k = 0$.\n\n2. La valeur de *t* est égale à `−0,070401 / 0,002202 = −31,97139` pour `HABHA` et à `0,010790 / 0,006369 = 1,694144` pour `AgeMedian`.\n\n3. Le nombre de degrés de liberté est égal à $\\mbox{dl} = \\mbox{n}-\\mbox{k}-\\mbox{1} = \\mbox{10 210} − \\mbox{6} - \\mbox{1} = \\mbox{10 203}$.\n\n4. Nous choisissons respectivement les seuils $\\alpha$ de 0,10, 0,05, 0,01 ou 0,001.\n\n5. Avec 10210 degrés de liberté, les valeurs critiques de la table T de Student ([section @sec-133]) sont de 1,65 (*p* = 0,10), 1,96 (*p* = 0,05), 2,58 (*p* = 0,01), 3,29 (*p* = 0,001).\n\n6. Il reste à valider ou réfuter l'hypothèse nulle (*H~0~*) :\n - pour `HABHA`, la valeur absolue de *t* (−31,975) est supérieure à la valeur critique de 3,29. Son coefficient de régression est donc significativement différent de 0. Autrement dit, ce prédicteur a un effet significatif et négatif sur la variable dépendante.\n\n - pour `AgeMedian`, la valeur absolue de *t* (1,694) est supérieure à 1,65 (*p* = 0,10), mais inférieure à 1,96 (*p* = 0,05), à 2,58 (*p* = 0,01), à 3,29 (*p* = 0,001). Par conséquent, ce coefficient est différent de 0 uniquement au seuil de *p* = 0,10 et non au seuil de *p* = 0,05. Cela signifie que bous avons un peu moins de 10 % de chances de se tromper en affirmant que cette variable a un effet significatif sur la variable dépendante.\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Calculer et obtenir des valeurs de *p* dans R**\n:::\n::: bloc_astuce-body\nIl est très rare d'utiliser la table *T* de Student pour obtenir un seuil de significativité. D'une part, il est possible de calculer directement la valeur de *p* à partir de la valeur de *t* et du nombre de degrés de liberté avec la fonction `pt` avec les paramètres suivants :\n\n`pt(q= abs(valeur de T), df= nombre de degrés de liberté, lower.tail = FALSE) *2`\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Degrés de liberté\ndl <- nrow(DataFinal) - (length(Modele1$coefficients) - 1) + 1\n\n# Valeurs de T\nValeurT <- summary(Modele1)$coefficients[,3]\n\n# Calcul des valeurs de P\nValeurP <- pt(q= abs(ValeurT), df= dl, lower.tail = FALSE) *2\n\ndf_tp <- data.frame(\n ValeurT = round(ValeurT,3), \n ValeurP = round(ValeurP,3)\n)\nprint(df_tp)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n ValeurT ValeurP\n(Intercept) 29.874 0.000\nHABHA -31.975 0.000\nAgeMedian 1.694 0.090\nPct_014 33.702 0.000\nPct_65P 21.265 0.000\nPct_MV -2.990 0.003\nPct_FR -29.918 0.000\n```\n:::\n:::\n\n\nD'autre part, la fonction `summary` renvoie d'emblée les valeurs de *t* et de *p*. Par convention, R, comme la plupart des logiciels d'analyses statistiques, utilise aussi des symboles pour indiquer le seuil de signification du coefficient (voir @tbl-CoefStand2) : \n\n '***' _p_ <= 0,001\n \n '**' _p_ <= 0,01 \n \n '*' _p_ <= 0,05 \n \n '.' _p_ <= 0,10\n:::\n:::\n\n\n### Intervalle de confiance des coefficients {#sec-0744}\n\nFinalement, il est possible de calculer l'intervalle de confiance d'un coefficient à partir d'un niveau de signification (habituellement 0,95 ou encore 0,99). Pour ce faire, la fonction `confint(nom du modèle, level=.95)` est très utile. L'intérêt de ces intervalles de confiance pour les coefficients de régression est double :\n\n* Il permet de vérifier si le coefficient est ou non significatif au seuil retenu. Pour cela, la borne inférieure et la borne supérieure du coefficient doivent être toutes deux négatives ou positives. À l'inverse, un intervalle à cheval sur 0, soit avec une borne inférieure négative et une borne supérieure positive, n'est pas significatif.\n\n* Il permet d'estimer la précision de l'estimation; plus l'intervalle du coefficient est réduit, plus l'estimation de l'effet de la variable indépendante est précise. Inversement, un intervalle large signale que le coefficient est incertain.\n\nCela explique que de nombreux auteurs reportent les intervalles de confiance dans les articles scientifiques (habituellement à 95 %). Dans le modèle présenté ici, il est alors possible d'écrire : toutes choses étant égales par ailleurs, le pourcentage d'enfants de moins de 15 ans est positivement et significativement associé avec le pourcentage de la couverture végétale dans l'îlot (B = 1,084; IC 95 % = [1,021 - 1,148], *p* < 0,001).\n\nEn guise d'exemple, à la lecture de la sortie R ci-dessous, l'estimation de l'effet de la variable indépendante `AgeMedian` sur la variable `VegPct` se situe dans l'intervalle -0,002 à 0,023 qui est à cheval sur 0. Contrairement aux autres variables, nous ne pouvons donc pas en conclure que cet effet est significatif avec *p* = 0,05.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Intervalle de confiance à 95 % des coefficients\nround(confint(Modele1, level=.95),3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 2.5 % 97.5 %\n(Intercept) 24.626 28.085\nHABHA -0.075 -0.066\nAgeMedian -0.002 0.023\nPct_014 1.021 1.148\nPct_65P 0.364 0.437\nPct_MV -0.052 -0.011\nPct_FR -0.371 -0.325\n```\n:::\n:::\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Comment est calculé un intervalle de confiance?**\n:::\n::: bloc_astuce-body\nL'intervalle du coefficient est obtenu à partir de : \n\n1. la valeur du coefficient ($\\beta_k$),\n\n2. la valeur de son erreur type $s(\\beta_k)$ et \n\n3. la valeur critique de T ($t_{\\alpha/2}$) obtenue avec $n-k-1$ degrés de liberté et le niveau de significativité retenu (95 %, 99 % ou 99,9 %).\n\n\n$$\nIC_{\\beta_k}= \\left[ \\beta_k - t_{\\alpha/2} \\times s(\\beta_k) ; \\beta_k + t_{\\alpha/2} \\times s(\\beta_k) \\right]\n$$ {#eq-ICcoef}\n\nAutrement dit, lorsque vous disposez d'un nombre très important d'observations, les intervalles de confiance s'écrivent simplement avec les fameuses valeurs critiques de T de 1,96, 2,58, 3,29 :\n\n$$\n\\mbox{Intervalle à 95 \\%\\: } IC_{\\beta_k}= \\left[ \\beta_k - 1,96 \\times s(\\beta_k) ; \\beta_k + 1,96 \\times s(\\beta_k) \\right]\n$$ {#eq-IC95}\n\n\n$$\n\\mbox{Intervalle à 99 \\%\\: } IC_{\\beta_k}= \\left[ \\beta_k - 2,58 \\times s(\\beta_k) ; \\beta_k + 2,58 \\times s(\\beta_k) \\right]\n$$ {#eq-IC99}\n\n$$\n\\mbox{Intervalle à 99,9 \\%\\: } IC_{\\beta_k}= \\left[ \\beta_k - 3,29 \\times s(\\beta_k) ; \\beta_k + 3,29 \\times s(\\beta_k) \\right]\n$$ {#eq-IC999}\n\nLa syntaxe R ci-dessous illustre comment calculer les intervalles de confiance à 95 % à partir de l'@eq-ICcoef. Rappelez-vous toutefois qu'il est bien plus simple d'utiliser la fonction `confint`:\n\n* `round(confint(Modele1, level=.95),3) `\n* `round(confint(Modele1, level=.99),3)`\n* `round(confint(Modele1, level=.999),3)`\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Coeffients de régression\ncoefs <- Modele1$coefficients\n\n# Erreur type des coef.\ncoefs_se <- summary(Modele1)$coefficients[,2]\n\n# Nombre de degrés de liberté\nn <- length(Modele1$fitted.values)\nk <- length(Modele1$coefficients)-1\ndl <- n-k-1\n\n# valeurs critiques de T\nt95 <- qt(p=1 - (0.05/2), df=dl)\nt99 <- qt(p=1 - (0.01/2), df=dl)\nt99.9 <- qt(p=1 - (0.001/2), df=dl)\ncat(\"Valeurs critiques de T en fonction du niveau de confiance\",\n \"\\n et du nombre de degrés de liberté\",\n \"\\n95 % : \", t95,\n \"\\n99 % : \", t99,\n \"\\n99,9 % : \", t99.9\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nValeurs critiques de T en fonction du niveau de confiance \n et du nombre de degrés de liberté \n95 % : 1.960197 \n99 % : 2.576311 \n99,9 % : 3.291481\n```\n:::\n\n```{.r .cell-code}\n# Intervalle de confiance à 95\ndata.frame(\n IC2.5 = round(coefs-t95*coefs_se,3),\n IC97.5 = round(coefs+t95*coefs_se,3)\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n IC2.5 IC97.5\n(Intercept) 24.626 28.085\nHABHA -0.075 -0.066\nAgeMedian -0.002 0.023\nPct_014 1.021 1.148\nPct_65P 0.364 0.437\nPct_MV -0.052 -0.011\nPct_FR -0.371 -0.325\n```\n:::\n\n```{.r .cell-code}\n# Intervalle de confiance à 99\ndata.frame(\n IC0.5 = round(coefs-t99*coefs_se,3),\n IC99.5 = round(coefs+t99*coefs_se,3)\n)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n IC0.5 IC99.5\n(Intercept) 24.083 28.629\nHABHA -0.076 -0.065\nAgeMedian -0.006 0.027\nPct_014 1.002 1.167\nPct_65P 0.352 0.449\nPct_MV -0.058 -0.004\nPct_FR -0.378 -0.318\n```\n:::\n\n```{.r .cell-code}\n# Intervalle de confiance à 99.9\ndata.frame(\n IC0.05 = round(coefs-t99.9*coefs_se,3),\n IC99.95 = round(coefs+t99.9*coefs_se,3)\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n IC0.05 IC99.95\n(Intercept) 23.452 29.260\nHABHA -0.078 -0.063\nAgeMedian -0.010 0.032\nPct_014 0.979 1.190\nPct_65P 0.339 0.463\nPct_MV -0.065 0.003\nPct_FR -0.387 -0.310\n```\n:::\n:::\n\n:::\n:::\n\n## Introduction de variables explicatives particulières {#sec-075}\n\n### Exploration des relations non linéaires {#sec-0751}\n\n#### Variable indépendante avec une fonction polynomiale {#sec-07511}\n\nDans la [section @sec-041], nous avons vu que la relation entre deux variables continues n'est pas toujours linéaire; elle peut être aussi curvilinéaire. Pour explorer les relations curvilinéaires, nous introduisons la variable indépendante sous la forme polynomiale d'ordre 2 (voir le prochain encadré). L'équation de régression s'écrit alors :\n\n$$\nY = b_{0} + b_{1}X_{1} + b_{11}X_{1}^2 + b_{2}X_{2} +\\ldots+ b_{k}X_{k} + e\n$$ {#eq-regpolyordre2}\n\nDans l'@eq-regpolyordre2, la première variable indépendante est introduite dans le modèle de régression à la fois dans sa forme originelle et mise au carré : $b_{1}X_{1} + b_{11}X_{1}^2$. Un coefficient différent est ajusté pour chacune de ces deux versions de la variable $X_{1}$.\n\nLa démographie est probablement la discipline des sciences sociales qui a le plus recours aux régressions polynomiales. En effet, la variable `âge` est souvent introduite comme variable explicative dans sa forme originale et mise au carré. L'objectif est de vérifier si l'âge partage ou non une relation curvilinéaire avec un phénomène donné : par exemple, il pourrait y être associé positivement jusqu'à un certain seuil (45 ans par exemple), puis négativement à partir de ce seuil.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Régression polynomiale et nombre d'ordres**\n:::\n::: bloc_aller_loin-body\nSachez qu'il est aussi possible de construire des régressions polynomiales avec plus de deux ordres. Par exemple, une régression polynomiale d'ordre 3 comprend une variable dans sa forme originelle, puis mise au carré et au cube. Cela a l'inconvénient d'augmenter corollairement le nombre de coefficients. Nous verrons au [chapitre @sec-chap11] qu'il existe une solution plus élégante et efficace : le recours aux modèles de régressions linéaires généralisés additifs avec des *splines*. Dans le cadre de cette section, nous nous limitons à des régressions polynomiales d'ordre 2.\n\n$$\n\\mbox{Ordre 2 : } Y = b_{0} + b_{1}X_{1} + b_{11}X_{}^2 + b_{2}X_{2} +\\ldots+ b_{k}X_{k} + e\n$$ {#eq-regpolyordre2b}\n\n$$\n\\mbox{Ordre 3 : } Y = b_{0} + b_{1}X_{1} + b_{11}X_{}^2 + b_{111}X_{}^3 + b_{2}X_{2} +\\ldots+ b_{k}X_{k} + e\n$$ {#eq-regpolyordre3}\n\n$$\n\\mbox{Ordre 4 : } Y = b_{0} + b_{1}X_{1} + b_{11}X_{}^2 + b_{111}X_{}^3 + b_{1111}X_{}^4 + b_{2}X_{2} +\\ldots+ b_{k}X_{k} + e\n$$ {#eq-regpolyordre4}\n\n:::\n:::\n\nPour construire une régression polynomiale dans R, il est possible d'utiliser deux fonctions de R :\n\n* `I(VI^2)` avec `VI` qui est la variable indépendante sur laquelle est appliquée la mise au carré.\n* `poly(VI,2)` qui utilise une forme polynomiale orthogonale pour éviter les problèmes de corrélation entre les deux termes, c'est-à-dire entre **VI** et **VI^2^**.\n\nCes deux méthodes produisent les mêmes résultats pour les autres variables dépendantes et pour la qualité d'ajustement du modèle (R^2^, F, etc.). Nous privilégions la seconde fonction pour éviter de détecter à tort des problèmes de multicolinéarité excessive.\n\nAppliquons cette démarche à la variable `AgeMedian` (âge médian des bâtiments) afin de vérifier si elle partage ou non une relation curvilinéaire avec la couverture végétale de l'îlot. À la lecture des résultats pour les deux modèles, les constats suivants peuvent être avancés :\n\n* Le R^2^ ajusté passe de 0,4179 à 0,4378 du modèle 1 au modèle 2, ce qui signale un gain de variance expliquée.\n\n* Le *F* incrémentiel entre les deux modèles s'élève à 362,64 et est significatif (*p* < 0,001). Nous pouvons donc en conclure que le second modèle est plus performant que le premier, ce qui signale que la forme curvilinéaire pour `AgeMedian` (modèle 2) est plus efficace que la forme linéaire (modèle 1).\n\n* Dans le premier modèle, le coefficient de régression pour `AgeMedian` n'est pas significatif. L'âge médian des bâtiments n'est donc pas associé linéairement avec la variable dépendante.\n\n* Dans le second modèle, la valeur du coefficient de `poly(AgeMedian, 2)1` est positive et celle de `poly(AgeMedian, 2)2` est négative et significative. Cela indique qu'il existe une relation linéaire en forme de U inversé. Si le premier coefficient avait été négatif et le second positif, nous aurions alors conclu que la forme curvilinéaire prend la forme d'un U.\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# régression linéaire\nmodele1 <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n# régression polynomiale\nmodele2 <- lm(VegPct ~ HABHA+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n# affichage des résultats du modèle 1\nsummary(modele1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCall:\nlm(formula = VegPct ~ HABHA + AgeMedian + Pct_014 + Pct_65P + \n Pct_MV + Pct_FR, data = DataFinal)\n\nResiduals:\n Min 1Q Median 3Q Max \n-48.876 -9.757 -0.232 9.499 103.830 \n\nCoefficients:\n Estimate Std. Error t value Pr(>|t|) \n(Intercept) 26.355774 0.882235 29.874 <2e-16 ***\nHABHA -0.070401 0.002202 -31.975 <2e-16 ***\nAgeMedian 0.010790 0.006369 1.694 0.0902 . \nPct_014 1.084478 0.032179 33.702 <2e-16 ***\nPct_65P 0.400531 0.018835 21.265 <2e-16 ***\nPct_MV -0.031112 0.010406 -2.990 0.0028 ** \nPct_FR -0.348256 0.011640 -29.918 <2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\nResidual standard error: 14.16 on 10203 degrees of freedom\nMultiple R-squared: 0.4182,\tAdjusted R-squared: 0.4179 \nF-statistic: 1223 on 6 and 10203 DF, p-value: < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\n# affichage des résultats du modèle 1\nsummary(modele2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCall:\nlm(formula = VegPct ~ HABHA + poly(AgeMedian, 2) + Pct_014 + \n Pct_65P + Pct_MV + Pct_FR, data = DataFinal)\n\nResiduals:\n Min 1Q Median 3Q Max \n-49.659 -9.361 -0.159 9.034 105.160 \n\nCoefficients:\n Estimate Std. Error t value Pr(>|t|) \n(Intercept) 2.968e+01 7.535e-01 39.383 < 2e-16 ***\nHABHA -7.107e-02 2.164e-03 -32.839 < 2e-16 ***\npoly(AgeMedian, 2)1 1.134e+01 1.598e+01 0.710 0.47788 \npoly(AgeMedian, 2)2 -2.721e+02 1.429e+01 -19.043 < 2e-16 ***\nPct_014 9.969e-01 3.196e-02 31.198 < 2e-16 ***\nPct_65P 3.219e-01 1.896e-02 16.972 < 2e-16 ***\nPct_MV -2.888e-02 1.023e-02 -2.823 0.00476 ** \nPct_FR -3.562e-01 1.145e-02 -31.116 < 2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\nResidual standard error: 13.92 on 10202 degrees of freedom\nMultiple R-squared: 0.4382,\tAdjusted R-squared: 0.4378 \nF-statistic: 1137 on 7 and 10202 DF, p-value: < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\n# test de Fisher pour comparer les modèles\nanova(modele1, modele2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nAnalysis of Variance Table\n\nModel 1: VegPct ~ HABHA + AgeMedian + Pct_014 + Pct_65P + Pct_MV + Pct_FR\nModel 2: VegPct ~ HABHA + poly(AgeMedian, 2) + Pct_014 + Pct_65P + Pct_MV + \n Pct_FR\n Res.Df RSS Df Sum of Sq F Pr(>F) \n1 10203 2046427 \n2 10202 1976182 1 70245 362.64 < 2.2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n```\n:::\n:::\n\n\n**Construction d'un graphique des effets marginaux**\n\nPour visualiser la relation linéaire et curvilinéaire, nous vous proposons de réaliser un graphique des effets marginaux à partir de la syntaxe ci-dessous.\n\nLes graphiques des effets marginaux permettent de visualiser l'impact d'une variable indépendante sur la variable dépendante d'une régression. Nous nous basons pour cela sur les prédictions effectuées par le modèle. Admettons que nous nous intéressons à l'effet de la variable *X~1~* sur la variable *Y*. Il est possible de créer de nouvelles données fictives pour lesquelles l'ensemble des autres variables *X* sont fixées à leur moyenne respective, et seule *X~1~* est autorisée à varier. En utilisant l'équation de régression du modèle sur ces données fictives, nous pouvons observer l'évolution de la valeur prédite de *Y* quand *X~1~* augmente ou diminue, et ce, toutes choses étant égales par ailleurs (puisque toutes les autres variables ont une valeur fixe). Cette approche est particulièrement intéressante pour décrire des effets non linéaires obtenus avec des polynomiales, mais aussi des interactions comme nous le verrons plus tard. Elle est également utilisée dans les modèles linéaires généralisés (GLM) et additifs (GAM) (chapitres [-@sec-chap08] et [-@sec-chap11]). Notez qu'il est aussi important de représenter, sur ce type de graphique, l'incertitude de la prédiction. Pour cela, il est possible de construire des intervalles de confiance à 95 % autour de la prédiction en utilisant l'erreur standard de la prédiction (renvoyée par la fonction `predict`).\n\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggplot2)\n# Statistique sur la variable AgeMedian qui varie de 0 à 226 ans\nsummary(DataFinal$AgeMedian)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Min. 1st Qu. Median Mean 3rd Qu. Max. \n 0.00 37.25 49.00 52.11 61.00 226.00 \n```\n:::\n\n```{.r .cell-code}\n# Création d'un DataFrame temporaire\n# remarquez que les autres variables indépendantes sont constantes :\n# nous leur avons attribué leur moyenne correspondante\ndf <- data.frame(\n HABHA = mean(DataFinal$HABHA),\n AgeMedian= seq(0,200, by = 2),\n AgeMedian2 = seq(0,200, by = 2)**2,\n Pct_014= mean(DataFinal$Pct_014),\n Pct_65P= mean(DataFinal$Pct_65P),\n Pct_MV= mean(DataFinal$Pct_MV),\n Pct_FR= mean(DataFinal$Pct_FR)\n)\n\n# Calcul de la valeur de t pour un intervalle à 95 %\nn <- length(modele1$fitted.values) \nk <- length(modele1$coefficients)-1\nt95 <- qt(p=1 - (0.05/2), df=n-k-1)\n\n# Calcul des valeurs prédites pour le 1er modèle\n# avec l'intervalle de confiance à 95 %\npredsM1 <- predict(modele1, se = TRUE, newdata = df)\ndf$predM1 <- predsM1$fit\ndf$lowerM1 <- predsM1$fit - t95*predsM1$se.fit\ndf$upperM1 <- predsM1$fit + t95*predsM1$se.fit\n\n# Calcul des valeurs prédites pour le 2e modèle\n# avec l'intervalle de confiance à 95 %\npredsM2 <- predict(modele2, se = TRUE, newdata = df)\ndf$predM2 <- predsM2$fit\ndf$lowerM2 <- predsM2$fit - t95*predsM2$se.fit\ndf$upperM2 <- predsM2$fit + t95*predsM2$se.fit\n\n# Graphique\nggplot(data = df) + \n geom_ribbon(aes(x = AgeMedian, ymin = lowerM1, ymax = upperM1), \n fill = rgb(0.1,0.1,0.1,0.4)) + \n geom_path(aes(x = AgeMedian, y = predM1), color = \"blue\", size = 1)+\n \n geom_ribbon(aes(x = AgeMedian, ymin = lowerM2, ymax = upperM2), \n fill = rgb(0.1,0.1,0.1,0.4)) + \n geom_path(aes(x = AgeMedian, y = predM2), color = \"red\", size = 1)+\n \n labs(title = \"Effet marginal de l'âge médian des bâtiments sur la\",\n subtitle = \"couverture végétale des îlots de l'île de Montréal\",\n caption = \"bleu : relation linéaire; rouge : curvilinéaire\",\n x = \"Âge médian des bâtiments\",\n y = \"Couverture végétale (%)\")\n```\n\n::: {.cell-output-display}\n![Relations linéaire et curvilinéaire](07-regressionlineaire_files/figure-html/fig-calculRegPoly2-1.png){#fig-calculRegPoly2 fig-align='center' width=75%}\n:::\n:::\n\n\nLa @fig-calculRegPoly2 démontre bien que la relation linéaire n'est pas significative : la pente est extrêmement faible, ce qui signale que l'effet de l'âge médian est presque nul (B = 0,0108, *p* = 0,0902). En revanche, la relation curvilinéaire est plus intéressante : la couverture végétale croît quand l'âge médian des bâtiments dans l'îlot augmente de 0 à 60 ans environ, puis elle décroît.\n\n#### Variable indépendante sous forme logarithmique {#sec-07512}\n\nUne autre manière d'explorer une relation non linéaire est d'intégrer la variable sous forme logarithmique [@hanck2019introduction, p.212-218]. L'interprétation du coefficient de régression est alors plus complexe : 1 % d'augmentation de la variable $X_k$ entraîne un changement de $\\mbox{0,01} \\times \\beta_k$ de la variable dépendante. Autrement dit, il n'est plus exprimé dans les unités de mesure originales des deux variables.\n\nAu @tbl-regmodeleLog, le coefficient de `-6,855` pour la variable `logHABHA` s'interprète alors comme suit : un changement de 1 % de la variable densité de population entraîne une diminution de $\\mbox{0,01} \\times -\\mbox{6,855 =} -\\mbox{0,07}$ de la couverture végétale dans l'île, toutes choses étant égales par ailleurs.\n\n\n::: {#tbl-regmodeleLog .cell tbl-cap='Modèle avec une variable indépendante sous forme logarithmique'}\n::: {.cell-output-display}\n|Variable | Coef.| Erreur type| Valeur de T| P| coef. 2,5 %| coef. 97,5 %| |\n|:-----------------|--------:|-----------:|-----------:|-----:|-----------:|------------:|---:|\n|Constante | 52,831| 1,001| 52,780| 0,000| 50,868| 54,793| ***|\n|logHABHA | -6,855| 0,168| -40,730| 0,000| -7,185| -6,525| ***|\n|AgeMedian ordre 1 | 11,985| 15,586| 0,770| 0,442| -18,568| 42,537| |\n|AgeMedian ordre 2 | -286,144| 13,942| -20,520| 0,000| -313,473| -258,816| ***|\n|Pct_014 | 0,941| 0,031| 30,090| 0,000| 0,879| 1,002| ***|\n|Pct_65P | 0,306| 0,019| 16,550| 0,000| 0,270| 0,343| ***|\n|Pct_MV | -0,036| 0,010| -3,650| 0,000| -0,056| -0,017| ***|\n|Pct_FR | -0,344| 0,011| -31,210| 0,000| -0,366| -0,323| ***|\n:::\n:::\n\n\nPuisque l'interprétation du coefficient de régression de $log(\\beta_k)$ est plus complexe, il convient de s'assurer que son apport au modèle est justifié, et ce, de deux façons :\n\n* **Comparez les mesures d'ajustement des deux modèles (surtout les R^2^ ajustés)**. Si le R^2^ ajusté du modèle avec $log(\\beta_k)$ est plus élevé que celui avec $\\beta_k$, alors la transformation logarithmique fait de votre variable indépendante un meilleur prédicteur, toutes choses étant égales par ailleurs. \n\n* **Construisez les graphiques des effets marginaux** de votre variable afin de vérifier si la relation qu'elle partage avec votre VD est plutôt logarithmique que linéaire (@fig-EffetMarginalVariableLogEtNon). Notez que cette approche graphique peut aussi ne donner aucune indication lorsque vos données sont très dispersées ou que la relation est faible entre votre variable dépendante et indépendante.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggpubr)\nlibrary(ggplot2)\nlibrary(ggeffects)\n\n# Modèles\nmodele1a <- lm(VegPct ~ HABHA+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\nmodele1b <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n\n# Valeurs prédites\nfit1a <- ggpredict(modele1a, terms = \"HABHA\")\nfit1b <- ggpredict(modele1b, terms = \"HABHA\")\n# Graphiques\nG1a <- ggplot(fit1a, aes(x, predicted)) +\n geom_point(data = DataFinal, mapping = aes(x = HABHA, y = VegPct),\n size = 0.2, color = rgb(0.1,0.1,0.1,0.4)) + \n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3, fill = \"red\")+\n geom_line(color = \"red\") +\n labs(title = \"Variable non transformée\",\n y = \"VD: valeur prédite\",\n x = \"Habitants km2\") + \n ylim(0,100) + xlim(0,600)\n\nG1b <- ggplot(fit1b, aes(x, predicted)) +\n geom_point(data = DataFinal, mapping = aes(x = HABHA, y = VegPct),\n size = 0.2, color = rgb(0.1,0.1,0.1,0.4)) + \n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3, fill = \"red\")+\n geom_line(color = \"red\") +\n labs(title = \"Variable transformée (log)\",\n y = \"VD: valeur prédite\",\n x = \"Habitants km2\")\n\nG1aG1b <- ggarrange(G1a, G1b, nrow = 1)\nG1aG1b\n```\n\n::: {.cell-output-display}\n![Effet marginal de la densité de population](07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLogEtNon-1.png){#fig-EffetMarginalVariableLogEtNon fig-align='center' width=75%}\n:::\n:::\n\n\n### Variable indépendante qualitative dichotomique {#sec-0752}\n\nIl est très fréquent d'introduire une variable qualitative dichotomique comme variable explicative ou de contrôle dans un modèle. À titre de rappel, une variable dichotomique comprend deux modalités ([section @sec-0212]). \n\nDans le modèle ci-dessous, nous voulons vérifier si un îlot situé sur le territoire de la ville de Montréal a proportionnellement moins de végétation qu'un îlot situé dans une autre municipalité de l'île de Montréal, toutes choses étant égales par ailleurs. Pour ce faire, nous créons une variable binaire dénommée `VilleMtl` qui prend la valeur de 1 pour les îlots de la ville de Montréal et 0 pour ceux d'une autre municipalité.\n\nNous obtenons ainsi un coefficient de régression pour `VilleMtl` de -7,699 (@tbl-regmodeleDich2). Cela signifie que si toutes les autres variables indépendantes du modèle étaient constantes, alors un îlot de la ville de Montréal aurait en moyenne une valeur de -7,7 % de moins de végétation comparativement à un îlot situé dans une autre municipalité.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Création d'une variable muette pour Montréal (0 ou 1)\nDataFinal$VilleMtl <- ifelse(DataFinal$SDRNOM == \"Montréal\", 1, 0)\n# Modèle avec la variable dichtonomique\nmodele3 <- lm(VegPct ~ VilleMtl+log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n```\n:::\n\n::: {#tbl-regmodeleDich2 .cell tbl-cap='Modèle avec une variable dichotomique'}\n::: {.cell-output-display}\n|Variable | Coef.| Erreur type| Valeur de T| P| coef. 2,5 %| coef. 97,5 %| |\n|:-----------------|--------:|-----------:|-----------:|-----:|-----------:|------------:|---:|\n|Constante | 57,676| 1,009| 57,140| 0,000| 55,697| 59,654| ***|\n|VilleMtl | -7,699| 0,377| -20,430| 0,000| -8,438| -6,960| ***|\n|log(HABHA) | -6,174| 0,168| -36,680| 0,000| -6,504| -5,844| ***|\n|AgeMedian ordre 1 | -14,871| 15,334| -0,970| 0,332| -44,929| 15,186| |\n|AgeMedian ordre 2 | -280,251| 13,668| -20,500| 0,000| -307,044| -253,459| ***|\n|Pct_014 | 0,794| 0,031| 25,230| 0,000| 0,732| 0,856| ***|\n|Pct_65P | 0,270| 0,018| 14,810| 0,000| 0,234| 0,306| ***|\n|Pct_MV | -0,028| 0,010| -2,890| 0,004| -0,047| -0,009| **|\n|Pct_FR | -0,294| 0,011| -26,550| 0,000| -0,316| -0,273| ***|\n:::\n:::\n\n\n \n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Bien interpréter un coefficient d'une variable dichotomique**\n:::\n::: bloc_astuce-body\nNous avons vu que le coefficient de régression ($\\beta_k$) indique le changement de la variable dépendante (*Y*), lorsque la variable indépendante augmente d’une unité, toutes choses étant égales par ailleurs.\n\nPour une variable dichotomique, le coefficient indique le changement de *Y* quand les observations appartiennent à la modalité qui a la valeur de 1 (ici la ville de Montréal), comparativement à celle qui a la valeur de 0 (autres municipalités de l'île de Montréal), toutes choses étant égales par ailleurs.\n\nLa modalité qui a la valeur de 0 est alors appelée **modalité ou catégorie de référence**.\n\nAutrement dit, si la variable avait été codée : 0 pour la ville de Montréal et 1 pour les autres municipalités, alors le coefficient aurait été de 7,699.\n\nPour éviter d'oublier quelle est la modalité de référence (valeur de 0), nous verrons plus tard (dans la section mise en œuvre des modèles de régression dans R ([section @sec-077]) qu'il peut être préférable de définir un facteur avec la fonction `as.factor` et d'indiquer la catégorie de référence avec la fonction `relevel(x, ref)`.\n:::\n:::\n\nComme pour une variable indépendante introduite avec une fonction polynomiale, il peut être très intéressant d'illustrer l'effet marginal de la variable dichotomique avec un graphique qui montre l'écart entre les moyennes des deux modalités, une fois contrôlées les autres variables indépendantes (@fig-EffetMarginalDich). Notez que dans ce graphique, les barres d'erreurs situées au sommet des rectangles représentent les intervalles à 95 % des prédictions du modèle.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Effet marginal d'une variable dichotomique](07-regressionlineaire_files/figure-html/fig-EffetMarginalDich-1.png){#fig-EffetMarginalDich fig-align='center' width=70%}\n:::\n:::\n\n \n### Variable indépendante qualitative polytomique {#sec-0753}\n\nIl est possible d'introduire une variable qualitative polytomique comme variable explicative ou de contrôle dans un modèle. À titre de rappel, une variable polytomique comprend plus de deux modalités, qu'elle soit nominale ou ordinale ([section @sec-0212]). \n\nEn guise d'exemple, une variable qualitative pourrait être : différents groupes de population (groupes d'âge, minorités visibles, catégories socioprofessionnelles, etc.), différents territoires ou régions (ville centrale, première couronne, deuxième couronne, etc.), une variable continue transformée en quatre ou cinq catégories ordinales selon les quartiles ou les quintiles.\n\n#### Comment construire un modèle de régression avec une variable explicative qualitative polytomique? {#sec-07531}\n\nPrenons l'exemple d'un modèle de régression comprenant deux variables indépendantes : l'une continue (`X1`), l'autre qualitative (`X2`) avec quatre modalités (A, B, C et D). L'introduction de la variable qualitative dans le modèle revient à :\n\n* Transformer chaque modalité en variable muette (binaire). Nous avons ainsi quatre nouvelles variables binaires : `X2A`, `X2B`, `X2C` et `X2D`. Par exemple, pour `X2A`, les observations de la modalité *A* se verront affecter la valeur de 1 versus 0 pour les autres observations. La même démarche s'applique à `X2B`, `X2C` et `X2D` (voir @tbl-transfVarQMuettes).\n\n* Toutes les modalités transformées en variables muettes sont introduites dans le modèle comme variables indépendantes **sauf celle servant de catégorie de référence**. Pourquoi sauf une? Si nous mettions toutes les modalités en variable muette, alors chaque observation serait repérée par une valeur de 1, « il y aurait alors une parfaite multicolinéarité et aucune solution unique pour les coefficients de régression ne pourrait être trouvée » [@bressoux2010, p.128]. \n\n* Par exemple, si nous choisissons la modalité *A* comme catégorie de référence, l'équation de régression s'écrit alors :\n\n\n$$\nY = b_{0} + b_{1}X_{1} + b_{2B}X_{2B} + b_{2C}X_{2C} + b_{2D}X_{2D}+ e\n$$ {#eq-regvarpoly1}\n\n* Vous aurez compris que choisir la modalité *D* comme catégorie de référence revient à écrire l'équation suivante :\n\n$$\nY = b_{0} + b_{1}X_{1} + b_{2A}X_{2A} + b_{2B}X_{2B} + b_{2C}X_{2C} + e\n$$ {#eq-regvarpoly2}\n\n\n\n::: {#tbl-transfVarQMuettes .cell tbl-cap='Transformation d\\'une variable qualitative en variables muettes pour chaque modalité'}\n::: {.cell-output-display}\n| obs| Y| X1| X2 | X2A | X2B | X2C | X2D |\n|---:|-----:|-----:|:--:|:---:|:---:|:---:|:---:|\n| 1| 44,27| 18,71| A | 1 | 0 | 0 | 0 |\n| 2| 38,12| 22,08| A | 1 | 0 | 0 | 0 |\n| 3| 60,94| 18,88| A | 1 | 0 | 0 | 0 |\n| 4| 46,03| 19,77| B | 0 | 1 | 0 | 0 |\n| 5| 45,61| 16,16| B | 0 | 1 | 0 | 0 |\n| 6| 51,43| 22,61| B | 0 | 1 | 0 | 0 |\n| 7| 35,56| 16,06| C | 0 | 0 | 1 | 0 |\n| 8| 38,75| 23,77| C | 0 | 0 | 1 | 0 |\n| 9| 45,91| 11,70| D | 0 | 0 | 0 | 1 |\n| 10| 65,31| 23,83| D | 0 | 0 | 0 | 1 |\n:::\n:::\n\n\n\n#### Comment interpréter les coefficients des modalités d'une variable explicative qualitative polytomique {#sec-07532}\n\nLes coefficients des différentes modalités s'interprètent en fonction de la catégorie de référence. Dans l'exemple ci-dessous, nous avons inclus la ville de Montréal comme catégorie de référence (@tbl-ModeleVarPoly1). Toutes choses étant égales par ailleurs, nous pouvons alors constater que  :\n\n* en moyenne, les îlots résidentiels de Senneville et de Baie-D’Urfé ont respectivement 23,235 % et 21,400 % plus de végétation que ceux de la ville de Montréal.\n\n* la seule municipalité comprenant en moyenne moins de végétation dans ses îlots résidentiels est Montréal-Est (-13,334 %).\n\n* nous remarquons aussi que les îlots des municipalités de Sainte-Anne-de-Bellevue, de Montréal-Ouest et de Côte-Saint-Luc ne présentent pas significativement moins ou plus de végétation que ceux de la ville de Montréal (leurs valeurs de *p* sont supérieures à 0,05).\n\nPar conséquent, les valeurs de *t* et de *p* pour une modalité permettent de vérifier si elle est ou non significativement différente de la catégorie de référence.\n\n\n::: {#tbl-ModeleVarPoly1 .cell tbl-cap='Modèle avec une variable polytomique (ville de Montréal en catégorie de référence)'}\n::: {.cell-output-display}\n|Variable | Coef.| Erreur type| Valeur de T| P| |\n|:-----------------------|--------:|-----------:|-----------:|-----:|---:|\n|Constante | 48,193| 0,992| 48,580| 0,000| ***|\n|log(HABHA) | -5,836| 0,168| -34,840| 0,000| ***|\n|AgeMedian ordre 1 | -11,807| 15,648| -0,750| 0,451| |\n|AgeMedian ordre 2 | -266,469| 13,613| -19,570| 0,000| ***|\n|Pct_014 | 0,794| 0,032| 25,190| 0,000| ***|\n|Pct_65P | 0,277| 0,018| 15,130| 0,000| ***|\n|Pct_MV | -0,036| 0,010| -3,740| 0,000| ***|\n|Pct_FR | -0,279| 0,011| -25,340| 0,000| ***|\n|*Municipalité* | | | | | |\n|ref : Montréal | --| --| --| --| --|\n|Baie-D'Urfé | 21,400| 1,635| 13,090| 0,000| ***|\n|Beaconsfield | 14,112| 0,893| 15,810| 0,000| ***|\n|Côte-Saint-Luc | 0,172| 1,035| 0,170| 0,868| |\n|Dollard-Des Ormeaux | 7,960| 0,748| 10,640| 0,000| ***|\n|Dorval | 11,157| 0,971| 11,490| 0,000| ***|\n|Hampstead | 3,080| 1,599| 1,930| 0,054| .|\n|Kirkland | 6,937| 1,014| 6,840| 0,000| ***|\n|Mont-Royal | 12,699| 0,894| 14,210| 0,000| ***|\n|Montréal-Est | -13,334| 1,920| -6,940| 0,000| ***|\n|Montréal-Ouest | 3,306| 1,819| 1,820| 0,069| .|\n|Pointe-Claire | 9,896| 0,866| 11,430| 0,000| ***|\n|Sainte-Anne-de-Bellevue | 0,342| 1,904| 0,180| 0,858| |\n|Senneville | 23,235| 3,793| 6,130| 0,000| ***|\n|Westmount | 2,255| 1,088| 2,070| 0,038| *|\n:::\n:::\n\n\nUtilisons maintenant comme référence la municipalité qui avait le coefficient le plus fort dans le modèle précédent, soit Senneville (@tbl-ModeleVarPoly2). Bien entendu, les coefficients des variables continues et de la constante ne changent pas. Par contre, les coefficients de toutes les municipalités sont négatifs puisque la municipalité de Senneville est celle qui a proportionnellement le plus de végétation dans ses îlots, toutes choses étant égales par ailleurs.\n\n\n::: {#tbl-ModeleVarPoly2 .cell tbl-cap='Modèle avec une variable polytomique (Senneville en catégorie de référence'}\n::: {.cell-output-display}\n|Variable | Coef.| Erreur type| Valeur de T| P| |\n|:-----------------------|--------:|-----------:|-----------:|-----:|---:|\n|Constante | 71,429| 3,846| 18,570| 0,000| ***|\n|log(HABHA) | -5,836| 0,168| -34,840| 0,000| ***|\n|AgeMedian ordre 1 | -11,807| 15,648| -0,750| 0,451| |\n|AgeMedian ordre 2 | -266,469| 13,613| -19,570| 0,000| ***|\n|Pct_014 | 0,794| 0,032| 25,190| 0,000| ***|\n|Pct_65P | 0,277| 0,018| 15,130| 0,000| ***|\n|Pct_MV | -0,036| 0,010| -3,740| 0,000| ***|\n|Pct_FR | -0,279| 0,011| -25,340| 0,000| ***|\n|*Municipalité* | | | | | |\n|ref : Senneville | --| --| --| --| --|\n|Baie-D'Urfé | -1,835| 4,093| -0,450| 0,654| |\n|Beaconsfield | -9,123| 3,866| -2,360| 0,018| *|\n|Côte-Saint-Luc | -23,064| 3,918| -5,890| 0,000| ***|\n|Dollard-Des Ormeaux | -15,275| 3,852| -3,970| 0,000| ***|\n|Dorval | -12,078| 3,891| -3,100| 0,002| **|\n|Hampstead | -20,156| 4,094| -4,920| 0,000| ***|\n|Kirkland | -16,298| 3,911| -4,170| 0,000| ***|\n|Mont-Royal | -10,537| 3,875| -2,720| 0,007| **|\n|Montréal | -23,235| 3,793| -6,130| 0,000| ***|\n|Montréal-Est | -36,570| 4,231| -8,640| 0,000| ***|\n|Montréal-Ouest | -19,930| 4,187| -4,760| 0,000| ***|\n|Pointe-Claire | -13,339| 3,865| -3,450| 0,001| ***|\n|Sainte-Anne-de-Bellevue | -22,893| 4,225| -5,420| 0,000| ***|\n|Westmount | -20,980| 3,927| -5,340| 0,000| ***|\n:::\n:::\n\n\nÀ l'inverse, si nous utilisons Montréal-Est comme modalité de référence, soit la municipalité avec le coefficient le plus faible dans le premier modèle, tous les coefficients deviendront positifs (@tbl-ModeleVarPoly3).\n\n\n\n::: {#tbl-ModeleVarPoly3 .cell tbl-cap='Modèle avec une variable polytomique (Montréal-Est en catégorie de référence)'}\n::: {.cell-output-display}\n|Variable | Coef.| Erreur type| Valeur de T| P| |\n|:-----------------------|--------:|-----------:|-----------:|-----:|---:|\n|Constante | 34,859| 2,109| 16,530| 0,000| ***|\n|log(HABHA) | -5,836| 0,168| -34,840| 0,000| ***|\n|AgeMedian ordre 1 | -11,807| 15,648| -0,750| 0,451| |\n|AgeMedian ordre 2 | -266,469| 13,613| -19,570| 0,000| ***|\n|Pct_014 | 0,794| 0,032| 25,190| 0,000| ***|\n|Pct_65P | 0,277| 0,018| 15,130| 0,000| ***|\n|Pct_MV | -0,036| 0,010| -3,740| 0,000| ***|\n|Pct_FR | -0,279| 0,011| -25,340| 0,000| ***|\n|*Municipalité* | | | | | |\n|ref : Montréal-Est | --| --| --| --| --|\n|Baie-D'Urfé | 34,735| 2,495| 13,920| 0,000| ***|\n|Beaconsfield | 27,446| 2,091| 13,130| 0,000| ***|\n|Côte-Saint-Luc | 13,506| 2,167| 6,230| 0,000| ***|\n|Dollard-Des Ormeaux | 21,294| 2,053| 10,370| 0,000| ***|\n|Dorval | 24,491| 2,134| 11,480| 0,000| ***|\n|Hampstead | 16,414| 2,478| 6,620| 0,000| ***|\n|Kirkland | 20,272| 2,159| 9,390| 0,000| ***|\n|Mont-Royal | 26,033| 2,101| 12,390| 0,000| ***|\n|Montréal | 13,334| 1,920| 6,940| 0,000| ***|\n|Montréal-Ouest | 16,640| 2,628| 6,330| 0,000| ***|\n|Pointe-Claire | 23,230| 2,087| 11,130| 0,000| ***|\n|Sainte-Anne-de-Bellevue | 13,676| 2,687| 5,090| 0,000| ***|\n|Senneville | 36,570| 4,231| 8,640| 0,000| ***|\n|Westmount | 15,590| 2,196| 7,100| 0,000| ***|\n:::\n:::\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Comment choisir la catégorie de référence?**\n:::\n::: bloc_astuce-body\nPlusieurs options sont possibles. Vous pouvez retenir :\n\n* la modalité comprenant le plus d'observations;\n\n* la modalité avec la plus forte valeur pour la variable dépendante;\n\n* la modalité avec la plus faible valeur pour la variable dépendante;\n\n* la modalité qui fait le plus de sens avec votre cadre théorique. Prenons l'exemple d'une variable qualitative comprenant plusieurs groupes d'âge (15-29 ans, 30-39 ans, 40-49 ans, 50-54 ans, 65 ans et plus). Si votre étude porte sur les jeunes et que vous souhaitez comparer leur situation comparativement aux autres groupes d'âge, toutes choses étant égales par ailleurs, sélectionnez bien évidemment la modalité des 15 à 29 ans comme catégorie de référence.\n\nMais surtout, évitez de choisir une catégorie comprenant très peu d'observations.\n:::\n:::\n\n\n#### Effet marginal d'une variable explicative qualitative polytomique {#sec-07533}\n\nComme pour une variable dichotomique, il est possible d'illustrer l'effet marginal de la variable qualitative dichotomique avec un graphique. Quelle que soit la catégorie de référence choisie, le graphique est le même. La @fig-EffetMarginalPoly illustre ainsi la valeur moyenne, avec son intervalle de confiance à 95 %, de la végétation dans les îlots résidentiels de chacune des municipalités de la région de Montréal, *ceteris paribus*.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Effet marginal d'une variable polytomique](07-regressionlineaire_files/figure-html/fig-EffetMarginalPoly-1.png){#fig-EffetMarginalPoly fig-align='center' width=90%}\n:::\n:::\n\n\n\n### Variables d'interaction {#sec-0754}\n\n#### Variable d'interaction entre deux variables continues {#sec-07541}\n\nUne interaction entre deux variables indépendantes continues consiste à simplement les multiplier ($X_1 \\times X_2$). Le modèle s'écrit alors :\n\n$$\nY = \\beta_{0} + \\beta_{1}X_{1} + \\beta_{2}X_{2} + \\beta_{3}(X_{1}\\times X_{2}) +\\ldots+ \\beta_{k}X_{k} + e \n$$ {#eq-reginteractioncontinues}\n\nUn nouveau coefficient ($\\beta_{3}$) s'ajoute pour l'interaction (la multiplication) entre les deux variables continues. **Pourquoi ajouter une interaction entre deux variables?** L'objectif est d'évaluer l'effet d'une augmentation de $\\beta_{1}$ en fonction d'un niveau donné de $\\beta_{2}$ et inversement. Cela permet ainsi de répondre à la question suivante : l'effet de la variable $\\beta_{1}$ est-il influencé par la variable $\\beta_{2}$ et inversement?\n\nPrenons un exemple concret pour illustrer le tout. Premièrement, nous ajoutons `DistCBDkm` comme VI, soit la distance au centre-ville exprimée en kilomètres. Notez que pour ne pas surspécifier le modèle, les variables dichotomique `VilleMtl` ou polytomique `Municipalité` ont été préalablement ôtées. Le coefficient (B = 0,659, *p* < 0,001) signale que plus nous nous éloignons du centre-ville, plus la couverture végétale des îlots augmente significativement. En guise d'exemple, toutes choses étant égales par ailleurs, un îlot situé à dix kilomètres du centre-ville aura en moyenne 6,59 % plus de végétation (@tbl-ModeleInteraction1).\n\n\n::: {#tbl-ModeleInteraction1 .cell tbl-cap='Modèle avec la distance au centre-ville (km)'}\n::: {.cell-output-display}\n|Variable | Coef.| Erreur type| Valeur de T| P| |\n|:-----------------|--------:|-----------:|-----------:|-----:|---:|\n|Constante | 41,061| 1,085| 37,830| 0,000| ***|\n|log(HABHA) | -5,555| 0,172| -32,300| 0,000| ***|\n|AgeMedian ordre 1 | 176,921| 16,582| 10,670| 0,000| ***|\n|AgeMedian ordre 2 | -298,735| 13,560| -22,030| 0,000| ***|\n|Pct_014 | 0,763| 0,031| 24,440| 0,000| ***|\n|Pct_65P | 0,321| 0,018| 17,860| 0,000| ***|\n|Pct_MV | -0,018| 0,010| -1,880| 0,060| .|\n|Pct_FR | -0,288| 0,011| -26,260| 0,000| ***|\n|DistCBDkm | 0,659| 0,027| 24,460| 0,000| ***|\n:::\n:::\n\n\nDans ce modèle (@tbl-ModeleInteraction1), les pourcentages d'enfants de moins de 15 ans et de 65 ans et plus (`Pct_014` et `Pct_65P`) sont associés positivement à la variable dépendante tandis que le pourcentage de personnes à faible revenu (`Pct_FR`) est associé négativement.\n\nQue se passe-t-il si nous introduisons une variable d'interaction entre `DistCBDkm` et `Pct_FR` (@tbl-ModeleInteraction2)? L’effet du pourcentage de personnes à faible revenu (%) est significatif et négatif lorsqu’il est mis en interaction avec la distance au centre-ville. Cela indique que plus l'îlot est éloigné du centre-ville, plus `Pct_FR` a un effet négatif sur la couverture végétale (B = −0,011, *p* < 0,001).\n\n\n::: {#tbl-ModeleInteraction2 .cell tbl-cap='Modèle avec une variable d\\'interaction entre deux VI continues'}\n::: {.cell-output-display}\n|Variable | Coef.| Erreur type| Valeur de T| P| |\n|:-----------------|--------:|-----------:|-----------:|-----:|---:|\n|Constante | 38,382| 1,137| 33,760| 0,000| ***|\n|log(HABHA) | -5,505| 0,172| -32,080| 0,000| ***|\n|AgeMedian ordre 1 | 160,523| 16,672| 9,630| 0,000| ***|\n|AgeMedian ordre 2 | -310,666| 13,610| -22,830| 0,000| ***|\n|Pct_014 | 0,786| 0,031| 25,130| 0,000| ***|\n|Pct_65P | 0,345| 0,018| 18,960| 0,000| ***|\n|Pct_MV | -0,018| 0,010| -1,820| 0,069| .|\n|Pct_FR | -0,191| 0,017| -11,500| 0,000| ***|\n|DistCBDkm | 0,821| 0,034| 24,060| 0,000| ***|\n|DistCBDkmX_Pct_FR | -0,011| 0,001| -7,700| 0,000| ***|\n:::\n:::\n\n\nÀ nouveau, il est possible de représenter l'effet de cette interaction à l'aide d'un graphique des effets marginaux. Notez cependant que nous devons représenter l'effet simultané de deux variables indépendantes sur notre variable dépendante, ce qu'il est possible de faire avec une carte de chaleur. La @fig-ModeleInteraction2heat représente donc l'effet moyen de l'interaction sur la prédiction dans le premier panneau, ainsi que l'intervalle de confiance à 95 % de la prédiction dans les deuxième et troisième panneaux. \n\nNous constatons ainsi que le modèle prédit des valeurs de végétation les plus faibles lorsque le pourcentage de personnes à faible revenu est élevé et que la distance au centre-ville est élevée (en haut à droite à la @fig-ModeleInteraction2heat). En revanche, les valeurs les plus élevées de végétation sont atteintes lorsque la distance au centre-ville est élevée et que le pourcentage de personnes à faible revenu est faible (en bas à droite). Il semble donc que l'éloignement au centre-ville soit associé avec une augmentation de la densité végétale, mais que cette augmentation puisse être mitigée par l'augmentation parallèle du pourcentage de personnes à faible revenu.\n\n\n::: {.cell}\n::: {.cell-output-display}\n![Effet marginal de l'interaction entre deux variables continues](07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat-1.png){#fig-ModeleInteraction2heat width=95%}\n:::\n:::\n\n\nNotez que dans la @fig-ModeleInteraction2heat, la relation entre les deux variables indépendantes et la variable dépendante apparaît non linéaire du fait de l'interaction. À titre de comparaison, si nous utilisons les prédictions du modèle 5 (sans interaction), nous obtenons les prédictions présentées à la @fig-ModeleInteraction2heat2. Vous pouvez constater sur cette figure sans interaction que les deux effets des variables indépendantes sont linéaires puisque toutes les lignes sont parallèles.\n\n\n::: {.cell}\n::: {.cell-output-display}\n![Effets marginaux de deux variables continues en cas d'absence d'interaction](07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat2-1.png){#fig-ModeleInteraction2heat2 width=75%}\n:::\n:::\n\n\n#### Variable d'interaction entre une variable continue et une variable dichotomique {#sec-07542}\n\nUne interaction entre une VI continue et une VI dichotomique consiste aussi à les multiplier ($X_1 \\times D_2$); le modèle s'écrit alors :\n\n$$\nY = \\beta_{0} + \\beta_{1}X_{1} + \\beta_{2}D_{2} + \\beta_{3}(X_{1}\\times D_{2}) +\\ldots+ \\beta_{k}X_{k} + e \n$$ {#eq-reginteractioncontinuedicho}\n\nPour interpréter le coefficient $B_3$, il convient alors de bien connaître le nom de la modalité ayant la valeur de 1 (0 étant la modalité de référence). Dans le modèle présenté au @tbl-ModeleInteractionBinaire, nous avons multiplié la variable dichotomique ville de Montréal (`VilleMtl`) avec le pourcentage de personnes à faible revenu (`Pct_FR`). Les résultats de ce modèle démontrent que, toutes choses étant égales par ailleurs :\n\n* À chaque augmentation d'une unité du pourcentage à faible revenu (`Pct_FR`), le pourcentage de la couverture végétale diminue significativement de −0,444.\n\n* Comparativement à un îlot situé dans une autre municipalité de l'île de Montréal, un îlot de la ville de Montréal a en moyenne −9,804 de couverture végétale.\n\n* À chaque augmentation d'une unité de `Pct_FR` pour un îlot de la Ville Montréal, la couverture végétale augmente de 0,166 comparativement à une autre municipalité de l'île. En d'autres termes, le `Pct_FR` sur le territoire de la ville de Montréal est associé à une diminution de la couverture végétale moins forte que les autres municipalités, comme illustré à la @fig-ModeleInteractionBinaire) (pentes en rouge et en bleu).\n\n\n\n::: {#tbl-ModeleInteractionBinaire .cell tbl-cap='Modèle avec les variables d\\'interaction entre une VI continue et une VI dichotomique'}\n::: {.cell-output-display}\n|Variable | Coef.| Erreur type| Valeur de T| P| |\n|:-----------------|--------:|-----------:|-----------:|-----:|---:|\n|Constante | 59,275| 1,053| 56,300| 0,000| ***|\n|log(HABHA) | -6,160| 0,168| -36,640| 0,000| ***|\n|AgeMedian ordre 1 | -20,719| 15,354| -1,350| 0,177| |\n|AgeMedian ordre 2 | -278,141| 13,656| -20,370| 0,000| ***|\n|Pct_014 | 0,789| 0,031| 25,100| 0,000| ***|\n|Pct_65P | 0,278| 0,018| 15,200| 0,000| ***|\n|Pct_MV | -0,030| 0,010| -3,030| 0,002| **|\n|Pct_FR | -0,444| 0,030| -14,550| 0,000| ***|\n|VilleMtl | -9,804| 0,549| -17,850| 0,000| ***|\n|VilleMtlX_Pct_FR | 0,166| 0,032| 5,260| 0,000| ***|\n:::\n:::\n\n\nL'interaction entre une variable qualitative et une variable quantitative peut être représentée par un graphique des effets marginaux. La pente (coefficient) de la variable quantitative varie en fonction des deux catégories de la variable qualitative dichotomique (@fig-ModeleInteractionBinaire).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Graphique de l’effet marginal de l’interaction entre une variable quantitative et qualitative](07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaire-1.png){#fig-ModeleInteractionBinaire fig-align='center' width=75%}\n:::\n:::\n\n\n\n#### Variable d'interaction entre deux variables dichotomiques {#sec-07543}\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Variable d'interaction entre deux variables dichotomiques**\n:::\n::: bloc_aller_loin-body\nNous avons vu qu'il est possible d'introduire une variable d'interaction entre deux variables continues ou entre une variable continue et une autre dichotomique. Sachez qu’il est aussi possible d’introduire une interaction entre deux variables dichotomiques. Sur le sujet, vous pouvez consulter la section 8.3 de l'excellent ouvrage de Hanck et al. [-@hanck2019introduction].\n:::\n:::\n\n## Diagnostics de la régression {#sec-076}\n\nPour illustrer comment vérifier si le modèle respecte ou non les hypothèses de la régression, nous utilisons le modèle suivant :\n\n`modele3 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)`\n\n\n### Nombre d'observations {#sec-0761}\nTous les auteurs ne s'entendent pas sur le nombre d'observations minimal que devrait comprendre une régression linéaire multiple, tant s'en faut! Parallèlement, d'autres auteurs proposent aussi des méthodes de simulation pour estimer les coefficients de régression sur un jeu de données comprenant peu d'observations. Bien qu'aucune règle ne soit bien établie, la question du nombre d'observations mérite d'être posée puisqu'un modèle basé sur trop peu d'observations risque de produire des coefficients de régression peu fiables. Par faible fiabilité des coefficients, nous entendons que la suppression d’une ou de plusieurs observations pourrait drastiquement changer l’effet et/ou la significativité d’une ou de plusieurs variables explicatives.\n\nDans un ouvrage classique intitulé *Using Multivariate Statistics*, Barbara Tabachnick et Linda Fidell [-@tabachnick2007, p.123-124] proposent deux règles de pouce (à la louche) :\n\n1. $n \\geq 50 + 8k$ avec $n$ et $k$ étant respectivement les nombres d'observations et de variables indépendantes, pour tester le coefficient de corrélation multiple (R^2^).\n\n2. $n \\geq 104 + k$ pour tester individuellement chaque variable indépendante.\n\nDans le modèle, nous avons 10 210 observations et variables indépendantes. Les deux conditions sont donc largement respectées.\n\n\n\n\n\n\n### Normalité des résidus {#sec-0762}\n\nPour vérifier si les résidus sont normalement distribués, trois démarches largement décrites dans la [section @sec-0254] peuvent être utilisées :\n\n* le calcul des coefficients d’asymétrie et d’aplatissement;\n* les tests de normalité, particulièrement celui de Jarque-Bera basé sur un test multiplicateur de Lagrange;\n* les graphiques (histogramme avec courbe normale et diagramme quantile-quantile) (@fig-VerifierNormaliteResidus).\n\nLes deux premières démarches étant parfois très restrictives, nous accordons habituellement une attention particulière aux graphiques.\n\nPour notre modèle, les coefficients d’asymétrie (−0,263) et d’aplatissement (1,149) signalent que la distribution est plutôt symétrique, mais leptokurtique, c'est-à-dire que les valeurs des résidus sont bien réparties autour de 0, mais avec une faible dispersion. Puisque la valeur de *p* associée au test de Jarque-Bera est inférieure à 0,05, nous pouvons en conclure que la distribution des résidus est anormale. La forme pointue de la distribution est d'ailleurs confirmée à la lecture de l'histogramme avec la courbe normale et du diagramme quantile-quantile.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output .cell-output-stdout}\n```\nSkewness Kurtosis \n -0.161 1.193 \n```\n:::\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tRobust Jarque Bera Test\n\ndata: residus\nX-squared = 513.15, df = 2, p-value < 2.2e-16\n```\n:::\n\n::: {.cell-output-display}\n![Vérification de la normalité des résidus](07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidus-1.png){#fig-VerifierNormaliteResidus fig-align='center' width=75%}\n:::\n:::\n\n\n### Linéarité et homoscédasticité des résidus {#sec-0763}\n\nUn modèle est efficace si la dispersion des résidus est homogène sur tout le spectre des valeurs prédites de la variable dépendante. Dans le cas d’une absence d’homoscédasticité – appelée problème d'hétéroscédasticité –, le nuage de points construit à partir des résidus et des valeurs prédites (@fig-VerifierHomoscedasticite) prend la forme d’une trompette ou d'un entonnoir : les résidus sont alors faibles quand les valeurs prédites sont faibles et sont de plus en plus élevés au fur et à mesure que les valeurs prédites augmentent.\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution des résidus en fonction des valeurs prédites](07-regressionlineaire_files/figure-html/fig-VerifierHomoscedasticite-1.png){#fig-VerifierHomoscedasticite fig-align='center' width=75%}\n:::\n:::\n\n\nLe test de Breusch-Pagan est souvent utilisé pour vérifier l'homoscédasticité des résidus. Il est construit avec les hypothèses suivantes :\n\n* *H~0~* : homoscédasticité, c'est-à-dire que les termes d'erreur ont une variance constante à travers les valeurs prédites.\n\n* *H~1~* : hétéroscédasticité.\n\nSi la valeur de *p* associée à ce test est inférieure à 0,05, nous réfutons l'hypothèse nulle et nous concluons qu'il y a un problème d'hétéroscédasticité, ce qui est le cas pour notre modèle.\n\n\n\n::: {.cell}\n::: {.cell-output .cell-output-stdout}\n```\n\n\tstudentized Breusch-Pagan test\n\ndata: modele3\nBP = 1722, df = 8, p-value < 2.2e-16\n```\n:::\n:::\n\n\n### Absence de multicolinéarité excessive {#sec-0764}\n\nUn modèle présente un problème de multicolinéarité excessive lorsque deux variables indépendantes ou plus sont très fortement corrélées entre elles. Rappelez-vous qu'un coefficient de régression estime l'effet d'une variable dépendante ($X_k$) si toutes les autres VI restent constantes (c'est-à-dire une fois les autres VI contrôlées, toutes choses étant égales par ailleurs...).\n\nPrenons deux variables indépendantes ($X_1$ et $X_2$) fortement corrélées avec un coefficient de Pearson très élevé (0,90 par exemple). Admettons que chacune des deux VI a un effet important et significatif sur votre VD lorsqu’une seule est introduite dans le modèle. Si les deux variables sont introduites dans le même modèle, vous évaluez donc l’effet de $X_1$ une fois contrôlé $X_2$ et l’effet de $X_2$ une fois contrôlé $X_1$. Par conséquent, l’effet de l’une des deux devient très faible, voire probablement non significatif.\n\n#### Comment évaluer la multicolinéarité? {#sec-07641}\n\nPour ce faire, nous utilisons habituellement le facteur d’inflation de la variance (*Variance Inflation Factor – VIF* en anglais). Le calcul de ce facteur pour chaque VI est basé sur trois étapes. \n\n\n1. Pour chaque VI, nous construisons un modèle de régression multiple où elle est expliquée par toutes les autres variables indépendantes du modèle. Par exemple, pour la première VI ($X_1$), l'équation du modèle s'écrit :\n\n\n$$\nX_1 = b_0 + b_2X_2 +\\ldots+ b_kX_k + e\n$$ {#eq-RegVIF}\n\n\n2. À partir de cette équation, nous obtenons ainsi un $R^2$ qui nous indique la proportion de la variance de $X_1$ expliquée par les autres VI. Par convention, nous calculons la tolérance (@eq-ToleranceVIF) qui indique la proportion de la variance de $X_k$ n'étant pas expliquée par les autres VI. En guise d'exemple, une valeur de tolérance égale à 0,1 signale que 90 % de la variance de $X_k$ est expliqué par les autres variables, ce qui est un problème de multicolinéarité en soit. Concrètement, plus la valeur de la tolérance est proche de zéro, plus c’est problématique.\n\n\n$$\n\\mbox{Tolérance}_k=1-R_k^2=\\frac{1}{VIF_k}\n$$ {#eq-ToleranceVIF}\n\n\n3. Puis, nous calculons le facteur d'inflation de la variance (@eq-VIF). Là encore, des règles de pouce (à la louche) sont utilisées. Certains considéreront une valeur de VIF supérieur à 10 (soit une tolérance à 0,1 ou inférieure) comme problématique, d'autres retiendront le seuil de 5 plus conservateur (soit une tolérance à 0,2 ou inférieure).\n\n\n$$\nVIF_k = \\frac{1}{1-R_k^2} \n$$ {#eq-VIF}\n\nPour notre modèle, toutes les valeurs de VIF sont inférieures à 2, indiquant, sans l'ombre d'un doute, l'absence de multicolinéarité excessive.\n\n\n::: {.cell}\n::: {.cell-output .cell-output-stdout}\n```\n GVIF Df GVIF^(1/(2*Df))\nVilleMtl 1.319 1 1.149\nlog(HABHA) 1.342 1 1.159\npoly(AgeMedian, 2) 1.399 2 1.087\nPct_014 1.601 1 1.265\nPct_65P 1.317 1 1.147\nPct_MV 1.483 1 1.218\nPct_FR 1.818 1 1.348\n```\n:::\n:::\n\n\n#### Comment régler un problème de multicolinéarité? {#sec-07642}\n\n* La prudence est de mise! Si une ou plusieurs variables présentent une valeur de VIF supérieure à 5, construisez une matrice de corrélation de Pearson ([section @sec-0437]) et repérez les valeurs de corrélation supérieures à 0,8 ou inférieures à −0,8. Vous repérerez ainsi les corrélations problématiques entre deux variables indépendantes du modèle.\n\n * Refaites ensuite un modèle en ôtant la variable indépendante avec la plus forte valeur de VIF (7 ou 12 par exemple), et revérifiez les valeurs de VIF. Refaites cette étape si le problème de multicolinéarité excessive persiste.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Une multicolinéarité excessive n'est pas forcément inquiétante**\n:::\n::: bloc_attention-body\nNous avons vu plus haut comment introduire des variables indépendantes particulières comme des variables d'interaction ($X_1 \\times X_2$) ou des variables sous une forme polynomiale (ordre 2 : $X_1 + X_1^2$; ordre 3 : $X_1 + X_1^2 + X_1^3$, etc.). Bien entendu, ces termes composant les variables d'interaction ou d'une forme polynomiale sont habituellement fortement corrélés entre eux. Cela n'est toutefois pas problématique!\n\nDans l'exemple ci-dessous, nous obtenons deux valeurs de VIF très élevées pour la variable d'interaction `Pct_014:DistCBDkm` (16,713) et l'un des paramètres à partir duquel elle est calculée, soit `DistCBDkm` (12,526). \n\n\n::: {.cell}\n::: {.cell-output .cell-output-stdout}\n```\n GVIF Df GVIF^(1/(2*Df))\nlog(HABHA) 1.426 1 1.194\npoly(AgeMedian, 2) 1.768 2 1.153\nPct_014 3.326 1 1.824\nPct_65P 1.359 1 1.166\nPct_MV 1.495 1 1.223\nPct_FR 1.810 1 1.345\nDistCBDkm 12.526 1 3.539\nPct_014:DistCBDkm 16.713 1 4.088\n```\n:::\n:::\n\n:::\n:::\n\n\n### Absence d'observations aberrantes {#sec-0766}\n\n#### Détection des observations très influentes du modèle {#sec-07661} \n\nLors de l'analyse des corrélations ([section @sec-043]), nous avons vu que des valeurs extrêmes peuvent avoir un impact important sur le coefficient de corrélation de Pearson. Le même principe s'applique à la régression multiple, pour laquelle nous nous s'attendrions à ce que chaque observation joue un rôle équivalent dans la détermination de l'équation du modèle.\n\nAutrement dit, il est possible que certaines observations avec des valeurs extrêmes – fortement dissemblables des autres – aient une influence importante, voire démesurée, dans l’estimation du modèle. Concrètement, cela signifie que si elles étaient ôtées, les coefficients de régression et la qualité d'ajustement du modèle pourraient changer drastiquement. Deux mesures sont habituellement utilisées pour évaluer l’influence de chaque observation sur le modèle :\n\n* **La statistique de la distance de Cook** qui mesure l’influence de chaque observation sur les résultats du modèle. Brièvement, la distance de Cook évalue l’influence de l’observation *i* en la supprimant du modèle (@eq-DistanceCook). Plus sa valeur est élevée, plus l’observation joue un rôle important dans la détermination de l’équation de régression.\n\n\n$$\nD_i = \\frac{\\sum_{j=1}^n(\\widehat{y}_i-\\widehat{y}_{i(j)})^2}{ks^2}\n$$ {#eq-DistanceCook}\n\navec $\\widehat{y}_{i(j)}$ la valeur prédite quand l'observation *i* est ôté du modèle, *k* le nombre de variables indépendantes et $s^2$ l'erreur quadratique moyenne du modèle.\n\n* **La statistique de l'effet levier** (*leverage value* en anglais) qui varie de 0 (aucune influence) à 1 (explique tout le modèle). La somme de toutes les valeurs de cette statistique est égale au nombre de VI dans le modèle.\n\n\n**Quel critère retenir pour détecter les observations avec potentiellement une trop grande influence sur le modèle?**\n\nPour les repérer, voire les supprimer, plusieurs auteur(e)s proposent les seuils suivants : $4/n$ ou $8/n$ ou $16/n$. Avec 10210 observations dans le modèle, les seuils seraient les suivants : \n\n\n::: {.cell}\n::: {.cell-output .cell-output-stdout}\n```\nNombre d'observations = 10210 (100 %) \n 4/n = 0.00039 \n 8/n = 0.00078 \n 16/n = 0.00157 \nObservations avec une valeur supérieure ou égale aux différents seuils \n 4/n = 605 soit 5.93 % \n 8/n = 275 soit 2.69 % \n 16/n = 133 soit 1.3 %\n```\n:::\n:::\n\n\nLe critère de $4/n$ étant plutôt sévère, nous privilégions généralement celui de $8/n$, voire $16/n$. Il est aussi possible de construire un nuage de points pour les repérer (@fig-GraphCookLev).\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Repérage graphique les valeurs influentes du modèle](07-regressionlineaire_files/figure-html/fig-GraphCookLev-1.png){#fig-GraphCookLev fig-align='center' width=75%}\n:::\n:::\n\n\n#### Quoi faire avec les observations très influentes du modèle {#sec-07662} \n\nTrois approches sont possibles :\n\n* **Recourir à des régressions *boostrap***, ce qui permet généralement de supprimer l'effet de ces observations. Brièvement, le principe général est de créer un nombre élevé d'échantillons du jeu de données initial (1000 à 2000 itérations par exemple) et de construire un modèle de régression pour chacun d'eux. On obtiendra ainsi des intervalles de confiance pour les coefficients de régression et les mesures d'ajustement du modèle.\n\n* **Supprimer les observations trop influentes** (avec l'un des critères de $4/n$, $8/n$ et $16/n$ vus plus haut). Une fois supprimées, il convient 1) de recalculer le modèle, 2) de refaire le diagnostic de la régression au complet et finalement, 3) de comparer les modèles avant et après suppression des valeurs trop influentes, notamment la qualité d'ajustement du modèle (R^2^ ajusté) et les coefficients de régression. Des changements importants indiqueront que le premier modèle est potentiellement biaisé.\n\n* **Utiliser un modèle linéaire généralisé (GLM)** permettant d'utiliser une distribution différente correspondant plus à votre jeu de données ([chapitre @sec-chap08]).\n\n\n## Mise en œuvre dans R {#sec-077}\n\n### Fonctions `lm`, `summary()` et `confint()` {#sec-0771}\n\nLes fonctions de base `lm`, `summary()` et `confint()` permettent respectivement 1) de construire un modèle, 2) d'afficher ces résultats et 3) d'obtenir les intervalles de confiance des coefficients de régression : \n\n* `monModele <- lm(Y ~X1+X2+..+Xk)` avec *Y* étant la variable dépendante et les variables indépendantes (`X1 à Xk`) étant séparées par le signe +.\n\n* `summary(monModele)`\n\n* `confint(monModele, level=.95)`.\n\nDans la syntaxe ci-dessous, vous retrouverez les différents modèles abordés dans les sections précédentes; remarquez que toutes que les lignes `summary` sont mises en commentaires afin de ne pas afficher les résultats des modèles.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Chargement des données\nload(\"data/lm/DataVegetation.RData\")\n\n# 1er modèle de régression\nmodele1 <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR,\n data = DataFinal)\n# summary(Modele1)\n\n# 2e modèle de régression : fonction polynomiale d'ordre 2 (poly(AgeMedian,2))\nmodele2 <- lm(VegPct ~ HABHA+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR,\n data = DataFinal)\n# summary(Modele2)\n\n# 3e modèle de régression : forme logarithmique (log(HABHA))\nmodele3 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR,\n data = DataFinal)\n# summary(Modele3)\n\n# 4e modèle de régression : VI dichotomique\n# création de la variable dichotomique (VilleMtl)\nDataFinal$VilleMtl <- ifelse(DataFinal$SDRNOM == \"Montréal\", 1, 0)\nmodele4 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+\n VilleMtl, # variable dichotomique\n data = DataFinal)\n# summary(Modele4)\n\n# 5e modèle de régression : VI polytomique\n# création de la variable polytomique (Munic)\nDataFinal$Munic <- relevel(DataFinal$SDRNOM, ref = \"Montréal\")\nmodele5 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+\n Munic, data = DataFinal)\n# summary(Modele5)\n\n\n# 6e modèle de régression : interaction entre deux VI continues, \n# soit DistCBDkm*Pct_014\nmodele6 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+\n DistCBDkm+DistCBDkm*Pct_014,\n data = DataFinal)\n# summary(Modele6)\n\n# 7e modèle de régression : interaction entre une VI continue et une VI dichotomique,\n# soit VilleMtl*Pct_FR\nmodele8 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+\n VilleMtl*Pct_FR,\n data = DataFinal)\n# summary(Modele7)\n```\n:::\n\n\n\nÀ la @fig-OutputRegression, les résultats de la régression linéaire multiple, obtenus avec la `summary(monModele)`, sont présentés en quatre sections distinctes :\n\na. Le rappel de l'équation du modèle.\n\nb. Quelques statistiques descriptives sur les résidus du modèle, soit la différence entre les valeurs observées et prédites.\n\nc. Un tableau pour les coefficients de régression comprenant plusieurs colonnes, à savoir les coefficients de régression (`Estimate`), l'erreur type du coefficient (`Std. Error`), la valeur de *t* (`t value`) et la probabilité associée à la valeur de *t* (`Pr(>|t|)`). La première ligne de ce tableau (`Estimate`) est pour la constante (*Intercept* en anglais) et celles qui suivent sont pour les variables indépendantes.\n\nd. Les mesures d'ajustement du modèle, dont le RMSE (`Residual standard error`), les R^2^ classique (`Multiple R-squared`) et ajusté (`Adjusted R-squared`), la statistique *F* avec le nombre de degrés de liberté en lignes (nombre d'observations) et en colonnes (*n-k-1*) ainsi que la valeur de *p* qui est lui associée (`F-statistic: 1223 on 6 and 10203 DF, p-value: < 2.2e-16`).\n\n![Différentes parties obtenues avec la fonction `summary(Modèle)`](images/Chap07/SortiesLM.jpg){#fig-OutputRegression width=\"75%\" fig-align=\"center\"}\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Intervalle de confiance des coefficients à 95 %\nconfint(modele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 2.5 % 97.5 %\n(Intercept) 50.8684505 54.79255157\nlog(HABHA) -7.1847527 -6.52495353\npoly(AgeMedian, 2)1 -18.5676034 42.53686203\npoly(AgeMedian, 2)2 -313.4726002 -258.81630119\nPct_014 0.8793672 1.00190861\nPct_65P 0.2699504 0.34250907\nPct_MV -0.0557951 -0.01681481\nPct_FR -0.3659445 -0.32269562\n```\n:::\n:::\n\n\n\n### Comparaison des modèles {#sec-0772}\n\nTel que détaillé à la [section @sec-0732], pour comparer des modèles imbriqués, il convient d'analyser les valeurs du R^2^ ajusté et du *F* incrémentiel, ce qui peut être fait en trois étapes.\n\n**Première étape.** Il peut être judicieux d'afficher l'équation des différents modèles afin de se remémorer les VI introduites dans chacun d'eux, et ce, avec la fonction `MonModèle$call$formula`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Rappel des équations des huit modèles \nprint(modele1$call$formula)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nVegPct ~ HABHA + AgeMedian + Pct_014 + Pct_65P + Pct_MV + Pct_FR\n```\n:::\n\n```{.r .cell-code}\nprint(modele2$call$formula)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nVegPct ~ HABHA + poly(AgeMedian, 2) + Pct_014 + Pct_65P + Pct_MV + \n Pct_FR\n```\n:::\n\n```{.r .cell-code}\nprint(modele3$call$formula)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nVegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + \n Pct_MV + Pct_FR\n```\n:::\n\n```{.r .cell-code}\nprint(modele4$call$formula)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nVegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + \n Pct_MV + Pct_FR + VilleMtl\n```\n:::\n\n```{.r .cell-code}\nprint(modele5$call$formula)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nVegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + \n Pct_MV + Pct_FR + Munic\n```\n:::\n\n```{.r .cell-code}\nprint(modele6$call$formula)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nVegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + \n Pct_MV + Pct_FR + DistCBDkm + DistCBDkm * Pct_014\n```\n:::\n\n```{.r .cell-code}\nprint(modele7$call$formula)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nVegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + \n Pct_MV + Pct_FR + VilleMtl + VilleMtlX_Pct_FR\n```\n:::\n:::\n\n\n**Deuxième étape.** La syntaxe ci-dessous vous permet de comparer les R^2^ ajustés des différents modèles. Nous constatons ainsi que :\n\n* La valeur du R^2^ ajusté du modèle 2 est supérieure à celle du modèle 1 (0,4378 versus 0,4179), signalant que la forme polynomiale d'ordre 2 pour l'âge médian des bâtiments (`poly(AgeMedian, 2)`) améliore la prédiction comparativement à la forme originelle de (`AgeMedian`).\n\n* La valeur du R^2^ ajusté du modèle 3 est supérieure à celle du modèle 2 (0,4653 versus 0,4378), signalant que la forme logarithmique pour la densité de population (`log(HABHA)`) améliore la prédiction comparativement à la forme originelle (`HABHA`).\n\n* La valeur du R^2^ ajusté du modèle 4 est supérieure à celle du modèle 3 (0,4863 versus 0,4653), signalant que l'introduction de la variable dichotomique (`VilleMtl`) pour la municipalité apporte un gain de variance expliquée non négligeable.\n\n* La valeur du R^2^ ajusté du modèle 5 est supérieure à celle du modèle 4 (0,5064 versus 0,4863), signalant que l'introduction de la variable polytomique pour les municipalités de l'île de Montréal (`Muni`) améliore la prédiction du modèle comparativement à la variable dichotomique (`VilleMtl`).\n\n* La valeur du R^2^ ajusté du modèle 6 est supérieure à celle du modèle 2 (0,4953 versus 0,4378), signalant que l'introduction d'une variable d'interaction entre deux variables continues (`DistCBDkm + DistCBDkm * Pct_014`) apporte également un gain substantiel comparativement au modèle 2, ne comprenant pas cette variable d'interaction.\n\n* La valeur du R^2^ ajusté du modèle 7 est supérieure à celle du modèle 2 (0,4877 versus 0,4378), signalant que l'introduction d'une variable d'interaction entre une variable continue et la variable dichotomique (`DistCBDkm + DistCBDkm * Pct_014`) apporte également un gain substantiel comparativement au modèle 2, ne comprenant pas cette variable d'interaction.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncat(\"\\nComparaison des R2 ajustés :\",\n \"\\nModèle 1.\", round(summary(modele1)$adj.r.squared,4), \n \"\\nModèle 2.\", round(summary(modele2)$adj.r.squared,4), \n \"\\nModèle 3.\", round(summary(modele3)$adj.r.squared,4), \n \"\\nModèle 4.\", round(summary(modele4)$adj.r.squared,4), \n \"\\nModèle 5.\", round(summary(modele5)$adj.r.squared,4), \n \"\\nModèle 6.\", round(summary(modele6)$adj.r.squared,4), \n \"\\nModèle 7.\", round(summary(modele7)$adj.r.squared,4)\n)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nComparaison des R2 ajustés : \nModèle 1. 0.4179 \nModèle 2. 0.4378 \nModèle 3. 0.4653 \nModèle 4. 0.4863 \nModèle 5. 0.5064 \nModèle 6. 0.4953 \nModèle 7. 0.4877\n```\n:::\n:::\n\n\n**Troisième étape.** La syntaxe ci-dessous permet d'obtenir le *F* incrémentiel pour des modèles ne comprenant pas le même nombre de variables dépendantes, et ce, en utilisant la fonction `anova(modele1, modele2, ..., modelen)`.\n\nPar exemple, la syntaxe `anova(modele1, modele2)` permet de comparer les deux modèles et signale que le gain de variance expliquée entre les deux modèles (R^2^ de 0,4179 et de 0,4378) est significatif (*F* incrémentiel = 362,64; *p* < 0,001).\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Comparaison des deux modèles uniquement (modèles 1 et 2)\nanova(modele1, modele2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nAnalysis of Variance Table\n\nModel 1: VegPct ~ HABHA + AgeMedian + Pct_014 + Pct_65P + Pct_MV + Pct_FR\nModel 2: VegPct ~ HABHA + poly(AgeMedian, 2) + Pct_014 + Pct_65P + Pct_MV + \n Pct_FR\n Res.Df RSS Df Sum of Sq F Pr(>F) \n1 10203 2046427 \n2 10202 1976182 1 70245 362.64 < 2.2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n```\n:::\n:::\n\n\nIl est aussi possible de comparer plusieurs modèles simultanément. Notez que dans la syntaxe ci-dessous, le troisième modèle n'est pas inclus, car il comprend le même nombre de variables indépendantes que le second modèle; il en va de même pour le sixième modèle comparativement au cinquième. Ici aussi, l'analyse des valeurs de *F* et de *p* vous permettent de vérifier si les modèles, et donc leurs R^2^ ajustés, sont significativement différents (quand *p* < 0,05).\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Comparaison de plusieurs modèles\nanova(modele1, modele2, modele4, modele5, modele7)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nAnalysis of Variance Table\n\nModel 1: VegPct ~ HABHA + AgeMedian + Pct_014 + Pct_65P + Pct_MV + Pct_FR\nModel 2: VegPct ~ HABHA + poly(AgeMedian, 2) + Pct_014 + Pct_65P + Pct_MV + \n Pct_FR\nModel 3: VegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + \n Pct_MV + Pct_FR + VilleMtl\nModel 4: VegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + \n Pct_MV + Pct_FR + Munic\nModel 5: VegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + \n Pct_MV + Pct_FR + VilleMtl + VilleMtlX_Pct_FR\n Res.Df RSS Df Sum of Sq F Pr(>F) \n1 10203 2046427 \n2 10202 1976182 1 70245 412.995 < 2.2e-16 ***\n3 10201 1805547 1 170636 1003.224 < 2.2e-16 ***\n4 10188 1732849 13 72698 32.878 < 2.2e-16 ***\n5 10200 1800664 -12 -67815 33.226 < 2.2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n```\n:::\n:::\n\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Quel modèle choisir?** \n:::\n::: bloc_attention-body\nNous avons déjà évoqué le principe de parcimonie. À titre de rappel, l'ajout de variables indépendantes qui s'avèrent significatives fait inévitablement augmenter la variance expliquée et ainsi la valeur R^2^ ajusté. Par contre, elle peut rendre le modèle plus complexe à analyser, voire entraîner un surajustement du modèle. Nous avons vu que l'introduction des variables ditchtomique, polytomique et d'interaction avait pour effet d'augmenter la capacité de prédiction du modèle. Quoi qu'il en soit, le gain de variance expliquée s'élève à environ 4 % entre le troisième modèle versus le cinquième et le sixième :\n\n* Modèle 3 (R^2^=0,465). `VegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + Pct_MV + Pct_FR`\n* Modèle 5 (R^2^=0,506). `VegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + Muni`\n* Modèle 6 (R^2^=0,495). `VegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + Pct_MV + Pct_FR + DistCBDkm + DistCBDkm * Pct_014`\n\nPar conséquent, il est légitime de se questionner sur le bien-fondé de conserver ces variables indépendantes additionnelles : `Muni` pour le modèle 5 et `DistCBDkm + DistCBDkm * Pct_014` pour le modèle 6. Trois options sont alors envisageables :\n\n* Bien entendu, conservez l'une ou l'autre de ces variables additionnelles si elles sont initialement reliées à votre cadre théorique.\n\n* Conservez l'une ou l'autre de ces variables additionnelles si elles permettent de répondre à une question spécifique (non prévue initialement) et si les associations ainsi révélées méritent, selon vous, discussion.\n\n* Supprimez-les si leur apport est limité et ne fait que complexifier le modèle.\n:::\n:::\n\n### Diagnostic sur un modèle {#sec-0773}\n\n#### Vérification le nombre d'observations {#sec-07731}\n\nLa syntaxe suivante permet de vérifier si le nombre d'observations est suffisant pour tester le R^2^ et chacune des variables indépendantes.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodele3 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n# Nombre d'observation\nnobs <- length(modele3$fitted.values)\n# Nombre de variables indépendantes (coefficients moins la constante)\nk <- length(modele3$coefficients)-1\n# Première règle de pouce\nif(nobs >= 50+(8*k)){\n cat(\"\\nNombre d'observations suffisant pour tester le R2\")\n}else{\n cat(\"\\nAttention! Nombre d'observations insuffisant pour tester le R2\")\n}\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nNombre d'observations suffisant pour tester le R2\n```\n:::\n\n```{.r .cell-code}\n# Deuxième règle de pouce\nif(nobs >= 104+k){\n cat(\"\\nNombre d'observations suffisant pour tester individuellement chaque VI\")\n}else{\n cat(\"\\nAttention! Nombre d'observations insuffisant\",\n \"\\npour tester individuellement chaque VI\")\n}\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nNombre d'observations suffisant pour tester individuellement chaque VI\n```\n:::\n:::\n\n\n#### Vérification la normalité des résidus {#sec-07732}\n\nLa syntaxe suivante permet de vérifier la normalité des résidus selon les trois démarches classiques : 1) coefficients d’asymétrie et d’aplatissement, 2) test de normalité de Jarque-Bera (fonction `JarqueBeraTest` du *package* `DescTools`) et 3) les graphiques (histogramme avec courbe normale et diagramme quantile-quantile).\n\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(DescTools)\nlibrary(stats)\nlibrary(ggplot2)\nlibrary(ggpubr)\n\n# Vecteur pour les résidus du modèle\nresidus <- modele3$residuals\n# 1. coefficients d’asymétrie et d’aplatissement \nc(Skewness= round(DescTools::Skew(residus),3), \n Kurtosis = round(DescTools::Kurt(residus),3))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nSkewness Kurtosis \n -0.263 1.149 \n```\n:::\n\n```{.r .cell-code}\n# 2. Test de normalité de Jarque-Bera\nJarqueBeraTest(residus)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tRobust Jarque Bera Test\n\ndata: residus\nX-squared = 528.51, df = 2, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\n# 3. Graphiques \nGhisto <- ggplot() +\n geom_histogram(aes(x = residus, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n stat_function(fun = dnorm, \n args = list(mean = mean(residus),\n sd = sd(residus)), \n color = \"#e63946\", size = 1.2, linetype = \"dashed\")+\n labs(title = \"Histogramme et courbe normale\",\n y = \"densité\", \"Résidus du modèle\")\n\nGqqplot <- qplot(sample = residus)+\n geom_qq_line(line.p = c(0.25, 0.75),\n color = \"#e63946\", size = 1.2)+\n labs(title = \"Diagramme quantile-quantile\",\n x = \"Valeurs théoriques\",\n y = \"Résidus\")\nggarrange(Ghisto, Gqqplot, ncol = 2, nrow = 1)\n```\n\n::: {.cell-output-display}\n![Diagnostic : la normalité des résidus](07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidusDia-1.png){#fig-VerifierNormaliteResidusDia fig-align='center' width=75%}\n:::\n:::\n\n\n#### Évaluation de la linéarité et l'homoscédasticité des résidus {#sec-07733}\n\nLa syntaxe suivante permet de vérifier si l'hypothèse d'homoscédasticité des résidus est respectée avec : 1) un nuage de points entre les valeurs prédites et des résidus, 3) les graphiques (histogramme avec courbe normale et diagramme quantile-quantile) et 2) le test de Breusch-Pagan (fonction `bptest` du *package* `lmtest`).\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# 1. Test de Breusch-Pagan pour vérifier l'homoscédasticité\nlibrary(lmtest)\nbptest(modele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tstudentized Breusch-Pagan test\n\ndata: modele3\nBP = 1651.5, df = 7, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\nif(bptest(modele3)$p.value < 0.05){\n cat(\"\\nAttention : problème d'hétéroscédasticité des résidus\")\n}else{\n cat(\"\\nParfait : homoscédasticité des résidus\")\n}\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nAttention : problème d'hétéroscédasticité des résidus\n```\n:::\n\n```{.r .cell-code}\n# 2. Graphique entre les valeurs prédites et les résidus\nresidus <- modele3$residuals\nypredits <- modele3$fitted.values\n\nggplot() +\n geom_point(aes(x = ypredits, y = residus),\n color = \"#343a40\", fill = \"#a8dadc\",\n alpha = 0.2, size = 0.8) +\n geom_smooth(aes(x = ypredits, y = residus), \n method = lm, color = \"red\")+\n labs(x = \"Valeurs prédites\", y = \"Résidus\")\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution des résidus en fonction des valeurs prédites](07-regressionlineaire_files/figure-html/fig-DiaHomoscedasticite-1.png){#fig-DiaHomoscedasticite fig-align='center' width=75%}\n:::\n:::\n\n\n#### Vérification la multicolinéarité excessive {#sec-07734}\nPour vérifier la présence ou l'absence de multicolinéarité excessive, nous utilisons habituellement la fonction `vif` du *package* `car`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(car)\n# facteur d'inflation de la variance\nround(car::vif(modele3),3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n GVIF Df GVIF^(1/(2*Df))\nlog(HABHA) 1.289 1 1.136\npoly(AgeMedian, 2) 1.387 2 1.085\nPct_014 1.518 1 1.232\nPct_65P 1.304 1 1.142\nPct_MV 1.480 1 1.217\nPct_FR 1.730 1 1.315\n```\n:::\n\n```{.r .cell-code}\n# problème de multicolinéarité (VIF > 10)?\ncar::vif(modele3) > 10\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n GVIF Df GVIF^(1/(2*Df))\nlog(HABHA) FALSE FALSE FALSE\npoly(AgeMedian, 2) FALSE FALSE FALSE\nPct_014 FALSE FALSE FALSE\nPct_65P FALSE FALSE FALSE\nPct_MV FALSE FALSE FALSE\nPct_FR FALSE FALSE FALSE\n```\n:::\n\n```{.r .cell-code}\n# problème de multicolinéarité (VIF > 5)?\ncar::vif(modele3) > 5 \n```\n\n::: {.cell-output .cell-output-stdout}\n```\n GVIF Df GVIF^(1/(2*Df))\nlog(HABHA) FALSE FALSE FALSE\npoly(AgeMedian, 2) FALSE FALSE FALSE\nPct_014 FALSE FALSE FALSE\nPct_65P FALSE FALSE FALSE\nPct_MV FALSE FALSE FALSE\nPct_FR FALSE FALSE FALSE\n```\n:::\n:::\n\n\n#### Répérage des valeurs très influentes du modèle {#sec-07735}\n\nLa syntaxe suivante permet d'évaluer le nombre de valeurs très influentes dans le modèle avec les critères de $\\mbox{4/n}$, $\\mbox{8/n}$ et $\\mbox{16/n}$ pour la distance de Cook.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nnobs <- length(modele3$fitted.values)\nDistanceCook <- cooks.distance(modele3)\nn4 <- length(DistanceCook[DistanceCook > 4/nobs])\nn8 <- length(DistanceCook[DistanceCook > 8/nobs])\nn16 <- length(DistanceCook[DistanceCook > 16/nobs])\ncat(\"Nombre d'observations =\", nobs, \"(100 %)\",\n \"\\n 4/n =\", round(4/nobs,5),\n \"\\n 8/n =\", round(8/nobs,5),\n \"\\n 16/n =\", round(16/nobs,5),\n\"\\nObservations avec une valeur supérieure ou égale aux différents seuils\",\n \"\\n 4/n =\", n4, \"soit\", round(n4/nobs*100,2),\" %\",\n \"\\n 8/n =\", n8, \"soit\", round(n8/nobs*100,2),\" %\",\n \"\\n 16/n =\", n16, \"soit\", round(n16/nobs*100,2), \" %\"\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nNombre d'observations = 10210 (100 %) \n 4/n = 0.00039 \n 8/n = 0.00078 \n 16/n = 0.00157 \nObservations avec une valeur supérieure ou égale aux différents seuils \n 4/n = 604 soit 5.92 % \n 8/n = 285 soit 2.79 % \n 16/n = 132 soit 1.29 %\n```\n:::\n:::\n\n\nVous pouvez également construire un nuage de points avec la distance de Cook et l'effet de levier (*leverage value*) pour repérer visuellement les observations très influentes (@fig-DiaGraphCookLev).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(car)\nlibrary(ggpubr)\nDistanceCook <- cooks.distance(modele3)\nLeverageValue <- hatvalues(modele3)\n\nG1 <- ggplot()+\n geom_point(aes(x = LeverageValue, y = DistanceCook), \n alpha = 0.2, size = 2, col = \"black\", fill = \"red\")+\n labs(x = \"Effet levier\",\n y = \"Distance de Cook\",\n title = \"Repérer les valeurs influentes\",\n subtitle = \"(toutes les observations)\")\n\nG2 <- ggplot()+\n geom_point(aes(x = LeverageValue, y = DistanceCook), \n alpha = 0.2, size = 2, col = \"black\", fill = \"red\")+\n ylim(0,0.01)+\n xlim(0,0.01)+\n labs(x = \"Effet levier\",\n y = \"Distance de Cook\",\n title = \"Repérer les valeurs influentes\",\n subtitle = \"(agrandissement)\")\n\nggarrange(G1, G2, nrow = 1, ncol = 2)\n```\n\n::: {.cell-output-display}\n![Repérage graphique des valeurs influentes du modèle](07-regressionlineaire_files/figure-html/fig-DiaGraphCookLev-1.png){#fig-DiaGraphCookLev fig-align='center' width=672}\n:::\n:::\n\n\n\n#### Construction d'un nouveau modèle en supprimant les observations très influentes du modèle {#sec-07736}\n\nDans un premier temps, il convient de construire un nouveau modèle sans les valeurs influentes du modèle de départ.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Nombre d'observation dans le modèle 3\nnobs <-length(modele3$fitted.values)\n# Distance de Cook\ncook <- cooks.distance(modele3)\n# Les observations très influentes avec le critère de 16/n\nDataSansOutliers <- cbind(DataFinal, cook)\nDataSansOutliers <- DataSansOutliers[DataSansOutliers$cook < 8/nobs, ]\nmodele3b <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR,\n data = DataSansOutliers)\nnobsb <-length(modele3b$fitted.values)\n```\n:::\n\n\nComparez les valeurs du R^2^ ajusté des deux modèles. Habituellement, la suppression des valeurs très influentes s'accompagne d'une augmentation du R^2^ ajusté. C'est notamment le cas ici puisque sa valeur grimpe de 0,4653 à 0,5684, signalant ainsi un gain important pour la variance expliquée.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncat(\"\\nComparaison des R2 ajustés :\",\n \"\\nModèle de départ (n=\", nobs, \"), \",\n round(summary(modele3)$adj.r.squared,4), \n \"\\nModèle sans les observations très influentes (n=\", nobsb, \"), \",\n round(summary(modele3b)$adj.r.squared,4),\n sep = \"\"\n)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nComparaison des R2 ajustés :\nModèle de départ (n=10210), 0.4653\nModèle sans les observations très influentes (n=9925), 0.5684\n```\n:::\n:::\n\n\nPour le modèle, il convient alors de refaire le diagnostic de la régression et de vérifier si la suppression des observations très influentes a amélioré : 1) la normalité, la linéarité et l'homoscédasticité des résidus, 2) la multicolinéarité excessive et 3) l'absence de valeurs trop influentes.\n\n**La normalité des résidus s'est-elle ou non améliorée?**\n\nPour ce faire, comparez les valeurs d’asymétrie, d’aplatissement et du test de Jarque-Bera et les graphiques de normalité. À la lecture des valeurs :\n\n* l'asymétrie est très similaire (-0,260 à -0,265);\n\n* l'aplatissement s'est amélioré (1,183 à 0,164);\n\n* le test de Jarque-Bera signale toujours un problème de normalité (*p* < 0,001), mais sa valeur a nettement diminué (548,7 à 131,24);\n\n* les graphiques démontrent une nette amélioration de la normalité des résidus (@fig-ResidusCompa).\n\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# 1. coefficients d’asymétrie et d’aplatissement \nresmodele3 <- rstudent(modele3)\nresmodele3b <- rstudent(modele3b)\n \nc(Skewness= round(Skew(resmodele3),3), \n Kurtosis = round(Kurt(resmodele3),3))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nSkewness Kurtosis \n -0.260 1.183 \n```\n:::\n\n```{.r .cell-code}\nc(Skewness= round(Skew(resmodele3b),3), \n Kurtosis = round(Kurt(resmodele3b),3))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nSkewness Kurtosis \n -0.265 0.164 \n```\n:::\n\n```{.r .cell-code}\n# 2. Test de normalité de Jarque-Bera\nJarqueBeraTest(resmodele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tRobust Jarque Bera Test\n\ndata: resmodele3\nX-squared = 548.7, df = 2, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\nJarqueBeraTest(resmodele3b)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tRobust Jarque Bera Test\n\ndata: resmodele3b\nX-squared = 131.24, df = 2, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\n# 3. Graphiques \nGhisto1 <- ggplot() +\n geom_histogram(aes(x = resmodele3, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n stat_function(fun = dnorm, args = list(mean = mean(resmodele3),\n sd = sd(resmodele3)), \n color = \"#e63946\", size = 1.2, linetype = \"dashed\")+\n labs(title = \"Modèle de départ\", y = \"densité\", x = \"Résidus studentisés\")\n\nGqqplot1 <- qplot(sample = residus)+\n geom_qq_line(line.p = c(0.25, 0.75), color = \"#e63946\", size = 1.2)+\n labs(title = \"Modèle de départ\", x = \"Valeurs théoriques\", y = \"Résidus studentisés\")\n\nGhisto2 <- ggplot() +\n geom_histogram(aes(x = resmodele3b, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n stat_function(fun = dnorm, args = list(mean = mean(resmodele3b),\n sd = sd(resmodele3b)), \n color = \"#e63946\", linewidth = 1.2, linetype = \"dashed\")+\n labs(title = \"Modèle après suppression\", x = \"Valeurs théoriques\", y = \"Résidus studentisés\")\n\nGqqplot2 <- qplot(sample = resmodele3b)+\n geom_qq_line(line.p = c(0.25, 0.75), color = \"#e63946\", size = 1.2)+\n labs(title = \"Modèle après suppression\",x = \"Valeurs théoriques\", y = \"Résidus studentisés\")\n\nlibrary(ggpubr)\nggarrange(Ghisto1, Ghisto2, Gqqplot1, Gqqplot2, ncol = 2, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Normalité des résidus avant et après la suppression des valeurs influentes](07-regressionlineaire_files/figure-html/fig-ResidusCompa-1.png){#fig-ResidusCompa fig-align='center' width=65%}\n:::\n:::\n\n\n**Le problème d’hétéroscédasticité est-il corrigé?**\n\n* la valeur du test de Breusch-Pagan est beaucoup plus faible, mais il semble persister un problème d'hétéroscédasticité.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# homoscédasticité des résidus améliorée ou non?\nlibrary(lmtest)\nlibrary(ggpubr)\n\nbptest(modele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tstudentized Breusch-Pagan test\n\ndata: modele3\nBP = 1651.5, df = 7, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\nbptest(modele3b)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tstudentized Breusch-Pagan test\n\ndata: modele3b\nBP = 640.53, df = 7, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\nresmodele3 <- residuals(modele3)\nresmodele3b <- residuals(modele3b)\nypredits3 <- modele3$fitted.values\nypredits3b <- modele3b$fitted.values\n\nG1 <- ggplot() +\n geom_point(aes(x = ypredits3, y = resmodele3),\n color = \"#343a40\", fill = \"#a8dadc\", alpha = 0.2, size = 0.8) +\n geom_smooth(aes(x = ypredits3, y = resmodele3), method = lm, color = \"red\")+\n labs(title = \"Modèle de départ\",x = \"Valeurs prédites\", y = \"Résidus studentisés\")\n\nG2 <- ggplot() +\n geom_point(aes(x = ypredits3b, y = resmodele3b),\n color = \"#343a40\", fill = \"#a8dadc\", alpha = 0.2, size = 0.8) +\n geom_smooth(aes(x = ypredits3b, y = resmodele3b), method = lm, color = \"red\")+\n labs(title = \"Modèle après suppression\",x = \"Valeurs prédites\", y = \"Résidus studentisés\")\n\nggarrange(G1, G2, ncol = 2, nrow = 1)\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Amélioration de l'homoscédasticité des résidus](07-regressionlineaire_files/figure-html/fig-HomosComp-1.png){#fig-HomosComp fig-align='center' width=65%}\n:::\n:::\n\n\n\nFinalement, il convient de comparer les coefficients de régression.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Comparaison des coefficients\nsummary(modele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCall:\nlm(formula = VegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + \n Pct_65P + Pct_MV + Pct_FR, data = DataFinal)\n\nResiduals:\n Min 1Q Median 3Q Max \n-66.848 -8.660 0.381 8.961 83.269 \n\nCoefficients:\n Estimate Std. Error t value Pr(>|t|) \n(Intercept) 5.283e+01 1.001e+00 52.781 < 2e-16 ***\nlog(HABHA) -6.855e+00 1.683e-01 -40.730 < 2e-16 ***\npoly(AgeMedian, 2)1 1.198e+01 1.559e+01 0.769 0.441958 \npoly(AgeMedian, 2)2 -2.861e+02 1.394e+01 -20.525 < 2e-16 ***\nPct_014 9.406e-01 3.126e-02 30.093 < 2e-16 ***\nPct_65P 3.062e-01 1.851e-02 16.546 < 2e-16 ***\nPct_MV -3.630e-02 9.943e-03 -3.651 0.000262 ***\nPct_FR -3.443e-01 1.103e-02 -31.212 < 2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\nResidual standard error: 13.57 on 10202 degrees of freedom\nMultiple R-squared: 0.4657,\tAdjusted R-squared: 0.4653 \nF-statistic: 1270 on 7 and 10202 DF, p-value: < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\nsummary(modele3b)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCall:\nlm(formula = VegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + \n Pct_65P + Pct_MV + Pct_FR, data = DataSansOutliers)\n\nResiduals:\n Min 1Q Median 3Q Max \n-46.417 -7.734 0.456 8.290 40.085 \n\nCoefficients:\n Estimate Std. Error t value Pr(>|t|) \n(Intercept) 6.748e+01 9.869e-01 68.370 < 2e-16 ***\nlog(HABHA) -1.000e+01 1.720e-01 -58.167 < 2e-16 ***\npoly(AgeMedian, 2)1 4.357e+01 1.387e+01 3.142 0.00168 ** \npoly(AgeMedian, 2)2 -3.564e+02 1.250e+01 -28.510 < 2e-16 ***\nPct_014 8.351e-01 2.870e-02 29.101 < 2e-16 ***\nPct_65P 2.271e-01 1.807e-02 12.566 < 2e-16 ***\nPct_MV -8.517e-03 9.109e-03 -0.935 0.34976 \nPct_FR -2.924e-01 1.028e-02 -28.440 < 2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\nResidual standard error: 11.96 on 9917 degrees of freedom\nMultiple R-squared: 0.5687,\tAdjusted R-squared: 0.5684 \nF-statistic: 1868 on 7 and 9917 DF, p-value: < 2.2e-16\n```\n:::\n:::\n\n\n### Graphiques pour les effets marginaux {#sec-0774}\nTel que signalé ultérieurement, il est courant de représenter l'effet marginal d'une VI sur une VD, une fois contrôlées les autres VI. Pour ce faire, il est possible d'utiliser les *packages* `ggplot2` et `ggeffects`.\n\n#### Effet marginal pour une variable continue {#sec-07741}\n\nLa syntaxe ci-dessous illustre comment obtenir un graphique pour nos quatre variables explicatives. Bien entendu, si le coefficient de régression est positif (comme pour les pourcentages de jeunes de moins de 15 ans et les personnes âgées), la pente est alors montante, et inversement descendante pour des coefficients négatifs (comme pour les personnes ayant déclaré appartenir à une minorité visible et les personnes à faible revenu). En outre, plus la valeur absolue du coefficient est forte, plus la pente est prononcée.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggplot2)\nlibrary(ggeffects)\nlibrary(ggpubr)\n\n# Création d'un DataFrame pour les valeurs prédites pour chaque VI continue\nfitV1 <- ggpredict(modele3, terms = \"Pct_014\")\nfitV2 <- ggpredict(modele3, terms = \"Pct_65P\")\nfitV3 <- ggpredict(modele3, terms = \"Pct_MV\")\nfitV4 <- ggpredict(modele3, terms = \"Pct_FR\")\n\n# Construction des graphiques\nG1 <-ggplot(fitV1, aes(x, predicted)) +\n # ligne de régression\n geom_line(color = \"red\", linewidth = 1) +\n # intervalle de confiance à 95 %\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n # Titres\n labs(y = \"valeur prédite Y\", x = \"Moins de 15 ans (%)\")\n\nG2 <-ggplot(fitV2, aes(x, predicted)) +\n geom_line(color = \"red\", linewidth = 1) +\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n labs(y = \"valeur prédite Y\", x = \"65 ans et plus (%)\")\n\nG3 <-ggplot(fitV3, aes(x, predicted)) +\n geom_line(color = \"blue\", linewidth = 1) +\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n labs(y = \"valeur prédite Y\", x = \"Minorités visibles (%)\")\n\nG4 <-ggplot(fitV4, aes(x, predicted)) +\n geom_line(color = \"blue\", linewidth = 1) +\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n labs(y = \"valeur prédite Y\", x = \"Personne à faible revenu (%)\")\n\n# Assemblage des graphiques\nggarrange(G1, G2, G3, G4, ncol =2, nrow =2)\n```\n\n::: {.cell-output-display}\n![Effets marginaux pour des variables continues](07-regressionlineaire_files/figure-html/fig-EffetMarginalVariablesContinues-1.png){#fig-EffetMarginalVariablesContinues fig-align='center' width=85%}\n:::\n:::\n\n\n#### Effet marginal pour une variable avec une fonction polynomiale d'ordre 2 {#sec-07742}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggplot2)\nlibrary(ggeffects)\nlibrary(ggpubr)\n\nfitAgeMedian <- ggpredict(modele3, terms = \"AgeMedian\")\n\n ggplot(fitAgeMedian, aes(x, predicted)) +\n geom_line(color = \"green\", linewidth = 1) +\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n labs(title = \"Variable sous forme polynomiale (ordre 2)\",\n y = \"VD: valeur prédite\", x = \"Âge médian des bâtiments\")\n```\n\n::: {.cell-output-display}\n![Effet marginal d'une variable avec un fonction polynomiale d'ordre 2](07-regressionlineaire_files/figure-html/fig-Titi-1.png){#fig-Titi fig-align='center' width=70%}\n:::\n:::\n\n\n#### Effet marginal pour une variable transformée en logarithme {#sec-07743}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nfitHabHa <- ggpredict(modele3, terms = \"HABHA\")\n\nggplot(fitHabHa, aes(x, predicted)) +\n geom_line(color = \"blue\", linewidth = 1) +\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n labs(y = \"VD: valeur prédite\", x = \"Habitants km2\")\n```\n\n::: {.cell-output-display}\n![Effet du logarithme de la densité](07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLog-1.png){#fig-EffetMarginalVariableLog fig-align='center' width=75%}\n:::\n:::\n\n\n#### Effet marginal pour une variable dichotomique {#sec-07744}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Valeurs prédites selon le modèle avec la variable dichotomique\nfitVilleMtl <- ggpredict(modele4, terms = \"VilleMtl\")\n# Graphique\nggplot(fitVilleMtl, aes(x = x, y = predicted)) +\n geom_bar(stat = \"identity\", position = position_dodge(), fill = \"wheat\") +\n geom_errorbar(aes(ymin = conf.low, ymax = conf.high), alpha = .9, position = position_dodge())+\n labs(title = \"Effet marginal de la ville de Montréal sur la végétation\",\n x = \"Municipalités de la région de Montréal\",\n y = \"Couverture végétation de l'îlot (%)\")+\n scale_x_continuous(breaks=c(0,1),\n labels = c(\"Autre municipalité\", \"Ville de Montréal\"))\n```\n\n::: {.cell-output-display}\n![Effet marginal d'une variable dichotomique](07-regressionlineaire_files/figure-html/fig-EffetMarginalDichCode-1.png){#fig-EffetMarginalDichCode fig-align='center' width=70%}\n:::\n:::\n\n\n#### Effet marginal pour une variable polytomique {#sec-07745}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Valeurs prédites selon le modèle avec la variable polytomique\nfitVilles <- ggpredict(modele5, terms = \"Munic\")\n# Graphique\nGraphique <- ggplot(fitVilles, aes(x = x, y = predicted)) +\n geom_bar(stat = \"identity\", position = position_dodge(), fill = \"wheat\") +\n geom_errorbar(aes(ymin = conf.low, ymax = conf.high), alpha = .9, position = position_dodge())+\n labs(title = \"Effet marginal de la ville de Montréal sur la végétation\",\n x = \"Municipalités de la région de Montréal\",\n y = \"Couverture végétation de l'îlot (%)\")\n\n# Rotation du graphique\nGraphique + coord_flip()\n```\n\n::: {.cell-output-display}\n![Effet marginal d'une variable polytomique](07-regressionlineaire_files/figure-html/fig-EffetMarginalPolyT-1.png){#fig-EffetMarginalPolyT fig-align='center' width=70%}\n:::\n:::\n\n\n#### Effet marginal pour une variable d'interaction (deux VI continues) {#sec-07746}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(metR) # pour ajouter des labels aux contours\n\ndf <- expand.grid(\n DistCBDkm = seq(0,33,0.1),\n Pct_FR = seq(0,95,1),\n HABHA = mean(DataFinal$HABHA),\n AgeMedian = mean(DataFinal$AgeMedian),\n Pct_014 = mean(DataFinal$Pct_014),\n Pct_65P = mean(DataFinal$Pct_65P),\n Pct_MV = mean(DataFinal$Pct_MV)\n)\n\ndf$DistCBDkmX_Pct_FR <- df$DistCBDkm * df$Pct_FR\npred <- predict(modele6, newdata = df, se = TRUE)\ndf$pred <- pred$fit\ndf$pred_se <- pred$se.fit\ndf$lower <- df$pred - 1.96 * df$pred_se\ndf$upper <- df$pred + 1.96 * df$pred_se\n\nP1 <- ggplot(data = df) + \n geom_tile(aes(x = DistCBDkm, y = Pct_FR, fill = pred)) +\n stat_contour(aes(x = DistCBDkm, y = Pct_FR, z = pred), \n color = \"black\", linetype = \"dashed\") + \n geom_text_contour(aes(x = DistCBDkm, y = Pct_FR, z = pred), )+\n scale_fill_viridis(discrete = FALSE) + \n labs(x = \"Distance au centre-ville\", \n y = \"Pers à faible revenu (%)\",\n fill = \"\",\n subtitle = \"Prédiction\")\n\nP2 <- ggplot(data = df) + \n geom_tile(aes(x = DistCBDkm, y = Pct_FR, fill = lower)) +\n stat_contour(aes(x = DistCBDkm, y = Pct_FR, z = lower), \n color = \"black\", linetype = \"dashed\") + \n geom_text_contour(aes(x = DistCBDkm, y = Pct_FR, z = lower), )+\n scale_fill_viridis(discrete = FALSE)+ \n labs(x = \"Distance au centre-ville\", \n y = \"Pers à faible revenu (%)\",\n fill = \"\",\n subtitle = \"IC 2,5 %\")\n\nP3 <- ggplot(data = df) + \n geom_tile(aes(x = DistCBDkm, y = Pct_FR, fill = upper)) +\n stat_contour(aes(x = DistCBDkm, y = Pct_FR, z = upper), \n color = \"black\", linetype = \"dashed\") + \n geom_text_contour(aes(x = DistCBDkm, y = Pct_FR, z = upper), )+\n scale_fill_viridis(discrete = FALSE)+ \n labs(x = \"Distance au centre-ville\", \n y = \"Pers à faible revenu (%)\",\n fill = \"\",\n subtitle = \"IC 97,5 %\")\n\nggarrange(P1, P2, P3, common.legend = FALSE, ncol = 2, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Effet marginal de l'interaction entre deux variables continues](07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heatex-1.png){#fig-ModeleInteraction2heatex fig-align='center' width=95%}\n:::\n:::\n\n\n#### Effet marginal pour une variable d'interaction (une VI continue et une VI dichotomique) {#sec-07747}\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndf <- expand.grid(\n VilleMtl = c(0,1),\n Pct_FR = seq(0,95,1),\n HABHA = mean(DataFinal$HABHA),\n AgeMedian = mean(DataFinal$AgeMedian),\n Pct_014 = mean(DataFinal$Pct_014),\n Pct_65P = mean(DataFinal$Pct_65P),\n Pct_MV = mean(DataFinal$Pct_MV)\n)\ndf$VilleMtlX_Pct_FR <- df$VilleMtl * df$Pct_FR\nhead(df, n=5)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n VilleMtl Pct_FR HABHA AgeMedian Pct_014 Pct_65P Pct_MV VilleMtlX_Pct_FR\n1 0 0 87.7694 52.11494 15.89268 14.86761 20.96675 0\n2 1 0 87.7694 52.11494 15.89268 14.86761 20.96675 0\n3 0 1 87.7694 52.11494 15.89268 14.86761 20.96675 0\n4 1 1 87.7694 52.11494 15.89268 14.86761 20.96675 1\n5 0 2 87.7694 52.11494 15.89268 14.86761 20.96675 0\n```\n:::\n\n```{.r .cell-code}\npred <- predict(modele7, se = TRUE, newdata = df)\ndf$pred <- pred$fit\ndf$upper <- df$pred + 1.96*pred$se.fit\ndf$lower <- df$pred - 1.96*pred$se.fit\ndf$VilleMtl_str <- ifelse(df$VilleMtl==0,\"Autre municipalité\" , \"Ville de Montréal\")\nDataFinal$VilleMtl_str <- ifelse(DataFinal$VilleMtl==0,\"Autre municipalité\" , \"Ville de Montréal\")\ncols <- c(\"Autre municipalité\" =\"#1d3557\" ,\"Ville de Montréal\"=\"#e63946\")\n\nggplot(data = df) +\n geom_point(data = DataFinal, mapping = aes(x = Pct_FR, y = VegPct, color = VilleMtl_str),\n size = 0.2, alpha = 0.2)+\n geom_ribbon(aes(x = Pct_FR, ymin = lower, ymax = upper, group = VilleMtl_str),\n fill = rgb(0.1,0.1,0.1,0.4))+\n geom_path(aes(x = Pct_FR, y = pred, color = VilleMtl_str), size = 1) +\n scale_colour_manual(values = cols)+\n labs(x = \"Personnes à faible revenu (%)\",\n y = \"Densité de végétation prédite (%)\",\n color = \"\")\n```\n\n::: {.cell-output-display}\n![Graphique de l’effet marginal de l’interaction entre une variable quantitative et qualitative](07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaireeffectex-1.png){#fig-ModeleInteractionBinaireeffectex fig-align='center' width=70%}\n:::\n:::\n\n\n## Quiz de révision du chapitre {#sec-078}\n\n\n
\n\n\n\n
\n
Quels modèles sont imbriqués?
\n
Relisez au besoin la [section @sec-0732].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quelle mesure relative à la qualité d'ajustement du modèle indique la proportion de la variance de la variable dépendante expliquée par les variables indépendantes du modèle?
\n
Relisez au besoin la [section @sec-0731].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Le R2 ajusté permet de comparer des modèles avec des nombres de variables indépendantes et/ou d'observations différents
\n
Relisez au besoin le début de la [section @sec-0732].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Comment repérer les variables les plus importantes du modèle?
\n
Relisez au besoin la [section @sec-0742].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Comment évaluer la significativité des coefficients?
\n
Relisez au besoin la [section @sec-0743].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Pour un nombre très élevé d'observations, quelle affirmation est vraie pour les valeurs de t et de p?
\n
Relisez au besoin la [section @sec-0743).
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Une variable indépendante dont l'intervalle de confiance à 95 % du coefficient de régression est de [-15,06 ; 28,17] est-elle significatif au seuil de p = 0,05?
\n
Relisez au besoin la [section @sec-0744].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Comment poser un diagnostic sur un modèle de régression linéaire?
\n
Relisez le deuxième encadré à la [section @sec-076].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n\n
\n\n
\n
\n", + "supporting": [ + "07-regressionlineaire_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/07-regressionlineaire_files/figure-html/fig-DiaGraphCookLev-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-DiaGraphCookLev-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-DiaGraphCookLev-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-DiaGraphCookLev-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-DiaHomoscedasticite-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-DiaHomoscedasticite-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-DiaHomoscedasticite-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-DiaHomoscedasticite-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalDich-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalDich-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalDich-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalDich-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalDichCode-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalDichCode-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalDichCode-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalDichCode-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalPoly-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalPoly-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalPoly-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalPoly-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalPolyT-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalPolyT-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalPolyT-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalPolyT-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLog-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalVariableLog-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLog-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalVariableLog-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLogEtNon-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalVariableLogEtNon-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLogEtNon-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalVariableLogEtNon-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariablesContinues-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalVariablesContinues-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariablesContinues-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-EffetMarginalVariablesContinues-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-GraphCookLev-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-GraphCookLev-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-GraphCookLev-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-GraphCookLev-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-HomosComp-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-HomosComp-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-HomosComp-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-HomosComp-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-ModeleInteraction2heat-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-ModeleInteraction2heat-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat2-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-ModeleInteraction2heat2-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat2-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-ModeleInteraction2heat2-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heatex-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-ModeleInteraction2heatex-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heatex-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-ModeleInteraction2heatex-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaire-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-ModeleInteractionBinaire-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaire-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-ModeleInteractionBinaire-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaireeffectex-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-ModeleInteractionBinaireeffectex-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaireeffectex-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-ModeleInteractionBinaireeffectex-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-ResidusCompa-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-ResidusCompa-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-ResidusCompa-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-ResidusCompa-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-Titi-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-Titi-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-Titi-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-Titi-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-VerifierHomoscedasticite-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-VerifierHomoscedasticite-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-VerifierHomoscedasticite-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-VerifierHomoscedasticite-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidus-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-VerifierNormaliteResidus-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidus-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-VerifierNormaliteResidus-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidusDia-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-VerifierNormaliteResidusDia-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidusDia-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-VerifierNormaliteResidusDia-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/fig-calculRegPoly2-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/fig-calculRegPoly2-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/fig-calculRegPoly2-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/fig-calculRegPoly2-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/unnamed-chunk-45-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/unnamed-chunk-45-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/unnamed-chunk-45-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/unnamed-chunk-45-1.png diff --git a/docs/07-regressionlineaire_files/figure-html/unnamed-chunk-53-1.png b/.quarto/_freeze/07-regressionlineaire/figure-html/unnamed-chunk-53-1.png similarity index 100% rename from docs/07-regressionlineaire_files/figure-html/unnamed-chunk-53-1.png rename to .quarto/_freeze/07-regressionlineaire/figure-html/unnamed-chunk-53-1.png diff --git a/.quarto/_freeze/08-GLM/execute-results/html.json b/.quarto/_freeze/08-GLM/execute-results/html.json new file mode 100644 index 0000000..ae3532a --- /dev/null +++ b/.quarto/_freeze/08-GLM/execute-results/html.json @@ -0,0 +1,16 @@ +{ + "hash": "65f8ddcc537d0c1def07290749b7c0e1", + "result": { + "markdown": "# Régressions linéaires généralisées (GLM) {#sec-chap08}\n\nDans ce chapitre, nous présentons les modèles linéaires généralisés plus communément appelés GLM (*generalized linear models* en anglais). Il s’agit d’une extension directe du modèle de régression linéaire multiple (LM) basé sur la méthode des moindres carrés ordinaires, décrite dans le chapitre précédent. Pour aborder cette section sereinement, il est important d’avoir bien compris le concept de distribution présenté dans la [section @sec-024]. À la fin de cette section, vous serez en mesure de :\n\n* Comprendre la distinction entre un modèle LM classique et un GLM.\n* Identifier les composantes d’un GLM.\n*\tInterpréter les résultats d’un GLM.\n*\tEffectuer les diagnostics d’un GLM.\n\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\nDans ce chapitre, nous utilisons principalement les *packages* suivants : \n\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes.\n \n* Pour ajuster des modèles GLM :\n - `VGAM` et `gamlss` offrent tous les deux un très large choix de distributions et de fonctions de diagnostic, mais nécessitent souvent un peu plus de code.\n - `mgcv` offre moins de distributions que les deux précédents, mais est plus simple d'utilisation.\n\n * Pour analyser des modèles GLM :\n - `car` essentiellement pour la fonction `vif`.\n - `DHARMa` pour le diagnostic des résidus simulés.\n - `ROCR` et `caret` pour l'analyse de la qualité d'ajustement de modèles pour des variables qualitatives.\n - `AER` pour des tests de sur-dispersion.\n - `fitdistrplus` pour ajuster des distributions à des données.\n - `LaplacesDemon` pour manipuler certaines distributions.\n - `sandwich` pour générer des erreurs standards robustes pour le modèle GLM logistique binomial.\n:::\n:::\n\n## Qu'est qu'un modèle GLM? {#sec-081}\n\nNous avons vu qu’une régression linéaire multiple (LM) ne peut être appliquée que si la variable dépendante analysée est continue et si elle est normalement distribuée, une fois les variables indépendantes contrôlées. Il s’agit d’une limite très importante puisqu’elle ne peut être utilisée pour modéliser et prédire des variables binaires, multinomiales, de comptage, ordinales ou plus simplement des données anormalement distribuées. Une seconde limite importante des LM est que l’influence des variables indépendantes sur la variable dépendante ne peut être que linéaire. L’augmentation d’une unité de *X* conduit à une augmentation (ou diminution) de $\\beta$ (coefficient de régression) unités de *Y*, ce qui n’est pas toujours représentatif des phénomènes étudiés. Afin de dépasser ces contraintes, @GLMnelder ont proposé une extension des modèles LM, soit les modèles linéaires généralisés (GLM).\n\n### Formulation d'un GLM {#sec-0811}\n\nPuisqu’un modèle GLM est une extension des modèles LM, il est possible de traduire un modèle LM sous forme d’un GLM. Nous utilisons ce point de départ pour détailler la morphologie d’un GLM. Nous avons vu dans la section précédente qu’un modèle LM est formulé de la façon suivante (notation matricielle) :\n\n$$\nY = \\beta_0 + X\\beta + \\epsilon\n$$ {#eq-regmultiple5B}\n\n\nAvec $\\beta_0$ la constante (*intercept* en anglais) et $\\beta$ un vecteur de coefficients de régression pour les *k* variables indépendantes (*X*).\n\nD'après cette formule, nous modélisons la variable *Y* avec une équation de régression linéaire et un terme d’erreur que nous estimons être normalement distribué. Nous pouvons reformuler ce simple LM sous forme d’un GLM avec l’écriture suivante : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\beta X\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glm1}\n\n\nPas de panique! Cette écriture se lit comme suit : la variable *Y* est issue d’une distribution normale $(Y \\sim Normal)$ avec deux paramètres : $\\mu$ (sa moyenne) et $\\sigma$ (son écart-type). $\\mu$ varie en fonction d’une équation de régression linéaire ($\\beta_0 + \\beta X$) transformée par une fonction de lien *g* (détaillée plus loin). Dans ce cas précis, la fonction de lien est appelée fonction identitaire puisqu’elle n’applique aucune transformation ($g(x) = x$). Notez ici que le second paramètre de la distribution normale $\\sigma$ (paramètre de dispersion) a une valeur fixe et ne dépend donc pas des variables indépendantes à la différence de $\\mu$. Dans ce modèle spécifiquement, les paramètres à estimer sont $\\sigma$, $\\beta_0$ et $\\beta$.\nNotez que dans la notation traditionnelle, la fonction de lien est appliquée au paramètre modélisé. Il est possible de renverser cette notation en utilisant la réciproque ($g'$) de la fonction de lien ($g$) :\n\n$$\ng(\\mu) = \\beta_0 + \\beta X \\Longleftrightarrow \\mu = g'(\\beta_0 + \\beta X)\n\\text{ si : }g'(g(x)) = x\n$$ {#eq-glm2}\n\n\nDans un modèle GLM, la distribution attendue de la variable *Y* est déclarée de façon explicite ainsi que la façon dont nos variables indépendantes conditionnent cette distribution. Ici, c’est la moyenne ($\\mu$) de la distribution qui est modélisée, nous nous intéressons ainsi au changement moyen de *Y* provoqué par les variables *X*.\n\nAvec cet exemple, nous voyons les deux composantes supplémentaires d’un modèle GLM :\n\n*\tLa distribution supposée de la variable *Y* conditionnée par les variables *X* (ici, la distribution normale).\n\n*\tUne fonction de lien associant l’équation de régression formée par les variables indépendantes et un paramètre de la distribution retenue (ici, la fonction identitaire et le paramètre $\\mu$).\n\nNotez également que l’estimation des paramètres d’un modèle GLM (ici, $\\beta_0$, $\\beta X$ et $\\sigma$) ne se fait plus avec la méthode des moindres carrés ordinaires utilisée pour les modèles LM. À la place, la méthode par maximum de vraisemblance (*maximum likelihood*) est la plus souvent utilisée, mais certains *packages* utilisent également la méthode des moments (*method of moments*). Ces deux méthodes nécessitent des échantillons plus grands que la méthode des moindres carrés. Dans le cas spécifique d'un modèle GLM utilisant une distribution normale, la méthode des moindres carrés et la méthode par maximum de vraisemblance produisent les mêmes résultats.\n\n### Autres distributions et rôle de la fonction de lien {#sec-0812}\n\nÀ première vue, il est possible de se demander pourquoi ajouter ces deux éléments puisqu’ils ne font que complexifier le modèle. Pour mieux saisir la pertinence des GLM, prenons un exemple appliqué au cas d’une variable binaire. Admettons que nous souhaitons modéliser / prédire la probabilité qu’une personne à vélo décède lors d’une collision avec un véhicule motorisé. Notre variable dépendante est donc binaire (0 = survie, 1 = décès) et nous souhaitons la prédire avec trois variables continues que sont : la vitesse de déplacement du ou de la cycliste ($x_1$), la vitesse de déplacement du véhicule ($x_2$) et la masse du véhicule ($x_3$). Puisque la variable *Y* n’est pas continue, il serait absurde de supposer qu’elle est issue d’une distribution normale. Il serait plus logique de penser qu’elle provient d’une distribution de Bernoulli (pour rappel, une distribution de Bernoulli permet de modéliser un phénomène ayant deux issues possibles comme un lancer de pièce de monnaie ([section @sec-024]). Plus spécifiquement, nous pourrions formuler l’hypothèse que nos trois variables $x_1$, $x_2$ et $x_3$ influencent le paramètre *p* (la probabilité d’occurrence de l’évènement) d’une distribution de Bernoulli. À partir de ces premières hypothèses, nous pouvons écrire le modèle suivant : \n\n$$\n\\begin{aligned}\n&Y \\sim Bernoulli(p)\\\\\n&g(p) = \\beta_0 + \\beta X\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glm3}\n\n\nToutefois, le résultat n’est pas entièrement satisfaisant. En effet, *p* est une probabilité et, par nature, ce paramètre doit être compris entre 0 et 1 (entre 0 et 100 % de « chances de décès », ni plus ni moins). L’équation de régression que nous utilisons actuellement peut produire des résultats compris entre $-\\infty$ et $+\\infty$ pour *p* puisque rien ne contraint la somme $\\beta_0+ \\beta_1x_1+\\beta_2x_2+ \\beta_3x_3$ à être comprise entre 0 et 1. Il est possible de visualiser le problème soulevé par cette situation avec les figures suivantes. Admettons que nous avons observé une variable *Y* binaire et que nous savons qu’elle est influencée par une variable *X* qui, plus elle augmente, plus les chances que *Y* soit 1 augmentent (@fig-linearbinom).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Exemple de données issues d'une distribution de Bernoulli](08-GLM_files/figure-html/fig-linearbinom-1.png){#fig-linearbinom fig-align='center' width=70%}\n:::\n:::\n\n\nSi nous utilisons l’équation de régression actuelle, cela revient à trouver la droite la mieux ajustée passant dans ce nuage de points (@fig-linearbinom2).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Ajustement d'une droite de régression aux données issues d'une distribution de Bernoulli](08-GLM_files/figure-html/fig-linearbinom2-1.png){#fig-linearbinom2 fig-align='center' width=70%}\n:::\n:::\n\n\nCe modèle semble bien cerner l’influence positive de *X* sur *Y*, mais la droite est au final très éloignée de chaque point, indiquant un faible ajustement du modèle. De plus, la droite prédit des probabilités négatives lorsque *X* est inférieur à −2,5 et des probabilités supérieures à 1 quand *X* est supérieur à 1. Elle est donc loin de bien représenter les données.\n\nC’est ici qu’intervient la fonction de lien. La fonction identitaire que nous avons utilisée jusqu'ici n’est pas satisfaisante, nous devons la remplacer par une fonction qui conditionnera la somme $\\beta_0+ \\beta_1x_1+\\beta_2x_2+ \\beta_3x_3$ pour donner un résultat entre 0 et 1. Une candidate toute désignée est la fonction *sigmoidale*, plus souvent appelée la fonction *logistique*!\n\n$$\n\\begin{aligned}\n&Y \\sim Bernoulli(p)\\\\\n&S(p) = \\beta_0 + \\beta X\\\\\n&S(x) = \\frac{e^{x}}{e^x+1}\n\\end{aligned}\n$$ {#eq-glm4}\n\n\nLa fonction logistique prend la forme d’un *S*. Plus la valeur entrée dans la fonction est grande, plus le résultat produit par la fonction est proche de 1 et inversement. Si nous reprenons l’exemple précédent, nous obtenons le modèle illustré à la @fig-linearbinom3.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Utilisation de la fonction de lien logistique](08-GLM_files/figure-html/fig-linearbinom3-1.png){#fig-linearbinom3 fig-align='center' width=70%}\n:::\n:::\n\n\nUne fois cette fonction insérée dans le modèle, nous constatons qu’une augmentation de la somme $\\beta_0+ \\beta_1x_1+\\beta_2x_2+ \\beta_3x_3$ conduit à une augmentation de la probabilité *p* et inversement, et que cet effet est non linéaire. Nous avons donc maintenant un GLM permettant de prédire la probabilité d’un décès lors d’un accident en combinant une distribution et une fonction de lien adéquates.\n\n### Conditions d'application {#sec-0813}\n\nLa famille des GLM englobe de (très) nombreux modèles du fait de la diversité de distributions existantes et des fonctions de liens utilisables. Cependant, certaines combinaisons sont plus souvent utilisées que d’autres. Nous présentons donc dans les prochaines sections les modèles GLM les plus communs. Les conditions d’application varient d’un modèle à l’autre, il existe cependant quelques conditions d’application communes à tous ces modèles : \n\n*\tl’indépendance des observations (et donc des erreurs);\n\n*\tl’absence de valeurs aberrantes / fortement influentes;\n\n*\tl’absence de multicolinéarité excessive entre les variables indépendantes.\n\nCes trois conditions sont également valables pour les modèles LM tel qu'abordé dans le [chapitre @sec-chap07]. La distance de *Cook* peut ainsi être utilisée pour détecter les potentielles valeurs aberrantes et le facteur d’inflation de la variance (*VIF*) pour détecter la multicolinéarité.\nLes conditions d’application particulières sont détaillées dans les sections dédiées à chaque modèle.\n\n### Résidus et déviance {#sec-0814}\n\nDans la section sur la régression linéaire simple, nous avons présenté la notion de résidu, soit l’écart entre la valeur observée (réelle) de *Y* et la valeur prédite par le modèle. Pour un modèle GLM, ces résidus traditionnels (aussi appelés résidus naturels) ne sont pas très informatifs si la variable à modéliser est binaire, multinomiale ou même de comptage. Lorsque l’on travaille avec des GLM, nous préférons utiliser trois autres formes de résidus, soit les résidus de Pearson, les résidus de déviance et les résidus simulés.\n\n**Les résidus de Pearson** sont une forme ajustée des résidus classiques, obtenus par la division des résidus naturels par la racine carrée de la variance modélisée. Leur formule varie donc d’un modèle à l’autre puisque l’expression de la variance change en fonction de la distribution du modèle. Pour un modèle GLM gaussien, elle s'écrit :\n\n$$\nr_i = \\frac{y_i - \\mu_i}{\\sigma}\n$$ {#eq-glm5}\n\nPour un modèle GLM de Bernoulli, elle s'écrit : \n\n$$\nr_i = \\frac{y_i - p_i}{\\sqrt{p_i(1-p_i)}}\n$$ {#eq-glm6}\n\navec $\\mu_i$ et $p_i$ les prédictions du modèle pour l'observation *i*.\n\n**Les résidus de déviance** sont basés sur le concept de *likelihood* présenté dans la [section @sec-02adjdistrib]. Pour rappel, le *likelihood*, ou la vraisemblance d’un modèle, correspond à la probabilité conjointe d’avoir observé les données *Y* selon le modèle étudié. Pour des raisons mathématiques (voir [section @sec-02adjdistrib]), le *log likelihood* est plus souvent calculé. Plus cette valeur est forte, moins le modèle se trompe. Cette interprétation est donc inverse à celle des résidus classiques, c’est pourquoi le *log likelihood* est généralement multiplié par −2 pour retrouver une interprétation intuitive. Ainsi, pour chaque observation *i*, nous pouvons calculer :\n\n$$\nd_i = \\mbox{-2} \\times log(P(y_i|M_e))\n$$ {#eq-glm7}\n\n\navec $d_i$ le résidu de déviance et $P(y_i|M_e)$ la probabilité d’avoir observé la valeur $y_i$ selon le modèle étudié ($M_e$).\n\nLa somme de tous ces résidus est appelée la déviance totale du modèle.\n\n$$\nD(M_e) = \\sum_{i=1}^n \\mbox{-2} \\times log(P(y_i|M_e))\n$$ {#eq-glm8}\n\nIl s’agit donc d’une quantité représentant à quel point le modèle est erroné vis-à-vis des données. Notez qu’en tant que telle, la déviance n’a pas d’interprétation directe en revanche, elle est utilisée pour calculer des mesures d’ajustement des modèles GLM.\n\n**Les résidus simulés** sont une avancée récente dans le monde des GLM, ils fournissent une définition et une interprétation harmonisée des résidus pour l’ensemble des modèles GLM. Dans la section sur les LM ([section @sec-0722]), nous avons vu comment interpréter les graphiques des résidus pour détecter d’éventuels problèmes dans le modèle. Cependant, cette technique est bien plus compliquée à mettre en œuvre pour les GLM puisque la forme attendue des résidus varie en fonction de la distribution choisie pour modéliser *Y*. La façon la plus efficace de procéder est d’interpréter les graphiques des résidus simulés qui ont la particularité d’être **identiquement distribués, quel que soit le modèle GLM construit**. Ces résidus simulés sont compris entre 0 et 1 et sont calculés de la manière suivante :\n\n* À partir du modèle GLM construit, simuler *S* fois (généralement 1 000) une variable *Y’* avec autant d’observation (*n*) que *Y*. Cette variable simulée est une combinaison de la prédiction du modèle (coefficient et variables indépendantes) et de sa dispersion (variance). Ces simulations représentent des variations vraisemblables de la variable *Y* si le modèle est correctement spécifié. En d’autres termes, si le modèle représente bien le phénomène à l’origine de la variable *Y*, alors les simulations *Y’* issues du modèle devraient être proches de la variable *Y* originale. Pour une explication plus détaillée de ce que signifie simuler des données à partir d’un modèle, référez-vous au *bloc attention* intitulé *Distinction entre simulation et prédiction* dans la [section @sec-08152].\n\n* Pour chaque observation, nous obtenons ainsi *S* valeurs formant une distribution $Ds_i$, soit les valeurs simulées par le modèle pour cette observation.\n\n* Pour chacune de ces distributions, nous calculons la probabilité cumulative d’observer la vraie valeur $Y_i$ d'après la distribution $Ds_i$. Cette valeur est comprise entre 0 (toutes les valeurs simulées sont plus grandes que $Y_i$) et 1 (toutes les valeurs simulées sont inférieures à $Y_i$).\n\nSi le modèle est correctement spécifié, le résultat attendu est que la distribution de ces résidus est uniforme. En effet, il y a autant de chances que les simulations produisent des résultats supérieurs ou inférieurs à $Y_i$ si le modèle représente bien le phénomène [@RandomizedResid;@gelman2006data]. Si la distribution des résidus ne suit pas une loi uniforme, cela signifie que le modèle échoue à reproduire le phénomène à l’origine de *Y*, ce qui doit nous alerter sur sa pertinence.\n\n### Vérification l’ajustement {#sec-0815}\n\nIl existe trois façons de vérifier l’ajustement d’un modèle GLM : \n\n* utiliser des mesures d’ajustement (AIC, pseudo-R^2^, déviance expliquée, etc.);\n* comparer les distributions de la variable originale et celle des prédictions;\n* comparer les prédictions du modèle avec les valeurs originales.\n\nNotez d’emblée que vérifier la qualité d’ajustement d’un modèle (ajustement aux données originales) ne revient pas à vérifier la validité d’un modèle (respect des conditions d’application). Cependant, ces deux éléments sont généralement liés, car un modèle mal ajusté a peu de chances d’être valide et inversement.\n\n#### Mesures d'ajustement {#sec-08151}\n\nLes mesures d’ajustement sont des indicateurs plus ou moins arbitraires dont le principal intérêt est de faciliter la comparaison entre plusieurs modèles similaires. Il est nécessaire de les reporter, car dans certains cas, ils peuvent indiquer que des modèles sont très mal ajustés.\n\n##### Déviance expliquée {#sec-081511}\n\nRappelons que la déviance d’un modèle est une quantité représentant à quel point le modèle est erroné. L’objectif de l’indicateur de la déviance expliquée est d’estimer le pourcentage de la déviance maximale observable dans les données que le modèle est parvenu à expliquer. La déviance maximale observable dans les données est obtenue en utilisant la déviance totale du modèle nul (notée $M_n$, soit un modèle dans lequel aucune variable indépendante n’est ajoutée et ne comportant qu’une constante). Cette déviance est maximale puisqu’aucune variable indépendante n’est présente dans le modèle. Nous calculons ensuite le pourcentage de cette déviance totale qui a été contrôlée par le modèle étudié ($M_e$).\n\n$$\n\\mbox{déviance expliquée} = \\frac{D(M_n) - D(M_e)}{D(M_n)} = 1- \\frac{D(M_e)}{D(M_n)}\n$$ {#eq-glm9}\n\n\nIl s’agit donc d’un simple calcul de pourcentage entre la déviance maximale ($D(M_n)$) et la déviance expliquée par le modèle étudié ($D(M_n )-D(M_e)$). Cet indicateur est compris entre 0 et 1 : plus il est petit, plus la capacité de prédiction du modèle est faible. Attention, cet indicateur ne tient pas compte de la complexité du modèle. Ajouter une variable indépendante supplémentaire ne fait qu’augmenter la déviance expliquée, ce qui ne signifie pas que la complexification du modèle soit justifiée (**voir l'encadré sur le principe de parcimonie**, [section @sec-0732]).\n\n##### Pseudo-R^2^ {#sec-081512}\n\nLe R^2^ est une mesure d’ajustement représentant la part de la variance expliquée dans un modèle linéaire classique. Cette mesure n’est pas directement transposable au cas des GLM puisqu’ils peuvent être appliqués à des variables non continues et anormalement distribuées. Toutefois, il existe des mesures semblables appelées pseudo-R^2^, remplissant un rôle similaire. Notez cependant qu’ils ne peuvent pas être interprétés comme le R^2^ classique (d'une régression linéaire multiple) : **ils ne représentent pas la part de la variance expliquée**. Ils sont compris dans l’intervalle 0 et 1; plus leurs valeurs s’approchent de 1, plus le modèle est ajusté.\n\n\n::: {#tbl-pseudor2 .cell tbl-cap='Principaux pseudos-$R^2$'}\n::: {.cell-output-display}\n|Nom |Formule |Commentaire |\n|:---------------|:------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n|McFadden |$1-\\frac{loglike(M_e)}{loglike(M_n)}$ |Le rapport des *loglikelihood*, très proche de la déviance expliquée. |\n|McFadden ajusté |$1-\\frac{loglike(M_e)-K}{loglike(M_n)}$ |Version ajustée du R^2^ de McFadden tenant compte du nombre de paramètres (*k*) dans le modèle. |\n|Efron |$1-\\frac{\\sum_{i=1}^n(y_i-\\hat{y}_i)^2}{\\sum_{i=1}^n(y_i-\\bar{y}_i)^2}$ |Rapport entre la somme des résidus classiques au carré (numérateur) et de la somme des écarts au carré à la moyenne (dénominateur). Notez que pour un GLM gaussien, ce pseudo-R^2^ est identique au R^2^ classique. |\n|Cox & Snell |$1-e^{-\\frac{2}{n}({loglike(M_e) - loglike(M_n))}}$ |Transformation de la déviance afin de la mettre sur une échelle de 0 à 1 (mais ne pouvant atteindre exactement 1). |\n|Nagelkerke |$\\frac{1-e^{-\\frac{2}{n}({loglike(M_e) - loglike(M_n))}}}{1-e^{\\frac{2*loglike(M_n)}{n}}}$ |Ajustement du R^2^ de Cox et Snell pour que l’échelle de valeurs possibles puisse comporter 1 (attention, car les valeurs de ce R^2^ tendent à être toujours plus fortes que les autres). |\n:::\n:::\n\n\nEn dehors du pseudo-R^2^ de McFadden ajusté, aucune de ces mesures ne tient compte de la complexité du modèle. Il est cependant important de les reporter, car des valeurs très faibles indiquent vraisemblablement un modèle avec une moindre capacité informative. À l’inverse, des valeurs trop fortes pourraient indiquer un problème de surajustement (**voir encadré sur le principe de parcimonie**, [section @sec-0732]).\n\n##### Critère d'information d'Akaike (AIC) {#sec-081513}\n\nProbablement l’indicateur le plus répandu, sa formule est relativement simple, car il s’agit seulement d’un ajustement de la déviance :\n\n$$\nAIC = D(M_e) + 2K\n$$ {#eq-glm10}\n\n\navec *K* le nombre de paramètres à estimer dans le modèle (coefficients, paramètres de distribution, etc.). \n\nL'AIC n’a pas d’interprétation directe, mais permet de comparer deux modèles imbriqués ([section @sec-0732]). Plus l'AIC est petit, mieux le modèle est ajusté. L’idée derrière cet indicateur est relativement simple. Si la déviance *D* est grande, alors le modèle est mal ajusté. Ajouter des paramètres (des coefficients pour de nouvelles variables *X*, par exemple) ne peut que réduire *D*, mais cette réduction n’est pas forcément suffisamment grande pour justifier la complexification du modèle. L'AIC pondère donc *D* en lui ajoutant 2 fois le nombre de paramètres du modèle. Un modèle plus simple (avec moins de paramètres) parvenant à une même déviance est préférable à un modèle complexe (principe de parcimonie ou du rasoir d’Ockham), ce que permet de « quantifier » l'AIC. Attention, l'AIC **ne peut pas être utilisé pour comparer des modèles non imbriqués**. Notez que d’autres indicateurs similaires comme le WAIC, le BIC et le DIC sont utilisés dans un contexte d’inférence bayésienne. Retenez simplement que ces indicateurs sont conceptuellement proches du AIC et s’interprètent (à peu de choses près) de la même façon.\n\n#### Comparaison des distributions originales et prédites {#sec-08152}\n\nUne façon rapide de vérifier si un modèle est mal ajusté est de comparer la forme de la distribution originale et celle capturée par le modèle. L’idée est la suivante : si le modèle est bien ajusté aux données, il est possible de se servir de celui-ci pour générer de nouvelles données dont la distribution ressemble à celle des données originales. Si une différence importante est observable, alors les résultats du modèle ne sont pas fiables, car le modèle échoue à reproduire le phénomène étudié. Cette lecture graphique ne permet pas de s’assurer que le modèle est valide ou bien ajusté, mais simplement d’écarter rapidement les mauvais candidats. Notez que cette méthode ne s’applique pas lorsque la variable modélisée est binaire, multinomiale ou ordinale.\nLe graphique à réaliser comprend donc la distribution de la variable dépendante *Y* (représentée avec un histogramme ou un graphique de densité) et plusieurs distributions simulées à partir du modèle. Cette approche est plus répandue dans la statistique bayésienne, mais elle reste pertinente dans l’approche fréquentiste. Il est rare de reporter ces figures, mais elles doivent faire partie de votre diagnostic.\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Distinction entre simulation et prédiction**\n:::\n::: bloc_attention-body\nNotez ici que **simuler des données** à partir d’un modèle et **effectuer des prédictions** à partir d’un modèle sont deux opérations différentes. Prédire une valeur à partir d’un modèle revient simplement à appliquer son équation de régression à des données. Si nous réutilisons les mêmes données, la prédiction renvoie toujours le même résultat, il s’agit de la partie systématique (ou déterministe) du modèle. \nPour illustrer cela, admettons que nous avons ajusté un modèle GLM de type gaussien (fonction de lien identitaire) avec trois variables continues $X_1$, $X_2$ et $X_3$ et des coefficients respectifs de 0,5, 1,2 et 1,8 ainsi qu’une constante de 7. Nous pouvons utiliser ces valeurs pour prédire la valeur attendue de $Y$ quand $X_1= 3$, $X_2= 5$ et $X_3 = 5$ : \n\n$\\mbox{Prédiction} = \\mbox{7 + 3}\\times \\mbox{0,5 + 5}\\times \\mbox{1,2 + 5}\\times\\mbox{1,8 = 23,5}$\n\nEn revanche, simuler des données à partir d’un modèle revient à ajouter la dimension stochastique (aléatoire) du modèle. Puisque notre modèle GLM est gaussien, il comporte un paramètre $\\sigma$ (son écart-type); admettons, pour cet exemple, qu’il est de 1,2. Ainsi, avec les données précédentes, il est possible de simuler un ensemble infini de valeurs dont la distribution est la suivante : $Normal(\\mu = \\mbox{23,5, } \\sigma = \\mbox{1,2})$. 95 % du temps, ces valeurs simulées se trouveront dans l’intervalle $\\mbox{[21,1-25,9]}$ ($\\mu - 2\\sigma \\text{; } \\mu + 2\\sigma$), puisque cette distribution est normale. Les valeurs simulées dépendent donc de la distribution choisie pour le modèle et de l’ensemble des paramètres du modèle, pas seulement de l’équation de régression.\n\nSi vous aviez à ne retenir qu’une seule phrase de ce bloc, retenez que la prédiction ne se réfère qu’à la partie systématique du modèle (équation de régression), alors que la simulation incorpore la partie stochastique (aléatoire) de la distribution du modèle. Deux prédictions effectuées sur des données identiques donnent nécessairement des résultats identiques, ce qui n’est pas le cas pour la simulation.\n:::\n:::\n\n#### Comparaison des prédictions du modèle avec les valeurs originales {#sec-08153}\n\nLes prédictions d’un modèle devraient être proches des valeurs réelles observées. Si ce n’est pas le cas, alors le modèle n’est pas fiable et ses paramètres ne sont pas informatifs. Dépendamment de la nature de la variable modélisée (quantitative ou qualitative), plusieurs approches peuvent être utilisées pour quantifier l’écart entre valeurs réelles et valeurs prédites.\n\n##### Pour une variable quantitative {#sec-081531}\n\nLa mesure la plus couramment utilisée pour une variable quantitative est l’erreur moyenne quadratique (*Root Mean Square Error* – RMSE en anglais). \n\n$$\nRMSE = \\sqrt{\\frac{\\sum_{i=1}^n(y_i - \\hat{y_i})^2}{n}}\n$$ {#eq-glm11}\n\n\nIl s’agit de la racine carrée de la moyenne des écarts au carré entre valeurs réelles et prédites. Le RMSE est exprimé dans la même unité que la donnée originale et nous donne une indication sur l’erreur moyenne de la prédiction du modèle. Admettons, par exemple, que nous modélisons les niveaux de bruit environnemental en ville en décibels et que notre modèle de régression ait un RMSE de 3,5. Cela signifierait qu’en moyenne notre modèle se trompe de 3,5 décibels (erreur pouvant être négative ou positive), ce qui serait énorme (3 décibels correspondent à une multiplication par deux de l’intensité sonore) et nous amènerait à reconsidérer la fiabilité du modèle. Notez que l’usage d’une moyenne quadratique plutôt qu’une moyenne arithmétique permet de donner plus d’influence aux larges erreurs et donc de pénaliser davantage des modèles faisant parfois de grosses erreurs de prédiction. Le RMSE est donc très sensible à la présence de valeurs aberrantes.\nÀ la place de la moyenne quadratique, il est possible d’utiliser la simple moyenne arithmétique des valeurs absolues des erreurs (MAE). Cette mesure est cependant moins souvent utilisée :\n\n$$\nMAE = \\frac{\\sum_{i=1}^n|y_i - \\hat{y_i|}}{n}\n$$ {#eq-glm12}\n\n\nCes deux mesures peuvent être utilisées pour comparer la capacité de prédiction de deux modèles appliqués aux mêmes données, même s’ils ne sont pas imbriqués. Elles ne permettent cependant pas de prendre en compte la complexité du modèle. Un modèle plus complexe aura toujours des valeurs de RMSE et de MAE plus faibles.\n\n##### Pour une variable qualitative {#sec-081532}\n\nLorsque l’on modélise une variable qualitative, une erreur revient à prédire la mauvaise catégorie pour une observation. Il est ainsi possible de compter, pour un modèle, le nombre de bonnes et de mauvaises prédictions et d’organiser cette information dans une **matrice de confusion**. Cette dernière prend la forme suivante pour un modèle binaire : \n\n\n::: {#tbl-confusmat1 .cell tbl-cap='Exemple de matrice de confusion'}\n::: {.cell-output-display}\n|Valeur prédite / Valeur réelle | A| B| Total (%)|\n|:------------------------------|---------:|---------:|---------:|\n|A | 15| 3| 18 (41,9)|\n|B | 5| 20| 25 (51,1)|\n|Total (%) | 20 (46,6)| 23 (53,5)| 43 (81,4)|\n:::\n:::\n\n\nEn colonne du @tbl-confusmat1, nous avons les catégories observées et en ligne, les catégories prédites. La diagonale représente les prédictions correctes. Dans le cas présent, le modèle a bien catégorisé 35 (15 + 20) observations sur 43, soit une précision totale de 81,4 %; huit sont mal classifiées (18,6 %); cinq avec la modalité A ont été catégorisées comme des B, soit 20 % des A, et seules trois B ont été catégorisées comme des A (13 %).\n\nLa matrice ci-dessus (@tbl-confusmat1) ne comporte que deux catégories possibles puisque la variable *Y* modélisée est binaire. Il est facile d'étendre le concept de matrice de confusion au cas des variables avec plus de deux modalités (multinomiale). Le @tbl-confusmat2 est un exemple de matrice de confusion multinomiale.\n\n\n::: {#tbl-confusmat2 .cell tbl-cap='Exemple de matrice de confusion multinomiale'}\n::: {.cell-output-display}\n|Valeur prédite / Valeur réelle | A| B| C| D| Total (%)|\n|:------------------------------|---------:|---------:|---------:|---------:|---------:|\n|A | 15| 3| 1| 5| 24 (18,7)|\n|B | 5| 20| 2| 12| 39 (30,4)|\n|C | 2| 10| 25| 8| 45 (35,2)|\n|D | 1| 0| 5| 14| 20 (15,6)|\n|Total (%) | 23 (18,1)| 33 (25,7)| 33 (25,7)| 39 (30,5)| 128|\n:::\n:::\n\n\nTrois mesures pour chaque catégorie peuvent être utilisées pour déterminer la capacité de prédiction du modèle : \n\n* La précision (*precision* en anglais), soit le nombre de fois où une catégorie a été correctement prédite, divisé par le nombre de fois où la catégorie a été prédite.\n\n* Le rappel (*recall* en anglais), soit le nombre de fois où une catégorie a été correctement prédite divisé par le nombre de fois où elle se trouve dans les données originales.\n\n* Le score *F1* est la moyenne harmonique entre la précision et le rappel, soit :\n\n$$\n\\text{F1} = 2 \\times \\frac{\\text{précision} \\times \\text{rappel}}{\\text{précision} + \\text{rappel}}\n$$ {#eq-glm13}\n\nIl est possible de calculer les moyennes pondérées des différents indicateurs (macro-indicateurs) afin de disposer d’une valeur d’ensemble pour le modèle. La pondération est faite en fonction du nombre de cas observé de chaque catégorie; l’idée étant qu’il est moins grave d’avoir des indicateurs plus faibles pour des catégories moins fréquentes. Cependant, il est tout à fait possible que cette pondération ne soit pas souhaitable. C’est par exemple le cas dans de nombreuses études en santé portant sur des maladies rares où l’attention est concentrée sur ces catégories peu fréquentes.\n\nLe **coefficient de Kappa** (variant de 0 à 1) peut aussi être utilisé pour quantifier la fidélité générale de la prédiction du modèle. Il est calculé avec l'@eq-kappEq :\n\n$$\nk = \\frac{Pr(a)-Pr(e)}{1-Pr(e)}\n$$ {#eq-kappEq}\n\n\navec $Pr(a)$ la proportion d'accords entre les catégories observées et les catégories prédites, et $Pr(e)$ la probabilité d'un accord aléatoire entre les catégories observées et les catégories prédites (@eq-kappEq2).\n\n$$\nPr(e) = \\sum^{J}_{j=1} \\frac{Cnt_{prédit}(j)}{n\\times2} \\times \\frac{Cnt_{réel}(j)}{n\\times2}\n$$ {#eq-kappEq2}\n\n\navec *n* le nombre d'observations, $Cnt_{prédit}(j)$ le nombre de fois où le modèle prédit la catégorie *j* et $Cnt_{réel}(j)$ le nombre de fois où la catégorie *j* a été observée.\n\nPour l'interprétation du coefficient de Kappa, référez-vous au @tbl-Kappvals.\n\n\n::: {#tbl-Kappvals .cell tbl-cap='Inteprétation des valeurs du coefficient de Kappa'}\n::: {.cell-output-display}\n|K |Interprétation |\n|:-----------|:----------------------|\n|< 0 |Désaccord |\n|0 - 0,20 |Accord très faible |\n|0,21 - 0,40 |Accord faible |\n|0,41 - 0,60 |Accord modéré |\n|0,61 - 0,80 |Accord fort |\n|0,81 - 1 |Accord presque parfait |\n:::\n:::\n\n\nEnfin, un test statistique basé sur la distribution binomiale peut être utilisé pour vérifier que le modèle atteint un niveau de précision supérieur au seuil de non-information. Ce seuil correspond à la proportion de la modalité la plus présente dans le jeu de données. Dans la matrice de confusion utilisée dans le @tbl-Kappvals, ce seuil est de 30,5 % (catégorie D), ce qui signifie qu’un modèle prédisant tout le temps la catégorie D aurait une précision de 30,5 % pour cette catégorie. Il est donc nécessaire que notre modèle fasse mieux que ce seuil.\n\nDans le cas de la matrice de confusion du @tbl-confusmat2, nous obtenons donc les valeurs affichées dans le @tbl-confusIndic.\n\n\n::: {#tbl-confusIndic .cell tbl-cap='Indicateurs de qualité de prédiction'}\n::: {.cell-output-display}\n| | précision| rappel| F1|\n|:------------------------------|---------:|------:|----:|\n|A | 65,2| 31,3| 42,3|\n|B | 60,6| 25,6| 36,0|\n|C | 75,8| 27,8| 40,7|\n|D | 35,9| 35,0| 35,4|\n|macro | 57,8| 30,0| 38,2|\n|Kappa | 0,44| | |\n|Valeur de p (précision > NIR) | < 0,0001| | |\n:::\n:::\n\n\nÀ la lecture du @tbl-confusIndic, nous remarquons que : \n\n* La catégorie D est la moins bien prédite des quatre catégories (faible précision et faible rappel).\n\n* La catégorie C a une forte précision, mais un faible rappel, ce qui signifie que de nombreuses observations étant originalement des A, B ou D ont été prédites comme des C. Ce constat est également vrai pour la catégorie B.\n\n* Le coefficient de Kappa indique un accord modéré entre les valeurs originales et la prédiction.\n\n* La probabilité que la précision du modèle ne dépasse pas le seuil de non-information est inférieure à 0,001, indiquant que le modèle à une précision supérieure à ce seuil.\n\n\n### Comparaison de deux modèles GLM {#sec-0816}\n\nTel qu'abordé dans le chapitre sur les régressions linéaires classiques, il est courant de comparer plusieurs modèles imbriqués ([section @sec-0732]). Cette procédure permet de déterminer si l'ajout d'une ou de plusieurs variables contribue à significativement améliorer le modèle. Il est possible d'appliquer la même démarche aux GLM à l'aide du test de rapport de vraisemblance (*likelihood ratio test*). Le principe de base de ce test est de comparer le *likelihood* de deux modèles GLM imbriqués; la valeur de ce test se calcule avec l'équation suivante :\n\n$$\nLR = 2(loglik(M_2) - loglik(M_1))\n$$ {#eq-glm14}\n\n\navec $M_2$ un modèle reprenant toutes les variables du modèle $M_1$, impliquant donc que $loglik(M_2) >= loglik(M_1)$. \n\nAvec ce test, nous supposons que le modèle $M_2$, qui comporte plus de paramètres que le modèle $M_1$, devrait être mieux ajusté aux données. Si c'est bien le cas, la différence entre les *loglikelihood* de deux modèles devrait être supérieure à zéro. La valeur calculée *LR* suit une distribution du khi-deux avec un nombre de degrés de liberté égal au nombre de paramètres supplémentaires dans le modèle $M_2$ comparativement à $M_1$. Avec ces deux informations, il est possible de déterminer la valeur de *p* associée à ce test et de déterminer si $M_2$ est significativement mieux ajusté que $M_1$ aux données. Notez qu'il existe aussi deux autres tests (test de Wald et test de Lagrange) ayant la même fonction. Il s'agit, dans les deux cas, d'approximation du test de rapport des vraisemblances dont la puissance statistique est inférieure au test de rapport de vraisemblance [@NeymanLemma].\n\nDans les prochaines sections, nous décrivons les modèles GLM les plus couramment utilisés. Il en existe de nombreuses variantes que nous ne pouvons pas toutes décrire ici. L'objectif est de comprendre les rouages de ces modèles afin de pouvoir, en cas de besoin, transposer ces connaissances sur des modèles plus spécifiques. Pour faciliter la lecture de ces sections, nous vous proposons une carte d’identité de chacun des modèles présentés. Elles contiennent l’ensemble des informations pertinentes à retenir pour chaque modèle.\n\n\n## Modèles GLM pour des variables qualitatives {#sec-082}\n\nNous abordons en premier les principaux GLM utilisés pour modéliser des variables binaires, multinomiales et ordinales. Prenez bien le temps de saisir le fonctionnement du modèle logistique binomial, car il sert de base pour les trois autres modèles présentés.\n\n### Modèle logistique binomial {#sec-0821}\n\nLe modèle logistique binomial est une généralisation du modèle de Bernoulli que nous avons présenté dans l’introduction de cette section. Le modèle logistique binomiale couvre donc deux cas de figure : \n\n1.\tLa variable observée est binaire (0 ou 1). Dans ce cas, le modèle logistique binomiale devient un simple modèle de Bernoulli.\n\n2.\tLa variable observée est un comptage (nombre de réussites) et nous disposons d’une autre variable avec le nombre de réplications de l’expérience. Par exemple, pour chaque intersection d’un réseau routier, nous pourrions avoir le nombre de décès à vélo (variable *Y* de comptage) et le nombre de collisions vélo / automobile (variable quantifiant le nombre d’expériences, chaque collision étant une expérience).\nSpécifiquement, nous tentons de prédire le paramètre *p* de la distribution binomiale à l’aide de notre équation de régression et de la fonction logistique comme fonction de lien. Notez ici que cette fonction de lien influence directement l'interprétation des paramètres du modèle. Pour rappel, cette fonction est définie comme :\n\n$$\ng(x) = ln(\\frac{x}{1-x})\n$$\n\navec $ln$ étant le logarithme naturel.\n\nAu-delà de sa propriété mathématique assurant que $g(x) \\in \\mathopen[0,1\\mathclose]$, cette fonction offre une interprétation intéressante. La partie $\\frac{x}{1-x}$ est une cote et s'interprète en termes de chances d'observer un évènement. Par exemple, dans le cas des accidents de cyclistes, si la probabilité d'observer un décès suite à une collision est de 0,1, alors la cote de cet évènement est $\\frac{\\frac{1}{10}}{\\frac{9}{10}} = \\frac{1}{9}$ soit un contre neuf. Dans un modèle GLM logistique, les coefficients ajustés pour les variables indépendantes représentent des **logarithmes de rapport de cote**, car ils comparent les chances d'observer l'évènement (y = 1) en fonction des valeurs des variables indépendantes.\n\n\n::: {#tbl-binomidentity .cell tbl-cap='Carte d\\'identité du modèle logistique binomial'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:-------------------------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable binaire (0 ou 1) ou comptage de réussite à une expérience (ex : 3 réussites sur 5 expériences) |\n|Distribution utilisée |Binomiale |\n|Formulation |$Y \\sim Binomial(p)$ \\newline $g(p) = \\beta_0 + \\beta X$ \\newline $g(x) = log(\\frac{x}{1-x})$ |\n|Fonction de lien |Logistique |\n|Paramètre modélisé |p |\n|Paramètres à estimer |$\\beta_0$, $\\beta$ |\n|Conditions d'application |Non-séparation complète, absence de sur-dispersion ou de sous-dispersion |\n:::\n:::\n\n\n#### Interprétation des paramètres {#sec-08211}\n\nLes seuls paramètres à estimer du modèle sont les coefficients $\\beta$ et la constante $\\beta_0$. La fonction de lien logistique transforme la valeur de ces coefficients, en conséquence, **ils ne peuvent plus être interprétés directement**. $\\beta_0$ et $\\beta$ sont exprimés dans une unité particulière: des logarithmes de rapports de cote (*log odd ratio*). Le rapport de cote est relativement facile à interpréter contrairement à son logarithme. Pour l’obtenir, il suffit d’utiliser la fonction exponentielle (l’inverse de la fonction logarithme) pour passer des log rapports de cote à de simples rapports de cote.\nDonc si $exp(\\beta)$ est inférieur à 1, il réduit les chances d’observer l’évènement et inversement si $exp(\\beta)$ est supérieur à 1. \n\nPar exemple, admettons que nous ayons un coefficient $\\beta_1$ de 1,2 pour une variable $X_1$ dans une régression logistique. Il est nécessaire d'utiliser son exponentiel pour l'interpréter de façon intuitive. $exp\\mbox{(1,2)} = \\mbox{3,32}$, ce qui signifie que lorsque $X_1$ augmente d'une unité, les chances d'observer 1 plutôt que 0 comme valeur de *Y* sont multipliées par 3,32. Admettons maintenant que $\\beta_1$ vaille −1,2, nous calculons donc $exp\\mbox{(-1,2) = 0,30}$, ce qui signifie qu'à chaque augmentation d'une unité de $X_1$, les chances d'observer 1 plutôt que 0 comme valeur de *Y* sont multipliées par 0,30. En d'autres termes,les chances d'observer 1 plutôt que 0 sont divisées par 3,33 ($\\mbox{1}/\\mbox{0,30} = \\mbox{3,33}$), soit une diminution de 70 % ($\\mbox{1}-\\mbox{0,3} = \\mbox{0,7}$) des chances d'observer 1 plutôt que 0.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Les rapports de cotes**\n:::\n::: bloc_aller_loin-body\nLe rapport de cote ou rapport des chances est une mesure utilisée pour exprimer l’effet d’un facteur sur une probabilité. Il est très utilisé dans le domaine de la santé, mais aussi des paris. Prenons un exemple concret avec le port du casque à vélo. Si sur 100 accidents impliquant des cyclistes portant un casque, nous observons seulement 3 cas de blessures graves à la tête, contre 15 dans un second groupe de 100 cyclistes ne portant pas de casque, nous pouvons calculer le rapport de cote suivant : \n\n$$\n\\frac{p(1-q)}{q(1-p)} = \\frac{\\mbox{0,15} \\times (\\mbox{1}-\\mbox{0,03})}{\\mbox{0,03} \\times (\\mbox{1}-\\mbox{0,15})} = \\mbox{5,71}\n$$\n\navec *p* la probabilité d'observer le phénomène (ici la blessure grave à la tête) dans le groupe 1 (ici les cyclistes sans casque) et *q* la probabilité d'observer le phénomène dans le groupe 2 (ici les cyclistes avec un casque). Ce rapport de cote indique que les cyclistes sans casques ont 5,71 fois plus de risques de se blesser gravement à la tête lors d’un accident comparativement aux cyclistes portant un casque.\n:::\n:::\n\n#### Conditions d'application {#sec-08212}\n\nLa non-séparation complète signifie qu’aucune des variables *X* n'est, à elle seule, capable de parfaitement distinguer les deux catégories 0 et 1 de la variable *Y*. Dans un tel cas de figure, les algorithmes d’ajustement utilisés pour estimer les paramètres des modèles sont incapables de converger. Notez aussi l’absurdité de créer un modèle pour prédire une variable *Y* si une variable *X* est capable à elle seule de la prédire à coup sûr. Ce problème est appelé un effet de Hauck-Donner. Il est assez facile de le repérer, car la plupart du temps les fonctions de R signalent ce problème (message d'erreur sur la convergence). Sinon, des valeurs extrêmement élevées ou faibles pour certains rapports de cote peuvent aussi indiquer un effet de Hauck-Donner.\n\nLa sur-dispersion est un problème spécifique aux distributions n’ayant pas de paramètre de dispersion (binomiale, de Poisson, exponentielle, etc.), pour lesquelles la variance dépend directement de l'espérance. La sur-dispersion désigne une situation dans laquelle les résidus (ou erreurs) d'un modèle sont plus dispersés que ce que suppose la distribution utilisée. À l’inverse, il est aussi possible (mais rare) d’observer des cas de sous-dispersion (lorsque la dispersion des résidus est plus petite que ce que suppose la distribution choisie). Ce cas de figure se produit généralement lorsque le modèle parvient à réaliser une prédiction trop précise pour être crédible. Si vous rencontrez une forte sous-dispersion, cela signifie souvent que l’une de vos variables indépendantes provoque une séparation complète. La meilleure option, dans ce cas, est de supprimer la variable en question du modèle. La variance attendue d’une distribution binomiale est $nb \\times p \\times(1-p)$, soit le produit entre le nombre de tirages, la probabilité de réussite et la probabilité d'échec. À titre d'exemple, si nous considérons une distribution binomiale avec un seul tirage et 50 % de chances de réussite, sa variance serait : $1 \\times \\mbox{0,5} \\times \\mbox{(1}-\\mbox{0,5}) = \\mbox{0,25}$.\n\nPlusieurs raisons peuvent expliquer la présence de sur-dispersion dans un modèle : \n\n* il manque des variables importantes dans le modèle, conduisant à un mauvais ajustement et donc une sur-dispersion des erreurs;\n\n* les observations ne sont pas indépendantes, impliquant qu’une partie de la variance n’est pas contrôlée et augmente les erreurs;\n\n* la probabilité de succès de chaque expérience varie d’une répétition à l’autre (différentes distributions).\n\nLa conséquence directe de la sur-dispersion est la sous-estimation de la variance des coefficients de régression. En d’autres termes, la sur-dispersion conduit à sous-estimer notre incertitude quant aux coefficients obtenus et réduit les valeurs de *p* calculées pour ces coefficients. Les risques de trouver des résultats significatifs à cause des fluctuations d'échantillonnage augmentent.\n\nPour détecter une sur-dispersion ou une sous-dispersion dans un modèle logistique binomial, il est possible d'observer les résidus de déviance du modèle. Ces derniers sont supposés suivre une distribution du khi-deux avec *n−k* degrés de liberté (avec *n* le nombre d'observations et *k* le nombre de coefficients dans le modèle). Par conséquent, la somme des résidus de déviance d'un modèle logistique binomiale divisée par le nombre de degrés de liberté devrait être proche de 1. Une légère déviation (jusqu'à 0,15 au-dessus ou au-dessous de 1) n'est pas alarmante; au-delà, il est nécessaire d'ajuster le modèle.\n\nNotez que si la variable *Y* modélisée est exactement binaire (chaque expérience est indépendante et n'est composée que d'un seul tirage) et que le modèle utilise donc une distribution de Bernoulli, le test précédent pour détecter une éventuelle sur-dispersion n'est pas valide. @hilbe2009logistic parle de sur-dispersion implicite pour le modèle de Bernoulli et recommande notamment de toujours ajuster les erreurs standards des modèles utilisant des distributions de Bernoulli, binomiale et de Poisson. L'idée ici est d'éviter d'être trop optimiste face à l'incertitude du modèle sur les coefficients et de l'ajuster en conséquence. Pour cela, il est possible d'utiliser des quasi-distributions ou des estimateurs robustes [@zeileis2004econometric]. Notez que si le modèle ne souffre pas de sur ou sous-dispersion, ces ajustements produisent des résultats équivalents aux résultats non ajustés.\n\n#### Exemple appliqué dans R {#sec-08213}\n\n**Présentation des données**\n\nPour illustrer le modèle logistique binomial, nous utilisons ici un jeu de données proposé par l’Union européenne : [l’enquête de déplacement sur la demande pour des systèmes de transports innovants](https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/P82V9X). Pour cette enquête, un échantillon de 1 000 individus représentatifs de la population a été constitué dans chacun des 26 États membres de l’UE, soit un total de 26 000 observations. Pour chaque individu, plusieurs informations ont été collectées relatives à la catégorie socioprofessionnelle, le mode de transport le plus fréquent, le temps du trajet de son déplacement le plus fréquent et son niveau de sensibilité à la cause environnementale. Nous modélisons ici la probabilité qu’un individu déclare utiliser le plus fréquemment le vélo comme moyen de transport. Les variables explicatives sont résumées au @tbl-binomdata. Il existe bien évidemment un grand nombre de facteurs individuels qui influence la prise de décision sur le mode de transport. Les résultats de ce modèle ne doivent donc pas être pris avec un grand sérieux; il est uniquement construit à des fins pédagogiques, sans cadre conceptuel solide.\n\n\n::: {#tbl-binomdata .cell tbl-cap='Variables indépendantes utilisées pour prédire le mode de transport le plus utilisé'}\n::: {.cell-output-display}\n|Nom de la variable |Signification |Type de variable |Mesure |\n|:------------------|:----------------------------------------------------------|:---------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n|Pays |Pays de résidence |Variable multinomiale |Le nom d’un des 26 pays membres de l’UE |\n|Sexe |Sexe biologique |Variable binaire |Homme ou femme |\n|Age |Âge biologique |Variable continue |L’âge en nombre d’années variant de 16 à 84 ans dans le jeu de données |\n|Education |Niveau d’éducation maximum atteint |Variable multinomiale |Premier cycle, secondaire inférieur (classes supérieures de l’école élémentaire), secondaire, troisième cycle |\n|StatutEmploi |Employé ou non |Variable binaire |Employé ou non |\n|Revenu |Niveau de revenu autodéclaré |Variable multinomiale |Très faible revenu, faible revenu, revenu moyen, revenu élevé, revenu très élevé, sans reponse |\n|Residence |Lieu de résidence |Variable multinomiale |Zone rurale, petite ou moyenne ville (moins de 250 000 habitants), grande ville (entre 250 000 et 1 million d’habitants) , aire métropolitaine (plus d’un million d’habitants) |\n|Duree |Durée du voyage le plus fréquent autodéclarée (en minutes) |Variable continue |Nombre de minutes |\n|ConsEnv |Préoccupation environnementale |Variable ordinale |Échelle de Likert de 1 à 10 |\n:::\n:::\n\n\n**Vérification des conditions d'application**\n\nLa première étape de la vérification des conditions d'application est de calculer les valeurs du facteur d'inflation de variance (VIF) pour s'assurer de l'absence de multicolinéarité trop forte entre les variables indépendantes. L'ensemble des valeurs de VIF sont inférieures à 5, indiquant l'absence de multicolinéarité excessive dans le modèle. \n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(car)\n# Chargement des données\ndfenquete <- read.csv(\"data/glm/enquete_transport_UE.csv\", encoding = 'UTF-8')\ndfenquete$Pays <- relevel(as.factor(dfenquete$Pays), ref = \"Allemagne\")\n# Vérification du VIF\nmodel1 <- glm(y ~\n Pays + Sexe + Age + Education + StatutEmploi + Revenu +\n Residence + Duree + ConsEnv,\n family = binomial(link=\"logit\"),\n data = dfenquete\n)\nvif(model1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n GVIF Df GVIF^(1/(2*Df))\nPays 1.794797 27 1.010890\nSexe 1.028618 1 1.014208\nAge 1.060256 1 1.029687\nEducation 1.428872 3 1.061285\nStatutEmploi 1.151879 1 1.073256\nRevenu 1.220934 5 1.020162\nResidence 1.130526 3 1.020658\nDuree 1.042638 1 1.021096\nConsEnv 1.090987 1 1.044503\n```\n:::\n:::\n\n\nLa seconde étape de vérification est le calcul des distances de Cook et l'identification d'éventuelles valeurs aberrantes (@fig-cookdistGLMbinom).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Calcul et représentation des distances de Cook\ncookd <- data.frame(\n dist = cooks.distance(model1),\n oid = 1:nrow(dfenquete)\n)\nggplot(cookd) + \n geom_point(aes(x = oid, y = dist ), color = rgb(0.1,0.1,0.1,0.4), size = 1)+\n geom_hline(yintercept = 0.002, color = \"red\")+\n labs(x = \"observations\", y = \"distance de Cook\") + \n theme(axis.text.x = element_blank(),\n axis.ticks.x = element_blank())\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle binomial avec toutes les observations](08-GLM_files/figure-html/fig-cookdistGLMbinom-1.png){#fig-cookdistGLMbinom fig-align='center' width=60%}\n:::\n:::\n\n\nLe calcul de la distance de Cook révèle un ensemble d'observations se démarquant nettement des autres (délimitées dans la @fig-cookdistGLMbinom) par la ligne rouge). Nous les isolons dans un premier temps pour les analyser.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Isoler les observations avec de très fortes valeurs de Cook\n# valeur seuil choisie : 0,002\ncas_etranges <- subset(dfenquete, cookd$dist>=0.002)\ncat(nrow(cas_etranges),'observations se démarquant dans le modèle')\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n19 observations se démarquant dans le modèle\n```\n:::\n\n```{.r .cell-code}\nprint(cas_etranges)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n X y Pays Sexe Age Education Statut_emploi\n7660 7660 1 Slovaquie homme 50 universite Employed\n25150 25150 1 Malte homme 16 secondaire Not Employed\n25227 25227 1 Malte femme 53 secondaire inferieur Not Employed\n25309 25309 1 Malte femme 32 secondaire Employed\n25322 25322 1 Malte homme 38 universite Employed\n25536 25536 1 Malte homme 27 universite Employed\n25541 25541 1 Malte homme 38 secondaire inferieur Employed\n25549 25549 1 Malte homme 31 universite Employed\n25690 25690 1 Luxembourg homme 32 universite Employed\n26190 26190 1 Chypre homme 24 secondaire Not Employed\n26201 26201 1 Chypre homme 25 secondaire Employed\n26244 26244 1 Chypre homme 32 secondaire Employed\n26269 26269 1 Chypre homme 60 secondaire Not Employed\n26303 26303 1 Chypre homme 59 secondaire Not Employed\n26393 26393 1 Chypre homme 30 premier cycle Employed\n26444 26444 1 Chypre femme 52 universite Employed\n26516 26516 1 Chypre homme 21 universite Not Employed\n26549 26549 1 Chypre homme 28 universite Employed\n26600 26600 1 Chypre homme 36 secondaire Employed\n Revenu Residence Duree mode_pref StatutEmploi ConsEnv\n7660 moyen zone rurale 775 velo employe 7\n25150 moyen zone rurale 15 velo sans emploi 3\n25227 moyen zone rurale 45 marche sans emploi 5\n25309 moyen petite-moyenne ville 25 marche employe 4\n25322 eleve zone rurale 30 marche employe 10\n25536 tres eleve petite-moyenne ville 14 velo employe 10\n25541 moyen zone rurale 5 marche employe 8\n25549 sans reponse petite-moyenne ville 60 velo employe 10\n25690 tres eleve petite-moyenne ville 720 velo employe 6\n26190 moyen grande ville 20 velo sans emploi 5\n26201 faible zone rurale 20 velo employe 5\n26244 tres faible petite-moyenne ville 18 velo employe 4\n26269 moyen petite-moyenne ville 5 velo sans emploi 7\n26303 moyen zone rurale 7 velo sans emploi 8\n26393 tres eleve petite-moyenne ville 61 velo employe 5\n26444 eleve petite-moyenne ville 120 velo employe 3\n26516 moyen petite-moyenne ville 25 velo sans emploi 8\n26549 tres faible petite-moyenne ville 15 velo employe 2\n26600 moyen petite-moyenne ville 8 velo employe 1\n```\n:::\n:::\n\n\nÀ la lecture des valeurs pour ces 19 cas étranges, nous remarquons que la plupart des observations proviennent de Malte et de Chypre. Ces deux petites îles constituent des cas particuliers en Europe et devraient vraisemblablement faire l'objet d'une analyse séparée. Nous décidons donc de les retirer du jeu de données. Deux autres observations étranges sont observables en Slovaquie et au Luxembourg. Dans les deux cas, les répondants ont renseigné des temps de trajet fantaisistes de respectivement 775 et 720 minutes. Nous les retirons donc également de l'analyse.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Retirer les observations aberrantes\ndfenquete2 <- subset(dfenquete, (dfenquete$Pays %in% c(\"Malte\", \"Chypre\")) == F & \n dfenquete$Duree < 400)\n# Réajuster le modèle\nmodel2 <- glm(y ~\n Pays + Sexe + Age + Education + StatutEmploi + Revenu +\n Residence + Duree + ConsEnv,\n family = binomial(link=\"logit\"),\n data = dfenquete2)\n# Recalculer la distance de Cook\ncookd <- data.frame(\n dist = cooks.distance(model2),\n oid = 1:nrow(dfenquete2)\n)\nggplot(cookd) + \n geom_point(aes(x = oid, y = dist ), color = rgb(0.1,0.1,0.1,0.4), size = 1)+\n labs(x = \"observations\", y = \"distance de Cook\") + \n theme(axis.text.x = element_blank(),\n axis.ticks.x = element_blank())\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle binomial sans les valeurs aberrantes](08-GLM_files/figure-html/fig-cookdistGLMbinom2-1.png){#fig-cookdistGLMbinom2 fig-align='center' width=60%}\n:::\n:::\n\n\nAprès avoir retiré ces valeurs aberrantes, nous n'observons plus de nouveaux cas singuliers avec les distances de Cook (@fig-cookdistGLMbinom2).\n\nLa prochaine étape de vérification des conditions d'application est l'analyse des résidus simulés. Nous commençons donc par calculer ces résidus et afficher leur histogramme (@fig-residsimbinomHistoUnif).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(DHARMa)\n# Extraire les probabilités prédites par le modèle\nprobs <- predict(model2, type = \"response\")\n# Calculer 1000 simulations a partir du modele ajuste\nsims <- lapply(1:length(probs), function(i){\n p <- probs[[i]]\n vals <- rbinom(n = 1000, size = 1, prob = p)\n})\nmatsim <- do.call(rbind, sims)\n# Utiliser le package DHARMa pour calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = matsim, \n observedResponse = dfenquete2$y,\n fittedPredictedResponse = probs,\n integerResponse = TRUE)\nggplot()+\n geom_histogram(aes(x = residuals(sim_res)),\n bins = 30, fill = \"white\", color = rgb(0.3,0.3,0.3))+\n labs(x = \"résidus simulés\", y = \"fréquence\")\n```\n\n::: {.cell-output-display}\n![Distribution des résidus simulés pour le modèle binomial](08-GLM_files/figure-html/fig-residsimbinomHistoUnif-1.png){#fig-residsimbinomHistoUnif fig-align='center' width=60%}\n:::\n:::\n\n\nL'histogramme indique clairement que les résidus simulés suivent une distribution uniforme (@fig-residsimbinomHistoUnif). Il est possible d'aller plus loin dans le diagnostic en utilisant la fonction `plot` sur l'objet `sim_res`. La partie de droite de la figure ainsi obtenue (@fig-residsimbinom) est un diagramme de quantiles-quantiles (ou Q-Q plot). Les points du graphique sont supposés suivre une ligne droite matérialisée par la ligne rouge. Une déviation de cette ligne indique un éloignement des résidus de leur distribution attendue. Trois tests sont également réalisés par la fonction :\n\n* Le premier (Test de Kolmogorov-Smirnov, *KS test*) permet de tester si les points dévient significativement de la ligne droite. Dans notre cas, la valeur de *p* n'est pas significative, indiquant que les résidus ne dévient pas de la distribution uniforme.\n\n* Le second test permet de vérifier la présence de sur ou sous-dispersion. Dans notre cas, ce test n'est pas significatif, n'indiquant aucun problème de sur-dispersion ou de sous-dispersion.\n\n* Le dernier test permet de vérifier si des valeurs aberrantes sont présentes dans les résidus. Une valeur non significative indique une absence de valeurs aberrantes.\n\nLe second graphique permet de comparer les résidus et les valeurs prédites. L'idéal est donc d'observer une ligne droite horizontale au milieu du graphique qui indiquerait une absence de relation entre les valeurs prédites et les résidus (ce que nous observons bien ici).\n\n\n::: {.cell}\n\n```{.r .cell-code}\nplot(sim_res)\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Diagnostic des résidus simulés par le package DHARMa](images/Chap08/fig-residsimbinom.png){#fig-residsimbinom fig-align='center' width=80%}\n:::\n:::\n\n\n\nL'analyse approfondie des résidus nous permet donc de conclure que le modèle respecte les conditions d'application et que nous pouvons passer à la vérification de la qualité d'ajustement du modèle.\n\n**Vérification de la qualité d'ajustement**\n\nPour calculer les différents R^2^ d'un modèle GLM, nous proposons la fonction suivante :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nrsqs <- function(loglike.full, loglike.null, full.deviance, null.deviance, nb.params, n){\n # Calcul de la déviance expliquée\n explained_dev <- 1-(full.deviance / null.deviance)\n K <- nb.params\n # R2 de McFadden ajusté\n r2_faddenadj <- 1- (loglike.full - K) / loglike.null\n Lm <- loglike.full\n Ln <- loglike.null\n # R2 de Cox and Snell\n Rcs <- 1 - exp((-2/n) * (Lm-Ln))\n # R2 de Nagelkerke\n Rn <- Rcs / (1-exp(2*Ln/n))\n return(\n list(\"deviance expliquee\" = explained_dev,\n \"McFadden ajuste\" = r2_faddenadj,\n \"Cox and Snell\" = Rcs,\n \"Nagelkerke\" = Rn\n )\n )\n}\n```\n:::\n\n\nNous l'utilisons pour l'ensemble des modèles GLM de ce chapitre. Dans le cas du modèle binomial, nous obtenons : \n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Ajuster un modele null avec seulement une constante\nmodel2.null <- glm(y ~1,\n family = binomial(link=\"logit\"),\n data = dfenquete2)\n# Calculer les R2\nrsqs(loglike.full = as.numeric(logLik(model2)), # loglikelihood du modèle complet\n loglike.null = as.numeric(logLik(model2.null)), # loglikelihood du modèle nul\n full.deviance = deviance(model2), # déviance du modèle complet\n null.deviance = deviance(model2.null), # déviance du modèle nul\n nb.params = model2$rank, # nombre de paramètres dans le modèle\n n = nrow(dfenquete2) # nombre d'observations\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n$`deviance expliquee`\n[1] 0.0876057\n\n$`McFadden ajuste`\n[1] 0.08357379\n\n$`Cox and Snell`\n[1] 0.0689509\n\n$Nagelkerke\n[1] 0.1236597\n```\n:::\n:::\n\n\nLa déviance expliquée par le modèle est de 8,8 %, les pseudos R^2^ de McFadden (ajusté), d'Efron et de Nagelkerke sont respectivement 0,084, 0,069 et 0,124. Toutes ces valeurs sont relativement faibles et indiquent qu'une large partie de la variabilité de *Y* reste inexpliquée.\n\nPour vérifier la qualité de prédiction du modèle, nous devons comparer les catégories prédites et les catégories réelles de notre variable dépendante et construire une matrice de confusion. Cependant, un modèle GLM binomial prédit **la probabilité d’appartenance au groupe 1** (ici les personnes utilisant le vélo pour effectuer leur déplacement le plus fréquent). Pour convertir ces probabilités prédites en catégories prédites, il faut choisir un seuil de probabilité au-delà duquel nous considérons que la valeur attendue est 1 (cycliste) plutôt que 0 (autre). Un exemple naïf serait de prendre le seuil 0,5, ce qui signifierait que si le modèle prédit qu’une observation a au moins 50 % de chance d’être une personne à vélo, alors nous l’attribuons à cette catégorie. Cependant, cette méthode est rarement optimale; il est donc plus judicieux de fixer le seuil de probabilité en trouvant le point d’équilibre entre la sensibilité (proportion de 1 correctement identifiés) et la spécificité (proportion de 0 correctement identifiés). Ce point d’équilibre est identifiable graphiquement en calculant la spécificité et la sensibilité de la prédiction selon toutes les valeurs possibles du seuil.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ROCR)\n# Obtention des prédictions du modèle\nprob <- predict(model2, type = \"response\")\n# Calcul de la sensibilité et de la spécificité (package ROCR)\npredictions <- prediction(prob, dfenquete2$y)\nsens <- data.frame(x = unlist(ROCR::performance(predictions, \"sens\")@x.values),\n y = unlist(ROCR::performance(predictions, \"sens\")@y.values))\nspec <- data.frame(x = unlist(ROCR::performance(predictions, \"spec\")@x.values),\n y = unlist(ROCR::performance(predictions, \"spec\")@y.values))\n# Trouver numériquement la valeur seuil (minimiser la différence absolue\n# entre sensibilité et spécificité)\nreal <- dfenquete2$y\nfind_cutoff <- function(seuil){\n pred <- ifelse(prob>seuil,1,0)\n sensi <- sum(real==1 & pred==1) / sum(real==1)\n spec <- sum(real==0 & pred==0) / sum(real==0)\n return(abs(sensi-spec))\n}\nprob_seuil <- optimize(find_cutoff, interval = c(0,1), maximum = FALSE)$minimum\ncat(\"Le seuil de probabilité à retenir équilibrant\",\n \"la sensibilité et la spécificité est de\", prob_seuil)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLe seuil de probabilité à retenir équilibrant la sensibilité et la spécificité est de 0.14785\n```\n:::\n\n```{.r .cell-code}\n# Affichage du graphique\nggplot() +\n geom_line(data = sens, mapping = aes(x = x, y = y)) +\n geom_line(data = spec, mapping = aes(x = x, y = y, col=\"red\")) +\n scale_y_continuous(sec.axis = sec_axis(~., name = \"Spécificité\")) +\n labs(x = \"Seuil de probabilité\", y = \"Sensibilité\") +\n geom_vline(xintercept = prob_seuil, color = \"black\", linetype = \"dashed\") + \n annotate(geom = \"text\", x = prob_seuil, y = 0.01, label = round(prob_seuil,3))+\n theme(axis.title.y.right = element_text(colour = \"red\"), legend.position = \"none\")\n```\n\n::: {.cell-output-display}\n![Point d'équilibre entre sensibilité et spécificité](08-GLM_files/figure-html/fig-equlibresensispeci-1.png){#fig-equlibresensispeci fig-align='center' width=80%}\n:::\n:::\n\n\nNous constatons à la @fig-equlibresensispeci que si la valeur du seuil est 0 %, alors la prédiction a une sensibilité parfaite (le modèle prédit toujours 1, donc tous les 1 sont détectés); à l’inverse, si le seuil choisi est 100 %, alors la prédiction à une spécificité parfaite (le modèle prédit toujours 0, donc tous les 0 sont détectés). Dans notre cas, la valeur d’équilibre est d'environ 0,148, donc si le modèle prédit une probabilité au moins égale à 14,8 % qu’un individu utilise le vélo pour son déplacement le plus fréquent, nous devons l’attribuer à la catégorie *cycliste*. Avec ce seuil, nous pouvons convertir les probabilités prédites en classes prédites et construire notre matrice de confusion.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(caret) # pour la matrice de confusion\n# Calcul des catégories prédites\nypred <- ifelse(predict(model2, type = \"response\")>0.148,1,0)\ninfo <- confusionMatrix(as.factor(dfenquete2$y), as.factor(ypred))\n# Affichage des valeurs brutes de la matrice de confusion\nprint(info)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nConfusion Matrix and Statistics\n\n Reference\nPrediction 0 1\n 0 14355 7576\n 1 1251 2365\n \n Accuracy : 0.6545 \n 95% CI : (0.6486, 0.6603)\n No Information Rate : 0.6109 \n P-Value [Acc > NIR] : < 2.2e-16 \n \n Kappa : 0.1783 \n \n Mcnemar's Test P-Value : < 2.2e-16 \n \n Sensitivity : 0.9198 \n Specificity : 0.2379 \n Pos Pred Value : 0.6546 \n Neg Pred Value : 0.6540 \n Prevalence : 0.6109 \n Detection Rate : 0.5619 \n Detection Prevalence : 0.8585 \n Balanced Accuracy : 0.5789 \n \n 'Positive' Class : 0 \n \n```\n:::\n:::\n\n\nLes résultats proposés par le *package* `caret` sont exhaustifs; nous vous proposons ici une façon de les présenter dans deux tableaux : l'un présente la matrice de confusion (@tbl-confusmatbinom) et l'autre, les indicateurs de qualité de prédiction (@tbl-confusmatbinom2).\n\n\n::: {#tbl-confusmatbinom .cell tbl-cap='Matrice de confusion pour le modèle binomial'}\n::: {.cell-output-display}\n| | | 0 (réel)| 1 (réel)| Total| %|\n|:--|:----------|--------:|--------:|-----:|----:|\n|0 |0 (prédit) | 14355| 7576| 21931| 85.8|\n|1 |1 (prédit) | 1251| 2365| 3616| 14.2|\n| |Total | 15606| 9941| 25547| |\n| |% | 61.1| 38.9| | |\n:::\n:::\n\n\nD’après ces indicateurs, nous constatons que le modèle a une capacité de prédiction relativement faible, mais tout de même significativement supérieure au seuil de non-information. La valeur de rappel pour la catégorie 1 (cycliste) est faible, indiquant que le modèle a manqué un nombre important de cyclistes lors de sa prédiction. \n\n\n::: {#tbl-confusmatbinom2 .cell tbl-cap='Matrice de confusion pour le modèle binomial'}\n::: {.cell-output-display}\n| | | Précision| Rappel| F1|\n|:------------|:------------------------------|---------:|------:|----:|\n|0 |0 | 0.65| 0.92| 0.76|\n|1 |1 | 0.65| 0.24| 0.35|\n| | | | | |\n|macro_scores |macro | 0.65| 0.65| 0.6|\n| |Kappa | 0.18| | |\n| |Valeur de p (précision > NIR) | < 0,0001| | |\n:::\n:::\n\n\n**Interprétation des résultats du modèle**\n\nL'interprétation des résultats d'un modèle binomial passe par la lecture des rapports de cotes (exponentiel des coefficients) et de leurs intervalles de confiance. Nous commençons donc par calculer la version robuste des erreurs standards des coefficients.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(dplyr)\nlibrary(sandwich) # pour calculer les erreurs standards robustes\ncovModel2 <- vcovHC(model2, type = \"HC0\") # méthode HC0, basée sur les résidus\nstdErrRobuste <- sqrt(diag(covModel2)) # extraire la diagonale\n# Extraction des coefficients\ncoeffs <- model2$coefficients\n# Recalcul des scores Z\nzvalRobuste <- coeffs / stdErrRobuste\n# Recalcul des valeurs de P\npvalRobuste <- 2 * pnorm(abs(zvalRobuste), lower.tail = FALSE)\n# Calcul des rapports de cote\noddRatio <- exp(coeffs)\n# Calcul des intervalles de confiance à 95 % des rapports de cote\nlowerBound <- exp(coeffs - 1.96 * stdErrRobuste)\nupperBound <- exp(coeffs + 1.96 * stdErrRobuste)\n# Étoiles pour les valeurs de p\nstarsp <- case_when(pvalRobuste <= 0.001 ~ \"***\",\n pvalRobuste > 0.001 & pvalRobuste <= 0.01 ~ \"**\",\n pvalRobuste > 0.01 & pvalRobuste <= 0.05 ~ \"*\",\n pvalRobuste > 0.05 & pvalRobuste <= 0.1 ~ \".\",\n TRUE ~ \"\"\n )\n# Compilation des résultats dans un tableau\ntableau_binom <- data.frame(\n coefficients = coeffs,\n rap.cote = oddRatio,\n err.std = stdErrRobuste,\n score.z = zvalRobuste,\n p.val = pvalRobuste,\n rap.cote.2.5 = lowerBound,\n rap.cote.97.5 = upperBound,\n sign = starsp\n)\n```\n:::\n\n\nConsidérant que la variable *Pays* a 24 modalités, il est plus judicieux de présenter ses 23 rapports de cotes sous forme d’un graphique. Nous avons choisi l’Allemagne comme catégorie de référence puisqu’elle fait partie des pays avec une importante part modale pour le vélo sans pour autant constituer un cas extrême comme le Danemark.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Isoler les ligne du tableau récapitualtif pour les pays\npaysdf <- subset(tableau_binom, grepl(\"Pays\", row.names(tableau_binom), fixed = TRUE))\n#paysdf$Pays <- gsub(\"Pays\" , \"\", row.names(paysdf), fixed = TRUE)\npaysdf$Pays <- substr(row.names(paysdf), 5, nchar(row.names(paysdf)))\nggplot(data = paysdf) +\n geom_vline(xintercept = 1, color = \"red\")+ #afficher la valeur de référence\n geom_errorbarh(aes(xmin = rap.cote.2.5, xmax = rap.cote.97.5, \n y = reorder(Pays, rap.cote)), height = 0)+\n geom_point(aes(x = rap.cote, y = reorder(Pays, rap.cote))) +\n geom_text(aes(x = rap.cote.97.5, y = reorder(Pays, rap.cote), \n label = paste(\"RC : \", round(rap.cote,2), sep = \"\")),\n size = 3, nudge_x = 0.25)+\n labs(x = \"Rapports de cote\", y = \"Pays (référence : Allemagne)\")\n```\n\n::: {.cell-output-display}\n![Rapports de cote pour les différents pays de l'UE](08-GLM_files/figure-html/fig-paysbinom-1.png){#fig-paysbinom fig-align='center' width=80%}\n:::\n:::\n\n\nDans la @fig-paysbinom, la barre horizontale pour chaque pays représente l’intervalle de confiance de son rapport de cotes (le point); plus cette ligne est longue, plus grande est l’incertitude autour de ce paramètre. Lorsque les lignes de deux pays se chevauchent, cela signifie qu’il n’y a pas de différence significative au seuil 0,05 entre les rapports de cotes des deux pays. La ligne rouge tracée à x = 1, représente le rapport de cotes du pays de référence (ici l’Allemagne). Nous constatons ainsi que comparativement à un individu vivant en Allemagne, ceux vivant au Danemark et aux Pays-Bas ont 2,4 fois plus de chances d’utiliser le vélo pour leur déplacement le plus fréquent. Les Pays de l’Ouest (France, Luxembourg, Royaume-Uni, Irlande) et du Sud (Grèce, Italie, Espagne, Portugal) ont en revanche des rapports de cotes plus faibles. En France, les chances qu’un individu utilise le vélo pour son trajet le plus fréquent sont 3,22 (1/0,31) fois plus faibles que si l’individu vivait en Allemagne.\n\nPour le reste des coefficients et des rapports de cotes, nous les rapportons dans le @tbl-coeffbinom.\n\n\n::: {#tbl-coeffbinom .cell tbl-cap='Résultats du modèle binomial'}\n::: {.cell-output-display}\n|Variable | Coefficient| Rapport de cote| Err.std| Val.z| P| RC 2,5 %| RC 97,5 %|\n|:-------------------------|-----------:|---------------:|-------:|-------:|-----:|--------:|---------:|\n|Constante | -2,497| 0,082| 0,183| -13,674| 0,000| 0,058| 0,118|\n|*Sexe* | | | | | | | |\n|ref : femme | --| --| --| --| --| --| --|\n|homme | 0,372| 1,451| 0,038| 9,803| 0,000| 1,347| 1,562|\n|Age | -0,009| 0,991| 0,002| -5,361| 0,000| 0,988| 0,994|\n|*Education* | | | | | | | |\n|ref : premier cycle | --| --| --| --| --| --| --|\n|secondaire | 0,193| 1,213| 0,105| 1,836| 0,066| 0,987| 1,490|\n|secondaire inferieur | 0,301| 1,351| 0,114| 2,649| 0,008| 1,081| 1,687|\n|universite | 0,146| 1,157| 0,108| 1,349| 0,177| 0,936| 1,432|\n|*StatutEmploi* | | | | | | | |\n|ref : employe | --| --| --| --| --| --| --|\n|sans emploi | 0,257| 1,293| 0,043| 6,045| 0,000| 1,190| 1,405|\n|*Revenu* | | | | | | | |\n|ref : eleve | --| --| --| --| --| --| --|\n|faible | 0,077| 1,080| 0,072| 1,067| 0,286| 0,938| 1,244|\n|moyen | 0,042| 1,043| 0,065| 0,639| 0,523| 0,917| 1,185|\n|sans reponse | 0,217| 1,242| 0,102| 2,120| 0,034| 1,016| 1,517|\n|tres eleve | -0,120| 0,887| 0,188| -0,637| 0,524| 0,613| 1,283|\n|tres faible | 0,240| 1,271| 0,086| 2,776| 0,006| 1,073| 1,505|\n|*Residence* | | | | | | | |\n|ref : aire metropolitaine | --| --| --| --| --| --| --|\n|grande ville | 0,273| 1,314| 0,070| 3,911| 0,000| 1,146| 1,507|\n|petite-moyenne ville | 0,277| 1,319| 0,061| 4,503| 0,000| 1,169| 1,487|\n|zone rurale | -0,119| 0,888| 0,069| -1,713| 0,087| 0,775| 1,017|\n|Duree | -0,001| 0,999| 0,001| -0,981| 0,326| 0,998| 1,001|\n|ConsEnv | 0,102| 1,108| 0,010| 10,502| 0,000| 1,087| 1,130|\n:::\n:::\n\n\nLes chances pour un individu d’utiliser le vélo pour son trajet le plus fréquent sont augmentées de 45 % s’il s’agit d’un homme plutôt qu’une femme. Pour l’âge, nous constatons un effet relativement faible puisque chaque année supplémentaire réduit les chances qu’un individu utilise le vélo comme mode de transport pour son trajet le plus fréquent de 0,9 % $((\\mbox{0,991}-\\mbox{1})\\times\\mbox{100})$. Le fait d’être sans emploi augmente les chances d’utiliser le vélo de 29 % comparativement au fait d’avoir un emploi. Concernant le niveau d’éducation, seul le coefficient pour le groupe des personnes de la catégorie « secondaire inférieure » est significatif, indiquant que les personnes de ce groupe ont 35 % de chances en plus d'utiliser le vélo comme mode de transport pour leur déplacement le plus fréquent comparativement aux personnes de la catégorie « premier cycle ». Pour le revenu, seul le groupe avec de très faibles revenus se distingue significativement du groupe avec un revenu élevé avec un rapport de cotes de 1,27, soit 27 % de chances en plus d'utiliser le vélo.\n\nComparativement à ceux vivant dans une aire métropolitaine, les personnes vivant dans de petites, moyennes et grandes villes ont des chances accrues d’utiliser le vélo comme mode de déplacement pour leur trajet le plus fréquent. En revanche, nous n'observons aucune différence entre la probabilité d’utiliser le vélo dans une métropole et en zone rurale. La @fig-villebinom permet de clairement visualiser cette situation. Rappelons que la référence est la situation : vivre dans une région métropolitaine, représentée par la ligne verticale rouge. Plusieurs pistes d’interprétation peuvent être envisagées pour ce résultat : \n\n* En métropole et dans les zones rurales, les distances domicile-travail tendent à être plus grandes que dans les petites, moyennes et grandes villes.\n\n* En métropole, le système de transport en commun est davantage développé et entre donc en concurrence avec les modes de transport actifs.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Isoler les lignes du tableau récapitulatif pour les lieux de résidence\nresiddf <- subset(tableau_binom, grepl(\"Residence\", row.names(tableau_binom), fixed = TRUE))\nresiddf$resid <- gsub(\"Residence\" , \"\", row.names(residdf), fixed=T)\nggplot(data = residdf) +\n geom_vline(xintercept = 1, color = \"red\")+ #afficher la valeur de référence\n geom_errorbarh(aes(xmin = rap.cote.2.5, xmax = rap.cote.97.5, y = resid), height = 0)+\n geom_point(aes(x = rap.cote, y = resid)) +\n geom_text(aes(x = rap.cote.97.5, y = resid, \n label = paste(\"RC : \", round(rap.cote,2), sep = \"\")),\n size = 3, nudge_x = 0.1)+\n labs(x = \"Rapports de cotes\",\n y = \"Lieu de résidence (référence : aire métropolitaine)\")\n```\n\n::: {.cell-output-display}\n![Rapports de cote pour les différents lieux de résidence](08-GLM_files/figure-html/fig-villebinom-1.png){#fig-villebinom fig-align='center' width=85%}\n:::\n:::\n\n\nIl est aussi intéressant de noter que la durée des trajets ne semble pas influencer la probabilité d’utiliser le vélo. Enfin, une conscience environnementale plus affirmée semble être associée avec une probabilité supérieure d’utiliser le vélo pour son déplacement le plus fréquent, avec une augmentation des chances de 11 % pour chaque point supplémentaire sur l’échelle de Likert.\n\nAfin de simplifier la présentation de certains résultats, il est possible de calculer exactement les prédictions réalisées par le modèle. Un bon exemple ici est le cas de la variable *âge*. À quelle différence pouvons-nous nous attendre entre deux individus identiques ayant seulement une différence d’âge de 15 ans?\n\nPrenons comme individu un homme de 30 ans, vivant dans une grande ville allemande, ayant un niveau d’éducation de niveau secondaire, employé, dans la tranche de revenu moyen, déclarant effectuer un trajet de 45 minutes et ayant rapporté un niveau de conscience environnementale de 5 (sur 10). Nous pouvons prédire la probabilité qu’il utilise le vélo pour son trajet le plus fréquent en utilisant la formule suivante : \n\n\n$$logit(p) = -\\mbox{2,497} + \\mbox{1} \\times \\mbox{0,372} + \\mbox{30} \\times -\\mbox{0,009} + \\mbox{1} \\times \\mbox{0,193} + \\mbox{1} \\times \\mbox{0,042} + \\mbox{1} \\times \\mbox{0,273} + \\mbox{45} \\times -\\mbox{0,001} + \\mbox{5} \\times \\mbox{0,102}$$\n\n$$p = \\frac{exp(-\\mbox{2,497} + \\mbox{1} \\times \\mbox{0,372} + \\mbox{30} \\times -\\mbox{0,009} + \\mbox{1} \\times \\mbox{0,193} + \\mbox{1} \\times \\mbox{0,042} + 1 \\times \\mbox{0,273} + 45 \\times -\\mbox{0,001} + \\mbox{5} \\times \\mbox{0,102})}{(\\mbox{1}+exp(-\\mbox{2,497} + 1 \\times \\mbox{0,372} + \\mbox{30} \\times-\\mbox{0,009} + 1 \\times \\mbox{0,193} + 1 \\times \\mbox{0,042} + \\mbox{1} \\times \\mbox{0,273} + \\mbox{45} \\times -\\mbox{0,001} + 5 \\times \\mbox{0,102}))} = \\mbox{0,194}$$\n\n\nIl y aurait 19,4 % de chances pour que cette personne soit cycliste. Comme cette probabilité dépasse le seuil que nous avons sélectionné, cette personne serait classée comme cycliste. Si nous augmentons son âge de 15 ans, nous obtenons :\n\n$$p = \\frac{exp(-\\mbox{2,497} + \\mbox{1} \\times \\mbox{0,372} + \\mbox{45} \\times \\mbox{-0,009} + \\mbox{1} \\times \\mbox{0,193} + \\mbox{1} \\times \\mbox{0,042} + \\mbox{1} \\times \\mbox{0,273} + \\mbox{45} \\times -\\mbox{0,001} + \\mbox{5} \\times \\mbox{0,102})} {(\\mbox{1}+exp(-\\mbox{2,497} + \\mbox{1} \\times \\mbox{0,372} + \\mbox{45} \\times -\\mbox{0,009} + \\mbox{1} \\times \\mbox{0,193} + \\mbox{1} \\times \\mbox{0,042} + \\mbox{1} \\times \\mbox{0,273} + \\mbox{45} \\times -\\mbox{0,001} + \\mbox{5} \\times \\mbox{0,102}))} = \\mbox{0,174}$$\n\nsoit une réduction de 2 points de pourcentages. Il est également possible de représenter cette évolution sur un graphique pour montrer l’effet sur l’étendue des valeurs possibles. Sur ces graphiques des effets marginaux, il est essentiel de représenter l'incertitude quant à la prédiction. En temps normal, la fonction `predict` calcule directement l'erreur standard de la prédiction et cette dernière peut être utilisée pour calculer l'intervalle de confiance de la prédiction. Cependant, nous voulons ici utiliser nos erreurs standards robustes. Nous devons donc procéder par simulation pour déterminer l'intervalle de confiance à 95 % de nos prédictions. Cette opération nécessite de réaliser plusieurs opérations manuellement dans R.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Créer un jeu de données fictif pour la prédiction\nmat <- model.matrix(model2$terms, model2$model)\nage2seq <- seq(20, 80)\nmat2 <- matrix(mat[1,], nrow = length(age2seq), ncol = length(mat[1,]), byrow = TRUE)\ncolnames(mat2) <- colnames(mat)\nmat2[,\"Age\"] <- age2seq\nmat2[,\"PaysBelgique\"] <- 0\nmat2[,\"Duree\"] <- 45\nmat2[,\"ConsEnv\"] <- 5\nmat2[,\"StatutEmploisans emploi\"] <- 0\nmat2[,\"Residencegrande ville\"] <- 1\nmat2[,\"Educationsecondaire\"] <- 1\nmat2[,\"Sexehomme\"] <- 1\nmat2[,\"Revenumoyen\"] <- 1\nmat2[,\"Revenufaible\"] <- 0\n# Calculer la prédiction comme un log de rapport de cote (avec les erreurs standards)\n# en multipliant les coefficient par les valeurs des données fictives\ncoeffs <- model2$coefficients\npred <- coeffs %*% t(mat2)\n# Simulation de prédictions (toujours en log de rapport de cote)\n# Étape 1 : simuler 1000 valeurs pour chaque coefficient\nsim_coeffs <- lapply(1:length(coeffs), function(i){\n coef <- coeffs[[i]]\n std.err <- stdErrRobuste[[i]]\n vals <- rnorm(n = 1000, mean = coef, sd = std.err)\n return(vals)\n})\nmat_sim_coeffs <- do.call(rbind, sim_coeffs)\n# Étape 2 : effectuer les prédictions à partir des coefficients simulés\nsim_preds <- lapply(1:ncol(mat_sim_coeffs), function(i){\n temp_coefs <- mat_sim_coeffs[,i]\n temp_pred <- as.vector(temp_coefs %*% t(mat2))\n return(temp_pred)\n})\nmat_sim_preds <- do.call(cbind, sim_preds)\n# Étape 3 : extraire les intervalles de confiance pour les simulations\nintervals <- apply(mat_sim_preds, MARGIN = 1, FUN = function(vec){\n return(quantile(vec, probs = c(0.025, 0.975)))\n})\n# Étape 4 : récupérer tous ces éléments dans un DataFrame\ndf <- data.frame(\n Age = seq(20,80),\n pred = as.vector(pred),\n lower = as.vector(intervals[1,]),\n upper = as.vector(intervals[2,])\n)\n# Étape 5 : appliquer l'inverse de la fonction de lien pour\n# obtenir les prédictions en termes de probabilité\nilink <- family(model2)$linkinv\ndf$prob_pred <- ilink(df$pred)\ndf$prob_lower <- ilink(df$lower)\ndf$prob_upper <- ilink(df$upper)\n# Étape 6 : représenter le tout sur un graphique\nggplot(df) + \n geom_ribbon(aes(x = Age, ymax = prob_upper, ymin = prob_lower), \n fill = rgb(0.1,0.1,0.1,0.4)) + \n geom_path(aes(x = Age, y = prob_pred), color = \"blue\", size = 1) +\n geom_hline(yintercept = 0.15, linetype = \"dashed\", size = 0.7) + \n labs(x = \"Âge\", y = \"Probabilité prédite (intervalle de confiance à 95 %)\")\n```\n\n::: {.cell-output-display}\n![Effet de l'âge sur la probabilité d'utiliser le vélo comme moyen de déplacement pour son trajet le plus fréquent](08-GLM_files/figure-html/fig-agebinom-1.png){#fig-agebinom fig-align='center' width=65%}\n:::\n:::\n\n\nLa @fig-agebinom permet de bien constater la diminution de la probabilité d’utiliser le vélo pour son trajet le plus fréquent avec l’âge, mais cette réduction est relativement ténue. Dans le cas utilisé en exemple, l’individu ne serait plus classé cycliste qu’après 67 ans.\n\n### Modèle probit binomial {#sec-0822}\n\nLe modèle GLM probit binomial est pour ainsi dire le frère du modèle logistique binomial. La seule différence entre les deux réside dans l'utilisation d'une autre fonction de lien: probit plutôt que logistique. La fonction de lien probit (Φ) correspond à la fonction cumulative de la distribution normale et a également une forme de *S*. Cette version du modèle est plus souvent utilisée par les économistes. Le principal changement réside dans l’interprétation des coefficients $\\beta_0$ et $\\beta$. Du fait de la transformation probit, ces derniers indiquent le changement en termes de scores Z de la probabilité modélisée. Vous conviendrez qu’il ne s’agit pas d’une échelle très intuitive; la plupart du temps, seuls la significativité et le signe (positif ou négatif) des coefficients sont interprétés.\n\n\n::: {#tbl-probitdentity .cell tbl-cap='Carte d\\'identité du modèle probit binomial'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:-------------------------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable binaire (0 ou 1) ou comptage de réussite à une expérience (ex : 3 réussites sur 5 expériences) |\n|Distribution utilisée |Binomiale |\n|Formulation |$Y \\sim Binomial(p)$ \\newline $g(p) = \\beta_0 + \\beta X$ \\newline $g(x) = \\Phi^-1(x)$ |\n|Fonction de lien |probit |\n|Paramètre modélisé |p |\n|Paramètres à estimer |$\\beta_0$, $\\beta$ |\n|Conditions d'application |Non-séparation complète, absence de sur-dispersion ou de sous-dispersion |\n:::\n:::\n\n\n### Modèle logistique des cotes proportionnelles {#sec-0823}\n\nLe modèle logistique des cotes proportionnelles (aussi appelé modèle logistique cumulatif) est utilisé pour modéliser une variable qualitative ordinale. Un exemple classique de ce type de variable est une échelle de satisfaction (très insatisfait, insatisfait, mitigé, satisfait, très satisfait) qui peut être recodée avec des valeurs numériques (0, 1, 2, 3, 4; ces échelons étant notés *j*). Il n’existe pas à proprement parler de distribution pour représenter ces données, mais avec une petite astuce, il est possible de simplement utiliser la distribution binomiale. Cette astuce consiste à poser l’hypothèse de la proportionnalité des cotes, soit que le passage de la catégorie 0 à la catégorie 1 est proportionnel au passage de la catégorie 1 à la catégorie 2 et ainsi de suite. Si cette hypothèse est respectée, alors les coefficients du modèle pourront autant décrire le passage de la catégorie *satisfait* à celle *très satisfait* que le passage de *insatisfait* à *mitigé*. Si cette hypothèse n’est pas respectée, il faudrait des coefficients différents pour représenter les passages d’une catégorie à l’autre (ce qui est le cas pour le modèle multinomial présenté dans la [section @sec-0824]).\n\n\n::: {#tbl-cumuldentity .cell tbl-cap='Carte d\\'identité du modèle logistique des cotes proportionnelles'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:-------------------------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable qualitative ordinale avec *j* catégories |\n|Distribution utilisée |Binomiale |\n|Formulation |$Y \\sim Binomial(p)$ \\newline $g(p \\leq j) = \\beta_{0j} + \\beta X$ \\newline $g(x) = log(\\frac{x}{1-x})$ |\n|Fonction de lien |logistique |\n|Paramètre modélisé |p |\n|Paramètres à estimer |$\\beta$ et *j*-1 constantes $\\beta_{0j}$ |\n|Conditions d'application |Non-séparation complète, absence de sur-dispersion ou de sous-dispersion, Proportionnalité des cotes |\n:::\n:::\n\n\nAinsi, dans le modèle logistique binomial vu précédemment, nous modélisons la probabilité d’observer un évènement $P(Y = 1)$. Dans un modèle logistique ordinal, nous modélisons la probabilité cumulative d’observer l’échelon *j* de notre variable ordinale $P(Y \\leq j)$. L’intérêt de cette reformulation est que nous conservons la facilité d’interprétation du modèle logistique binomial classique avec les rapports de cotes, à ceci prêt qu’ils représentent maintenant la probabilité de passer à un échelon supérieur de *Y*. La différence pratique est que notre modèle se retrouve avec autant de constantes qu’il y a de catégories à prédire moins une, chacune de ces constantes contrôlant la probabilité de base de passer de la catégorie *j* à la catégorie *j* + 1.\n\n#### Conditions d'application {#sec-08231}\n\nLes conditions d’application sont les mêmes que pour un modèle binomial, avec bien sûr l’ajout de l’hypothèse sur la proportionnalité des cotes. Selon cette hypothèse, l'effet de chaque variable indépendante est identique sur la probabilité de passer d'un échelon de la variable *Y* au suivant. Afin de tester cette condition, deux approches sont envisageables : \n\n1. Utiliser l’approche de Brant [-@brant1990assessing]. Il s’agit d’un test statistique comparant les résultats du modèle ordinal avec ceux d’une série de modèles logistiques binomiaux (1 pour chaque catégorie possible de *Y*).\n\n2. Ajuster un modèle ordinal sans l’hypothèse de proportionnalité des cotes et effectuer un test de ratio des *likelihood* pour vérifier si le premier est significativement mieux ajusté.\n\nSi certaines variables ne respectent pas cette condition d’application, trois options sont possibles pour y remédier : \n\n1. Supprimer la variable du modèle (à éviter si cette variable est importante dans votre cadre théorique).\n\n2. Autoriser la variable à avoir un effet différent entre chaque palier (possible avec le *package* `VGAM`).\n\n3. Changer de modèle et opter pour un modèle des catégories adjacentes. Il s’agit du cas particulier où toutes les variables sont autorisées à changer à chaque niveau. Ne pas confondre ce dernier modèle et le modèle multinomial ([section @sec-0824]), puisque le modèle des catégories adjacentes continue à prédire la probabilité de passer à une catégorie supérieure.\n\n\n#### Exemple appliqué dans R {#sec-08232}\n\nPour cet exemple, nous analysons un jeu de données proposé par [Inside Airbnb](http://insideairbnb.com/get-the-data.html), une organisation sans but lucratif collectant des données des annonces sur le site d’Airbnb pour alimenter le débat sur l’effet de cette société sur les quartiers. Plus spécifiquement, nous utilisons le jeu de données pour Montréal compilé le 30 juin 2020. Nous modélisons ici le prix par nuit des logements, ce type d’exercice est appelé modélisation hédonique. Il est particulièrement utilisé en économie urbaine pour évaluer les déterminants du marché immobilier et prédire son évolution. Le cas d'Airbnb a déjà été étudié dans plusieurs articles [@teubner2017price; @wang2017price; @zhang2017key]. Il en ressort notamment que le niveau de confiance inspiré par l’hôte, les caractéristiques intrinsèques du logement et sa localisation sont les principales variables indépendantes de son prix. Nous construisons donc notre modèle sur cette base. Notez que nous avons décidé de retirer les logements avec des prix supérieurs à 250 \\$ par nuit qui constituent des cas particuliers et qui devraient faire l'objet d'une analyse à part entière. Nous avons également retiré les observations pour lesquelles certaines données sont manquantes, et obtenons un nombre final de 9 051 observations.\n\nLa distribution originale du prix des logements dans notre jeu de données est présentée à la @fig-histopriceairbnb.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Charger le jeu de données\ndata_airbnb <- read.csv(\"data/glm/airbnb_data.csv\")\n# Afficher la distribution du prix\nggplot(data = data_airbnb) + \n geom_histogram(aes(x = price), bins = 30, \n color = \"white\", fill = \"#1d3557\", linewidth = 0.02)+\n labs(x = \"Prix (en dollars)\", y = \"Fréquence\")\n```\n\n::: {.cell-output-display}\n![Distribution des prix des logements Airbnb](08-GLM_files/figure-html/fig-histopriceairbnb-1.png){#fig-histopriceairbnb fig-align='center' width=65%}\n:::\n:::\n\n\nNous avons ensuite découpé le prix des logements en trois catégories : inférieur à 50 \\$, de 50 \\$ à 99 \\$ et de 100 \\$ à 249 \\$. Ces catégories forment une variable ordinale de trois échelons que nous modélisons à partir de trois catégories de variables : \n\n* les caractéristiques propres au logement;\n* les caractéristiques environnementales autour du logement;\n* les notes obtenues par le logement sur le site d’Airbnb.\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Afficher le nombre de logement par catégories\ntable(data_airbnb$fac_price_cat)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n 1 2 3 \n2212 3911 2928 \n```\n:::\n:::\n\n\nLe @tbl-variablecumul présente l’ensemble des variables utilisées dans le modèle.\n\n\n\n\n::: {#tbl-variablecumul .cell tbl-cap='Variables indépendantes utilisées pour prédire la catégorie de prix de logements Airbnb'}\n::: {.cell-output-display}\n|Nom de la variable |Description |Type de variable |Mesure |\n|:-------------------------|:-----------------------------------------------------------------------------|:--------------------|:--------------------------------------------------------------------------------------------------------------------|\n|beds |Nombre de lits dans le logement |Variable de comptage |Nombre de lits dans le logement |\n|Garden_or_backyard |Présence d’un jardin ou d’une arrière-cour |Variable binaire |Oui ou non |\n|private |Le logement est entièrement à disposition du locataire ou seulement une pièce |Variable binaire |Privé ou partagé |\n|Free_street_parking |Une place de stationnement gratuite est disponible sur la rue |Variable binaire |Oui ou non |\n|Host_greets_you |L’hôte accueille personnellement les locataires |Variable binaire |Oui ou non |\n|prt_veg_500m |Végétation dans les environs du logement |Variable continue |Pourcentage de surface végétale dans un rayon de 500 mètres autour du logement |\n|has_metro_500m |Présence d’une station de métro à proximité du logement |Variable binaire |Présence d’une station de métro dans un rayon de 500 mètres autour du logement |\n|commercial_1km |Commerce dans les environs du logement |Variable continue |Pourcentage de surface dédiée au commerce (mode d’occupation du sol) dans un rayon d'un kilomètre autour du logement |\n|cat_review |Évaluation de la qualité du logement par les usagers |Variable ordinale |Note obtenue par le logement sur une échelle allant de 1 (très mauvais) à 5 (parfait) |\n|host_total_listings_count |Nombre total de logements détenus par l’hôte sur Airbnb |Variable de comptage |Nombre total de logements détenus par l’hôte sur Airbnb |\n:::\n:::\n\n\n**Vérification des conditions d'application**\n\nAvant d'ajuster le modèle, il convient de vérifier l'absence de multicolinéarité excessive entre les variables indépendantes.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Notez que la fonction vif ne s'intéresse qu'aux variables indépendantes.\n# Vous pouvez ainsi utiliser la fonction glm avec la fonction vif \n# pour n'importe quel modèle glm\nvif(glm(price ~ beds +\n Garden_or_backyard + Host_greets_you + Free_street_parking + \n prt_veg_500m + has_metro_500m + commercial_1km +host_total_listings_count +\n private + cat_review, data = data_airbnb))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n beds Garden_or_backyard Host_greets_you \n 1.123595 1.079324 1.046884 \n Free_street_parking prt_veg_500m has_metro_500m \n 1.142189 1.532536 1.239516 \n commercial_1km host_total_listings_count private \n 1.225301 1.058232 1.143932 \n cat_review \n 1.015778 \n```\n:::\n:::\n\n\nToutes les valeurs de VIF sont inférieures à 2, indiquant une absence de multicolinéarité excessive. Nous pouvons alors ajuster le modèle et analyser les distances de Cook afin de vérifier la présence ou non d'observations très influentes. Pour ajuster le modèle, nous utilisons le *package* `VGAM` et la fonction `vglm` qui nous donnent accès à la famille `cumulative` pour ajuster des modèles logistiques ordinaux. Notez que le fonctionnement de base de cette famille est de modéliser $P(Y\\leq1),P(Y\\leq2),...,P(Y\\leq J)$ avec *J* le nombre de catégories. Cependant, nous voulons ici modéliser la probabilité de passer à une catégorie supérieure de prix. Pour cela, il est nécessaire de spécifier le paramètre `reverse = TRUE` pour la famille `cumulative` (voir `help(cumulative)` pour plus de détails).\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(VGAM)\nmodele <- vglm(fac_price_cat ~ beds +\n Garden_or_backyard + Free_street_parking + \n prt_veg_500m + has_metro_500m + commercial_1km +\n private + cat_review + host_total_listings_count ,\n family = cumulative(link=\"logitlink\", # fonction de lien \n parallel = TRUE, # cote proportionnelle\n reverse = TRUE),\n data = data_airbnb, model = T)\n```\n:::\n\n\nNotez que, puisque la variable *Y* a trois catégories différentes et que nous modélisons la probabilité de passer à une catégorie supérieure, chaque observation a alors deux (3-1) valeurs de résidus différentes. Par conséquent, nous calculons deux distances de Cook différentes que nous devons analyser conjointement. Malheureusement, la fonction `cook.distance` ne fonctionne pas avec les objets `vglm`, nous devons donc les calculer manuellement.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggpubr)\n# Extraction des résidus\nres <- residuals(modele, type = \"pearson\")\n# Extraction de la hat matrix (nécessaire pour calculer la distance de Cook)\nhat <- hatvaluesvlm(modele)\n# Calcul des distances de Cook\ncooks <- lapply(1:ncol(res), function(i){\n r <- res[,i]\n h <- hat[,i]\n cook <- (r/(1 - h))^2 * h/(1 * modele@rank)\n})\n# Structuration dans un DataFrame\nmatcook <- data.frame(do.call(cbind, cooks))\nnames(matcook) <- c(\"dist1\" , \"dist2\")\nmatcook$oid <- 1:nrow(matcook)\n# Afficher les distances de Cook\nplot1 <- ggplot(data = matcook) + \n geom_point(aes(x = oid, y = dist1), size = 0.2, color = rgb(0.1,0.1,0.1,0.4)) + \n labs(x = \"\", y = \"\", subtitle = \"distance de Cook P(Y>=2)\")+\n theme(axis.ticks.x = element_blank(),\n axis.text.x = element_blank())\nplot2 <- ggplot(data = matcook) + \n geom_point(aes(x = oid, y = dist2), size = 0.2, color = rgb(0.1,0.1,0.1,0.4)) + \n labs(x = \"\", y = \"\", subtitle = \"distance de Cook P(Y>=3)\")+\n theme(axis.ticks.x = element_blank(),\n axis.text.x = element_blank())\n\nggarrange(plot1, plot2, ncol = 2, nrow = 1)\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle logistique des cotes proportionnelles](08-GLM_files/figure-html/fig-CookdCotePropor-1.png){#fig-CookdCotePropor fig-align='center' width=65%}\n:::\n:::\n\n\nLes distances de Cook (@fig-CookdCotePropor) nous permettent d'identifier quelques observations potentiellement trop influentes, mais elles semblent être différentes d'un graphique à l'autre. Nous décidons donc de ne pas retirer d'observations à ce stade et de passer à l'analyse des résidus simulés. Pour effectuer des simulations à partir de ce modèle, nous nous basons sur les probabilités d'appartenance prédites par le modèle.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Extraire les probabilités prédites\npredicted <- predict(modele, type = \"response\")\nround(head(predicted, n = 4),3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 1 2 3\n1 0.706 0.267 0.028\n2 0.073 0.461 0.466\n3 0.687 0.283 0.030\n4 0.049 0.383 0.568\n```\n:::\n:::\n\n\nNous constatons ainsi que, pour la première observation, la probabilité prédite d'appartenir au groupe 1 est de 69,4 %, de 27,7 % pour le groupe 2 et de 2,9 % pour le groupe 3. Si nous effectuons 1 000 simulations, nous pouvons nous attendre à ce qu'en moyenne, sur ces 1 000 simulations, 694 indiqueront 1 comme catégorie prédite, 277 indiqueront 2 et seulement 29 indiqueront 3.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Nous effectuerons 1000 simulations\nnsim <- 1000\n# Lancement des simulations pour chaque observation (lignes dans predicted)\nsimulations <- lapply(1:nrow(predicted), function(i){\n probs <- predicted[i,]\n sims <- sample(c(1,2,3), size = nsim, replace = TRUE, prob = probs)\n return(sims)\n})\n# Combiner les prédictions dans un tableau\nmatsim <- do.call(rbind, simulations)\n# Observons si nos simulations sont proches de ce que nous attendions\ntable(matsim[1,])\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n 1 2 3 \n713 257 30 \n```\n:::\n:::\n\n\nÀ partir de ces simulations de prédiction, nous pouvons réaliser un diagnostic des résidus simulés grâce au *package* `DHARMa`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(DHARMa)\n# Extraction de la prédiction moyenne du modèle\npred_cat <- unique(data_airbnb$fac_price_cat)[max.col(predicted)]\n# Préparer les données avec le package DHARMa\nsim_res <- createDHARMa(simulatedResponse = matsim, \n observedResponse = as.numeric(data_airbnb$fac_price_cat),\n fittedPredictedResponse = as.numeric(pred_cat),\n integerResponse = TRUE)\n# Afficher le graphique de diagnostic général\nplot(sim_res)\n```\n\n::: {.cell-output-display}\n![Diagnostic général des résidus simulés du modèle des cotes proportionnelles](08-GLM_files/figure-html/fig-diagressimcumul-1.png){#fig-diagressimcumul fig-align='center' width=65%}\n:::\n:::\n\n\nLa @fig-diagressimcumul nous indique que les résidus simulés suivent bien une distribution uniforme et qu'aucune valeur aberrante n'est observable. Pour affiner notre diagnostic, nous vérifions également si aucune relation ne semble exister entre chaque variable indépendante et les résidus. \n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Préparons un plot multiple\npar(mfrow=c(3,4))\nvars <- c(\"nombre de lits\" = \"beds\",\n \"couvert végétal\" = \"prt_veg_500m\", \n \"commercial\" = \"commercial_1km\",\n \"nb logements hôte\" = \"host_total_listings_count\",\n \"jardin\" = \"Garden_or_backyard\",\n \"accueil\" = \"Host_greets_you\",\n \"stationnement gratuit\" = \"Free_street_parking\", \n \"métro\" = \"has_metro_500m\", \n \"logement privé\" = \"private\",\n \"évaluation\" = \"cat_review\")\n\nfor(name in names(vars)){\n v <- vars[[name]]\n plotResiduals(sim_res, data_airbnb[[v]], rank = FALSE, quantreg = FALSE, main = \"\",\n xlab = name, ylab = \"résidus\")\n}\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Diagnostic des variables indépendantes et des résidus simulés du modèle des cotes proportionnelles](images/Chap08/diagressimcumul2.png){#fig-diagressimcumul2 fig-align='center' width=100%}\n:::\n:::\n\n\nLa fonction `plotResiduals` du *package* `DHARMa` produit des graphiques peu esthétiques, mais pratiques pour effectuer ce type de diagnostic.\n\nLa @fig-diagressimcumul2 indique qu'aucune relation marquée n'existe entre nos variables indépendantes et nos résidus simulés, sauf pour la variable *nombre de lits*. En effet, nous pouvons constater que les résidus ont tendance à être toujours plus faibles quand le nombre de lits augmente. Cet effet est sûrement lié au fait qu'au-delà de cinq lits, le logement en question est vraisemblablement un dortoir. Il pourrait être judicieux de retirer ces observations de l'analyse, considérant qu'elles sont peu nombreuses et constituent un type de logement particulier.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndata_airbnb2 <- subset(data_airbnb, data_airbnb$beds <=5)\nmodele2 <- vglm(fac_price_cat ~ beds + \n Garden_or_backyard + Free_street_parking + \n prt_veg_500m + has_metro_500m + commercial_1km +\n private + cat_review + host_total_listings_count ,\n family = cumulative(link=\"logitlink\", # fonction de lien \n parallel = TRUE, # cote proportionelle\n reverse = TRUE),\n data = data_airbnb2, model = T)\n```\n:::\n\n\nNous pouvons ensuite recalculer les résidus simulés pour observer si cette tendance a été corrigée. La @fig-diagressimcumul3 montre qu'une bonne partie du problème a été corrigée; cependant, il semble tout de même que les résidus soient plus forts pour les logements avec un seul lit.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Nous effectuerons 1000 simulations\nnsim <- 1000\npredicted <- predict(modele2, type = \"response\")\n# Lancement des simulations pour chaque observation (lignes dans predicted)\nsimulations <- lapply(1:nrow(predicted), function(i){\n probs <- predicted[i,]\n sims <- sample(c(1,2,3), size = nsim, replace = TRUE, prob = probs)\n return(sims)\n})\n# Combiner les prédictions dans un tableau\nmatsim <- do.call(rbind, simulations)\n# Extraction de la prédiction moyenne du modèle\npred_cat <- unique(data_airbnb2$fac_price_cat)[max.col(predicted)]\n# Préparer les donnees avec le package DHARMa\nsim_res <- createDHARMa(simulatedResponse = matsim, \n observedResponse = as.numeric(data_airbnb2$fac_price_cat),\n fittedPredictedResponse = as.numeric(pred_cat),\n integerResponse = TRUE)\n```\n:::\n\n::: {.cell}\n\n```{.r .cell-code}\npar(mfrow=c(3,4))\nvars <- c(\"nombre de lits\" = \"beds\",\n \"couvert végétal\" = \"prt_veg_500m\", \n \"commercial\" = \"commercial_1km\",\n \"nb logements hôte\" = \"host_total_listings_count\",\n \"jardin\" = \"Garden_or_backyard\",\n \"accueil\" = \"Host_greets_you\",\n \"stationnement gratuit\" = \"Free_street_parking\", \n \"métro\" = \"has_metro_500m\", \n \"logement privé\" = \"private\",\n \"évaluation\" = \"cat_review\")\n\nfor(name in names(vars)){\n v <- vars[[name]]\n plotResiduals(sim_res, data_airbnb2[[v]], rank = FALSE, quantreg = FALSE, main = \"\",\n xlab = name, ylab = \"résidus\")\n}\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Diagnostic des variables indépendantes et des résidus simulés du modèle des cotes proportionnelles (après correction)](images/Chap08/diagressimcumul3.png){#fig-diagressimcumul3 fig-align='center' width=100%}\n:::\n:::\n\n\nLa prochaine étape du diagnostic est de vérifier l'absence de séparation parfaite provoquée par une de nos variables indépendantes. Le *package* `VGAM` propose pour cela la fonction `hdeff`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ntests <- hdeff(modele2)\nproblem <- table(tests)\nproblem\n```\n\n::: {.cell-output .cell-output-stdout}\n```\ntests\nFALSE \n 11 \n```\n:::\n:::\n\n\nLa fonction nous informe qu'aucune de nos variables indépendantes ne provoque de séparation parfaite : toutes les valeurs renvoyées par la fonction `hdeff` sont égales à `FALSE.`\n\nIl ne nous reste donc plus qu'à vérifier que l'hypothèse de proportionnalité des cotes est respectée, soit que l'effet de chacune des variables indépendantes est bien le même pour passer de la catégorie 1 à 2 que pour passer de la catégorie 2 à 3. Pour cela, deux approches sont possibles : le test de Brant ou la réalisation d'une séquence de tests de rapport de vraisemblance.\n\nLe *package* `brant` propose une implémentation du test de Brant, mais celle-ci ne peut être appliquée qu'à des modèles construits avec la fonction `polr` du *package* `MASS`. Nous avons donc récupéré le code source de la fonction `brant` du *package* `brant` et apporté quelques modifications pour qu'elle soit utilisable sur un objet `vglm`. Cette nouvelle fonction, appelée `brant.vglm`, est disponible dans le code source de ce livre.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ntableau_brant <- round(brant.vglm(modele2), 3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n------------------------------------------------------------ \nTest for\t\t\tX2\tdf\tprobability \n------------------------------------------------------------ \nOmnibus\t\t\t\t113.72\t9\t0\nbeds\t\t\t\t0.63\t1\t0.43\nGarden_or_backyardYES\t\t0.16\t1\t0.69\nFree_street_parkingYES\t0.84\t1\t0.36\nprt_veg_500m\t\t\t6.49\t1\t0.01\nhas_metro_500mYES\t\t0.02\t1\t0.89\ncommercial_1km\t\t\t0.01\t1\t0.92\nprivateEntier\t\t\t93.56\t1\t0\ncat_review\t\t\t0.63\t1\t0.43\nhost_total_listings_count\t1.51\t1\t0.22\n------------------------------------------------------------ \n\nH0: Parallel Regression Assumption holds\n```\n:::\n:::\n\n\nCe premier tableau nous indique que seule la variable indiquant si le logement est disponible en entier ou partagé contrevient à l'hypothèse de proportionnalité des cotes (la seule valeur *p* significative). Pour confirmer cette observation, nous pouvons réaliser un ensemble de tests de rapport de vraisemblance. Pour chaque variable du modèle, nous créons un second modèle dans lequel cette variable est autorisée à varier pour chaque catégorie et nous comparons les niveaux d'ajustement des modèles. Nous avons implémenté cette procédure dans la fonction `parallel.likelihoodtest.vglm` disponible dans le code source de ce livre.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ntableau_likelihood <- parallel.likelihoodtest.vglm(modele2, verbose = FALSE)\nprint(tableau_likelihood)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n variable non parallele AIC loglikelihood p.val loglikelihood ratio test\n1 beds 15304 -7640 0.271\n2 Garden_or_backyard 15305 -7641 0.417\n3 Free_street_parking 15301 -7639 0.079\n4 prt_veg_500m 15296 -7636 0.007\n5 has_metro_500m 15303 -7640 0.191\n6 commercial_1km 15305 -7640 0.271\n7 private 15215 -7595 0.000\n8 cat_review 15306 -7641 0.430\n9 host_total_listings_count 15304 -7640 0.257\n```\n:::\n:::\n\n\nLes résultats de cette seconde série de tests confirment les précédents, la variable concernant le type de logement doit être autorisée à varier en fonction de la catégorie. Ce second tableau nous indique que la variable concernant la densité de végétation pourrait aussi être amenée à varier en fonction du groupe, mais ce changement a un effet très marginal (différence entre les valeurs d'AIC de seulement 8 points). Nous ajustons donc un nouveau modèle autorisant la variable `private` à changer en fonction de la catégorie prédite.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodele3 <- vglm(fac_price_cat ~ beds + \n Garden_or_backyard + Host_greets_you + Free_street_parking + \n prt_veg_500m + has_metro_500m + commercial_1km +\n private + cat_review + host_total_listings_count,\n family = cumulative(link=\"logitlink\",\n parallel = FALSE ~ private ,\n reverse = TRUE),\n data = data_airbnb2, model = T)\n```\n:::\n\n\n**Vérification l'ajustement du modèle**\n\nMaintenant que toutes les conditions d'application ont été passées en revue, nous pouvons passer à la vérification de l'ajustement du modèle.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodelenull <- vglm(fac_price_cat ~ 1,\n family = cumulative(link=\"logitlink\",\n parallel = TRUE,\n reverse = TRUE),\n data = data_airbnb2, model = T)\nrsqs(loglike.full = logLik(modele3),\n loglike.null = logLik(modelenull),\n full.deviance = deviance(modele3),\n null.deviance = deviance(modelenull),\n nb.params = modele3@rank,\n n = nrow(data_airbnb2)\n)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n$`deviance expliquee`\n[1] 0.2087098\n\n$`McFadden ajuste`\n[1] 0.2073552\n\n$`Cox and Snell`\n[1] 0.3606848\n\n$Nagelkerke\n[1] 0.4085924\n```\n:::\n:::\n\n\nLe modèle final parvient à expliquer 21 % de la déviance originale. Il obtient un R^2^ ajusté de McFadden de 0,21, et des R^2^ de Cox et Snell et de Nagelkerke de respectivement 0,36 et 0,41. Construisons à présent la matrice de confusion de la prédiction du modèle (nous utilisons ici la fonction `nice_confusion_matrix` également disponible dans le code source de ce livre).\n\n\n::: {.cell}\n\n```{.r .cell-code}\npreds_probs <- fitted(modele3)\npred_cat <- c(1,2,3)[max.col(preds_probs)]\nlibrary(caret)\nmatrices <- nice_confusion_matrix(data_airbnb2$fac_price_cat, pred_cat)\n# Afficher la matrice de confusion\nprint(matrices$confusion_matrix)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n rowsnames 1 2 3 rs rp \ncolsnames \"\" \"1 (reel)\" \"2 (reel)\" \"3 (reel)\" \"Total\" \"%\" \n1 \"1 (predit)\" \"1576\" \"736\" \"168\" \"2480\" \"27.7\"\n2 \"2 (predit)\" \"579\" \"2385\" \"1331\" \"4295\" \"48\" \n3 \"3 (predit)\" \"49\" \"771\" \"1360\" \"2180\" \"24.3\"\n \"Total\" \"2204\" \"3892\" \"2859\" \"8955\" NA \n \"%\" \"24.6\" \"43.5\" \"31.9\" NA NA \n```\n:::\n\n```{.r .cell-code}\n# Afficher les indicateurs de qualité de prédiction\nprint(matrices$indicators)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n rnames precision rappel F1 \n1 \"1\" \"0.64\" \"0.72\" \"0.67\"\n2 \"2\" \"0.56\" \"0.61\" \"0.58\"\n3 \"3\" \"0.62\" \"0.48\" \"0.54\"\nmacro_scores \"macro\" \"0.6\" \"0.59\" \"0.59\"\n \"Kappa\" \"0.37\" NA NA \n \"Valeur de p (precision > NIR)\" \"0\" NA NA \n```\n:::\n:::\n\n\nLe modèle a une précision totale de 61 % (61 % des observations ont été correctement prédites). La catégorie 1 a de loin la meilleure précision (72 %) et la 3 a la pire (48 %), ce qui indique qu’il manque vraisemblablement des variables indépendantes contribuant à prédire les prix des logements les plus chers. Le coefficient de Kappa (0,37) indique un niveau d’accord entre modéré et faible, mais le modèle parvient à une prédiction significativement supérieure au seuil de non-information. Si l'ajustement du modèle est imparfait, il est suffisamment fiable pour nous donner des renseignements pertinents sur le phénomène étudié.\n\n**Interprétation des résultats**\n\nL'ensemble des coefficients du modèle sont accessibles via la fonction `summary`. À partir des coefficients et de leurs erreurs standards, il est possible de calculer les rapports de cotes ainsi que leurs intervalles de confiance.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ntableau <- summary(modele3)@coef3\nrappCote <- exp(tableau[,1])\nrappCote2.5 <- exp(tableau[,1] - 1.96 * tableau[,2])\nrappCote97.5 <- exp(tableau[,1] + 1.96 * tableau[,2])\ntableau <- cbind(tableau, rappCote, rappCote2.5, rappCote97.5)\nprint(round(tableau,3))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Estimate Std. Error z value Pr(>|z|) rappCote\n(Intercept):1 -1.203 0.137 -8.768 0.000 0.300\n(Intercept):2 -3.240 0.151 -21.516 0.000 0.039\nbeds 0.748 0.027 28.143 0.000 2.113\nGarden_or_backyardYES 0.120 0.067 1.795 0.073 1.128\nHost_greets_youYES 0.094 0.060 1.548 0.122 1.098\nFree_street_parkingYES -0.015 0.046 -0.320 0.749 0.985\nprt_veg_500m -0.026 0.003 -10.182 0.000 0.975\nhas_metro_500mYES 0.063 0.048 1.326 0.185 1.065\ncommercial_1km 0.008 0.008 0.955 0.340 1.008\nprivateEntier:1 2.445 0.062 39.241 0.000 11.533\nprivateEntier:2 1.576 0.081 19.573 0.000 4.834\ncat_review 0.200 0.021 9.563 0.000 1.222\nhost_total_listings_count -0.002 0.001 -2.094 0.036 0.998\n rappCote2.5 rappCote97.5\n(Intercept):1 0.230 0.393\n(Intercept):2 0.029 0.053\nbeds 2.006 2.226\nGarden_or_backyardYES 0.989 1.287\nHost_greets_youYES 0.975 1.236\nFree_street_parkingYES 0.900 1.078\nprt_veg_500m 0.970 0.980\nhas_metro_500mYES 0.970 1.170\ncommercial_1km 0.992 1.024\nprivateEntier:1 10.207 13.031\nprivateEntier:2 4.128 5.660\ncat_review 1.173 1.273\nhost_total_listings_count 0.996 1.000\n```\n:::\n:::\n\n\nPour faciliter la lecture des résultats, nous proposons le @tbl-FinalOrdinale.\n\n\n::: {#tbl-FinalOrdinale .cell tbl-cap='Coefficients du modèle logistique des cotes proportionnelles'}\n::: {.cell-output-display}\n|Variable | Coefficient| RC| P| RC 2,5 %| RC 97,5 %| sign.|\n|:-------------------------|-----------:|------:|-----:|--------:|---------:|-----:|\n|(Intercept):1 | -1,200| 0,300| 0,000| 0,230| 0,395| ***|\n|(Intercept):2 | -3,240| 0,039| 0,000| 0,029| 0,052| ***|\n|beds | 0,750| 2,113| 0,000| 2,014| 2,226| ***|\n|*Garden_or_backyard* | | | | | | |\n|ref : NO | --| --| --| --| --| --|\n|YES | 0,120| 1,128| 0,073| 0,990| 1,284| .|\n|*Host_greets_you* | | | | | | |\n|ref : NO | --| --| --| --| --| --|\n|YES | 0,090| 1,098| 0,122| 0,980| 1,234| |\n|*Free_street_parking* | | | | | | |\n|ref : NO | --| --| --| --| --| --|\n|YES | -0,010| 0,985| 0,749| 0,896| 1,083| |\n|prt_veg_500m | -0,030| 0,975| 0,000| 0,970| 0,980| ***|\n|*has_metro_500m* | | | | | | |\n|ref : NO | --| --| --| --| --| --|\n|YES | 0,060| 1,065| 0,185| 0,970| 1,174| |\n|commercial_1km | 0,010| 1,008| 0,340| 0,990| 1,020| |\n|cat_review | 0,200| 1,222| 0,000| 1,174| 1,271| ***|\n|host_total_listings_count | 0,000| 0,998| 0,036| 1,000| 1,000| *|\n| | | | | | | |\n|**Effets par niveau** | | | | | | |\n|*private* | | | | | | |\n|ref : Chambre | --| --| --| --| --| --|\n|Entier:1 | 2,450| 11,533| 0,000| 10,176| 13,066| ***|\n|Entier:2 | 1,580| 4,834| 0,000| 4,137| 5,641| ***|\n:::\n:::\n\n\nSans surprise, chaque lit supplémentaire contribue à augmenter les chances que le logement soit dans une catégorie de prix supérieure (multiplication par deux à chaque lit supplémentaire). En revanche, la présence d’un stationnement gratuit, d'un jardin et l’accueil en personne par l’hôte n’ont pas d’effets significatifs. Comme l'indiquent les articles mentionnés en début de section, les revues positives augmentent la probabilité d'appartenir à une catégorie supérieure de prix. Pour chaque point supplémentaire sur l'échelle de 1 à 5, la probabilité d'appartenir à une catégorie de prix supérieure augmente de 22,2 %. Il est intéressant de noter que le fait de disposer du logement entier plutôt que d'une simple chambre augmente davantage les chances de passer du groupe de prix 1 à 2 (multiplication par 2,45) que du groupe 2 à 3 (multiplication par 1,58). Il semble également que si l’hôte possède plusieurs logements, la probabilité d’avoir une classe de prix supérieure diminue légèrement. Cependant, l’effet est trop petit pour pouvoir se livrer à des interprétations.\n\nLes variables environnementales ont peu d’effet : le pourcentage de surface commerciale dans un rayon d’un kilomètre et la présence d’une station de métro ne sont pas significatifs. En revanche, une augmentation de la surface végétale dans un rayon de 500 mètres tend à réduire la probabilité d’appartenir à une classe supérieure. Notre hypothèse concernant ce résultat est que cette variable représente un effet associé à la localisation des Airbnb, les plus centraux ayant tendance à être plus dispendieux, mais avec un environnement moins vert et inversement. Pour l’illustrer, prédisons les probabilités d’appartenance aux différents niveaux de prix d’un logement avec les caractéristiques suivantes : entièrement privé, 2 lits, un jardin, une place de stationnement gratuite, l’hôte ne dispose que d’un logement sur Airbnb et accueille les arrivants en personne, 10 % de surface commerciale dans un rayon d'un kilomètre, noté 2 comme catégorie de revue, absence de métro dans un rayon de 500 mètres.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Créer un jeu de données pour effectuer des prédictions\ndf <- data.frame(\n prt_veg_500m = seq(5,90),\n beds = 2, \n Garden_or_backyard = \"YES\",\n Host_greets_you = \"YES\",\n Free_street_parking = \"YES\",\n has_metro_500m = \"NO\",\n commercial_1km = 10,\n private = \"Entier\",\n cat_review = 2,\n host_total_listings_count = 1\n)\n# Effectuer les prédictions (dans l'échelle log)\npreds <- predict(modele3, newdata = df, type = \"link\", se.fit=T)\n# Définir l'inverse de la fonction de lien\nilink <- function(x){exp(x)/(1+exp(x))}\n# Calculer les probabilités et leurs intervalles de confiance\ndf[[\"P[Y>=2]\"]] <- ilink(preds$fitted.values[,1])\ndf[[\"P[Y>=2] 2,5\"]] <- ilink(preds$fitted.values[,1] - 1.96 * preds$se.fit[,1])\ndf[[\"P[Y>=2] 97,5\"]] <- ilink(preds$fitted.values[,1] + 1.96 * preds$se.fit[,1])\ndf[[\"P[Y>=3]\"]] <- ilink(preds$fitted.values[,2])\ndf[[\"P[Y>=3] 2,5\"]] <- ilink(preds$fitted.values[,2] - 1.96 * preds$se.fit[,2])\ndf[[\"P[Y>=3] 97,5\"]] <- ilink(preds$fitted.values[,2] + 1.96 * preds$se.fit[,2])\ndf[[\"P[Y=1]\"]] = 1-df[[\"P[Y>=2]\"]]\ndf[[\"P[Y=1] 2,5\" ]] = 1-df[[\"P[Y>=2] 2,5\"]]\ndf[[\"P[Y=1] 97,5\"]] = 1-df[[\"P[Y>=2] 97,5\"]]\n# Afficher les résultats\nggplot(data = df) + \n geom_ribbon(aes(x = prt_veg_500m, \n ymin = `P[Y>=2] 2,5`,\n ymax = `P[Y>=2] 97,5`), fill = \"#f94144\", alpha = 0.4)+\n geom_path(aes(x = prt_veg_500m, y = `P[Y>=2]`, color = \"Y2\")) + \n geom_ribbon(aes(x = prt_veg_500m, \n ymin = `P[Y>=3] 2,5`,\n ymax = `P[Y>=3] 97,5`), fill = \"#90be6d\", alpha = 0.4)+\n geom_path(aes(x = prt_veg_500m, y = `P[Y>=3]`, color = \"Y3\" )) + \n geom_ribbon(aes(x = prt_veg_500m, \n ymin = `P[Y=1] 2,5`,\n ymax = `P[Y=1] 97,5`), fill = \"#277da1\" , alpha = 0.4)+\n geom_path(aes(x = prt_veg_500m, y = `P[Y=1]`, color = \"Y1\")) + \n scale_color_manual(name = \"Probabilités prédites\",\n breaks = c(\"Y1\", \"Y2\", \"Y3\"),\n labels = c(\"P[Y=1]\", \"P[Y>=2]\", \"P[Y>=3]\"),\n values = c(\"Y2\" = \"#f94144\", \"Y3\" = \"#90be6d\",\n \"Y1\" = \"#277da1\")) + \n labs(x = \"Densité de végétation (%)\",\n y = \"Probabilité\",\n subtitle = \"Y1 : moins de 50 $; Y2 : 50 à 99 $; Y3 : 100 à 249 $\")\n```\n\n::: {.cell-output-display}\n![Prédiction de la probabilité d'appartenance aux trois catégories de prix en fonction de la densité de végétation](08-GLM_files/figure-html/fig-predpricecatveg-1.png){#fig-predpricecatveg fig-align='center' width=65%}\n:::\n:::\n\n\nNous constatons, à la @fig-predpricecatveg, que les probabilités d’appartenir aux niveaux 2 et 3 diminuent à mesure qu’augmente le pourcentage de végétation. La probabilité d’appartenir à la classe 2 et plus (en rouge) passe de plus de 95 % en cas d’absence de végétation et à environ 75 % avec 80 % de végétation dans un rayon de 500 mètres. Comme vous pouvez le constater, la probabilité $P[Y=1]$ est la symétrie de $P[Y>=2]$ puisque $P[Y=1]+P[Y>=2] = 1$.\n\n### Modèle logistique multinomial {#sec-0824}\n\nLa régression logistique multinomiale est utilisée pour modéliser une variable *Y* qualitative multinomiale, c’est-à-dire une variable dont les modalités ne peuvent pas être ordonnées. Dans le modèle précédent, nous avons vu qu’il était possible de modéliser une variable ordinale avec une distribution binomiale en formulant l’hypothèse de la proportionnalité des cotes. Avec une variable multinomiale, cette hypothèse ne tient plus, car les catégories ne sont plus ordonnées. Il faut donc formuler le modèle différemment.\n\nL’idée derrière un modèle multinomial est de choisir une catégorie de référence, puis de modéliser les probabilités d’appartenir à chaque autre catégorie plutôt qu’à cette catégorie de référence (@tbl-multinomdentity). Si nous avons *K* catégories possibles dans notre variable *Y*, nous obtenons *K*-1 comparaisons. Chaque comparaison est modélisée avec sa propre équation, ce qui génère de nombreux paramètres. Par exemple, admettons que notre variable *Y* a cinq catégories et que nous disposons de six variables *X* prédictives. Nous avons ainsi 4 (5-1) équations de régression avec 7 paramètres (6 coefficients et une constante), soit 28 coefficients à analyser. \n\nConsidérant cette tendance à la multiplication des coefficients, il est fréquent de recourir à une méthode appelée *Analyse de type 3* pour limiter au maximum le nombre de variables indépendantes (VI) dans le modèle. L'idée de cette méthode est de recalculer plusieurs versions du modèle dans lesquelles une variable indépendante est retirée, puis de réaliser un test de rapport de vraisemblance en comparant ce nouveau modèle (complet moins une VI) au modèle complet (toutes les VI) pour vérifier si la variable en question améliore significativement le modèle. Il est alors possible de retirer toutes les variables dont l'apport est négligeable si elles sont également peu intéressantes du point de vue théorique.\n\n\n::: {#tbl-multinomdentity .cell tbl-cap='Carte d\\'identité du modèle logistique multinomial'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:----------------------------------------------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable qualitative multinomiale avec *K* catégories |\n|Distribution utilisée |Binomiale |\n|Formulation |$Y \\sim Binomial(p)$ \\newline $g(p = k\\text{ avec }ref = a) = \\beta_{0k} + \\beta X_{k}$ \\newline $g(x) = \\frac{log(x)}{1-x}$ |\n|Fonction de lien |Logistique |\n|Paramètre modélisé |p |\n|Paramètres à estimer |$\\beta_{0k}$, $\\beta$k pour $k \\in [2,...,K]$ |\n|Conditions d'application |Non-séparation complète, absence de sur-dispersion ou de sous-dispersion, Indépendance des alternatives non pertinentes |\n:::\n:::\n\n\n#### Conditions d'application {#sec-08241}\n\nLes conditions d’application sont les mêmes que pour un modèle binomial, avec l’ajout de l’hypothèse sur **l’indépendance des alternatives non pertinentes**. Cette dernière suppose que le choix entre deux catégories est indépendant des catégories proposées. Voici un exemple simple pour illustrer cette hypothèse: admettons que nous disposons d’une trentaine de personnes et que nous leur demandons la couleur de leurs yeux. Cette variable ne serait pas affectée par la présence de nouvelles couleurs en dehors de notre échantillon. En revanche, si nous leur demandons de choisir un mode de transport parmi une liste pour se rendre à leur lieu de travail, leur réponse serait nécessairement affectée par la liste des modes de transport disponibles. Les tests développés pour vérifier cette hypothèse sont connus pour leur [faible fiabilité](https://statisticalhorizons.com/iia). Il est plus pertinent de décider théoriquement si cette hypothèse est valide ou non. Dans le cas contraire, il est possible d’utiliser une classe de modèle logistique plus rare: le modèle logistique imbriqué. \n\nNotez également que le grand nombre de paramètres dans ce type de modèle implique de disposer d’un plus grand nombre d’observations afin d'avoir suffisamment d’information dans chaque catégorie pour ajuster tous les paramètres.\n\nPour vérifier la présence de sur-dispersion, il est possible, dans le cas du modèle multinomial, de calculer le rapport entre le khi-deux de Pearson et le nombre de degrés de liberté du modèle. Si ce rapport est supérieur à 1 (des valeurs jusqu'à 1,15 ne sont pas problématiques), alors le modèle souffre de sur-dispersion [@Sasmultinom]. Le khi-deux de Pearson est simplement la somme des résidus de Pearson au carré dans le cas d'un modèle GLM.\n\n$$\n\\chi^2 = \\sum_{i=1}^N\\sum_{c=1}^K{\\frac{(y_{ic} - p_{ic})^2}{p_{ic}}}\n$$ {#eq-glm15}\n\nAvec $y_{ic}$ 1 si l'observation *i* appartient à la catégorie *c*, 0 autrement, $p_{ic}$ la probabilité prédite pour l'observation *i* d'appartenir à la catégorie *c*, *N* le nombre d'observations et *K* le nombre de catégories.\n\nLe ratio est ensuite calculé comme suit: $\\frac{\\chi^2}{(N - p)(K-1)}$, avec *N* le nombre d'observations et *K* le nombre de modalités dans la variable *Y*. Si ce ratio est égal ou supérieur à 1, alors le modèle souffre de sur-dispersion, si le ratio est inférieur à 1, le modèle souffre de sous-dispersion. Un léger écart (> 0,15) n'est pas considéré comme problématique. \n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Le modèle logistique imbriqué**\n:::\n::: bloc_aller_loin-body\nDu fait de sa proximité avec les modèles à effets mixtes que nous abordons au [chapitre @sec-chap09], nous ne détaillons pas ici le modèle logistique imbriqué, mais présentons plutôt son principe général. Il s’agit d’une généralisation du modèle logistique multinomial basé sur l’idée que certaines catégories pourraient être regroupées dans des « nids » (*nest* en anglais). Dans ces groupes, les erreurs peuvent être corrélées, indiquant ainsi que si une catégorie est manquante, une autre catégorie du même groupe sera préférée. Un paramètre $\\lambda$ contrôle spécifiquement cette corrélation et permet de mesurer sa force une fois le modèle ajusté. Il peut être pertinent de comparer un modèle imbriqué à un modèle multinomial pour déterminer lequel des deux est le mieux ajusté aux données.\n:::\n:::\n\n#### Exemple appliqué dans R {#sec-08242}\n\nPour cet exemple, nous reproduisons une partie de l'analyse effectuée dans l'étude de @mcfadden2016examining. Cet article s'intéresse aux écarts entre les croyances des individus et les connaissances scientifiques sur les sujets des OGM et du réchauffement climatique. Les auteurs utilisent pour cela des données issues d'une enquête auprès de 961 individus formant un échantillon représentatif de la population des États-Unis. Les données issues de cette enquête sont téléchargeables sur le [site de l'éditeur](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0166140), ce qui nous permet ici de reproduire l'analyse effectuée par les auteurs. Deux questions sont centrales dans l'enquête : \n\n* Dans quelle mesure êtes-vous en accord ou en désaccord avec la phrase suivante : les plantations génétiquement modifiées sont sans danger pour la consommation ?\n* Dans quelle mesure êtes-vous en accord ou en désaccord avec la phrase suivante : la Terre se réchauffe du fait des activités humaines ?\n\nPour ces deux questions, les répondants devaient sélectionner leur degré d'accord sur une échelle de Likert allant de 1 (fortement en désaccord) à 5 (fortement en accord). Les réponses à ces deux questions ont été utilisées pour former une variable multinomiale à quatre modalités :\n\n* A. Les individus sont en accord avec les deux propositions.\n* B. Les individus sont en désaccord sur les OGM, mais en accord sur le réchauffement climatique.\n* C. Les individus sont en accord sur les OGM, mais en désaccord sur le réchauffement climatique.\n* D. Les individus sont en désaccord avec les deux propositions.\n\nUn modèle logistique multinomial a été utilisé pour déterminer quels facteurs contribuent à la probabilité d'appartenir à ces différentes catégories. Les variables indépendantes présentes dans le modèle sont détaillées dans le @tbl-variablemultinom. Les auteurs avaient notamment conclu que : \n\n* Les effets des connaissances (réelles ou perçues) sur l'appartenance aux différentes catégories n'étaient pas uniformes et pouvaient varier en fonction du sujet.\n\n* L'orientation politique avait une influence significative sur les croyances.\n\n* Les répondants avec de plus hauts résultats au test de cognition CRT avaient plus souvent des opinions divergentes de la communauté scientifique.\n\n\n::: {#tbl-variablemultinom .cell tbl-cap='Variables indépendantes utilisées dans le modèle logistique multinomial'}\n::: {.cell-output-display}\n|Nom de la variable |signification |Type de variable |Mesure |\n|:------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------|:---------------------|:------------------------------------------------------------------------------|\n|PercepOGM |La recherche scientifique supporte ma vision sur la sécurité des plantes OGM |Variable ordinale |Échelle de Likert de 1 (fortement en désaccord) à 5 (fortement en accord) |\n|PercepRechClim |La recherche scientifique supporte ma vision sur le réchauffement climatique |Variable ordinale |Échelle de Likert de 1 (fortement en désaccord) à 5 (fortement en accord) |\n|ConnaisOGM |Niveau de connaissance sur les OGM |Variable ordinale |Nombre de réponses sur trois questions portant sur les OGM |\n|ConnaisRechClim |Niveau de connaissance sur le réchauffement climatique |Variable ordinale |Nombre de réponses sur trois questions portant sur le réchauffement climatique |\n|CRT |Score obtenu au Cognitive Reflection Test, utilisé pour déterminer la propension à faire preuve d’esprit d’analyse plutôt que choisir des réponses intuitives |Variable ordinale |Nombre de réponses sur trois questions pièges |\n|Parti |Orientation politique du répondant |Variable multinomiale |Républicain, démocrate et autre |\n|Sexe |Sexe du répondant |Variable binaire |Femme ou homme |\n|Age |Âge du répondant |Variable continue |Âge du répondant |\n|Revenu |Niveau de revenu du répondant |Variable ordinale |Échelle de 1 (moins de 20 000 $) à (140 000 $ et plus) |\n:::\n:::\n\n\n**Vérification des conditions d'application**\n\nAvant d'ajuster le modèle, nous commençons par vérifier l'absence de multicolinéarité excessive entre les variables indépendantes. Toutes les valeurs de VIF sont inférieures à 2, indiquant bien une absence de multicolinéarité.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndata_quest <- read.csv(\"data/glm/enquete_PublicOpinion_vs_Science.csv\")\n# Choix des valeurs de références dans les facteurs\ndata_quest$Parti <- relevel(as.factor(data_quest$Parti), ref = \"Democrate\")\ndata_quest$Sexe <- relevel(as.factor(data_quest$Sexe), ref = \"homme\")\nvif(glm(SCIGM ~ PercepOGM + PercepRechClim + ConnaisOGM + ConnaisRechClim +\n CRT + Parti + AGE + Sexe + Revenu, data = data_quest))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n GVIF Df GVIF^(1/(2*Df))\nPercepOGM 1.092693 1 1.045320\nPercepRechClim 1.177495 1 1.085125\nConnaisOGM 1.150662 1 1.072689\nConnaisRechClim 1.158438 1 1.076307\nCRT 1.155371 1 1.074882\nParti 1.130817 2 1.031212\nAGE 1.071655 1 1.035208\nSexe 1.064918 1 1.031949\nRevenu 1.049499 1 1.024451\n```\n:::\n:::\n\n\nLa seconde étape est d'ajuster le modèle et de vérifier l'absence de sur ou sous-dispersion. Pour ajuster le modèle, nous utilisons à nouveau la fonction `vglm` du *package* `VGAM`, avec le paramètre `family = multinomial()`. Le ratio entre la statistique de Pearson et le nombre de degrés de liberté du modèle indique une absence de sur ou sous-dispersion (1,04).\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Ajustement du modèle\nmodele <- vglm(Y ~ PercepOGM + PercepRechClim + ConnaisOGM + ConnaisRechClim + \n CRT + Parti + AGE + Sexe + Revenu,\n data = data_quest, \n family = multinomial(refLevel = \"A\"), model = T)\n# Calcul du Khi2 de Pearson\npred <- predict(modele, type= \"response\")\ncat_predict <- colnames(pred)[max.col(pred)]\nfreq_real <- table(data_quest$Y)\nfreq_pred <- table(cat_predict)\n\nkhi2 <- sum(residuals(modele, type = \"pearson\")^2)\n\nN <- nrow(data_quest)\np <- modele@rank\nr <- length(freq_real)\nratio <- khi2 / ((N-p)*(r-1))\nprint(ratio)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 1.045889\n```\n:::\n:::\n\n\nLa troisième étape de la vérification des conditions d'application est l'analyse des distances de Cook. À nouveau, puisque le modèle évalue la probabilité d'appartenir à $K-1$ catégorie, nous pouvons calculer $K-1$ résidus par observation et par extension $K-1$ distances de Cook. Aucune observation ne semble se détacher nettement dans la @fig-cookmultinom. Nous décidons donc pour le moment de conserver toutes les observations.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction des résidus\nres <- residuals(modele, type = \"pearson\")\n# Extraction de la hat matrix (nécessaire pour calculer la distance de Cook)\nhat <- hatvaluesvlm(modele)\n# Calcul des distances de Cook\nvals <- c(\"A\" , \"B\" , \"C\" , \"D\")\ncooks <- lapply(1:ncol(res), function(i){\n r <- res[,i]\n h <- hat[,i]\n cook <- (r/(1 - h))^2 * h/(1 * modele@rank)\n df <- data.frame(\n oid = 1:length(cook),\n cook = cook\n )\n plot <- ggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.2, color = rgb(0.1,0.1,0.1,0.4)) + \n labs(x = \"\", y = \"\", subtitle = paste(\"distance de Cook P(\",vals[[1]],\" VS \",vals[[i+1]],\")\", sep = \"\"))+\n theme(axis.ticks.x = element_blank(),\n axis.text.x = element_blank())\n return(plot)\n})\nggarrange(plotlist = cooks, ncol = 2, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle logistique multinomial](08-GLM_files/figure-html/fig-cookmultinom-1.png){#fig-cookmultinom fig-align='center' width=90%}\n:::\n:::\n\n\nAvant de passer à l'analyse de résidus simulés, il est pertinent de réaliser une analyse de type 3 afin de retirer les variables indépendantes dont l'apport au modèle est négligeable. La fonction `AnalyseType3` (disponible dans le code source de ce livre) permet d'effectuer cette opération automatiquement pour un objet de type `vglm`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ntableau <- AnalyseType3(modele, data_quest, verbose = FALSE)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n************************************* \nType 3 Analysis of Effects \n************************************* \nAIC model complet : 1855 \nloglikelihood model complet : 1789 \n variable retiree AIC loglikelihood p.val\n1 PercepOGM 1879 1819 0\n2 PercepRechClim 1941 1881 0\n3 ConnaisOGM 1910 1850 0\n4 ConnaisRechClim 1862 1802 0.0059\n5 CRT 1860 1800 0.0125\n6 Parti 1879 1825 0\n7 AGE 1852 1792 0.4469\n8 Sexe 1875 1815 0\n9 Revenu 1850 1790 0.7718\n```\n:::\n:::\n\n\nL'analyse de type 3 nous permet de déterminer que l'âge et le revenu sont deux variables dont la contribution au modèle est marginale. À titre de rappel, l’analyse de type 3 permet de comparer si le modèle complet (avec l’ensemble des variables indépendantes) est statistiquement mieux ajusté que le modèle avec l’ensemble des variables, sauf une. Or, dans notre cas, le modèle complet n’est pas statistiquement mieux ajusté que le modèle complet sans la variable *Age* (*p* = 0,44) et que le modèle complet sans la variable Revenu (*p* = 0,77). Cela signifie donc que ces deux variables n’ont pas un apport significatif au modèle et peuvent par conséquent être ôtées par parcimonie. Nous décidons donc de les retirer afin d'alléger les tableaux de coefficients que nous présentons plus loin. Nous pouvons également en conclure que ces deux variables ne jouent aucun rôle dans la propension à être en désaccord avec la recherche scientifique. Nous réajustons le modèle en conséquence.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodele2 <- vglm(Y ~ PercepOGM + PercepRechClim + ConnaisOGM + ConnaisRechClim + \n CRT + Parti + Sexe,\n data = data_quest, \n family = multinomial(refLevel = \"A\"), model = T)\n```\n:::\n\n\nNous pouvons à présent passer à l'analyse des résidus simulés. Le problème avec ce modèle est que sa variable *Y* est qualitative alors que la méthode d'analyse des résidus du *package* `DHARMa` ne peut traiter que des variables quantitatives, binaires ou ordinales. Pour rappel, il est possible d'envisager la prédiction d'un modèle logistique multinomial comme la prédiction d'une série de modèles logistiques binomiaux. En représentant nos prédictions de cette façon, nous pouvons à nouveau utiliser le *package* `DHARMa` pour analyser nos résidus. Veuillez noter que cette approche n'est pas optimale et que cette section du livre peut être amenée à changer.\n\nLa @fig-residusmultinom indique que les résidus suivent bien une distribution uniforme et qu'aucune valeur aberrante n'est observable.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraire les prédictions du modèle\ncategories <- c(\"B\" , \"C\" , \"D\")\npredicted <- predict(modele2, type = \"link\")\nnsim <- 1000\nilink <- function(x){exp(x)/(1+exp(x))}\n# Boucler sur chacune des catégories en dehors de la référence\ndata_sims <- lapply(1:ncol(predicted), function(i){\n categorie <- categories[[i]]\n # Extraire les observation de la catégorie i et de la référence\n test <- data_quest$Y %in% c(\"A\", categorie)\n # Calculer les probabilité d'appartenance à i\n values <- predicted[test,i]\n probs <- ilink(values)\n # Extraire les valeurs réelles et les convertir en 0 / 1\n real <- data_quest[test,]$Y\n real <- ifelse(real==\"A\",0,1)\n # Enregistrer ces différents éléments\n all_probs <- cbind(1-probs, probs)\n sub_data <- subset(data_quest, test)\n return(list(\"real\" = real, \"probs\" = all_probs, \"data\" = sub_data))\n})\n# Extraire les probabilités prédites\nall_probs <- do.call(rbind, lapply(data_sims, function(i){i$probs}))\n# Extraire les vrais catégories\nall_real <- unlist(lapply(data_sims, function(i){i$real}))\n# Effectuer les simulations\nsimulations <- lapply(1:nrow(all_probs), function(i){\n probs <- all_probs[i,]\n sims <- sample(c(0,1), size = nsim, replace = TRUE, prob = probs)\n return(sims)\n})\nmatsim <- do.call(rbind, simulations)\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = matsim, \n observedResponse = all_real,\n fittedPredictedResponse = all_probs[,2],\n integerResponse = TRUE)\n# Afficher les résultats\nplot(sim_res)\n```\n\n::: {.cell-output-display}\n![Diagnostic général des résidus simulés pour le modèle multinomial](08-GLM_files/figure-html/fig-residusmultinom-1.png){#fig-residusmultinom fig-align='center' width=65%}\n:::\n:::\n\n\nLa @fig-residusmultinom2 permet d'affiner le diagnostic en s'assurant de l'absence de relation entre les variables indépendantes et les résidus. Il est possible de remarquer des irrégularités pour les variables de perception (premier et second panneaux). Dans les deux cas, la catégorie 1 (fort désaccord) se démarque nettement des autres catégories. Nous proposons donc de les recoder comme des variables binaires : en désaccord / pas en désaccord pour minimiser cet effet.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Recomposer les données pour coller au format\n# étendu de la prediction\netend_data <- do.call(rbind, lapply(data_sims, function(i){i$data}))\npar(mfrow=c(3,3))\nvars <- c(\"PercepOGM\", \"PercepRechClim\", \"ConnaisOGM\", \n \"ConnaisRechClim\", \"CRT\", \"Parti\", \"Sexe\")\nfor(v in vars){\n plotResiduals(sim_res, etend_data[[v]], xlab= v, ylab = \"résidus\")\n}\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Diagnostic des variables indépendantes et des résidus simulés pour le modèle multinomial](images/Chap08/residusmultinom2.png){#fig-residusmultinom2 fig-align='center' width=100%}\n:::\n:::\n\n\nNous réajustons donc le modèle et recalculons nos résidus ajustés (masqué ici pour alléger le document). La @fig-residusmultinom3 nous confirme que le problème a été corrigé.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Convertir les variables ordinales et variables binaires\ndata_quest$PercepOGMDes <- ifelse(data_quest$PercepOGM %in% c(1,2), 1,0)\ndata_quest$PercepRechClimDes <- ifelse(data_quest$PercepRechClim %in% c(1,2), 1,0)\n# Réajuster le modèle\nmodele3 <- vglm(Y ~ PercepOGMDes + PercepRechClimDes + \n ConnaisOGM + ConnaisRechClim + \n CRT + Parti + Sexe,\n data = data_quest, \n family = multinomial(refLevel = \"A\"), model = T)\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Diagnostic général des résidus simulés pour le modèle multinomial (version 3)](images/Chap08/residusmultinom3.png){#fig-residusmultinom3 fig-align='center' width=65%}\n:::\n:::\n\n\nProfitons du fait que nous utilisons le *package* `VGAM` pour vérifier l'absence d'effet de Hauck-Donner qui indiquerait que des variables indépendantes provoquent des séparations parfaites. \n\n\n::: {.cell}\n\n```{.r .cell-code}\ntest <- hdeff(modele3)\ntest[test == TRUE]\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n(Intercept):2 (Intercept):3 \n TRUE TRUE \n```\n:::\n:::\n\n\nLa fonction nous informe que les constantes permettant de comparer le groupe C au groupe A, et le groupe D au groupe A provoquent des séparations parfaites. Cela s'explique notamment par le faible nombre d'observations tombant dans ces catégories. Considérant que comparativement à la catégorie A, être dans les catégories B, C, ou D signifie remettre en cause au moins un consensus scientifique, il peut être raisonnable de fixer la constante pour qu'elle soit la même pour les trois comparaisons. Ainsi, les chances de passer de A à un autre groupe ne dépenderaient pas du groupe en question, mais uniquement des variables indépendantes. Pour cela, nous pouvons forcer le modèle à n'ajuster qu'une seule constante avec la syntaxe suivante :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodele4 <- vglm(Y ~ PercepOGMDes + PercepRechClimDes + \n ConnaisOGM + ConnaisRechClim + \n CRT + Parti + Sexe,\n data = data_quest, \n family = multinomial(refLevel = \"A\",\n parallel = TRUE ~1), model = T)\ntest <- hdeff(modele4)\nprint(table(test))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\ntest\nFALSE \n 25 \n```\n:::\n\n```{.r .cell-code}\n# Calcul du khi2 de Pearson\npred <- predict(modele4, type= \"response\")\ncat_predict <- colnames(pred)[max.col(pred)]\nfreq_real <- table(data_quest$Y)\nfreq_pred <- table(cat_predict)\nkhi2 <- sum(residuals(modele4, type = \"pearson\")^2)\nN <- nrow(data_quest)\np <- modele4@rank\nr <- length(freq_real)\nratio <- khi2 / ((N)*(r-1)-p)\nprint(ratio)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 1.010319\n```\n:::\n:::\n\n\nNous n'avons donc plus de séparation complète ni de sur ou sous-dispersion et les résidus simulés de la quatrième version du modèle sont toujours acceptables (@fig-residusmultinom4).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraire les prédictions du modèle\ncategories <- c(\"B\" , \"C\" , \"D\")\npredicted <- predict(modele4, type = \"link\")\nnsim <- 1000\nilink <- function(x){exp(x)/(1+exp(x))}\n\n# Boucler sur chacune des catégories en dehors de la référence\ndata_sims <- lapply(1:ncol(predicted), function(i){\n categorie <- categories[[i]]\n # Extraire les observation de la catégorie i et de la référence\n test <- data_quest$Y %in% c(\"A\", categorie)\n # Calculer les probabilité d'appartenance à i\n values <- predicted[test,i]\n probs <- ilink(values)\n # Extraire les valeurs réelles et les convertir en 0 / 1\n real <- data_quest[test,]$Y\n real <- ifelse(real==\"A\",0,1)\n # Enregistrer ces différents éléments\n all_probs <- cbind(1-probs, probs)\n sub_data <- subset(data_quest, test)\n return(list(\"real\" = real, \"probs\" = all_probs, \"data\" = sub_data))\n})\n\n# Extraire les probabilités prédites\nall_probs <- do.call(rbind, lapply(data_sims, function(i){i$probs}))\n\n# Extraire les vrais catégories\nall_real <- do.call(c, lapply(data_sims, function(i){i$real}))\n\n# Effectuer les simulations\nsimulations <- lapply(1:nrow(all_probs), function(i){\n probs <- all_probs[i,]\n sims <- sample(c(0,1), size = nsim, replace = TRUE, prob = probs)\n return(sims)\n})\nmatsim <- do.call(rbind, simulations)\n\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = matsim, \n observedResponse = all_real,\n fittedPredictedResponse = all_probs[,2],\n integerResponse = TRUE)\nplot(sim_res)\n```\n\n::: {.cell-output-display}\n![Diagnostic général des résidus simulés pour le modèle multinomial (version 4)](08-GLM_files/figure-html/fig-residusmultinom4-1.png){#fig-residusmultinom4 fig-align='center' width=65%}\n:::\n:::\n\n\n**Vérification l'ajustement du modèle**\n\nPuisque les conditions d'application du modèle sont respectées, nous pouvons à présent vérifier sa qualité d'ajustement.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodelenull <- vglm(Y ~ 1 ,\n data = data_quest, \n family = multinomial(refLevel = \"A\",\n parallel = TRUE ~ 1 + CRT)\n , model = T)\nrsqs(loglike.full = logLik(modele4),\n loglike.null = logLik(modelenull),\n full.deviance = deviance(modele4),\n null.deviance = deviance(modelenull),\n nb.params = modele4@rank,\n n = nrow(data_quest)\n)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n$`deviance expliquee`\n[1] 0.1750071\n\n$`McFadden ajuste`\n[1] 0.1530715\n\n$`Cox and Snell`\n[1] 0.3397248\n\n$Nagelkerke\n[1] 0.3746843\n```\n:::\n:::\n\n\nLe modèle parvient à expliquer 17,5 % de la déviance totale. Il obtient un R^2^ ajusté de McFadden de 0,15, et des R^2^ de Cox et Snell et de Nagelkerke de respectivement 0,34 et 0,37. Passons à la construction de la matrice de confusion pour analyser la capacité de prédiction du modèle.\n\n\n::: {.cell}\n\n```{.r .cell-code}\npreds <- predict(modele4, type = \"response\")\npred_cats <- colnames(preds)[max.col(preds)]\nreal <- data_quest$Y\nmatrices <- nice_confusion_matrix(real, pred_cats)\n\n# Afficher la matrice de confusion\nprint(matrices$confusion_matrix)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n rowsnames A B C D rs \ncolsnames \"\" \"A (reel)\" \"B (reel)\" \"C (reel)\" \"D (reel)\" \"Total\"\nA \"A (predit)\" \"482\" \"168\" \"75\" \"29\" \"754\" \nB \"B (predit)\" \"31\" \"88\" \"9\" \"20\" \"148\" \nC \"C (predit)\" \"10\" \"6\" \"18\" \"6\" \"40\" \nD \"D (predit)\" \"3\" \"4\" \"3\" \"9\" \"19\" \n \"Total\" \"526\" \"266\" \"105\" \"64\" \"961\" \n \"%\" \"54.7\" \"27.7\" \"10.9\" \"6.7\" NA \n rp \ncolsnames \"%\" \nA \"78.5\"\nB \"15.4\"\nC \"4.2\" \nD \"2\" \n NA \n NA \n```\n:::\n\n```{.r .cell-code}\n# Afficher les indicateurs de qualité de prédiction\nprint(matrices$indicators)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n rnames precision rappel F1 \nA \"A\" \"0.64\" \"0.92\" \"0.75\"\nB \"B\" \"0.59\" \"0.33\" \"0.43\"\nC \"C\" \"0.45\" \"0.17\" \"0.25\"\nD \"D\" \"0.47\" \"0.14\" \"0.22\"\nmacro_scores \"macro\" \"0.6\" \"0.62\" \"0.57\"\n \"Kappa\" \"0.27\" NA NA \n \"Valeur de p (precision > NIR)\" \"0\" NA NA \n```\n:::\n:::\n\n\nLa précision globale (macro) du modèle est de 60 % et dépasse significativement le seuil de non-information. L'indicateur de Kappa indique un accord modéré entre la prédiction et les valeurs réelles. Les catégories C et D sont les catégories avec la plus faible précision, indiquant ainsi que le modèle a tendance à manquer les prédictions pour les individus en désaccord avec le consensus scientifique sur le réchauffement climatique. Les indices de rappel sont également très faibles pour les catégories B, C et D, indiquant que très peu d'observations appartenant originalement à ces groupes ont bien été classées dans ces groupes. La capacité de prédiction du modèle est donc relativement faible.\n\n**Interprétation des résultats**\n\nPuisque nous disposons de quatre catégories dans notre variable *Y*, nous obtenons au final trois tableaux de coefficients. Il est possible de visualiser l'ensemble des coefficients du modèle avec la fonction `summary`, nous proposons les tableaux [-@tbl-coeffsmultinom1], [-@tbl-coeffsmultinom2] et [-@tbl-coeffsmultinom3] pour présenter l'ensemble des résultats.\n\n\n::: {.cell}\n\n:::\n\n::: {#tbl-coeffsmultinom1 .cell tbl-cap='Coefficients du modèle multinomial A versus B'}\n::: {.cell-output-display}\n|Variable | Coefficient| RC| val.p| RC 2,5 %| RC 97,5 %| sign.|\n|:-----------------|-----------:|-----:|-----:|--------:|---------:|-----:|\n|PercepOGMDes | 1,940| 6,989| 0,000| 4,221| 11,588| ***|\n|PercepRechClimDes | 0,430| 1,532| 0,305| 0,677| 3,456| |\n|ConnaisOGM | -0,330| 0,718| 0,000| 0,607| 0,852| ***|\n|ConnaisRechClim | 0,180| 1,197| 0,084| 0,980| 1,462| .|\n|CRT | 0,350| 1,417| 0,016| 1,073| 1,878| *|\n|*Parti* | | | | | | |\n|ref : Democrate | --| --| --| --| --| --|\n|autre | 0,660| 1,934| 0,001| 1,310| 2,858| ***|\n|Republicain | 0,650| 1,910| 0,003| 1,259| 2,915| **|\n|*Sexe* | | | | | | |\n|ref : homme | --| --| --| --| --| --|\n|femme | 1,280| 3,581| 0,000| 2,535| 5,053| ***|\n:::\n:::\n\n\nLe @tbl-coeffsmultinom1 compare donc le groupe A (en accord avec la recherche scientifique sur les deux sujets) et le groupe B (en désaccord sur la question des OGM). Les résultats indiquent que le fait de se percevoir en désaccord avec le consensus scientifique sur la question des OGM multiplie par sept les chances d'appartenir au groupe B comparativement au groupe A. Cependant, pour chaque bonne réponse supplémentaire sur les questions testant les connaissances sur les OGM, les chances d'appartenir au groupe B comparativement au groupe A diminuent de 28 %. Ainsi, un individu ayant répondu correctement aux trois questions verrait ses chances réduites de 63 % d'appartenir au groupe B ($exp(-\\text{0,33}\\times\\text{3})$). Il est intéressant de noter que les variables concernant le réchauffement climatique n'ont pas d'effet significatif ici. La variable CRT indique qu'à chaque bonne réponse supplémentaire au test de cognition, les chances d'appartenir au groupe B augmentent de 42 %. Un individu qui aurait répondu aux trois questions du test aurait donc 2,9 fois plus de chances d'appartenir au groupe B qu'au groupe A. Concernant le parti politique, comparativement à une personne se déclarant plus proche du parti démocrate, les personnes proches du parti républicain ou d'un autre parti ont près de deux fois plus de chances d'appartenir au groupe B. Enfin, une femme, comparativement à un homme, a 3,6 fois plus de chance d'appartenir au groupe B.\n\n\n::: {#tbl-coeffsmultinom2 .cell tbl-cap='Coefficients du modèle multinomial A versus C'}\n::: {.cell-output-display}\n|variable | Coefficient| RC| val.p| RC 2,5 %| RC 97,5 %| sign.|\n|:-----------------|-----------:|-----:|-----:|--------:|---------:|-----:|\n|PercepOGMDes | -0,180| 0,834| 0,705| 0,326| 2,138| |\n|PercepRechClimDes | 2,060| 7,821| 0,000| 3,819| 16,119| ***|\n|ConnaisOGM | -0,110| 0,896| 0,287| 0,733| 1,094| |\n|ConnaisRechClim | 0,280| 1,323| 0,024| 1,041| 1,682| *|\n|CRT | 0,240| 1,275| 0,149| 0,914| 1,768| |\n|*Parti* | | | | | | |\n|ref : Democrate | --| --| --| --| --| --|\n|autre | -0,190| 0,828| 0,496| 0,482| 1,433| |\n|Republicain | 0,920| 2,512| 0,000| 1,584| 4,015| ***|\n|*Sexe* | | | | | | |\n|ref : homme | --| --| --| --| --| --|\n|femme:1 | -0,450| 0,640| 0,040| 0,419| 0,980| *|\n:::\n:::\n\n\nLe @tbl-coeffsmultinom2 compare les groupes A et C (en désaccord sur le réchauffement climatique). Il est intéressant de noter ici que se percevoir en désaccord avec la recherche scientifique est associé avec une forte augmentation des chances d'appartenir au groupe C. Cependant, un plus grand nombre de bonnes réponses aux questions sur le réchauffement climatique est également associé avec une augmentation des chances (30 % à chaque bonne réponse supplémentaire) d'appartenir au groupe C. Le CRT n'a cette fois-ci pas d'effet. Se déclarer proche du parti républicain, comparativement au parti démocrate, multiplie les chances par 2,5 d'appartenir au groupe C. Comparativement au tableau précédent, le fait d'être une femme diminue les chances de 36 % d'appartenir au groupe C.\n\n\n::: {#tbl-coeffsmultinom3 .cell tbl-cap='Coefficients du modèle multinomial A versus D'}\n::: {.cell-output-display}\n|variable | Coefficient| RC| val.p| RC 2,5 %| RC 97,5 %| sign.|\n|:-----------------|-----------:|------:|-----:|--------:|---------:|-----:|\n|PercepOGMDes | 1,500| 4,488| 0,000| 2,270| 8,935| ***|\n|PercepRechClimDes | 2,440| 11,501| 0,000| 5,312| 25,028| ***|\n|ConnaisOGM | -0,480| 0,621| 0,000| 0,492| 0,787| ***|\n|ConnaisRechClim | 0,130| 1,140| 0,399| 0,844| 1,553| |\n|CRT | 0,340| 1,409| 0,119| 0,914| 2,160| |\n|*Parti* | | | | | | |\n|ref : Democrate | --| --| --| --| --| --|\n|autre | 0,190| 1,211| 0,531| 0,664| 2,203| |\n|Republicain | 0,630| 1,872| 0,038| 1,041| 3,387| *|\n|*Sexe* | | | | | | |\n|ref : homme | --| --| --| --| --| --|\n|femme:1 | -0,110| 0,896| 0,664| 0,543| 1,477| |\n:::\n:::\n\n\nLe dernier tableau ([-@tbl-coeffsmultinom3]) compare le groupe A au groupe D (en désaccord sur les deux sujets). Les variables les plus importantes sont une fois encore le fait de se sentir en désaccord avec la recherche scientifique et le degré de connaissance sur les OGM. La variable concernant le parti politique est significative au seuil 0,05 et exprime toujours une tendance accrue pour les individus du parti républicain à appartenir au groupe D.\n\nNos propres conclusions corroborent celles de l'article original. Une des conclusions intéressantes est que le rejet du consensus scientifique ne semble pas nécessairement être associé à un déficit d'information ni à une plus faible capacité analytique, mais relèverait davantage d'une polarisation politique. Notez que cette littérature sur les croyances et la confiance dans la recherche est complexe, si le sujet vous intéresse, la discussion de l'article de @mcfadden2016examining est un bon point de départ.\n\n\n### Conclusion sur les modèles pour des variables qualitatives\n\nNous avons vu dans cette section, les trois principales formes de modèles GLM pour modéliser une variable binaire (modèle binomial), une variable ordinale (modèle de cotes proportionnel) et une variable multinomiale (modèle multinomial). Pour ces trois modèles, nous avons vu que la distribution utilisée est toujours la distribution binomiale et la fonction de lien logistique. Les coefficients obtenus s'interprètent comme des rapports de cotes, une fois qu'ils sont transformés avec la fonction exponentielle. \n\n## Modèles GLM pour des variables de comptage {#sec-083}\n\nDans cette section, nous présentons les principaux modèles utilisés pour modéliser des variables de comptage. Il peut s'agir de variables comme le nombre d'accidents à une intersection, le nombre de cafés par quartier, le nombre de cas d'une maladie donnée par entité géographique, etc.\n\n### Modèle de Poisson {#sec-0831}\n\nLe modèle GLM de base pour modéliser une variable de comptage est le modèle de Poisson. Pour rappel, la distribution de Poisson a un seul paramètre: $\\lambda$. Il représente le nombre moyen d'évènements observés sur l’intervalle de temps d'une observation, ainsi que la dispersion de la distribution. En conséquence, $\\lambda$ doit être un nombre strictement positif; autrement dit, nous ne pouvons pas observer un nombre négatif d'évènements. Il est donc nécessaire d’utiliser une fonction de lien pour contraindre l’équation de régression sur l’intervalle $[0 ,+\\infty]$. La fonction la plus utilisée est le logarithme naturel (*log*) dont la réciproque est la fonction exponentielle (*exp*).\n\n\n::: {#tbl-poissondentity .cell tbl-cap='Carte d\\'identité du modèle de Poisson'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:-------------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable de comptage |\n|Distribution utilisée |Poisson |\n|Formulation |$Y \\sim Poisson(\\lambda)$ \\newline $g(\\lambda) = \\beta_0 + \\beta X$ \\newline $g(x) =log(x)$ |\n|Fonction de lien |log |\n|Paramètre modélisé |$\\lambda$ |\n|Paramètres à estimer |$\\beta_0$, $\\beta$ |\n|Conditions d'application |Absence d’excès de zéros, absence de sur-dispersion ou de sous-dispersion |\n:::\n:::\n\n\n#### Interprétation des paramètres {#sec-08311}\n\nLes coefficients du modèle expriment l’effet du changement d’une unité des variables *X* sur $\\lambda$ (le nombre de cas) dans l’échelle logarithmique (*log-scale*). Pour rappel, l’échelle logarithmique est multiplicative : si nous convertissons les coefficients dans leur échelle originale avec la fonction exponentielle, leur effet n’est plus additif, mais multiplicatif. Prenons un exemple concret, admettons que nous avons ajusté un modèle de Poisson à une variable de comptage *Y* avec deux variables $X_1$ et $X_2$ et que nous avons obtenus les coefficients suivants :\n\n$\\beta_0 = 1,8 \\text{; } \\beta_1 = 0,5 \\text{; } \\beta_2 = -1,5$\n\nL’interprétation basique (sur l’échelle logarithmique) est la suivante : une augmentation d'une unité de la variable $X_1$ est associée avec une augmentation de 0,5 du logarithme du nombre de cas attendus. Une augmentation d'une unité de la variable $X_2$ est associée avec une réduction de 1,5 unité du logarithme du nombre de cas attendus. Avec la conversion avec la fonction exponentielle, nous obtenons alors : \n\n* $exp\\mbox{(0,5) = 1,649}$, soit une multiplication par 1,649 du nombre de cas attendu (aussi appelé taux d'incident) à chaque augmentation d’une unité de $X_1$;\n\n* $exp\\mbox{(-1,5) = 0,223}$, soit une division par 4,54 (1/0,223) du nombre de cas attendu (aussi appelé taux d'incident) à chaque augmentation d’une unité de $X_2$.\n\nUtilisons maintenant notre équation pour effectuer une prédiction si $X_1 = 1$ et $X_2 = 1$.\n\n$\\lambda = exp(\\mbox{1,8} + (\\mbox{0,5}\\times 1) + (\\mbox{-1,5}\\times1)) = \\mbox{2,225}$\n\nSi nous augmentons $X_1$ d’une unité, nous obtenons alors : \n\n$\\lambda = exp(1,8 + (\\mbox{0,5}\\times 2) + (\\mbox{-1,5}\\times1)) = \\mbox{3,670}$\n\nEn ayant augmenté d’une unité $X_1$, nous avons multiplié notre résultat par 1,649 ($\\mbox{2,225} \\times \\mbox{1,649 = 3,670}$).\n\nNotez que ces effets se multiplient entre eux. Si nous augmentons à la fois $X_1$ et $X_2$ d'une unité chacune, nous obtenons : $\\lambda = exp(1,8 + (\\mbox{0,5} \\times 2) + (\\mbox{-1,5} \\times 2)) = \\mbox{0,818}$, ce qui correspond bien à $\\mbox{2,225} \\times \\mbox{1,649} \\text{ (effet de }X_1\\text{)} \\times \\mbox{0,223} \\text{ (effet de }X_2\\text{)} = \\mbox{0,818}$.\n\nIl existe des fonctions dans R qui calculent ces prédictions à partir des équations des modèles. Il est cependant essentiel de bien saisir ce comportement multiplicatif induit par la fonction de lien *log*.\n\n#### Conditions d'application {#sec-08312}\n\nPuisque la distribution de Poisson n’a qu’un seul paramètre, le modèle GLM de Poisson est exposé au même problème potentiel de sur-dispersion que les modèles binomiaux de la section précédente. Référez-vous à la [section @sec-08212] pour davantage de détails sur le problème posé par la sur-dispersion. Pour détecter une potentielle sur-dispersion dans un modèle de Poisson, il est possible, dans un premier temps, de calculer le ratio entre la déviance du modèle et son nombre de degrés de liberté [@Saspoiss]. Ce ratio doit être proche de 1, s'il est plus grand, le modèle souffre de sur-dispersion.\n\n$$\n\\hat{\\phi} = \\frac{D(modele)}{N-p}\n$$ {#eq-glm16}\n\navec $N$ et $p$ étant respectivement les nombres d'observations et de paramètres. Il est également possible de tester formellement si la sur-dispersion est significative avec un test de dispersion.\n\nLa question de l’excès de zéros a été abordée dans la [section @sec-poissonzero] du [chapitre @sec-chap02]. Il s’agit d’une situation où un plus grand nombre de zéros sont présents dans les données que ce que suppose la distribution de Poisson. Dans ce cas, il convient d'utiliser la distribution de Poisson avec excès de zéros.\n\n#### Exemple appliqué dans R {#sec-08313}\n\nPour cet exemple, nous reproduisons l’analyse effectuée dans l’article de @cloutier2014carrefours. L’enjeu de cette étude était de modéliser le nombre de piétons blessés autour de plus de 500 carrefours dans les quartiers centraux de Montréal. Pour cela, trois types de variables étaient utilisées : des variables décrivant l’intersection, des variables décrivant les activités humaines dans un rayon d'un kilomètre autour de l’intersection et des variables représentant le trafic routier autour de l’intersection. Un effet direct de ce type d’étude est bien évidemment l’établissement de meilleures pratiques d’aménagement réduisant les risques encourus par les piétons lors de leurs déplacements en ville. Le @tbl-variablepoiss présente l'ensemble des variables utilisées dans l'analyse.\n\n\n::: {#tbl-variablepoiss .cell tbl-cap='Variables indépendantes utilisées dans le modèle de Poisson'}\n::: {.cell-output-display}\n|Nom de la variable |Signification |Type de variable |Mesure |\n|:------------------|:---------------------------------------------------------------------------------|:-----------------|:----------------------------------------------------------------------------------------------------|\n|Feux_auto |Présence de feux de circulation |Variable binaire |0 = absence; 1 = présence |\n|Feux_piet |Présence de feux de traversée pour les piétons |Variable binaire |0 = absence; 1 = présence |\n|Pass_piet |Présence d’un passage piéton |Variable binaire |0 = absence; 1 = présence |\n|Terreplein |Présence d’un terre-plein central |Variable binaire |0 = absence; 1 = présence |\n|Apaisement |Présence de mesure d’apaisement de la circulation |Variable binaire |0 = absence; 1 = présence |\n|LogEmploi |Logarithme du nombre d’emplois dans un rayon d’un kilomètre |Variable continue |Logarithme du nombre d’emplois. Utilisation du logarithme, car la variable est fortement asymétrique |\n|Densite_pop |Densité de population dans un rayon d’un kilomètre |Variable continue |Habitants par hectare |\n|Entropie |Diversité des occupations du sol dans un rayon d’un kilomètre (indice d'entropie) |Variable continue |Mesure de 0 à 1; 0 = spécialisation parfaite; 1 = diversité parfaite |\n|DensiteInter |Densité d’intersections dans un rayon d’un kilomètre (connexité) |Variable continue |Nombre d’intersection par km2 |\n|Artere |Présence d’une artère à l’intersection |Variable binaire |0 = absence; 1 = présence |\n|Long_arterePS |Longueur d’artère dans un rayon d’un kilomètre |Variable continue |Exprimée en mètres |\n|NB_voies5 |Présence d’une cinq voies à l’intersection |Variable binaire |0 = absence; 1 = présence |\n:::\n:::\n\n\nLa distribution originale de la variable est décrite à la @fig-distripoissmod. Les barres grises représentent la distribution du nombre d'accidents et les barres rouges une distribution de Poisson ajustée sans variable indépendante (modèle nul). Ce premier graphique peut laisser penser qu’un modèle de Poisson n'est pas nécessairement le plus adapté considérant le grand nombre d’intersections pour lesquelles nous n’avons aucun accident. Cependant, rappelons que la variable *Y* n'a pas besoin de suivre une distribution de Poisson. Dans un modèle GLM, l'hypothèse que nous formulons est que la variable dépendante (*Y*) **conditionnée par les variables indépendantes (*X*)** suit une certaine distribution (ici Poisson).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Chargement des données\ndata_accidents <- read.csv(\"data/glm/accident_pietons.csv\", sep = \";\")\n# Ajustement d'une distribution de Poisson sans variable indépendante\nlibrary(fitdistrplus)\nmodel_poisson <- fitdist(data_accidents$Nbr_acci, distr = \"pois\")\n# Création d'un graphique pour comparer les deux distributions\ndfpoisson <- data.frame(x=c(0:19),\n y = dpois(0:19, model_poisson$estimate)\n)\ncounts <- data.frame(table(data_accidents$Nbr_acci))\nnames(counts) <- c(\"nb_accident\",'frequence')\ncounts$nb_accident <- as.numeric(as.character(counts$nb_accident))\ncounts$prop <- counts$frequence / sum(counts$frequence)\nggplot() + \n geom_bar(aes(x = nb_accident, weight = prop, fill = \"real\"), width = 0.6, data = counts)+\n geom_bar(aes(x = x, weight = y, fill = \"adj\"), width = 0.15, data = dfpoisson)+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n scale_fill_manual(name = \"\",\n breaks = c(\"real\" , \"adj\"),\n labels = c(\"distribution originale\", \"distribution de Poisson\"),\n values = c(\"real\" = rgb(0.4,0.4,0.4), \"adj\" = \"red\"))+\n labs(subtitle = \"\",\n x = \"nombre d'accidents\",\n y = \"\")\n```\n\n::: {.cell-output-display}\n![Distribution originale du nombre d'accidents par intersection](08-GLM_files/figure-html/fig-distripoissmod-1.png){#fig-distripoissmod fig-align='center' width=65%}\n:::\n:::\n\n\n**Vérification des conditions d'application**\n\nComme précédemment, notre première étape est de vérifier l'absence de multicolinéarité excessive avec la fonction `vif` du *package* `car`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nvif(glm(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = poisson(link=\"log\"),\n data = data_accidents))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Feux_auto Feux_piet Pass_piet Terreplein Apaisement \n 2.861708 1.518668 2.321213 1.221683 1.059722 \n LogEmploi Densite_pop Entropie DensiteInter Long_arterePS \n 4.763692 1.153096 1.770904 2.040457 4.467841 \n Artere NB_voies5 \n 1.887728 1.520514 \n```\n:::\n:::\n\n\nToutes les valeurs de VIF sont inférieures à 5. Notons tout de même que le logarithme de l'emploi et la longueur d'artère dans un rayon d'un kilomètre ont des valeurs de VIF proches de 5. La seconde étape du diagnostic consiste à calculer et à visualiser les distances de Cook.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Ajustement d'une première version du modèle\nmodele <- glm(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = poisson(link=\"log\"),\n data = data_accidents)\n\n# Calcul des distances de Cook\ncooksd <- cooks.distance(modele)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, alpha = 0.5)+\n labs(x = \"\",\n y = \"Distance de Cook\")\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle de Poisson](08-GLM_files/figure-html/fig-poisscookdist-1.png){#fig-poisscookdist fig-align='center' width=60%}\n:::\n:::\n\n\nLa @fig-poisscookdist signale la présence de trois observations avec des valeurs extrêmement fortes de distance de Cook. Nous les isolons dans un premier temps pour les analyser.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncas_etrange <- subset(data_accidents, cooksd>0.1)\nprint(cas_etrange)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Nbr_acci Feux_auto Feux_piet Pass_piet Terreplein Apaisement EmpTotBuffer\n1 19 1 1 1 1 0 7208.538\n26 7 0 0 1 0 0 1342.625\n428 0 1 1 1 0 1 13122.560\n Densite_pop Entropie DensiteInter Long_arterePS Artere NB_voies5 log_acci\n1 5980.923 0.8073926 42.41597 6955.00 1 1 2.995732\n26 2751.012 0.0000000 73.35344 2849.66 0 0 2.079442\n428 14148.827 0.6643891 109.25066 4634.20 0 0 0.000000\n catego_acci catego_acci2 Arret VAG sum_app LogEmploi AccOrdinal PopHa\n1 1 1 0 1 4 8.883021 2 5.980923\n26 1 1 1 1 3 7.202382 2 2.751012\n428 0 0 0 0 3 9.482088 0 14.148827\n```\n:::\n:::\n\n\nLes deux premiers cas sont des intersections avec de nombreux accidents (respectivement 19 et 7) qui risquent de perturber les estimations du modèle. Le troisième cas ne comprend en revanche aucun accident. Puisqu'il ne s'agit que de trois observations et que leurs distances de Cook sont très nettement supérieures aux autres, nous les retirons du modèle.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndata2 <- subset(data_accidents, cooksd<0.1)\n# Ajustement d'une première version du modèle\nmodele <- glm(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = poisson(link=\"log\"),\n data = data2)\n\n# Calcul des distances de Cook\ncooksd <- cooks.distance(modele)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, alpha = 0.5)+\n labs(x = \"\",\n y = \"distance de Cook\")\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle de Poisson après avoir retiré les valeurs aberrantes](08-GLM_files/figure-html/fig-poisscookdist2-1.png){#fig-poisscookdist2 fig-align='center' width=60%}\n:::\n:::\n\n\nLa @fig-poisscookdist2 montre que nous n'avons plus d'observations fortement influentes dans le modèle après avoir retiré les trois observations identifiées précédemment. Nous devons à présent vérifier l'absence de sur-dispersion.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Calcul du rapport entre déviance et nombre de degrés de liberté du modèle\ndeviance(modele)/(nrow(data2) - modele$rank)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 1.674691\n```\n:::\n:::\n\n\nLe rapport entre la déviance et le nombre de degrés de liberté du modèle est nettement supérieur à 1, indiquant une sur-dispersion excessive. Nous pouvons confirmer ce résultat avec la fonction `dispersiontest` du *package* `AER`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(AER)\n# Test de sur-dispersion\ndispersiontest(modele)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tOverdispersion test\n\ndata: modele\nz = 5.2737, p-value = 6.686e-08\nalternative hypothesis: true dispersion is greater than 1\nsample estimates:\ndispersion \n 1.891565 \n```\n:::\n:::\n\n\nContrairement à la forme classique d’un modèle de Poisson pour laquelle la dispersion attendue est de 1, le test nous indique qu’une dispersion de 1,89 serait mieux ajustée aux données. \n\nIl est également possible d'illuster cet écart à l'aide d'un graphique représentant les valeurs réelles, les valeurs prédites, ainsi que la variance (sous forme de barres d'erreurs) attendue par le modèle (@fig-surdisppoiss). Nous constatons ainsi que les valeurs réelles (en rouge) ont largement tendance à dépasser la variance attendue par le modèle, surtout pour les valeurs les plus faibles de la distribution. \n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction des prédictions du modèle\nlambdas <- predict(modele, type = \"response\")\n# Création d'un DataFrame pour contenir la prédiction et les vraies valeurs\ndf1 <- data.frame(\n lambdas = lambdas,\n reals = data2$Nbr_acci\n)\n# Calcul de l'intervalle de confiance à 95 % selon la distribution de Poisson\n# et stockage dans un second DataFrame\nseqa <- seq(0, round(max(lambdas)),1)\ndf2 <- data.frame(\n lambdas = seqa,\n lower = qpois(p = 0.025, lambda = seqa),\n upper = qpois(p = 0.975, lambda = seqa)\n)\n# Affichage des valeurs réelles et prédites (en rouge)\n# et de leur variance selon le modèle (en noir)\nggplot() + \n geom_errorbar(data = df2,\n mapping = aes(x = lambdas, ymin = lower, ymax = upper),\n width = 0.2, color = rgb(0.4,0.4,0.4)) + \n geom_point(data = df1, \n mapping = aes(x = lambdas, y = reals),\n color =\"red\", size = 0.5) + \n labs(x = \"valeurs prédites\",\n y = \"valeurs réelles\")\n```\n\n::: {.cell-output-display}\n![Représentation de la sur-dispersion des données dans le modèle de Poisson](08-GLM_files/figure-html/fig-surdisppoiss-1.png){#fig-surdisppoiss fig-align='center' width=60%}\n:::\n:::\n\n\nPour tenir compte de cette particularité des données, nous modifions légèrement le modèle pour utiliser une distribution de quasi-Poisson, intégrant spécifiquement un paramètre de dispersion. Cet ajustement ne modifie pas l'estimation des coefficients du modèle, mais modifie le calcul des erreurs standards et par extension les valeurs de *p* pour les rendre moins sensibles au problème de sur-dispersion. Une autre approche aurait été de calculer une version robuste des erreurs standards avec le *package* `sandwich` comme nous l'avons fait dans la [section @sec-0821] sur le modèle binomial. Après réajustement du modèle, le nouveau paramètre de dispersion estimé est de 1,92.\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Les quasi-distributions**\n:::\n::: bloc_notes-body\nLes distributions binomiale et de Poisson ne disposent chacune que d’un paramètre décrivant à la fois leur dispersion et leur espérance. Elles manquent donc de flexibilité et échouent parfois à représenter fidèlement des données avec une forte variance. Il existe donc d'autres distributions, respectivement les distributions quasi-binomiale et quasi-Poisson comprenant chacune un paramètre supplémentaire pour contrôler la dispersion. Bien que cette solution soit attrayante, il ne faut pas perdre de vue que la sur ou la sous dispersion peuvent être causées par l’absence de certaines variables explicatives, la sur-représentation de zéros, ou encore une séparation parfaite de la variable dépendante causée par une variable indépendante.\n:::\n:::\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodele2 <- glm(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = quasipoisson(link=\"log\"),\n data = data2)\n```\n:::\n\n\nNous pouvons à présent comparer la distribution originale des données et les simulations issues du modèle. Notez que contrairement à la distribution de Poisson simple, il n'existe pas dans R de fonction pour simuler des valeurs issues d'une distribution de quasi-Poisson. Il est cependant possible d'exploiter sa proximité théorique avec la distribution binomiale négative pour définir notre propre fonction de simulation. La @fig-comppoissdistr permet de comparer la distribution originale (en gris) et l'intervalle de confiance à 95 % des simulations (en rouge). Nous remarquons que le modèle semble capturer efficacement la forme générale de la distribution originale. À titre de comparaison, nous pouvons effectuer le même exercice avec la distribution de Poisson classique (le code n'est pas montré pour éviter les répétitions). La @fig-comppoissdistr2 montre qu'un simple modèle de Poisson est très éloigné de la distribution originale de *Y*.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Définition d'une fonction pour simuler des données quasi-Poisson\nrqpois <- function(n, lambda, disp) {\n rnbinom(n = n, mu = lambda, size = lambda/(disp-1))\n}\n# Extraction des valeurs prédites par le modèle\npreds <- predict(modele2, type = \"response\")\n# Génération de 1000 simulations pour chaque prédiction\ndisp <- summary(modele2)$dispersion\nnsim <- 1000\ncols <- lapply(1:length(preds), function(i){\n lambda <- preds[[i]]\n sims <- round(rqpois(n = nsim, lambda = lambda, disp = disp))\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Préparation des données pour le graphique (valeurs réelles)\ncounts <- data.frame(table(data2$Nbr_acci))\nnames(counts) <- c(\"nb_accident\",'frequence')\ncounts$nb_accident <- as.numeric(as.character(counts$nb_accident))\ncounts$prop <- counts$frequence / sum(counts$frequence)\n# Préparation des données pour le graphique (valeurs simulées)\ndf1 <- data.frame(count = 0:25)\ncount_sims <- lapply(1:nsim, function(i){\n sim <- mat_sims[,i]\n cnt <- data.frame(table(sim))\n df2 <- merge(df1, cnt, by.x = \"count\", by.y = \"sim\", all.x = TRUE, all.y = FALSE)\n df2$Freq <- ifelse(is.na(df2$Freq),0, df2$Freq)\n return(df2$Freq)\n})\ncount_sims <- do.call(cbind, count_sims)\ndf_sims <- data.frame(\n val = 0:25,\n med = apply(count_sims, MARGIN = 1, median),\n lower = apply(count_sims, MARGIN = 1, quantile, probs = 0.025),\n upper = apply(count_sims, MARGIN = 1, quantile, probs = 0.975)\n)\n\nggplot() + \n geom_bar(aes(x = nb_accident, weight = frequence), width = 0.6, data = counts)+\n geom_errorbar(aes(x = val, ymin = lower, ymax = upper),\n data = df_sims, color = \"red\", width = 0.6)+\n geom_point(aes(x = val, y = med), color = \"red\", size = 1.3, data = df_sims)+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n xlim(-1,12)+\n labs(subtitle = \"\",\n x = \"nombre d'accidents\",\n y = \"nombre d'occurrences\")\n```\n\n::: {.cell-output-display}\n![Comparaison de la distribution originale et des simulations pour le modèle de quasi-Poisson](08-GLM_files/figure-html/fig-comppoissdistr-1.png){#fig-comppoissdistr fig-align='center' width=65%}\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Comparaison de la distribution originale et des simulations pour le modèle de Poisson](08-GLM_files/figure-html/fig-comppoissdistr2-1.png){#fig-comppoissdistr2 fig-align='center' width=65%}\n:::\n:::\n\n\nLa prochaine étape du diagnostic est l'analyse des résidus simulés. La @fig-simrespoiss indique que les résidus du modèle suivent bien une distribution uniforme et qu'aucune valeur aberrante n'est observable.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Génération de 1000 simulations pour chaque prédiction\ndisp <- 1.918757 # trouvable dans le summary(modele2)\nnsim <- 1000\ncols <- lapply(1:length(preds), function(i){\n lambda <- preds[[i]]\n sims <- rqpois(n = nsim, lambda = lambda, disp = disp)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = data2$Nbr_acci,\n fittedPredictedResponse = modele2$fitted.values,\n integerResponse = TRUE)\nplot(sim_res)\n```\n\n::: {.cell-output-display}\n![Analyse globale des résidus simulés pour le modèle de quasi-Poisson](08-GLM_files/figure-html/fig-simrespoiss-1.png){#fig-simrespoiss fig-align='center' width=65%}\n:::\n:::\n\n\nPour affiner notre diagnostic, nous pouvons également comparer les résidus simulés et chaque variable indépendante. La @fig-simrespoiss2 n'indique aucune relation problématique entre nos variables indépendantes et les résidus.\n\n\n::: {.cell}\n\n```{.r .cell-code}\npar(mfrow=c(3,4))\nvars <- c(\"Feux_auto\", \"Feux_piet\", \"Pass_piet\", \"Terreplein\", \"Apaisement\",\n \"LogEmploi\", \"Densite_pop\", \"Entropie\", \"DensiteInter\",\n \"Long_arterePS\", \"Artere\", \"NB_voies5\")\nfor(v in vars){\n plotResiduals(sim_res, data2[[v]], xlab = v, main = \"\", ylab = \"résidus\")\n}\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Comparaison des résidus simulés et de chaque variable indépendante](images/Chap08/simrespoiss2.png){#fig-simrespoiss2 fig-align='center' width=100%}\n:::\n:::\n\n\n\nMaintenant que l'ensemble des diagnostics a été effectué, nous pouvons passer à la vérification de la qualité d'ajustement.\n\n**Vérification de la qualité d'ajustement**\n\nPour le calcul des pseudo-R^2^, notez qu'il n'existe pas à proprement parler de *loglikelihood* pour les quasi-distributions. Pour contourner ce problème, il est possible d'utiliser le *loglikelihood* d'un simple modèle de Poisson (puisque les coefficients ne changent pas), mais il est important de garder à l'esprit que ces pseudo-R^2^ seront d'autant plus faibles que la sur-dispersion originale était forte.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodelnull <- glm(Nbr_acci ~ 1,\n family = poisson(link=\"log\"),\n data = data2)\nrsqs(loglike.full = logLik(modele),\n loglike.null = logLik(modelnull),\n full.deviance = deviance(modele),\n null.deviance = deviance(modelnull),\n nb.params = modele$rank,\n n = nrow(data2))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n$`deviance expliquee`\n[1] 0.4805998\n\n$`McFadden ajuste`\n'log Lik.' 0.3258375 (df=13)\n\n$`Cox and Snell`\n'log Lik.' 0.7789704 (df=13)\n\n$Nagelkerke\n'log Lik.' 0.787958 (df=13)\n```\n:::\n:::\n\n\nLe modèle parvient ainsi à expliquer 48 % de la déviance totale. Il obtient un R^2^ ajusté de McFadden de 0,33 et un R^2^ de Cox et Snell de 0,78.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Calcul du RMSE\nsqrt(mean((predict(modele2, type = \"response\") - data2$Nbr_acci)**2))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 1.838026\n```\n:::\n\n```{.r .cell-code}\n# Nombre moyen d'accidents\nmean(data2$Nbr_acci)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 1.503984\n```\n:::\n:::\n\n\nL’erreur quadratique moyenne du modèle est de 1,84, ce que signifie qu’en moyenne le modèle se trompe d’environ deux accidents pour chaque intersection. Cette valeur est relativement élevée si nous la comparons avec le nombre moyen d’accidents, soit 1,5. Cela s’explique certainement par le grand nombre de zéros dans la variable *Y* qui tendent à tirer les prédictions vers le bas.\n\n**Interprétation des résultats**\n\nL'ensemble des coefficients du modèle sont accessibles via la fonction `summary`. Puisque la fonction de lien du modèle est la fonction `log`, il est pertinent de convertir les coefficients avec la fonction `exp` afin de pouvoir les interpréter sur l'échelle originale (`nombre d'accidents`) plutôt que l'échelle logarithmique (`log(nombre d'accidents)`). N'oubliez pas que ces effets sont multiplicatifs une fois transformés avec la fonction `exp`. Nous pouvons également utiliser les erreurs standards pour calculer des intervalles de confiance à 95 % des exponentiels des coefficients. Le @tbl-coeffpoiss présente l'ensemble des informations pertinentes pour l'interprétation des résultats.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Calcul des coefficients en exponentiel et des intervalles de confiance\ntableau <- summary(modele2)$coefficients\ncoeffs <- tableau[,1]\nerr.std <- tableau[,2]\nexpcoeff <- exp(coeffs)\nexp2.5 <- exp(coeffs - 1.96*err.std)\nexp975 <- exp(coeffs - 1.96*err.std)\npvals <- tableau[,4]\ntableauComplet <- cbind(coeffs, err.std, expcoeff, exp2.5, exp975, pvals)\n# print(tableauComplet)\n```\n:::\n\n::: {#tbl-coeffpoiss .cell tbl-cap='Résultats du modèle de quasi-Poisson'}\n::: {.cell-output-display}\n|Variable | Coeff.| exp(Coeff.)| Val.p| IC 2,5 % exp(Coeff.)| IC 97,5 % exp(Coeff.)| Sign.|\n|:-------------|------:|-----------:|-----:|--------------------:|---------------------:|-----:|\n|Constante | -3,680| 0,030| 0,000| 0,010| 0,090| ***|\n|Feux_auto | 1,100| 3,000| 0,000| 1,970| 4,660| ***|\n|Feux_piet | 0,330| 1,390| 0,009| 1,090| 1,790| **|\n|Pass_piet | 0,340| 1,400| 0,149| 0,880| 2,200| |\n|Terreplein | -0,360| 0,700| 0,099| 0,440| 1,050| .|\n|Apaisement | 0,290| 1,330| 0,157| 0,880| 1,950| |\n|LogEmploi | 0,230| 1,260| 0,017| 1,040| 1,520| *|\n|Densite_pop | 0,000| 1,000| 0,000| 1,000| 1,000| ***|\n|Entropie | -0,420| 0,660| 0,271| 0,320| 1,390| |\n|DensiteInter | 0,000| 1,000| 0,410| 1,000| 1,010| |\n|Long_arterePS | 0,000| 1,000| 0,684| 1,000| 1,000| |\n|Artere | 0,030| 1,030| 0,842| 0,780| 1,360| |\n|NB_voies5 | 0,640| 1,890| 0,000| 1,460| 2,440| ***|\n:::\n:::\n\n\nParmi les variables décrivant les aménagements de l’intersection, nous constatons que les présences d’un feu de circulation et d’un feu de traversée pour les piétons multiplient le nombre attendu d’accidents à une intersection par 3,0 et 1,39. Par contre, les présences d’un passage piéton, d’un terre-plein ou de mesures d’apaisement n’ont pas d’effets significatifs (valeurs de *p* > 0,05).\nConcernant les variables décrivant l’environnement à proximité des intersections, nous observons que la concentration d’emplois et la densité de population contribuent toutes les deux à augmenter le nombre d’accidents à une intersection, bien que leurs effets soient limités. Enfin, la présence d’une rue à cinq voies à l’intersection augmente le nombre d’accidents attendu à l’intersection de 89 %. Nous ne détaillons pas plus les résultats, car nous utilisons le même jeu de données dans les prochaines sections.\n\n### Modèle binomial négatif {#sec-0832}\n\nDans le cas où une variable de comptage est marquée par une sur ou sous-dispersion, la distribution de Poisson n’est pas en mesure de capturer efficacement sa variance. Pour contourner ce problème, il est possible d’utiliser la distribution binomiale négative plutôt que la distribution de Poisson (ou quasi-Poisson). Cette distribution peut être décrite comme une généralisation de la distribution de Poisson : elle inclut un second paramètre $\\theta$ contrôlant la dispersion. L’intérêt premier de ce changement de distribution est que l’interprétation des paramètres est la même pour les deux modèles, tout en contrôlant directement l'effet d'une potentielle sur ou sous-dispersion.\n\n\n::: {#tbl-nbdentity .cell tbl-cap='Carte d\\'identité du modèle binomial négatif'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:-------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable de comptage |\n|Distribution utilisée |Négative binomiale |\n|Formulation |$Y \\sim NB(\\mu,\\theta)$ \\newline $g(\\mu) = \\beta_0 + \\beta X$ \\newline $g(x) =log(x)$ |\n|Fonction de lien |log |\n|Paramètre modélisé |$\\mu$ |\n|Paramètres à estimer |$\\beta_0$, $\\beta$ et $\\theta$ |\n|Conditions d'application |Absence d’excès de zéros, respect du lien variance-moyenne |\n:::\n:::\n\n\n#### Conditions d'application {#sec-08321}\n\nLes conditions d'application d'un modèle binomial négatif sont presque les mêmes que celles d'un modèle de Poisson. La seule différence est que la condition d'absence de sur ou sous-dispersion est remplacée par une condition de respect du lien espérance-variance. En effet, dans un modèle binomial négatif, le paramètre de dispersion $\\theta$ est combiné avec $\\mu$ (l'espérance) pour exprimer la dispersion de la distribution. Dans le *package* `mgcv` que nous utilisons dans l'exemple, le lien entre $\\mu$, $\\theta$ et la variance est le suivant : \n\n$$\nvariance = \\mu + \\mu^{\\frac{2}{\\theta}}\n$$ {#eq-glm17}\n\nIl s'agit donc d'un **modèle hétéroscédastique** : sa variance n'est pas fixe, mais varie en fonction de sa propre espérance. Si celle-ci augmente, la variance augmente (comme pour un modèle de Poisson), et l'intensité de cette augmentation est contrôlée par le paramètre $\\theta$. Si cette condition n'est pas respectée, l'analyse des résidus simulés révélera un problème de dispersion.\n\n#### Exemple appliqué dans R {#sec-08322}\n\nDans l’exemple précédent avec le modèle de Poisson, nous avons observé une certaine sur-dispersion que nous avons contournée en utilisant un modèle de quasi-Poisson. Dans l’article original, les auteurs ont opté pour un modèle binomial négatif, ce que nous reproduisons ici. Les variables utilisées sont les mêmes que pour le modèle de Poisson. Nous utilisons le *package* `mgcv` et sa fonction `gam` pour ajuster le modèle.\n\n**Vérification des conditions d'application**\n\nNous avons vu précédemment que nos variables indépendantes ne sont pas marquées par une multicolinéarité forte. Il n'est pas nécessaire de recalculer les valeurs de VIF puisque nous utilisons les mêmes données. La première étape du diagnostic est donc de calculer les distances de Cook.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(mgcv)\n# Chargement des données\ndata_accidents <- read.csv(\"data/glm/accident_pietons.csv\", sep = \";\")\n# Ajustement d'une première version du modèle\nmodelnb <- gam(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + \n Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = nb(link=\"log\"),\n data = data_accidents)\n# Calcul et affichage des distances de Cook\ncooksd <- cooks.distance(modelnb)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, color = rgb(0.4,0.4,0.4)) +\n labs(x = \"\", y = \"distance de Cook\")+\n theme(axis.ticks.x = element_blank(),\n axis.text.x = element_blank())\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle binomial négatif](08-GLM_files/figure-html/fig-cookdistnb-1.png){#fig-cookdistnb fig-align='center' width=65%}\n:::\n:::\n\n\nNous observons, dans la @fig-cookdistnb, que quatre observations se distinguent très nettement des autres. \n\n\n::: {.cell}\n\n```{.r .cell-code}\ncas_etrange <- subset(data_accidents, cooksd > 0.03)\nprint(cas_etrange)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Nbr_acci Feux_auto Feux_piet Pass_piet Terreplein Apaisement EmpTotBuffer\n1 19 1 1 1 1 0 7208.538\n5 12 1 0 1 0 0 8585.350\n26 7 0 0 1 0 0 1342.625\n34 6 0 0 1 0 0 12516.410\n Densite_pop Entropie DensiteInter Long_arterePS Artere NB_voies5 log_acci\n1 5980.923 0.8073926 42.41597 6955.00 1 1 2.995732\n5 8655.430 0.7607852 89.11495 6412.27 0 0 2.564949\n26 2751.012 0.0000000 73.35344 2849.66 0 0 2.079442\n34 8950.942 0.4300549 74.91879 8443.01 1 0 1.945910\n catego_acci catego_acci2 Arret VAG sum_app LogEmploi AccOrdinal PopHa\n1 1 1 0 1 4 8.883021 2 5.980923\n5 1 1 0 1 4 9.057813 2 8.655430\n26 1 1 1 1 3 7.202382 2 2.751012\n34 1 1 1 0 3 9.434796 2 8.950942\n```\n:::\n:::\n\n\nIl s'agit à nouveau de quatre observations avec un grand nombre d'accidents. Nous décidons de les retirer du jeu de données pour ne pas fausser les résultats concernant l'ensemble des autres intersections. Dans une analyse plus détaillée, il serait judicieux de chercher à comprendre pourquoi ces quatre observations sont particulièrement accidentogènes.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndata2 <- subset(data_accidents, cooksd < 0.03)\n# Ajustement d'une première version du modèle\nmodelnb <- gam(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + \n Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = nb(link=\"log\"),\n data = data2)\n# Calcul et affichage des distances de Cook\ncooksd <- cooks.distance(modelnb)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, color = rgb(0.4,0.4,0.4)) +\n labs(x = \"\", y = \"distance de Cook\")+\n theme(axis.ticks.x = element_blank(),\n axis.text.x = element_blank())\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle binomial négatif (après avoir retiré quatre observations fortement influentes](08-GLM_files/figure-html/fig-cookdistnb2-1.png){#fig-cookdistnb2 fig-align='center' width=65%}\n:::\n:::\n\n\nAprès avoir retiré ces quatre observations, les distances de Cook ne révèlent plus d'observations fortement influentes dans le modèle (@fig-cookdistnb2). La prochaine étape du diagnostic est donc d'analyser les résidus simulés.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction de la valeur de theta\ntheta <- modelnb$family$getTheta(T)\nnsim <- 1000\n# Extraction des valeurs prédites par le modèle\nmus <- predict(modelnb, type = \"response\")\n# Calcul des simulations\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- rnbinom(n = nsim, mu = mu, size = theta)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calcul des résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = data2$Nbr_acci,\n fittedPredictedResponse = mus,\n integerResponse = TRUE)\n# Affichage du diagnostic\nplot(sim_res)\n```\n\n::: {.cell-output-display}\n![Diagnostic général des résidus simulés pour le modèle binomial négatif](08-GLM_files/figure-html/fig-diagresnb-1.png){#fig-diagresnb fig-align='center' width=65%}\n:::\n:::\n\n\nLa @fig-diagresnb présentant le diagnostic des résidus simulés, montre que ces derniers suivent bien une distribution uniforme et aucun problème de dispersion ni de valeurs aberrantes. La @fig-compnbdistr2 permet de comparer la distribution originale de la variable *Y* et les simulations issues du modèle (intervalles de confiance représentés en bleu). Nous constatons que le modèle parvient bien à reproduire la distribution originale, et ce, même pour les valeurs les plus extrèmes de la distribution.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction des valeurs prédites par le modèle\nmus <- predict(modelnb, type = \"response\")\n# Génération de 1000 simulations pour chaque prédiction\ntheta <- modelnb$family$getTheta(T)\nnsim <- 1000\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- round(rnbinom(n = nsim, mu = mu, size = theta))\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Préparation des données pour le graphique (valeurs réelles)\ncounts <- data.frame(table(data2$Nbr_acci))\nnames(counts) <- c(\"nb_accident\",'frequence')\ncounts$nb_accident <- as.numeric(as.character(counts$nb_accident))\ncounts$prop <- counts$frequence / sum(counts$frequence)\n# Préparation des données pour le graphique (valeurs simulées)\ndf1 <- data.frame(count = 0:25)\ncount_sims <- lapply(1:nsim, function(i){\n sim <- mat_sims[,i]\n cnt <- data.frame(table(sim))\n df2 <- merge(df1, cnt, by.x = \"count\", by.y = \"sim\", all.x = TRUE, all.y = FALSE)\n df2$Freq <- ifelse(is.na(df2$Freq),0, df2$Freq)\n return(df2$Freq)\n})\ncount_sims <- do.call(cbind, count_sims)\ndf_sims <- data.frame(\n val = 0:25,\n med = apply(count_sims, MARGIN = 1, median),\n lower = apply(count_sims, MARGIN = 1, quantile, probs = 0.025),\n upper = apply(count_sims, MARGIN = 1, quantile, probs = 0.975)\n)\n# Affichage du graphique\nggplot() + \n geom_bar(aes(x = nb_accident, weight = frequence), width = 0.6, data = counts)+\n geom_errorbar(aes(x = val, ymin = lower, ymax = upper),\n data = df_sims, color = \"blue\", width = 0.6)+\n geom_point(aes(x = val, y = med), color = \"blue\", size = 1.3, data = df_sims)+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n xlim(-1,12)+\n labs(subtitle = \"\",\n x = \"nombre d'accidents\",\n y = \"nombre d'occurrences\")\n```\n\n::: {.cell-output-display}\n![Comparaison de la distribution originale et des simulations pour le modèle binomial négatif](08-GLM_files/figure-html/fig-compnbdistr2-1.png){#fig-compnbdistr2 fig-align='center' width=65%}\n:::\n:::\n\n\nÀ titre de comparaison, nous pouvons à nouveau réaliser le graphique permettant de visualiser si la variance attendue par le modèle est proche de celle effectivement observée dans les données. Nous avons constaté avec ce graphique, lorsque nous ajustions un modèle de Poisson, que la variance des données était trop grande comparativement à celle attendue par le modèle (@fig-surdisppoiss).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction des prédictions du modèle\nmus <- predict(modelnb, type = \"response\")\n# Création d'un DataFrame pour contenir la prédiction et les vraies valeurs\ndf1 <- data.frame(\n mus = mus,\n reals = data2$Nbr_acci\n)\n# Calcul de l'intervalle de confiance à 95 % selon la distribution de Poisson\n# et stockage dans un second DataFrame\nseqa <- seq(0, round(max(mus)),1)\ndf2 <- data.frame(\n mus = seqa,\n lower = qnbinom(p = 0.025, mu = seqa, size = theta),\n upper = qnbinom(p = 0.975, mu = seqa, size = theta)\n)\n# Affichage des valeurs réelles et prédites (en rouge)\n# et de leur variance selon le modèle (en noir)\nggplot() + \n geom_errorbar(data = df2,\n mapping = aes(x = mus, ymin = lower, ymax = upper),\n width = 0.2, color = rgb(0.4,0.4,0.4)) + \n geom_point(data = df1, \n mapping = aes(x = mus, y = reals),\n color =\"red\", size = 0.5) + \n labs(x = \"valeurs prédites\",\n y = \"valeurs réelles\")\n```\n\n::: {.cell-output-display}\n![Représentation de la sur-dispersion des données dans le modèle de Poisson](08-GLM_files/figure-html/fig-surdispnb-1.png){#fig-surdispnb fig-align='center' width=65%}\n:::\n:::\n\n\nNous pouvons ainsi constater à la @fig-surdispnb que le modèle binomial négatif autorise une variance bien plus large que le modèle de Poisson et est ainsi mieux ajusté aux données.\n\n**Vérification de la qualité d'ajustement**\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Calcul des pseudo R2\nrsqs(loglike.full = logLik(modelnb),\n loglike.null = logLik(modelnull),\n full.deviance = deviance(modelnb),\n null.deviance = modelnb$null.deviance,\n nb.params = modelnb$rank,\n n = nrow(data2))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n$`deviance expliquee`\n[1] 0.458052\n\n$`McFadden ajuste`\n'log Lik.' 0.384353 (df=14)\n\n$`Cox and Snell`\n'log Lik.' 0.8304773 (df=14)\n\n$Nagelkerke\n'log Lik.' 0.8399731 (df=14)\n```\n:::\n\n```{.r .cell-code}\n# Calcul du RMSE\nsqrt(mean((predict(modelnb, type = \"response\") - data2$Nbr_acci)**2))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 1.825278\n```\n:::\n:::\n\n\nLe modèle parvient à expliquer 45 % de la déviance. Il obtient un R^2^ ajusté de McFadden de 0,14 et un R^2^ de Nagelkerke de 0,42. L’erreur moyenne quadratique de la prédiction est de 1,82, ce qui est identique au modèle de Poisson ajusté précédemment.\n\n**Interprétation des résultats**\n\nIl est possible d'accéder à l'ensemble des coefficients du modèle via la fonction `summary`. À nouveau, les coefficients doivent être convertis avec la fonction exponentielle (du fait de la fonction de lien *log*) et interprétés comme des effets multiplicatifs. Le @tbl-coeffsnb présente les coefficients estimés par le modèle. Les résultats sont très similaires à ceux du modèle de quasi-Poisson original. Nous notons cependant que la variable représentant la présence d'un feu pour piéton n'est plus significative au seuil de 0,05.\n\n\n::: {#tbl-coeffsnb .cell tbl-cap='Résultats du modèle binomial négatif'}\n::: {.cell-output-display}\n|Variable | Coeff.| exp(Coeff.)| Val.p| IC 2,5 % exp(Coeff.)| IC 97,5 % exp(Coeff.)| Sign.|\n|:-------------|------:|-----------:|-----:|--------------------:|---------------------:|-----:|\n|Constante | -3,880| 0,020| 0,000| 0,010| 0,080| ***|\n|Feux_auto | 1,130| 3,100| 0,000| 2,030| 4,710| ***|\n|Feux_piet | 0,350| 1,420| 0,016| 1,060| 1,900| *|\n|Pass_piet | 0,220| 1,240| 0,300| 0,830| 1,880| |\n|Terreplein | -0,340| 0,710| 0,155| 0,440| 1,140| |\n|Apaisement | 0,240| 1,270| 0,315| 0,790| 2,030| |\n|LogEmploi | 0,230| 1,260| 0,025| 1,030| 1,550| *|\n|Densite_pop | 0,000| 1,000| 0,000| 1,000| 1,000| ***|\n|Entropie | -0,170| 0,840| 0,669| 0,380| 1,860| |\n|DensiteInter | 0,000| 1,000| 0,925| 0,990| 1,010| |\n|Long_arterePS | 0,000| 1,000| 0,587| 1,000| 1,000| |\n|Artere | 0,110| 1,110| 0,497| 0,820| 1,510| |\n|NB_voies5 | 0,700| 2,010| 0,000| 1,480| 2,750| ***|\n:::\n:::\n\n\n### Modèle de Poisson avec excès fixe de zéros {#sec-0833}\n\nDans le cas où la variable *Y* comprendrait significativement plus de zéros que ce que suppose une distribution de Poisson, il est possible d’utiliser la distribution de Poisson avec excès de zéros. Pour rappel, cette distribution ajoute un paramètre *p* contrôlant pour la proportion de zéros dans la distribution. Du point de vue conceptuel, cela revient à formuler l’hypothèse suivante : dans les données que nous avons observées, deux processus distincts sont à l’œuvre. Le premier est issu d’une distribution de Poisson et l'autre produit des zéros qui s’ajoutent aux données. Les zéros produits par la distribution de Poisson sont appelés les **vrais zéros**, alors que ceux produits par le second phénomène sont appelés les **faux zéros**.\n\n\n::: {#tbl-poisszidentity .cell tbl-cap='Carte d\\'identité du modèle de Poisson avec excès fixe de zéros'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:------------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable de comptage |\n|Distribution utilisée |Poisson avec excès de zéros |\n|Formulation |$Y \\sim ZIP(\\mu,\\theta)$ \\newline $g(\\lambda) = \\beta_0 + \\beta X$ \\newline $g(x) =log(x)$ |\n|Fonction de lien |log |\n|Paramètre modélisé |$\\lambda$ |\n|Paramètres à estimer |$\\beta_0$, $\\beta$ et *p* |\n|Conditions d'application |Absence de sur-dispersion |\n:::\n:::\n\n\nDans cette formulation, *p* est fixé. Nous n’avons donc aucune information sur ce qui produit les zéros supplémentaires, mais seulement leur proportion totale dans le jeu de données.\n\n#### Interprétation des paramètres {#sec-08331}\n\nL’interprétation des paramètres est identique à celle d’un modèle de Poisson. Le paramètre *p* représente la proportion de faux zéros dans la variable *Y* une fois que les variables indépendantes sont contrôlées.\n\n#### Exemple appliqué dans R {#sec-08332}\n\nLa variable de comptage des accidents des piétons que nous avons utilisée dans les deux exemples précédents semble être une bonne candidate pour une distribution de Poisson avec excès de zéros. En effet, nous avons pu constater une sur-dispersion dans le modèle de Poisson original, ainsi qu’un nombre important d’intersections sans accident. Tentons donc d’améliorer notre modèle en ajustant un excès fixe de zéros. Nous utilisons la fonction `gamlss` du *package* `gamlss`.\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(gamlss)\nmodelzi <- gamlss(formula = Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet +\n Terreplein + Apaisement + LogEmploi + Densite_pop + \n Entropie + DensiteInter + Long_arterePS + Artere + NB_voies5,\n sigma.formula = ~1,\n family = ZIP(mu.link = \"log\", sigma.link=\"logit\"),\n data = data_accidents)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nGAMLSS-RS iteration 1: Global Deviance = 1516.53 \nGAMLSS-RS iteration 2: Global Deviance = 1514.656 \nGAMLSS-RS iteration 3: Global Deviance = 1514.52 \nGAMLSS-RS iteration 4: Global Deviance = 1514.508 \nGAMLSS-RS iteration 5: Global Deviance = 1514.506 \nGAMLSS-RS iteration 6: Global Deviance = 1514.506 \n```\n:::\n\n```{.r .cell-code}\nmodelnull <- glm(formula = Nbr_acci ~ 1,\n family = poisson(link=\"log\"),\n data = data_accidents)\n\n# Constante pour p\ncoeff_p <- modelzi$sigma.coefficients\ncat(\"Coefficient pour p =\", round(coeff_p,4))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nCoefficient pour p = -1.4376\n```\n:::\n\n```{.r .cell-code}\n# Calcul de la déviance expliquée\n1 - deviance(modelzi) / deviance(modelnull)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 0.08267513\n```\n:::\n\n```{.r .cell-code}\n# Calcul de la probabilité de base p d'être un faux 0\n# en appliquant l'inverse de la fonction logistique\nexp(-coeff_p) / (1+exp(-coeff_p))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n(Intercept) \n 0.80809 \n```\n:::\n:::\n\n\nNous constatons immédiatement que le modèle avec excès fixe de zéros est peu ajusté aux données. Cette version du modèle ne parvient à capter que 8 % de la déviance, ce qui s’explique facilement, car nous n’avons donné aucune variable au modèle pour distinguer les vrais et les faux zéros. Pour cela, nous devons passer au prochain modèle : Poisson avec excès ajusté de zéros. Notons tout de même que d'après ce modèle, 81 % des observations seraient des faux zéros.\n\n### Modèle de Poisson avec excès ajusté de zéros {#sec-0834}\n\nNous avons vu dans le modèle précédent que l’excès de zéro était conceptualisé comme la combinaison de deux phénomènes, l’un issu d’une distribution de Poisson que nous souhaitons modéliser, et l'autre générant des zéros supplémentaires. Il est possible d’aller plus loin que de simplement contrôler la proportion de zéros supplémentaires en modélisant explicitement ce second processus en ajoutant une deuxième équation au modèle. Cette deuxième équation a pour enjeu de modéliser *p* (la proportion de 0) à l’aide de variables indépendantes, ces dernières pouvant se retrouver dans les deux parties du modèle. L’idée étant que, pour chaque observation, le modèle évalue sa probabilité d’être un faux zéro (partie binomiale), et le nombre attendu d'accidents.\n\n\n::: {#tbl-poisszadentity .cell tbl-cap='Carte d\\'identité du modèle de Poisson avec excès ajusté de zéros'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable de comptage |\n|Distribution utilisée |Poisson avec excès de zéros |\n|Formulation |$Y \\sim ZIP(\\mu,\\theta)$ \\newline $g(\\mu) = \\beta_0 + \\beta X$ \\newline $s(p) = \\alpha_0 + \\alpha_X$ \\newline $g(x) =log(x)$ \\newline $s(x) = log(\\frac{x}{1-x})$ |\n|Fonction de lien |log et logistique |\n|Paramètre modélisé |$\\mu$ et *p* |\n|Paramètres à estimer |$\\beta_0$, $\\beta$, $\\alpha_0$ et $\\alpha$ |\n|Conditions d'application |Absence de sur-dispersion |\n:::\n:::\n\n\n#### Interprétation des paramètres {#sec-08341}\n\nL’interprétation des paramètres $\\beta_0$ et $\\beta$ est identique à celle d’un modèle de Poisson. Les paramètres $\\alpha_0$ et $\\alpha$ sont identiques à ceux d’un modèle binomial. Plus spécifiquement, ces derniers paramètres modélisent la probabilité d’observer des valeurs supérieures à zéro.\n\n#### Exemple appliqué {#sec-08342}\n\nNous avons vu, dans l’exemple précédent, que l’utilisation du modèle avec excès fixe de zéros pour les données d’accident des piétons aux intersections ne donnait pas de résultats satisfaisants. Nous tentons ici d’améliorer le modèle en ajoutant les variables indépendantes significatives du modèle Poisson dans la seconde équation de régression destinée à détecter les faux zéros.\n\n**Vérification des conditions d'application**\n\nPour un modèle de Poisson avec excès de zéros, il n'est pas possible de calculer les distances de Cook. Nous devons donc directement passer à l'analyse des résidus simulés.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Ajuster une première version du modèle\nmodelza <- gamlss(formula = Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet +\n Terreplein + Apaisement + LogEmploi + Densite_pop + \n Entropie + DensiteInter + Long_arterePS + Artere + NB_voies5,\n sigma.formula = ~1 + Feux_auto + Feux_piet + Densite_pop + NB_voies5,\n family = ZIP(mu.link = \"log\", sigma.link=\"logit\"),\n data = data_accidents)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nGAMLSS-RS iteration 1: Global Deviance = 1505.155 \nGAMLSS-RS iteration 2: Global Deviance = 1488.658 \nGAMLSS-RS iteration 3: Global Deviance = 1483.304 \nGAMLSS-RS iteration 4: Global Deviance = 1482.085 \nGAMLSS-RS iteration 5: Global Deviance = 1481.868 \nGAMLSS-RS iteration 6: Global Deviance = 1481.832 \nGAMLSS-RS iteration 7: Global Deviance = 1481.827 \nGAMLSS-RS iteration 8: Global Deviance = 1481.825 \nGAMLSS-RS iteration 9: Global Deviance = 1481.825 \n```\n:::\n\n```{.r .cell-code}\n# Extraire la prédiction des valeurs lambda\nlambdas <- predict(modelza, type = \"response\", what = \"mu\")\n# Extraire la prédiction des valeurs p\nps <- predict(modelza, type = \"response\", what = \"sigma\")\n# Calculer la combinaison de ces deux éléments\npreds <- lambdas * ps\n# Effectuer les 1000 simulations\nnsim <- 1000\ncols <- lapply(1:length(lambdas), function(i){\n lambda <- lambdas[[i]]\n p <- ps[[i]]\n sims <- rZIP(n = nsim, mu = lambda, sigma = p)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = data_accidents$Nbr_acci,\n fittedPredictedResponse = preds,\n integerResponse = TRUE)\n```\n:::\n\n::: {.cell}\n\n```{.r .cell-code}\nplot(sim_res)\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Diagnostic général des résidus simulés du modèle de Poisson avec excès de zéros ajusté\",](images/Chap08/diagzip.png){#fig-diagzip fig-align='center' width=65%}\n:::\n:::\n\n\n\nLa @fig-diagzip indique deux problèmes importants dans le modèle : la présence de valeurs aberrantes ainsi qu'un potentiel problème de dispersion. Nous commençons donc par identifier ces valeurs aberrantes.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Identification des outliers\nisOutlier <- outliers(sim_res, return = \"logical\", lowerQuantile = 0.001,\n upperQuantile = 0.999)\ncas_etrange <- subset(data_accidents, isOutlier)\nprint(cas_etrange)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Nbr_acci Feux_auto Feux_piet Pass_piet Terreplein Apaisement EmpTotBuffer\n1 19 1 1 1 1 0 7208.538\n2 13 1 1 1 0 0 15198.958\n5 12 1 0 1 0 0 8585.350\n26 7 0 0 1 0 0 1342.625\n34 6 0 0 1 0 0 12516.410\n44 5 0 0 0 0 0 4998.519\n482 0 0 0 0 0 0 1813.911\n Densite_pop Entropie DensiteInter Long_arterePS Artere NB_voies5 log_acci\n1 5980.923 0.8073926 42.41597 6955.00 1 1 2.995732\n2 11696.805 0.6432018 86.50445 9581.51 1 0 2.639057\n5 8655.430 0.7607852 89.11495 6412.27 0 0 2.564949\n26 2751.012 0.0000000 73.35344 2849.66 0 0 2.079442\n34 8950.942 0.4300549 74.91879 8443.01 1 0 1.945910\n44 8090.478 0.7879618 66.86856 4517.65 0 0 1.791759\n482 8988.260 0.4486079 60.93742 3821.78 1 0 0.000000\n catego_acci catego_acci2 Arret VAG sum_app LogEmploi AccOrdinal PopHa\n1 1 1 0 1 4 8.883021 2 5.980923\n2 1 1 0 1 4 9.628982 2 11.696805\n5 1 1 0 1 4 9.057813 2 8.655430\n26 1 1 1 1 3 7.202382 2 2.751012\n34 1 1 1 0 3 9.434796 2 8.950942\n44 1 1 1 1 4 8.516897 2 8.090478\n482 0 0 0 0 3 7.503240 0 8.988260\n```\n:::\n:::\n\n\nNous retirons des données les quelques observations pouvant avoir une trop forte influence sur le modèle. Après réajustement, la @fig-diagzip2 nous informe que nous n'avons plus de valeurs aberrantes restantes ni de fort problème de dispersion. En revanche, le premier quantile des résidus tant à être plus faible que ce que nous aurions pu nous attendre d'une distribution uniforme. Ce constat laisse penser que le modèle a du mal à bien identifier les faux zéros. Ce résultat n'est pas étonnant, car aucune variable n'avait été identifiée à cette fin dans l'article original [@cloutier2014carrefours] qui utilisait un modèle binomial négatif.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndata2 <- subset(data_accidents, isOutlier == FALSE)\n# Ajuster une première version du modèle\nmodelza <- gamlss(formula = Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet +\n Terreplein + Apaisement + LogEmploi + Densite_pop + \n Entropie + DensiteInter + Long_arterePS + Artere + NB_voies5,\n sigma.formula = ~1 + Feux_auto + Feux_piet + Densite_pop + NB_voies5,\n family = ZIP(mu.link = \"log\", sigma.link=\"logit\"),\n data = data2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nGAMLSS-RS iteration 1: Global Deviance = 1364.723 \nGAMLSS-RS iteration 2: Global Deviance = 1356.21 \nGAMLSS-RS iteration 3: Global Deviance = 1353.425 \nGAMLSS-RS iteration 4: Global Deviance = 1352.45 \nGAMLSS-RS iteration 5: Global Deviance = 1352.067 \nGAMLSS-RS iteration 6: Global Deviance = 1351.924 \nGAMLSS-RS iteration 7: Global Deviance = 1351.87 \nGAMLSS-RS iteration 8: Global Deviance = 1351.851 \nGAMLSS-RS iteration 9: Global Deviance = 1351.845 \nGAMLSS-RS iteration 10: Global Deviance = 1351.842 \nGAMLSS-RS iteration 11: Global Deviance = 1351.841 \n```\n:::\n\n```{.r .cell-code}\n# Extraire la prédiction des valeurs lambda\nlambdas <- predict(modelza, type = \"response\", what = \"mu\")\n# Extraire la prédiction des valeurs p\nps <- predict(modelza, type = \"response\", what = \"sigma\")\n# Calculer la combinaison de ces deux éléments\npreds <- lambdas * ps\n# Effectuer les 1000 simulations\nnsim <- 1000\ncols <- lapply(1:length(lambdas), function(i){\n lambda <- lambdas[[i]]\n p <- ps[[i]]\n sims <- rZIP(n = nsim, mu = lambda, sigma = p)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = data2$Nbr_acci,\n fittedPredictedResponse = preds,\n integerResponse = TRUE)\nplot(sim_res)\n```\n\n::: {.cell-output-display}\n![Diagnostic général des résidus simulés du modèle de Poisson avec excès de zéros ajusté (sans valeurs aberrantes)](08-GLM_files/figure-html/fig-diagzip2-1.png){#fig-diagzip2 fig-align='center' width=65%}\n:::\n:::\n\n\nNous pouvons une fois encore comparer des simulations issues du modèle et de la distribution originale de la variable *Y*. La @fig-compzipdistr montre clairement que les simulations du modèle (en bleu) sont très éloignées dans la distribution originale (en gris), ce qui remet directement en question la pertinence de ce modèle.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n#| # Extraire la prédiction des valeurs lambda\nlambdas <- predict(modelza, type = \"response\", what = \"mu\")\n# Extraire la prédiction des valeurs p\nps <- predict(modelza, type = \"response\", what = \"sigma\")\n# Génération de 1000 simulations pour chaque prédiction\nnsim <- 1000\ncols <- lapply(1:length(lambdas), function(i){\n lambda <- lambdas[[i]]\n p <- ps[[1]]\n sims <- round(rZIP(nsim, mu=lambda, sigma = p))\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Préparation des données pour le graphique (valeurs réelles)\ncounts <- data.frame(table(data2$Nbr_acci))\nnames(counts) <- c(\"nb_accident\",'frequence')\ncounts$nb_accident <- as.numeric(as.character(counts$nb_accident))\ncounts$prop <- counts$frequence / sum(counts$frequence)\n# Préparation des données pour le graphique (valeurs simulées)\ndf1 <- data.frame(count = 0:25)\ncount_sims <- lapply(1:nsim, function(i){\n sim <- mat_sims[,i]\n cnt <- data.frame(table(sim))\n df2 <- merge(df1, cnt, by.x = \"count\", by.y = \"sim\", all.x = TRUE, all.y = FALSE)\n df2$Freq <- ifelse(is.na(df2$Freq),0, df2$Freq)\n return(df2$Freq)\n})\ncount_sims <- do.call(cbind, count_sims)\ndf_sims <- data.frame(\n val = 0:25,\n med = apply(count_sims, MARGIN = 1, median),\n lower = apply(count_sims, MARGIN = 1, quantile, probs = 0.025),\n upper = apply(count_sims, MARGIN = 1, quantile, probs = 0.975)\n)\n# Affichage du graphique\nggplot() + \n geom_bar(aes(x = nb_accident, weight = frequence), width = 0.6, data = counts)+\n geom_errorbar(aes(x = val, ymin = lower, ymax = upper),\n data = df_sims, color = \"blue\", width = 0.6)+\n geom_point(aes(x = val, y = med), color = \"blue\", size = 1.3, data = df_sims)+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n xlim(-1,12)+\n labs(subtitle = \"\",\n x = \"nombre d'accidents\",\n y = \"nombre d'occurrences\")\n```\n\n::: {.cell-output-display}\n![Comparaison de la distribution originale et des simulations pour le modèle de Poisson avec excès de zéros ajusté](08-GLM_files/figure-html/fig-compzipdistr-1.png){#fig-compzipdistr fig-align='center' width=65%}\n:::\n:::\n\n\n**Vérification la qualité d'ajustement**\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodelenull <- glm(Nbr_acci ~ 1,\n family = poisson(link=\"log\"),\n data = data2)\n# Calcul des R2\nrsqs(loglike.full = logLik(modelza),\n loglike.null = logLik(modelenull),\n full.deviance = deviance(modelza),\n null.deviance = deviance(modelenull),\n nb.params = modelza$sigma.df + modelza$mu.df,\n n = nrow(data2)\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n$`deviance expliquee`\n[1] 0.09930469\n\n$`McFadden ajuste`\n'log Lik.' 0.355712 (df=18)\n\n$`Cox and Snell`\n'log Lik.' 0.8002923 (df=18)\n\n$Nagelkerke\n'log Lik.' 0.8110203 (df=18)\n```\n:::\n\n```{.r .cell-code}\n# Calcul du RMSE\nsqrt(mean((preds - data2$Nbr_acci)**2))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 2.566753\n```\n:::\n:::\n\n\nLe modèle avec excès de zéro ajusté ne parvient à expliquer que 11 % de la déviance totale. Il obtient toutefois des valeurs de R^2^ assez hautes (McFadden ajusté : 0,36, Nagerlkerke : 0,82). Son RMSE est très élevé (2,6), comparativement à celui que nous avons obtenu avec le modèle binomial négatif (1,9). Considérant ces éléments, ce modèle est nettement moins informatif que le modèle binomial négatif et ne devrait pas être retenu. Nous montrons tout de même ici comment interpréter ces résultats.\n\n**Interprétation des résultats**\n\nL'ensemble des coefficients du modèle sont accessibles avec la fonction `summary`. Les coefficients dédiés à la partie Poisson (appelée **Mu** dans le résumé) doivent être analysés et interprétés de la même manière que s'ils provenaient d'un modèle de Poisson. Les coefficients appartenant à la partie logistique (appelé **Sigma** dans le résumé) doivent être analysés et interprétés de la même manière que s'ils provenaient d'un modèle logistique.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Extraction des résultats\nbase_table <- summary(modelza)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n******************************************************************\nFamily: c(\"ZIP\", \"Poisson Zero Inflated\") \n\nCall: gamlss(formula = Nbr_acci ~ Feux_auto + Feux_piet + \n Pass_piet + Terreplein + Apaisement + LogEmploi + \n Densite_pop + Entropie + DensiteInter + Long_arterePS + \n Artere + NB_voies5, sigma.formula = ~1 + Feux_auto + \n Feux_piet + Densite_pop + NB_voies5, family = ZIP(mu.link = \"log\", \n sigma.link = \"logit\"), data = data2) \n\nFitting method: RS() \n\n------------------------------------------------------------------\nMu link function: log\nMu Coefficients:\n Estimate Std. Error t value Pr(>|t|) \n(Intercept) -2.555e+00 5.484e-01 -4.660 4.11e-06 ***\nFeux_auto 7.206e-01 2.037e-01 3.538 0.000442 ***\nFeux_piet 3.942e-01 1.100e-01 3.584 0.000373 ***\nPass_piet 2.787e-01 1.999e-01 1.394 0.163996 \nTerreplein -3.336e-01 1.663e-01 -2.005 0.045473 * \nApaisement 2.326e-01 1.539e-01 1.511 0.131453 \nLogEmploi 1.542e-01 7.616e-02 2.025 0.043410 * \nDensite_pop 8.098e-05 1.557e-05 5.202 2.93e-07 ***\nEntropie -6.568e-02 3.079e-01 -0.213 0.831194 \nDensiteInter 3.592e-03 2.086e-03 1.722 0.085772 . \nLong_arterePS 9.658e-06 2.033e-05 0.475 0.634882 \nArtere 1.290e-02 1.206e-01 0.107 0.914862 \nNB_voies5 4.953e-01 1.075e-01 4.605 5.28e-06 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\n------------------------------------------------------------------\nSigma link function: logit\nSigma Coefficients:\n Estimate Std. Error t value Pr(>|t|) \n(Intercept) 1.036e+00 5.573e-01 1.859 0.06367 . \nFeux_auto -1.562e+00 6.011e-01 -2.598 0.00967 **\nFeux_piet 8.278e-02 7.427e-01 0.111 0.91130 \nDensite_pop -1.228e-04 5.536e-05 -2.218 0.02702 * \nNB_voies5 -1.552e+00 1.001e+00 -1.550 0.12182 \n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\n------------------------------------------------------------------\nNo. of observations in the fit: 498 \nDegrees of Freedom for the fit: 18\n Residual Deg. of Freedom: 480 \n at cycle: 11 \n \nGlobal Deviance: 1351.841 \n AIC: 1387.841 \n SBC: 1463.632 \n******************************************************************\n```\n:::\n\n```{.r .cell-code}\n# Multiplication par 1000 des coefficients de population\n# (effet pour 1000 habitants)\nbase_table[8,1] <- 1000 * base_table[8,1]\nbase_table[8,2] <- 1000 * base_table[8,2]\nbase_table[17,1] <- 1000 * base_table[17,1]\nbase_table[17,2] <- 1000 * base_table[17,2]\n# Multiplication par 1000 des coefficients de longueur artère\n# (effet pour 1 km)\nbase_table[11,1] <- 1000 * base_table[11,1]\nbase_table[11,2] <- 1000 * base_table[11,2]\n# Calcul des exponentiels des variables indépendantes\n# et des intervalles de confiance\nexpcoeff <- exp(base_table[,1])\nexpcoeff2.5 <- exp(base_table[,1] - 1.96 * base_table[,2])\nexpcoeff97.5 <- exp(base_table[,1] + 1.96 * base_table[,2])\nbase_table <- cbind(base_table, expcoeff, expcoeff2.5, expcoeff97.5)\n# Calculer une colonne indiquant le niveau de significativité\nsign <- case_when(\n base_table[,4] < 0.001 ~ \"***\",\n base_table[,4] >= 0.001 & base_table[,4]<0.01 ~ \"**\",\n base_table[,4] >= 0.01 & base_table[,4]<0.05 ~ \"*\",\n base_table[,4] >= 0.05 & base_table[,4]<0.1 ~ \".\",\n TRUE ~ \"\"\n)\n# Arrondir à trois décimales\nbase_table <- round(base_table,3)\n# Enlever les colonnes de valeurs de t et d'erreur standard\nbase_table <- base_table[, c(1,4,5,6,7)]\nbase_table <- cbind(base_table, sign)\n# Remplacer les 0 dans la colonne pval\nbase_table[,2] <- ifelse(base_table[,2]==\"0\" , \"<0.001\",base_table[,2])\n# Séparer le tout en deux tableaux\npart_poiss <- base_table[1:13,]\npart_logit <- base_table[14:18,]\n# Mettre les bons noms de colonnes\ncolnames(part_poiss) <- c(\"Coeff.\" , \"Val.p\" , \"Exp(Coeff.)\",\n \"IC 2,5 % exp(Coeff.)\" , \"IC 97,5 % exp(Coeff.)\", \"Sign.\")\ncolnames(part_logit) <- c(\"Coeff.\" , \"Val.p\" , \"RC\" , \"IC 2,5 % RC\" , \"IC 97,5 % RC\", \"Sign.\")\n```\n:::\n\n\nNous rapportons les résultats de ce modèle de Poisson avec excès de zéro ajusté dans les tableaux [-@tbl-zapoisstab1] et [-@tbl-zapoisstab2].\n\n\n::: {#tbl-zapoisstab1 .cell tbl-cap='Résultats de la partie Poisson du modèle de Poisson avec excès de zéros ajusté'}\n::: {.cell-output-display}\n|Variable | Coeff.| Val.p| Exp(Coeff.)| IC 2,5 % exp(Coeff.)| IC 97,5 % exp(Coeff.)| Sign.|\n|:-------------|------:|------:|-----------:|--------------------:|---------------------:|-----:|\n|(Intercept) | -2.555| <0.001| 0.078| 0.027| 0.228| ***|\n|Feux_auto | 0.721| <0.001| 2.056| 1.379| 3.064| ***|\n|Feux_piet | 0.394| <0.001| 1.483| 1.196| 1.84| ***|\n|Pass_piet | 0.279| 0.164| 1.321| 0.893| 1.955| |\n|Terreplein | -0.334| 0.045| 0.716| 0.517| 0.992| *|\n|Apaisement | 0.233| 0.131| 1.262| 0.933| 1.706| |\n|LogEmploi | 0.154| 0.043| 1.167| 1.005| 1.355| *|\n|Densite_pop | 0.081| <0.001| 1.084| 1.052| 1.118| ***|\n|Entropie | -0.066| 0.831| 0.936| 0.512| 1.712| |\n|DensiteInter | 0.004| 0.086| 1.004| 1| 1.008| .|\n|Long_arterePS | 0.01| 0.635| 1.01| 0.97| 1.051| |\n|Artere | 0.013| 0.915| 1.013| 0.8| 1.283| |\n|NB_voies5 | 0.495| <0.001| 1.641| 1.329| 2.026| ***|\n:::\n:::\n\n::: {#tbl-zapoisstab2 .cell tbl-cap='Résultats de la partie logistique du modèle de Poisson avec excès de zéros ajusté'}\n::: {.cell-output-display}\n|Variable | Coeff.| Val.p| RC| IC 2,5 % RC| IC 97,5 % RC| Sign.|\n|:-----------|------:|-----:|-----:|-----------:|------------:|-----:|\n|(Intercept) | 1.036| 0.064| 2.817| 0.945| 8.399| .|\n|Feux_auto | -1.562| 0.01| 0.21| 0.065| 0.681| **|\n|Feux_piet | 0.083| 0.911| 1.086| 0.253| 4.658| |\n|Densite_pop | -0.123| 0.027| 0.884| 0.793| 0.986| *|\n|NB_voies5 | -1.552| 0.122| 0.212| 0.03| 1.508| |\n:::\n:::\n\n\nNous observons ainsi que la présence d’un feu de circulation divise par 5 les chances de rentrer dans la catégorie d'intersection où des accidents peuvent se produire. De même, la densité de population réduit les chances de passer dans cette catégorie de 11 %.\n\nConcernant les coefficients pour la partie Poisson du modèle, nous observons que les présences d’un feu de circulation et d’un feu pour piéton contribuent à multiplier respectivement par 2 et 1,5 le nombre attendu d’accidents à une intersection. De même, la présence d’un axe de circulation à cinq voies augmente de 57 % le nombre d’accidents. Enfin, la densité de population est aussi associée à une augmentation du nombre d’accidents : pour 1 000 habitants supplémentaires autour de l'intersection, nous augmentons le nombre d'accidents attendu de 9 %.\n\n### Conclusion sur les modèles destinés à des variables de comptage {#sec-0835}\n\nDans cette section, nous avons vu que modéliser une variable de comptage ne doit pas toujours être réalisé avec une simple distribution de Poisson. Il est nécessaire de tenir compte de la sur ou sous-dispersion potentielle ainsi que de l’excès de zéros. Nous n’avons cependant pas couvert tous les cas. Il est en effet possible d’ajuster des modèles avec une distribution binomiale négative avec excès de zéros (avec le *package* `gamlss`), ainsi que des modèles de **Hurdle**. Ces derniers ont une approche différente de celle proposée par les distributions ajustées pour tenir compte de l’excès de zéro que nous détaillons dans l’encadré « pour aller plus loin » ci-dessous. Le processus de sélection du modèle peut être résumé avec la @fig-poisswork. Notez que même en suivant cette procédure, rien ne garantit que votre modèle final reflète bien les données que vous étudiez. L’analyse approfondie des résidus et des prédictions du modèle est la seule façon de déterminer si oui ou non le modèle est fiable.\n\n\n![Processus de sélection d'un modèle pour une variable de comptage](images/Chap08/poisson_workflow.png){#fig-poisswork width=\"80%\" fig-align=\"center\"}\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Modèle de Hurdle *versus* modèle avec excès de zéro**\n:::\n::: bloc_aller_loin-body\nLes modèles de Hurdle sont une autre catégorie de modèles GLM. Ils peuvent être décrits avec la formulation suivante : \n\n$$\n\\left\\{\\begin{array}{c}\nY \\sim \\text {Binomial}(p) \\text { si } y = 0 \\\\\n\\text { logit }(p)=\\beta_{a} X_{a} \\\\\nY \\sim \\text { TrPoisson}(\\lambda) \\text { si } y>0 \\\\\n\\log (\\lambda)=\\beta_{b} X_{b}\n\\end{array}\\right.\n$$ {#eq-glmHurdle}\n\nNous constatons qu’un modèle de Hurdle utilise deux distributions, la première est une distribution binomiale dont l’objectif est de prédire si les observations sont à 0 ou au-dessus de 0. La seconde est une distribution strictement positive (supérieure à 0), il peut s’agir d’une distribution tronquée de Poisson, tronquée binomiale négative, Gamma, log-normale ou autre, dépendamment du phénomène modélisé. Puisque le modèle fait appel à deux distributions, deux équations de régression sont utilisées, l’une pour prédire *p* (la probabilité d’observer une valeur au-dessus de 0) et l'autre l’espérance (moyenne) de la seconde distribution. \n\nEn d’autres termes, un modèle de Hurdle modélise les données à zéro et les données au-delà de 0 comme deux processus différents (chacun avec sa propre distribution). Cette approche se distingue des modèles avec excès de zéros qui utilisent une seule distribution pour décrire l’ensemble des données. D’après un modèle avec excès de zéro, il existe de vrais et de faux zéros que l’on tente de distinguer. Dans un modèle de Hurdle, l’idée est que les zéros constituent une limite. Nous modélisons la probabilité de dépasser cette limite et ensuite la magnitude du dépassement de cette limite.\n\nPrenons un exemple pour rendre la distinction plus concrète. Admettons que nous utilisons un capteur capable de mesurer la concentration de particules fines dans l’air. D’après les spécifications du fabricant, le capteur est capable de mesurer des taux de concentration à partir de 0,001 µg/m^3^. Dans une ville avec des niveaux de concentration très faibles, il est très fréquent que le capteur enregistre des valeurs à zéro. Considérant ce phénomène, il serait judicieux de modéliser le processus avec un modèle de Hurdle Gamma puisque les 0 représentent une limite qui n’a pas été franchie : le seuil de détection du capteur. Nous traitons donc différemment les secteurs au-dessous et au-dessus de ce seuil. Si nous reprenons notre exemple sur les accidents des piétons à des intersections, il est plus judicieux, dans ce cas, de modéliser le phénomène avec un modèle avec excès de zéro puisque nous pouvons observer zéro accident à une intersection dangereuse (vrai zéro) et zéro accident à une intersection sur laquelle aucun piéton ne traverse jamais (faux zéro).\n:::\n:::\n\n## Modèles GLM pour des variables continues {#sec-084}\n\nComme nous l'avons vu dans la [section @sec-024], il existe un grand nombre de distributions permettant de décrire une grande diversité de variables continues. Il serait fastidieux de toutes les présenter, nous revenons donc seulement sur les plus fréquentes.\n\n### Modèle GLM gaussien {#sec-0841}\n\nComme nous l'avons vu en introduction, le modèle GLM gaussien est le plus simple puisqu'il correspond à la transposition de la régression linéaire classique (des moindres carrés) dans la forme des modèles généralisés.\n\n\n::: {#tbl-gaussiandentity .cell tbl-cap='Carte d\\'identité du modèle gaussien'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:-------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable continue dans l'intervalle $]-\\infty ; + \\infty[$ |\n|Distribution utilisée |Normale |\n|Formulation |$Y \\sim Normal(\\mu,\\sigma)$ \\newline $g(\\mu) = \\beta_0 + \\beta X$ \\newline $g(x) = x$ |\n|Fonction de lien |Identitaire |\n|Paramètre modélisé |$\\mu$ |\n|Paramètres à estimer |$\\beta_0$, $\\beta$ et $\\sigma$ |\n|Conditions d'application |Homoscédasticité |\n:::\n:::\n\n\n#### Conditions d'application {#sec-08411}\n\nLes conditions d'application sont les mêmes que celles d'une régression linéaire classique. La condition de l'homoscédasticité (homogénéité de la variance) est due au fait que la variance du modèle est contrôlée par un seul paramètre fixe $var(y) = \\sigma$ (l'écart-type de la distribution normale). À titre de comparaison, rappelons que dans un modèle de Poisson, la variance est égale à la moyenne ($var(y) = E(y)$) alors que dans un modèle binomial négatif, la variance est fonction de la moyenne et d'un paramètre $\\theta$ ($var(y) = E(y) + E(y)^{\\frac{2}{\\theta}}$). Pour ces deux exemples, la variance augmente au fur et à mesure que la moyenne augmente.\n\n#### Interprétation des paramètres {#sec-08412}\n\nL'interprétation des paramètres est la même que pour une régression linéaire classique : \n\n* $\\beta_0$ : la constante, soit la moyenne attendue de la variable *Y* lorsque les valeurs de toutes les variables *X* sont 0.\n\n* $\\beta$ : les coefficients de régression qui quantifient l'effet d’une augmentation d’une unité des variables *X* sur la moyenne de la variable *Y*.\n\n* $\\sigma$ : l’écart-type de *Y* après avoir contrôlé les variables *X*. Il peut s’interpréter comme l’incertitude restante après modélisation de la moyenne de *Y*. Concrètement, si vous utilisez votre équation de régression pour prédire une nouvelle valeur de *Y* : $\\hat{Y}$, l’intervalle de confiance à 95 % de cette prédiction est ($\\hat{Y} - 3\\sigma\\text{ ; }\\hat{Y} + 3\\sigma$). Vous noterez donc que plus $\\sigma$ est grand, plus grande est l'incertitude de la prédiction.\n\n#### Exemple appliqué dans R {#sec-08413}\n\nPour cet exemple, nous reprenons le modèle LM que nous avons présenté dans la [section @sec-077]. À titre de rappel, l'objectif est de modéliser la densité végétale dans les secteurs de recensement de Montréal. Pour cela, nous utilisons des variables relatives aux populations vulnérables physiologiquement ou socioéconomiquement, tout en contrôlant l'effet de la forme urbaine. Parmi ces dernières, l'âge médian des bâtiments est ajouté au modèle avec une polynomiale d'ordre deux, et la densité d'habitants est transformée avec la fonction logarithmique.\n\n**Vérification des conditions d'application**\n\nLa première étape de la vérification des conditions d'application est bien sûr de s'assurer de l'absence de multicolinéarité excessive. \n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Chargement des données\nload(\"data/lm/DataVegetation.RData\")\n# Calcul du VIF\nlibrary(car)\nvif(glm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n GVIF Df GVIF^(1/(2*Df))\nlog(HABHA) 1.289495 1 1.135559\npoly(AgeMedian, 2) 1.387429 2 1.085307\nPct_014 1.517957 1 1.232054\nPct_65P 1.304094 1 1.141969\nPct_MV 1.480275 1 1.216666\nPct_FR 1.729646 1 1.315160\n```\n:::\n:::\n\n\nPuisque l'ensemble des valeurs de VIF sont inférieures à deux, nos données ne sont pas marquées par une multicolinéarité problématique. La seconde étape du diagnostic consiste à calculer et à afficher les distances de Cook.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distances de Cook pour le modèle gaussien](08-GLM_files/figure-html/fig-gausscook-1.png){#fig-gausscook fig-align='center' width=65%}\n:::\n:::\n\n\nLa @fig-gausscook indique clairement que quatre observations sont très influentes dans le modèle. \n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Sélection des cas étranges\ncas_etranges <- subset(DataFinal, cooksd > 0.03)\nprint(cas_etranges)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n VegPct ArbPct V250Pct V500Pct A250Pct A500Pct HABHA AgeMedian Pct_014\n3374 10.481 5.478 18.987 13.744 2.908 2.704 74.835867 226 4.76\n3378 0.000 0.000 12.709 12.505 2.116 2.324 88.006946 206 6.25\n4446 23.162 5.209 31.437 31.535 8.672 9.108 313.142733 206 14.40\n9088 85.767 27.583 78.195 83.492 42.999 51.074 2.070472 207 12.00\n Pct_65P Pct_MV Pct_FR DistCBDkm SDRNOM\n3374 14.29 23.81 14.29 0.748 Montréal\n3378 12.50 25.00 12.50 0.706 Montréal\n4446 16.87 53.50 42.39 8.678 Montréal\n9088 24.00 12.00 16.00 28.440 Montréal\n```\n:::\n:::\n\n\nIl s'agit de quatre îlots dans Montréal avec des logements très anciens : plus de 200 ans, alors que la moyenne est de 52 ans pour le reste de la zone d'étude. Le fait que nous ayons dans le modèle une polynomiale d'ordre 2 pour cette variable intensifie l'influence de ces valeurs extrêmes. Par conséquent, nous décidons de simplement les supprimer. Nous verrons plus tard qu'une alternative envisageable est de changer la distribution du modèle pour une distribution de Student (plus robuste aux valeurs extrêmes).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distances de Cook pour le modèle gaussien après suppression des observations influentes](08-GLM_files/figure-html/fig-gausscook2-1.png){#fig-gausscook2 fig-align='center' width=65%}\n:::\n:::\n\n\nUne fois ces observations retirées, les nouvelles distances de Cook ne révèlent plus d'observations fortement influentes (@fig-gausscook2). Nous pouvons passer à l'analyse des résidus simulés. La @fig-gaussresid démontre que la distribution des résidus est significativement différente d'une distribution uniforme, que des valeurs aberrantes sont encore présentes et qu'il existe un lien entre résidus et prédiction dans le modèle.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction des prédictions du modèle\nmus <- predict(modele, type = 'response')\nmodsigma <- sigma(modele)\n# Extraction de l'écart type du modèle\n# Génération de 1000 simulations pour chaque prédiction\nnsim <- 1000\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- rnorm(nsim, mean=mu, sd = modsigma)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = DataFinal2$VegPct,\n fittedPredictedResponse = mus,\n integerResponse = FALSE)\nplot(sim_res)\n```\n\n::: {.cell-output-display}\n![Diagnostic général des résidus simulés pour le modèle gaussien](08-GLM_files/figure-html/fig-gaussresid-1.png){#fig-gaussresid fig-align='center' width=65%}\n:::\n:::\n\n\nPour mieux cerner ce problème, nous pouvons, dans un premier temps, comparer la distribution originale des données et les simulations issues du modèle. La @fig-gausssim montre clairement que la distribution normale est mal ajustée aux données. Ces dernières sont légèrement asymétriques et ne peuvent pas être inférieures à zéro, ce que la distribution normale ne parvient pas à reproduire.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndf <- reshape2::melt(mat_sims[,1:30])\nggplot() + \n geom_histogram(data = DataFinal2, mapping = aes(x = VegPct, y = ..density..),\n color = \"black\", fill = \"white\", bins = 50)+\n geom_density(data = df, aes(x = value, group = Var2), \n color = rgb(0.4,0.4,0.4,0.4), fill = rgb(0,0,0,0))+\n labs(x = \"Pourcentage de végétation dans l'îlot (%)\",\n y = \"Densité\")\n```\n\n::: {.cell-output-display}\n![Comparaison de la distribution originale de la variable et des simulations issues du modèle](08-GLM_files/figure-html/fig-gausssim-1.png){#fig-gausssim fig-align='center' width=65%}\n:::\n:::\n\n\nIl est également possible de vérifier si la condition d'homogénéité de la variance s'applique bien aux données.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction des prédictions du modèle\nmus <- predict(modele, type = \"response\")\nsigma_model <- sigma(modele)\n# Création d'un DataFrame pour contenir les prédictions et les vraies valeurs\ndf1 <- data.frame(\n mus = mus,\n reals = DataFinal2$VegPct\n)\n# Calcul de l'intervalle de confiance à 95 % selon la distribution normale\n# et stockage dans un second DataFrame\nseqa <- seq(0,100,10)\ndf2 <- data.frame(\n mus = seqa,\n lower = qnorm(p = 0.025, mean = seqa, sd = sigma_model),\n upper = qnorm(p = 0.975, mean = seqa, sd = sigma_model)\n)\n\n# Affichage des valeurs réelles et prédites (en rouge)\n# et de leur variance selon le modèle (en noir)\nggplot() + \n geom_point(data = df1, \n mapping = aes(x = mus, y = reals),\n color =\"red\", size = 0.5) + \n geom_errorbar(data = df2,\n mapping = aes(x = mus, ymin = lower, ymax = upper),\n width = 0.2, color = rgb(0.4,0.4,0.4)) + \n labs(x = \"valeurs prédites\",\n y = \"valeurs réelles\")\n```\n\n::: {.cell-output-display}\n![Comparaison de la distribution originale de la variable et des simulations issues du modèle](08-GLM_files/figure-html/fig-gausssim2-1.png){#fig-gausssim2 fig-align='center' width=65%}\n:::\n:::\n\n\nÀ nouveau, nous constatons à la @fig-gausssim2 que le modèle s'attend à trouver des valeurs négatives pour la concentration de végétation, ce qui n'est pas possible dans notre cas. En revanche, il semble que la variance soit bien homogène puisque la dispersion des observations semble suivre à peu près la dispersion attendue par le modèle (en noir).\n\nMalgré ces différents constats indiquant clairement qu'un modèle gaussien est un choix sous-optimal pour ces données, nous poursuivons l'analyse de ce modèle.\n\n**Vérification de la qualité d'ajustement**\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Ajustement d'un modèle nul\nmodelenull <- glm(VegPct ~ 1,\n data = DataFinal2, \n family = gaussian())\n# Calcul des pseudo R2\nrsqs(loglike.full = logLik(modele),\n loglike.null = logLik(modelenull),\n full.deviance = deviance(modele),\n null.deviance = deviance(modelenull), \n nb.params = modele$rank,\n n = nrow(DataFinal2)\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n$`deviance expliquee`\n[1] 0.4706321\n\n$`McFadden ajuste`\n'log Lik.' 0.07310662 (df=9)\n\n$`Cox and Snell`\n'log Lik.' 0.4706321 (df=9)\n\n$Nagelkerke\n'log Lik.' 0.4707122 (df=9)\n```\n:::\n:::\n\n\nLe modèle parvient à expliquer 47 % de la déviance totale, mais obtient un R^2^ ajusté de McFadden de seulement 0,07.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Calcul du RMSE\nsqrt(mean((predict(modele, type = \"response\") - DataFinal2$VegPct)**2))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 13.49885\n```\n:::\n:::\n\n\nL'erreur quadratique moyenne et de 13,5 points de pourcentage, ce qui indique que le modèle a une assez faible capacité prédictive.\n\n**Interprétation des résultats**\n\nL'ensemble des coefficients du modèle sont accessibles via la fonction `summary`; le @tbl-tableaugauss présente les résultats pour les coefficients du modèle.\n\n\n::: {#tbl-tableaugauss .cell tbl-cap='Résultats du modèle gaussien'}\n::: {.cell-output-display}\n|Variable | Coeff.| Err.std| Val.z| val.p| IC coeff 2,5 %| IC coeff 97,5 %| Sign.|\n|:-----------------|--------:|-------:|-------:|-----:|--------------:|---------------:|-----:|\n|Constante | 53,606| 1,000| 53,640| 0,000| 51,647| 55,565| ***|\n|AgeMedian ordre 1 | 2,732| 15,560| 0,180| 0,861| -27,772| 33,237| |\n|AgeMedian ordre 2 | -320,869| 14,000| -22,910| 0,000| -348,318| -293,420| ***|\n|Pct_014 | 0,915| 0,030| 29,310| 0,000| 0,853| 0,976| ***|\n|Pct_65P | 0,280| 0,020| 15,050| 0,000| 0,243| 0,316| ***|\n|Pct_MV | -0,042| 0,010| -4,190| 0,000| -0,061| -0,022| ***|\n|Pct_FR | -0,340| 0,010| -30,940| 0,000| -0,362| -0,318| ***|\n:::\n:::\n\n\nLes résultats de la régression linéaire multiple ont déjà été interprétés dans la [section @sec-0771], nous ne commenterons pas ici les résultats du modèle GLM gaussien qui sont identiques.\n\n\n### Modèle GLM avec une distribution de Student {#sec-0842}\n\nPour rappel, la distribution de Student ressemble à une distribution normale ([section @sec-024311]). Elle est symétrique autour de sa moyenne et a également une forme de cloche. Cependant, elle dispose de queues lourdes, ce qui signifie qu’elle permet de représenter des phénomènes présentant davantage de valeurs extrêmes qu’une distribution normale. Pour contrôler le poids des queues, la distribution de Student intègre un troisième paramètre : $\\nu$ (nu). Lorsque $\\nu$ tends vers l’infini, la distribution de Student tend vers une distribution normale (@fig-studentdistrib).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Effet du paramètre nu sur une distribution de Student](08-GLM_files/figure-html/fig-studentdistrib-1.png){#fig-studentdistrib fig-align='center' width=65%}\n:::\n:::\n\n\nComme vous pouvez le constater dans la carte d'identité au @tbl-studentdentity, le modèle GLM de Student est très proche du modèle GLM gaussien. Nous modélisons explicitement la moyenne de la distribution et son paramètre de dispersion (variance) est laissé fixe. Ce GLM est même souvent utilisé comme une version « robuste » du modèle gaussien du fait de sa capacité à intégrer explicitement l’effet des observations extrêmes. En effet, dans un modèle gaussien, les observations extrêmes (aussi appelées observations aberrantes) vont davantage influencer les paramètres du modèle que pour un modèle utilisant une distribution de Student.\n\n\n::: {#tbl-studentdentity .cell tbl-cap='Carte d\\'identité du modèle de Student'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:------------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable continue dans l'intervalle $]-\\infty ; + \\infty[$ |\n|Distribution utilisée |Student |\n|Formulation |$Y \\sim Student(\\mu,\\sigma,\\nu)$ \\newline $g(\\mu) = \\beta_0 + \\beta X$ \\newline $g(x) = x$ |\n|Fonction de lien |Identitaire |\n|Paramètre modélisé |$\\mu$ |\n|Paramètres à estimer |$\\beta_0$, $\\beta$, $\\sigma$ et $\\nu$ |\n|Conditions d'application |Homoscédasticité |\n:::\n:::\n\n\n#### Conditions d'application {#sec-08421}\n\nLes conditions d’application sont les mêmes que pour un modèle GLM gaussien, à ceci prêt que le modèle utilisant la distribution de Student est moins sensible aux observations extrêmes.\n\n#### Interprétation des paramètres {#sec-08422}\n\nL’interprétation des paramètres est la même que pour un modèle gaussien puisque nous modélisons la moyenne de la distribution et que la fonction de lien est la fonction identitaire. Le seul paramètre supplémentaire est $\\nu$, qui n’a en soit aucune interprétation pratique. Notez simplement que si $\\nu$ est supérieur à 30, un simple modèle GLM gaussien serait sûrement suffisant.\n\n#### Exemple appliqué dans R {#sec-08423}\n\nNous proposons ici de simplement réajuster le modèle gaussien présenté dans la section précédente en utilisant une distribution de Student. Nous utilisons pour cela la fonction `gam` du *package* `mgcv` avec le paramètre `family = scat` pour utiliser une distribution de Student. Les valeurs de VIF ont déjà été calculées dans l'exemple précédent, nous pouvons donc passer directement au calcul des distances de Cook.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Chargement des données\nload(\"data/lm/DataVegetation.RData\")\n# Ajustement du modèle\nmodele <- gam(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal,\n family = scat)\n\n# Calcul des distances de Cook\ncooksd <- cooks.distance(modele)\n# Affichage des valeurs\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df) + \n geom_point(aes(x = oid, y = cook), color = rgb(0.4,0.4,0.4,0.7), size = 1) + \n labs(x = \"\", y = \"distance de Cook\")\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour un modèle GLM avec une distribution de Student](08-GLM_files/figure-html/fig-stucookdist-1.png){#fig-stucookdist fig-align='center' width=50%}\n:::\n:::\n\n\nNous retrouvons les quatre observations avec des distances de Cook très fortes que nous avons identifiées dans le modèle gaussien. Nous décidons donc de les enlever pour les mêmes raisons que précédemment.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Chargement des données\nDataFinal2 <- subset(DataFinal, cooksd<0.1)\n# Ajustement du modèle\nmodele <- gam(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal2,\n family = scat)\n\n# Calcul des distances de Cook\ncooksd <- cooks.distance(modele)\n# Affichage des valeurs\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df) + \n geom_point(aes(x = oid, y = cook), color = rgb(0.4,0.4,0.4,0.7), size = 1) + \n labs(x = \"\", y = \"distance de Cook\")\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour un modèle GLM avec une distribution de Student après suppression des valeurs fortement influentes](08-GLM_files/figure-html/fig-stucookdist2-1.png){#fig-stucookdist2 fig-align='center' width=50%}\n:::\n:::\n\n\n\nNous pouvons à présent vérifier si les résidus simulés se comportent tel qu'attendu.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction des prédictions du modèle\nmus <- predict(modele, type = 'response')\n# Affichage des paramètres nu et sigma\nmodele$family$family\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] \"Scaled t(6.333,11.281)\"\n```\n:::\n\n```{.r .cell-code}\nsigma_model <- 11.281\nnu_model <- 6.333\nlibrary(LaplacesDemon) # pour simuler des données d'une distribution de Student\n# Génération de 1000 simulations pour chaque prédiction\nnsim <- 1000\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- rst(nsim, mu=mu, sigma = sigma_model, nu = nu_model)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = DataFinal2$VegPct,\n fittedPredictedResponse = mus,\n integerResponse = FALSE)\nplot(sim_res)\n```\n\n::: {.cell-output-display}\n![Diagnostic général des résidus simulés pour le GLM avec distribution de Student](08-GLM_files/figure-html/fig-studentresid-1.png){#fig-studentresid fig-align='center' width=65%}\n:::\n:::\n\n\nIl semble que nous obtenons des résultats similaires à ceux du modèle gaussien: les résidus divergent significativement d'une distribution uniforme (@fig-studentresid). Le graphique quantile-quantile n'est parfois pas très adapté pour discerner une déviation de la distribution uniforme, nous pouvons dans ce cas afficher un histogramme des résidus pour en avoir le coeur net (@fig-studentresid2).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nggplot()+\n geom_histogram(aes(x = residuals(sim_res)), bins = 50, color = \"white\") + \n labs(x = \"effectifs\", y = \"résidus simulés\")\n```\n\n::: {.cell-output-display}\n![Distribution des résidus simulés du modèle GLM avec distribution de Student](08-GLM_files/figure-html/fig-studentresid2-1.png){#fig-studentresid2 fig-align='center' width=60%}\n:::\n:::\n\n\nPour cet exercice, il est intéressant de comparer les formes des simulations issues du modèle gaussien et du modèle de Student pour bien distinguer la différence entre les deux.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Simulations issues des modèles gaussien et de Student, comparées aux données originales](08-GLM_files/figure-html/fig-studentresid3-1.png){#fig-studentresid3 fig-align='center' width=60%}\n:::\n:::\n\n\nNous constatons ainsi que la différence entre les deux modèles est ici très mince, voire inexistante. Le seul élément que nous pouvons noter est que le modèle de Student à une courbe (une queue de distribution) moins aplatie vers la droite. Cela lui permettrait de mieux tenir compte de cas extrêmes avec de fortes densités de végétation (ce qui concerne donc très peu d'observations puisque cette variable a un maximum de 100).\n\nPour déterminer si le modèle de Student est plus pertinent à retenir que le modèle gaussien, nous pouvons ajuster un second modèle de Student pour lequel nous forçons artificiellement $\\nu$ à être très élevé. Pour rappel, quand $\\nu$ tend vers l'infini, la distribution de Student tend vers une distribution normale. Nous forçons ici $\\nu$ à être supérieur à 100 pour créer un second modèle de Student se comportant quasiment comme un modèle gaussien et calculons les AIC des deux modèles.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Calcul d'un modèle de Student identique à un modèle gaussien\nmodele2 <- gam(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal2,\n family = scat(min.df = 100))\n# Calcul des deux AIC\nAIC(modele)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 81771.92\n```\n:::\n\n```{.r .cell-code}\nAIC(modele2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 82057.79\n```\n:::\n:::\n\n\nLe second AIC (modèle gaussien) est plus élevé, indiquant que le modèle est moins bien ajusté aux données. Dans le cas présent, il est plus pertinent de retenir le modèle de Student même si les écarts entre ces deux modèles sont minimes. Ce résultat n'est pas surprenant puisque la variable *Y* (pourcentage de végétation dans les îlots de l'île de Montréal) est relativement compacte et comporte peu / pas de valeurs pouvant être qualifiées de valeurs extrêmes.\n\nNous ne détaillons pas ici l'interprétation des coefficients du modèle (présentés au @tbl-glmstudentres) puisqu'ils s'interprètent de la même façon qu'un modèle GLM et qu'un modèle de régression linéaire multiple.\n\n\n::: {#tbl-glmstudentres .cell tbl-cap='Résultats du modèle Student'}\n::: {.cell-output-display}\n|Variable | Coeff.| Err.std| Val.z| val.p| IC coeff 2,5 %| IC coeff 97,5 %| Sign.|\n|:----------|------:|-------:|-------:|-----:|--------------:|---------------:|-----:|\n|Constante | 65,096| 0,940| 69,110| 0,000| 63,250| 66,943| ***|\n|log(HABHA) | -9,502| 0,160| -60,160| 0,000| -9,811| -9,192| ***|\n|Pct_014 | 0,866| 0,030| 29,450| 0,000| 0,808| 0,924| ***|\n|Pct_65P | 0,237| 0,020| 13,540| 0,000| 0,203| 0,272| ***|\n|Pct_MV | -0,015| 0,010| -1,650| 0,099| -0,034| 0,003| .|\n|Pct_FR | -0,301| 0,010| -29,040| 0,000| -0,321| -0,280| ***|\n:::\n:::\n\n\n### Modèle GLM avec distribution Gamma {#sec-0843}\n\nPour rappel, la distribution Gamma est strictement positive ($[0;+\\infty[$), asymétrique, et a une variance proportionnelle à sa moyenne (hétéroscedastique). Dans la section sur les distributions, nous avons vu que la distribution Gamma ([section @sec-024315]) est formulée avec deux paramètres : sa forme ($\\alpha$ ou *shape*) et son échelle ($b$ ou *scale*). Ces deux paramètres n’ont pas une interprétation intuitive, mais il est possible avec un peu de jonglage mathématique d’arriver à une reparamétrisation intéressante. Cela est détaillé dans l'encadré ci-dessous; notez toutefois qu'il n'est pas nécessaire de maîtriser le contenu de cet encadré pour lire la suite de cette section sur les modèles GLM avec une distribution Gamma.\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Reparamétrisation d'une distribution Gamma pour un GLM**\n:::\n::: bloc_aller_loin-body\nSi nous disposons d’une variable *Y*, suivant une distribution Gamma telle que $Y \\sim Gamma(\\alpha,b)$ avec $\\alpha$ le paramètre de forme et $b$ le paramètre d’échelle, alors, l'espérance et la variance de *Y* peuvent être définies comme suit : \n\n$$\n\\begin{aligned}\n&E(Y) = \\alpha \\times b \\\\\n&Var(Y) = \\alpha \\times b^2\\\\\n\\end{aligned}\n$$ {#eq-glm18}\n\nEn d’autres termes, l’espérance (l’équivalent de la moyenne pour une distribution normale) de notre variable *Y* est égale au produit des paramètres de forme et d’échelle.\n\nAvec ces propriétés, il est possible de redéfinir la fonction de densité de la distribution Gamma et d’arriver à une nouvelle formulation : $Y \\sim Gamma(\\mu,\\alpha)$. $\\mu$ est donc l'espérance de *Y* (interprétable comme sa moyenne, soit sa valeur attendue) et $\\alpha$ permet de capturer la dispersion de la distribution Gamma. Par extension des relations présentées ci-dessus, il est possible de reformuler la variance en fonction de $\\mu$ et de $\\alpha$.\n\n$$\n\\begin{aligned}\n&Var(Y) = \\alpha \\times b^2\\\\\n&\\mu = \\alpha \\times b \\text{ soit }b = \\frac{\\mu}{a}\\\\\n&Var(Y) = \\alpha \\times (\\frac{\\mu}{\\alpha})^2 \\text{ soit } Var(Y) = \\frac{\\mu^2}{\\alpha}\\\\\n\\end{aligned}\n$$ {#eq-glm19}\n\nNous observons donc que la variance dans un modèle Gamma augmente de façon quadratique avec la moyenne, mais est tempérée par le paramètre de forme. Nous en concluons qu'un paramètre de forme plus grand produit une distribution moins étalée.\n\nDans ce contexte, $\\mu$ doit être strictement positif : la valeur attendue moyenne d'une distribution Gamma doit être positive par définition puisqu'une distribution Gamma ne peut pas produire de valeurs négatives. Il est donc logique d’utiliser la fonction logarithmique comme fonction de lien, puisque sa contrepartie (la fonction exponentielle) ne produit que des résultats positifs.\n:::\n:::\n\nPour résumer, nous nous retrouvons donc avec un modèle qui prédit, sur une échelle logarithmique, l'espérance (~moyenne) d’une distribution Gamma. Notez qu’il existe d’autres façons de spécifier un modèle GLM avec une distribution Gamma, mais celle-ci est la plus intuitive.\n\n\n::: {#tbl-gammadentity .cell tbl-cap='Carte d\\'identité du modèle Gamma'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:-----------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable continue dans l'intervalle $]0 ; + \\infty[$ |\n|Distribution utilisée |Gamma |\n|Formulation |$Y \\sim Gamma(\\mu,\\alpha)$ \\newline $g(\\mu) = \\beta_0 + \\beta X$ \\newline $g(x) = log(x)$ |\n|Fonction de lien |log |\n|Paramètre modélisé |$\\mu$ |\n|Paramètres à estimer |$\\beta_0$, $\\beta$, et $\\alpha$ |\n|Conditions d'application |$Variance = \\frac{\\mu^2}{\\alpha}$ |\n:::\n:::\n\n\n#### Interprétation des paramètres {#sec-08431}\n\nPuisque le modèle utilise la fonction de lien *log*, alors les coefficients $\\beta$ expriment l’augmentation de l’espérance (la valeur attendue de *Y*, ce qui est proche de l'idée de moyenne) de la variable Y sur une échelle logarithmique (comme dans un modèle de Poisson). Il est possible de convertir les coefficients dans l’échelle originale de la variable *Y* en utilisant la fonction exponentielle (l’inverse de la fonction *log*), mais ces coefficients représentent alors des effets multiplicatifs et non des effets additifs.\nPrenons un exemple, admettons que le coefficient $\\beta_1$, associé à la variable $X_1$ soit de 1,5. Cela signifie qu’une augmentation d’une unité de $X_1$, augmente le log de l'espérance de *Y* de 1,5 unité. L’exponentielle du coefficient est 4,48, ce qui signifie qu’une augmentation d’une unité entraîne une multiplication par 4,48 de la valeur attendue de *Y* (l’espérance de *Y*). Le paramètre de forme ($\\alpha$) n’a pas d’interprétation pratique, bien qu’il soit utilisé dans les différents tests des conditions d’application du modèle et dans le calcul de sa déviance.\n\n#### Conditions d'application {#sec-08432}\n\nDans un modèle GLM gaussien, la variance est capturée par un paramètre $\\sigma$ et est constante, produisant la condition d'homoscédasticité des résidus. Dans un modèle Gamma, la variance varie en fonction de l'espérance et du paramètre de forme selon la relation : $Var(Y) = \\frac{E(Y)^2}{\\alpha}$. Les résidus sont donc par nature hétéroscédastiques dans un modèle Gamma et doivent suivre cette relation.\n\n#### Exemple appliqué dans R {#sec-08433}\n\nPour cet exemple, nous nous intéressons à la durée de déplacement en milieu urbain. Ce type d’analyse permet notamment de mieux comprendre les habitudes de déplacement de la population et d’orienter les politiques de transport. Plusieurs travaux concluent que les durées de déplacement en milieu urbain varient en fonction du motif du déplacement, du mode de transport utilisé, des caractéristiques socio-économiques de l’individu et des caractéristiques du trajet lui-même [@anastasopoulos2012analysis; @frank2008urban]. Nous modélisons ici la durée en minute d’un ensemble de déplacements effectués par des Montréalais en 2017 et enregistrés avec l’application MTL Trajet proposée par la Ville de Montréal. Ces données sont disponibles sur le site web des [données ouvertes de Montréal](http://donnees.ville.montreal.qc.ca/dataset/mtl-trajet) et sont anonymisées. Nous ne disposons donc d’aucune information individuelle. Compte tenu du très grand nombre d’observations (plus de 185 000), nous avons dû effectuer quelques opérations de tri et nous avons ainsi supprimé:\n\n* les trajets utilisant de multiples modes de transport (sauf en combinaison avec la marche, par exemple, un trajet effectué à pied et en transport en commun a été recatégorisé comme un trajet en transport en commun uniquement). Les déplacements multimodaux se distinguent largement des déplacements unimodaux dans la littérature scientifique;\n\n* les trajets de nuit (seuls les trajets démarrant dans l'intervalle de 7 h à 21 h ont été conservés);\n\n* les trajets dont le point de départ est un arrondissement / municipalité pour lequel moins de 150 trajets ont été enregistrés (trop peu d’observations);\n\n* les trajets de plus de deux heures (cas rares, considérés comme des données aberrantes);\n\n* les trajets dont le point de départ est à moins de 100 mètres du point d’arrivée (formant des boucles plutôt que des déplacements).\n\nNous arrivons ainsi à un total de 24 969 observations. Pour modéliser ces durées de déplacement, nous utilisons les variables indépendantes présentées dans le @tbl-variablegamma.\n\n\n::: {#tbl-variablegamma .cell tbl-cap='Variables indépendantes utilisées dans le modèle Gamma'}\n::: {.cell-output-display}\n|Nom de la variable |Signification |Type de variable |Mesure |\n|:------------------|:------------------------------------------------------------------------------------|:---------------------|:------------------------------------------------------------------------------------|\n|Mode |Mode de déplacement |Variable catégorielle |Transport collectif; piéton; vélo et véhicule individuel |\n|Motif |Motif du déplacement |Variable catégorielle |Travail; loisir; magasinage et éducation |\n|HeureDep |Heure de départ |Variable catégorielle |De 7 h à 21 h |\n|ArrondDep |Arrondissement de départ |Variable catégorielle |Nom de l’arrondissement dont part le trajet |\n|LogDist |Logarithme de la distance à vol d’oiseau en km |Variable continue |Logarithme de la distance à vol d’oiseau en km entre le point de départ et d’arrivée |\n|MemeArrond |L’arrivée du trajet se situe-t-elle dans le même arrondissement que celui du départ? |Variable binaire |Oui ou non |\n|Semaine |Le trajet a-t-il été effectué en semaine ou en fin de semaine? |Variable binaire |Semaine ou fin de semaine |\n:::\n:::\n\n\nLes temps de trajet forment une variable strictement positive et très vraisemblablement asymétrique. En effet, nous nous attendons à observer une certaine concentration de valeurs autour d'une moyenne, et davantage de trajets avec de courtes durées que de trajets avec de longues durées. Pour nous en assurer, réalisons un histogramme de la distribution de notre variable *Y* et comparons-la avec des distributions normale et Gamma.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Chargement des données\ndataset <- read.csv(\"data/glm/DureeTrajets.csv\", stringsAsFactors = FALSE)\narrondMTL <- c(\"Mercier-Hochelaga-Maisonneuve\", \"Villeray-Saint-Michel-Parc-Extension\", \n \"Ville-Marie\", \"Verdun\", \"Saint-Leonard\", \"Saint-Laurent\", \n \"Rosemont-La Petite-Patrie\", \"Riviere-des-Prairies-Pointe-aux-Trembles\", \n \"Pierrefonds-Roxboro\", \"Outremont\", \"Montreal-Nord\", \"Le Sud-Ouest\", \n \"Le Plateau-Mont-Royal\", \"Lachine\" , \"Ahuntsic-Cartierville\",\n \"Anjou\" ,\"Cote-des-Neiges-Notre-Dame-de-Grace\", \"LaSalle\" \n)\ndataset <- subset(dataset, dataset$ArrondDep %in% arrondMTL)\n# Définissons 7 h du matin comme la référence pour la variable Heure de départ\ndataset$HeureDep <- relevel(\n factor(dataset$HeureDep, levels = as.character(7:21)),\n ref = \"7\")\n# Comparaison de la distribution originale avec une distribution \n# normale et une distribution Gamma\nlibrary(fitdistrplus)\nmodel_gamma <- fitdist(dataset$Duree, distr = \"gamma\")\nggplot(data = dataset) + \n geom_histogram(aes(x = Duree, y = ..density..), bins = 40, color = \"white\")+\n stat_function(fun = dgamma, color = \"red\", linewidth = 0.8, \n args = as.list(model_gamma$estimate))+\n stat_function(fun = dnorm, color = \"blue\", linewidth = 0.8, \n args = list(mean = mean(dataset$Duree), \n sd = sd(dataset$Duree)))+\n labs(x = \"Temps de déplacement (minutes)\",\n y = \"\",\n subtitle = \"modèles Gamma et gaussien\")\n```\n\n::: {.cell-output-display}\n![Distribution des temps de trajet diurne à Montréal](08-GLM_files/figure-html/fig-gammadatadistrib-1.png){#fig-gammadatadistrib fig-align='center' width=50%}\n:::\n:::\n\n\nLa @fig-gammadatadistrib permet de constater l'asymétrie de la distribution des temps de trajet et qu'un modèle Gamma (ligne rouge) a plus de chance d'être adapté aux données qu'un modèle gaussien (ligne bleue).\n\n**Vérification des conditions d'application**\n\nComme pour les modèles précédents, nous commençons par la vérification de l'absence de multicolinéarité.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n## Calcul du VIF\nvif(glm(Duree ~ Mode + Motif + HeureDep + LogDist +\n ArrondDep + MemeArrond + Jour,\n data = dataset,\n family = Gamma(link=\"log\")))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n GVIF Df GVIF^(1/(2*Df))\nMode 2.103392 3 1.131931\nMotif 1.934997 3 1.116298\nHeureDep 1.791009 14 1.021032\nLogDist 2.665998 1 1.632789\nArrondDep 1.439499 17 1.010772\nMemeArrond 2.151113 1 1.466667\nJour 1.330091 6 1.024055\n```\n:::\n:::\n\n\nL'ensemble des valeurs de VIF sont inférieures à trois, indiquant donc l'absence de multicolinéarité excessive. Nous pouvons donc ajuster une première version du modèle (ici avec le *package* `VGAM` et la fonction `vglm`) et calculer les distances de Cook.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Calcul du modèle avec VGAM\nmodele <- vglm(Duree ~ Mode + Motif + HeureDep + LogDist +\n ArrondDep+ MemeArrond + Semaine,\n data = dataset,\n family = gamma2(lmu = \"loglink\"))\n# Calcul des distances de Cook\nhats <- hatvaluesvlm(modele)[,1]\nres <- residuals(modele, type = \"pearson\")[,1]\ndisp <- modele@coefficients[[2]]**-1\nnbparams <- modele@rank\ncooksd <- (res/(1 - hats))^2 * hats/(disp * nbparams)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\n# Représentation des distances de Cook\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, color = rgb(0.4,0.4,0.4,0.4)) + \n geom_hline(yintercept = 0.003, color = \"red\") +\n labs(x = \"\", y = \"distance de Cook\")\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle Gamma](08-GLM_files/figure-html/fig-cookdistgamma-1.png){#fig-cookdistgamma fig-align='center' width=50%}\n:::\n:::\n\n\nPuisque nous disposons d'un (très) grand nombre d'observations, nous pouvons nous permettre de retirer les quelques observations fortement influentes (distance de Cook > 0,003 dans notre cas) qui apparaissent dans la @fig-cookdistgamma. Nous retirons ainsi 28 observations et réajustons le modèle.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Retirer les valeurs influentes\ndataset2 <- subset(dataset, cooksd<0.003)\n# Calcul du modèle avec VGAM\nmodele <- vglm(Duree ~ Mode + Motif + HeureDep + LogDist +\n ArrondDep+ MemeArrond + Semaine,\n data = dataset2,\n family = gamma2(lmu = \"loglink\"))\n```\n:::\n\n\nNous constatons ainsi que dans la nouvelle version du modèle (@fig-cookdistgamma2), aucune valeur particulièrement influente ne semble être présente.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Calcul des distances de Cook\nhats <- hatvaluesvlm(modele)[,1]\nres <- residuals(modele, type = \"pearson\")[,1]\ndisp <- modele@coefficients[[2]]**-1\nnbparams <- modele@rank\ncooksd <- (res/(1 - hats))^2 * hats/(disp * nbparams)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\n# Représentation des distances de Cook\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, color = rgb(0.4,0.4,0.4,0.4)) +\n labs(x = \"\", y = \"distance de Cook\")\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle Gamma (sans les observations fortement influentes)](08-GLM_files/figure-html/fig-cookdistgamma2-1.png){#fig-cookdistgamma2 fig-align='center' width=50%}\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction des prédictions du modèle (mu)\nmus <- modele@fitted.values\n# Extraction du paramètre de forme\nshape <- exp(modele@coefficients[[2]])\n# Calcul des simulations\nnsim <- 1000\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- rgamma(n = nsim, shape = shape, scale = mu/shape)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Représentation graphique de 20 simulations\ndf2 <- reshape2::melt(mat_sims[,0:20])\nggplot() + \n geom_histogram(aes(x = Duree, y = ..density..),\n data = dataset, bins = 100, color = \"black\", fill = \"white\") + \n geom_density(aes(x = value, y = ..density.., group = Var2), data = df2, \n fill = rgb(0,0,0,0), color = rgb(0.9,0.22,0.27,0.4), size = 1)+\n xlim(0,200)+\n labs(x = \"durée (minutes)\", y = \"densité\")\n```\n\n::: {.cell-output-display}\n![Comparaison de la distribution originale et de simulations issues du modèle Gamma](08-GLM_files/figure-html/fig-simdistribgamma-1.png){#fig-simdistribgamma fig-align='center' width=60%}\n:::\n:::\n\n\nAvant de calculer les résidus simulés, nous comparons la distribution originale des données et des simulations issues du modèle. La @fig-simdistribgamma permet de constater que le modèle semble bien capturer l’essentiel de la forme de la variable *Y* originale. Nous notons un léger décalage entre la pointe des deux distributions, laissant penser que les valeurs prédites par le modèle tendent à être légèrement plus grandes que les valeurs réelles. Pour mieux appréhender ce constat, nous passons à l'analyse des résidus simulés.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# DHarma tests\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = dataset2$Duree,\n fittedPredictedResponse = modele@fitted.values[,1],\n integerResponse = FALSE)\nggplot() + \n geom_histogram(aes(x = residuals(sim_res)), bins = 100, color = \"white\") + \n labs(x = \"résidus simulés\",\n y = \"effectifs\")\n```\n\n::: {.cell-output-display}\n![Distribution des résidus simulés du modèle Gamma](08-GLM_files/figure-html/fig-gammaresids-1.png){#fig-gammaresids fig-align='center' width=60%}\n:::\n:::\n\n\nNul besoin d'un test statistique pour constater que ces résidus (@fig-gammaresids) ne suivent pas une distribution uniforme. Nous observons une nette surreprésentation de résidus à 1 et une nette sous-représentation de résidus à 0. Il y a donc de nombreuses observations dans notre modèle pour lesquelles les simulations sont systématiquement trop fortes et il n'y en a pas assez pour lesquelles les simulations seraient systématiquement trop faibles.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nplot(sim_res)\n```\n\n::: {.cell-output-display}\n![Diagnostic général des résidus simulés du modèle Gamma](08-GLM_files/figure-html/fig-gammaresids2-1.png){#fig-gammaresids2 fig-align='center' width=65%}\n:::\n:::\n\n\nLa @fig-gammaresids2 indique que le modèle souffre à la fois d'un problème de dispersion (la relation espérance-variance n'est donc pas respectée) et est affecté par des valeurs aberrantes. Considérant que nous avons encore un très grand nombre d'observations, nous faisons le choix de retirer celles pour lesquelles la méthode des résidus simulés estime qu'elles sont des valeurs aberrantes dans au moins 1 % des simulations, soit environ 620 observations.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Sélection des valeurs aberrantes au seuil 0.01\nsim_outliers <- outliers(sim_res, \n lowerQuantile = 0.01,\n upperQuantile = 0.99, \n return = \"logical\")\ntable(sim_outliers)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nsim_outliers\nFALSE TRUE \n22912 634 \n```\n:::\n\n```{.r .cell-code}\n# Retirer ces observations des données\ndataset3 <- subset(dataset2, sim_outliers == FALSE)\n# Réajuster le modèle\nmodele <- vglm(Duree ~ Mode + Motif + HeureDep + \n LogDist + ArrondDep + MemeArrond + Semaine,\n data = dataset3,\n model = TRUE,\n family = gamma2)\nmodele2 <- vglm(Duree ~ Mode + Motif + HeureDep + ArrondDep + MemeArrond + Semaine,\n data = dataset3,\n model = TRUE,\n family = gamma2)\n# Extraction des prédictions du modèle (mu)\nmus <- modele@fitted.values\n# Extration du paramètre de forme\nshape <- exp(modele@coefficients[[2]])\n# Calcul des simulations\nnsim <- 1000\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- rgamma(n = nsim, shape = shape, scale = mu/shape)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calcul des résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = dataset3$Duree,\n fittedPredictedResponse = modele@fitted.values[,1],\n integerResponse = FALSE)\nplot(sim_res)\n```\n\n::: {.cell-output-display}\n![Diagnostic général des résidus simulés du modèle Gamma (après suppression d'environ 620 valeurs aberrantes)](08-GLM_files/figure-html/fig-gammaresids3-1.png){#fig-gammaresids3 fig-align='center' width=65%}\n:::\n:::\n\n\nLa @fig-gammaresids3 indique que les résidus simulés ne suivent toujours pas une distribution uniforme et qu'il existe une relation prononcée (panneau de droite) entre les résidus et les valeurs prédites. Cette dernière laisse penser que des variables indépendantes importantes ont été omises dans le modèle, ce qui n’est pas surprenant compte tenu du fait que nous ne disposons d’aucune donnée socioéconomique sur les individus ayant réalisé les trajets. Nos données sont également potentiellement affectées par la présence de dépendance spatiale.\n\nNous pouvons comparer graphiquement la variance observée dans les données et la variance attendue par le modèle. La @fig-dispgamma montre clairement que la variance des données tend à être plus grande qu'attendu quand les temps de trajet sont courts, mais diminue trop vite quand les temps de trajet augmentent. D'autres distributions pourraient être envisagées pour ajuster notre modèle : Lognormal, Weibull, etc.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction des prédictions du modèle\nmus <- predict(modele, type = \"response\")[,1]\n# Création d'un DataFrame pour contenir la prédiction et les vraies valeurs\ndf1 <- data.frame(\n mus = mus,\n reals = dataset3$Duree\n)\n# Calcul de l'intervalle de confiance à 95 % selon la distribution Gamma\n# et stockage dans un second DataFrame\nseqa <- seq(10,120,10)\nshape <- exp(modele@coefficients[[2]])\ndf2 <- data.frame(\n mus = seqa,\n lower = qgamma(p = 0.025, shape = shape, scale = seqa/shape),\n upper = qgamma(p = 0.975, shape = shape, scale = seqa/shape)\n)\n# Affichage des valeurs réelles et prédites (en rouge)\n# et de leur variance selon le modèle (en noir)\nggplot() + \n geom_point(data = df1, \n mapping = aes(x = mus, y = reals),\n color =rgb(0.9,0.22,0.27,0.4), size = 0.5) + \n geom_errorbar(data = df2,\n mapping = aes(x = mus, ymin = lower, ymax = upper),\n width = 0.2, color = rgb(0.4,0.4,0.4)) + \n labs(x = \"valeurs prédites\",\n y = \"valeurs réelles\")\n```\n\n::: {.cell-output-display}\n![Comparaison de la variance attendue par le modèle et la variance observée dans les données pour le modèle Gamma](08-GLM_files/figure-html/fig-dispgamma-1.png){#fig-dispgamma fig-align='center' width=50%}\n:::\n:::\n\n\nÀ ce stade, nous disposons de suffisamment d’éléments pour douter des résultats du modèle. Nous poursuivons tout de même notre analyse afin d'illustrer l'estimation de la qualité d'ajustement d'un tel modèle et son interprétation.\n\n**Analyse de la qualité d'ajustement**\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Ajustement d'un modèle nul\nmodele.null <- vglm(Duree ~1,\n data = dataset3,\n model = TRUE,\n family = gamma2)\n# Calcul des pseudos R2\nrsqs(loglike.full = logLik(modele),\n loglike.null = logLik(modele.null),\n full.deviance = logLik(modele) * -2,\n null.deviance = logLik(modele.null) * -2,\n nb.params = modele2@rank,\n n = nrow(dataset3)\n )\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n$`deviance expliquee`\n[1] 0.05081071\n\n$`McFadden ajuste`\n[1] 0.05036256\n\n$`Cox and Snell`\n[1] 0.3335397\n\n$Nagelkerke\n[1] 0.3336532\n```\n:::\n\n```{.r .cell-code}\n# Calcul du RMSE\npreds <- predict(modele, type = \"response\")[,1]\nsqrt(mean((preds - dataset3$Duree)**2))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 13.32661\n```\n:::\n:::\n\n\nLe modèle n’explique que 5 % de la déviance et obtient des valeurs de R^2^ ajusté de McFadden, de Cox et Snell et de Nagelkerke de respectivement 0,05, 0,33 et 0,33. La moyenne de l’erreur quadratique est de seulement 13,4 indiquant que le modèle se trompe en moyenne de seulement 13,4 minutes. La capacité de prédiction du modèle est donc limitée sans être catastrophique.\n\n**Interprétation des résultats**\n\nPour rappel, la fonction de lien dans notre modèle est la fonction `log`. Chaque coefficient représente donc l'effet de l'augmentation d'une unité des variables indépendantes sur le logarithme de l'espérance de notre variable dépendante. Si nous transformons nos coefficients avec la fonction exponentielle (`exp`), nous obtenons, pour chaque augmentation d'une unité des variables indépendantes, la multiplication de l'espérance de notre variable dépendante.\n\nPuisque nos trajets peuvent provenir de nombreux arrondissements, nous proposons de représenter l'exponentiel de leurs coefficients avec un graphique. Nous pouvons d'ailleurs comparer les exponentiels des coefficients et les effets marginaux pour simplifier l'interprétation.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction des coefficient du modèle\ncoeffs <- modele@coefficients\n# Calcul des interval de confiance des coefficients\nconf <- confint(modele)\n# Passage en exponentiel\ndf <- exp(cbind(coeffs, conf))\n# Extraction des coefficients pour les arrondissements\ndfArrond <- data.frame(df[grepl(\"ArrondDep\", row.names(df), fixed = TRUE),])\nnames(dfArrond) <- c(\"coeff\", \"lower\" , \"upper\")\ndfArrond$Arrondissement <- gsub(\"ArrondDep\" , \"\", rownames(dfArrond), fixed = TRUE)\n# Graphique des exponentiels des coefficients\nP1 <- ggplot(data = dfArrond) + \n geom_vline(xintercept = 1, color = \"red\")+\n geom_errorbarh(aes(y = reorder(Arrondissement, coeff), xmin = upper, xmax = lower),\n height = 0)+\n geom_point(aes(y = reorder(Arrondissement, coeff), x = coeff)) + \n geom_text(aes(x = upper, y = reorder(Arrondissement, coeff),\n label = paste(\"coeff. : \", round(coeff,2), sep = \"\")),\n size = 3, nudge_x = 0.07)+\n labs(x = \"Coefficient multiplicateur (ref : Ahuntsic-Cartierville)\",\n y = \"\",\n subtitle = \"Exponentiels des coefficients du modèle\")+\n xlim(c(0.75,1.46))\n# Création d'un DataFrame fictif pour les effets marginaux\ndfpred <- expand.grid(\n LogDist = mean(dataset3$LogDist),\n Motif = 'education',\n HeureDep = '7',\n MemeArrond = 'Different',\n ArrondDep = unique(dataset3$ArrondDep),\n Mode = 'pieton','velo','transport collectif',\n Semaine = 'lundi au vendredi'\n)\n# Utiliser le modèle pour effectuer des prédictions (échelle log)\nlin_pred <- predict(modele, dfpred, se = TRUE)\nmu_lin_pred <- lin_pred$fitted.values[,1]\nse_lin_pred <- lin_pred$se.fit[,1]\ndfpred2 <- data.frame(\n pred = exp(mu_lin_pred),\n lower = exp(mu_lin_pred- 1.96*se_lin_pred),\n upper = exp(mu_lin_pred+ 1.96*se_lin_pred)\n)\ndfpred2 <- cbind(dfpred2, dfpred)\n# Réaliser le graphique des effets marginaux\nP2 <- ggplot(data = dfpred2) + \n geom_col(aes(x = pred, y = ArrondDep)) + \n geom_errorbarh(aes(xmin = lower, xmax = upper, y = ArrondDep)) + \n labs(x = \"Temps de déplacement prédit\", y = \"\",\n subtitle = \"Prédiction du modèle\")\nggarrange(P1, P2, ncol = 1, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Effet de l'arrondissement de départ sur les temps de trajet à Montréal\",](08-GLM_files/figure-html/fig-arrondgamma-1.png){#fig-arrondgamma fig-align='center' width=100%}\n:::\n:::\n\n\nLa @fig-arrondgamma permet de constater que les arrondissements Ville-Marie et Plateau-Mont-Royal se distinguent avec des trajets plus courts (environ 20 % plus courts en moyenne que les trajets partant d'Ahuntsic-Cartierville). À l'inverse, Lachine est de loin l'arrondissement avec les trajets les plus longs (25 % plus longs en moyenne que les trajets partant d'Ahuntsic-Cartierville).\n\nNous appliquons la même méthode de visualisation à la variable *Heure de départ* des trajets.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Extraction des valeurs pour les heures de départ\ndfHeures <- data.frame(df[grepl(\"HeureDep\", row.names(df), fixed = TRUE),])\nnames(dfHeures) <- c(\"coeff\", \"lower\" , \"upper\")\ndfHeures$Heure <- gsub(\"HeureDep\" , \"\", rownames(dfHeures), fixed = TRUE)\n# Rajouter des 0 et des h pour de jolies légendes\ndfHeures$Heure <- paste(dfHeures$Heure,\"h\", sep=\" \")\n\n# Afficher le graphique\nggplot(data = dfHeures) + \n geom_hline(yintercept = 1, color = \"red\")+\n geom_errorbar(aes(x = Heure, ymin = upper, ymax = lower), width = 0)+\n geom_point(aes(x = Heure, y = coeff)) + \n geom_text(aes(y = upper, x = Heure, label = round(coeff,2)), size = 3, nudge_y = 0.07)+\n labs(x = \"Coefficient multiplicateur (ref : 7 h)\",\n y = \"\")\n```\n\n::: {.cell-output-display}\n![Effet de l'heure de départ sur les temps de trajet à Montréal\"](08-GLM_files/figure-html/fig-heuresgamma-1.png){#fig-heuresgamma fig-align='center' width=85%}\n:::\n:::\n\n\nNous pouvons ainsi observer, à la @fig-heuresgamma, que les trajets effectués à 10 h, 11 h et 12 h sont les plus longs de la journée, entre 30 et 40 % plus longs que ceux effectués à 7 h et 8 h qui constituent les trajets les plus courts.\n\nLe reste des coefficients (ainsi que le paramètre de forme) sont affichés dans le @tbl-coeffsgamma. Comparativement à un trajet effectué à pied, un trajet en transport en commun dure en moyenne 52 % plus longtemps (1,53 fois plus long), alors que les déplacements en véhicule individuel et en vélo sont respectivement 28 % et 23 % moins longs. Aucune différence n’est observable entre les déplacements effectués en semaine ou pendant la fin de semaine.\n\n\n::: {#tbl-coeffsgamma .cell tbl-cap='Résultats pour le modèle GLM Gamma'}\n::: {.cell-output-display}\n|Variable | Coeff.| Exp(Coeff.)| Val.p| IC 2,5 % exp(Coeff.)| IC 97,5 % exp(Coeff.)| Sign.|\n|:-----------------------|------:|-----------:|-----:|--------------------:|---------------------:|-----:|\n|Constante | 2,927| 18,672| 0,000| 14,954| 23,313| ***|\n|*Mode* | | | | | | |\n|ref : pieton | --| --| --| --| --| --|\n|transport collectif | 0,428| 1,534| 0,000| 1,495| 1,573| ***|\n|vehicule individuel | -0,312| 0,732| 0,000| 0,713| 0,751| ***|\n|velo | -0,254| 0,776| 0,000| 0,757| 0,795| ***|\n|*Motif* | | | | | | |\n|ref : education | --| --| --| --| --| --|\n|loisir | -0,015| 0,985| 0,381| 0,952| 1,019| |\n|magasinage | -0,118| 0,888| 0,000| 0,858| 0,919| ***|\n|travail | -0,068| 0,934| 0,000| 0,907| 0,963| ***|\n|LogDist | 0,331| 1,392| 0,000| 1,377| 1,406| ***|\n|*MemeArrond* | | | | | | |\n|ref : Different | --| --| --| --| --| --|\n|Meme | -0,040| 0,961| 0,000| 0,940| 0,981| ***|\n|*Semaine* | | | | | | |\n|ref : lundi au vendredi | --| --| --| --| --| --|\n|samedi et dimanche | 0,002| 1,002| 0,844| 0,981| 1,023| |\n| | | | | | | |\n|shape | 1,149| 3,156| 0,000| 3,102| 3,212| ***|\n:::\n:::\n\n\nLes déplacements ayant comme motif le magasinage et le travail ont tendance à être en moyenne plus courts de 11 % et 6 % respectivement, comparativement aux déplacements effectués pour l’éducation ou le loisir (différence non significative entre loisir et éducation). Sans surprise, la distance entre le point de départ et d’arrivée du trajet (`LogDist`) affecte sa durée de façon positive. Considérant qu’il est difficile d’interpréter des log de kilomètre (dû à une transformation de la variable originale), nous représentons l’effet de cette variable avec la prédiction du modèle à la figure. Nous utilisons pour cela le cas suivant: déplacement à pied à 7 h en semaine, ayant pour motif éducation, dont le point de départ se situe dans l’arrondissement Ahuntsic et donc le point d’arrivée est dans un autre arrondissement. Seule la distance du trajet varie de 1 à 40 km. À titre de comparaison, nous représentons aussi, pour les mêmes conditions, le cas d’une personne à vélo (en vert) et d’une personne utilisant le transport en commun (en bleu). Les lignes en pointillés représentent les intervalles de confiance à 95 % des prédictions (@fig-distancegamma).\n\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Création d'un DataFrame fictif pour la prédiction\ndfpred <- expand.grid(\n Dist = seq(1,40, 0.5),\n Motif = 'education',\n HeureDep = '7',\n MemeArrond = 'Different',\n ArrondDep = 'Ahuntsic-Cartierville',\n Mode = c('pieton','velo','transport collectif'),\n Semaine = 'lundi au vendredi'\n)\n# Mise en log de la variable de distance\ndfpred$LogDist <- log(dfpred$Dist)\n# Calcul des prédictions et de leur erreur standard (échelle log)\nlin_pred <- predict(modele, dfpred, se = TRUE)\n# Calcul des intervalles de confiance et mise en exponentielle des prédictions\ndfpred$pred <- exp(lin_pred$fitted.values[,1])\ndfpred$lower <- exp(lin_pred$fitted.values[,1] -1.96*lin_pred$se.fit[,1])\ndfpred$upper <- exp(lin_pred$fitted.values[,1] +1.96*lin_pred$se.fit[,1])\n# Ajoutons les accents pour le graphiques\ndfpred$Mode <- as.character(dfpred$Mode)\ndfpred$Mode2 <- case_when(dfpred$Mode == \"pieton\" ~ \"piéton\",\n dfpred$Mode == \"velo\" ~ \"vélo\",\n TRUE ~ dfpred$Mode)\n# Affichage des résultats\nggplot(data = dfpred) + \n geom_path(aes(x = Dist, y = lower, color = Mode2), linetype = \"dashed\")+\n geom_path(aes(x = Dist, y = upper, color = Mode2), linetype = \"dashed\")+\n geom_path(aes(x = Dist, y = pred, color = Mode2), size = 1) + \n labs(y = \"temps de trajet prédit (minutes)\",\n x = \"distance à vol d'oiseau (km)\")\n```\n\n::: {.cell-output-display}\n![Effet de la distance à vol d'oiseau sur les temps de trajet à Montréal](08-GLM_files/figure-html/fig-distancegamma-1.png){#fig-distancegamma fig-align='center' width=85%}\n:::\n:::\n\n\n### Modèle GLM avec une distribution bêta {#sec-0844}\n\nPour rappel, la distribution bêta est une distribution définie sur l’intervalle $[0,1]$, elle est donc particulièrement utile pour décrire des proportions, des pourcentages ou des probabilités. Dans la [section @sec-024316] sur les distributions, nous avons présenté la paramétrisation classique de la distribution avec les paramètres $a$ et $b$ étant tous les deux des paramètres de forme. Ces deux paramètres n’ont pas d’interprétation pratique, mais il est possible (comme pour la distribution Gamma) de reparamétrer la distribution bêta avec un paramètre de centralité (espérance) et de dispersion.\n\nNotez également que si la distribution bêta autorise la présence de 0 et de 1, le modèle GLM utilisant cette distribution doit les exclure des valeurs possibles s'il utilise la fonction de lien logistique. En effet, cette fonction à la forme suivante :\n\n$$\nlogit(x) = log(\\frac{x}{1-x})\\\\\n$$ {#eq-logitbeta}\n\nNous pouvons constater que si $x = 1$, alors le dénominateur de la fraction est 0, or il est impossible de diviser par 0. Si $x = 0$, alors nous obtenons $log(0)$ ce qui est également impossible au plan mathématique.\n\nDans le cas de figure où des 0 et/ou des 1 sont présents dans les données, quatre options sont possibles pour contourner le problème :\n\n1. Si les observations à 0 ou 1 sont très peu nombreuses, il est envisageable de les retirer des données.\n2. Si la variable mesurée le permet, il est possible de remplacer les 0 et les 1 par des valeurs très proches (0,0001 et 0,9999 par exemple) sans dénaturer excessivement les données initiales.\n3. Plutôt que d'utiliser une valeur arbitraire, @smithson2006better recommandent de recalculer la variable $Y \\in [0;1]$ avec la formule @eq-correctbeta;\n4. Employer un modèle Hurdle à trois équations, la première prédisant la probabilité d'observer $Y > 0$, la seconde, la probabilité d'observer $Y = 1$ et la dernière prédisant les valeurs de *Y* pour $0>Y>1$.\n\n$$\nY' = \\frac{Y(N-1)+s}{N}\n$$ {#eq-correctbeta}\n\nAvec *N* le nombre d'observations, *Y'* la variable *Y* transformée et *s* une constante. Plus cette dernière est élevée, plus la variable *Y'* a des valeurs éloignées de 0 et 1. la valeur de 0,5 est recommandée par les auteurs.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Reparamétrisation de la distribution bêta**\n:::\n::: bloc_aller_loin-body\nPour une distribution bêta telle que définie par $Y \\sim Beta(a,b)$, l'espérance de cette distribution et sa variance sont données par : \n\n$$\n\\begin{aligned}\n&E(Y) = \\frac{a}{a+b} \\\\\n&Var(Y) = \\frac{a \\times b}{(a+b)^2(a+b+1)}\\\\\n\\end{aligned}\n$$ {#eq-glm20}\n\nPour reparamétrer cette distribution, nous définissons un nouveau paramètre $\\phi$ (phi) tel que:\n\n$$\n\\begin{aligned}\n&a = \\phi * E(Y) \\\\\n&b = \\phi - a \\\\\n&Var(Y) = \\frac{E(Y) \\times (1-E(Y))}{1+\\phi}\n\\end{aligned}\n$$ {#eq-glm21}\n\nDe cette manière, il est possible d'exprimer la distribution bêta en fonction de son espérance (sa valeur attendue, ce qui s'interprète approximativement comme une moyenne) et d'un paramètre $\\phi$ intervenant dans le calcul de sa variance. Vous noterez d'ailleurs que la variance de cette distribution dépend de sa moyenne, impliquant à nouveau une hétéroscédasticité intrinsèque.\n:::\n:::\n\nPour résumer, nous nous retrouvons donc avec un modèle qui prédit l'espérance d’une distribution bêta avec une fonction de lien logistique. La variance de cette distribution est fonction de cette moyenne et d'un second paramètre $\\phi$. Ces informations sont résumées dans la fiche d'identité du modèle (@tbl-betaentity).\n\n\n::: {#tbl-betaentity .cell tbl-cap='Carte d\\'identité du modèle bêta'}\n::: {.cell-output-display}\n| | |\n|:---------------------------|:--------------------------------------------------------------------------------------------------|\n|Type de variable dépendante |Variable continue dans l'intervalle $]0,1[$ |\n|Distribution utilisée |Student |\n|Formulation |$Y \\sim Beta(\\mu,\\phi)$ \\newline $g(\\mu) = \\beta_0 + \\beta X$ \\newline $g(x) = log(\\frac{x}{1-x})$ |\n|Fonction de lien |log |\n|Paramètre modélisé |$\\mu$ |\n|Paramètres à estimer |$\\beta_0$, $\\beta$, et $\\phi$ |\n|Conditions d'application |$Variance = \\frac{\\mu \\times (1-\\mu)}{1+\\phi}$ |\n:::\n:::\n\n\n#### Conditions d'application {#sec-08441}\n\nComme pour un modèle Gamma, la seule condition d'application spécifique à un modèle avec distribution bêta est que la variance des résidus suit la forme attendue par la distribution bêta.\n\n#### Interprétation des coefficients {#sec-08442}\n\nPuisque le modèle utilise la fonction de lien logistique, les exponentiels des coefficients $\\beta$ du modèle peuvent être interprétés comme des rapports de cotes (voir la [section @sec-0821] sur le modèle GLM binomial). Admettons ainsi que nous avons obtenu pour une variable indépendante $X_1$ le coefficient $\\beta_1$ de 0,12. Puisque le coefficient est positif, cela signifie qu’une augmentation de $X_1$ conduit à une augmentation de l'espérance de *Y*. L’exponentiel de 0,12 est 1,13, ce qui signifie qu’une augmentation d’une unité de $X_1$ multiplie par 1,13 (augmente de 13 %) les chances d'une augmentation de *Y*. **Pour ce type de modèle, il est particulièrement important de calculer ses prédictions afin d'en faciliter l'interprétation**.\n\n#### Exemple appliqué dans R {#sec-08443}\n\nAfin de présenter le modèle GLM avec une distribution bêta, nous utilisons un jeu de données que nous avons construit pour l’île de Montréal. Nous nous intéressons à la question des îlots de chaleur urbains au niveau des aires de diffusion (AD – entités spatiales du recensement canadien comprenant entre 400 et 700 habitants). Pour cela, nous avons calculé dans chaque AD le pourcentage de sa surface classifiée comme îlot de chaleur dans la carte des îlots de [chaleur/fraicheur](https://www.donneesquebec.ca/recherche/fr/dataset/ilots-de-chaleur-fraicheur-urbains-et-temperature-de-surface) réalisée par l’INSPQ et le CERFO.\n\nLa question que nous nous posons est la suivante : les populations vulnérables socioéconomiquement et/ou physiologiquement sont-elles systématiquement plus exposées à la nuisance que représentent les îlots de chaleur? Cette question se rattache donc au champ de la recherche sur l'équité environnementale. Plusieurs études se sont d'ailleurs déjà penchées sur la question des îlots de chaleur abordée sous l'angle de l'équité environnementale [@harlan2007shade; @sanchez2019cooling; @huang2011everyone]. Nous modélisons donc pour chaque AD (n = 3 158) de l’île de Montréal la proportion de sa surface couverte par des îlots de chaleur. Nos variables indépendantes sont divisées en deux catégories : variables environnementales et variables socio-économiques. Les premières sont des variables de contrôle, il s’agit de la densité de végétation dans l’AD (ajoutée avec une polynomiale d'ordre deux) et de l'arrondissement dans lequel elle se situe. Ces deux paramètres affectent directement les chances d’observer des îlots de chaleur, mais nous souhaitons isoler leurs effets (toutes choses étant égales par ailleurs) de ceux des variables socio-économiques. Ces dernières ont pour objectif de cibler les populations vulnérables sur le plan physiologique (personnes âgées et enfants de moins de 14 ans) ou socio-économique (minorités visibles et faible revenu). L'ensemble de ces variables sont présentées dans le @tbl-variablebeta. Notez que, puisque le modèle avec distribution bêta ne peut pas prendre en compte des valeurs exactes de 1 ou 0, nous les avons remplacées respectivement par 0,99 et 0,01. Cette légère modification n'altère que marginalement les données, surtout si nous considérons qu'elles sont agrégées au niveau des AD et proviennent originalement d'imagerie satellitaire.\n\n\n::: {#tbl-variablebeta .cell tbl-cap='Variables indépendantes utilisées dans le modèle bêta'}\n::: {.cell-output-display}\n|Nom de la variable |Signification |Type de variable |Mesure |\n|:------------------|:-----------------------------|:-----------------|:------------------------------------------------------------------|\n|A65PlusPct |Population de 65 ans et plus |Variable continue |Pourcentage de la population ayant 65 ans et plus |\n|A014Pct |Population de 14 ans et moins |Variable continue |Pourcentage de la population ayant 14 ans et moins |\n|PopFRPct |Population à faible revenu |Variable continue |Pourcentage de la population à faible revenu |\n|PopMVPct |Minorités visibles |Variable continue |Pourcentage de la population faisant partie des minorités visibles |\n|VegPct |Végétation |Variable continue |Pourcentage de la surface de l’AD couverte par de la végétation |\n|Arrond |Arrondissements |Variable continue |Arrondissement de l'Île de Montréal |\n:::\n:::\n\n\n**Vérification des conditions d'application**\n\nSans surprise, nous commençons par charger nos données et nous nous assurons de l'absence de multicolinéarité excessive entre nos variables indépendantes.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n## Chargement des données\ndataset <- read.csv(\"data/glm/data_chaleur.csv\", fileEncoding = \"utf8\")\n## Calcul des valeurs de vif\nvif(glm(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n poly(prt_veg, degree = 2) + Arrond,\n data = dataset))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n GVIF Df GVIF^(1/(2*Df))\nA65Pct 1.609917 1 1.268825\nA014Pct 2.206072 1 1.485285\nPopFRPct 2.162036 1 1.470386\nPopMVPct 2.370269 1 1.539568\npoly(prt_veg, degree = 2) 2.619552 2 1.272204\nArrond 7.899208 32 1.032820\n```\n:::\n:::\n\n\nLa seule variable semblant poser un problème de multicolinéarité est la variable `Arrond`. Cependant, du fait de sa nature multinomiale, elle regroupe en réalité 32 coefficients (voir la colonne `Df`). Il faut donc utiliser la règle habituelle de 5 sur le carré de la troisième colonne (`GVIF^(1/(2*Df))`) du tableau [@fox1992generalized], soit `1,032820^2 = 1,066717`, ce qui est bien inférieur à la limite de 5. Nous n'avons donc pas de problème de multicolinéarité excessive. Nous pouvons passer au calcul des distances de Cook. Pour ajuster notre modèle, nous utilisons le *package* `mgcv` et la fonction `gam` avec le paramètre `family = betar(link = \"logit\")`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Ajustement d'une première version du modèle\nmodele <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n poly(prt_veg, degree=2) + Arrond,\n data = dataset, family = betar(link = \"logit\"))\n# Calcul des distances de Cook\ndf <- data.frame(\n cooksd = cooks.distance(modele),\n oid = 1:nrow(dataset)\n)\n# Affichage des distances de Cook\nggplot(data = df)+\n geom_point(aes(x = oid, y = cooksd),\n color = rgb(0.4,0.4,0.4,0.4), size = 0.5)+\n labs(x = \"\", y = \"Distance de Cook\")\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle GLM bêta](08-GLM_files/figure-html/fig-cookdistbeta-1.png){#fig-cookdistbeta fig-align='center' width=65%}\n:::\n:::\n\n\nNous pouvons observer à la @fig-cookdistbeta que seulement deux observations se distinguent très nettement des autres. Nous les isolons donc dans un premier temps.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ncas_etranges <- subset(dataset, df$cooksd >= 0.01)\nprint(cas_etranges[,23:ncol(cas_etranges)])\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n A014Pct A65Pct PopFRPct PopMVPct Km2 HabKm2 Shape_Leng Shape_Area\n1666 11.78 26.77 6.38 11.65 6.458460 72.3083 21153.055 6458456.6\n2803 15.54 31.07 24.17 52.17 0.134013 5283.0879 1651.471 134012.5\n prt_hot prt_veg dist_cntr Arrond hot\n1666 1.824483 90.11691 29.181345 Senneville 0.02\n2803 40.117994 60.15745 4.178823 Westmount 0.40\n```\n:::\n:::\n\n\nCes deux observations n'ont pas de points communs marqués, et ne semblent pas avoir de valeurs particulièrement fortes sur les différentes variables indépendantes ou la variable dépendante. Nous décidons donc de les supprimer et de recalculer les distances de Cook.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Suppression des deux observations très influentes\ndataset2 <- subset(dataset, df$cooksd < 0.01)\nmodele2 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n I(prt_veg**2) + prt_veg + Arrond,\n data = dataset2, family = betar(link = \"logit\"), methode = \"REML\")\n# Calcul des distances de Cook\ndf2 <- data.frame(\n cooksd = cooks.distance(modele2),\n oid = 1:nrow(dataset2)\n)\n# Affichage des distances de Cook\nggplot(data = df2)+\n geom_point(aes(x = oid, y = cooksd),\n color = rgb(0.4,0.4,0.4,0.4), size = 0.5)+\n labs(x = \"\", y = \"Distance de Cook\")\n```\n\n::: {.cell-output-display}\n![Distances de Cook pour le modèle GLM bêta (suppression de deux observations influentes)](08-GLM_files/figure-html/fig-cookdistbeta2-1.png){#fig-cookdistbeta2 fig-align='center' width=65%}\n:::\n:::\n\n\nAprès réajustement, nous constatons à nouveau qu'une observation est **extrêmement** éloignée des autres (@fig-cookdistbeta2). Nous la retirons également, car cette différence est si forte qu'elle risque de polluer le modèle.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Suppression de l'observation très étonnante\ndataset3 <- subset(dataset2, df2$cooksd\n\n\n\n
\n
Contrairement à un modèle LM, un GLM permet de choisir :
\n
Relisez au besoin la [section @sec-081].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
La fonction de lien est utilisée pour transformer :
\n
Relisez au besoin la [section @sec-0812]
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Un modèle GLM est ajusté par la méthode des moindres carrés.
\n
Relisez au besoin la [section @sec-0811].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Dans un modèle GLM la vraisemblance (likelihood) est :
\n
Relisez au besoin la [section @sec-113].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Idéalement, les résidus simulés d'un modèle GLM devraient :
\n
Relisez au besoin la [section @sec-0814].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
L'AIC
\n
Relisez au besoin la [section @sec-0815].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Pour un modèle utilisant une distribution binomiale, le paramètre modélisé par l'équation de régression est :
\n
Relisez au besoin la [section @sec-0821].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Si la fonction de lien logistique est utilisée dans un modèle binomial, comment peuvent être interprétés les coefficients?
\n
Relisez au besoin la [section @sec-0821].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Pour choisir la distribution la mieux adaptée pour un modèle GLM, il est possible de :
\n
Relisez au besoin la [section @sec-086].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n\n
\n\n
\n\n", + "supporting": [ + "08-GLM_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/08-GLM_files/figure-html/fig-CookdCotePropor-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-CookdCotePropor-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-CookdCotePropor-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-CookdCotePropor-1.png diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-agebinom-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-agebinom-1.png new file mode 100644 index 0000000..e817841 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-agebinom-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-arrondgamma-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-arrondgamma-1.png new file mode 100644 index 0000000..addd3b0 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-arrondgamma-1.png differ diff --git a/docs/08-GLM_files/figure-html/fig-betaArrond-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-betaArrond-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-betaArrond-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-betaArrond-1.png diff --git a/docs/08-GLM_files/figure-html/fig-betaFR-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-betaFR-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-betaFR-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-betaFR-1.png diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-compnbdistr2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-compnbdistr2-1.png new file mode 100644 index 0000000..8dfc888 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-compnbdistr2-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-comppoissdistr-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-comppoissdistr-1.png new file mode 100644 index 0000000..a1cc869 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-comppoissdistr-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-comppoissdistr2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-comppoissdistr2-1.png new file mode 100644 index 0000000..540dde1 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-comppoissdistr2-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-compzipdistr-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-compzipdistr-1.png new file mode 100644 index 0000000..f3d4daa Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-compzipdistr-1.png differ diff --git a/docs/08-GLM_files/figure-html/fig-cookdistGLMbinom-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-cookdistGLMbinom-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-cookdistGLMbinom-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-cookdistGLMbinom-1.png diff --git a/docs/08-GLM_files/figure-html/fig-cookdistGLMbinom2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-cookdistGLMbinom2-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-cookdistGLMbinom2-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-cookdistGLMbinom2-1.png diff --git a/docs/08-GLM_files/figure-html/fig-cookdistbeta-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-cookdistbeta-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-cookdistbeta-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-cookdistbeta-1.png diff --git a/docs/08-GLM_files/figure-html/fig-cookdistbeta2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-cookdistbeta2-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-cookdistbeta2-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-cookdistbeta2-1.png diff --git a/docs/08-GLM_files/figure-html/fig-cookdistbeta3-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-cookdistbeta3-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-cookdistbeta3-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-cookdistbeta3-1.png diff --git a/docs/08-GLM_files/figure-html/fig-cookdistgamma-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-cookdistgamma-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-cookdistgamma-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-cookdistgamma-1.png diff --git a/docs/08-GLM_files/figure-html/fig-cookdistgamma2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-cookdistgamma2-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-cookdistgamma2-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-cookdistgamma2-1.png diff --git a/docs/08-GLM_files/figure-html/fig-cookdistnb-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-cookdistnb-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-cookdistnb-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-cookdistnb-1.png diff --git a/docs/08-GLM_files/figure-html/fig-cookdistnb2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-cookdistnb2-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-cookdistnb2-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-cookdistnb2-1.png diff --git a/docs/08-GLM_files/figure-html/fig-cookmultinom-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-cookmultinom-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-cookmultinom-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-cookmultinom-1.png diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-diagresnb-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-diagresnb-1.png new file mode 100644 index 0000000..e91b740 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-diagresnb-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-diagressimcumul-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-diagressimcumul-1.png new file mode 100644 index 0000000..704c5be Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-diagressimcumul-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-diagzip2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-diagzip2-1.png new file mode 100644 index 0000000..9f80117 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-diagzip2-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-dispgamma-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-dispgamma-1.png new file mode 100644 index 0000000..dcfe187 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-dispgamma-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-distancegamma-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-distancegamma-1.png new file mode 100644 index 0000000..9166275 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-distancegamma-1.png differ diff --git a/docs/08-GLM_files/figure-html/fig-distripoissmod-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-distripoissmod-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-distripoissmod-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-distripoissmod-1.png diff --git a/docs/08-GLM_files/figure-html/fig-equlibresensispeci-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-equlibresensispeci-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-equlibresensispeci-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-equlibresensispeci-1.png diff --git a/docs/08-GLM_files/figure-html/fig-gammadatadistrib-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-gammadatadistrib-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-gammadatadistrib-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-gammadatadistrib-1.png diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-gammaresids-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-gammaresids-1.png new file mode 100644 index 0000000..6c0f5d0 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-gammaresids-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-gammaresids2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-gammaresids2-1.png new file mode 100644 index 0000000..1a426be Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-gammaresids2-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-gammaresids3-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-gammaresids3-1.png new file mode 100644 index 0000000..96e8bbb Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-gammaresids3-1.png differ diff --git a/docs/08-GLM_files/figure-html/fig-gausscook-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-gausscook-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-gausscook-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-gausscook-1.png diff --git a/docs/08-GLM_files/figure-html/fig-gausscook2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-gausscook2-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-gausscook2-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-gausscook2-1.png diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-gaussresid-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-gaussresid-1.png new file mode 100644 index 0000000..7e0baf1 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-gaussresid-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-gausssim-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-gausssim-1.png new file mode 100644 index 0000000..4f973fc Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-gausssim-1.png differ diff --git a/docs/08-GLM_files/figure-html/fig-gausssim2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-gausssim2-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-gausssim2-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-gausssim2-1.png diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-heuresgamma-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-heuresgamma-1.png new file mode 100644 index 0000000..e96e5a1 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-heuresgamma-1.png differ diff --git a/docs/08-GLM_files/figure-html/fig-histopriceairbnb-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-histopriceairbnb-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-histopriceairbnb-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-histopriceairbnb-1.png diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-linearbinom-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-linearbinom-1.png new file mode 100644 index 0000000..04dd039 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-linearbinom-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-linearbinom2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-linearbinom2-1.png new file mode 100644 index 0000000..b5b5893 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-linearbinom2-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-linearbinom3-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-linearbinom3-1.png new file mode 100644 index 0000000..e8c0d2f Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-linearbinom3-1.png differ diff --git a/docs/08-GLM_files/figure-html/fig-paysbinom-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-paysbinom-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-paysbinom-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-paysbinom-1.png diff --git a/docs/08-GLM_files/figure-html/fig-poisscookdist-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-poisscookdist-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-poisscookdist-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-poisscookdist-1.png diff --git a/docs/08-GLM_files/figure-html/fig-poisscookdist2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-poisscookdist2-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-poisscookdist2-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-poisscookdist2-1.png diff --git a/docs/08-GLM_files/figure-html/fig-predpricecatveg-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-predpricecatveg-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-predpricecatveg-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-predpricecatveg-1.png diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-residsimbeta-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-residsimbeta-1.png new file mode 100644 index 0000000..e6ba333 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-residsimbeta-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-residsimbeta3-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-residsimbeta3-1.png new file mode 100644 index 0000000..4d5c837 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-residsimbeta3-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-residsimbeta4-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-residsimbeta4-1.png new file mode 100644 index 0000000..eb4dfcd Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-residsimbeta4-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-residsimbinomHistoUnif-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-residsimbinomHistoUnif-1.png new file mode 100644 index 0000000..e02e167 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-residsimbinomHistoUnif-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-residusmultinom-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-residusmultinom-1.png new file mode 100644 index 0000000..f2b7e9d Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-residusmultinom-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-residusmultinom4-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-residusmultinom4-1.png new file mode 100644 index 0000000..8d22b6c Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-residusmultinom4-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-simdistribgamma-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-simdistribgamma-1.png new file mode 100644 index 0000000..72b8cdf Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-simdistribgamma-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-simrespoiss-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-simrespoiss-1.png new file mode 100644 index 0000000..05e34ff Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-simrespoiss-1.png differ diff --git a/docs/08-GLM_files/figure-html/fig-stucookdist-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-stucookdist-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-stucookdist-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-stucookdist-1.png diff --git a/docs/08-GLM_files/figure-html/fig-stucookdist2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-stucookdist2-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-stucookdist2-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-stucookdist2-1.png diff --git a/docs/08-GLM_files/figure-html/fig-studentdistrib-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-studentdistrib-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-studentdistrib-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-studentdistrib-1.png diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-studentresid-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-studentresid-1.png new file mode 100644 index 0000000..4462967 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-studentresid-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-studentresid2-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-studentresid2-1.png new file mode 100644 index 0000000..9b4941d Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-studentresid2-1.png differ diff --git a/.quarto/_freeze/08-GLM/figure-html/fig-studentresid3-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-studentresid3-1.png new file mode 100644 index 0000000..751aa88 Binary files /dev/null and b/.quarto/_freeze/08-GLM/figure-html/fig-studentresid3-1.png differ diff --git a/docs/08-GLM_files/figure-html/fig-surdispnb-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-surdispnb-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-surdispnb-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-surdispnb-1.png diff --git a/docs/08-GLM_files/figure-html/fig-surdisppoiss-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-surdisppoiss-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-surdisppoiss-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-surdisppoiss-1.png diff --git a/docs/08-GLM_files/figure-html/fig-villebinom-1.png b/.quarto/_freeze/08-GLM/figure-html/fig-villebinom-1.png similarity index 100% rename from docs/08-GLM_files/figure-html/fig-villebinom-1.png rename to .quarto/_freeze/08-GLM/figure-html/fig-villebinom-1.png diff --git a/.quarto/_freeze/09-GLMM/execute-results/html.json b/.quarto/_freeze/09-GLMM/execute-results/html.json new file mode 100644 index 0000000..afafa5d --- /dev/null +++ b/.quarto/_freeze/09-GLMM/execute-results/html.json @@ -0,0 +1,16 @@ +{ + "hash": "4468096d0712f081dfb506e67a6ec070", + "result": { + "markdown": "# Régressions à effets mixtes (GLMM) {#sec-chap09}\n\nDans les deux chapitres précédents, nous avons consécutivement présenté la méthode de la régression linéaire multiple (LM) ainsi qu'une de ses extensions, soit les modèles linéaires généralisés (GLM). Dans ce chapitre, nous poursuivons sur cette voie avec une nouvelle extension : les modèles généralisés à effet mixtes (GLMM). À la fin de cette section, vous serez en mesure de :\n\n* comprendre la distinction entre un modèle GLM et un modèle GLMM;\n* distinguer un effet fixe d'un effet aléatoire;\n*\tformuler des modèles GLMM avec des constantes et/ou des pentes aléatoires;\n*\teffectuer les diagnostics d’un GLMM.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes.\n - `ellipse` pour représenter des ellipses sur certains graphiques.\n \n* Pour ajuster des modèles GLMM :\n - `lme4`, offrant une interface simple pour ajuster des GLMM.\n\n* Pour analyser des modèles GLM :\n - `car`, essentiellement pour la fonction `vif`.\n - `DHARMa` pour le diagnostic des résidus simulés.\n - `merTools` pour explorer les résultats d'un GLMM.\n - `lmerTest` pour obtenir des tests de significativité pour les coefficients d'un GLMM.\n - `MuMin` pour calculer les R^2^ conditionnel et marginal.\n - `performance` pour calculer l'ICC et d'autres mesures d'ajustement.\n:::\n:::\n\n## Introduction {#sec-091}\n\n### Indépendance des observations et effets de groupes {#sec-0911}\n\nNous avons vu dans les précédents chapitres que l'indépendance des observations est une condition d'application commune à l'ensemble des modèles de régression. Cette condition implique ainsi que chaque unité d'observation de notre jeu de données est indépendante des autres; en d'autres termes, qu'elle ne soit associée à aucune autre observation par un lien de dépendance. Prenons un exemple concret pour illustrer cette notion. Admettons que nous nous intéressons à la performance scolaire d'élèves du secondaire à Montréal. Pour cela, nous collectons la moyenne des résultats aux examens du ministère de tous les élèves des différentes commissions scolaires de l'île de Montréal. Chaque élève appartient à une classe spécifique, et chaque classe se situe dans une école spécifique. Les classes constituent des environnements particuliers, la performance des élèves y est influencée par un ensemble de facteurs comme la personne qui enseigne et les relations entre les élèves d'une même classe. Deux élèves provenant d'une même classe sont donc lié(e)s par une forme de structure propre à leur classe et ne peuvent pas être considéré(e)s comme indépendant(e)s. De même, l'école constitue un environnement particulier pouvant influencer la performance des élèves du fait de moyens financiers plus importants, de la mise en place de programmes spéciaux, de la qualité des infrastructures (bâtiment, gymnase, cour d'école) ou d'une localisation minimisant certaines nuisances à l'apprentissage comme le bruit. À nouveau, deux élèves provenant d'une même école partagent une forme de structure qui, cette fois-ci, est propre à leur école. Si nous collectons des données pour l'ensemble du Canada, nous pourrions étendre ce raisonnement aux villes dans lesquelles les écoles se situent et aux provinces.\n\nDans cet exemple, la dépendance entre les données est provoquée par un effet de groupe : il est possible de rassembler les observations dans des ensembles (classes et écoles) influençant vraisemblablement la variable étudiée (performance scolaire). Les effets des classes et des écoles ne sont cependant pas intrinsèques aux élèves. En effet, il est possible de changer un ou une élève de classe ou d'école, mais pas de changer son âge ou sa situation familiale. Il est ainsi possible de distinguer la population des élèves, la population des classes, et la population des écoles (@fig-glmmecoles). Ces effets de groupes sont plus la règle que l'exception dans l'analyse de données en sciences sociales, ce qui met à mal l'hypothèse d'indépendance des observations. Notez que les effets de groupes ne sont pas les seules formes de structures remettant en cause l'indépendance des observations. Il existe également des structures temporelles (deux observations proches dans le temps ont plus de chances de se ressembler) et spatiales (deux observations proches dans l'espace ont plus de chances de se ressembler); cependant, les cas de la dépendance temporelle et spatiale ne sont pas couverts dans ce livre, car ils sont complexes et méritent un ouvrage dédié.\n\n\n![Structure hiérarchique entre élèves, classes et écoles](images/Chap09/Hierarchie_Ecoles.png){#fig-glmmecoles width=\"50%\" fig-align=\"center\"}\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**La notion de pseudo-réplication**\n:::\n::: bloc_aller_loin-body\nLes effets de dépendance causés par des structures de groupe, temporelles ou spatiales, sont regroupés sous le terme de pseudo-réplication. Il est intéressant de se pencher sur la signification de ce mot pour comprendre le problème intrinsèque causé par la dépendance entre les observations et son influence sur l'inférence.\n\nReprenons l'exemple des élèves et de la performance scolaire et admettons que nous souhaitons estimer la moyenne générale de l'ensemble des élèves sur l'île de Montréal, mais que nous ne disposons pas du jeu de données complet. Nous devons donc collecter un échantillon suffisamment grand pour estimer la moyenne pour l'ensemble de cette population. Raisonnons en termes de quantité d'informations. Si nous ne disposons d'aucune observation (nous n'avons pas encore interrogé d'élèves), cette quantité est de 0. Si nous interrogeons un premier ou une première élève, nous obtenons une donnée supplémentaire, et donc un point d'information supplémentaire (+1). Admettons maintenant que nous collectons 30 observations dans une école, 10 dans une seconde et 5 dans une troisième. A priori, nous pourrions dire que nous avons ajouté 45 points d'information à notre total de connaissance. Ce serait le cas si les observations étaient indépendantes les unes des autres. Dans un tel contexte, chaque observation ajoute la même quantité d'information. Cependant, puisque les personnes étudiant dans la même école ont plus de chance de se ressembler, interroger les élèves d'une même école apporte moins d'information. Notez que plus la ressemblance entre les élèves d'une même école est forte, plus la quantité d'information est réduite. Nous sommes donc loin de disposer d'une quantité d'information égale à 45. Chaque réplication de l'expérience (demander à un ou une élève sa moyenne annuelle) n'apporte pas autant d'information qu'attendu si les observations étaient indépendantes, c'est pourquoi on parle de **pseudo-réplication**.\n\nLa pseudo-réplication influence directement l'inférence statistique puisque le calcul des différents tests statistiques assume que chaque observation apporte autant d'information que les autres. En cas de présence de pseudo-réplication, la quantité d'information présente dans l'échantillon est plus petite qu'attendu. Il est possible de voir cela comme une forme de surestimation de la taille de l'échantillon. En cas de pseudo-réplication, nous disposons en réalité de moins de données que ce que l'on attendrait d'un échantillon de cette taille, si les observations étaient indépendantes. La conséquence est la sous-estimation de la variabilité réelle des données et l'augmentation des risques de trouver des effets significatifs dans l'échantillon alors qu'ils ne le sont pas pour l'ensemble de la population.\n:::\n:::\n\n\n### Terminologie : effets fixes et effets aléatoires {#sec-0912}\n\nPuisque les effets des classes et des écoles ne sont pas propres aux élèves, il convient de les introduire différemment dans les modèles de régression. Nous appelons un effet fixe, un effet qui est propre aux observations que nous étudions et un effet aléatoire, un effet provoqué par une structure externe (effet de groupe, effet temporel et/ou effet spatial). Un modèle combinant à la fois des effets fixes et des effets aléatoires est appelé un **modèle à effets mixtes**, ou GLMM pour *Generalized Linear Mixed Model*. Tous les modèles que nous avons ajustés dans les sections précédentes ne comprenaient que des effets fixes alors qu'à plusieurs reprises, des effets aléatoires induits par l'existence de structure de groupe auraient pu (dû) être utilisés. Prenons pour exemple le modèle logistique binomial visant à prédire la probabilité d'utiliser le vélo comme mode de transport pour son trajet le plus fréquent. La variable multinomiale *Pays*, représentant le pays dans lequel les personnes interrogées résident, a été introduite comme un effet fixe. Cependant, l'effet du pays ne constitue pas une caractéristique propre aux individus; il s'agit plutôt d'un agrégat complexe mêlant culture, météorologie, politiques publiques et formes urbaines. À l'inverse, le sexe ou l'âge sont bien des caractéristiques intrinsèques des individus et peuvent être considérés comme des effets fixes.\n\nNotez que l'utilisation du terme *effet aléatoire* peut porter à confusion, car il est utilisé différemment en fonction du champ d'études. Parmi les différentes définitions relevées par @gelman2005analysis d'un effet aléatoire, citons les suivantes : \n\n* Les effets fixes sont identiques pour tous les individus, alors que les effets aléatoires varient (définition 1).\n\n* Les effets sont fixes s'ils sont intéressants en eux-mêmes, et les effets sont aléatoires si nous nous intéressons à la population dont ils sont issus (définition 2).\n\n* Lorsqu'un échantillon couvre une grande part de la population, la variable correspondante est un effet fixe. Si l'échantillon couvre une faible part de la population, l'effet est aléatoire (définition 3).\n\n* Si l'effet est censé provenir d'une variable aléatoire, alors il s'agit d'un effet aléatoire (définition 4).\n\n* Les effets fixes sont estimés par la méthode des moindres carrés ou par le maximum de vraisemblance, alors que les effets aléatoires sont estimés avec régularisation (*shrinkage*) (définition 5).\n\nIl est ainsi possible de se retrouver dans des cas où un effet serait classé comme fixe selon une définition et aléatoire selon une autre. La deuxième définition suppose même qu'un effet peut être aléatoire ou fixe selon l'objectif de l'étude. La dernière définition a l'avantage d'être mathématique, mais ne permet pas de décider si un effet doit être traité comme aléatoire ou fixe. Nous ne proposons pas ici de clore le débat, mais plutôt de donner quelques pistes de réflexion pour décider si un effet doit être modélisé comme fixe ou aléatoire:\n\n* Est-ce que l'effet en question est propre aux individus étudiés ou est externe aux individus? S'il est propre aux individus, il s'agit plus certainement d'un effet fixe. À titre d'exemple, il n'est pas possible de changer l'âge d'une personne, mais il est certainement possible de changer de ville de résidence.\n\n* Existe-t-il un nombre bien arrêté de catégories possibles pour l'effet en question? Si oui, il s'agit plus certainement d'un effet fixe. Il y a un nombre bien arrêté de catégories pour la variable sexe, mais pour la variable pays, de nombreuses autres valeurs peuvent être ajoutées. Il est également possible de se demander s'il semble cohérent d'effectuer un échantillonnage sur les catégories en question. Dans le cas des pays, nous pourrions mener une étude à l'échelle des pays et collecter des données sur un échantillon de l'ensemble des pays. Il existe donc une population de pays, ce que nous ne pouvons pas affirmer pour la variable sexe.\n\n* L'effet en question est direct ou indirect? Dans le second cas, l'effet en question est un agglomérat complexe découlant de plusieurs processus n'ayant pas été mesurés directement, ce qui correspond davantage à un effet aléatoire. Ainsi, l'effet du pays de résidence des individus sur leur probabilité d'utiliser le vélo est bien une agglomération complexe d'effets (culture, météorologie, orientation des politiques publiques, formes urbaines, etc.) n'ayant pas tous été mesurés. À l'inverse, l'âge d'un individu a bien un effet direct sur sa probabilité d'utiliser le vélo.\n\n* L'effet est-il le même pour tous les individus, ou doit-il varier selon le groupe dans lequel l'individu se situe? Si un effet doit varier en fonction d'un groupe, il s'apparente davantage à un effet aléatoire. Pour reprendre l'exemple de l'âge, nous pourrions décider que cette caractéristique des individus n'a peut-être pas le même effet en fonction du pays dans lequel vit l'individu et l'ajouter au modèle comme un effet aléatoire.\n\nVous comprendrez donc qu'une partie non négligeable du choix entre effet fixe ou effet aléatoire réside dans le cadre théorique à l'origine du modèle. Maintenant que cette distinction conceptuelle a été détaillée, nous pouvons passer à la présentation statistique des modèles GLMM.\n\n## Principes de base des GLMM {#sec-092}\n\nUn GLMM est donc un modèle GLM introduisant à la fois des effets fixes et des effets aléatoires. Si nous ne considérons que les effets de groupes, un GLMM peut avoir trois formes : constantes aléatoires, pentes aléatoires et constantes et pentes aléatoires. Nous présentons ici ces trois formes en reprenant l'exemple ci-dessus avec des élèves intégré(e)s dans des classes et pour lesquel(le)s le niveau de performance à l'examen ministériel de mathématique nous intéresse.\n\n### GLMM avec constantes aléatoires {#sec-0921}\n\nIl s'agit de la forme la plus simple d'un GLMM. Plus spécifiquement, elle autorise le modèle à avoir une constante différente pour chaque catégorie d'une variable multinomiale. En d'autres termes, si nous reprenons l'exemple des élèves dans leurs classes, nous tentons d'ajouter dans le modèle l'idée que chaque classe a une moyenne différente en termes de performance à l'examen de mathématique. Il est assez facile de visualiser ce que cela signifie à l'aide d'un graphique. Admettons que nous modélisons la note obtenue par des élèves du secondaire à l'examen ministériel de mathématique à partir d'une autre variable continue représentant le temps de travail moyen par semaine en dehors des heures de classe et d'une variable catégorielle représentant dans quelle classe se trouve chaque élève. Notez qu'il ne s'agit pas ici de vraies données, mais de simples simulations utilisées à titre d'illustration. Si nous ne tenons pas compte des classes, nous pouvons ajuster une régression linéaire simple entre nos deux variables continues comme le propose la @fig-randominter1.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Influence du temps de travail sur la performance scolaire d'élèves](09-GLMM_files/figure-html/fig-randominter1-1.png){#fig-randominter1 fig-align='center' width=70%}\n:::\n:::\n\n\nNous constatons que notre modèle semble bien identifier la relation positive entre le temps de travail et le niveau de performance, mais la droite de régression est très éloignée de chaque point; nous avons ainsi énormément d'erreurs de prédiction, et donc des résidus importants. Jusqu'ici, nous avons vu que nous pouvons ajouter un prédicteur et intégrer l'effet des classes comme un effet fixe (@fig-randominter2).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Influence du temps de travail sur la performance scolaire d'élèves en tenant compte de l'effet de leur classe (effet fixe)](09-GLMM_files/figure-html/fig-randominter2-1.png){#fig-randominter2 fig-align='center' width=70%}\n:::\n:::\n\n\nCet ajustement constitue une nette amélioration du modèle. Prenons un instant pour reformuler clairement notre modèle à effets fixes : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\sum^k_{j=1}{\\beta_j x_{2j}}\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm1}\n\navec $x_1$ le temps de travail et $x_2$ la classe ayant *k-1* modalités (puisqu'une modalité est la référence). Nous ajustons ainsi un coefficient pour chaque classe, ce qui a pour effet de tirer vers le haut ou vers le bas la prédiction du modèle en fonction de la classe. Cet effet est pour l'instant fixe, mais nous avons déterminé dans les sections précédentes qu'il serait conceptuellement plus approprié de le traiter comme un effet aléatoire.\n\nPassons à présent à la reformulation de ce modèle en transformant l'effet fixe de la classe en effet aléatoire.\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\upsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon}) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm2}\n\nRemarquez que l'effet fixe de la classe $\\sum^k_{j=1}{\\beta_j x_{2j}}$ a été remplacé par $\\upsilon$ qui est un terme aléatoire propre aux classes et qui suit une distribution normale centrée sur 0 ($\\upsilon \\sim Normal(0, \\sigma_{\\upsilon})$). En d’autres termes, cela signifie que l'effet des classes sur la performance des élèves suit une distribution normale et que si nous moyennons l'effet de toutes les classes, cet effet serait de 0. Nous ne modélisons donc plus l'effet moyen de chaque classe comme dans le modèle à effets fixes, mais la variabilité de l'effet des classes, soit $\\sigma_{\\upsilon}$. Notre modèle a donc deux variances, une au niveau des élèves ($\\sigma_e$) et une au niveau des classes ($\\sigma_{\\upsilon}$). Cette particularité explique souvent pourquoi ce type de modèle est appelé un modèle hiérarchique ou un modèle de partition de la variance. Cette information est particulièrement intéressante, car elle permet de calculer la part de la variance présente au niveau des élèves et celle au niveau des classes.\n\nSelon cette formulation, les constantes propres à chaque classe sont issues d'une distribution normale (nous reviendrons d'ailleurs sur ce choix plus tard), mais elles n'apparaissent pas directement dans le modèle. Ces paramètres ne sont plus estimés directement dans le modèle, mais a posteriori à partir des prédictions du modèle, et sont appelés *Best Linear Unbiased Predictor* (*BLUP*). Ces dernières précisions devraient d'ailleurs mieux vous aider à comprendre l'origine des définitions 1, 2 et 4 que nous avons mentionnées précédemment.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Influence du temps de travail sur la performance scolaire d'élèves en tenant compte de l'effet de leur classe (effet aléatoire)](09-GLMM_files/figure-html/fig-randominter3-1.png){#fig-randominter3 fig-align='center' width=70%}\n:::\n:::\n\n\nEn comparant les figures [-@fig-randominter2] et [-@fig-randominter3], la différence ne saute pas aux yeux; vous pourriez alors légitimement vous demander pourquoi tous ces efforts et cette complexité théorique pour une différence d'ajustement minime? Trois arguments permettent de justifier l'utilisation de constantes aléatoires plutôt que d'effets fixes dans notre cas.\n\n#### Resserrement (*shrinkage*) et mutualisation (*partial pooling*) {#sec-09221}\n\nLe premier intérêt d'utiliser un effet aléatoire réside dans sa méthode d'estimation qui diffère largement d'un effet fixe. Il est assez facile de se représenter intuitivement la différence entre les deux. Dans le cas de nos élèves et de nos classes, lorsque l'effet des classes est estimé avec un effet fixe, l'effet de chaque classe est déterminé de façon totalement indépendante des autres classes. En d'autres termes, il n'est possible d'en apprendre plus sur une classe qu'en collectant des données dans cette classe (*separate pooling*). Si l'effet des classes est estimé comme un effet aléatoire, alors l'information entre les classes est mutualisée (*partial pooling*). L'idée étant que l'information que nous apprenons sur des élèves dans une classe est au moins en partie valide dans les autres classes. Cette méthode d'estimation est particulièrement intéressante si nous ne disposons que de peu d'observations dans certaines classes, puisque nous pouvons apprendre au moins une partie de l'effet de cette classe à partir des données des autres classes. Cela n'est pas possible dans le cas d'un effet fixe où l'on traite chaque classe en silo. @mcelreath2020statistical écrit à ce sujet qu'un effet fixe « n'a pas de mémoire » et qu'il oublie tout ce qu'il a appris sur les classes lorsqu'il passe à une nouvelle classe. La conséquence de cette mutualisation de l'information est un resserrement (*shrinkage*) des effets des classes autour de leur moyenne. Cela signifie que les tailles des effets de chaque classe sont plus petites dans le cas d'un effet aléatoire que d'un effet fixe. Utiliser des effets aléatoires conduit donc à une estimation plus conservatrice de l'effet des classes. Nous pouvons le visualiser en comparant les effets de classes dans le modèle à effets mixtes et le modèle à effets fixes. La @fig-randominter5 montre clairement que les effets aléatoires tendent à se rapprocher (resserrement) de leur moyenne (ligne noire), et donc à identifier des effets moins extrêmes pour chaque classe. Cette explication est directement en lien avec la définition 5 d'un effet aléatoire vu précédemment.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Comparaison des effets des classes pour le modèle à effets fixes versus le modèle à effets aléatoires](09-GLMM_files/figure-html/fig-randominter5-1.png){#fig-randominter5 fig-align='center' width=70%}\n:::\n:::\n\n\n#### Prédiction pour de nouveaux groupes {#sec-09222}\n\nUne autre retombée directe de la mutualisation de l'information est la capacité du modèle à envisager les effets plausibles pour de nouvelles classes. En effet, puisque nous avons approximé l'effet des classes sous forme d'une distribution normale dont nous connaissons la moyenne (0) et l'écart-type ($\\sigma_{\\upsilon}$), nous pouvons **simuler** des données pour de nouvelles classes, ce que ne permet pas un effet fixe. Ce constat est d'ailleurs directement lié à la définition 3 des effets aléatoires vue précédemment. Dans notre cas, $\\sigma_{\\upsilon}$ = 3,542, ce qui nous permet d'affirmer que dans 95 % des classes, l'effet de la classe sur la performance scolaire doit se trouver entre -1,96 $\\times$ 3,542 et +1,96 $\\times$ 3,542, soit l'intervalle [-6,942, 6,942].\n\n#### Partition de la variance {#sec-09223}\n\nUn autre avantage net de l'effet aléatoire est l'estimation du paramètre $\\sigma_{\\upsilon}$, soit la variance au niveau des écoles. Ce dernier permet de calculer un indicateur très intéressant, soit le **coefficient de corrélation intraclasse (ICC)** :\n\n$$\nICC = \\frac{\\sigma_{\\upsilon}}{\\sigma_{\\upsilon} + \\sigma_{e}}\n$$ {#eq-glmm3}\n\nIl s'agit donc du pourcentage de la variance présente au niveau des classes, qui peut être interprétée comme le niveau de corrélation (de ressemblance) entre les élèves d'une même classe.\n\nDans notre cas, l'écart-type est de 3,542 au niveau des classes et de 7,734 au niveau des élèves. Nous pouvons donc calculer l'ICC au niveau des classes avec la formule précédente : 3,542 / (3,542 + 7,734) = 0,314. Cela signifie que le niveau de corrélation entre deux élèves d'une même classe est de 0,314 ou encore que 31,4 % de la variance de *Y* se situe au niveau des classes, ce qui est conséquent. Une telle information ne peut être extraite d'un modèle avec uniquement des effets fixes. Notez ici que l'ICC peut être calculé pour chaque niveau d'un modèle à effet mixte. Dans notre exemple, nous n'avons qu'un seul niveau au-dessus des élèves, soit les classes, mais nous pourrions étendre cette logique à des écoles, par exemple. Notez également que cette formule de l'ICC n'est valide que pour un modèle pour lequel la distribution de la variable *Y* est normale. Des développements apparaissent pour proposer d'autres formulations adaptées à d'autres distributions, mais il est également possible d'estimer l'ICC à partir des simulations issues du modèle [@NakagawaICC; @aly2014reliability; @stryhn2006interpretation; @wu2012comparison]. L'idée générale reste d'expliquer la partition de la variance dans le modèle.\n\nEn plus de l'ICC, il est également possible de calculer les **R^2^ marginal et conditionnel** du modèle. Le premier représente la variance expliquée par le modèle si seulement les effets fixes sont pris en compte, et le second si les effets fixes et aléatoires sont pris en compte. Distinguer les deux sources d'information permet de mieux cerner l'importance du rôle des écoles dans la performance des élèves. Dans notre cas, nous obtenons un R^2^ marginal de 0,115 et un R^2^ conditionnel de 0,269, ce qui nous confirme à nouveau que le rôle joué par la classe dans le niveau de performance est loin d'être négligeable.\n\n### GLMM avec pentes aléatoires {#sec-0923}\n\nDans cette seconde version du GLMM, nous n'envisageons plus de faire varier une constante en fonction des classes, mais un coefficient en fonction des classes. Admettons que nous voulons tester ici si l’effet du temps de travail ($x_1$) sur la performance scolaire (*Y*) n'est pas constant partout. En d'autres termes, nous supposons que, dans certaines classes, le temps de travail hebdomadaire en dehors de l’école est plus ou moins efficace que d’autres classes. L'idée sous-jacente est que nous n'observons pas de différence en termes de moyenne entre deux classes, mais en termes d'effet pour notre variable $x_1$. À nouveau, nous pouvons nous contenter d'un effet fixe pour intégrer cette idée dans notre modèle. Pour cela, nous avons simplement à ajouter une interaction entre notre variable quantitative *temps de travail* et notre variable qualitative *classe*. Nous obtenons le résultat décrit par la @fig-randomslope. Notez ici que la constante est bien la même pour chaque classe (les lignes s'intersectent à 0 sur l'axe des x), et que seule la pente change.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Influence du temps de travail sur la performance scolaire d'élèves en interaction avec la classe (effet fixe)](09-GLMM_files/figure-html/fig-randomslope-1.png){#fig-randomslope fig-align='center' width=70%}\n:::\n:::\n\n\nLa formulation de ce modèle à effets fixes seulement est la suivante : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\sum^k_{j=1}{\\beta_j x_{2j} x_1}\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm4}\n\n\nNous constatons donc que nous avons un effet principal $\\beta_1$ décrivant le lien entre le temps de travail et la note obtenue à l'examen pour l'ensemble des élèves, ainsi qu'un bonus ou un malus sur cet effet $\\beta_j$ s'appliquant en fonction de la classe. Nous pouvons reformuler ce modèle pour inclure cet effet spécifique par classe comme un effet aléatoire :\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\upsilon x_1 \\\\\n&\\upsilon \\sim Normal(0,\\sigma_{\\upsilon})\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm5}\n\nNous formulons ici un modèle dans lequel la classe modifie l'effet de la variable *temps d'étude* sur la variable *note à l'examen*. L'effet moyen de $x_1$ (propre aux individus) est capté par le coefficient $\\beta_1$, les bonus ou malus ajoutés à cet effet par la classe sont issus d'une distribution normale centrée sur 0 avec un écart-type, soit $\\sigma_{\\upsilon}$. À nouveau, l'idée est que si nous moyennons l'effet de toutes les classes, nous obtenons 0. Aussi, le fait de modéliser cet effet comme un effet aléatoire nous permet de partitionner la variance, de mutualiser l'information entre les classes et de resserrer l'estimation des effets des classes.\n\nLes résultats pour ce second modèle sont présentés à la @fig-randomslope2, et une comparaison entre les estimations des effets fixes et des effets aléatoires est présentée à la @fig-randomslope3. Nous pouvons ainsi constater à nouveau l'effet de resserrement provoqué par l'effet aléatoire.\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Influence du temps de travail sur la réussite scolaire d'élèves en interaction avec la classe (effet aléatoire)](09-GLMM_files/figure-html/fig-randomslope2-1.png){#fig-randomslope2 fig-align='center' width=70%}\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Influence du temps de travail sur la réussite scolaire d'élèves en interaction avec la classe (effet aléatoire)](09-GLMM_files/figure-html/fig-randomslope3-1.png){#fig-randomslope3 fig-align='center' width=70%}\n:::\n:::\n\n\nLorsque nous intégrons des pentes aléatoires dans un modèle, nous faisons face au problème suivant : la variance associée aux pentes aléatoires n'est pas fixe, mais proportionnelle à la variable *X* autorisée à varier. Si nous comparons la @fig-randominter3 (constantes aléatoires) et la @fig-randomslope2 (pentes aléatoires), nous constatons bien que la dispersion des prédictions du modèle (représentées par les lignes) augmente dans le cas de pentes aléatoires et reste identique dans le cas des constantes aléatoires. La conséquence pratique est qu'il existe un nombre infini de valeurs possibles pour l'ICC. Dans ce contexte, il est préférable de laisser de côté cet indicateur et de ne reporter que les R^2^ marginal et conditionnel. Dans notre cas, nous obtenons les valeurs 0,109 et 0,258, ce qui confirme une fois encore que le rôle joué par la classe est loin d'être négligeable.\n\n### GLMM avec constantes et pentes aléatoires {#sec-0924}\n\nVous l'aurez certainement deviné en lisant le titre de cette section : il est tout à fait possible de combiner à la fois des constantes et des pentes aléatoires dans un modèle. Cela augmente bien sûr la complexité du modèle et introduit quelques subtilités comme la notion de distribution normale multivariée, mais chaque chose en son temps.\n\nSi nous reprenons notre exemple avec nos élèves et nos classes, combiner à la fois des constantes et des pentes aléatoires revient à formuler l'hypothèse que chaque classe a un effet sur la moyenne de la performance de ses élèves, mais également un effet sur l'efficacité du temps de travail. Il est possible de créer un modèle avec uniquement des effets fixes tenant compte de ces deux aspects en ajoutant dans le modèle la variable multinomiale *classe* ainsi que son interaction avec la variable *temps de travail*. La formulation de ce modèle à effets fixes est la suivante :\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\sum^k_{j=1}{\\beta_{2j} x_{2j} + \\beta_{3j} x_{2j} x_1}\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm6}\n\nNous pouvons représenter les résultats de ce modèle avec la @fig-fullrandom1.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Influence du temps de travail sur la performance scolaire d'élèves en tenant compte de l'effet de leur classe et de l'effet de la classe sur l'efficacité du temps de travail (effet fixe)](09-GLMM_files/figure-html/fig-fullrandom1-1.png){#fig-fullrandom1 fig-align='center' width=70%}\n:::\n:::\n\n\nNous reformulons à présent ce modèle pour intégrer l'effet moyen de chaque classe (constante) et l'effet des classes sur l'efficacité du temps de travail (pente) comme deux effets aléatoires : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\upsilon_1 + (\\beta_1 + \\upsilon_2) x_1\\\\\n&\\left(\\begin{array}{l}\n\\upsilon_{1} \\\\\n\\upsilon_{2}\n\\end{array}\\right) \\sim \\mathcal{N}\\left(\\left(\\begin{array}{l}\n0 \\\\\n0\n\\end{array}\\right),\\left(\\begin{array}{cc}\n\\sigma_{\\upsilon_1} & \\sigma_{\\upsilon_1\\upsilon_2} \\\\\n \\sigma_{\\upsilon_1\\upsilon_2} & \\sigma_{\\upsilon_1}\n\\end{array}\\right)\\right) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm7}\n\nPas de panique! Cette écriture peut être interprétée de la façon suivante :\n\nLe modèle a deux effets aléatoires, l'un faisant varier la constante en fonction de la classe ($\\upsilon_1$) et l'autre l'effet de la classe sur l'efficacité du temps de travail ($\\upsilon_2$). Ces deux effets sont issus d'une distribution normale bivariée (une dimension par effet aléatoire). Cette distribution normale bivariée a donc deux moyennes et ces deux moyennes sont à 0 (les effets s'annulent si nous considérons toutes les classes ensemble). Elle dispose également d'une variance par effet aléatoire ($\\sigma_{\\upsilon_1}$ et $\\sigma_{\\upsilon_2}$) et d'une covariance entre les deux effets aléatoires ($\\sigma_{\\upsilon_1\\upsilon_2}$). Cette covariance permet de tenir compte du fait que, potentiellement, les classes avec une constante plus élevée pourraient systématiquement avoir une efficacité du temps de travail plus faible ou plus élevée. Cette formulation implique donc d'ajuster trois paramètres de variance : $\\sigma_{\\upsilon_1}$, $\\sigma_{\\upsilon_2}$ et $\\sigma_{\\upsilon_1\\upsilon_2}$. Il peut arriver que nous n'ayons pas assez de données pour estimer ces trois paramètres, ou que nous décidions, pour des raisons théoriques, qu'aucune corrélation ne soit attendue entre $\\sigma_{\\upsilon_1}$ et $\\sigma_{\\upsilon_2}$. Dans ce cas, il est possible de fixer $\\sigma_{\\upsilon_1\\upsilon_2}$ à 0, ce qui revient à indiquer au modèle que $\\upsilon_1$ et $\\upsilon_2$ proviennent de deux distributions normales distinctes, nous pouvons donc écrire :\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\upsilon_1 + (\\beta_1 + \\upsilon_2) x_1\\\\\n&\\left(\\begin{array}{l}\n\\upsilon_{1} \\\\\n\\upsilon_{2}\n\\end{array}\\right) \\sim \\mathcal{N}\\left(\\left(\\begin{array}{l}\n0 \\\\\n0\n\\end{array}\\right),\\left(\\begin{array}{cc}\n\\sigma_{\\upsilon_1} & 0 \\\\\n 0 & \\sigma_{\\upsilon_1}\n\\end{array}\\right)\\right) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm8}\n\nCe qui est identique à : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\upsilon_1 + (\\beta_1 + \\upsilon_2) x_1\\\\\n&\\upsilon_{1} \\sim Normal(0,\\sigma_{\\upsilon_1}) \\\\\n&\\upsilon_{2} \\sim Normal(0,\\sigma_{\\upsilon_2}) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm9}\n\nNous avons déjà abordé la notion de covariance dans la [section @sec-042]. Pour rappel, la covariance dépend de l'unité de base des deux variables sur laquelle elle est calculée. Ici, il s'agit d'un coefficient et d'une constante. Il est donc préférable de la standardiser pour obtenir la corrélation entre les deux effets : \n\n$$\ncorr(\\upsilon_1;\\upsilon_2) = \\frac{\\sigma_{\\upsilon_1\\upsilon_2}}{\\sqrt{\\sigma_{\\upsilon_1}}\\sqrt{\\sigma_{\\upsilon_2}}}\n$$ {#eq-glmm10}\n\nSi cette corrélation est positive, cela signifie que les classes ayant tendance à avoir un effet positif sur la performance scolaire ont également tendance à influencer positivement l'efficacité du temps de travail. À l'inverse, une corrélation négative signifie que l'efficacité du temps de travail a tendance à être plus faible dans les classes où la performance scolaire moyenne est élevée. Si la corrélation n'est pas significative, c'est que les deux effets sont indépendants l'un de l'autre.\n\nPour cet exemple, nous conservons la première formulation afin de montrer comment interpréter $\\sigma_{\\upsilon_1\\upsilon_2}$, mais nous ne disposons probablement pas de suffisamment de classes différentes pour estimer correctement ces trois paramètres. Les résultats de ce modèle sont représentés à la @fig-fullrandom2.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Influence du temps de travail sur la performance scolaire d'élèves en tenant compte de l'effet de leur classe et de l'effet de la classe sur l'efficacité du temps de travail (effet aléatoire)](09-GLMM_files/figure-html/fig-fullrandom2-1.png){#fig-fullrandom2 fig-align='center' width=70%}\n:::\n:::\n\n\nNous pouvons ainsi constater que pour ce troisième modèle, l'effet de resserrement est bien plus prononcé que pour les modèles précédents (@fig-fullrandom3). Si nous nous fions au modèle à effets fixes (@fig-fullrandom1)), alors l'effet de l'école sur l'efficacité du temps de travail est très important. En revanche, le modèle à effet aléatoire identifie que la différence de moyenne entre les écoles est importante, mais la différence en termes d'efficacité du temps de travail est beaucoup plus anecdotique.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Comparaison des effets fixes et aléatoires pour le modèle intégrant l'effet des classes et l'interaction entre les classes et le temps de travail](09-GLMM_files/figure-html/fig-fullrandom3-1.png){#fig-fullrandom3 fig-align='center' width=90%}\n:::\n:::\n\n\nNotre modèle estime les valeurs de $\\sigma_{\\upsilon_1}$ à 8,563, de $\\sigma_{\\upsilon_2}$ à 0,042 et de $\\sigma_{\\upsilon_1\\upsilon_2}$ à 0,073. La corrélation entre les deux effets est donc de 0,122, ce qui est relativement faible (pour l'anecdote, notez que la valeur originale de corrélation entre ces deux effets était de 0,1 lorsque nous avons simulé ces données, notre modèle a donc bien été capable de retrouver le paramètre original). À nouveau, puisque nous avons des pentes aléatoires dans ce modèle, nous ne pouvons pas calculer l'ICC; nous pouvons cependant rapporter les R^2^ marginal et conditionnel. Leurs valeurs respectives sont 0,115 et 0,269, ce qui nous confirme une nouvelle fois que l'ajout d'effets aléatoires contribue à expliquer une partie importante de la variance de la performance scolaire.\n\nPour terminer cette section, comparons brièvement les trois modèles (constantes aléatoires, pentes aléatoires, constantes et pentes aléatoires) pour déterminer lequel est le mieux ajusté à nos données. Nous ajoutons également un quatrième modèle dans lequel les deux effets aléatoires sont présents, mais non corrélés ($\\sigma_{\\upsilon_1\\upsilon_2}=0$). Le @tbl-fullrandom4 nous permet de constater que l'ajout des constantes aléatoires joue un rôle essentiel dans le premier modèle : le R^2^ conditionnel est plus que deux fois supérieur au R^2^ marginal. Cependant, l'ajout des pentes aléatoires dans les trois autres modèles apporte finalement très peu d'information, nous laissant penser que l'effet de la classe sur le temps de travail est faible, voire inexistant.\n\n\n\n::: {#tbl-fullrandom4 .cell tbl-cap='Comparaison des trois modèles à effets aléatoires'}\n::: {.cell-output-display}\n|modèle | AIC| R2 marginal| R2 conditionnel|\n|:---------------------------------------------|-------:|-----------:|---------------:|\n|Constantes aléatoires | 2 100,9| 0,12| 0,27|\n|Pentes aléatoires | 2 101,6| 0,11| 0,26|\n|Pentes et constantes aléatoires corrélées | 2 104,7| 0,11| 0,27|\n|Pentes et constantes aléatoires non corrélées | 2 102,7| 0,11| 0,27|\n:::\n:::\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Modèles à effets mixtes avec des structures croisées**\n:::\n::: bloc_aller_loin-body\nJusqu'à présent, nous avons abordé des modèles GLMM comprenant des structures imbriquées (*nested* en anglais), c'est-à-dire qu'une observation d'un niveau 1 est incluse dans un et un seul groupe du niveau 2. Comme structure imbriquée à trois niveaux, nous avons vu comme exemple des élèves intégrés dans des classes elles-mêmes intégrées dans des écoles (@fig-glmmecoles) : un ou une élève appartient à une et une seule classe qui est elle-même localisée dans une et une seule école (élève / classe / école).\n\nNotez qu'il est aussi possible d'avoir des structures des données croisées (*crossed*).\n\nAdmettons à présent que nous ne nous intéressons pas à la classe dans laquelle se situe l'élève, mais plutôt à la personne qui enseigne. Admettons également que ces personnes peuvent donner des cours dans plusieurs écoles. Nous nous retrouvons dans un cas de figure où une personne qui enseigne peut se situer dans plusieurs écoles, ce qui diffère du cas précédent où chaque classe appartient à une seule école. Dans ce second cas, on parle d'une **structure croisée** plutôt qu'imbriquée.\n\nSi les personnes enseignent dans toutes les écoles, il est possible de dire que le design d'étude est croisé complet ou croisé partiel si elles n'enseignent que dans certaines écoles. La @fig-crossednested résume ces trois situations.\n\n\n\n![Différentes structures de données hiérarchiques (imbriquée versus croisée)](images/Chap09/glmm_croise-nested.png){#fig-crossednested width=\"50%\" fig-align=\"center\"}\n\nIl est important de bien saisir la structure de son jeu de données, car l'estimation d'un modèle avec effets imbriqués ou croisés peut donner des résultats parfois significativement différents. De plus, un modèle imbriqué est généralement moins difficile à ajuster qu'un modèle croisé. En effet, dans un modèle imbriqué, deux personnes étudiant dans deux écoles différentes sont jugées indépendantes. Dans un modèle croisé, deux élèves provenant de deux écoles différentes peuvent tout de même partager une dépendance du fait qu'ils ou elles ont pu avoir le même professeur ou la même professeure. La structure de dépendance (et donc de la matrice de covariance des effets aléatoires) est ainsi plus complexe pour un modèle croisé.\n:::\n:::\n\n\n## Conditions d'application des GLMM {#sec-093}\n\nPuisque les GLMM sont une extension des GLM, ils partagent l'essentiel des conditions d'application de ces derniers. Pour simplifier, si vous ajustez un modèle GLMM avec une distribution Gamma, vous devez réaliser les mêmes tests que ceux pour un simple GLM avec une distribution Gamma.\n\nUne question importante se pose souvent lorsque nous ajustons des modèles GLMM : **combien de groupes faut-il au minimum aux différents niveaux?** En effet, pour estimer les différentes variances, nous devons disposer de suffisamment de groupes différents. Dans le cas d'un modèle avec uniquement une constante aléatoire, il est fréquent de lire que nous devons disposer au minimum de cinq groupes différents [@gelman2006data], en dessous de ce minimum, traiter l'effet comme aléatoire plutôt que fixe apporte très peu d'information. De plus, l'estimation des variances pour chaque niveau est très imprécise, donnant potentiellement des valeurs inexactes pour l'ICC et polluant l'interprétation. Avec cinq groupes ou moins, il est certainement plus judicieux d'ajuster seulement un effet fixe. Dans un modèle avec plusieurs effets aléatoires et plusieurs variances / covariances à estimer, ce nombre doit être augmenté proportionnellement, à moins que les effets aléatoires ne soient estimés indépendamment les uns des autres. Notez ici que, si l'enjeu du modèle était d'estimer avec une grande précision les paramètres de variances, il faudrait compter au minimum une centaine de groupes. Il n'est pas nécessaire d'avoir le même nombre d'observations par groupe, car les modèles GLMM partagent l'information entre les groupes. Cependant, dans les groupes avec peu d'observations (inférieur à 15), l'estimation de leur effet propre (BLUP) est très incertaine.\n\nPuisque les GLMM font intervenir la distribution normale aux niveaux supérieurs du modèle, il est nécessaire de vérifier si les hypothèses qu'elle implique sont respectées. Il s'agit essentiellement de deux hypothèses : les effets aléatoires suivent bien une distribution normale (univariée ou multivariée), et la variance au sein des groupes est bien homogène.\n\n### Vérification de la distribution des effets aléatoires {#sec-0931}\n\nReprenons la formulation d'un modèle simple avec seulement deux niveaux et seulement une constante aléatoire:\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\upsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon}) \\\\\n&g(x) = x\n\\end{aligned}\n$$\n\nCe modèle formule l'hypothèse que les constantes aléatoires $\\upsilon$ proviennent d'une distribution normale avec une moyenne de 0 et un écart-type $\\sigma_{\\upsilon}$. La première étape du diagnostic est donc de vérifier si les constantes aléatoires suivent bien une distribution normale, ce que nous pouvons faire habituellement avec un diagramme quantile-quantile. Si nous reprenons notre exemple avec nos données de performance scolaire des sections précédentes, nous obtenons la @fig-diagglmm1. Puisque les points tombent bien approximativement sur la ligne rouge, nous pouvons conclure que cette condition d'application est bien respectée. Notez qu'il est également possible d'utiliser ici un des tests vus dans le [chapitre @sec-chap02] pour tester formellement la distribution des constantes aléatoires, mais nous disposons rarement de suffisamment de valeurs différentes pour qu'un tel test soit pertinent.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution normale univariée des constantes aléatoires](09-GLMM_files/figure-html/fig-diagglmm1-1.png){#fig-diagglmm1 fig-align='center' width=70%}\n:::\n:::\n\n\nCette vérification est bien sûr à appliquer à chacun des niveaux (en dehors du niveau de base) du modèle étudié.\n\nSi nous nous intéressons maintenant au modèle avec constantes et pentes aléatoires, nous avons deux cas de figure:\n\n* Notre modèle inclut une covariance entre les constantes et les pentes; elles proviennent donc d'une distribution normale bivariée.\n\n* Notre modèle considère les pentes et les constantes comme indépendantes; elles proviennent donc de deux distributions normales distinctes.\n\nLe second cas est de loin le plus simple puisqu'il nous suffit de réaliser un graphique de type quantile-quantile pour les deux effets aléatoires séparément. Dans le premier cas, il nous faut adapter notre stratégie pour vérifier si les deux effets aléatoires suivent conjointement une distribution normale multivariée. Pour cela, nous devons, dans un premier temps, observer séparément la distribution des pentes et des constantes, puisque chaque variable provenant d'une distribution normale multivariée suit elle-même une distribution normale univariée [@burdenski2000evaluating]. Nous pouvons, dans un second temps, construire un graphique nous permettant de juger si nos pentes et nos constantes suivent bien la distribution normale bivariée attendue par le modèle. Pour l'illustrer, nous reprenons le modèle sur la performance scolaire intégrant des pentes et des constantes aléatoires avec une covariance estimée entre les deux.\n\nLa @fig-diagglmm2 représente donc les deux graphiques quantile-quantile univariés. Les deux semblent indiquer que nos effets aléatoires suivent bien chacun une distribution normale. La @fig-diagglmm3 montre la distribution normale bivariée attendue par le modèle avec des ellipses représentant différents percentiles de cette distribution. Les valeurs des effets aléatoires sont représentées par des points noirs. Seulement 5 % des points noirs devraient se trouver dans la première ellipse et 95 % des points devraient se trouver dans la quatrième ellipse. En revanche, seulement 20 % des points devraient se trouver dans le dernier anneau et seulement 5 % des points en dehors de cet anneau. Il faut donc évaluer si les points sont plus ou moins centrés que ce que nous attendons. Pour simplifier la lecture, il est possible de rajouter des points grisés en arrière-plan représentant des réalisations possibles de cette distribution normale bivariée. Les vrais points noirs devraient avoir une dispersion similaire à celle des points grisés. Dans notre cas, ils semblent suivre un patron cohérent avec notre distribution normale bivariée. Dans le cas contraire, cela signifierait que le modèle doit être révisé.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Multiples distributions normales univariées des constantes et pentes aléatoires](09-GLMM_files/figure-html/fig-diagglmm2-1.png){#fig-diagglmm2 fig-align='center' width=70%}\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution normale bivariée des constantes et des pentes aléatoires](09-GLMM_files/figure-html/fig-diagglmm3-1.png){#fig-diagglmm3 fig-align='center' width=70%}\n:::\n:::\n\n\n### Homogénéité des variances au sein des groupes {#sec-0932}\n\nDans le [chapitre @sec-chap08] sur les GLM, nous avons vu que chaque distribution a sa propre définition de la variance. Pour rappel, un modèle gaussien assume une variance constante, un modèle de Poisson assume une variance égale à son espérance, alors qu'un modèle Gamma assume une variance proportionnelle au carré de son espérance divisée par un paramètre de forme, etc. Nous devions donc, pour chaque GLM, vérifier graphiquement si la variance présente dans les données originales était proche de la variance attendue par le modèle. Dans un modèle GLMM, le même exercice doit être fait pour chaque groupe aux différents niveaux du modèle. \n\nDans notre exemple sur la performance scolaire, notre variable *Y* a été modélisée avec une distribution normale. Le modèle assume donc une uniformité de sa variance (homoscédasticité). La @fig-glmmvariance nous montre ainsi que, quelle que soit la classe, la dispersion des points (notes des élèves) semble bien respecter la variance attendue par le modèle (représentée par les lignes noires).\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Homogénéité de la variance pour les différents groupes d'un modèle GLMM gaussien](09-GLMM_files/figure-html/fig-glmmvariance-1.png){#fig-glmmvariance fig-align='center' width=95%}\n:::\n:::\n\n\n## Inférence dans les modèles GLMM {#sec-094}\n\nUne des questions importantes à se poser lorsque nous construisons un modèle est toujours : est-ce que les différents effets présents dans le modèle ont un effet significativement différent de zéro sur la variable dépendante? Cette étape d'inférence est plus compliquée pour les modèles GLMM que dans les modèles GLM à cause de la présence d'effets aléatoires. Ces derniers brouillent le comptage du nombre de paramètres et, par extension, du nombre de degrés de liberté des modèles. Pour un effet aléatoire, il est possible de déterminer que le nombre de degrés de liberté est de 1 puisque nous ajustons un seul paramètre supplémentaire (la variance de cet effet aléatoire). Selon un autre point de vue, il serait possible d'affirmer que le nombre de degrés de liberté est de $k - 1$ (avec *k* le nombre de groupes dans cet effet aléatoire), ce que nous utilisons habituellement pour un effet fixe. La vraie valeur du nombre de degrés de liberté se situe quelque part entre ces deux extrêmes. L'enjeu du nombre de degrés de liberté est crucial, car il influence directement l'estimation des valeurs de *p* pour l'ensemble des coefficients du modèle. Avec un nombre de degrés de liberté plus petit, les valeurs de *p* sont plus faibles et les effets plus significatifs. Le sujet est d'ailleurs l'objet d'une telle controverse que les auteurs de certains *packages* comme `lme4` (un des *packages* les plus utilisés pour ajuster des GLMM) ont fait le choix de ne renvoyer aucune valeur de *p* dans les résultats des modèles. L'article de @bolker2009generalized propose une explication détaillée et relativement accessible du problème (en plus d'une excellente introduction aux GLMM) : en se basant sur leurs recommandations, il est possible de séparer le problème de l'inférence dans les GLMM en trois sous problèmes : \n\n* Quel est le degré de significativité des effets fixes?\n* Quel est le degré de significativité de l'effet aléatoire dans le modèle?\n* Quels sont les degrés de significativité de chaque constante / pente aléatoire?\n\n\n### Inférence pour les effets fixes {#sec-0941}\n\nTrois approches peuvent être envisagées pour déterminer si un effet fixe est significatif ou non. Elles font appel à trois approches théoriques différentes (test classique, comparaison de modèles et *bootstrapping*) et peuvent donc donner des résultats différents. À titre exploratoire, il peut être intéressant de toutes les tester, mais certaines peuvent être préférées en fonction de votre champ de recherche.\n\n#### Test classique {#sec-09411}\n\nNous avons vu, pour les modèles LM et GLM, que les valeurs de *p* sont calculées à partir de scores obtenus en divisant les coefficients par leurs erreurs standards. Une approche similaire peut être utilisée pour les modèles GLMM. Cependant, la question du nombre de degrés de liberté à utiliser reste un problème. L'approche la plus flexible est certainement l'approximation par la méthode Satterthwaite proposant une estimation de ce nombre de degrés de liberté et, par extension, des valeurs de *p*.\n\n#### Rapports de vraisemblance {#sec-09412}\n\nSi le modèle comprend suffisamment d'observations (par suffisamment, comprenez au moins une centaine d'observations par paramètre), il est également possible d'utiliser une série de tests de rapports de vraisemblance pour vérifier si l'apport de chaque variable indépendante contribue à améliorer significativement le modèle. Cette approche correspond à une analyse de type 3, comme nous l'avons mentionné dans la [section @sec-0824] pour le modèle logistique multinomial.\n\n#### Bootstrapping {#sec-09413}\n\nL'approche par *bootstrapping* (*parametric-bootstrap* ou *semi-parametric-bootstrap*) permet de calculer, pour les différents paramètres d'un modèle, un intervalle de confiance. L'idée étant de réajuster un grand nombre de fois le modèle sur des sous-échantillons de données pour saisir la variabilité des différents paramètres du modèle. Si les intervalles de confiance ainsi construits ne comprennent pas de zéro, il est possible de dire que cet effet est significatif. À nouveau, cette méthode n'est valide que si le jeu de données comporte suffisamment d'observations. L'intérêt de cette approche est qu'elle ne postule pas d'hypothèse sur la distribution des paramètres qui ont la fâcheuse tendance à ne pas suivre une distribution normale dans le cas des GLMM. Elle est d'ailleurs considérée comme la plus robuste, bien que coûteuse en termes de temps de calcul.\n\n### Inférence pour les effets aléatoires, effet global {#sec-0942}\n\nPour déterminer si un effet aléatoire est significatif dans un modèle, il est recommandé d'utiliser un test de rapport de vraisemblance entre un modèle sans l'effet aléatoire et un modèle avec l'effet aléatoire. L'analyse des différences entre les valeurs de déviance, l'AIC et le BIC peut également aider à déterminer si l'ajout de l'effet aléatoire est justifié. Il est également possible de considérer les valeurs de l'ICC et du R^2^ conditionnel. Notez ici que si vous avez une très bonne raison théorique d'ajouter l'effet aléatoire dans votre modèle et suffisamment d'observations / groupes pour l'ajuster, il peut être pertinent de laisser l'effet aléatoire dans le modèle même si tous les indicateurs mentionnés précédemment indiquent qu'il contribue faiblement au modèle. Le retirer risquerait en effet de donner l'impression que les autres paramètres du modèle sont plus significatifs qu'ils ne le sont en réalité.\n\nNotez que l'approche par *bootstrapping* décrite pour les effets fixes peut aussi être utilisée ici pour obtenir un intervalle de confiance pour l'ICC, le R^2^ conditionnel et les différents paramètres de variance et covariance. \n\n### Inférence pour les effets aléatoires, des constantes et des pentes {#sec-0943}\n\nPour rappel, dans l'approche fréquentiste présentée ici, les valeurs des constantes et des pentes aléatoires ne sont pas à proprement parler des paramètres du modèle : elles sont estimées a posteriori (BLUP). Pour déterminer si ces constantes et des pentes sont significativement différentes de zéro et significativement différentes les unes des autres, il est possible de calculer les intervalles de confiance de chacune d'entre elles par *bootstrap*, par profilage ou par simulation à partir du modèle. Si la constante du groupe *j* a zéro dans son intervalle de confiance, nous pouvons alors déclarer que le groupe *j* en question ne semble pas varier du reste de la population en termes de moyenne. Si la pente *l* du groupe *j* a zéro dans son intervalle de confiance, nous pouvons alors déclarer que le groupe *j* en question ne semble pas varier du reste de la population pour l'effet *l*. Notez que la méthode par simulation est bien plus rapide que les deux autres, mais que l'approche par *bootstrapping* reste la plus fiable.\n\n## Conclusion sur les GLMM {#sec-095}\n\nLes GLMM sont donc une extension des GLM offrant une grande flexibilité de modélisation (variabilité des pentes et des constantes en fonction de groupes) et nous permettant d'analyser la partition de la variance entre plusieurs niveaux de nos données. Cependant, cette flexibilité implique des modèles plus complexes avec un travail de diagnostic et d'interprétation plus long et potentiellement plus ardu.\n\n\n## Mise en œuvre des GLMM dans R {#sec-096}\n\nPour cet exemple de GLMM, nous proposons d'analyser à nouveau les données présentées dans la [section @sec-06211] sur le modèle logistique binomial. Pour rappel, nous modélisions la probabilité qu'un individu utilise le vélo comme mode de transport pour son trajet le plus fréquent en utilisant une enquête réalisée auprès d'environ 26 000 Européens. Initialement, nous avons intégré les pays comme un effet fixe. Or, nous savons à présent qu'il serait plus judicieux de les traiter comme un effet aléatoire. Nous comparons deux modèles, un pour lequel seulement la constante varie par pays et un second dans lequel la pente pour l'âge varie également par pays. L'hypothèse étant que l'effet de l'âge sur l'utilisation du vélo pourrait être réduit dans certains pays où la culture du vélo est plus présente. Cette hypothèse implique également la présence potentielle d'une corrélation inverse entre la constante et la pente de chaque pays : dans un pays où la probabilité de base d'utiliser le vélo est plus élevée, l'effet de l'âge est probablement réduit.\n\nPour ajuster ces modèles, nous utilisons le *package* `lme4`, permettant d'ajuster des modèles GLMM avec des distributions gaussienne, Gamma, de Poisson et binomial. Lorsque d'autres distributions sont nécessaires, il est possible de se tourner vers le *package* `gamlss`. Notez cependant que les effets aléatoires de `gamlss` sont estimés avec une méthode appelée PQL très flexible, mais qui peut produire des résultats erronés dans certains cas [@bolker2009generalized].\n\nAfin de limiter les répétitions, nous ne recalculons pas ici le VIF et nous excluons d'emblée les observations aberrantes (provenant de Malte ou de Chypre ou avec des temps de trajets supérieurs à 400 minutes).\n\n### Ajustement du modèle avec uniquement une constante aléatoire {#sec-0961}\n\nNous commençons donc par ajuster un premier modèle avec une constante aléatoire en fonction du pays. Dans la plupart des *packages* intégrant des effets aléatoires, la syntaxe suivante est utilisée pour stipuler une constante aléatoire : `+ (1|Pays)`. Concrètement, nous tentons d'ajuster le modèle décrit par l'@eq-glmmbinom1.\n\n$$\n\\begin{aligned}\n&Y \\sim Binomial(p)\\\\\n&g(p) = \\beta_0 + \\beta_1 x_1 + \\upsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon}) \\\\\n&g(x) = log(\\frac{x}{1-x})\n\\end{aligned}\n$$ {#eq-glmmbinom1}\n\nIl s'agit simplement d'un modèle logistique binomial dans lequel nous avons ajouté une constante aléatoire : $\\upsilon$. Dans notre cas, elle varie avec la variable `Pays`. La syntaxe dans R pour produire ce modèle est la suivante.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Chargement des données\ndfenquete <- read.csv(\"data/glm/enquete_transport_UE.csv\", encoding = \"UTF-8\")\ndfenquete$Pays <- relevel(as.factor(dfenquete$Pays), ref = \"Allemagne\")\n# Retirer les observations aberrantes\ndfenquete2 <- subset(dfenquete, (dfenquete$Pays %in% c(\"Malte\", \"Chypre\")) == F & \n dfenquete$Duree < 400)\n# Ajustement du modèle\nlibrary(lme4)\n# Nécessité ici de centrer et réduire ces variables pour permettre au modèle de converger\ndfenquete2$Age2 <- scale(dfenquete2$Age, center = TRUE, scale = TRUE)\ndfenquete2$Duree2 <- scale(dfenquete2$Duree, center = TRUE, scale = TRUE)\nmodele1 <- glmer(y ~Sexe + Age2 + Education + StatutEmploi + Revenu +\n Residence + Duree2 + ConsEnv + (1|Pays),\n family = binomial(link=\"logit\"),\n control = glmerControl(optimizer = \"bobyqa\"),\n data = dfenquete2)\n```\n:::\n\n\nNous nous concentrons ici sur l'interprétation des résultats du modèle et nous réalisons l'ensemble des diagnostics dans une section dédiée en fin de chapitre. Notez cependant que le diagnostic **devrait précéder l'interprétation** comme nous l'avons vu dans le chapitre sur les modèles GLM.\n\nVous constaterez que nous avons centré-réduit les variables `Age` et `Duree`. Il est souvent nécessaire de réaliser cette étape en amont pour s'assurer que le modèle converge sans trop de difficulté. Dans notre cas, si ces deux variables sont laissées dans leur échelle d'origine, la fonction `glmer` ne parvient pas à ajuster le modèle. Notez que cette transformation nous permet d'obtenir les coefficients standardisés, s'exprimant alors en écarts-types. La fonction `summary` nous donne accès à un premier ensemble d'informations.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nsummary(modele1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nGeneralized linear mixed model fit by maximum likelihood (Laplace\n Approximation) [glmerMod]\n Family: binomial ( logit )\nFormula: y ~ Sexe + Age2 + Education + StatutEmploi + Revenu + Residence + \n Duree2 + ConsEnv + (1 | Pays)\n Data: dfenquete2\nControl: glmerControl(optimizer = \"bobyqa\")\n\n AIC BIC logLik deviance df.resid \n 19176.1 19322.8 -9570.1 19140.1 25529 \n\nScaled residuals: \n Min 1Q Median 3Q Max \n-1.1989 -0.4418 -0.3212 -0.2134 7.2461 \n\nRandom effects:\n Groups Name Variance Std.Dev.\n Pays (Intercept) 0.5949 0.7713 \nNumber of obs: 25547, groups: Pays, 26\n\nFixed effects:\n Estimate Std. Error z value Pr(>|z|) \n(Intercept) -3.368957 0.212504 -15.854 < 2e-16 ***\nSexehomme 0.370864 0.037921 9.780 < 2e-16 ***\nAge2 -0.102387 0.018776 -5.453 4.95e-08 ***\nEducationsecondaire 0.188098 0.103158 1.823 0.06824 . \nEducationsecondaire inferieur 0.297593 0.111304 2.674 0.00750 ** \nEducationuniversite 0.138671 0.106469 1.302 0.19276 \nStatutEmploisans emploi 0.256477 0.042282 6.066 1.31e-09 ***\nRevenufaible 0.073837 0.071642 1.031 0.30271 \nRevenumoyen 0.039405 0.065232 0.604 0.54579 \nRevenusans reponse 0.215705 0.102286 2.109 0.03496 * \nRevenutres eleve -0.121254 0.185272 -0.654 0.51281 \nRevenutres faible 0.237388 0.085700 2.770 0.00561 ** \nResidencegrande ville 0.272280 0.069276 3.930 8.48e-05 ***\nResidencepetite-moyenne ville 0.276285 0.061492 4.493 7.02e-06 ***\nResidencezone rurale -0.118965 0.069091 -1.722 0.08510 . \nDuree2 -0.018718 0.019241 -0.973 0.33065 \nConsEnv 0.101757 0.009277 10.969 < 2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n```\n:::\n:::\n\n\nLa première partie de ce résumé nous rappelle la formule utilisée pour le modèle et nous indique différents indicateurs de qualité d'ajustement comme l'AIC, le BIC et la déviance. Nous avons ensuite une partie dédiée aux effets aléatoires (`Random Effects`) et une partie dédiée aux effets fixes (`Fixed effects`). Cette dernière s'interprète de la même manière que pour un modèle à effets fixes, n'oubliez cependant pas d'utiliser la fonction exponentielle pour obtenir les rapports de cotes (fonction de lien logistique).\n\n#### Rôle joué par l'effet aléatoire {#sec-09611}\n\nComme vous pouvez le constater, la section `Random Effects` ne comprend qu'un seul paramètre : la variance de l'effet pays. Nous pouvons ainsi écrire que l'effet du pays suit une distribution normale avec une moyenne de 0 et une variance $\\sigma^2$ de 0,595. Pour aller plus loin dans cette analyse, nous pouvons calculer le coefficient de corrélation intraclasse (ICC). Cependant, puisque notre modèle est binomial et non gaussien, nous ne disposons pas d'un paramètre de variance au niveau des individus, il est donc possible, à la place, d'utiliser la variance théorique du modèle : $\\frac{\\pi^2}{3}$. Nous calculons ainsi notre ICC :\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Extraction de la variance des Pays\nvar_pays <- VarCorr(modele1)[[1]][[1]]\n# Calcul de l'ICC\nvar_pays / (((pi**2)/3) + var_pays)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 0.1531364\n```\n:::\n:::\n\n\nNous pouvons parvenir au même résultat en utilisant la fonction `icc` du *package* `performance`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(performance)\n# Calcul de l'ICC\nicc(modele1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# Intraclass Correlation Coefficient\n\n Adjusted ICC: 0.153\n Unadjusted ICC: 0.148\n```\n:::\n:::\n\n\nNotez que cette fonction distingue un ICC ajusté et un ICC conditionnel. Le premier correspond à l'ICC que nous avons présenté jusqu'ici et que nous avons calculé à la main. L'ICC conditionnel inclut dans son estimation la variance présente dans les effets fixes. Un fort écart entre ces deux ICC indique que les effets fixes sont capables de capturer une très forte variance dans les données, ce qui pourrait remettre en cause la pertinence de l'effet aléatoire. Dans notre cas, la différence entre les deux est très faible.\n\nEn plus du ICC, nous pouvons calculer les R^2^ marginal et conditionnel. Pour cela, nous utilisons la fonction `r.squaredGLMM` du *package* `MuMIn`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(MuMIn)\nr.squaredGLMM(modele1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n R2m R2c\ntheoretical 0.03492162 0.18271030\ndelta 0.01554525 0.08133291\n```\n:::\n:::\n\n\nCette fonction nous renvoie à la fois les R^2^ obtenus en utilisant la variance théorique du modèle ($\\frac{\\pi^2}{3}$ dans notre cas) et la variance estimée par la méthode delta. La seconde est plus conservative, mais les deux résultats indiquent que les effets aléatoires expliquent une part importante de la variance comparativement aux effets fixes. Notez également que la fonction `r2` du *package* `performance` peut calculer ces deux R^2^, mais seulement en utilisant la variance théorique.\n\n#### Significativité de l'effet aléatoire {#sec-09612}\n\nNous souhaitons déterminer ici si notre effet aléatoire contribue à significativement améliorer le modèle. Pour cela, nous effectuons un test de rapport de vraisemblance entre le modèle sans l'effet aléatoire (un simple GLM ici) et le modèle complet. Nous utilisons pour cela la fonction `anova` : \n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Ajustement d'un modèle sans l'effet aléatoire\nmodel_simple <- glm(y ~Sexe + Age2 + Education + StatutEmploi + Revenu +\n Residence + Duree2 + ConsEnv,\n family = binomial(link=\"logit\"),\n data = dfenquete2)\n# Comparaison des deux modèles\nanova(modele1, model_simple)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nData: dfenquete2\nModels:\nmodel_simple: y ~ Sexe + Age2 + Education + StatutEmploi + Revenu + Residence + Duree2 + ConsEnv\nmodele1: y ~ Sexe + Age2 + Education + StatutEmploi + Revenu + Residence + Duree2 + ConsEnv + (1 | Pays)\n npar AIC BIC logLik deviance Chisq Df Pr(>Chisq) \nmodel_simple 17 20521 20660 -10243.6 20487 \nmodele1 18 19176 19323 -9570.1 19140 1347 1 < 2.2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n```\n:::\n:::\n\n\nLe test indique clairement que le modèle complet est mieux ajusté : les valeurs de l'AIC, du BIC et de la déviance sont toutes grandement réduites et le test est largement significatif.\n\nPour aller plus loin, nous pouvons utiliser une approche par *bootstrap* pour calculer un intervalle de confiance pour la variance de l'effet aléatoire, l'ICC et le R^2^ conditionnel. Nous utilisons pour cela la fonction `bootMer`. Si vous essayez de lancer cette syntaxe, vous constaterez qu'elle prend énormément de temps, ce qui s'explique par le grand nombre de fois où le modèle doit être réajusté. Nous vous recommandons donc de bien enregistrer vos résultats après l'exécution de la fonction avec la fonction `save.` Notez que pour réduire significativement le temps de calcul, il est possible d'utiliser simultanément plusieurs cœurs de votre processeur, ce que nous faisons ici avec le *package* `snow`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Définition d'une fonction pour extraire les valeurs qui nous intéressent\nextractor <- function(mod){\n vari <- VarCorr(mod)[[1]][[1]]\n ICC <- vari / (vari + (pi**2/3))\n r2cond <- performance::r2(mod)[[1]]\n return(c(\"vari\"=vari,\"icc\"=ICC,\"r2cond\"=r2cond))\n}\n# Préparation d'un environnement multitraitement pour accélérer le calcul\nlibrary(snow)\n# Préparation de huit coeurs (attention si votre machine en a moins!)\ncl <- makeCluster(8)\nclusterEvalQ(cl, library(\"lme4\"))\nvaleurs <- bootMer(modele1, FUN = extractor, nsim = 1000,\n use.u = FALSE, type = \"parametric\", ncpus = 8,\n parallel=\"snow\",\n cl = cl)\n# Sauvegarde des résultats\nsave(valeurs, file = 'data/glmm/boot_binom.rda')\n```\n:::\n\n\nNous pouvons à présent analyser l'incertitude de ces différents paramètres. Pour cela, nous devons commencer par observer graphiquement leurs distributions obtenues par *bootstrap* avec la @fig-bottdistrib.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Chargement de nos valeurs préalablement enregistrées\nload('data/glmm/boot_binom.rda')\n# Construction de trois graphiques de distribution\ndf <- data.frame(valeurs$t)\nnames(df) <- c(\"variance\" , \"icc\" , \"R2cond\")\nbreaks1 <- as.vector(quantile(df$variance, probs = c(0.001,0.15,0.5,0.85, 0.999)))\nlabs1 <- round(breaks1,2)\np1 <- ggplot(df) + \n geom_histogram(aes(x = variance), bins = 50, fill = \"#e63946\", color = \"black\")+\n geom_vline(xintercept = median(df$variance),\n color = \"black\", linetype = \"dashed\", size = 1)+\n scale_x_continuous(breaks = breaks1, labels = labs1)+\n theme(axis.ticks.y = element_blank(),\n axis.text.y = element_blank(), axis.title.y = element_blank())\nbreaks2 <- as.vector(quantile(df$icc, probs = c(0.001,0.15,0.5,0.85, 0.999)))\nlabs2 <- round(breaks2,2)\np2 <- ggplot(df) + \n geom_histogram(aes(x = icc), bins = 50, fill = \"#a8dadc\", color = \"black\")+\n geom_vline(xintercept = median(df$icc),\n color = \"black\", linetype = \"dashed\", size = 1)+\n scale_x_continuous(breaks = breaks2, labels = labs2)+\n theme(axis.ticks.y = element_blank(),\n axis.text.y = element_blank(), axis.title.y = element_blank())\nbreaks3 <- as.vector(quantile(df$R2cond, probs = c(0.001,0.15,0.5,0.85, 0.999)))\nlabs3 <- round(breaks3,3)\np3 <- ggplot(df) + \n geom_histogram(aes(x = R2cond), bins = 50, fill = \"#1d3557\", color = \"black\")+\n geom_vline(xintercept = median(df$R2cond),\n color = \"black\", linetype = \"dashed\", size = 1)+\n scale_x_continuous(breaks = breaks3, labels = labs3)+\n theme(axis.ticks.y = element_blank(),\n axis.text.y = element_blank(), axis.title.y = element_blank())\nggarrange(p1, p2, p3, nrow = 2, ncol = 2)\n```\n\n::: {.cell-output-display}\n![Distributions obtenues par bootstrap de la variance de l'effet aléatoire, de l'ICC et du R carré conditionnel](09-GLMM_files/figure-html/fig-bottdistrib-1.png){#fig-bottdistrib fig-align='center' width=80%}\n:::\n:::\n\n\nLes trois distributions sont toutes suffisamment éloignées de zéro pour que nous puissions en conclure que ces différentes valeurs sont toutes différentes de zéro. Notez également que les distributions sont relativement symétriques, indiquant que nous disposons de probablement suffisamment d'information dans nos données pour inclure notre effet aléatoire. Des distributions fortement asymétriques indiqueraient, au contraire, une forte difficulté du modèle à estimer le paramètre de variance à partir des données. Dans un article, il n'est pas nécessaire de reporter ces graphiques, mais plus simplement les intervalles de confiance à 95 % et les médianes.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Intervalle de confiance pour la variance\nquantile(df$variance, probs = c(0.0275,0.5,0.975))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 2.75% 50% 97.5% \n0.3059400 0.5578986 0.9200472 \n```\n:::\n\n```{.r .cell-code}\n# Intervalle de confiance pour l'ICC\nquantile(df$icc, probs = c(0.0275,0.5,0.975))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 2.75% 50% 97.5% \n0.0850824 0.1449928 0.2185428 \n```\n:::\n\n```{.r .cell-code}\n# Intervalle de confiance pour le R2 conditionnel\nquantile(df$R2cond, probs = c(0.0275,0.5,0.975))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n 2.75% 50% 97.5% \n0.1208577 0.1772778 0.2462622 \n```\n:::\n:::\n\n \n\n#### Significativité des différentes constantes {#sec-09613}\n\nPuisque nous avons conclu que l'effet aléatoire contribue significativement au modèle, nous pouvons à présent vérifier si les constantes ajustées pour chaque pays varient significativement les unes des autres. Pour rappel, les pentes et les constantes aléatoires ne sont pas directement estimées par le modèle, mais a posteriori. Il en résulte qu'il n'y a pas de moyen direct de mesurer l'incertitude de ces paramètres, et donc de construire des intervalles de confiance. Une première option pour contourner ce problème est d'effectuer des simulations à partir de la distribution postérieure du modèle. Notez que cette approche s'inspire largement de l'approche statistique bayésienne. Nous utilisons ici le *package* `merTools` pour effectuer 1000 simulations et obtenir une erreur standard pour chaque constante aléatoire de chaque pays.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Simulations et extraction des effets aléatoires\nlibrary(merTools)\nlibrary(dplyr)\nsimsRE <- REsim(modele1, n.sims = 1000, oddsRatio = FALSE)\n# Calcul des intervalles de confiance\nsimsRE$lower <- simsRE$mean - 1.96 * simsRE$sd\nsimsRE$upper <- simsRE$mean + 1.96 * simsRE$sd\n# Variable binaire pour la significativité\nsimsRE$sign <- case_when(\n simsRE$lower<0 & simsRE$upper<0 ~ \"inf\",\n simsRE$lower>0 & simsRE$upper>0 ~ \"sup\",\n TRUE ~ \"not\"\n)\n# Représentation des intervalles de confiance\nggplot(simsRE) + \n geom_errorbarh(aes(xmin = lower, xmax = upper,\n y = reorder(groupID, mean)), size = 0.5, height = 0.5) + \n geom_point(aes(x = mean, y = reorder(groupID, mean),\n color = sign)) + \n scale_color_manual(values = c(\"inf\" = \"#0077b6\", \"sup\" = \"#e63946\", \"not\"=\"#000000\"), \n labels = c(\"sign. < 0\", \"sign. > 0\", \"non sign.\")) +\n labs(x = \"Constante aléatoire\", y = \"Pays\")\n```\n\n::: {.cell-output-display}\n![Constantes aléatoires estimées par Pays (IC par simulations)](09-GLMM_files/figure-html/fig-randomconstantes1-1.png){#fig-randomconstantes1 fig-align='center' width=70%}\n:::\n:::\n\n\nLa @fig-randomconstantes1 permet de repérer en un coup d'oeil les pays pour lesquels la probabilité d'utiliser le vélo comme moyen de transport pour le trajet le plus fréquent est la plus élevée ou la plus faible. Notez cependant que les valeurs représentées sont pour l'instant des logarithmes de rapport de cotes. Nous devons donc les convertir en rapports de cotes avec la fonction exponentielle pour faciliter leur interprétation.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Conversion en rapports de cote (et arrondissement à trois décimales)\nmat <- round(exp(simsRE[c(\"mean\" , \"lower\" , \"upper\")]),3)\nrownames(mat) <- simsRE$groupID\nnames(mat) <- c(\"RC\" , \"RC.025\" , \"RC.975\")\nprint(mat)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n RC RC.025 RC.975\nAllemagne 1.667 1.191 2.333\nAutriche 1.311 0.927 1.853\nBelgique 1.428 1.022 1.997\nBulgarie 0.541 0.374 0.784\nCroatie 1.880 1.354 2.610\nDanemark 4.043 2.926 5.587\nEspagne 0.292 0.194 0.439\nEstonie 1.121 0.787 1.598\nFinlande 2.242 1.621 3.102\nFrance 0.523 0.357 0.766\nGrande Bretagne 0.396 0.269 0.583\nGrèce 0.615 0.422 0.897\nHongrie 2.359 1.700 3.273\nIreland 0.377 0.254 0.558\nItalie 0.805 0.575 1.126\nLettonie 1.270 0.901 1.790\nLituanie 0.902 0.632 1.287\nLuxembourg 0.419 0.262 0.670\nPays-Bas 3.939 2.873 5.400\nPologne 1.658 1.189 2.311\nPortugal 0.218 0.139 0.340\nRoumanie 0.542 0.376 0.781\nSlovaquie 1.029 0.727 1.455\nSlovénie 1.363 0.969 1.916\nSuède 2.166 1.555 3.018\nTchéquie 1.172 0.837 1.641\n```\n:::\n:::\n\n\nNous observons ainsi qu'une personne vivant en Finlande voit ses chances multipliées par 2,25 d'utiliser le vélo comme mode de transport pour son trajet le plus fréquent comparativement à la moyenne des pays européens. À l'inverse, une personne résidant en France a 47 % de chances de moins d'utiliser le vélo.\n\nNotez cependant que cette approche basée sur des simulations peut poser des problèmes, car elle ne renvoie qu'une erreur standard pour mesurer l'incertitude de nos constantes. Dans les cas où nous ne disposons pas de beaucoup d'observations par groupe, la distribution a posteriori des constantes peut être asymétrique, rendant l'estimation des intervalles de confiance par les erreurs standards inutiles. Il est possible de détecter ce cas de figure quand les médianes et les moyennes renvoyées par la fonction `simsRE` diffèrent nettement. Une alternative plus robuste est à nouveau d'estimer la variabilité des effets aléatoires par *bootstrap*. Cette méthode requiert bien plus de temps de calcul que la précédente, nous vous recommandons donc de commencer par la méthode par simulations pour disposer d'un premier aperçu des résultats et d'utiliser ensuite la méthode *bootstrap* quand votre modèle est dans sa forme finale.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Création de la fonction d'extraction\nextractor2 <- function(mod){\n elements <- ranef(mod)$Pays\n vec <- elements[,1]\n names(vec) <- rownames(elements)\n return(vec)\n}\n# Préparation de l'opération en multitraitement\ncl <- makeCluster(8)\nclusterEvalQ(cl, library(\"lme4\"))\n# Calcul des effets aléatoires en bootstrap\nvaleurs <- bootMer(modele1, FUN = extractor2, nsim = 1000,\n use.u = T, type = \"parametric\", ncpus = 8,\n parallel=\"snow\",\n cl = cl)\n# Sauvegarder des résultats!\nsave(valeurs, file = 'data/glmm/boot_binom2.rda')\n```\n:::\n\n\nPuisque nous disposons des distributions *bootstrapées* des différents effets aléatoires, nous pouvons directement les représenter dans un graphique (@fig-randomconstantes2). Les résultats sont très similaires à ceux de la @fig-randomconstantes1, ce qui s'explique par le grand nombre d'observations et de groupes. Avec moins d'observations, il est recommandé de privilégier l'approche par *bootstrap*.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Chargement de nos valeurs bootstrapées\nload('data/glmm/boot_binom2.rda')\n# Conversion des bootstraps en intervalle de confiance\nq025 <- function(x){return(quantile(x, probs = 0.025))}\nq975 <- function(x){return(quantile(x, probs = 0.975))}\ndf <- reshape2::melt(valeurs$t)\ndf_med <- df %>% group_by(Var2) %>% summarise(\n med = median(value),\n lower = q025(value),\n upper = q975(value))\n# Ajout d'une variable pour la couleur si significatif\ndf_med$sign <- case_when(\n df_med$lower<0 & df_med$upper<0 ~ \"inf\",\n df_med$lower>0 & df_med$upper>0 ~ \"sup\",\n TRUE ~ \"not\"\n)\n# Affichage des résultats\nggplot(df_med) + \n geom_errorbar(aes(xmin = lower, xmax = upper, y = reorder(Var2, med)), width = 0.5) +\n geom_point(aes(x = med, y = reorder(Var2, med), color = sign)) + \n scale_color_manual(values = c(\"inf\" = \"#0077b6\", \"sup\" = \"#e63946\", \"not\"=\"#000000\"), \n labels = c(\"sign. < 0\", \"sign. > 0\", \"non sign.\")) +\n labs(x = \"Constante aléatoire\", y = \"Pays\")\n```\n\n::: {.cell-output-display}\n![Constantes aléatoires estimées par Pays (IC par bootstrap)](09-GLMM_files/figure-html/fig-randomconstantes2-1.png){#fig-randomconstantes2 fig-align='center' width=70%}\n:::\n:::\n\n\n### Ajustement du modèle avec constantes et pentes aléatoires {#sec-0962}\n\nDans le modèle précédent, nous avons ajusté, pour chaque pays, une constante aléatoire afin de vérifier si la probabilité d'utiliser le vélo comme mode de transport principal changeait d'un pays d'Europe à l'autre. Nous souhaitons à présent tester l'hypothèse que l'effet de l'âge sur la probabilité d'utiliser le vélo varie d'un pays à l'autre. Pour cela, nous ajustons des constantes aléatoires par pays. Nous comparons trois modèles, triés ici selon leur niveau de complexité (nombre de paramètres) : \n\n* le modèle avec uniquement des constantes aléatoires;\n* le modèle avec des constantes et des pentes aléatoires indépendantes;\n* le modèle avec des constantes et des pentes aléatoires corrélées.\n\nDans le *package* `lme4`, les syntaxes pour ajuster ces trois modèles sont les suivantes : \n\n* constantes aléatoires : `+(1|Pays)`;\n* constantes et pentes aléatoires indépendantes : `+(1 + Age||Pays)`;\n* constantes et pentes aléatoires corrélées : `+(1 + Age|Pays)`.\n\nNotez qu'il est aussi possible d'ajuster un modèle avec uniquement des pentes aléatoires avec la syntaxe : `+(-1 + Age|Pays)`. Le paramètre `-1` sert à retirer explicitement la constante aléatoire du modèle. Ajustons donc nos deux modèles avec pentes et constantes aléatoires.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Constantes et pentes aléatoires indépendantes\nmodele2 <- glmer(y ~ Sexe + Age2 + Education + StatutEmploi + Revenu +\n Residence + Duree2 + ConsEnv + (1 + Age2||Pays),\n family = binomial(link=\"logit\"),\n control = glmerControl(optimizer = \"bobyqa\"),\n data = dfenquete2)\n# Constantes et pentes aléatoires corrélées\nmodele3 <- glmer(y ~ Sexe + Age2 + Education + StatutEmploi + Revenu +\n Residence + Duree2 + ConsEnv + (1 + Age2|Pays),\n family = binomial(link=\"logit\"),\n control = glmerControl(optimizer = \"bobyqa\"),\n data = dfenquete2)\n```\n:::\n\n\n#### Significativité de l'effet aléatoire {#sec-09621}\n\nPuisque les trois modèles sont imbriqués, la première étape est de vérifier si les ajouts successifs au modèle de base sont significatifs, ce que nous pouvons tester avec un rapport de vraisemblance.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nanova(modele1, modele2, modele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nData: dfenquete2\nModels:\nmodele1: y ~ Sexe + Age2 + Education + StatutEmploi + Revenu + Residence + Duree2 + ConsEnv + (1 | Pays)\nmodele2: y ~ Sexe + Age2 + Education + StatutEmploi + Revenu + Residence + Duree2 + ConsEnv + (1 + Age2 || Pays)\nmodele3: y ~ Sexe + Age2 + Education + StatutEmploi + Revenu + Residence + Duree2 + ConsEnv + (1 + Age2 | Pays)\n npar AIC BIC logLik deviance Chisq Df Pr(>Chisq) \nmodele1 18 19176 19323 -9570.1 19140 \nmodele2 19 19171 19325 -9566.3 19133 7.5754 1 0.005917 **\nmodele3 20 19172 19335 -9566.1 19132 0.4033 1 0.525385 \n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n```\n:::\n:::\n\n\nNous constatons ainsi que l'ajout des pentes aléatoires permet d'améliorer significativement le modèle, mais que l'ajout de la corrélation entre les pentes et les constantes aléatoires a un apport très marginal. Nous décidons tout de même de le garder dans un premier temps, car ce paramètre a un intérêt théorique. Affichons le résumé du modèle 3.\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nsummary(modele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nGeneralized linear mixed model fit by maximum likelihood (Laplace\n Approximation) [glmerMod]\n Family: binomial ( logit )\nFormula: y ~ Sexe + Age2 + Education + StatutEmploi + Revenu + Residence + \n Duree2 + ConsEnv + (1 + Age2 | Pays)\n Data: dfenquete2\nControl: glmerControl(optimizer = \"bobyqa\")\n\n AIC BIC logLik deviance df.resid \n 19172.2 19335.1 -9566.1 19132.2 25527 \n\nScaled residuals: \n Min 1Q Median 3Q Max \n-1.2087 -0.4392 -0.3218 -0.2137 7.1677 \n\nRandom effects:\n Groups Name Variance Std.Dev. Corr \n Pays (Intercept) 0.594976 0.77135 \n Age2 0.007326 0.08559 -0.22\nNumber of obs: 25547, groups: Pays, 26\n\nFixed effects:\n Estimate Std. Error z value Pr(>|z|) \n(Intercept) -3.35793 0.21306 -15.760 < 2e-16 ***\nSexehomme 0.37289 0.03796 9.823 < 2e-16 ***\nAge2 -0.08775 0.02780 -3.157 0.001594 ** \nEducationsecondaire 0.17963 0.10382 1.730 0.083597 . \nEducationsecondaire inferieur 0.28700 0.11189 2.565 0.010315 * \nEducationuniversite 0.13012 0.10713 1.215 0.224510 \nStatutEmploisans emploi 0.25625 0.04251 6.028 1.66e-09 ***\nRevenufaible 0.07058 0.07182 0.983 0.325727 \nRevenumoyen 0.03841 0.06534 0.588 0.556594 \nRevenusans reponse 0.20362 0.10265 1.984 0.047304 * \nRevenutres eleve -0.12420 0.18566 -0.669 0.503528 \nRevenutres faible 0.23562 0.08595 2.741 0.006117 ** \nResidencegrande ville 0.26958 0.06936 3.887 0.000102 ***\nResidencepetite-moyenne ville 0.27570 0.06157 4.478 7.53e-06 ***\nResidencezone rurale -0.11897 0.06917 -1.720 0.085428 . \nDuree2 -0.01889 0.01927 -0.980 0.327069 \nConsEnv 0.10189 0.00929 10.967 < 2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n```\n:::\n:::\n\n::: {.cell}\n\n:::\n\n\nÀ nouveau, nous nous intéressons ici principalement à la section `Random Effect`, puisque les effets fixes s'interprètent exactement comme dans les modèles présentés dans le [chapitre @sec-chap06]. Les constantes ont une variance de 0,595 et les pentes de 0,007. La corrélation entre les deux effets est de -0,22. Cette corrélation est négative et relativement faible, ce qui signifie que les pays dans lesquels la constante est forte tendent à avoir un coefficient plus petit pour l'âge, et donc une réduction accrue de la probabilité d'utiliser le vélo avec l'âge. Nous devons cependant encore nous assurer qu'elle est significativement différente de 0. Pour cela, nous devons calculer l'intervalle de confiance des trois paramètres de variance du modèle. Nous utilisons à nouveau une approche par *bootstrap* et nous enregistrons les résultats.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Fonction d'extraction des trois paramètres de variance\nextractor3 <- function(mod){\n vari1 <- VarCorr(mod)[[1]][[1]]\n vari2 <- VarCorr(mod)[[1]][[4]]\n covari <- VarCorr(mod)[[1]][[2]]\n return(c(\"vari1\"=vari1,\"vari2\"=vari2,\"covari\"=covari))\n}\n# Lancement du bootstrap\nvaleurs <- bootMer(modele3, FUN = extractor3, nsim = 1000,\n use.u = FALSE, type = \"parametric\", ncpus = 8,\n parallel=\"snow\",\n cl = cl,\n .progress=\"txt\", PBarg=list(style=3))\n# Enregistrement des résultats\nsave(valeurs, file = 'data/glmm/boot_binom3.rda')\n```\n:::\n\n\nÀ partir des valeurs *bootstrapées*, nous pouvons représenter les distributions de ces trois paramètres (variance des constantes, variance des pentes et corrélation entre les deux).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Chargement des résultats\nload('data/glmm/boot_binom3.rda')\n# Conversion des valeurs de covariance en corrélation\ndf <- data.frame(\n corr_values = valeurs$t[,3] / (sqrt(valeurs$t[,1]) * sqrt(valeurs$t[,2])),\n vari_const = valeurs$t[,1],\n vari_pente = valeurs$t[,2]\n )\n# Histogramme pour la variance des constantes\nbreaks1 <- quantile(df$vari_const, probs=c(0.025,0.5,0.975,0.999))\nlabel1 <- round(breaks1,3)\np1 <- ggplot(df) + \n geom_histogram(aes(x = vari_const), color = \"black\", fill = \"white\", bins = 30) + \n geom_vline(xintercept = median(df$vari_const), color = \"red\", linetype = 1, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$vari_const, probs = 0.025), \n color = \"blue\", linetype = 0.5, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$vari_const, probs = 0.975), \n color = \"blue\", linetype = 0.5, linetype = \"dashed\") + \n labs(x = \"Variance des constantes\", y = \"\")+ \n scale_x_continuous(breaks = breaks1, labels = label1)\n# Histogramme pour la variance des pentes\nbreaks2 <- quantile(df$vari_pente, probs=c(0.025,0.5,0.975,0.999))\nlabel2 <- round(breaks2,3)\np2 <- ggplot(df) + \n geom_histogram(aes(x = vari_pente), color = \"black\", fill = \"white\", bins = 30) + \n geom_vline(xintercept = median(df$vari_pente), color = \"red\", linetype = 1, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$vari_pente, probs = 0.025), \n color = \"blue\", size = 0.5, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$vari_pente, probs = 0.975), \n color = \"blue\", size = 0.5, linetype = \"dashed\") + \n labs(x = \"Variance des pentes\", y = \"\")+\n scale_x_continuous(breaks = breaks2, labels = label2)\n# Histogramme pour la corrélation\nbreaks3 <- c(-1,-0.5,0,0.5,1, median(df$corr_values))\nlabel3 <- round(breaks3,3)\np3 <- ggplot(df) + \n geom_histogram(aes(x = corr_values), color = \"black\", fill = \"white\", bins = 30) + \n geom_vline(xintercept = median(df$corr_values), color = \"red\", size = 1, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$corr_values, probs = 0.025), \n color = \"blue\", size = 0.5, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$corr_values, probs = 0.975), \n color = \"blue\", size = 0.5, linetype = \"dashed\") + \n labs(x = \"Corrélation pentes/constantes\", y = \"\") + \n scale_x_continuous(breaks = breaks3, labels = label3)\nggarrange(p1, p2, p3, ncol = 2, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Incertitude autour des paramètres de variance obtenue par bootstrap](09-GLMM_files/figure-html/fig-glmmvarboot-1.png){#fig-glmmvarboot fig-align='center' width=95%}\n:::\n:::\n\n\nNous constatons ainsi, à la @fig-glmmvarboot, que la variance des constantes aléatoires est significativement différente de zéro (cette valeur n'est pas dans l'intervalle de confiance à 95 % représenté par les lignes verticales bleues) et une médiane de 0,56 (ligne verticale rouge). Pour les pentes, zéro est également à la limite de l'intervalle de confiance, et la distribution asymétrique et étalée nous indique que ce paramètre est fortement incertain dans le modèle. Enfin, la corrélation entre les pentes et les constantes est de loin le paramètre le plus incertain et son intervalle de confiance est franchement à cheval sur zéro, ce qui devrait nous amener à privilégier un modèle sans ce paramètre.\n\nPour terminer, nous pouvons calculer les R^2^ marginal et conditionnel du modèle afin de mieux cerner le rôle joué par les effets fixes et les effets aléatoires.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nr.squaredGLMM(modele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n R2m R2c\ntheoretical 0.03413723 0.18360167\ndelta 0.01419943 0.07636937\n```\n:::\n:::\n\n\nLes valeurs des R^2^ marginal et conditionnel du modèle sont similaires à celles que nous avons obtenus avec seulement des constantes aléatoires dans la section précédente, signalant l'apport relativement faible des pentes aléatoires.\n\n#### Analyse des effets aléatoires {#sec-09622}\n\nPour analyser facilement les constantes et les pentes aléatoires de chaque pays, nous pouvons représenter graphiquement leurs intervalles de confiance construits à partir des simulations tirées de la distribution a posteriori du modèle.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Simulations et extraction des effets aléatoires\nlibrary(merTools)\nsimsRE <- REsim(modele3, n.sims = 1000, oddsRatio = FALSE)\n# Calcul des intervalles de confiance\nsimsRE$lower <- simsRE$mean - 1.96 * simsRE$sd\nsimsRE$upper <- simsRE$mean + 1.96 * simsRE$sd\n# Variable binaire pour la significativité\nsimsRE$sign <- case_when(\n simsRE$lower<0 & simsRE$upper<0 ~ \"inf\",\n simsRE$lower>0 & simsRE$upper>0 ~ \"sup\",\n TRUE ~ \"not\"\n)\ndf1 <- subset(simsRE, grepl(\"Intercept\", simsRE$term, fixed = TRUE))\ndf2 <- subset(simsRE, grepl(\"Age2\", simsRE$term, fixed = TRUE))\n# Représentation des intervalles de confiance\np1 <- ggplot(df1) + \n geom_errorbarh(aes(xmin = lower, xmax = upper,\n y = reorder(groupID, mean)), size = 0.5, height = 0.5) + \n geom_point(aes(x = mean, y = reorder(groupID, mean),\n color = sign)) + \n scale_color_manual(values = c(\"inf\" = \"#0077b6\", \"sup\" = \"#e63946\", \"not\"=\"#000000\"), \n labels = c(\"sign. < 0\", \"non sign.\", \"sign. > 0\")) +\n labs(x = \"Constante aléatoire\", y = \"Pays\")\np2 <- ggplot(df2) + \n geom_errorbarh(aes(xmin = lower, xmax = upper,\n y = reorder(groupID, mean)), size = 0.5, height = 0.5) + \n geom_point(aes(x = mean, y = reorder(groupID, mean),\n color = sign)) + \n scale_color_manual(values = c(\"inf\" = \"#0077b6\", \"sup\" = \"#e63946\", \"not\"=\"#000000\"), \n labels = c(\"sign. < 0\", \"non sign.\", \"sign. > 0\")) +\n labs(x = \"Pente aléatoire (âge)\", y = \"Pays\")\nggarrange(p1, p2, common.legend = TRUE, nrow = 1, ncol = 2)\n```\n\n::: {.cell-output-display}\n![Constantes aléatoires estimées par pays (intervalles de confiance obtenus par simulations)](09-GLMM_files/figure-html/fig-randomconstantes2b-1.png){#fig-randomconstantes2b fig-align='center' width=70%}\n:::\n:::\n\n\nLa @fig-randomconstantes2b nous permet ainsi de constater que l'effet des pays sur les pentes est presque toujours non significatif, sauf pour le Danemark. Son effet négatif (-0,136) indique un renforcement de l'effet général, lui-même négatif (-0,088). Une interprétation possible est qu'au Danemark, l'utilisation du vélo est proportionnellement plus courante par les jeunes que dans le reste des pays de l'Europe.\n\nPour l'interprétation finale, il est nécessaire d'afficher les valeurs exactes de ces différents paramètres et, dans notre cas, de les convertir en rapports de cotes avec la fonction exponentielle. Pour les pentes aléatoires, il peut être plus facile d'interpréter la somme de l'effet fixe et de l'effet aléatoire.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Extraction des effets aléatoires obtenus par simulation\nmat <- simsRE[c(\"mean\" , \"lower\" , \"upper\")]\nmat$Pays <- simsRE$groupID\nmat$effet <- simsRE$term\n# Séparation des pentes et des constantes\ndf1 <- subset(mat, grepl(\"Intercept\", mat$effet, fixed = TRUE))\ndf2 <- subset(mat, grepl(\"Age2\", mat$effet, fixed = TRUE))\n# Conversion en rapports de cotes pour les pentes (+ effet fixe)\ndf2$RC <- round(exp(df2$mean + fixef(modele3)[[3]]),3)\ndf2$RC025 <- round(exp(df2$lower + fixef(modele3)[[3]]),3)\ndf2$RC975 <- round(exp(df2$upper + fixef(modele3)[[3]]),3)\nprint(head(df2[c(\"Pays\" , \"RC\" , \"RC025\" , \"RC975\")],10))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Pays RC RC025 RC975\n27 Allemagne 0.835 0.744 0.937\n28 Autriche 0.986 0.875 1.112\n29 Belgique 0.895 0.797 1.005\n30 Bulgarie 0.946 0.824 1.086\n31 Croatie 0.905 0.802 1.020\n32 Danemark 0.799 0.720 0.886\n33 Espagne 0.920 0.796 1.063\n34 Estonie 0.950 0.835 1.080\n35 Finlande 0.865 0.774 0.967\n36 France 0.897 0.783 1.029\n```\n:::\n:::\n\n\nNous constatons ainsi qu'au Danemark, les chances pour un individu d'utiliser le vélo sont réduites de 20 % à chaque augmentation de l'âge d'un écart-type, contre seulement 1,5 % en Autriche (non significatif pour ce dernier). Notons ici que l'écart-type de la variable `Age` est de 11 ans. Nous pouvons à présent analyser les constantes.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Conversion en rapports de cotes pour les constantes\ndf1$RC <- round(exp(df1$mean),3)\ndf1$RC025 <- round(exp(df1$lower),3)\ndf1$RC975 <- round(exp(df1$upper),3)\nprint(head(df1[c(\"Pays\" , \"RC\" , \"RC025\" , \"RC975\")],10))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Pays RC RC025 RC975\n1 Allemagne 1.691 1.207 2.369\n2 Autriche 1.312 0.925 1.860\n3 Belgique 1.435 1.015 2.029\n4 Bulgarie 0.547 0.375 0.799\n5 Croatie 1.885 1.350 2.630\n6 Danemark 4.087 2.937 5.686\n7 Espagne 0.291 0.192 0.440\n8 Estonie 1.131 0.798 1.602\n9 Finlande 2.243 1.609 3.125\n10 France 0.527 0.359 0.774\n```\n:::\n:::\n\n\nEn revanche, les chances pour un individu d'utiliser le vélo comme mode de transport pour son trajet le plus fréquent sont 4 fois supérieures à la moyenne européenne, contre seulement 1,3 fois en Autriche. Notez à nouveau que les intervalles de confiance pour ces pentes et ces constantes pourraient être estimés plus fiablement par *bootstrap*.\n\n#### Diagnostic des effets aléatoires {#sec-09623}\n\nPour rappel, dans un modèle GLMM, les effets aléatoires sont modélisés comme provenant de distributions normales. Nous devons donc vérifier qu'ils respectent cette condition d'application. La @fig-diagbinomglmm1 (graphique quantile-quantile) nous permet de constater que les constantes suivent bien une distribution normale, ce qui ne semble pas vraiment être le cas pour les pentes. Considérant que leurs effets sont petits, il serait plus pertinent ici de les retirer du modèle.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Distribution normale univariée des constantes et des pentes aléatoires](09-GLMM_files/figure-html/fig-diagbinomglmm1-1.png){#fig-diagbinomglmm1 fig-align='center' width=90%}\n:::\n:::\n\n\nConsidérant que ce modèle inclut une corrélation entre les constantes et les pentes aléatoires, il est également nécessaire de vérifier si elles suivent conjointement une distribution normale bivariée. La @fig-diagbinomglmm2 semble indiquer que c'est le cas.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ncor_mat <- VarCorr(modele3)[[1]]\nre_effects <- data.frame(ranef(modele3)$Pays)\nnames(re_effects) <- c(\"constante\" , \"pente\")\nlibrary(ellipse)\nlevels <- c(0.05,0.25,0.75,0.95)\nels <- lapply(levels, function(i){\n el <- data.frame(ellipse(cor_mat, center = c(0,0), level = i))\n names(el) <- c(\"x\" , \"y\")\n return(el)\n})\nref_points <- data.frame(data.frame(MASS::mvrnorm(n = 1000, mu = c(0,0), Sigma = cor_mat)))\nnames(ref_points) <- c(\"x\" , \"y\")\nggplot() + \n geom_point(aes(x = x, y = y), data = ref_points, alpha = 0.3, size = 0.4) + \n geom_path(data = els[[1]], aes(x = x, y = y, color = \"a\")) + \n geom_path(data = els[[2]], aes(x = x, y = y, color = \"b\")) + \n geom_path(data = els[[3]], aes(x = x, y = y, color = \"c\")) +\n geom_path(data = els[[4]], aes(x = x, y = y, color = \"d\")) + \n geom_point(data = re_effects, aes(x = constante, y = pente))+\n scale_color_manual(values = c(\"a\"=\"#90e0ef\",\n \"b\"=\"#00b4d8\",\n \"c\"=\"#0077b6\",\n \"d\"=\"#03045e\"),\n labels = c(\"5 %\" , \"25 %\" , \"75 %\" , \"95 %\"))+\n labs(x = \"Constantes\", y = \"Pentes\", color = \"quantiles\")\n```\n\n::: {.cell-output-display}\n![Distribution normale bivariée des constantes et des pentes aléatoires](09-GLMM_files/figure-html/fig-diagbinomglmm2-1.png){#fig-diagbinomglmm2 fig-align='center' width=70%}\n:::\n:::\n\n\n#### Inférence pour les effets fixes {#sec-09624}\n\nNous avons mentionné, dans les sections précédentes, que le calcul de valeurs de *p* pour les effets fixes fait l'objet de controverses pour les modèles GLMM. La méthode offrant le meilleur compromis entre rapidité de calcul et fiabilité est la méthode Satterthwaite implémentée dans le *package* `lmerTest`. Pour l'utiliser, il suffit de charger le *package* `lmerTest` après `lme4`, ce qui modifie la fonction `summary` pour qu'elle utilise directement cette approche.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(lmerTest)\nround(summary(modele3)$coefficients,3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Estimate Std. Error z value Pr(>|z|)\n(Intercept) -3.358 0.213 -15.760 0.000\nSexehomme 0.373 0.038 9.823 0.000\nAge2 -0.088 0.028 -3.157 0.002\nEducationsecondaire 0.180 0.104 1.730 0.084\nEducationsecondaire inferieur 0.287 0.112 2.565 0.010\nEducationuniversite 0.130 0.107 1.215 0.225\nStatutEmploisans emploi 0.256 0.043 6.028 0.000\nRevenufaible 0.071 0.072 0.983 0.326\nRevenumoyen 0.038 0.065 0.588 0.557\nRevenusans reponse 0.204 0.103 1.984 0.047\nRevenutres eleve -0.124 0.186 -0.669 0.504\nRevenutres faible 0.236 0.086 2.741 0.006\nResidencegrande ville 0.270 0.069 3.887 0.000\nResidencepetite-moyenne ville 0.276 0.062 4.478 0.000\nResidencezone rurale -0.119 0.069 -1.720 0.085\nDuree2 -0.019 0.019 -0.980 0.327\nConsEnv 0.102 0.009 10.967 0.000\n```\n:::\n:::\n\n\nLes deux autres options envisageables sont : effectuer une analyse de type 3 ou calculer les intervalles de confiance par *bootstrap*. Cependant, elles requièrent beaucoup plus de temps de calcul. Par conséquent, elles ne sont pas présentées ici.\n\n## Quiz de révision du chapitre {#sec-097}\n\n\n
\n\n\n\n
\n
GLMM est un acronyme signifiant :
\n
Relisez au besoin la [section @sec-0912].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Les modèles GLMM, comparativement aux GLM, permettent de tenir compte de :
\n
Relisez au besoin la [section @sec-0911].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Un effet aléatoire se distingue d'un effet fixe, car :
\n
Relisez au besoin la [section @sec-0912].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quels sont les principaux types d'effets que nous pouvons modéliser avec des effets aléatoires?
\n
Relisez au besoin la [section @sec-092].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quels indicateurs peuvent être utilisés pour analyser la part de la variance / déviance expliquée aux différents niveaux d'un GLMM?
\n
Relisez au besoin la [section @sec-09223].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Toutes les variables catégorielles devraient être incluses dans un modèle comme des effets aléatoires.
\n
Relisez au besoin la [section @sec-0912].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Lors de l'estimation d'un effet aléatoire, le modèle estime exactement :
\n
Relisez au besoin la [section @sec-0921].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n\n
\n\n
\n
\n", + "supporting": [ + "09-GLMM_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/09-GLMM_files/figure-html/fig-bottdistrib-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-bottdistrib-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-bottdistrib-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-bottdistrib-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-diagbinomglmm1-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-diagbinomglmm1-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-diagbinomglmm1-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-diagbinomglmm1-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-diagbinomglmm2-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-diagbinomglmm2-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-diagbinomglmm2-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-diagbinomglmm2-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-diagglmm1-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-diagglmm1-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-diagglmm1-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-diagglmm1-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-diagglmm2-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-diagglmm2-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-diagglmm2-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-diagglmm2-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-diagglmm3-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-diagglmm3-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-diagglmm3-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-diagglmm3-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-fullrandom1-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-fullrandom1-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-fullrandom1-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-fullrandom1-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-fullrandom2-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-fullrandom2-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-fullrandom2-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-fullrandom2-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-fullrandom3-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-fullrandom3-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-fullrandom3-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-fullrandom3-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-glmmvarboot-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-glmmvarboot-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-glmmvarboot-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-glmmvarboot-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-glmmvariance-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-glmmvariance-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-glmmvariance-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-glmmvariance-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-randomconstantes1-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-randomconstantes1-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-randomconstantes1-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-randomconstantes1-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-randomconstantes2-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-randomconstantes2-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-randomconstantes2-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-randomconstantes2-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-randomconstantes2b-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-randomconstantes2b-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-randomconstantes2b-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-randomconstantes2b-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-randominter1-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-randominter1-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-randominter1-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-randominter1-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-randominter2-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-randominter2-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-randominter2-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-randominter2-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-randominter3-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-randominter3-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-randominter3-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-randominter3-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-randominter5-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-randominter5-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-randominter5-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-randominter5-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-randomslope-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-randomslope-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-randomslope-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-randomslope-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-randomslope2-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-randomslope2-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-randomslope2-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-randomslope2-1.png diff --git a/docs/09-GLMM_files/figure-html/fig-randomslope3-1.png b/.quarto/_freeze/09-GLMM/figure-html/fig-randomslope3-1.png similarity index 100% rename from docs/09-GLMM_files/figure-html/fig-randomslope3-1.png rename to .quarto/_freeze/09-GLMM/figure-html/fig-randomslope3-1.png diff --git a/.quarto/_freeze/10-Multiniveau/execute-results/html.json b/.quarto/_freeze/10-Multiniveau/execute-results/html.json new file mode 100644 index 0000000..93ec89c --- /dev/null +++ b/.quarto/_freeze/10-Multiniveau/execute-results/html.json @@ -0,0 +1,14 @@ +{ + "hash": "aaac3af710e39d3754bd6057fa30ac5d", + "result": { + "markdown": "# Régressions multiniveaux {#sec-chap10}\n\nDans le précédent chapitre, nous avons abordé les modèles à effets mixtes qui permettent d'introduire à la fois des effets fixes et aléatoires (GLMM). Dans ce chapitre, nous poursuivons sur cette voie avec une nouvelle extension des modèles GLM : les modèles multiniveaux. Ces modèles sont simplement une extension des modèles à effets mixtes et permettent de modéliser un phénomène avec une structure hiérarchique des données, tel que décrit dans le chapitre précédent.\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Rappel de la structure hiérarchique des données**\n:::\n::: bloc_notes-body\n**Exemple à deux niveaux :** il s’agit de modéliser un phénomène $y_{ij}$, soit une variable dépendante *Y* pour un individu *i* (niveau 1) niché dans un groupe *j* (niveau 2). Par exemple, modéliser l’indice de masse corporelle (IMC) de 5000 individus résidant dans 100 quartiers différents.\n\n**Exemple à trois niveaux :** il s’agit de modéliser un phénomène $y_{ijk}$, soit une variable dépendante *Y* pour un individu *i* (niveau 1), niché dans un groupe *j* (niveau 2) appartenant à un groupe *k* (niveau 3). Par exemple, modéliser les notes à un examen de mathématiques d’élèves (niveau 1) nichés dans des classes (niveau 2) nichées dans des écoles (niveau 3).\n:::\n:::\n\n\nNous avons largement décrit précédemment trois principaux types de modèles d’effets mixtes (GLMM) :\n\n* Les GLMM avec constantes aléatoires qui permettent d'avoir une constante différente pour chacun des groupes (niveau 2).\n\n* Les GLMM avec pentes aléatoires qui permettent de faire varier une variable indépendante au niveau 1 (coefficient) en fonction des groupes au niveau 2.\n\n* Les GLMM avec constantes et pentes aléatoires.\n\nLes modèles multiniveaux se différencient des modèles à effets mixtes puisqu'ils permettent d'introduire des variables indépendantes mesurées aux niveaux supérieurs (2 et 3).\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n - `lme4` pour en œuvre des modèles multiniveaux avec une variable dépendante continue.\n - `performance` pour obtenir le coefficient intraclasse (ICC).\n - `MuMIn` pour obtenir les pseudos R^2^.\n:::\n:::\n\n\n## Modèles multiniveaux : deux intérêts majeurs {#sec-101}\n\nLes modèles multiniveaux ont deux principaux avantages : analyser la répartition de la variance entre les différents niveaux et introduire des variables explicatives aux différents niveaux du modèle.\n\n### Répartition de la variance entre les différents niveaux {#sec-1011}\n\nLes modèles multiniveaux permettent d’estimer comment se répartit la variance entre les différents niveaux du jeu de données. Dans les deux exemples de l'encadré précédent, ils permettraient de répondre aux questions suivantes :\n\n* Quel niveau explique le plus l’IMC, le niveau individuel (niveau 1) ou le niveau contextuel (niveau 2)?\n\n* Comment se répartit la variance des notes à l’examen de mathématiques entre les trois niveaux? A-t-on plus de variance pour les individus (niveau 1) ou au sein des classes (niveau 2) ou entre les différentes écoles (niveau 3)?\n\n### Estimation des coefficients aux différents niveaux {#sec-1012}\nLes modèles multiniveaux permettent d’estimer simultanément les coefficients de plusieurs variables indépendantes introduites à chacun des niveaux du modèle. Autrement dit, de voir comment les variables indépendantes introduites aux différents niveaux influencent la variable dépendante (*Y*) mesurée au niveau 1. Si nous reprenons l'exemple à trois niveaux (élèves/classes/écoles), plusieurs facteurs peuvent influencer la réussite ou la performance scolaire des élèves aux différents niveaux :\n\n* **Variables indépendantes au niveau 1** (élève) : âge, sexe, statut socioéconomique, langue maternelle autre que la langue d'enseignement...\n\n* **Variables indépendantes au niveau 2** (classe) : nombre d’élèves par classe, programme spécialisé ou pas...\n\n* **Variables indépendantes au niveau 3** (école) : indice de défavorisation de l’école, école publique ou privée, qualité des infrastructures de l'école (bâtiment, gymnase, cour d'école)...\n\nDans la même veine, afin d'illustrer l'apport des modèles multiniveaux dans le champ de la géographie de la santé, Philibert et Apparicio [-@philibert2007statistiques, p. 129] signalent que « pour un modèle à deux niveaux, il s’agit de modéliser $y_{ij}$, par exemple l’IMC d’un individu *i* (niveau 1) résidant dans un quartier *j* (niveau 2). Il est alors possible de mettre des variables explicatives tant au niveau 1 (âge, sexe, revenu, niveau d’éducation, etc.) qu’au niveau 2 (niveau de défavorisation sociale du quartier, offre de services et d’équipements sportifs et récréatifs, caractéristiques de l’environnement urbain, etc.). Dans cet exemple, nous pouvons voir comment la modélisation multiniveau permet d’estimer simultanément les effets environnementaux et individuels de manière à distinguer la contribution de chacun des niveaux (ex. : l’effet du revenu des individus et celui de la défavorisation du quartier) dans l’explication des variations géographiques observées ».\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Évaluer les effets de milieu avec des analyses multiniveaux**\n:::\n::: bloc_aller_loin-body\nEn santé des populations et en études urbaines, les modèles multiniveaux sont largement mobilisés pour évaluer les effets de milieu (*neighbourhoods effects* ou *area effects* en anglais).\n\nAtkinson et Kintrea [-@atkinson2001disentangling, p. 2278] définissent les « effets de milieu comme le changement net dans les potentialités de l’existence (*life chances*) attribuable au fait de vivre dans un quartier (ou une zone) plutôt qu'un autre » [traduction libre]. Les effets de milieu peuvent être positifs ou négatifs et concerner aussi bien les enfants que les adultes.\n\nLes analyses multiniveaux sont particulièrement adaptées à l'évaluation des effets de milieu. En effet, plusieurs phénomènes — état de santé, comportement ou choix individuels — peuvent être influencés à la fois par des caractéristiques individuelles (âge, sexe, niveau de revenu, niveau d'éducation, etc.) et par des caractéristiques contextuelles (caractéristiques du quartier).\n\nAvec un modèle multiniveau, une fois contrôlées les caractéristiques individuelles (variables indépendantes mesurées au niveau 1), il est alors possible d'évaluer l'effet des caractéristiques du quartier (variables indépendantes mesurées au niveau 2) sur un phénomène $y_{ij}$ mesuré pour un individu *i* résidant dans un quartier *j*.\n:::\n:::\n\n## Différents types de modèles multiniveaux {#sec-102}\n\n### Description du jeu de données utilisé {#sec-1021} \n\nDans le cadre de cette section, nous présentons uniquement les modèles à deux niveaux, soit celui pour modéliser un phénomène $y_{ij}$. Pour ce faire, nous utilisons des données tirées d'une étude de Pham et al. [-@apparicio2017disentangling]. Dans cet article, les auteurs souhaitent évaluer les effets des caractéristiques de la forme urbaine et des caractéristiques socioéconomiques sur la couverture des arbres de rue, et ce, à partir d'un modèle multiniveau. Ils disposent ainsi d'une structure hiérarchique de données avec deux niveaux : les tronçons de rue (niveau 1, n = 10 814) inclus dans un et un seul secteur de recensement (niveau 2, n = 312). La variable dépendante ($y_{ij}$) est le pourcentage de la superficie du tronçon de rue qui est couverte par des arbres, calculé à partir d'images satellites à haute résolution (Quickbird, 60 cm, septembre 2008). L'ensemble des variables utilisées pour les modèles sont reportées au @tbl-Multi.\n\nSept variables indépendantes relatives à la forme urbaine sont mesurées pour les tronçons de rue, soit la largeur et la longueur de la rue, l'âge médian des bâtiments (introduit également au carré pour vérifier l'existence d'un effet curvilinéaire; voir la [section @sec-07511]), les pourcentages de bâtiments résidentiels, de duplex et de triplex, le nombre de bâtiments et finalement la distance moyenne entre le bâtiment et la rue. Les variables indépendantes pour les 312 secteurs de recensement (niveau 2) sont extraites du recensement canadien de 2006 (@tbl-Multi).\n\n\n::: {#tbl-Multi .cell tbl-cap='Statistiques descriptives pour les variables des modèles multiniveaux'}\n::: {.cell-output-display}\n|Nom |Intitulé | Type | Niveau | Moy.| Écart type|\n|:--------|:--------------------------------------------------|:----:|:------:|-------:|----------:|\n|PCTArb |Arbres sur le tronçon de rue (%) | VD | 1 | 7,2| 10,7|\n|Width |Largeur des rues | VI | 1 | 16,0| 7,3|\n|Length |Longueur de rues | VI | 1 | 136,0| 87,8|\n|AgeMed |Âge médian des bâtiments | VI | 1 | 1 952,7| 28,3|\n|ResiPCT |Bâtiments résidentiels (%) | VI | 1 | 83,5| 28,0|\n|DuTriPct |Duplex ou triplex (%) | VI | 1 | 41,8| 39,3|\n|NoLog |Nombre de bâtiments | VI | 1 | 14,0| 14,4|\n|Setback |Distance entre le bâtiment et la rue | VI | 1 | 7,2| 4,3|\n|ValLog |Valeur moyenne des logements (milliers de dollars) | VI | 2 | 267,6| 80,0|\n|UDipPCT |Diplômés universitaires (%) | VI | 2 | 16,9| 9,6|\n|PCTFRAVI |Personnes à faible revenu (%) | VI | 2 | 30,3| 11,5|\n|PCTIMGRE |Immigrants récents (%) | VI | 2 | 10,0| 7,3|\n|AvecEnf |Ménages avec enfants (%) | VI | 2 | 34,8| 12,6|\n|FranPCT |Langue maternelle française (%) | VI | 2 | 66,9| 24,1|\n:::\n:::\n\n\n### Démarche classique pour les modèles multiniveaux {#sec-1022} \n\nLa démarche habituelle en analyse multiniveau est de réaliser plusieurs modèles, allant du plus simple au plus complexe. Cette stratégie permet habituellement de bien cerner la répartition de la variance entre les différents niveaux et l'apport des variables explicatives introduites aux différents niveaux. De la sorte, cinq types de modèles peuvent être construits :\n\n1. Le modèle vide (appelé aussi modèle inconditionnel) qui comprend des constantes aléatoires au niveau 2, mais aucune variable explicative.\n\n2. Le modèle avec uniquement les variables indépendantes au niveau 1 et des constantes aléatoires au niveau 2.\n\n3. Le modèle complet avec les variables indépendantes aux deux niveaux et des constantes aléatoires.\n\n4. Le modèle complet avec les variables indépendantes aux deux niveaux, incluant une interaction entre une variable indépendante mesurée au niveau 1 et une autre mesurée au niveau 2.\n\n5. Le modèle avec les variables indépendantes aux deux niveaux et des constantes et pentes aléatoires.\n\n\nDans les sous-sections suivantes, nous détaillons les quatre premiers modèles en prenant soin de montrer les similitudes qu'ils partagent avec les modèles à effets mixtes vus précédemment. Notez d'emblée que les trois premiers modèles sont les plus fréquemment utilisés.\n\n#### Modèle vide {#sec-10221} \n\nComme son nom l'indique, le modèle vide ne comprend aucune variable explicative. Il consiste simplement à faire varier la constante du niveau 1 avec des effets aléatoires au niveau 2, ce qui explique qu'il est souvent comparé à une ANOVA avec des effets aléatoires. En d'autres termes, ce modèle correspond à un GLMM avec constantes aléatoires dans lequel aucune variable indépendante n'est incluse au niveau 1. D'ailleurs, si vous comparez l'@eq-multiniveauModeleVide avec l'@eq-glmm2 au chapitre précédent, vous constaterez que seul le paramètre $\\beta_1 x_1$ a été ôté et qu'il comprend aussi deux variances : l'une fixe au niveau 1 ($\\sigma_e$) et l'autre aléatoire (stochastique) au niveau 2 ($\\sigma_{\\upsilon}$).\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\beta_0 + \\upsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon}) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-multiniveauModeleVide}\n\n**Quel est alors l'intérêt de réaliser un modèle si simple?** À partir des deux variances, il est possible de calculer le **coefficient de corrélation intraclasse** (*intraclass-correlation* (ICC) en anglais) qui est le rapport entre la variance aléatoire et la somme des variances des deux niveaux, soit fixe et aléatoire (@eq-multiniveauIcc). Ce coefficient varie ainsi de 0 à 1 et indique la proportion de la variance de la variable dépendante qui est imputable au niveau 2. Tous(tes) les auteur(e)s s'entendent sur le fait qu'il est impératif de commencer une analyse de multiniveau en calculant ce modèle vide qui nous informe de la répartition de la variance entre les deux niveaux [@raudenbush2002hierarchical;@gelman2006data;@tabachnick2007;@bressoux2010]. Nous pourrons ensuite analyser l'évolution de ce coefficient dans les modèles subséquents.\n\n$$\n\\rho = \\frac{\\sigma_{\\upsilon}}{\\sigma_{\\upsilon} + \\sigma_{e}}\n$$ {#eq-multiniveauIcc}\n\nLes résultats du modèle vide (inconditionnel) à partir des données de Pham et al. [-@apparicio2017disentangling] sont présentés au @tbl-ModeleVide. La variance du niveau 1 est de 92,93 contre 19,82 au niveau 2. Le coefficient de corrélation intraclasse vaut alors : $\\mbox{19,82} / \\mbox{(19,82} + \\mbox{92,93}) = \\mbox{0,1758}$. Cela signifie que 18 % de la variance de la variable dépendante sont imputables au niveau 2 (des secteurs de recensement) et 82 % au niveau 1 (des tronçons). Nous verrons comment évolue ce coefficient dans les modèles subséquents.\n\n\n::: {#tbl-ModeleVide .cell tbl-cap='Résultats du modèle vide (modèle 1)'}\n::: {.cell-output-display}\n|Paramètre | Coefficient| Erreur type| Valeur de T|\n|:--------------------------------------|-----------:|-----------:|-----------:|\n|Effets fixes (niveau 1) | | | |\n|Constante | 7,337| 0,277| 26,466|\n|Répartition de la variance | | | |\n|Variance (niveau 1) | 19,818| | |\n|Variance (niveau 2) | 92,925| | |\n|Coefficient de corrélation intraclasse | 0,176| | |\n|Qualité d'ajustement du modèle | | | |\n|AIC | 80 305,219| | |\n|R^2^ marginal | 0,000| | |\n|R^2^ conditionnel | 0,176| | |\n:::\n:::\n\n\n#### Modèle avec les variables indépendantes du niveau 1 {#sec-10222}\n\nDans ce second modèle, nous introduisons uniquement les variables explicatives au niveau 1. Par conséquent, ce modèle est tout simplement un modèle à effets mixtes (GLMM) avec des constantes aléatoires largement décrit à la [section @sec-0921]). Si vous comparez l'équation du modèle vide (@eq-multiniveauModeleVide) avec l'équation de ce modèle (@eq-multiniveauModele2), vous constaterez que le paramètre $\\beta_1 x_1$ a été ajouté. Il correspond au coefficient pour la variable indépendante $X_1$ mesurée au niveau 1 (effet fixe). Nous pourrions alors ajouter d'autres paramètres pour les autres variables indépendantes du modèle, soit $\\beta_1 x_1 + \\beta_2 x_2+ \\ldots + \\beta_k x_k$ ($k$ étant le nombre de variables explicatives mesurées au niveau 1, effets fixes).\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\upsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon})) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-multiniveauModele2}\n\nLes résultats du second modèle sont présentés au @tbl-Modele2. \n\n**La répartition de la variance entre les deux niveaux**. La variance du niveau 1 est désormais de 15,263 contre 80,317 au niveau 2, ce qui permet d'obtenir un coefficient de corrélation intraclasse de 0,1597. Cela signifie que de 16 % de la variance de la variable dépendante sont imputables au niveau 2 (des secteurs de recensement), une fois contrôlées les caractéristiques des tronçons.\n\n**La qualité d'ajustement du modèle**. Dans le chapitre précédent sur les GLMM, nous avons largement décrit plusieurs mesures de la qualité d'ajustement du modèle, notamment l'AIC et les R^2^ marginal et conditionnel. À titre de rappel, voici comment interpréter ces mesures :\n\n* Plus la valeur de l'AIC est faible, mieux le modèle est ajusté. En comparant les valeurs d'AIC du modèle vide et du modèle avec les variables explicatives du niveau 1 (80 305 *versus* 78 785), nous constatons, sans surprise, que ce dernier modèle est plus performant.\n\n* Le R^2^ marginal indique la proportion de la variance expliquée uniquement si les effets fixes sont pris en compte (ici, 0,129). Quant au R^2^ conditionnel, il indique la proportion de la variance expliquée à la fois par les effets fixes et aléatoires (ici, 0,268). L'écart important entre les deux R^2^ signale que les secteurs de recensement (effets aléatoires, niveau 2) jouent un rôle important dans le modèle.\n\n**Quelles informations peut-on tirer des coefficients de régression?**\nLes variables indépendantes relatives à la forme urbaine les plus importantes sont : le pourcentage de bâtiments résidentiels (`ResiPCT`), la largeur de la rue (`Width`) et le nombre de bâtiments (`NoLog`). Aussi, la distance entre le bâtiment et la rue (`Setback`) est associée positivement avec la variable dépendante. En effet, à chaque ajout d'un mètre de la distance moyenne entre les bâtiments et le tronçon de rue, la couverture des arbres sur le tronçon augmente de 0,202 point de pourcentage, toutes choses étant égales par ailleurs.\n\n\n::: {#tbl-Modele2 .cell tbl-cap='Résultats du modèle avec les variables indépendantes au niveau 1 (modèle 2)'}\n::: {.cell-output-display}\n|Paramètre | Coefficient| Erreur type| Valeur de T|\n|:--------------------------------------|-----------:|-----------:|-----------:|\n|Effets fixes (niveau 1) | | | |\n|Constante | -1 028,618| 179,736| -5,723|\n|Width | -0,129| 0,013| -10,160|\n|Length | 0,011| 0,002| 6,322|\n|AgeMed | 1,103| 0,186| 5,946|\n|AgeMed2 | 0,000| 0,000| -6,158|\n|ResiPCT | 0,047| 0,003| 13,558|\n|DuTriPct | -0,013| 0,003| -4,842|\n|NoLog | 0,147| 0,011| 13,938|\n|Setback | 0,202| 0,023| 8,792|\n|Répartition de la variance | | | |\n|Variance (niveau 1) | 15,263| | |\n|Variance (niveau 2) | 80,317| | |\n|Coefficient de corrélation intraclasse | 0,160| | |\n|Qualité d'ajustement du modèle | | | |\n|AIC | 78 785,827| | |\n|R^2^ marginal | 0,129| | |\n|R^2^ conditionnel | 0,268| | |\n:::\n:::\n\n\nRemarquez la valeur de la constante : −1028,618. À titre de rappel, la constante est la valeur que prend la variable dépendante quand toutes les variables indépendantes sont égales à 0. Or, il est impossible qu'elles soient toutes égales à zéro. \n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Centrage des variables quantitatives mesurées au niveau 1**\n:::\n::: bloc_astuce-body\nEn analyse multiniveau, il est très courant et souvent recommandé de centrer les variables explicatives quantitatives au niveau 1. Deux options sont alors possibles :\n\n1. Pour une variable indépendante donnée, les observations sont centrées sur leur moyenne générale, c'est-à-dire la moyenne de l'ensemble des observations du jeu de données, soit $X_{ij} - \\bar{X}$. Dans ce cas, la constante est donc la valeur que prend la variable $Y$ quand toutes les variables indépendantes sont égales à leur moyenne respective.\n2. Chaque observation est centrée sur la moyenne de son groupe respectif, soit $X_{ij} - \\bar{X}_{.j}$.\n\nComme signalé par Bressoux [-@bressoux2010, p. 328], « dans le premier cas, la variance des pentes sera estimée pour l'individu moyen dans la distribution générale, tandis que dans le second elle est estimée pour l'individu moyen de chaque groupe ».\n\nAutrement dit, comparativement à un modèle sans centrage, les valeurs des coefficients pour les variables indépendantes sont les mêmes dans le premier cas (seule la valeur de la constante va changer) tandis qu'elles sont différentes dans le second cas.\n\nAttention, il ne faut pas appliquer de centrage sur une variable qualitative, qu'elle soit dichotomique, nominale ou ordinale.\n\n**Pourquoi la pratique du centrage en analyse multiniveau est si courante?**\n\nDans la plupart des livres sur les régressions multiniveaux, le centrage est recommandé, notamment dans l'ouvrage classique de Raudenbush et Bryk [-@raudenbush2002hierarchical]. Rappelons que ces modèles sont largement utilisés en éducation avec une structure hiérarchique classique élève/école/classe. Nous nous intéressons alors à l'individu moyen (l'élève), ce qui explique que le centrage est habituellement appliqué. Par exemple, ne pas centrer l'âge des élèves fait que la constante qui est obtenue est peu interprétable : difficile d'évaluer la note moyenne à un examen quand la variable *âge de l'élève* a la valeur de 0, tout comme les autres variables explicatives quantitatives relatives à l'élève.\n\n\n**Centrage et réduction de l'ensemble des variables du modèle**\n\nIl est à noter que certains auteurs centrent et réduisent l'ensemble des variables du modèle. À titre de rappel, le centrage consiste à soustraire à chaque valeur la moyenne de la variable; la réduction, à la diviser par l'écart-type de la variable ([section @sec-02552]). Pour chaque variable, la moyenne est alors égale à 0 et l'écart-type à 1. Les coefficients s'interprètent alors en termes d'augmentation d'une unité d'écart-type tant pour la VI que la VD. Ils correspondent alors à des coefficients de régression standardisés (abordés dans la [section @sec-0742]). Ce processus de centrage et de réduction des variables peut être motivé par des problèmes de convergence du modèle (lorsque l'algorithme d'optimisation n'arrive pas à trouver une solution pour produire les coefficients).\n:::\n:::\n\nPar conséquent, nous vous proposons de centrer les variables du niveau 1 de notre jeu de données. Si vous comparez les tableaux [-@tbl-Modele2] et [-@tbl-Modele2b], vous constaterez que les valeurs relatives aux coefficients, aux mesures de la répartition de la variance et à la qualité d'ajustement du modèle sont les mêmes. Seule la valeur de la constante change : elle passe de −1028,618 à 7,228. Elle s'interprète désormais de la façon suivante : si toutes les variables explicatives sont égales à leurs moyennes respectives, alors le pourcentage de la superficie du tronçon couverte par des arbres est égal à 7,228 %.\n\n\n::: {#tbl-Modele2b .cell tbl-cap='Résultats du modèle avec les variables indépendantes centrées au niveau 1 (modèle 2)'}\n::: {.cell-output-display}\n|Paramètre | Coefficient| Erreur type| Valeur de T|\n|:--------------------------------------|-----------:|-----------:|-----------:|\n|Effets fixes (niveau 1) | | | |\n|Constante | 7,228| 0,248| 29,151|\n|Width.c | -0,129| 0,013| -10,160|\n|Length.c | 0,011| 0,002| 6,322|\n|AgeMed.c | 1,103| 0,186| 5,946|\n|AgeMed2.c | 0,000| 0,000| -6,158|\n|ResiPCT.c | 0,047| 0,003| 13,558|\n|DuTriPct.c | -0,013| 0,003| -4,842|\n|NoLog.c | 0,147| 0,011| 13,938|\n|Setback.c | 0,202| 0,023| 8,792|\n|Répartition de la variance | | | |\n|Variance (niveau 1) | 15,263| | |\n|Variance (niveau 2) | 80,317| | |\n|Coefficient de corrélation intraclasse | 0,160| | |\n|Qualité d'ajustement du modèle | | | |\n|AIC | 78 785,827| | |\n|R^2^ marginal | 0,129| | |\n|R^2^ conditionnel | 0,268| | |\n:::\n:::\n\n\n#### Modèle complet avec les variables indépendantes aux niveaux 1 et 2 {#sec-10223}\n\nLe troisième type de modèle consiste à introduire à la fois les variables explicatives mesurées au niveau 1 et au niveau 2 (@eq-multiniveauModele3). Il est communément appelé le modèle complet. Les variables explicatives du niveau 2 sont aussi considérées comme des effets fixes.\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\underbrace{\\beta_0 + \\beta_1 x_1}_{\\mbox{effets fixes (niveau 1)}}+ \\underbrace{\\beta_2 z_2}_{\\mbox{effets fixes (niveau 2)}}+\\epsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon}) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-multiniveauModele3}\n\nLes résultats du troisième modèle sont présentés au @tbl-Modele3. Ce modèle permet d'évaluer les effets des caractéristiques socioéconomiques (mesurés au niveau des secteurs de recensement) sur la couverture des arbres des îlots, une fois contrôlées les caractéristiques de la forme urbaine des tronçons. Rappelons que dans ce modèle, les constantes sont aléatoires et les variables indépendantes au niveau 1 sont centrées.\n\n**Quelles informations peut-on tirer des coefficients de régression du niveau 2?**\nD’emblée, deux caractéristiques n'ont pas d'effet significatif sur la variable dépendante, soit les pourcentages de diplômés universitaires et de ménages avec enfants. Par contre, toutes choses étant égales par ailleurs, la valeur moyenne des logements et le pourcentage d'immigrants récents sont associés à une augmentation de la couverture végétale. À l'inverse, le pourcentage de personnes à faible revenu est associé à une diminution de la couverture végétale.\n\n\n::: {#tbl-Modele3 .cell tbl-cap='Résultats du modèle avec les variables indépendantes aux niveaux 1 et 2 (modèle 3)'}\n::: {.cell-output-display}\n|Paramètre | Coefficient| Erreur type| Valeur de T|\n|:-------------------------------------------------|-----------:|-----------:|-----------:|\n|Effets fixes (niveau 1 : tronçons) | | | |\n|Constante | -0,518| 3,227| -0,160|\n|Width.c | -0,132| 0,013| -10,375|\n|Length.c | 0,011| 0,002| 6,265|\n|AgeMed.c | 1,097| 0,185| 5,920|\n|AgeMed2.c | 0,000| 0,000| -6,136|\n|ResiPCT.c | 0,046| 0,003| 13,352|\n|DuTriPct.c | -0,013| 0,003| -4,737|\n|NoLog.c | 0,148| 0,011| 13,985|\n|Setback.c | 0,194| 0,023| 8,428|\n|Effets fixes (niveau 2 : secteurs de recensement) | | | |\n|ValLog | 0,016| 0,004| 4,126|\n|UDipPCT | 0,014| 0,035| 0,396|\n|PCTFRAVI | -0,088| 0,030| -2,988|\n|PCTIMGRE | 0,237| 0,049| 4,870|\n|AvecEnf | 0,001| 0,032| 0,018|\n|FranPCT | 0,052| 0,016| 3,183|\n|Répartition de la variance | | | |\n|Variance (niveau 1) | 12,121| | |\n|Variance (niveau 2) | 80,347| | |\n|Coefficient de corrélation intraclasse | 0,131| | |\n|Qualité d'ajustement du modèle | | | |\n|AIC | 78 776,845| | |\n|R^2^ marginal | 0,160| | |\n|R^2^ conditionnel | 0,270| | |\n:::\n:::\n\n\n#### Modèle avec une interaction entre deux niveaux {#sec-10224}\n\nDans la [section @sec-0754], nous avons vu comment introduire des variables d'interaction dans une régression linéaire multiple, soit entre deux variables continues ([section @sec-07541]), soit entre une variable continue et une variable dichotomique ([section @sec-07542]), soit entre deux variables dichotomiques ([section @sec-07543]). En analyse multiniveau, il peut être pertinent d'introduire une interaction entre une variable mesurée au niveau 1 et une autre mesurée au niveau 2 (@eq-multiniveauModele4).\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\underbrace{\\beta_0 + \\beta_1 x_1}_{\\mbox{effets fixes (niv. 1)}}+ \\underbrace{\\beta_2 z_2}_{\\mbox{effets fixes (niv. 2)}}+ \\underbrace{\\beta_3 (x_1 \\times z_2)}_{\\mbox{interaction (niv. 1 et 2)}}+ \\epsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon})) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-multiniveauModele4}\n\nDans le @tbl-Modele4, nous introduisons une variable d'interaction entre la *distance entre le bâtiment et la rue* (`Setback.c`) et le *pourcentage de personnes à faible revenu* (`PCTFRAVI`). On constate alors que `PCTFRAVI` est associé négativement avec la variable dépendante ($\\beta =$ −0,079, *t* = −2,684). Toutefois, lorsqu'elle est mise en interaction avec la variable `Setback.c`, cette variable est significative et positive ($\\beta =$ 0,008, *t* = 4,591).\n\n\n::: {#tbl-Modele4 .cell tbl-cap='Résultats du modèle avec une variable d\\'interaction entre les deux niveaux 1 et 2 (modèle 4)'}\n::: {.cell-output-display}\n|Paramètre | Coefficient| Erreur type| Valeur de T|\n|:-------------------------------------------------|-----------:|-----------:|-----------:|\n|Effets fixes (niveau 1 : tronçons) | | | |\n|Constante | -0,009| 3,198| -0,003|\n|Width.c | -0,136| 0,013| -10,660|\n|Length.c | 0,011| 0,002| 6,289|\n|AgeMed.c | 1,092| 0,185| 5,894|\n|AgeMed2.c | 0,000| 0,000| -6,114|\n|ResiPCT.c | 0,046| 0,003| 13,239|\n|DuTriPct.c | -0,013| 0,003| -4,742|\n|NoLog.c | 0,145| 0,011| 13,747|\n|Setback.c | 0,003| 0,048| 0,072|\n|Effets fixes (niveau 2 : secteurs de recensement) | | | |\n|ValLog | 0,016| 0,004| 4,141|\n|UDipPCT | 0,009| 0,035| 0,268|\n|PCTFRAVI | -0,079| 0,029| -2,684|\n|PCTIMGRE | 0,219| 0,048| 4,543|\n|AvecEnf | -0,007| 0,032| -0,221|\n|FranPCT | 0,050| 0,016| 3,072|\n|Variable d'interaction (niv. 1 et 2) | | | |\n|Setback X PCTFRAVI | 0,008| 0,002| 4,591|\n|Répartition de la variance | | | |\n|Variance (niveau 1) | 11,829| | |\n|Variance (niveau 2) | 80,239| | |\n|Coefficient de corrélation intraclasse | 0,128| | |\n|Qualité d'ajustement du modèle | | | |\n|AIC | 78 768,659| | |\n|R^2^ marginal | 0,163| | |\n|R^2^ conditionnel | 0,270| | |\n:::\n:::\n\n\n## Conditions d'application des régressions multiniveaux {#sec-103}\n\nPuisque les modèles multiniveaux sont une extension des modèles à effets mixtes (GLMM), nous retrouvons globalement les mêmes conditions d'application (voir la [section @sec-093]), dont les principales sont :\n\n1. l'absence de multicolinéarité excessive,\n2. la normalité des résidus,\n3. l'absence d'observations trop influentes dans le modèle.\n\n**Combien de groupes au niveau 2?** Dans la [section @sec-093], nous avons vu que dans un modèle GLMM, plusieurs auteur(e)s, notamment Gelman et Hill \n [-@gelman2006data], préconisent un minimum de cinq groupes dans un modèle à effets mixtes. Toutefois, dans un modèle complet d'une régression multiniveau, nous introduisons aussi des variables indépendantes au niveau 2. Par conséquent, le nombre de groupes doit être augmenté significativement, et ce, idéalement proportionnellement au nombre des variables indépendantes ajoutées au niveau 2. En ce sens, Bressoux [-@bressoux2010, p.325] conseille d'avoir au moins 10 groupes pour chaque variable indépendante mesurée au niveau 2. Toujours selon Bressoux [-@bressoux2010, p.325], certains auteurs recommandent même 20 groupes par variable indépendante au niveau 2. En conséquence, bien qu'aucune règle de pouce soit clairement admise, il est clair qu'un modèle complet multiniveau nécessite un nombre de groupes conséquent.\n\n## Mise en œuvre dans R {#sec-104}\n\nPour mettre en œuvre des modèles multiniveaux avec une variable dépendante continue, nous utilisons la fonction `lmer` du *package* `lme4`. Pour d'autres distributions, nous pouvons utiliser la fonction `glmer` implémentant différentes familles de modèles GLM, notamment binomiale (modèle multiniveau logistique), gaussien, Gamma, inverse gaussien, Poisson, Quasi-poisson, etc. Comme pour les modèles GLMM, lorsque d’autres distributions sont nécessaires, il est possible d'utiliser le *package* `gamlss`.\n\n### Le modèle vide {#sec-1041}\nDans le code R ci-dessous, la syntaxe `lmer(PCTArb ~ 1 + (1| SRNOM), data = Multiniveau)` permet de construire le modèle vide avec la variable indépendante `PCTArb` et `SRNOM` comme variable définissant les groupes au niveau 2, soit les 312 secteurs de recensement. À titre de rappel, le modèle vide ne comprend aucune variable indépendante.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(\"lme4\")\nlibrary(\"MuMIn\")\n# chargement du jeu de données\nload(\"data/multiniveau/dataArbres.RData\")\n\n# MODÈLE 1 : modèle vide (sans prédicteurs)\n#------------------------------------------------------\n# Écrire Y ~ 1 signifie que le modèle est vide\n# 1| SRNOM : signifie que l'on fait varier la constante avec la variable SRNOM\nModele1 <- lmer(PCTArb ~ 1 + (1| SRNOM), data = Multiniveau)\n\n# Nombre de groupes\ncat(\"nombre de groupes =\", length(unique(Multiniveau$SRNOM)))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nnombre de groupes = 312\n```\n:::\n:::\n\n\nLa fonction `summary(Modele1)` permet d'afficher les résultats du modèle. Dans la section intitulée `Random effects`, la variance pour le niveau 2 (`SRNOM (Intercept)`) est de 19,82 contre 92,93 pour le niveau 1 (`Residual`). Le coefficient de corrélation intraclasse (ICC) est donc égal à $\\mbox{19,82 / (19,82+92,93)} \\times \\mbox{100 = 17,58}$%.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Résultats du modèle\nsummary(Modele1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLinear mixed model fit by REML ['lmerMod']\nFormula: PCTArb ~ 1 + (1 | SRNOM)\n Data: Multiniveau\n\nREML criterion at convergence: 80299.2\n\nScaled residuals: \n Min 1Q Median 3Q Max \n-1.9413 -0.5295 -0.2235 0.2175 8.4695 \n\nRandom effects:\n Groups Name Variance Std.Dev.\n SRNOM (Intercept) 19.82 4.452 \n Residual 92.93 9.640 \nNumber of obs: 10814, groups: SRNOM, 312\n\nFixed effects:\n Estimate Std. Error t value\n(Intercept) 7.3373 0.2772 26.47\n```\n:::\n:::\n\n\nNotez qu'il est possible d'obtenir directement la valeur de l'ICC avec la fonction `icc(Modele1)` du *package* `performance` et les statistiques d'ajustement du modèle avec les fonctions `logLik`, `AIC` et `BIC`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Calcul de l'ICC (coefficient intraclasse)\nperformance::icc(Modele1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# Intraclass Correlation Coefficient\n\n Adjusted ICC: 0.176\n Unadjusted ICC: 0.176\n```\n:::\n\n```{.r .cell-code}\nICC1 <- performance::icc(Modele1)\ncat(\"Part de la variance de la variable dépendante imputable au niveau 2 : \", \n round(ICC1$ICC_adjusted*100,2), \"%\", sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nPart de la variance de la variable dépendante imputable au niveau 2 : 17.58%\n```\n:::\n\n```{.r .cell-code}\n# Qualité d'ajustement du modèle\ncat(\"Statistiques d'ajustement du modèle :\",\n \"\\n-2 Log V = \", -2*logLik(Modele1),\n \"\\nAIC =\", AIC(Modele1), \n \"\\nBIC =\", BIC(Modele1))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nStatistiques d'ajustement du modèle : \n-2 Log V = 80299.22 \nAIC = 80305.22 \nBIC = 80327.08\n```\n:::\n:::\n\n\n### Modèle avec les variables indépendantes du niveau 1 {#sec-1042}\n\nLe second modèle consiste à introduire les variables indépendantes mesurées pour les tronçons de rue (niveau 1). Notez comment sont centrées préalablement les variables explicatives.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Centrage des variables indépendantes\nVINiv1 <- c(\"Width\" , \"Length\" , \"AgeMed\" , \"AgeMed2\" , \"ResiPCT\" , \"DuTriPct\" , \"NoLog\" , \"Setback\")\nfor (e in VINiv1){\n e.c <- paste(e, \".c\", sep = \"\")\n Multiniveau[[e.c]] <- Multiniveau[[e]] - mean(Multiniveau[[e]])\n}\n\n# MODÈLE 2 : modèle avec les prédicteurs au niveau 1 (rues) \n# ------------------------------------------------------\nModele2 <- lmer(PCTArb ~\n # Variables indépendantes au niveau 1\n Width.c+Length.c+AgeMed.c+AgeMed2.c+ResiPCT.c+DuTriPct.c+NoLog.c+Setback.c+\n (1| SRNOM), data = Multiniveau)\n\n# Résultats du modèle\nsummary(Modele2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLinear mixed model fit by REML ['lmerMod']\nFormula: PCTArb ~ Width.c + Length.c + AgeMed.c + AgeMed2.c + ResiPCT.c + \n DuTriPct.c + NoLog.c + Setback.c + (1 | SRNOM)\n Data: Multiniveau\n\nREML criterion at convergence: 78763.8\n\nScaled residuals: \n Min 1Q Median 3Q Max \n-2.9065 -0.5536 -0.1941 0.2569 9.4205 \n\nRandom effects:\n Groups Name Variance Std.Dev.\n SRNOM (Intercept) 15.26 3.907 \n Residual 80.32 8.962 \nNumber of obs: 10814, groups: SRNOM, 312\n\nFixed effects:\n Estimate Std. Error t value\n(Intercept) 7.228e+00 2.479e-01 29.151\nWidth.c -1.292e-01 1.272e-02 -10.160\nLength.c 1.085e-02 1.717e-03 6.322\nAgeMed.c 1.103e+00 1.856e-01 5.946\nAgeMed2.c -2.950e-04 4.791e-05 -6.158\nResiPCT.c 4.699e-02 3.466e-03 13.558\nDuTriPct.c -1.299e-02 2.683e-03 -4.842\nNoLog.c 1.473e-01 1.057e-02 13.938\nSetback.c 2.018e-01 2.295e-02 8.792\n\nCorrelation of Fixed Effects:\n (Intr) Wdth.c Lngth. AgMd.c AgMd2. RsPCT. DTrPc. NoLg.c\nWidth.c -0.003 \nLength.c 0.011 -0.216 \nAgeMed.c 0.000 0.010 -0.014 \nAgeMed2.c 0.002 -0.011 0.013 -1.000 \nResiPCT.c 0.056 0.095 0.208 0.023 -0.024 \nDuTriPct.c -0.010 0.022 0.086 -0.074 0.077 0.025 \nNoLog.c -0.030 0.156 -0.785 -0.008 0.009 -0.269 -0.127 \nSetback.c 0.048 -0.018 -0.146 0.007 -0.008 -0.014 0.035 0.038\nfit warnings:\nSome predictor variables are on very different scales: consider rescaling\n```\n:::\n\n```{.r .cell-code}\n# Calcul de l'ICC (coefficient intraclasse)\nperformance::icc(Modele2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# Intraclass Correlation Coefficient\n\n Adjusted ICC: 0.160\n Unadjusted ICC: 0.139\n```\n:::\n\n```{.r .cell-code}\nICC2 <- performance::icc(Modele2)\ncat(\"Part de la variance de la variable dépendante \",\n \"\\nimputable au niveau 2 : \", round(ICC2$ICC_adjusted*100,2), \"%\", sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nPart de la variance de la variable dépendante \nimputable au niveau 2 : 15.97%\n```\n:::\n\n```{.r .cell-code}\n# Calcul des R2 conditionnel et marginal avec les fonctions\n# r.squaredGLMM ou r2_nakagawa du package performance\nr.squaredGLMM(Modele2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n R2m R2c\n[1,] 0.1292872 0.2683329\n```\n:::\n\n```{.r .cell-code}\nr2_nakagawa(Modele2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# R2 for Mixed Models\n\n Conditional R2: 0.268\n Marginal R2: 0.129\n```\n:::\n\n```{.r .cell-code}\n# Qualité d'ajustement du modèle\ncat(\"Statistiques d'ajustement du modèle\",\n \"\\n-2 Log L = \", -2*logLik(Modele2),\n \"\\nAIC =\", AIC(Modele2), \n \"\\nBIC =\", BIC(Modele2))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nStatistiques d'ajustement du modèle \n-2 Log L = 78763.83 \nAIC = 78785.83 \nBIC = 78866\n```\n:::\n:::\n\n\n\n### Modèle avec les variables indépendantes aux niveaux 1 et 2 {#sec-1043}\n\nLe troisième modèle comprend à la fois les variables indépendantes mesurées aux deux niveaux (tronçons et secteurs de recensement).\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# MODÈLE 3 : modèle complet avec les prédicteurs aux niveaux 1 et 2\n# ------------------------------------------------------\nModele3 <- lmer(PCTArb ~\n # Variables indépendantes au niveau 1\n Width.c+Length.c+AgeMed.c+AgeMed2.c+ResiPCT.c+DuTriPct.c+NoLog.c+Setback.c+\n # Variables indépendantes au niveau 2\n ValLog+UDipPCT+PCTFRAVI+PCTIMGRE+AvecEnf+FranPCT+\n (1| SRNOM), data = Multiniveau)\n\n# Résultats du modèle\nsummary(Modele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLinear mixed model fit by REML ['lmerMod']\nFormula: PCTArb ~ Width.c + Length.c + AgeMed.c + AgeMed2.c + ResiPCT.c + \n DuTriPct.c + NoLog.c + Setback.c + ValLog + UDipPCT + PCTFRAVI + \n PCTIMGRE + AvecEnf + FranPCT + (1 | SRNOM)\n Data: Multiniveau\n\nREML criterion at convergence: 78742.8\n\nScaled residuals: \n Min 1Q Median 3Q Max \n-3.0461 -0.5558 -0.1939 0.2622 9.4190 \n\nRandom effects:\n Groups Name Variance Std.Dev.\n SRNOM (Intercept) 12.12 3.482 \n Residual 80.35 8.964 \nNumber of obs: 10814, groups: SRNOM, 312\n\nFixed effects:\n Estimate Std. Error t value\n(Intercept) -5.175e-01 3.227e+00 -0.160\nWidth.c -1.319e-01 1.271e-02 -10.375\nLength.c 1.076e-02 1.717e-03 6.265\nAgeMed.c 1.097e+00 1.854e-01 5.920\nAgeMed2.c -2.936e-04 4.785e-05 -6.136\nResiPCT.c 4.649e-02 3.482e-03 13.352\nDuTriPct.c -1.268e-02 2.677e-03 -4.737\nNoLog.c 1.478e-01 1.057e-02 13.985\nSetback.c 1.944e-01 2.307e-02 8.428\nValLog 1.591e-02 3.856e-03 4.126\nUDipPCT 1.405e-02 3.546e-02 0.396\nPCTFRAVI -8.837e-02 2.958e-02 -2.988\nPCTIMGRE 2.367e-01 4.860e-02 4.870\nAvecEnf 5.778e-04 3.226e-02 0.018\nFranPCT 5.213e-02 1.638e-02 3.183\nfit warnings:\nSome predictor variables are on very different scales: consider rescaling\n```\n:::\n\n```{.r .cell-code}\n# Qualité d'ajustement du modèle\ncat(\"Statistiques d'ajustement du modèle\",\n \"\\n-2 Log L = \", -2*logLik(Modele3),\n \"\\nAIC =\", AIC(Modele3), \"\\nBIC =\", BIC(Modele3))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nStatistiques d'ajustement du modèle \n-2 Log L = 78742.85 \nAIC = 78776.85 \nBIC = 78900.75\n```\n:::\n\n```{.r .cell-code}\n# Calcul de l'ICC (coefficient intraclasse)\nperformance::icc(Modele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# Intraclass Correlation Coefficient\n\n Adjusted ICC: 0.131\n Unadjusted ICC: 0.110\n```\n:::\n\n```{.r .cell-code}\nICC3 <- performance::icc(Modele3)\ncat(\"Part de la variance de la variable dépendante \",\n \"\\nimputable au niveau 2 : \", round(ICC3$ICC_adjusted*100,2), \"%\", sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nPart de la variance de la variable dépendante \nimputable au niveau 2 : 13.11%\n```\n:::\n\n```{.r .cell-code}\n# Calcul des R2 conditionnel et marginal avec les fonctions\n# r.squaredGLMM ou r2_nakagawa du package performance\nr.squaredGLMM(Modele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n R2m R2c\n[1,] 0.1598477 0.269979\n```\n:::\n\n```{.r .cell-code}\nr2_nakagawa(Modele3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# R2 for Mixed Models\n\n Conditional R2: 0.270\n Marginal R2: 0.160\n```\n:::\n:::\n\n\n### Modèle complet avec une interaction {#sec-10414}\n\nLe quatrième modèle consiste à ajouter au modèle complet une interaction entre deux variables des deux niveaux.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Variance d'interaction\nMultiniveau$PCTFRAVI_Setback <- Multiniveau$PCTFRAVI * Multiniveau$Setback.c\n\n# MODÈLE 4 : interaction aux deux niveaux\n# ------------------------------------------------------\nModele4 <- lmer(PCTArb ~\n # Variables indépendantes au niveau 1\n Width.c+Length.c+AgeMed.c+AgeMed2.c+ResiPCT.c+DuTriPct.c+NoLog.c+Setback.c+\n # Variables indépendantes au niveau 2\n ValLog+UDipPCT+PCTFRAVI+PCTIMGRE+AvecEnf+FranPCT+\n # Variable d'interaction\n PCTFRAVI_Setback+\n(1| SRNOM), data = Multiniveau)\n\n# Résultats du modèle\nsummary(Modele4)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLinear mixed model fit by REML ['lmerMod']\nFormula: PCTArb ~ Width.c + Length.c + AgeMed.c + AgeMed2.c + ResiPCT.c + \n DuTriPct.c + NoLog.c + Setback.c + ValLog + UDipPCT + PCTFRAVI + \n PCTIMGRE + AvecEnf + FranPCT + PCTFRAVI_Setback + (1 | SRNOM)\n Data: Multiniveau\n\nREML criterion at convergence: 78732.7\n\nScaled residuals: \n Min 1Q Median 3Q Max \n-3.0148 -0.5568 -0.1922 0.2598 9.4261 \n\nRandom effects:\n Groups Name Variance Std.Dev.\n SRNOM (Intercept) 11.83 3.439 \n Residual 80.24 8.958 \nNumber of obs: 10814, groups: SRNOM, 312\n\nFixed effects:\n Estimate Std. Error t value\n(Intercept) -0.0094840 3.1984732 -0.003\nWidth.c -0.1356543 0.0127250 -10.660\nLength.c 0.0107911 0.0017159 6.289\nAgeMed.c 1.0915688 0.1851983 5.894\nAgeMed2.c -0.0002923 0.0000478 -6.114\nResiPCT.c 0.0460769 0.0034803 13.239\nDuTriPct.c -0.0126785 0.0026735 -4.742\nNoLog.c 0.1453667 0.0105748 13.747\nSetback.c 0.0034430 0.0475943 0.072\nValLog 0.0158168 0.0038196 4.141\nUDipPCT 0.0094041 0.0351462 0.268\nPCTFRAVI -0.0788297 0.0293729 -2.684\nPCTIMGRE 0.2193705 0.0482873 4.543\nAvecEnf -0.0070626 0.0319907 -0.221\nFranPCT 0.0498673 0.0162308 3.072\nPCTFRAVI_Setback 0.0081695 0.0017794 4.591\nfit warnings:\nSome predictor variables are on very different scales: consider rescaling\n```\n:::\n\n```{.r .cell-code}\n# Qualité d'ajustement du modèle\ncat(\"Statistiques d'ajustement du modèle\",\n \"\\n-2 Log L = \", -2*logLik(Modele4),\n \"\\nAIC =\", AIC(Modele3), \"\\nBIC =\", BIC(Modele4))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nStatistiques d'ajustement du modèle \n-2 Log L = 78732.66 \nAIC = 78776.85 \nBIC = 78899.85\n```\n:::\n\n```{.r .cell-code}\n# Calcul de l'ICC (coefficient intraclasse)\nperformance::icc(Modele4)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# Intraclass Correlation Coefficient\n\n Adjusted ICC: 0.128\n Unadjusted ICC: 0.108\n```\n:::\n\n```{.r .cell-code}\nICC4 <- performance::icc(Modele4)\ncat(\"Part de la variance de la variable dépendante \",\n \"\\nimputable au niveau 2 : \", round(ICC4$ICC_adjusted*100,2), \"%\", sep = \"\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nPart de la variance de la variable dépendante \nimputable au niveau 2 : 12.85%\n```\n:::\n\n```{.r .cell-code}\n# Calcul des R2 conditionnel et marginal avec les fonctions\n# r.squaredGLMM ou r2_nakagawa du package performance\nr.squaredGLMM(Modele4)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n R2m R2c\n[1,] 0.1628372 0.270394\n```\n:::\n\n```{.r .cell-code}\nr2_nakagawa(Modele4)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n# R2 for Mixed Models\n\n Conditional R2: 0.270\n Marginal R2: 0.163\n```\n:::\n:::\n\n\n### Comparaison des quatre modèles {#sec-1045}\n\nPour comparer les modèles, nous utilisons habituellement les statistiques d'ajustement du modèle vues plus haut, soit le maximum de vraisemblance (*−2 Log-likelihood*), l'AIC, l'ICC et les R^2^ marginal et conditionnel.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nc_logLik <- c(logLik(Modele1),logLik(Modele2),logLik(Modele3),logLik(Modele4))\nICC <- c(performance::icc(Modele1)$ICC_adjusted,\n performance::icc(Modele2)$ICC_adjusted,\n performance::icc(Modele3)$ICC_adjusted,\n performance::icc(Modele4)$ICC_adjusted)\n\nR2m <- c(r.squaredGLMM(Modele1)[1],\n r.squaredGLMM(Modele2)[1],\n r.squaredGLMM(Modele3)[1],\n r.squaredGLMM(Modele4)[1])\n\nR2c <- c(r.squaredGLMM(Modele1)[2],\n r.squaredGLMM(Modele2)[2],\n r.squaredGLMM(Modele3)[2],\n r.squaredGLMM(Modele4)[2])\n\nprint(data.frame(\n Modele = c(\"Modèle 1 (vide)\", \n \"Modèle 2 (VI : niv. 1)\", \n \"Modèle 3 (VI : niv. 1 et 2)\",\n \"Modèle 4 (interaction niv. 1 et 2\"),\n dl = AIC(Modele1, Modele2, Modele3, Modele4)$df,\n Moins2LogLik = round(-2*c_logLik,0),\n AIC = round(AIC(Modele1, Modele2, Modele3, Modele4)$AIC,0),\n ICC = round(ICC,4),\n R2marg = round(R2m,3),\n R2cond = round(R2c,3)\n))\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n Modele dl Moins2LogLik AIC ICC R2marg R2cond\n1 Modèle 1 (vide) 3 80299 80305 0.1758 0.000 0.176\n2 Modèle 2 (VI : niv. 1) 11 78764 78786 0.1597 0.129 0.268\n3 Modèle 3 (VI : niv. 1 et 2) 17 78743 78777 0.1311 0.160 0.270\n4 Modèle 4 (interaction niv. 1 et 2 18 78733 78769 0.1285 0.163 0.270\n```\n:::\n:::\n\n\nVous constaterez ci-dessus que les valeurs d'AIC et de -2 log de vraisemblance diminuent des modèles 1 à 4, signalant une amélioration progressive des modèles. Cela se traduit aussi par une augmentation du R^2^ conditionnel incluant à la fois les effets fixes et aléatoires. Sans surprise, la valeur du coefficient de corrélation intraclasse diminue du modèle vide au modèle complet : plus nous ajoutons de variables dépendantes, plus la capacité explicative du niveau 2 diminue.\n\nIl est également judicieux de vérifier si un modèle est significativement différent du modèle précédent avec la fonction `anova` qui compare les différences de leurs déviances. En guise d'exemple, la différence de déviance de 59 ($\\mbox{78 625}-\\mbox{78 684}=\\mbox{59}$) entre les modèles 3 et 2 (modèle complet *versus* modèle GLMM) avec six degrés de liberté – puisque le modèle 3 inclut six variables indépendantes de plus que le précédent ($\\mbox{17}-\\mbox{11}=\\mbox{6}$) – est significative (*p* < 0,001). Cela indique que le modèle 3 est plus performant que le précédent.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nanova(Modele1, Modele2, Modele3, Modele4)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nData: Multiniveau\nModels:\nModele1: PCTArb ~ 1 + (1 | SRNOM)\nModele2: PCTArb ~ Width.c + Length.c + AgeMed.c + AgeMed2.c + ResiPCT.c + DuTriPct.c + NoLog.c + Setback.c + (1 | SRNOM)\nModele3: PCTArb ~ Width.c + Length.c + AgeMed.c + AgeMed2.c + ResiPCT.c + DuTriPct.c + NoLog.c + Setback.c + ValLog + UDipPCT + PCTFRAVI + PCTIMGRE + AvecEnf + FranPCT + (1 | SRNOM)\nModele4: PCTArb ~ Width.c + Length.c + AgeMed.c + AgeMed2.c + ResiPCT.c + DuTriPct.c + NoLog.c + Setback.c + ValLog + UDipPCT + PCTFRAVI + PCTIMGRE + AvecEnf + FranPCT + PCTFRAVI_Setback + (1 | SRNOM)\n npar AIC BIC logLik deviance Chisq Df Pr(>Chisq) \nModele1 3 80304 80326 -40149 80298 \nModele2 11 78706 78786 -39342 78684 1614.351 8 < 2.2e-16 ***\nModele3 17 78659 78783 -39313 78625 59.131 6 6.758e-11 ***\nModele4 18 78640 78771 -39302 78604 21.166 1 4.213e-06 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n```\n:::\n:::\n\n\n## Quiz de révision du chapitre {#sec-105}\n\n\n
\n\n\n\n
\n
Quels sont les deux intérêts majeurs des modèles multiniveaux?
\n
Relisez au besoin la [section @sec-101].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Le modèle vide comprend :
\n
Relisez au besoin la [section @sec-10221].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Un modèle avec uniquement les variables indépendantes du niveau 1 est un modèle à effets mixtes (GLMM).
\n
Relisez au besoin la [section @sec-10222].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quelle mesure permet d'analyser la répartition de la variance entre les deux niveaux?
\n
Relisez au besoin la [section @sec-10221].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Un modèle complet comprend des variables explicatives aux deux niveaux.
\n
Relisez au besoin la [section @sec-10223].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Est-ce possible d'introduire une interaction entre une variable mesurée au niveau 1 et une autre mesurée au niveau 2?
\n
Relisez au besoin la [section @sec-10224].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n\n
\n\n
\n
\n", + "supporting": [], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/.quarto/_freeze/11-GAM/execute-results/html.json b/.quarto/_freeze/11-GAM/execute-results/html.json new file mode 100644 index 0000000..f6d2e99 --- /dev/null +++ b/.quarto/_freeze/11-GAM/execute-results/html.json @@ -0,0 +1,16 @@ +{ + "hash": "63ef30f8c9fec5e51097c8b4c21f4ed8", + "result": { + "markdown": "# Modèles généralisés additifs {#sec-chap11}\n\nDans les précédents chapitres, nous avons eu l'occasion d'explorer toute une panoplie de modèles : régressions linéaires, modèles généralisés, modèles généralisés à effets mixtes et modèles multiniveaux. Dans ce chapitre, nous abordons une nouvelle extension dans le monde des régressions : les modèles généralisés additifs (*Generalized additive model* en anglais — GAM). Cette extension a pour but de permettre de modéliser des relations non linéaires entre les variables indépendantes et la variable dépendante.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2` le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes.\n - `metR` pour placer des étiquettes sur des isolignes.\n \n* Pour jouer avec des *splines* :\n - `splines2` pour construire les fonctions de base de nombreuses *splines*.\n - `segmented` pour ajuster des modèles avec des coefficients variant par segment.\n \n* Pour ajuster des modèles GAM :\n - `mgcv`, le *package* de référence pour ajuster des GAM dans R!\n - `gamlss`, un second *package* très flexible pour ajuster des GAM.\n - `gamlss.add`, une extension de `gamlss` ajoutant des distributions supplémentaires.\n\n* Pour analyser des modèles GAM :\n - `itsadug` pour notamment extraire certains résultats d'un GAM.\n - `mixedup` pour notamment extraire les effets aléatoires d'un GAM.\n - `DHARMa` pour le diagnostic des résidus simulés.\n:::\n:::\n\n\n## Introduction {#sec-111}\n\nPuisque les modèles GAM sont une extension des modèles GLM, ils peuvent s'appliquer à des modèles pour des variables indépendantes qualitatives, de comptage ou continues. Nous l'appliquons ici, à titre d'illustration, à une variable indépendante continue. Pour rappel, la formule décrivant un modèle linéaire généralisé (GLM) utilisant une distribution normale et une fonction de lien identitaire est la suivante : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\beta X\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glm1B}\n\nLes coefficients $\\beta$ permettent de quantifier l'effet des variables indépendantes (*X*) sur la moyenne (l'espérance) ($\\mu$) de la variable dépendante (*Y*). Un coefficient $\\beta_k$ négatif indique que, si la variable $X_k$ augmente, alors la variable *Y* tend à diminuer et inversement, si le coefficient est positif. L'inconvénient de cette formulation est que le modèle est capable de capter uniquement des relations linéaires entre ces variables. Or, il existe de nombreuses situations dans lesquelles une variable indépendante a un lien non linéaire avec une variable dépendante; voici quelques exemples : \n\n* Si nous mesurons le niveau de bruit émis par une source sonore (variable dépendante) à plusieurs endroits et que nous tentons de prédire l'intensité sonore en fonction de la distance à la source (variable indépendante), nous pouvons nous attendre à observer une relation non linéaire entre les deux. En effet, le son étant une énergie se dispersant selon une sphère dans l'espace, son intensité est inversement proportionnelle au carré de la distance avec la source sonore.\n\n* La concentration de la pollution atmosphérique en ville suit généralement des patrons temporels et spatiaux influencés directement par la météorologie et les activités humaines. Autrement dit, il serait absurde d'introduire l'espace de façon linéaire (avec un gradient nord-sud ou est-ouest), ou le moment de la journée de façon linéaire (comme si la pollution augmentait du matin au soir ou inversement). En guise d'exemple, la @fig-gam1, tirée de @2020_3, illustre bien ces variations temporelles pour deux polluants (le dioxyde d'azote et l'ozone).\n\n\n![Patron journalier du dioxyde d'azote et de l'ozone à Paris](images/Chap11/no2_03_patterns.png){#fig-gam1 width=\"75%\" fig-align=\"center\"}\n\n### Non-linéarité fonctionnelle {#sec-1111}\n\nIl existe de nombreuses façons d'introduire des relations non linéaires dans un modèle. La première et la plus simple à mettre en œuvre est de transformer la variable indépendante à l'aide d'une fonction inverse, exponentielle, logarithmique ou autre.\n\nPrenons un premier exemple avec une variable *Y* que nous tentons de prédire avec une variable *X*, présenté à la @fig-gam2. Si nous ajustons une droite de régression à ces données (en bleu), nous constatons que l'augmentation de *X* est associée à une augmentation de *Y*. Cependant, la droite de régression est très éloignée des données et ne capte qu'une petite partie de la relation. Une lecture attentive permet de constater que l'effet de *X* sur *Y* augmente de plus en plus rapidement à mesure que *X* augmente. Cette forme est caractéristique d'une relation exponentielle. Nous pouvons donc transformer la variable *X* avec la fonction exponentielle afin d'obtenir un meilleur ajustement (en rouge).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Relation non linéaire exponentielle](11-GAM_files/figure-html/fig-gam2-1.png){#fig-gam2 fig-align='center' width=50%}\n:::\n:::\n\n\n\nLa @fig-gam3 illustre trois autres situations avec les fonctions logarithmique, logistique inverse et racine carrée. Cette approche peut donner des résultats intéressants si vous disposez d'une bonne justification théorique sur la forme attendue de la relation entre *X* et *Y*. \n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Autres relations non linéaires](11-GAM_files/figure-html/fig-gam3-1.png){#fig-gam3 fig-align='center' width=75%}\n:::\n:::\n\n\nIl existe également des cas de figure dans lesquels aucune fonction ne donne de résultats pertinents, comme illustré à la @fig-gam4. Nous constatons facilement qu'aucune des fonctions proposées n'est capable de bien capter la relation entre les deux variables. Puisque cette relation est complexe, il convient alors d'utiliser une autre stratégie pour la modéliser. \n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Relation non linéaire plus complexe](11-GAM_files/figure-html/fig-gam4-1.png){#fig-gam4 fig-align='center' width=75%}\n:::\n:::\n\n\n\n### Non-linéarité avec des polynomiales {#sec-1112}\n\nNous avons vu, dans le chapitre sur la régression simple ([section @sec-07511]), qu'il est possible d'utiliser des polynomiales pour ajuster des relations non linéaires. Pour rappel, il s'agit simplement d'ajouter à un modèle la variable *X* à différents exposants ($X+X^2+\\dots+X^k$). Chaque exposant supplémentaire (chaque ordre supplémentaire) permet au modèle d'ajuster une relation plus complexe. Rien de tel qu'un graphique pour illustrer le tout (@fig-gam5).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Visualisation de plusieurs polynomiales](11-GAM_files/figure-html/fig-gam5-1.png){#fig-gam5 fig-align='center' width=70%}\n:::\n:::\n\n\nL'enjeu est de sélectionner le bon nombre de degrés de la polynomiale pour le modèle. Chaque degré supplémentaire constitue une nouvelle variable dans le modèle, et donc un paramètre supplémentaire. Un trop faible nombre de degrés produit des courbes trop simplistes, alors qu'un nombre trop élevé conduit à un surajustement (*overfitting* en anglais) du modèle. La @fig-gam6 illustre ces deux situations.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Sur et sous-ajustement d'une polynomiale](11-GAM_files/figure-html/fig-gam6-1.png){#fig-gam6 fig-align='center' width=70%}\n:::\n:::\n\n\nUn des problèmes inhérents à l'approche des polynomiales est la difficulté d'interprétation. En effet, les coefficients ne sont pas directement interprétables et seule une figure représentant les prédictions du modèle permet d'avoir une idée de l'effet de la variable *X* sur la variable *Y*.\n\n### Non-linéarité par segments {#sec-1113}\n\nUn compromis intéressant offrant une interprétation simple et une relation potentiellement complexe consiste à découper la variable *X* en segments, puis d'ajuster un coefficient pour chacun de ces segments. Nous obtenons ainsi une ligne brisée et des coefficients faciles à interpréter (@fig-gam7). Nous ne présentons pas d'exemple d'application dans R, mais sachez que le *package* `segmented` permet d'ajuster ce type de modèle. \n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Régression par segment](11-GAM_files/figure-html/fig-gam7-1.png){#fig-gam7 fig-align='center' width=70%}\n:::\n:::\n\n\nL'enjeu est alors de déterminer le nombre de points et la localisation de points de rupture. L'inconvénient majeur de cette approche est qu'en réalité, peu de phénomènes sont marqués par des ruptures très nettes.\n\nÀ la @fig-gam7, nous avons divisé la variable *X* en trois segments ($k_1$, $k_2$ et $k_3$), définis respectivement avec les intervalles suivants : [0,00-0,22], [0,22-0,41] et [0,41-1,00]. Concrètement, cela revient à diviser la variable *X* en trois nouvelles variables $X_{k1}$, $X_{k2}$, et $X_{k3}$. La valeur de $X_{ik}$ est égale à $x_i$ si $x_i$ se trouve dans l'intervalle propre à *k*, et à 0 autrement. Ici, nous obtenons trois coefficients : \n\n* le premier est positif, une augmentation de *X* sur le premier segment est associée à une augmentation de *Y*;\n\n* le second est négatif, une augmentation de *X* sur le second segment est associée à une diminution de *Y*;\n\n* le troisième est aussi négatif, une augmentation de *X* sur le troisième segment est associée à une diminution de *Y*, mais moins forte que pour le second segment.\n\n\n### Non-linéarité avec des *splines* {#sec-1114}\n\nLa dernière approche, et certainement la plus flexible, est d'utiliser ce que l'on appelle une *spline* pour capter des relations non linéaires. Une *spline* est une fonction créant des variables supplémentaires à partir d'une variable *X* et d'une fonction de base. Ces variables supplémentaires, appelées bases (*basis* en anglais), sont ajoutées au modèle; la sommation de leurs valeurs multipliées par leurs coefficients permet de capter les relations non linéaires entre une variable dépendante et une variable indépendante. Le nombre de bases et leur localisation (plus souvent appelé nœuds) permettent de contrôler la complexité de la fonction non linéaire.\n\nPrenons un premier exemple simple avec une fonction de base triangulaire (*tent basis* en anglais). Nous créons ici une *spline* avec sept nœuds répartis équitablement sur l'intervalle de valeurs de la variable *X*. Les sept bases qui en résultent sont présentées à la @fig-gam8. Dans cette figure, chaque sommet d'un triangle correspond à un nœud et chaque triangle correspond à une base.\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Bases de la spline triangulaire](11-GAM_files/figure-html/fig-gam8-1.png){#fig-gam8 fig-align='center' width=70%}\n:::\n:::\n\n\n\nEn ajoutant ces bases dans notre modèle de régression, nous pouvons ajuster un coefficient pour chacune et le représenter en multipliant ces bases par les coefficients obtenus avec une simple régression linéaire (@fig-gam9).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Spline triangulaire multipliée par ces coefficients](11-GAM_files/figure-html/fig-gam9-1.png){#fig-gam9 fig-align='center' width=70%}\n:::\n:::\n\n\nNous remarquons ainsi que les bases correspondant à des valeurs plus fortes de *Y* ont reçu des coefficients plus élevés. Pour reconstituer la fonction non linéaire, il suffit d'additionner ces bases multipliées par leurs coefficients, soit la ligne bleue à la @fig-gam10.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Spline triangulaire](11-GAM_files/figure-html/fig-gam10-1.png){#fig-gam10 fig-align='center' width=70%}\n:::\n:::\n\n\nLa fonction de base triangulaire est intéressante pour présenter la logique qui sous-tend les *splines*, mais elle est rarement utilisée en pratique. On lui préfère généralement d'autres formes donnant des résultats plus lisses comme les *B-spline* quadratiques, *B-spline* cubiques, *M-spline*, *Duchon spline*, etc.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Comparaison de différentes bases](11-GAM_files/figure-html/fig-gam11-1.png){#fig-gam11 fig-align='center' width=75%}\n:::\n:::\n\n\nLes approches que nous venons de décrire sont regroupées sous l'appellation de modèles additifs. Dans les prochaines sous-sections, nous nous concentrons davantage sur les *splines* du fait de leur plus grande flexibilité.\n\n## *Spline* de régression et *spline* de lissage {#sec-112}\n\nDans les exemples précédents, nous avons vu que la construction d'une *spline* nécessite d'effectuer deux choix importants : le nombre de nœuds et leur localisation. Un trop grand nombre de nœuds conduit à un surajustement du modèle alors qu'un trop faible nombre de nœuds conduit à un sous-ajustement. Lorsque ces choix sont effectués par l'utilisateur et que les bases sont ajoutées manuellement dans le modèle tel que décrit précédemment, nous parlons alors de **_splines_ de régression** (*Regression Spline* en anglais).\n\nUne approche a été proposée pour faciliter le choix du nombre de nœuds, il s'agit de **_splines_ de lissage** (*smoothing spline* en anglais). L'idée derrière cette approche est d'introduire dans le modèle une pénalisation associée avec le nombre de nœuds (ou degré de liberté) de la *spline*, dans un souci de parcimonie : chaque nœud supplémentaire doit suffisamment contribuer au modèle pour être conservé. Il n'est pas nécessaire ici de rentrer dans le détail mathématique de cette pénalisation qui est un peu complexe. Retenez simplement qu'elle dépend d'un paramètre appelé $\\lambda$ :\n\n* plus $\\lambda$ tend vers 0, plus la pénalisation est faible et plus la *spline* de lissage devient une simple *spline* de régression; \n\n* à l'inverse, plus elle est forte, plus la pénalité est importante, au point que la *spline* peut se résumer à une simple ligne droite. \n\nCela est illustré à la @fig-gam12 comprenant trois *splines* avec 20 nœuds et des valeurs $\\lambda$ différentes contrôlant la force de la pénalité. \n\nBien évidemment, nous constatons qu'avec la *spline* de régression (non pénalisée), 20 nœuds conduisent à un fort surajustement du modèle. En revanche, les *splines* de lissage (pénalisées) permettent de corriger ce problème de surajustement. Toutefois, une valeur trop importante de $\\lambda$ conduit à un sous-ajustement du modèle (ici $\\lambda = 3$ et $\\lambda = 100$, lignes verte et bleue).\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Pénalisation des splines](11-GAM_files/figure-html/fig-gam12-1.png){#fig-gam12 fig-align='center' width=70%}\n:::\n:::\n\n\n\nAvec les *splines* de lissage, l'enjeu est de sélectionner une valeur optimale de $\\lambda$. Le plus souvent, les *packages* R **estiment eux-mêmes** ce paramètre à partir des données utilisées dans le modèle. Toutefois, gardez en mémoire que vous pouvez modifier ce paramètre. Mentionnons également que les *splines* de lissage peuvent être reparamétrées dans un modèle pour être intégrées comme des effets aléatoires. Dans ce cas-ci, $\\lambda$ est remplacé par un simple paramètre de variance directement estimé dans le modèle [@wood2004stable].\n\n\n## Interprétation d'une *spline* {#sec-113}\n\nL'interprétation d'une *spline* se fait à l'aide de graphiques. En effet, puisqu'elle est composée d'un ensemble de coefficients appliqués à des bases, il est difficile d'interpréter directement ces derniers. Nous préférons alors représenter la fonction obtenue à l'aide d'un graphique, illustrant son **effet marginal**. Ce graphique est construit en trois étapes : \n\n1. Créer un jeu de données fictif dans lequel l'ensemble des variables indépendantes sont fixées à leurs moyennes respectives, sauf la variable pour laquelle nous souhaitons représenter la *spline*. Pour cette dernière, un ensemble de valeurs allant de son minimum à son maximum est utilisé;\n\n2. Utiliser le modèle pour prédire les valeurs attendues de la variable dépendante pour chacune des observations fictives ainsi créées;\n\n3. Afficher les prédictions obtenues dans un graphique.\n\nNotez ici qu'un graphique des effets marginaux se base sur les prédictions du modèle. Si un modèle est mal ajusté, les prédictions ne seront pas fiables et il sera inutile d'interpréter la *spline* obtenue.\n\nIl est aussi possible, dans le cas des *splines* de lissage, d'interpréter les *estimated degrees of freedom* (EDF) qui constituent une approximation du nombre de nœuds de la *spline*. S'ils ne nous renseignent pas sur la forme de la *spline*, ils nous indiquent son niveau de complexité. Une *spline* avec un EDF de 1 est en réalité un simple terme linéaire. Plus l'EDF augmente, plus la *spline* est complexe. \n\n\n## Multicolinéarité non linéaire {#sec-114}\n\nLorsque des *splines* sont ajoutées dans un modèle, il est nécessaire de vérifier si ces dernières ne posent pas un problème de multicolinéarité. Cependant, le VIF ne peut plus être utilisé du fait de la non-linéarité des relations modélisées. Il est alors nécessaire d'utiliser une autre mesure : la concurvité (*concurvity*) permettant de mesurer sur une échelle allant de 0 à 1 à quel point deux *splines* ont en réalité capturé le même effet et se substituent l'une à l'autre. Une valeur de 0 indique une absence totale de concurvité alors qu'une valeur de 1 indique que deux *splines* sont rigoureusement identiques (modèle non identifiable). \n\n## *Splines* avancées {#sec-115}\n\nJusqu'ici, nous avons seulement présenté le cas le plus simple pour lequel une *spline* est construite à partir d'une seule variable dépendante continue, mais les **splines** peuvent être utilisées dans de nombreux autres contextes et ont une incroyable flexibilité. Nous détaillons ici trois exemples fréquents : les *splines* cycliques, les *splines* variant par groupe et les *splines* multivariées. Pour une description complète des effets non linéaires possibles avec `mgcv`, n'hésitez pas à consulter sa [documentation](https://stat.ethz.ch/R-manual/R-patched/library/mgcv/html/smooth.terms.html).\n\n\n::: {#tbl-exemplesplines .cell tbl-cap='Exemples de splines avancées'}\n::: {.cell-output-display}\n|Type |Code |Description |\n|:------------------------------|:---------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n|spline cyclique |`s(x, bs = 'cc')` |Une spline cyclique doit être utilisée si le 0 de la variable X correspond également à sa valeur maximum. Un bon exemple est le temps dans une journée, car 24 h est équivalent à 0 h |\n|spline variant par groupe |`s(x, by = x2)` |Une spline variant par groupe permet d'ajuster une spline à une variable X1 différente pour chaque groupe identifié par une variable qualitative X2 |\n|spline bivariée |`s(x1,x2)` |Une spline bivariée est utilisée pour modéliser l'interaction non linéaire de deux variables X1 et X2 s'exprimant dans la même unité (typiquement des coordonnées géographiques cartésiennes) |\n|spline d'interaction complète |`te(x1,x2)` |Une spline d'interaction permet de modéliser l'interaction non linéaire de deux variables continues pouvant s'exprimer dans des unités différentes, elle combine les effets spécifiques de chacune des deux variables et leur interaction |\n|spline d'interaction partielle |`s(x1) + s(x2) + ti(x1,x2)` |Une spline d'interaction partielle permet de distinguer les effets non linéaires individuels de deux variables de leur interaction non linéaire |\n:::\n:::\n\n\n\n### *Splines* cycliques {#sec-1151}\n\nUne *spline* cyclique est une extension d'une *spline* classique dont les bases aux extrémités sont spécifiées de telle sorte que la valeur au départ de la *spline* soit la même que celle à la fin de la *spline*. Cela permet à la *spline* de former une boucle, ce qui est particulièrement intéressant pour des variables dont le 0 et la valeur maximale correspondent en réalité à la même valeur. L'exemple le plus parlant est certainement le cas d'une variable représentant la mesure d'un angle en degrés. Les valeurs de 0 et 360 sont identiques et les valeurs 350 et 10 sont toutes les deux à une distance de 10 degrés de 0. Un autre exemple possible serait de considérer l'heure comme une variable continue; dans ce cas, 24 h et 0 h signifient la même chose.\n\nPrenons un exemple concret. Nous souhaitons modéliser la concentration de dioxyde d'azote (NO~2~) à Paris, mesurée par un ensemble de stations fixes. Nous pourrions nous attendre à ce que le NO~2~ suive chaque jour un certain patron. Concrètement, à proximité d'axes routiers majeurs, nous nous attendons à observer des pics suivant les flux pendulaires. À la @fig-gam13, nous retrouvons bien les deux pics attendus correspondant aux heures de pointe du matin et du soir. Aussi, comme indiqué par la ligne rouge, la valeur prédite par la *spline* est la même à 24 h et à 0 h.\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Spline cyclique pour modéliser la concentration de dioxyde d'azote](11-GAM_files/figure-html/fig-gam13-1.png){#fig-gam13 fig-align='center' width=70%}\n:::\n:::\n\n\n\n\n### Splines par groupe {#sec-1152}\n\nTel qu'abordé dans les chapitres précédents, il arrive régulièrement que les observations appartiennent à différents groupes. Dans ce cas de figure, nous pouvons être amenés à vérifier si la relation décrite par une *spline* est identique pour chacun des groupes d'observations. Il s'agit alors d'ajuster une *spline* différente par groupe. Dans l'exemple précédent, chaque valeur de NO~2~ a été mesurée par une station fixe de mesure spécifique. Compte tenu du fait que l'environnement autour de chaque station est particulier, nous pourrions s'attendre à ce que les valeurs de NO~2~ ne présentent pas exactement les mêmes patrons journaliers pour chaque station.\n\nÀ la @fig-gam14, il est possible de constater que le NO~2~ suit globalement le même patron temporel pour l'ensemble des stations à l'exception de trois d'entres-elles. Il s'agit en réalité de stations situées dans des secteurs ruraux de la région parisienne, et donc moins impactées par le trafic routier.\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Spline cyclique variant par groupe](11-GAM_files/figure-html/fig-gam14-1.png){#fig-gam14 fig-align='center' width=70%}\n:::\n:::\n\n\n\n### *Splines* multivariées et *splines* d'interaction {#sec-1153}\n\nJusqu'ici, nous n'avons considéré que des *splines* ne s'appliquant qu'à une seule variable indépendante; cependant, il est possible de construire des *splines* multivariées s'ajustant simultanément sur plusieurs variables indépendantes. L'objectif est alors de modéliser les potentielles interactions non linéaires entre les variables indépendantes combinées dans une même *spline*. Prenons un exemple concret, dans la section sur les modèles GLM, nous avons modélisé la couverture des aires de diffusion (AD) à Montréal par des îlots de chaleur. Parmi les variables indépendantes, nous avons notamment utilisé la distance au centre-ville ainsi que la part de la surface végétalisée des AD. Nous pourrions formuler l'hypothèse que ces deux variables influencent conjointement et de façon non linéaire la proportion de la surface d'îlot de chaleur dans chaque AD. Pour représenter une *spline* sur plusieurs dimensions, nous utilisons alors une carte de chaleur dont la couleur représente la valeur de la variable dépendante prédite en fonction des deux variables indépendantes.\n\nIl est important de distinguer la *spline* d'**interaction** et la *spline* **multivariée**. La première est utilisée lorsque les variables indépendantes introduites dans la *spline* ne sont pas exprimées sur la même échelle et n'évoluent pas conjointement. L'exemple donné ci-dessus avec les variables de végétation et de distance au centre-ville est un exemple de *spline* d'interaction, la première variable étant exprimée en pourcentage et l'autre en mètres. De plus, ces deux variables ne sont pas conjointes, mais bien distinctes l'une de l'autre. Un cas typique où une *spline* multivariée serait à privilégier est le cas de l'ajout des coordonnées spatiales dans le modèle. L'emplacement des AD est mesuré par deux variables (coordonnées spatiales *x* et *y*) toutes les deux exprimées en mètres évoluant conjointement, au sens où les coordonnées *x* n'interagissent pas avec les coordonnées *y*, mais forment à elles deux un espace propre. Au-delà de la problématique de l'échelle des données, il est important de retenir que les *splines* d'interaction tendent à être davantage pénalisées que les splines *multivariées*.\n\nLa *spline* d'interaction représentée à la @fig-gam15 indique que les AD avec la plus grande proportion de leur surface couverte par des îlots de chaleur sont situées à moins de 25 kilomètres du centre-ville, au-delà de cette distance, cette proportion chute en bas de 0,1, soit 10 % de la surface de l'AD. En revanche, à proximité du centre-ville (moins d'un kilomètre), même les AD disposant d'un fort pourcentage de surface végétalisée sont tout de même marquées par un fort pourcentage de surface couverte par des îlots de chaleur.\n\nLes *splines* bivariées sont fréquemment utilisées pour capturer un potentiel patron spatial dans les données. En effet, si nous disposons des coordonnées spatiales de chaque observation (*x, y*), il est possible d'ajuster une *spline* bivariée sur ces coordonnées, contrôlant ainsi l'effet de l'espace. \n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Spline d'interaction bivariée](11-GAM_files/figure-html/fig-gam15-1.png){#fig-gam15 fig-align='center' width=70%}\n:::\n:::\n\n\nIl n'y a pas de limite théorique au nombre de variables qui peuvent être ajoutées dans une *spline* d'interaction ou multivariée. Notez cependant que plus le nombre de dimensions augmente, plus la fonction à estimer est complexe et plus le volume de données nécessaire est grand et doit couvrir densément l'ensemble de l'espace d'échantillonnage multidimensionnel.\n\n## Mise en œuvre dans R {#sec-116}\n\nIl est possible d'ajuster des *splines* de régression dans n'importe quel *package* permettant d'ajuster des coefficients pour un modèle de régression. Il suffit de construire les bases des *splines* en amont à l'aide du *package* `splines2` et de les ajouter directement dans l'équation de régression. \nEn revanche, il est nécessaire d'utiliser des *packages* spécialisés pour ajuster des *splines* de lissage. Parmi ceux-ci, `mgcv` est probablement le plus populaire du fait de sa (très) grande flexibilité, suivi des *packages* `gamlss`, `gam` et `VGAM.` Nous comparons ici les deux approches, puis nous tentons d'améliorer le modèle que nous avons ajusté pour prédire le pourcentage de surface couverte par des îlots de chaleur dans les aires de diffusion de Montréal, dans une perspective d'équité environnementale. Pour rappel, la variable dépendante est exprimée en pourcentage et nous utilisons une distribution bêta pour la modéliser.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(mgcv)\n# Chargement des données\ndataset <- read.csv(\"data/gam/data_chaleur.csv\", fileEncoding = \"utf8\")\n# Ajustement du modèle de base\nrefmodel <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n poly(prt_veg, degree = 2) + Arrond,\n data = dataset, family = betar(link = \"logit\"))\n```\n:::\n\n\nDans notre première analyse de ces données, nous avons ajusté une polynomiale d'ordre 2 pour représenter un potentiel effet non linéaire de la végétation sur les îlots de chaleur. Nous remplaçons à présent ce terme par une *spline* de régression en sélectionnant quatre nœuds.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(splines2)\n# Création des bases de la spline\nbasis <- bSpline(x = dataset$prt_veg, df =4, intercept = FALSE)\n# Ajouter les bases au DataFrame\nbasisdf <- as.data.frame(basis)\nnames(basisdf) <- paste('spline',1:ncol(basisdf), sep='')\ndataset <- cbind(dataset, basisdf)\n# Ajuster le modèle\nmodel0 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n spline1 + spline2 + spline3 + spline4 + Arrond,\n data = dataset, family = betar(link = \"logit\"))\n```\n:::\n\n\nNous pouvons à présent ajuster une *spline* de lissage et laisser `mgcv` déterminer son niveau de complexité.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Ajustement du modèle avec une spline simple\nmodel1 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n s(prt_veg) + Arrond,\n data = dataset, family = betar(link = \"logit\"))\n```\n:::\n\n\nNotez ici que la syntaxe à employer est très simple, il suffit de spécifier `s(prt_veg)` pour indiquer à la fonction `gam` que vous souhaitez ajuster une *spline* pour la variable `prt_veg`. Nous pouvons à présent comparer l'ajustement des deux modèles en utilisant la mesure de l'AIC.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Comparaison des AIC\nAIC(refmodel, model0, model1)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n df AIC\nrefmodel 40.00000 -6399.784\nmodel0 42.00000 -6419.630\nmodel1 44.61065 -6417.562\n```\n:::\n:::\n\n\nNous constatons que la valeur de l'AIC du second modèle est plus réduite, indiquant un meilleur ajustement du modèle avec une *spline* de régression. Notons cependant que la différence avec la *spline* de lissage est anecdotique (deux points de l'AIC) et que nous connaissions a priori le bon nombre de nœuds à utiliser. Pour des relations plus complexes, les *splines* de lissage ont tendance à nettement mieux performer. Voyons à présent comment représenter ces trois termes non linéaires.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Création d'un DataFrame de prédiction dans lequel seule\n# la variable prt_veg varie.\ndfpred <- data.frame(\n prt_veg = seq(min(dataset$prt_veg), max(dataset$prt_veg), 0.5),\n A65Pct = mean(dataset$A65Pct),\n A014Pct = mean(dataset$A014Pct),\n PopFRPct = mean(dataset$PopFRPct),\n PopMVPct = mean(dataset$PopMVPct),\n Arrond = \"Verdun\"\n)\n\n# Recréation des bases de la spline de régression\n# pour les nouvelles observations\nnvl_bases <- data.frame(predict(basis, newx = dfpred$prt_veg))\nnames(nvl_bases) <- paste('spline',1:ncol(basisdf), sep='')\ndfpred <- cbind(dfpred, nvl_bases)\n\n# Définition de la fonction inv.logit, soit l'inverse de la fonction \n# de lien du modèle pour retrouver les prédictions dans l'échelle \n# originales des données\ninv.logit <- function(x){exp(x)/(1+exp(x))}\n\n# Utilisation des deux modèles pour effectuer les prédictions\npredref <- predict(refmodel, newdata = dfpred, type = 'link', se.fit = TRUE)\npredmod0 <- predict(model0, newdata = dfpred, type = 'link', se.fit = TRUE)\npredmod1 <- predict(model1, newdata = dfpred, type = 'link', se.fit = TRUE)\n\n# Calcul de la valeur prédite et construction des intervalles de confiance\ndfpred$polypred <- inv.logit(predref$fit)\ndfpred$poly025 <- inv.logit(predref$fit - 1.96 * predref$se.fit)\ndfpred$poly975 <- inv.logit(predref$fit + 1.96 * predref$se.fit)\n\ndfpred$regsplinepred <- inv.logit(predmod0$fit)\ndfpred$regspline025 <- inv.logit(predmod0$fit - 1.96 * predmod0$se.fit)\ndfpred$regspline975 <- inv.logit(predmod0$fit + 1.96 * predmod0$se.fit)\n\ndfpred$splinepred <- inv.logit(predmod1$fit)\ndfpred$spline025 <- inv.logit(predmod1$fit - 1.96 * predmod1$se.fit)\ndfpred$spline975 <- inv.logit(predmod1$fit + 1.96 * predmod1$se.fit)\n\n# Créer un graphique pour afficher les résultats\nggplot(dfpred) + \n geom_ribbon(aes(x = prt_veg, ymin = poly025, ymax = poly975),\n alpha = 0.4, color = \"grey\") +\n geom_ribbon(aes(x = prt_veg, ymin = spline025, ymax = spline975),\n alpha = 0.4, color = \"grey\") +\n geom_ribbon(aes(x = prt_veg, ymin = regspline025, ymax = regspline975),\n alpha = 0.4, color = \"grey\") +\n geom_line(aes(y = polypred, x = prt_veg, color = \"polynomiale\"),\n linewidth = 1) + \n geom_line(aes(y = regsplinepred, x = prt_veg, color = \"spline de régression\"),\n linewidth = 1)+\n geom_line(aes(y = splinepred, x = prt_veg, color = \"spline de lissage\"),\n linewidth = 1)\n```\n\n::: {.cell-output-display}\n![Comparaison d'une spline et d'une polynomiale](11-GAM_files/figure-html/fig-gam16-1.png){#fig-gam16 fig-align='center' width=75%}\n:::\n:::\n\n\nNous constatons que les trois termes renvoient des prédictions très similaires et qu'une légère différence n'est observable que pour les secteurs avec les plus hauts niveaux de végétation (supérieurs à 75 %).\n\nJusqu'ici, nous utilisons l'arrondissement dans lequel est comprise chaque aire de diffusion comme une variable nominale afin de capturer la dimension spatiale du jeu de données. Puisque nous avons abordé la notion de *splines* bivariées, il serait certainement plus efficace d'en construire une à partir des coordonnées géographiques (*x*,*y*) des centroïdes des aires de diffusion. En effet, il est plus probable que la distribution des îlots de chaleur suive un patron spatial continu sur le territoire plutôt que les délimitations arbitraires des arrondissements.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Ajustement du modèle avec une spline bivariée pour l'espace\nmodel2 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n s(prt_veg) + s(X,Y),\n data = dataset, family = betar(link = \"logit\"))\n```\n:::\n\n\nNotez ici que l'expression `s(X,Y)` permet de créer une *spline* bivariée à partir des coordonnées (*x, y*), soit deux colonnes présentes dans le jeu de données. Ces coordonnées sont exprimées toutes deux en mètres et n'interagissent pas ensemble au sens strict, nous devons donc ajuster une *spline* bivariée. Si vous avez besoin d'ajuster une *spline* d'interaction (notamment quand les variables sont dans des unités différentes), il est nécessaire d'utiliser une autre syntaxe `te(X,Y)` ou `t2(X,Y)` faisant appel à une structure mathématique légèrement différente, soit des *tensor product smooths*.\n\nPuisque notre modèle intègre deux *splines*, nous devons nous assurer que nous n'avons pas de problème de concurvité, ce que nous pouvons faire avec la fonction `concurvity` du *package* `mgcv`. \n\n\n::: {.cell}\n\n```{.r .cell-code}\nvalues <- concurvity(model2, full = FALSE)\n\n# Worst, estimation pessimiste de la concurvité\nround(values$worst,3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n para s(prt_veg) s(X,Y)\npara 1 0.000 0.000\ns(prt_veg) 0 1.000 0.458\ns(X,Y) 0 0.458 1.000\n```\n:::\n\n```{.r .cell-code}\n# Observed, estimation optimiste de la concurvité\nround(values$observed,3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n para s(prt_veg) s(X,Y)\npara 1 0.000 0.000\ns(prt_veg) 0 1.000 0.154\ns(X,Y) 0 0.403 1.000\n```\n:::\n\n```{.r .cell-code}\n# Estimate, estimation entre deux de la concurvité\nround(values$estimate,3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n para s(prt_veg) s(X,Y)\npara 1 0.000 0.000\ns(prt_veg) 0 1.000 0.142\ns(X,Y) 0 0.358 1.000\n```\n:::\n:::\n\n\nNous pouvons ainsi constater des niveaux de concurvité tout à fait acceptables dans notre modèle. Des valeurs supérieures à 0,8 devraient être considérées comme alarmantes, surtout si elles sont reportées pour `observed` et `estimate`.\n\nVoyons désormais, le résumé d'un modèle GAM tel que présenté dans R.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nsummary(model2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nFamily: Beta regression(15.469) \nLink function: logit \n\nFormula:\nhot ~ A65Pct + A014Pct + PopFRPct + PopMVPct + s(prt_veg) + s(X, \n Y)\n\nParametric coefficients:\n Estimate Std. Error z value Pr(>|z|) \n(Intercept) -0.6050031 0.0645191 -9.377 < 2e-16 ***\nA65Pct 0.0027671 0.0014072 1.966 0.0493 * \nA014Pct -0.0019040 0.0027674 -0.688 0.4914 \nPopFRPct 0.0095992 0.0014323 6.702 2.06e-11 ***\nPopMVPct 0.0010113 0.0008159 1.239 0.2152 \n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\nApproximate significance of smooth terms:\n edf Ref.df Chi.sq p-value \ns(prt_veg) 6.38 7.565 6731 <2e-16 ***\ns(X,Y) 27.10 28.764 1349 <2e-16 ***\n---\nSignif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1\n\nR-sq.(adj) = 0.891 Deviance explained = 90.8%\n-REML = -3234.3 Scale est. = 1 n = 3157\n```\n:::\n:::\n\n\nLa première partie du résumé comprend les résultats pour les effets fixes et linéaires du modèle. Ils s'interprètent comme pour ceux d'un GLM classique. La seconde partie présente les résultats pour les termes non linéaires. La valeur de *p* permet de déterminer si la *spline* a ou non un effet différent de 0. Une valeur non significative indique que la *spline* ne contribue pas au modèle. Les colonnes *edf* et *Ref.df* indiquent la complexité de la *spline* et peuvent être considérées comme une approximation du nombre de nœuds. Dans notre cas, la *spline* spatiale (`s(X,Y)`) est environ 5 fois plus complexe que la *spline* ajustée pour la végétation (`s(prt_veg)`). Cela n'est pas surprenant puisque la dimension spatiale (*spline* bivariée) du phénomène est certainement plus complexe que l’effet de la végétation. Notez ici que des valeurs *edf* et *Ref.df* proches de 1 signaleraient que l'effet d’un prédicteur est essentiellement linéaire et qu'il n'est pas nécessaire de recourir à une *spline* pour cette variable.\n\nLa dernière partie du résumé comprend deux indicateurs de qualité d'ajustement, soit le R^2^ ajusté et la part de la déviance expliquée.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nAIC(refmodel, model1, model2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n df AIC\nrefmodel 40.00000 -6399.784\nmodel1 44.61065 -6417.562\nmodel2 40.06053 -6596.884\n```\n:::\n:::\n\n\nNous pouvons constater que le fait d'introduire la *spline* spatiale dans le modèle contribue à réduire encore la valeur de l'AIC, et donc à améliorer le modèle. À ce stade, nous pourrions tenter de forcer la *spline* à être plus complexe en augmentant le nombre de nœuds.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Augmentation de la complexité de la spline spatiale\nmodel3 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n s(prt_veg) + s(X,Y,k = 40),\n data = dataset, family = betar(link = \"logit\"))\n\nAIC(refmodel, model1, model2, model3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n df AIC\nrefmodel 40.00000 -6399.784\nmodel1 44.61065 -6417.562\nmodel2 40.06053 -6596.884\nmodel3 48.28633 -6639.955\n```\n:::\n:::\n\n\nCela a pour effet d'améliorer de nouveau le modèle. Pour vérifier si l'augmentation du nombre nœuds est judicieuse, il est possible de représenter le résultat des deux *splines* précédentes. Pour ce faire, nous proposons de calculer les valeurs prédites de la *spline* pour chaque localisation dans notre terrain d'étude, en le découpant préalablement en pixels de 100 de côté. Pour cette prédiction, nous maintenons toutes les autres variables à leur moyenne respective afin d'évaluer uniquement l'effet de la *spline* spatiale.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(viridis)\nlibrary(metR) # pour placer des étiquettes sur les isolignes\n\n# Création d'un DataFrame fictif pour les prédictions\ndfpred <- expand.grid(\n prt_veg =mean(dataset$prt_veg),\n A65Pct = mean(dataset$A65Pct),\n A014Pct = mean(dataset$A014Pct),\n PopFRPct = mean(dataset$PopFRPct),\n PopMVPct = mean(dataset$PopMVPct),\n X = seq(min(dataset$X), max(dataset$X),100),\n Y = seq(min(dataset$Y), max(dataset$Y),100)\n)\n\ndfpred$predicted1 <- predict(model2, newdata = dfpred, type = 'response')\ndfpred$predicted2 <- predict(model3, newdata = dfpred, type = 'response')\n\n# Centrage des prédictions\ndfpred$predicted1 <- dfpred$predicted1 - mean(dfpred$predicted1)\ndfpred$predicted2 <- dfpred$predicted2 - mean(dfpred$predicted2)\n\n# Représentation des splines\nplot1 <- ggplot(dfpred) + \n geom_raster(aes(x = X, y = Y, fill = predicted1)) + \n geom_point(aes(x = X, y = Y),\n size = 0.2, alpha = 0.4,\n color = \"black\", data = dataset)+\n geom_contour(aes(x = X, y = Y, z = predicted1), binwidth = 0.1, \n color = \"white\", linetype = 'dashed') + \n geom_text_contour(aes(x = X, y = Y, z = predicted1), \n color = \"white\", binwidth = 0.1)+\n scale_fill_viridis() +\n coord_cartesian() + \n theme(axis.title= element_blank(),\n axis.text = element_blank(),\n axis.ticks = element_blank()\n ) + \n labs(subtitle = \"spline de base\", fill = \"prédictions\")\n\nplot2 <- ggplot(dfpred) + \n geom_raster(aes(x = X, y = Y, fill = predicted2)) + \n geom_point(aes(x = X, y = Y),\n size = 0.2, alpha = 0.4,\n color = \"black\", data = dataset)+\n geom_contour(aes(x = X, y = Y, z = predicted2),\n binwidth = 0.1, color = \"white\", linetype = 'dashed') + \n geom_text_contour(aes(x = X, y = Y, z = predicted2), color = \"white\", binwidth = 0.1)+\n scale_fill_viridis() +\n coord_cartesian()+ \n theme(axis.title= element_blank(),\n axis.text = element_blank(),\n axis.ticks = element_blank()\n ) + \n labs(subtitle = \"spline plus complexe\", fill = \"prédictions\")\n\nggarrange(plot1, plot2, nrow = 1, ncol = 2, common.legend = TRUE, legend = 'bottom')\n```\n\n::: {.cell-output-display}\n![Comparaison de deux splines spatiales](11-GAM_files/figure-html/fig-gam17-1.png){#fig-gam17 fig-align='center' width=100%}\n:::\n:::\n\n\nOr, il s'avère que les deux *splines* spatiales sont très similaires (@fig-gam17). Par conséquent, il est vraisemblablement plus pertinent de conserver la plus simple des deux. Notez que le Mont-Royal, compris dans le cercle central avec une isoligne à 0, est caractérisé par des valeurs plus faibles d'îlots de chaleur, alors que les quartiers centraux situés un peu plus au nord sont au contraire marqués par des pourcentages d'îlots de chaleur supérieurs de 20 points de pourcentage en moyenne.\n\n## GAMM {#sec-117}\n\nBien entendu, il est possible de combiner les modèles généralisés additifs (GAM) avec les modèles à effet mixtes (GLMM) abordés dans les sections précédentes. Ces modèles généralisés additifs à effets mixtes (GAMM) peuvent facilement être mis en œuvre avec `mgcv`.\n\n#### GAMM et interceptes aléatoires {#sec-1171}\n\nPour définir des constantes aléatoires, il suffit d'utiliser la notation `s(var, bs = 're')` avec `var` une variable nominale. Reprenons l'exemple précédent, mais avec cette fois-ci les arrondissements comme un intercepte aléatoire.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndataset$Arrond <- as.factor(dataset$Arrond)\nmodel4 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n s(prt_veg) + s(Arrond, bs = \"re\"),\n data = dataset, family = betar(link = \"logit\"))\n```\n:::\n\n\nL'enjeu est ensuite d'extraire la variance propre à cet effet aléatoire ainsi que les valeurs des interceptes pour chaque arrondissement.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ngam.vcomp(model4)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nStandard deviations and 0.95 confidence intervals:\n\n std.dev lower upper\ns(prt_veg) 0.007047166 0.003785275 0.01311993\ns(Arrond) 0.393539474 0.302707198 0.51162747\n\nRank: 2/2\n```\n:::\n:::\n\n\nNous constatons donc que l'écart-type de l'effet aléatoire des arrondissements est de 0,39, ce qui signifie que les effets de chaque arrondissement seront compris à 95 % entre -1,17 et 1,17 (`1.17 = 3*0.39`) sur l'échelle du prédicteur linéaire. En effet, rappelons que les effets aléatoires sont modélisés comme des distributions normales et que 95 % de la densité d'une distribution normale se situe entre -3 et +3 écarts-types. Pour extraire les interceptes spécifiques de chaque arrondissement, nous pouvons utiliser la fonction `get_random` du *package* `itsadug.`\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(itsadug)\nvalues <- get_random(model4)[[1]]\ndf <- data.frame(\n ri = as.numeric(values),\n arrond = names(values)\n)\n\nggplot(df) + \n geom_point(aes(x = ri, y = reorder(arrond, ri))) + \n geom_vline(xintercept = 0, color = \"red\") + \n labs(y = \"Arrondissement\", x = \"intercepte aléatoire\")\n```\n\n::: {.cell-output-display}\n![Constantes aléatoires pour les arrondissements](11-GAM_files/figure-html/fig-randomconstGAM-1.png){#fig-randomconstGAM width=672}\n:::\n:::\n\n\nNous constatons ainsi, à la @fig-randomconstGAM, que pour une partie des arrondissements, la densité d'îlot de chaleur est systématiquement supérieure à la moyenne régionale représentée ici par la ligne rouge (0 = effet moyen pour tous les arrondissements). Il convient alors d’améliorer ce graphique en ajoutant le niveau d'incertitude associé à chaque intercepte. Pour ce faire, nous utilisons la fonction `extract_random_effects` du *package* `mixedup.` Notez que ce *package* n'est actuellement pas disponible sur CRAN et doit être téléchargé sur **github** avec la commande suivante :\n\n\n::: {.cell}\n\n```{.r .cell-code}\nremotes::install_github('m-clark/mixedup')\n```\n:::\n\n\nAvec la version 4.0.1 de R, nous avons rencontré des difficultés pour installer `mixedup`. Nous avons donc simplement récupéré le code source de la fonction et l'avons enregistré dans un fichier de code séparé que nous appelons ici.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nsource(\"code_complementaire/gam_functions.R\")\n```\n:::\n\n\nNous pouvons ensuite procéder à l'extraction des effets aléatoires et les représenter à nouveau (@fig-randomconstGAM2).\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf_re <- extract_random_effects.gam(model4, re = \"Arrond\")\n\nggplot(df_re) + \n geom_errorbarh(aes(xmin = lower_2.5, xmax = upper_97.5, y = reorder(group, value))) +\n geom_point(aes(x = value, y = reorder(group, value))) + \n geom_vline(xintercept = 0, color = \"red\") + \n labs(y = \"Arrondissement\", x = \"Intercepte aléatoire\")\n```\n\n::: {.cell-output-display}\n![Constantes aléatoires pour les arrondissements avec intervalle de confiance](11-GAM_files/figure-html/fig-randomconstGAM2-1.png){#fig-randomconstGAM2 width=672}\n:::\n:::\n\n\nCela permet de distinguer quels écarts sont significativement différents de 0 au seuil de 95 %. À titre de rappel, pour être significatif à ce seuil, un intervalle représenté par une ligne noire horizontale ne doit pas intersecter la ligne rouge verticale. Puisque nous utilisons ici la distribution bêta et une fonction de lien logistique, nous devons utiliser des prédictions pour simplifier l'interprétation des coefficients. Nous fixons ici toutes les variables à leur moyenne respective, sauf l'arrondissement, et calculons les prédictions dans l'échelle originale (0 à 1).\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndfpred <- data.frame(\n A65Pct = mean(dataset$A65Pct),\n A014Pct = mean(dataset$A014Pct),\n PopFRPct = mean(dataset$PopFRPct),\n PopMVPct = mean(dataset$PopMVPct),\n prt_veg = mean(dataset$prt_veg),\n Arrond = as.character(unique(dataset$Arrond))\n)\n\n# Calculer les prédictions pour le prédicteur linéaire\ndfpred$preds <- predict(model4, newdata = dfpred, type = \"link\")\n\n# Calculer l'intervalle de confiance en utilisant les valeurs\n# extraites avec extract_random_effects\ndfpred <- dfpred[order(dfpred$Arrond),]\ndf_re <- df_re[order(df_re$group),]\n\ndfpred$lower <- dfpred$preds - 1.96*df_re$se\ndfpred$upper <- dfpred$preds + 1.96*df_re$se\n\n# Il nous reste juste à reconvertir le tout dans l'unité d'origine\n# en utilisant l'inverse de la fonction logistique\ninv.logit <- function(x){exp(x)/(1+exp(x))}\n\ndfpred$lower <- inv.logit(dfpred$lower)\ndfpred$upper <- inv.logit(dfpred$upper)\ndfpred$preds <- inv.logit(dfpred$preds)\n\nggplot(dfpred) + \n geom_errorbarh(aes(xmin = lower, xmax = upper, y = reorder(Arrond, preds))) +\n geom_point(aes(x = preds, y = reorder(Arrond, preds))) + \n geom_vline(xintercept = mean(dfpred$preds), color = \"red\") + \n labs(y = \"Arrondissement\", x = \"intercepte aléatoire\")\n```\n\n::: {.cell-output-display}\n![Prédictions pour les différents arrondissements pour une AD fictive moyenne](11-GAM_files/figure-html/fig-randomconstGAM3-1.png){#fig-randomconstGAM3 width=672}\n:::\n:::\n\n\nNous constatons ainsi, à la @fig-randomconstGAM3, que pour une hypothétique aire de diffusion moyenne, la différence de densité d'îlot de chaleur peut être de 0,32 (32 % de la surface de l'AD) entre les arrondissements Verdun et Dollard-des-Ormeaux.\n\n#### GAMM et coefficients aléatoires {#sec-1172}\n\nEn plus des interceptes aléatoires, il est aussi possible de définir des coefficients aléatoires. Reprenons notre exemple et tentons de faire varier l'effet de la variable `PopFRPct` en fonction de l'arrondissement.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nmodel5 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n s(prt_veg) + s(Arrond, bs = \"re\") + \n s(PopFRPct, Arrond, bs = \"re\"),\n data = dataset, family = betar(link = \"logit\"))\n```\n:::\n\n\nNotez ici une distinction importante! Le modèle n'assume aucune corrélation entre les coefficients aléatoires pour la variable `PopFRPct` et pour les constantes aléatoires. Il est présumé que ces deux effets proviennent de deux distributions normales distinctes. En d'autres termes, le modèle ne dispose pas des paramètres nécessaires pour vérifier si les arrondissements avec les constantes les plus fortes (avec des densités supérieures d'îlot de chaleur) sont aussi des arrondissements dans lesquels l'effet de la variable `PopFRPct` est plus prononcé (et vice-versa). Pour plus d'informations sur cette distinction, référez-vous à la [section @sec-0924].\n\n\n::: {.cell}\n\n```{.r .cell-code}\nAIC(model4, model5)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n df AIC\nmodel4 41.54635 -6421.791\nmodel5 56.84734 -6466.726\n```\n:::\n:::\n\n\nCe dernier modèle présente une valeur de l'AIC plus faible et serait donc ainsi mieux ajusté que notre modèle avec seulement un intercepte aléatoire. Nous pouvons donc extraire les coefficients aléatoires et les représenter à la @fig-randomconstcoefGAM.\n\n\n::: {.cell}\n\n```{.r .cell-code}\ndf_re <- extract_random_effects.gam(model5)\ndf_re <- subset(df_re, df_re$effect == 'PopFRPct')\n\nggplot(df_re) + \n geom_errorbarh(aes(xmin = lower_2.5, xmax = upper_97.5, y = reorder(group, value))) +\n geom_point(aes(x = value, y = reorder(group, value))) + \n geom_vline(xintercept = 0, color = \"red\") + \n labs(y = \"Arrondissement\", x = \"coefficient aléatoire\")\n```\n\n::: {.cell-output-display}\n![Pentes et constantes aléatoires pour les arrondissements](11-GAM_files/figure-html/fig-randomconstcoefGAM-1.png){#fig-randomconstcoefGAM width=672}\n:::\n:::\n\n\nNous constatons notamment que seuls trois arrondissements ont des coefficients aléatoires significativement différents de 0. Ainsi, pour les arrondissements Anjou et Plateau-Mont-Royal, les coefficients aléatoires sont respectivement de -0,013 et -0,015, et viennent donc se retrancher à la valeur moyenne régionale de 0,0154 qui atteint alors presque 0. Du point de vue de l'interprétation, nous pouvons en conclure que le groupe des personnes à faible revenu ne subit pas de surexposition aux îlots de chaleur à l'échelle des AD dans ces arrondissements.\n\nEn revanche, dans l'arrondissement Mercier-Hochelaga-Maisonneuve, la situation est à l'inverse plus systématiquement en défaveur des populations à faible revenu, avec une taille d'effet près de deux fois supérieure à la moyenne régionale. En effet, l'effet moyen régional (coefficient fixe) est de 0,0154, auquel vient s'ajouter l'effet spécifique (coefficient aléatoire) de Mercier-Hochelaga-Maisonneuve, soit 0,011, pour un effet total de 0,0264\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Des effets aléatoires plus complexes dans les GAMM**\n:::\n::: bloc_aller_loin-body\nIl est possible de spécifier des GAMM avec des effets aléatoires plus complexes autorisant, par exemple, des corrélations entre les différents effets / niveaux. Il faut pour cela utiliser la fonction `gamm` de `mgcv` ou la fonction `gamm4` du *package* `gamm4.` La première offre plus de flexibilité, mais la seconde est plus facile à utiliser et doit être privilégiée quand un modèle comporte un très grand nombre de groupes dans un effet aléatoire, ou lorsque la distribution du modèle n'est pas gaussienne. La fonction `gamm` permet d'ajuster des modèles non gaussiens, mais elle utilise une approche appelée PQL (*Penalized Quasi-Likelihood* en anglais) connue pour être moins stable et moins précise.\n\nCependant, dans l'exemple de cette section, nous utilisons un modèle GAMM avec une distribution bêta, ce qui n'est actuellement pas supporté par les fonctions `gamm` et `gamm4`. Pour un modèle GAMM plus complexe utilisant une distribution bêta, il est nécessaire d'utiliser le *package* `gamlss`, mais ce dernier utilise aussi une approche de type PQL. Nous montrons tout de même ici comment ajouter un modèle qui inclut une corrélation entre les deux effets aléatoires de l'exemple précédent. Notez ici que le terme `re` apparaissant dans la formule permet de spécifier un effet aléatoire en utilisant la syntaxe du *package* `nlme.` Plus spécifiquement, `gamlss` fait un pont avec `nlme` et utilise son algorithme d'ajustement au sein de ces propres routines. De même, le terme `pb` permet de spécifier une *spline* de lissage dans le même esprit que `mgcv.` Il est également possible d'utiliser le terme `ga` faisant le lien avec `mgcv` et de profiter de sa flexibilité dans `gamlss`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(gamlss)\nlibrary(gamlss.add)\n\nmodel6 <- gamlss(hot ~\n pb(prt_veg) + \n re(fixed = ~ A65Pct + A014Pct + PopFRPct + PopMVPct, \n random = ~(1 + PopFRPct)|Arrond),\n data = dataset, family = BE(mu.link = \"logit\"))\n```\n:::\n\n\nNous pouvons ensuite accéder à la partie du modèle qui nous intéresse, soit celle concernant les effets aléatoires.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nrandomPart <- model6$mu.coefSmo[[2]]\nprint(randomPart)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLinear mixed-effects model fit by maximum likelihood\n Data: Data \n Log-likelihood: -2964.494\n Fixed: fix.formula \n (Intercept) A65Pct A014Pct PopFRPct PopMVPct \n-0.060862840 -0.001945204 -0.010139278 0.017259606 -0.002599745 \n\nRandom effects:\n Formula: ~(1 + PopFRPct) | Arrond\n Structure: General positive-definite, Log-Cholesky parametrization\n StdDev Corr \n(Intercept) 0.47298363 (Intr)\nPopFRPct 0.01078909 -0.646\nResidual 0.99888012 \n\nVariance function:\n Structure: fixed weights\n Formula: ~W.var \nNumber of Observations: 3157\nNumber of Groups: 33 \n```\n:::\n:::\n\n\n\nÀ lecture de la partie du résumé consacrée aux résultats pour les effets aléatoires, nous constatons que la corrélation entre les interceptes aléatoires et les coefficients aléatoires est de -0,65. Cela signifie que pour les arrondissements avec des interceptes élevés (plus grande proportion d'îlots de chaleur), l'effet de la variable `PopFRPct` tend à être plus faible. Autrement dit, dans les arrondissements avec beaucoup d'îlots de chaleur, les personnes à faible revenu ont tendance à être moins exposées, tel qu'illustré à la @fig-corrrandom).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndf <- ranef(randomPart)\ndf$arrond <- rownames(df)\nnames(df) <- c('Intercept', 'PopFRPct', 'Arrondissement')\n\nggplot(df) + \n geom_hline(yintercept = 0, color = \"red\") +\n geom_vline(xintercept = 0, color = \"red\") +\n geom_point(aes(x = Intercept, y = PopFRPct))\n```\n\n::: {.cell-output-display}\n![Relation entre les effets aléatoires des arrondissements et la variable population à faible revenu](11-GAM_files/figure-html/fig-corrrandom-1.png){#fig-corrrandom fig-align='center' width=75%}\n:::\n:::\n\n:::\n:::\n\n## Quiz de révision du chapitre {#sec-118}\n\n\n
\n\n\n\n
\n
Que signifie l'acronyme GAM?
\n
Relisez l'introduction du [chapitre @sec-chap11] au besoin.
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quel est l'intérêt d'un modèle GAM comparativement à un modèle GLM?
\n
Relisez au besoin la [section @sec-111].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Une spline ajustée sur une variable X dans un GAM est construite comme :
\n
Relisez au besoin la [section @sec-1114].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Le degré de complexité d'une spline est contrôlé par :
\n
Relisez au besoin la [section @sec-1114].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Le nombre de nœuds d'une spline peut être :
\n
Relisez au besoin la [section @sec-113].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Une spline bivariée est un autre nom pour une spline d'interaction.
\n
Relisez au besoin la [section @sec-115].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Une spline peut être ajustée sur plus que deux variables X simultanément.
\n
Relisez au besoin la [section @sec-115].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Pour interpréter les résultats d'une spline, il est possible de :
\n
Relisez au besoin la [section @sec-114].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n\n
\n\n
\n
\n", + "supporting": [ + "11-GAM_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/11-GAM_files/figure-html/fig-corrrandom-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-corrrandom-1.png similarity index 100% rename from docs/11-GAM_files/figure-html/fig-corrrandom-1.png rename to .quarto/_freeze/11-GAM/figure-html/fig-corrrandom-1.png diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam10-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam10-1.png new file mode 100644 index 0000000..70dba1b Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam10-1.png differ diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam11-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam11-1.png new file mode 100644 index 0000000..02650ec Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam11-1.png differ diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam12-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam12-1.png new file mode 100644 index 0000000..5ba3fc3 Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam12-1.png differ diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam13-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam13-1.png new file mode 100644 index 0000000..9a8cfe6 Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam13-1.png differ diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam14-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam14-1.png new file mode 100644 index 0000000..a0b1099 Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam14-1.png differ diff --git a/docs/11-GAM_files/figure-html/fig-gam15-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam15-1.png similarity index 100% rename from docs/11-GAM_files/figure-html/fig-gam15-1.png rename to .quarto/_freeze/11-GAM/figure-html/fig-gam15-1.png diff --git a/docs/11-GAM_files/figure-html/fig-gam16-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam16-1.png similarity index 100% rename from docs/11-GAM_files/figure-html/fig-gam16-1.png rename to .quarto/_freeze/11-GAM/figure-html/fig-gam16-1.png diff --git a/docs/11-GAM_files/figure-html/fig-gam17-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam17-1.png similarity index 100% rename from docs/11-GAM_files/figure-html/fig-gam17-1.png rename to .quarto/_freeze/11-GAM/figure-html/fig-gam17-1.png diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam2-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam2-1.png new file mode 100644 index 0000000..9a9046f Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam2-1.png differ diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam3-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam3-1.png new file mode 100644 index 0000000..22b60b7 Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam3-1.png differ diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam4-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam4-1.png new file mode 100644 index 0000000..d389dda Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam4-1.png differ diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam5-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam5-1.png new file mode 100644 index 0000000..c66fb83 Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam5-1.png differ diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam6-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam6-1.png new file mode 100644 index 0000000..9813a4e Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam6-1.png differ diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam7-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam7-1.png new file mode 100644 index 0000000..551caa2 Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam7-1.png differ diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam8-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam8-1.png new file mode 100644 index 0000000..db4c519 Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam8-1.png differ diff --git a/.quarto/_freeze/11-GAM/figure-html/fig-gam9-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-gam9-1.png new file mode 100644 index 0000000..e7b9629 Binary files /dev/null and b/.quarto/_freeze/11-GAM/figure-html/fig-gam9-1.png differ diff --git a/docs/11-GAM_files/figure-html/fig-randomconstGAM-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-randomconstGAM-1.png similarity index 100% rename from docs/11-GAM_files/figure-html/fig-randomconstGAM-1.png rename to .quarto/_freeze/11-GAM/figure-html/fig-randomconstGAM-1.png diff --git a/docs/11-GAM_files/figure-html/fig-randomconstGAM2-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-randomconstGAM2-1.png similarity index 100% rename from docs/11-GAM_files/figure-html/fig-randomconstGAM2-1.png rename to .quarto/_freeze/11-GAM/figure-html/fig-randomconstGAM2-1.png diff --git a/docs/11-GAM_files/figure-html/fig-randomconstGAM3-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-randomconstGAM3-1.png similarity index 100% rename from docs/11-GAM_files/figure-html/fig-randomconstGAM3-1.png rename to .quarto/_freeze/11-GAM/figure-html/fig-randomconstGAM3-1.png diff --git a/docs/11-GAM_files/figure-html/fig-randomconstcoefGAM-1.png b/.quarto/_freeze/11-GAM/figure-html/fig-randomconstcoefGAM-1.png similarity index 100% rename from docs/11-GAM_files/figure-html/fig-randomconstcoefGAM-1.png rename to .quarto/_freeze/11-GAM/figure-html/fig-randomconstcoefGAM-1.png diff --git a/.quarto/_freeze/12-AnalysesFactorielles/execute-results/html.json b/.quarto/_freeze/12-AnalysesFactorielles/execute-results/html.json new file mode 100644 index 0000000..a36adfd --- /dev/null +++ b/.quarto/_freeze/12-AnalysesFactorielles/execute-results/html.json @@ -0,0 +1,20 @@ +{ + "hash": "354cbb2690bca74b987a0c84eb2ee3c0", + "result": { + "markdown": "# Méthodes factorielles {#sec-chap12}\n\nDans le cadre de ce chapitre, nous présentons les trois méthodes factorielles les plus utilisées en sciences sociales : l'analyse en composantes principales (ACP, [section @sec-122]), l'analyse factorielle des correspondances (AFC, [section @sec-123]) et l'analyse factorielle des correspondances multiples (ACM, [section @sec-124]). Ces méthodes, qui permettent d'explorer et de synthétiser l'information de différents tableaux de données, relèvent de la statistique exploratoire multidimensionnelle.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques.\n* Pour les analyses factorielles :\n - `FactoMineR` pour réaliser une ACP, une AFC et une ACM.\n - `factoextra` pour réaliser des graphiques à partir des résultats d'une analyse factorielle.\n - `explor` pour les résultats d'une ACP, d'une AFC ou d'une ACM avec une interface Web interactive.\n* Autres *packages* :\n - `geocmeans` pour un jeu de données utilisé pour calculer une ACP.\n - `ggplot2`, `ggpubr`, `stringr` et `corrplot` pour réaliser des graphiques personnalisés sur les résultats d'une analyse factorielle.\n - `tmap` et `RColorBrewer` pour cartographier les coordonnées factorielles.\n - `Hmisc` pour l'obtention d'une matrice de corrélation.\n:::\n:::\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Réduction de données et identification de variables latentes**\n:::\n::: bloc_objectif-body\nLes méthodes factorielles sont souvent dénommées des **méthodes de réduction de données**, en raison de leur objectif principal : résumer l'information d'un tableau en quelques nouvelles variables synthétiques (@fig-AnalysesFactoriellesFig). Ainsi, elles permettent de réduire l'information d'un tableau volumineux — comprenant par exemple 1000 observations et 100 variables — en *p* nouvelles variables (par exemple cinq avec toujours 1000 observations) résumant *X* % de l'information contenue dans le tableau initial. Lebart et al. [-@lebart1995statistique, p.13] proposent une formulation plus mathématique : ils signalent qu'avec les méthodes factorielles, « on cherche à réduire les dimensions du tableau de données en représentant les associations entre individus et entre variables dans des espaces de faibles dimensions ».\n\n![Principe de base des analyses factorielles](images/Chap12/AnalysesFactorielles.png){#fig-AnalysesFactoriellesFig width=\"40%\" fig-align=\"center\"}\n\n\nCes nouvelles variables synthétiques peuvent être considérées comme des **variables latentes** puisqu’elles ne sont pas directement observées; elles sont plutôt produites par la méthode factorielle utilisée afin de résumer les relations/associations entre plusieurs variables mesurées initialement.\n:::\n:::\n\n## Aperçu des méthodes factorielles {#sec-121}\n\n### Méthodes factorielles et types de données {#sec-1211}\n\nEn analyse factorielle, la nature même des données du tableau à traiter détermine la méthode à employer : l’analyse en composantes principales (ACP) est adaptée aux tableaux avec des variables continues (idéalement normalement distribuées), l’analyse factorielle des correspondances (AFC) s’applique à des tableaux de contingence tandis que l’analyse des correspondances multiples (ACM) permet de résumer des tableaux avec des données qualitatives (issues d'un sondage par exemple) (@tbl-typesanalysesfactorielles). Sachez toutefois qu'il existe d'autres méthodes factorielles qui ne sont pas abordées dans ce chapitre, notamment : l'analyse factorielle de données mixtes (AFDM) permettant d'explorer des tableaux avec à la fois des variables continues et des variables qualitatives et l'analyse factorielle multiple hiérarchique (AFMH) permettant de traiter des tableaux avec une structure hiérarchique. Pour s'initier à ces deux autres méthodes factorielles plus récentes, consultez notamment l'excellent ouvrage de Jérôme Pagès [-@pages2013analyse].\n\n\n::: {#tbl-typesanalysesfactorielles .cell tbl-cap='Trois principales méthodes factorielles'}\n::: {.cell-output-display}\n|Méthode factorielle |Abr. |Type de données |Type de distance |\n|:-------------------------------------------------|:----|:----------------------|:--------------------|\n|Analyse en composantes principales |ACP |Variables continues |Distance euclidienne |\n|Analyse factorielle des correspondances |AFC |Tableau de contingence |Distance du khi-deux |\n|Analyse factorielle des correspondances multiples |ACM |Variables qualitatives |Distance du khi-deux |\n:::\n:::\n\n\n### Bref historique des méthodes factorielles {#sec-1212}\n\nIl existe une longue tradition de l'utilisation des méthodes factorielles dans le monde universitaire francophone puisque plusieurs d'entre elles ont été proposées par des statisticiens et des statisticiennes francophones à partir des années 1960. L’analyse en composantes principales (ACP) a été proposée dès les années 1930 par le statisticien américain Harold Hotelling [-@hotelling1933analysis]. En revanche, l’analyse des correspondances (AFC) et son extension, l’analyse des correspondances multiples (ACM), ont été proposées par le statisticien français Jean-Paul Benzécri [-@benzecri1973analyse], tandis que l’analyse factorielle de données mixtes (AFDM) a été proposée par Brigitte Escofier et Jérôme Pagès [@escofier1979traitement; @pages2002analyse].\n\nAinsi, plusieurs ouvrages de statistique sur les méthodes factorielles, désormais classiques, ont été publiés en français [@benzecri1973analyse; @escofier1998analyses; @lebart1995statistique; @pages2013analyse]. Ils méritent grandement d'être consultés, notamment pour mieux comprendre les formulations mathématiques (matricielles et géométriques) de ces méthodes. À cela s'ajoutent plusieurs ouvrages visant à « vulgariser ces méthodes » en sciences sociales; c'est notamment le cas de l'excellent ouvrage de Léna Sanders [-@sanders1989analyse] en géographie.\n\n\n## Analyses en composantes principales (ACP) {#sec-122}\n\nD'emblée, notez qu'il existe deux types d'analyse en composantes principales (ACP) (*Principal Component Analysis, PCA* en anglais) : \n\n- **l'ACP non normée** dans laquelle les variables quantitatives du tableau sont uniquement centrées (moyenne = 0).\n\n- **l'ACP normée** dans laquelle les variables quantitatives du tableau sont préalablement centrées réduites (moyenne = 0 et variance = 1; [section @sec-02552]).\n\nPuisque les variables d'un tableau sont souvent exprimées dans des unités de mesure différentes ou avec des ordres de grandeur différents (intervalles et écarts-types bien différents), l'utilisation de l'ACP normée est bien plus courante. Elle est d'ailleurs l'option par défaut dans les fonctions R permettant de calculer une ACP. Par conséquent, nous détaillons dans cette section uniquement l'ACP normée.\n\nAutrement dit, le recours à une ACP non normée est plus rare et s'applique uniquement à la situation suivante : toutes les variables du tableau sont mesurées dans la même unité (par exemple, en pourcentage); il pourrait être ainsi judicieux de conserver leurs variances respectives.\n\n### Recherche d'une simplification {#sec-1221}\n\nL’ACP permet d'explorer et de résumer un tableau constitué uniquement de variables quantitatives (@fig-AnalysesFactoriellesTabACPFig), et ce, de trois façons : 1) en montrant les ressemblances entre les individus (observations), 2) en révélant les liaisons entre les variables quantitatives et 3) en résumant l’ensemble des variables du tableau par des variables synthétiques nommées composantes principales.\n\n\n![Tableau pour une ACP](images/Chap12/AnalysesFactoriellesTabACP.png){#fig-AnalysesFactoriellesTabACPFig width=\"60%\" fig-align=\"center\"}\n\n**Ressemblance entre les individus**. Concrètement, deux individus se ressemblent si leurs valeurs respectives pour les *p* variables du tableau sont similaires. Cette proximité/ressemblance est évaluée à partir de la distance euclidienne (@eq-ACPdistEuc). La notion de distance fait l'objet d'une section à part entière ([section @sec-1321]) que vous pouvez consulter dès à présent si elle ne vous est pas familière.\n\n$$\nd^2(a,b) = \\sum_{j=1}^p(x_{aj}-x_{bj})^2\n$$ {#eq-ACPdistEuc}\n\n\nPrenons un exemple fictif avec trois individus (*i*, *j* et *k*) ayant des valeurs pour trois variables préalablement centrées réduites (V1 à V3) (@tbl-distanceACPindi). La proximité entre les paires de points est évaluée comme suit : \n\n$$d^2(i,j)=(-\\mbox{1,15}-\\mbox{0,49})^2+(-\\mbox{1,15}-\\mbox{0,58})^2+(\\mbox{0,83}+\\mbox{1,11})^2=\\mbox{9,44}$$\n$$d^2(i,k)=(-\\mbox{1,15}+\\mbox{0,66})^2+(-\\mbox{1,15}-\\mbox{0,58})^2+(\\mbox{0,83}-\\mbox{0,28})^2=\\mbox{5,98}$$\n\n$$d^2(j,k)= (\\mbox{0,49}+\\mbox{0,66})^2+(\\mbox{0,58}-\\mbox{0,58})^2+(-\\mbox{1,11}-\\mbox{0,28})^2=\\mbox{1,97}$$\n\nNous pouvons en conclure que *i* est plus proche de *k* que de *j*, mais aussi que la paire de points les plus proches est (*i*,*k*). En d'autres termes, les deux observations *i* et *k* sont les plus similaires du jeu de données selon la distance euclidienne.\n\n\n::: {#tbl-distanceACPindi .cell tbl-cap='Données fictives'}\n::: {.cell-output-display}\n`````{=html}\n\n \n\n\n\n\n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
Variables centrées réduites
Individu V1 V2 V3
i -1,15 -1,15 0,83
j 0,49 0,58 -1,11
k 0,66 0,58 0,28
\n\n`````\n:::\n:::\n\n\n\n**Liaisons entre les variables**. Dans une ACP normée, les liaisons entre les variables deux à deux sont évaluées avec le coefficient de corrélation ([section @sec-0431]), soit la moyenne du produit des deux variables centrées réduites (@eq-ACPcor). Notez que dans une ACP non normée, plus rarement utilisée, les liaisons sont évaluées avec la covariance puisque les variables sont uniquement centrées (@eq-ACPcov).\n\n\n$$\nr_{xy} = \\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})(y_{i}-\\bar{y})}{n\\sqrt{\\sum_{i=1}^n(x_i - \\bar{x})^2(y_i - \\bar{y})^2}}=\\sum_{i=1}^n\\frac{Zx_iZy_i}{n}\n$$ {#eq-ACPcor}\n\n\n$$\ncov(x,y) = \\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})(y_{i}-\\bar{y})}{n}\n$$ {#eq-ACPcov}\n\n\n**Composantes principales**. Au [chapitre @sec-chap04], nous avons abordé deux méthodes pour identifier des relations linéaires entre des variables continues normalement distribuées : \n\n* la corrélation de Pearson ([section @sec-043]), qu'il est possible d'illustrer graphiquement à partir d'un nuage de points;\n\n* la régression linéaire simple ([section @sec-044]), permettant de résumer la relation linéaire entre deux variables avec une droite de régression de type $Y=a+bX$. \n\nBrièvement, plus deux variables sont corrélées (positivement ou négativement), plus le nuage de points qu'elles forment est allongé et plus les points sont proches de la droite de régression (@fig-liaisons2Vars, partie **a**). À l'inverse, plus la liaison entre les deux variables normalement distribuées est faible, plus le nuage prend la forme d'un cercle et plus les points du nuage sont éloignés de la droite de régression (@fig-liaisons2Vars, partie **b**). Puisqu'en ACP normée, les variables sont centrées réduites, le centre de gravité du nuage de points est (*x* = 0, *y* = 0) et il est toujours traversé par la droite de régression. Finalement, nous avons vu que la méthode des moindres carrés ordinaires (MCO) permet de déterminer cette droite en minimisant les distances entre les valeurs observées et celles projetées orthogonalement sur cette droite (valeurs prédites). Dans le cas de deux variables uniquement, l'axe factoriel principal/la composante principale est donc la droite qui résume le mieux la liaison entre les deux variables (en rouge). L'axe 2 représente la seconde plus importante composante (axe, dimension) et il est orthogonal (perpendiculaire) au premier axe (en bleu).\n\n\n![Corrélation, allongement du nuage de points et axes factoriels](images/Chap12/bivariePlanFacto.png){#fig-liaisons2Vars width=\"100%\" fig-align=\"center\"}\n\n\n\n\n::: {.cell}\n\n:::\n\n\nImaginez maintenant trois variables pour lesquelles vous désirez identifier un axe, une droite qui résume le mieux les liaisons entre elles. Visuellement, vous passez d'un nuage de points en deux dimensions (2D) à un nuage en dimensions (3D). Si les corrélations entre les trois variables sont très faibles, alors le nuage prend la forme d'un ballon de soccer (football en Europe). Par contre, plus ces liaisons sont fortes, plus la forme est allongée comme un ballon de rugby et plus les points sont proches de l'axe traversant le ballon.\n\nAjouter une autre variable revient alors à ajouter une quatrième dimension qu'il est impossible de visualiser, même pour les plus fervents adaptes de science-fiction. Pourtant, le problème reste le même : identifier, dans un plan en *p* dimensions (variables), les axes factoriels – les composantes principales – qui concourent le plus à résumer les liaisons entre les variables continues préalablement centrées réduites, et ce, en utilisant la méthode des moindres carrés ordinaires.\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Composantes principales et axes factoriels**\n:::\n::: bloc_attention-body\nLes termes **composantes principales** et **axes factoriels** sont des synonymes employés pour référer aux nouvelles variables synthétiques produites par l'ACP et résumant l'information du tableau initial.\n:::\n:::\n\n### Aides à l'interprétation {#sec-1222}\n\nPour illustrer les aides à l'interprétation de l'ACP, nous utilisons un jeu de données spatiales tiré d'un article sur l'agglomération lyonnaise en France [@2021_4]. Ce jeu de données comprend dix variables, dont quatre environnementales (EN) et six socioéconomiques (SE), pour les îlots regroupés pour l'information statistique (IRIS) de l'agglomération lyonnaise (@tbl-dataacp et @fig-datacartoacp). Sur ces dix variables, nous calculons une **ACP normée**.\n\n\n::: {#tbl-dataacp .cell tbl-cap='Statistiques descriptives pour le jeu de données utilisé pour l\\'ACP'}\n::: {.cell-output-display}\n| |Nom |Intitulé | Type | Moy.| E.-T.| Min.| Max.|\n|:----------|:----------|:--------------------------------|:----:|--------:|-------:|--------:|--------:|\n|Lden |Lden |Bruit routier (Lden dB(A)) | EN | 55,6| 4,9| 33,9| 71,7|\n|NO2 |NO2 |Dioxyde d'azote (ug/m^3^) | EN | 28,7| 7,9| 12,0| 60,2|\n|PM25 |PM25 |Particules fines (PM$_{2,5}$) | EN | 16,8| 2,1| 11,3| 21,9|\n|VegHautPrt |VegHautPrt |Canopée (%) | EN | 18,7| 10,1| 1,7| 53,8|\n|Pct0_14 |Pct0_14 |Moins de 15 ans (%) | SE | 18,5| 5,7| 0,0| 54,0|\n|Pct_65 |Pct_65 |65 ans et plus (%) | SE | 16,2| 5,9| 0,0| 45,1|\n|Pct_Img |Pct_Img |Immigrants (%) | SE | 14,5| 9,1| 0,0| 59,8|\n|TxChom1564 |TxChom1564 |Taux de chômage | SE | 14,8| 8,1| 0,0| 98,8|\n|Pct_brevet |Pct_brevet |Personnes à faible scolarité (%) | SE | 23,5| 12,6| 0,0| 100,0|\n|NivVieMed |NivVieMed |Médiane du niveau de vie (Euros) | SE | 21 804,5| 4 922,5| 11 324,0| 38 707,0|\n:::\n:::\n\n\n\n![Cartographie des dix variables utilisées pour l'ACP](images/Chap12/Figure3Data.png){#fig-datacartoacp width=\"100%\" fig-align=\"center\"}\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Trois étapes pour bien analyser une ACP et comprendre la signification des axes factoriels**\n:::\n::: bloc_objectif-body\n1. Interprétation des résultats des valeurs propres pour identifier le nombre d'axes (de composantes principales) à retenir. L'enjeu est de garder un nombre d'axes limité qui résume le mieux le tableau initial (réduction des données).\n\n2. Analyse des résultats pour les variables (coordonnées factorielles, cosinus carrés et contributions sur les axes retenus).\n\n3. Analyse des résultats pour les individus (coordonnées factorielles, cosinus carrés et contributions sur les axes retenus).\n\nLes deux dernières étapes permettent de comprendre la signification des axes retenus et de les qualifier. Cette étape d'interprétation est essentielle en sciences sociales. En effet, nous avons vu dans l'introduction du chapitre que les méthodes factorielles permettent de résumer l'information d'un tableau en quelques nouvelles variables synthétiques, souvent considérées comme des variables latentes dans le jeu de données. Il convient alors de bien comprendre ces variables synthétiques (latentes), si nous souhaitons les utiliser dans une autre analyse subséquente (par exemple, les introduire dans une régression).\n:::\n:::\n\n#### Résultats de l'ACP pour les valeurs propres {#sec-12221}\n\nÀ titre de rappel, une ACP normée est réalisée sur des variables préalablement centrées réduites (@eq-scorezacpnormee), ce qui signifie que pour chaque variable :\n\n- Nous soustrayons à chaque valeur la moyenne de la variable correspondante (centrage); la moyenne est donc égale à 0.\n- Nous divisons cette différence par l’écart-type de la variable correspondante (réduction); la variance est égale à 1.\n\t\n$$\nz= \\frac{x_i-\\mu}{\\sigma}\n$$ {#eq-scorezacpnormee}\n\n\t\nPar conséquent, la variance totale (ou inertie totale) d’un tableau sur lequel est calculée une ACP normée est égale au nombre de variables qu'il comprend. Puisque nous l'appliquons ici à dix variables, la variance totale du tableau à réduire – c'est-à-dire à résumer en *K* nouvelles variables synthétiques, composantes principales, axes factoriels – est donc égale à 10. Trois mesures reportées au @tbl-dataacpValeurPropres permettent d'analyser les valeurs propres : \n\n- $\\mbox{VP}_k$, la valeur propre (*eigenvalue* en anglais) de l'axe *k*, c'est-à-dire la quantité de variance du tableau initial résumé par l'axe.\n\n- $\\mbox{VP}_k / \\mbox{P}$ avec *P* étant le nombre de variables que comprend le tableau initial. Cette mesure représente ainsi le pourcentage de la variance totale du tableau résumé par l’axe *k*; autrement dit, la quantité d’informations du tableau initial résumée par l’axe, la composante principale *k*. Cela nous permet ainsi d’évaluer le pouvoir explicatif de l’axe.\n\n- Le pourcentage cumulé pour les axes.\n\n\n::: {#tbl-dataacpValeurPropres .cell tbl-cap='Résultats de l\\'ACP pour les valeurs propres'}\n::: {.cell-output-display}\n| | Composante| Valeur propre| Pourcentage| Pourc. cumulé|\n|:-------|----------:|-------------:|-----------:|-------------:|\n|comp 1 | 1| 3,543| 35,425| 35,425|\n|comp 2 | 2| 2,760| 27,596| 63,021|\n|comp 3 | 3| 1,042| 10,422| 73,443|\n|comp 4 | 4| 0,751| 7,511| 80,954|\n|comp 5 | 5| 0,606| 6,059| 87,013|\n|comp 6 | 6| 0,388| 3,880| 90,893|\n|comp 7 | 7| 0,379| 3,788| 94,681|\n|comp 8 | 8| 0,244| 2,441| 97,122|\n|comp 9 | 9| 0,217| 2,167| 99,289|\n|comp 10 | 10| 0,071| 0,711| 100,000|\n:::\n:::\n\n\nAvant d'analyser en détail le @tbl-dataacpValeurPropres, notez que la somme des valeurs propres de toutes les composantes de l'ACP est toujours égale au nombre de variables du tableau initial. Aussi, la quantité de variance expliquée (les valeurs propres) décroît de la composante 1 à la composante *K*.\n\n**Combien d'axes d'une ACP faut-il retenir?** Pour répondre à cette question, deux approches sont possibles :\n\n- **Approche statistique** (avec le critère de Kaiser [-@kaiser1960application]). Nous retenons uniquement les composantes qui présentent une valeur propre supérieure à 1. Rappelez-vous qu'en ACP normée, les variables sont préalablement centrées réduites, et donc que leur variance respective est égale à 1. Par conséquent, une composante ayant une valeur propre inférieure à 1 a un pouvoir explicatif inférieur à celui d'une variable. À la lecture du tableau, nous retenons les trois premières composantes si nous appliquons ce critère.\n\n- **Approche empirique** basée sur la lecture des pourcentages et des pourcentages cumulés. Nous pouvons retenir uniquement les deux premières composantes. En effet, ces deux premiers facteurs résument près des deux tiers de la variance totale du tableau (63,02 %). Cela démontre bien que l'ACP, comme les autres méthodes factorielles, est bien une méthode de réduction de données puisque nous résumons dix variables avec deux nouvelles variables synthétiques (axes, composantes principales). Pour faciliter le choix du nombre d'axes, il est fortement conseillé de construire des histogrammes à partir des valeurs propres, des pourcentages et des pourcentages cumulés (@fig-acpgraphvp). Or, à la lecture de ces graphiques, nous constatons que la variance expliquée chute drastiquement après les deux premières composantes. Par conséquent, nous pouvons retenir uniquement les deux premiers axes.\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Lecture du diagramme des valeurs propres** \n:::\n::: bloc_astuce-body\nPlus les variables incluses dans l'ACP sont corrélées entre elles, plus l'ACP est intéressante : plus les valeurs propres des premiers axes sont fortes et plus il y a des sauts importants dans le diagramme des valeurs propres. À l'inverse, lorsque les variables incluses dans l'ACP sont peu corrélées entre elles, il n'y a pas de sauts importants dans l'histogramme, autrement dit les valeurs propres sont uniformément décroissantes.\n:::\n:::\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Graphiques personnalisés pour les valeurs propres pour l'ACP](12-AnalysesFactorielles_files/figure-html/fig-acpgraphvp-1.png){#fig-acpgraphvp fig-align='center' width=75%}\n:::\n:::\n\n\n#### Résultats de l'ACP pour les variables {#sec-12222}\n\nPour qualifier les axes, quatre mesures sont disponibles pour les variables :\n\n- **Les coordonnées factorielles des variables** sont simplement les coefficients de corrélation de Pearson des variables sur l’axe *k* et varient ainsi de -1 à 1 (relire au besoin la [section @sec-043]). Pour qualifier un axe, il convient alors de repérer les variables les plus corrélées positivement et négativement sur l’axe, autrement dit, de repérer les variables situées aux extrémités l'axe. \n\n- **Les cosinus carrés des variables** (Cos^2^) (appelés aussi les qualités de représentation des variables sur un axe) permettent de repérer le ou les axes qui concourent le plus à donner un sens à la variable. Ils sont en fait les coordonnées des variables mises au carré. La somme des cosinus carrés d’une variable sur tous les axes de l’ACP est donc égale à 1 (sommation en ligne).\n\n- **La qualité de représentation d'une variable sur les _n_ premiers axes** est simplement la somme des cosinus carrés d'une variable sur les axes retenus. Par exemple, pour la variable `Lden`, la qualité de représentation de la variable sur le premier axe est égale : $\\mbox{0,42}^2=\\mbox{0,17}$. Pour cette même variable, la qualité de la `Lden` sur les trois premiers axes est égale à : $\\mbox{0,17}+\\mbox{0,32}+\\mbox{0,26}=\\mbox{0,75}$.\n\n- **Les contributions des variables** permettent de repérer celles qui participent le plus à la formation d’un axe. Elles s'obtiennent en divisant les cosinus carrés par la valeur propre de l’axe multiplié par 100. La somme des contributions des variables pour un axe donné est donc égale à 100 (sommation en colonne). Par exemple, pour la variable `Lden`, la contribution sur le premier axe est égale : $\\mbox{0,174} / \\mbox{3,543} \\times \\mbox{100}= \\mbox{4,920 }%$.\n\nLes résultats de l'ACP pour les variables sont présentés au @tbl-dataacpCoordVars.\n\n\n::: {#tbl-dataacpCoordVars .cell tbl-cap='Résultats de l\\'ACP pour les variables'}\n::: {.cell-output-display}\n`````{=html}\n\n \n\n\n\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
Coordonnées
Cosinus carrés
Contributions
Variable 1 2 3 1 2 3 Qualité 1 2 3
Lden 0,42 0,57 0,51 0,17 0,32 0,26 0,75 4,92 11,64 24,80
NO2 0,15 0,93 0,19 0,02 0,86 0,04 0,92 0,66 31,07 3,54
PM25 0,19 0,92 0,03 0,04 0,84 0,00 0,87 1,01 30,36 0,12
VegHautPrt -0,40 -0,42 0,40 0,16 0,18 0,16 0,50 4,63 6,35 15,46
Pct0_14 0,55 -0,53 0,08 0,30 0,28 0,01 0,59 8,61 10,28 0,55
Pct_65 -0,41 -0,27 0,72 0,17 0,07 0,51 0,75 4,73 2,66 49,26
Pct_Img 0,87 -0,09 0,11 0,76 0,01 0,01 0,78 21,56 0,29 1,08
TxChom1564 0,77 -0,09 -0,07 0,60 0,01 0,00 0,61 16,89 0,27 0,45
Pct_brevet 0,73 -0,43 0,22 0,53 0,19 0,05 0,77 14,94 6,81 4,61
NivVieMed -0,88 0,09 0,04 0,78 0,01 0,00 0,79 22,06 0,28 0,14
\n\n`````\n:::\n:::\n\n\n**Analyse de la première composante principale (valeur propre de 3,54, 35,43 %)**\n\n- À la lecture des contributions, il est clair que quatre variables contribuent grandement à la formation de l'axe 1 : `NivVieMed` (22,06 %), \n`Pct_Img` (21,56 %), `TxChom1564` (16,89 %) et `Pct_brevet` (14,94 %). Il convient alors d'analyser en détail leurs coordonnées factorielles et leurs cosinus carrés.\n\n- À la lecture des coordonnées factorielles, nous constatons que trois variables socioéconomiques sont fortement corrélées positivement avec l’axe 1, soit le *pourcentage d’immigrants* (0,87), le *taux de chômage* (0,77) et le *pourcentage de personnes avec une faible scolarité* (0,73). À l’autre extrémité, la *médiane du niveau de vie* (en euros) est négativement corrélée avec l’axe 1. Comment interpréter ce résultat? Premièrement, cela signifie que plus la valeur de l’axe 1 est positive et élevée, plus celles des trois variables (`Pct_Img`,`TxChom1564` et `Pct_brevet`) sont aussi élevées (corrélations positives) et plus la valeur de `NivVieMed` est faible (corrélation négative). Inversement, plus la valeur de l’axe 1 est négative et faible, les valeurs de `Pct_Img`, `TxChom1564` et `Pct_brevet` sont faibles et plus celle de `NivVieMed` est forte. Deuxièmement, cela signifie que les trois variables (`Pct_Img`,`TxChom1564` et `Pct_brevet`) sont fortement corrélées positivement entre elles puisqu’elles se situent sur la même extrémité de l’axe et qu’elles sont toutes trois négativement corrélées avec la variable `NivVieMed`. Cela peut être rapidement confirmé avec la matrice de corrélation entre les dix variables (@tbl-dataacpMatriceCorr). \n\n- À la lecture des cosinus carrés de l'axe 1, nous constatons que plus des trois quarts de la dispersion/de l'information des variables `NivVieMed` (0,78) et `Pct_Img` (0,76) est concentrée sur l'axe 1.\n\n\n\n::: {#tbl-dataacpMatriceCorr .cell tbl-cap='Matrice de corrélation de Pearson entre les variables utilisées pour l\\'ACP'}\n::: {.cell-output-display}\n| |Variable | A| B| C| D| E| F| G| H| I| J|\n|:----------|:-------------|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|-----:|\n|Lden |A. Lden | | 0,62| 0,49| -0,23| 0,04| -0,09| 0,28| 0,19| 0,14| -0,26|\n|NO2 |B. NO2 | 0,62| | 0,90| -0,28| -0,34| -0,21| 0,07| 0,04| -0,25| -0,04|\n|PM25 |C. PM25 | 0,49| 0,90| | -0,39| -0,34| -0,26| 0,12| 0,07| -0,25| -0,10|\n|VegHautPrt |D. VegHautPrt | -0,23| -0,28| -0,39| | 0,04| 0,32| -0,22| -0,18| -0,14| 0,32|\n|Pct0_14 |E. Pct0_14 | 0,04| -0,34| -0,34| 0,04| | -0,12| 0,46| 0,36| 0,54| -0,45|\n|Pct_65 |F. Pct_65 | -0,09| -0,21| -0,26| 0,32| -0,12| | -0,24| -0,30| 0,00| 0,32|\n|Pct_Img |G. Pct_Img | 0,28| 0,07| 0,12| -0,22| 0,46| -0,24| | 0,66| 0,64| -0,73|\n|TxChom1564 |H. TxChom1564 | 0,19| 0,04| 0,07| -0,18| 0,36| -0,30| 0,66| | 0,47| -0,62|\n|Pct_brevet |I. Pct_brevet | 0,14| -0,25| -0,25| -0,14| 0,54| 0,00| 0,64| 0,47| | -0,67|\n|NivVieMed |J. NivVieMed | -0,26| -0,04| -0,10| 0,32| -0,45| 0,32| -0,73| -0,62| -0,67| |\n:::\n:::\n\n\n**Analyse de la deuxième composante principale (valeur propre de 2,76, 27,60 %)**\n\n- À la lecture des contributions, trois variables environnementales contribuent à la formation de l'axe 2 : principalement, celles sur la pollution de l'air (`NO2` = 31,07 % et `PM25` = 30,36 %) et secondairement, celle sur le bruit routier (`Lden` = 11,64 %).\n\n- À la lecture des coordonnées factorielles, ces trois variables sont fortement corrélées positivement avec l'axe 2 : `NO2` (0,93), `PM25` (0,92) et `Lden` (0,57). À l'autre extrémité de l'axe, la variable `Pct0_14` est négativement, mais pas fortement, corrélée (-0,53). La lecture de la matrice de corrélation au @tbl-dataacpMatriceCorr confirme que ces trois variables environnementales sont fortement corrélées positivement entre elles (par exemple, un coefficient de corrélation de Pearson de 0,90 entre `NO2` et `PM25`).\n\n- À la lecture des cosinus carrés de l'axe 2, nous constatons que près de 90 % de la dispersion/de l'information des variables `NO2` (0,86) et `PM25` (0,84) est concentrée sur l'axe 2.\n\n\n**Analyse de la troisième composante principale (valeur propre de 1,042, 10,42 %)**\n\n- Le *pourcentage de personnes âgées* (`Pct_65`) contribue principalement à la formation de l'axe 3 avec lequel il est corrélé positivement (contribution de 49,26 % et coordonnée factorielle de 0,72). S'en suit la variable `Lden`, qui joue un rôle beaucoup moins important (contribution de 24,80 % et coordonnée factorielle de 0,51).\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Lien entre la valeur propre d'un axe et le nombre de variables contribuant à sa formation**\n:::\n::: bloc_astuce-body\nVous auvez compris que plus la valeur propre d'un axe est forte, plus il y a potentiellement de variables qui concourent à sa formation. Cela explique que pour la troisième composante, qui a une faible valeur propre (1,042), seule une variable contribue significativement à sa formation. \n:::\n:::\n\n**Analyse de la qualité de représentation des variables sur les premiers axes de l'ACP**\n\nÀ titre de rappel, la qualité est simplement la somme des cosinus carrés d’une variable sur les axes retenus. Si nous retenons trois axes, les six variables qui sont le mieux résumées – et qui ont donc le plus d'influence sur les résultats de l'ACP – sont  : `NO2` (0,92), `PM25` (0,87), `NivVieMed` (0,79), `Pct_Img` (0,78), `Pct_brevet` (0,77) et `Lden` (0,75).\n\n**Qualification, dénomination d'axes factoriels**\n\nL'analyse des coordonnées, des contributions et des cosinus carrés doit vous permettre de formuler un intitulé pour chacun des axes retenus. Nous vous proposons les intitulés suivants : \n\n- *Niveau de défavorisation socioéconomique* (axe 1). Plus la valeur de l'axe est élevée, plus le niveau de défavorisation de l'entité spatiale (IRIS) est élevé.\n\n- *Qualité environnementale* (axe 2). Plus la valeur de l'axe est forte, plus les niveaux de pollution atmosphérique (dioxyde d'azote et particules fines) et de bruit (Lden) sont élevés.\n\n**Recours à des graphiques pour analyser les résultats de l'ACP pour des variables**\n\nPlus le nombre de variables utilisées pour calculer l'ACP est important, plus l'analyse des coordonnées factorielles, des cosinus carrés et des contributions reportés dans un tableau devient fastidieuse. Puisque l’ACP a été calculée sur dix variables, l’analyse des valeurs du @tbl-dataacpCoordVars a été assez facile et rapide. Imaginez maintenant que nous réalisons une ACP sur une centaine de variables, la taille du tableau des résultats pour les variables sera considérable... Par conséquent, il est recommandé de construire plusieurs graphiques qui facilitent l’analyse des résultats pour les variables. \n\nPar exemple, à la @fig-acpgraphvarscoords, nous avons construit des graphiques avec les coordonnées factorielles sur les trois premiers axes de l’ACP. En un coup d’œil, il est facile de repérer les variables les plus corrélées positivement ou négativement avec chacun d’entre eux.\nAussi, il est fréquent de construire un nuage de points avec les coordonnées des variables sur les deux premiers axes factoriels, soit un graphique communément appelé **nuage de points des variables sur le premier plan factoriel** sur lequel est représenté le cercle des corrélations (@fig-acp1erplanfactVars). Bien entendu, cet exercice peut être fait avec d’autres axes factoriels (les axes 3 et 4 par exemple).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Coordonnées factorielles des variables](12-AnalysesFactorielles_files/figure-html/fig-acpgraphvarscoords-1.png){#fig-acpgraphvarscoords fig-align='center' width=80%}\n:::\n:::\n\n::: {.cell layout-align=\"center\" quietly='true'}\n::: {.cell-output-display}\n![Premier plan factoriel de l'ACP pour les variables](12-AnalysesFactorielles_files/figure-html/fig-acp1erplanfactVars-1.png){#fig-acp1erplanfactVars fig-align='center' width=75%}\n:::\n:::\n\n\n#### Résultats de l'ACP pour les individus {#sec-12223}\n\nComme pour les variables, nous retrouvons les mêmes mesures pour les individus : les coordonnées factorielles, les cosinus carrés et les contributions. Les coordonnées factorielles des individus sont les projections orthogonales des observations sur l'axe. Puisqu'en ACP normée, les variables utilisées pour l'ACP sont centrées réduites, la moyenne des coordonnées factorielles des individus pour un axe est toujours égale à zéro. En revanche, contrairement aux coordonnées factorielles pour les variables, les coordonnées pour les individus ne varient pas de -1 à 1! Les cosinus carrés quantifient à quel point chaque axe représente chaque individu. Enfin, les contributions quantifient l'apport de chaque individu à la formation d'un axe.\n\nSi le jeu de données comprend peu d'observations, il est toujours possible de créer un **nuage de points des individus sur le premier plan factoriel** sur lequel vous pouvez ajouter les étiquettes permettant d'identifier les observations (@fig-acp1erplanfactIndiv). Ce graphique est rapidement illisible lorsque le nombre d'observations est important. Il peut rester utile si certaines des observations du jeu de données doivent faire l'objet d'une analyse spécifique.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Premier plan factoriel pour les individus](12-AnalysesFactorielles_files/figure-html/fig-acp1erplanfactIndiv-1.png){#fig-acp1erplanfactIndiv fig-align='center' width=75%}\n:::\n:::\n\n\nLorsque les observations sont des unités spatiales, il est très intéressant de cartographier les coordonnées factorielles des individus (@fig-acp1erplanfactIndiv). À la lecture de la carte choroplèthe de gauche (axe 1), nous pouvons constater que le niveau de défavorisation socioéconomique est élevé dans l'est (IRIS en vert), et inversement, très faible à l'ouest de l'agglomération (IRIS en rouge). À la lecture de la carte de droite (axe 2), sans surprise, la partie centrale de l'agglomération est caractérisée par des niveaux de pollution atmosphérique et de bruit routier bien plus élevés qu'en périphérie.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Cartographie des coordonnées factorielles des individus](12-AnalysesFactorielles_files/figure-html/fig-acpcartoindiv-1.png){#fig-acpcartoindiv fig-align='center' width=80%}\n:::\n:::\n\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Autres éléments intéressants de l'ACP**\n:::\n::: bloc_aller_loin-body\n**Ajout de variables ou d'individus supplémentaires** \n\nPremièrement, il est possible d'ajouter des variables continues ou des individus supplémentaires qui n'ont pas été pris en compte dans le calcul de l'ACP (@fig-acpvarindcorrsuppl). Concernant les variables continues supplémentaires, il s'agit simplement de calculer leurs corrélations avec les axes retenus de l'ACP. Concernant les individus, il s'agit de les projeter sur les axes factoriels. Pour plus d'informations sur le sujet, consultez les excellents ouvrages de Ludovic Lebart, Alain Morineau et Marie Piron [-@lebart1995statistique, p.42-45] ou encore de Jérôme Pagès [-@pages2013analyse, p.22-24].\n\n\n![Variables et individus supplémentaires pour l'ACP](images/Chap12/AcpIndVarSuppl.png){#fig-acpvarindcorrsuppl width=\"28%\" fig-align=\"center\"}\n\n\n**Pondération des individus et des variables**\n\nDeuxièmement, il est possible de pondérer à la fois les individus et, plus rarement, les variables lors du calcul de l'ACP.\n\n**Analyse en composantes principales non paramétrique**\n\nTroisièmement, il est possible de calculer une ACP sur des variables préalablement transformées en rang ([section @sec-02552]). Cela peut être justifié lorsque les variables sont très anormalement distribuées en raison de valeurs extrêmes. Les coordonnées factorielles pour les variables sont alors le coefficient de Spearman ([section @sec-0433]) et non de Pearson. Aussi, les variables sont centrées non pas sur leurs moyennes respectives, mais sur leurs médianes. Pour plus d'informations sur cette approche, consultez de nouveau Lebart et al. [-@lebart1995statistique, p.51-52].\n\n**Analyse en composantes principales robuste**\n\nFinalement, d'autres méthodes plus avancées qu'une ACP non paramétrique peuvent être utilisées afin d'obtenir des composantes principales qui ne sont pas influencées par des valeurs extrêmes : les ACP robustes [@rivest1988analyse; @hubert2005robpca] qui peuvent être mises en œuvre, entre autres avec le *package* `roscpca`.\n:::\n:::\n\n\n### Mise en œuvre dans R {#sec-1223}\n\nPlusieurs *packages* permettent de calculer une ACP dans R, notamment `psych` avec la fonction `principal`, `ade4` avec la fonction `dudi.pca` et `FactoMineR`[@FactoMineR] avec la fonction `PCA`. Ce dernier est certainement le plus abouti. De plus, il permet également de calculer une analyse des correspondances (AFC), une analyse des correspondances multiples (ACM) et une analyse factorielle de données mixtes (AFDM). Nous utilisons donc `FactoMineR` pour mettre en œuvre les trois types de méthodes factorielles abordées dans ce chapitre (ACP, AFC et ACM). Pour l'ACP, nous exploitons un jeu de données issu du *package* `geocmeans` qu'il faut préalablement charger à l'aide des lignes de code suivantes.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(geocmeans)\ndata(LyonIris)\nData <- st_drop_geometry(LyonIris[c(\"CODE_IRIS\" , \"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\",\n \"Pct0_14\" , \"Pct_65\" , \"Pct_Img\",\n \"TxChom1564\" , \"Pct_brevet\" , \"NivVieMed\")])\n```\n:::\n\n\n#### Calcul et exploration d'une ACP avec `FactoMineR` {#sec-12231}\n\nPour calculer l'ACP, il suffit d'utiliser la fonction `PCA` de `FactoMineR`, puis la fonction `summary(MonACP)` qui renvoie les résultats de l'ACP pour : \n\n- Les valeurs propres (section `Eigenvalues`) pour les composantes principales (`Dim.1` à `Dim.n`) avec leur variance expliquée brute (`Variance`) en pourcentage (`% of var.`) et en pourcentage cumulé (`Cumulative % of var.`).\n\n- Les dix premières observations (section `Individuals`) avec les coordonnées factorielles (`Dim.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`). Pour accéder aux résultats pour toutes les observations, utilisez les fonctions `res.acp$ind` ou encore `res.acp$ind$coord` (uniquement les coordonnées factorielles), `res.acp$ind$contrib` (uniquement les contributions) et `res.acp$ind$cos2` (uniquement les cosinus carrés).\n\n- Les variables (section `Variables`) avec les coordonnées factorielles (`Dim.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`).\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(FactoMineR)\n# Version classique avec FactoMineR\n# Construction d'une ACP sur les colonnes 2 à 11 du DataFrame Data\nres.acp <- PCA(Data[,2:11], scale.unit = TRUE, graph = FALSE)\n# Affichage des résultats de la fonction PCA\nprint(res.acp)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n**Results for the Principal Component Analysis (PCA)**\nThe analysis was performed on 506 individuals, described by 10 variables\n*The results are available in the following objects:\n\n name description \n1 \"$eig\" \"eigenvalues\" \n2 \"$var\" \"results for the variables\" \n3 \"$var$coord\" \"coord. for the variables\" \n4 \"$var$cor\" \"correlations variables - dimensions\"\n5 \"$var$cos2\" \"cos2 for the variables\" \n6 \"$var$contrib\" \"contributions of the variables\" \n7 \"$ind\" \"results for the individuals\" \n8 \"$ind$coord\" \"coord. for the individuals\" \n9 \"$ind$cos2\" \"cos2 for the individuals\" \n10 \"$ind$contrib\" \"contributions of the individuals\" \n11 \"$call\" \"summary statistics\" \n12 \"$call$centre\" \"mean of the variables\" \n13 \"$call$ecart.type\" \"standard error of the variables\" \n14 \"$call$row.w\" \"weights for the individuals\" \n15 \"$call$col.w\" \"weights for the variables\" \n```\n:::\n\n```{.r .cell-code}\n# Résumé des résultats (valeurs propres, individus, variables)\nsummary(res.acp)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCall:\nPCA(X = Data[, 2:11], scale.unit = TRUE, graph = FALSE) \n\n\nEigenvalues\n Dim.1 Dim.2 Dim.3 Dim.4 Dim.5 Dim.6 Dim.7\nVariance 3.543 2.760 1.042 0.751 0.606 0.388 0.379\n% of var. 35.425 27.596 10.422 7.511 6.059 3.880 3.788\nCumulative % of var. 35.425 63.021 73.443 80.954 87.013 90.893 94.681\n Dim.8 Dim.9 Dim.10\nVariance 0.244 0.217 0.071\n% of var. 2.441 2.167 0.711\nCumulative % of var. 97.122 99.289 100.000\n\nIndividuals (the 10 first)\n Dist Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3\n1 | 3.054 | 1.315 0.096 0.185 | -2.515 0.453 0.678 | 0.221\n2 | 1.882 | 0.193 0.002 0.011 | -1.744 0.218 0.859 | 0.082\n3 | 2.820 | 2.338 0.305 0.687 | -0.860 0.053 0.093 | -0.765\n4 | 2.816 | -0.740 0.031 0.069 | 2.265 0.367 0.647 | 1.293\n5 | 3.210 | -2.208 0.272 0.473 | -1.597 0.183 0.248 | 1.471\n6 | 3.016 | 2.287 0.292 0.575 | -1.515 0.164 0.252 | 0.390\n7 | 3.022 | -1.540 0.132 0.260 | -1.803 0.233 0.356 | 0.465\n8 | 3.122 | -1.536 0.132 0.242 | -2.038 0.298 0.426 | -0.120\n9 | 4.743 | -3.930 0.862 0.687 | -1.806 0.234 0.145 | 0.993\n10 | 3.055 | 2.713 0.411 0.789 | 0.368 0.010 0.014 | -0.391\n ctr cos2 \n1 0.009 0.005 |\n2 0.001 0.002 |\n3 0.111 0.074 |\n4 0.317 0.211 |\n5 0.411 0.210 |\n6 0.029 0.017 |\n7 0.041 0.024 |\n8 0.003 0.001 |\n9 0.187 0.044 |\n10 0.029 0.016 |\n\nVariables\n Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3 ctr cos2\nLden | 0.417 4.920 0.174 | 0.567 11.640 0.321 | 0.508 24.799 0.258\nNO2 | 0.153 0.657 0.023 | 0.926 31.068 0.857 | 0.192 3.540 0.037\nPM25 | 0.189 1.007 0.036 | 0.915 30.355 0.838 | 0.035 0.117 0.001\nVegHautPrt | -0.405 4.630 0.164 | -0.419 6.353 0.175 | 0.401 15.459 0.161\nPct0_14 | 0.552 8.605 0.305 | -0.533 10.281 0.284 | 0.076 0.553 0.006\nPct_65 | -0.409 4.730 0.168 | -0.271 2.658 0.073 | 0.716 49.258 0.513\nPct_Img | 0.874 21.559 0.764 | -0.089 0.288 0.008 | 0.106 1.077 0.011\nTxChom1564 | 0.774 16.893 0.598 | -0.086 0.267 0.007 | -0.068 0.450 0.005\nPct_brevet | 0.727 14.936 0.529 | -0.434 6.813 0.188 | 0.219 4.612 0.048\nNivVieMed | -0.884 22.062 0.782 | 0.088 0.278 0.008 | 0.038 0.136 0.001\n \nLden |\nNO2 |\nPM25 |\nVegHautPrt |\nPct0_14 |\nPct_65 |\nPct_Img |\nTxChom1564 |\nPct_brevet |\nNivVieMed |\n```\n:::\n:::\n\n\nAvec les fonctions de base `barplot` et `plot`, il est possible de construire rapidement des graphiques pour explorer les résultats de l'ACP pour les valeurs propres, les variables et les individus.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Graphiques pour les valeurs propres\nbarplot(res.acp$eig[,1], main=\"Valeurs propres\", names.arg=1:nrow(res.acp$eig))\n```\n\n::: {.cell-output-display}\n![](12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-1.png){width=672}\n:::\n\n```{.r .cell-code}\nbarplot(res.acp$eig[,2], main=\"Variance expliquée (%)\", names.arg=1:nrow(res.acp$eig))\n```\n\n::: {.cell-output-display}\n![](12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-2.png){width=672}\n:::\n\n```{.r .cell-code}\nbarplot(res.acp$eig[,3], main=\"Variance expliquée cumulée (%)\",\n names.arg=1:nrow(res.acp$eig))\n```\n\n::: {.cell-output-display}\n![](12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-3.png){width=672}\n:::\n\n```{.r .cell-code}\n# Nuage du points du premier plan factoriel pour les variables et les individus\nplot(res.acp, graph.type = \"classic\", choix = \"var\", axes = 1:2, \n title = \"Premier plan factoriel (variables)\")\n```\n\n::: {.cell-output-display}\n![](12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-4.png){width=672}\n:::\n\n```{.r .cell-code}\nplot(res.acp, graph.type = \"classic\", choix = \"ind\", axes = 1:2, \n title = \"Premier plan factoriel (individus)\")\n```\n\n::: {.cell-output-display}\n![](12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-5.png){width=672}\n:::\n:::\n\n\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Pondérations pour les individus et les variables**\n:::\n::: bloc_aller_loin-body\nNous avons vu, dans un encadré ci-dessus, qu'il est possible d'ajouter des variables et des individus supplémentaires dans une ACP, ce que permet la fonction `PCA` de `FactoMineR` avec les paramètres `ind.sup` et `quanti.sup`. Aussi, pour ajouter des pondérations aux individus ou aux variables, utilisez les paramètres `row.w` et `col.w`. Pour plus d'informations sur ces paramètres, consulter l'aide de la fonction en tapant `?PCA` dans la console de RStudio.\n:::\n:::\n\n#### Exploration graphique des résultats de l'ACP avec `factoextra` {#sec-12232}\n\nVisuellement, vous avez pu constater que les graphiques ci-dessus (pour les valeurs propres et pour le premier plan factoriel pour les variables et les individus), réalisés avec les fonctions de base `barplot` et `plot`, sont peu attrayants. Avec le *package* `factoextra`, quelques lignes de code suffissent pour construire des graphiques bien plus esthétiques. \n\nPremièrement, la syntaxe ci-dessous renvoie deux graphiques pour analyser les résultats des valeurs propres (@fig-factoextra1).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(factoextra)\nlibrary(ggplot2)\nlibrary(ggpubr)\n\n# Graphiques pour les variables propres avec factoextra\nG1 <- fviz_screeplot(res.acp, choice =\"eigenvalue\", addlabels = TRUE,\n x = \"Composantes\",\n y = \"Valeur propre\",\n title = \"\")\nG2 <- fviz_screeplot(res.acp, choice =\"variance\", addlabels = TRUE,\n x = \"Composantes\",\n y = \"Pourcentage de la variance expliquée\",\n title = \"\")\nggarrange(G1, G2)\n```\n\n::: {.cell-output-display}\n![Graphiques pour les valeurs propres de l'ACP avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-factoextra1-1.png){#fig-factoextra1 fig-align='center' width=75%}\n:::\n:::\n\n\nDeuxièmement, la syntaxe ci-dessous renvoie trois graphiques pour analyser les contributions de chaque variable aux deux premiers axes de l'ACP (figures [-@fig-factoextra2] et [-@fig-factoextra3]) et la qualité de représentation des variables sur les trois premiers axes (@fig-factoextra4), c'est-à-dire la somme des cosinus carrés sur les trois axes retenus.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Contributions des variables aux deux premières composantes avec factoextra\nfviz_contrib(res.acp, choice = \"var\", axes = 1, top = 10,\n title = \"Contributions des variables à la première composante\")\nfviz_contrib(res.acp, choice = \"var\", axes = 2, top = 10,\n title = \"Contributions des variables à la première composante\")\nfviz_cos2(res.acp, choice = \"var\", axes = 1:3)+\n labs(x = \"\", y = \"Somme des cosinus carrés sur les 3 axes retenus\",\n title = \"Qualité de représentation des variables sur les axes retenus de l'ACP\")\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Contributions des variables à la première composante avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-factoextra2-1.png){#fig-factoextra2 fig-align='center' width=85%}\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Contributions des variables à la deuxième composante avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-factoextra3-1.png){#fig-factoextra3 fig-align='center' width=85%}\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Qualité des variables sur les trois premières composantes avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-factoextra4-1.png){#fig-factoextra4 fig-align='center' width=85%}\n:::\n:::\n\n\n\nTroisièmement, le code ci-dessous renvoie un nuage de points pour le premier plan factoriel de l'ACP (axes 1 et 2) pour les variables (@fig-factoextra5) et les individus (@fig-factoextra6).\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Premier plan factoriel pour les variables avec factoextra\nfviz_pca_var(res.acp, col.var=\"contrib\",\n title = \"Premier plan factoriel pour les variables\")+\n scale_color_gradient2(low=\"#313695\", mid=\"#ffffbf\", high=\"#a50026\",\n midpoint=mean(res.acp$var$contrib[,1]))\n# Premier plan factoriel pour les individus avec factoextra\nfviz_pca_ind(res.acp, label = \"none\", title = \"ACP. Individus\")\nfviz_pca_ind(res.acp, col.ind=\"cos2\", title = \"ACP. Individus\") +\n scale_color_gradient2(low=\"blue\", mid=\"white\", high=\"red\", midpoint=0.50)\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Premier plan factoriel de l'ACP pour les variables avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-factoextra5-1.png){#fig-factoextra5 fig-align='center' width=100%}\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Premier plan factoriel de l'ACP pour les individus avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-factoextra6-1.png){#fig-factoextra6 fig-align='center' width=75%}\n:::\n:::\n\n\n#### Personnalisation des graphiques avec les résultats de l'ACP {#sec-12233}\n\nAvec un peu plus de lignes de code et l'utilisation d'autres *packages* (`ggplot2`, `ggpubr`, `stringr`, `corrplot`), vous pouvez aussi construire des graphiques personnalisés.\n\nPremièrement, la syntaxe ci-dessous permet de réaliser trois graphiques pour analyser les valeurs propres (@fig-acpmesgraphs1). Notez que, d'un coup d'œil, nous pouvons identifier les composantes principales avec une valeur propre égale ou supérieure à 1. \n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(ggplot2)\nlibrary(ggpubr)\nlibrary(stringr)\nlibrary(corrplot)\n\n# Calcul de l'ACP\nres.acp <- PCA(Data[,2:11], ncp=5, scale.unit = TRUE, graph = FALSE)\nprint(res.acp)\n\n# Construction d'un DataFrame pour les valeurs propres\ndfACPvp <- data.frame(res.acp$eig)\nnames(dfACPvp) <- c(\"VP\" , \"VP_pct\" , \"VP_cumupct\")\ndfACPvp$Composante <- factor(1:nrow(dfACPvp), levels = rev(1:nrow(dfACPvp)))\ncouleursAxes <- c(\"steelblue\" , \"skyblue2\")\nvpsup1 <- round(sum(subset(dfACPvp, VP >= 1)$VP),2)\nvpsup1cumul <- round(sum(subset(dfACPvp, VP >= 1)$VP_pct),2)\n\nplotVP1 <- ggplot(dfACPvp, aes(x = VP, y = Composante, fill = VP<1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 1, linetype = \"dashed\", color = \"azure4\", linewidth = 1)+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n labs(x = \"Valeur propre\", y = \"Composante principale\")\nplotVP2 <- ggplot(dfACPvp, aes(x = VP_pct, y = Composante, fill = VP<1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n theme(legend.position = \"none\")+\n labs(x = \"Pourcentage de la variance expliquée\", y = \"\")\nplotVP3 <- ggplot(dfACPvp, aes(x = VP_cumupct, y = Composante, fill = VP<1, group=1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n geom_line(colour = \"brown\", linetype = \"solid\", size=.8) +\n geom_point(size=3, shape=21, color = \"brown\", fill = \"brown\")+\n theme(legend.position = \"none\")+\n labs(x = \"Pourcentage cumulé de la variance expliquée\", y = \"\")\n\ntext1 <- paste0(\"Somme des valeurs propres supérieures à 1 : \",\n vpsup1,\n \".\\nPourcentage cumulé des valeurs propres supérieures à 1 : \",\n vpsup1cumul, \"%.\")\nannotate_figure(ggarrange(plotVP1, plotVP2, plotVP3, ncol = 2, nrow = 2),\n text_grob(\"Analyse des valeurs propres\", \n color = \"black\", face = \"bold\", size = 12),\n bottom = text_grob(text1,\n color = \"black\", hjust = 1, x = 1, size = 10))\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Graphiques personnalisés pour les valeurs propres](12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs1-1.png){#fig-acpmesgraphs1 fig-align='center' width=75%}\n:::\n:::\n\n\nDeuxièmement, la syntaxe ci-dessous permet de : \n\n- Construire un *DataFrame* avec les résultats des variables.\n\n- Construire des histogrammes avec les coordonnées des variables sur les axes factoriels (@fig-acpmesgraphs2). Notez que les coordonnées négatives sont indiquées avec des barres bleues et celles positives, avec des barres de couleur saumon.\n\n- Un graphique avec les contributions des variables sur les axes retenus (@fig-acpmesgraphs3).\n\n- Un graphique avec les cosinus carrés des variables sur les axes retenus (@fig-acpmesgraphs4). \n\n- Un histogramme avec la qualité des variables sur les axes retenus (@fig-acpmesgraphs5), soit la sommation de leurs cosinus carrés sur les axes retenus.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Analyse des résultats de L'ACP pour les variables\nlibrary(corrplot)\nlibrary(stringr)\nlibrary(ggplot2)\nlibrary(ggpubr)\n\n# Indiquer le nombre d'axes à conserver suite à l'analyse des valeurs propres\nnComp <- 3\n# Variance expliquée par les axes retenus\nvppct <- round(dfACPvp[1:nComp,\"VP_pct\"],1)\n# Dataframe des résultats pour les variables\nCoordsVar <- res.acp$var$coord[, 1:nComp]\nCos2Var <- res.acp$var$cos2[, 1:nComp]\nCtrVar <- res.acp$var$contrib[, 1:nComp]\ndfACPVars <- data.frame(Variable = row.names(res.acp$var$coord[, 1:nComp]),\n Coord = CoordsVar,\n Cos2 = Cos2Var,\n Qualite = rowSums(Cos2Var),\n Ctr = CtrVar)\nrow.names(dfACPVars) <- NULL\nnames(dfACPVars) <- str_replace(names(dfACPVars), \".Dim.\", \"Comp\")\ndfACPVars\n\n# Histogrammes pour les coordonnées\ncouleursCoords <- c(\"lightsalmon\" , \"steelblue\")\nplotCoordF1 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp1),\n x = CoordComp1, fill = CoordComp1<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords,\n labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 1 (\", vppct[1],\"%)\"), y = \"Variable\")+\n theme(legend.position = \"none\")\nplotCoordF2 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp2),\n x = CoordComp2, fill = CoordComp2<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords,\n labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 2 (\", vppct[2],\"%)\"), y = \"Variable\")+\n theme(legend.position = \"none\")\nplotCoordF3 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp3),\n x = CoordComp3, fill = CoordComp3<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\", values = couleursCoords,\n labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 3 (\", vppct[3],\"%)\"), y = \"Variable\")\n\nannotate_figure(ggarrange(plotCoordF1, plotCoordF2, plotCoordF3, nrow = nComp),\n text_grob(\"Coordonnées des variables sur les axes factoriels\",\n color = \"black\", face = \"bold\", size = 12))\n\n# Contributions des variables à la formation des axes\ncorrplot(CtrVar, is.corr = FALSE, method =\"square\",\n addCoef.col = 1, cl.pos = FALSE)\n\n# La qualité des variables sur les composantes retenues : cosinus carrés\ncorrplot(Cos2Var, is.corr = FALSE, method =\"square\",\n addCoef.col = 1, cl.pos = FALSE)\n\nggplot(dfACPVars)+\n geom_bar(aes(y = reorder(Variable, Qualite), x=Qualite),\n stat = \"identity\", width = .6, alpha = .8, fill = \"steelblue\")+\n labs(x = \"\", y = \"Somme des cosinus carrés sur les axes retenus\",\n title = \"Qualité de représentation des variables sur les axes retenus de l'ACP\",\n subtitle = paste0(\"Variance expliquée par les \", nComp, \n \" composantes : \", sum(vppct), \"%\"))\n```\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Histogrammes personnalisés avec les coordonnées factorielles pour les variables](12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs2-1.png){#fig-acpmesgraphs2 fig-align='center' width=75%}\n:::\n:::\n\n\n![Graphiques personnalisés avec les contributions des variables](images/Chap12/corrplotacpmesgraph3.png){#fig-acpmesgraphs3 width=\"30%\" fig-align=\"center\"}\n\n![Graphiques personnalisés avec les cosinus carrés des variables](images/Chap12/corrplotacpmesgraph4.png){#fig-acpmesgraphs4 width=\"30%\" fig-align=\"center\"}\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Graphique personnalisé avec la qualité des variables sur les axes retenus de l'ACP](12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs5-1.png){#fig-acpmesgraphs5 fig-align='center' width=75%}\n:::\n:::\n\n\nTroisièmement, lorsque les observations sont des unités spatiales, il convient de cartographier les coordonnées factorielles des individus. Dans le jeu de données utilisé, les observations sont des polygones délimitant les îlots regroupés pour l'information statistique (IRIS) pour l'agglomération de Lyon (France). Nous utilisons les *packages* `tmap` et `RColorBrewer` pour réaliser des cartes choroplèthes avec les coordonnées des deux premières composantes (@fig-acpmesgraphs6).\n\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(\"tmap\")\nlibrary(\"RColorBrewer\")\n# Analyse des résultats de l'ACP pour les individus\n# Dataframe des résultats pour les individus\nCoordsInd <- res.acp$ind$coord[, 1:nComp]\nCos2Ind <- res.acp$ind$cos2[, 1:nComp]\nCtrInd <- res.acp$ind$contrib[, 1:nComp]\ndfACPInd <- data.frame(Coord = CoordsInd, Cos2 = Cos2Ind, Ctr = CtrInd)\nnames(dfACPInd) <- str_replace(names(dfACPInd), \".Dim.\", \"Comp\")\n# Fusion du tableau original avec les résultats de l'ACP pour les individus\nCartoACP <- cbind(LyonIris, dfACPInd)\n# Cartographie des coordonnées factorielles pour les individus pour les\n# deux premières composantes\nCarte1 <- tm_shape(CartoACP) +\n tm_polygons(col = \"CoordComp1\", style = \"cont\",\n midpoint = 0, title = \"Coordonnées\")+\n tm_layout(main.title = paste0(\"Axe 1 (\", vppct[1],\"%)\"),\n attr.outside = TRUE, frame = FALSE, main.title.size = 1)\nCarte2 <- tm_shape(CartoACP) +\n tm_polygons(col = \"CoordComp2\", style = \"cont\",\n midpoint = 0, title = \"Coordonnées\")+\n tm_layout(main.title = paste0(\"Axe 2 (\", vppct[2],\"%)\"),\n attr.outside = TRUE, frame = FALSE, main.title.size = 1)\ntmap_arrange(Carte1, Carte2)\n```\n\n::: {.cell-output-display}\n![Cartographie des coordonnées factorielles des individus](12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs6-1.png){#fig-acpmesgraphs6 fig-align='center' width=75%}\n:::\n:::\n\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Exploration interactive des résultats d'une ACP avec le _package_ `explor`**. \n:::\n::: bloc_aller_loin-body\nVous avez compris qu'il ne suffit pas de calculer une ACP, il faut retenir les *n* premiers axes de l'ACP qui nous semblent les plus pertinents, puis les interpréter à la lecture des coordonnées factorielles, des cosinus carrés et des contributions des variables et des individus sur les axes. Il faut donc bien explorer les résultats à l’aide de tableaux et de graphiques! Cela explique que nous avons mobilisé de nombreux graphiques dans les deux sections précédentes ([-@sec-12232] et [-@sec-12233]). \nL’exploration des données d’une ACP peut aussi être réalisée avec des graphiques interactifs. Or, un superbe *package* dénommé [`explor`](https://juba.github.io/explor/), reposant sur [`Shiny`](https://shiny.rstudio.com/), permet d’explorer de manière interactive les résultats de plusieurs méthodes factorielles calculés avec `FactorMinerR`. Pour cela, il vous suffit de lancer les deux lignes de code suivantes :\n\n`library(explor)`\n\n`explor(res.acp)`\n\nFinalement, `explor` permet également d'explorer les résultats d'une analyse des correspondances (AFC) et d'une analyse des correspondances multiples (ACM).\n:::\n:::\n\n## Analyse factorielle des correspondances (AFC) {#sec-123}\n\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**AFC et tableau de contingence**\n:::\n::: bloc_notes-body\nPour bien comprendre l'AFC, il est essentiel de bien maîtriser les notions de tableau de contingence (marges du tableau, fréquences observées et théoriques, pourcentages en ligne et en colonne, contributions au khi-deux) et de distance du khi-deux. Si ce n'est pas le cas, il est conseillé de (re)lire le [chapitre @sec-chap05]. \n:::\n:::\n\nDans le [chapitre @sec-chap05], nous avons vu comment construire un tableau de contingence (@fig-AnalysesFactoriellesTabAFCFig) à partir de deux variables qualitatives comprenant plusieurs modalités, puis comment vérifier s’il y a dépendance entre les deux variables qualitatives avec le test du khi-deux. Or, s’il y a bien dépendance, il est peut-être judicieux de résumer l’information que contient le tableau de contingence en quelques nouvelles variables synthétiques, objectif auquel répond l’analyse factorielle des correspondances (AFC).\n\n\n![Tableau de contingence pour une AFC](images/Chap12/AnalysesFactoriellesTabAFC.png){#fig-AnalysesFactoriellesTabAFCFig width=\"70%\" fig-align=\"center\"}\n\nÀ titre de rappel ([section @sec-1212]), l’AFC a été développée par le statisticien français Jean-Paul Benzécri [-@benzecri1973analyse]. Cela explique qu’elle est souvent enseignée et utilisée en sciences sociales dans les universités francophones, mais plus rarement dans les universités anglophones. Pourtant, les applications de l’AFC sont nombreuses dans différentes disciplines des sciences sociales comme illustrées avec les exemples suivants :\n\n-\tEn géographie, les modalités de la première variable du tableau de contingence sont souvent des entités spatiales (régions, municipalités, quartiers, etc.) croisées avec les modalités d'une autre variable qualitative (catégories socioprofessionnelles, modes de transport, tranches de revenu des ménages ou des individus, etc.).\n\n- En économie régionale, nous pourrions vouloir explorer un tableau de contingence croisant des entités spatiales (par exemple, MRC au Québec, départements en France) et les effectifs d'emplois pour différents secteurs d’activité.\n\n- En sciences politiques, le recours à l’AFC peut être intéressant pour explorer les résultats d’une élection. Les deux variables qualitatives pourraient être les *circonscriptions électorales* et les *partis politiques*. Le croisement des lignes et des colonnes du tableau de contingence représenterait le nombre de votes obtenus par un parti politique *j* dans la circonscription électorale *i*. Appliquer une AFC sur un tel tableau de contingence permettrait de révéler les ressemblances entre les différents partis politiques et celles entre les circonscriptions électorales. \n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Appliquer une ACP sur un tableau de contingence : un bien mauvais calcul...**\n:::\n::: bloc_attention-body\n\nIl pourrait être tentant de transformer le tableau de contingence initial (@tbl-encadreAFCACP1) en un tableau avec les pourcentages en ligne (@tbl-encadreAFCACP2) afin de lui appliquer une analyse en composantes principales. Une telle démarche a deux inconvénients majeurs : chacune des modalités de la première variable qualitative (*I*) aurait alors le même poids; chacune des modalités de la deuxième variable (*J*) aurait aussi le même poids. Or, à la lecture des marges en ligne et en colonne au @tbl-encadreAFCACP1), il est clair que les modalités `j1` et `i1` comprennent bien plus d'individus que les autres modalités respectives.\n\nSi nous reprenons le dernier exemple applicatif, cela signifierait que le même poids est accordé à chaque parti puisque les variables sont centrées réduites en ACP (moyenne = 0 et variance = 1). Autrement dit, les grands partis traditionnels seraient ainsi sur le pied d’égalité que les autres partis. Aussi, chaque circonscription électorale aurait le même poids bien que certaines comprennent bien plus d’électeurs et d’électrices que d’autres.\n\n\n::: {#tbl-encadreAFCACP1 .cell tbl-cap='Exemple de tableau de contingence pour l\\'AFC'}\n::: {.cell-output-display}\nTable: Exemple de tableau de contingence pour l'AFC\n\n| | j1| j2| j3| j4| j5| Marge (ligne)|\n|:---------------|---------:|------:|-------:|-------:|------:|-------------:|\n|i1 | 357 060| 22 010| 276 625| 65 000| 29 415| 750 110|\n|i2 | 427 530| 26 400| 295 860| 69 410| 30 645| 849 845|\n|i3 | 147 500| 6 545| 34 545| 4 415| 1 040| 194 045|\n|i4 | 128 520| 6 405| 42 925| 6 565| 2 670| 187 085|\n|Marge (colonne) | 1 060 610| 61 360| 649 955| 145 390| 63 770| 1 981 085|\n:::\n:::\n\n::: {#tbl-encadreAFCACP2 .cell tbl-cap='Exemple d\\'un tableau de contingence transformé (pourcentage en ligne) pour l\\'ACP'}\n::: {.cell-output-display}\n| | V1| V2| V3| V4| V5|\n|:--|----:|---:|----:|---:|---:|\n|i1 | 47,6| 2,9| 36,9| 8,7| 3,9|\n|i2 | 50,3| 3,1| 34,8| 8,2| 3,6|\n|i3 | 76,0| 3,4| 17,8| 2,3| 0,5|\n|i4 | 68,7| 3,4| 22,9| 3,5| 1,4|\n:::\n:::\n\n:::\n:::\n\n\n### Recherche d'une simplification basée sur la distance du khi-deux {#sec-1231}\n\nSur le plan mathématique et des objectifs visés, l'AFC est similaire à l'ACP puisqu'elle permet d'explorer un tableau de trois façons : 1) en montrant les ressemblances entre un ensemble d'individus (*I*), 2) en révélant les liaisons entre les variables (*J*) et 3) en résumant le tout avec des variables synthétiques. Toutefois, avec l'AFC, les ensembles *I* et *J* sont les modalités de deux variables qualitatives (dont le croisement forme un tableau de contingence) et elle est basée sur la distance du khi-deux (et non sur la distance euclidienne comme en ACP).\n\nAinsi, avec la distance du khi-deux, la proximité (ressemblance) entre deux lignes (*i* et *l*) et deux colonnes (*j* et *k*) est mesurée comme suit :\n\n$$\nd_{\\chi_{il}^2} = \\sum_j \\frac{1}{f_{.j}}(\\frac{f_{ij}}{f_{i.}}-\\frac{f_{lj}}{f_{l.}})^2\n$$ {#eq-khideuxlignes}\n\n$$\nd_{\\chi_{jk}^2} = \\sum_i \\frac{1}{f_{i.}}(\\frac{f_{ij}}{f_{.j}}-\\frac{f_{ik}}{f_{.k}})^2\n$$ {#eq-khideuxcolonnes}\n\nPrenons un exemple fictif pour calculer ces deux distances. Le @tbl-afcdataex1 comprend trois modalités en ligne (*I*) et trois autres en colonne (*J*). Le total des effectifs de ce tableau de contingence est égal à 1 665.\n\nÀ partir des données brutes, il est facile de construire deux tableaux : le profil des lignes et le profil des colonnes (@tbl-afcProfilsLignesCols, c'est-à-dire les proportions en ligne et en colonne.\n\n\n::: {#tbl-afcdataex1 .cell tbl-cap='Données brutes du tableau de contingence'}\n::: {.cell-output-display}\n| | j1 | j2 | j3 | Total (ligne) |\n|:---------------|:---:|:---:|:---:|:-------------:|\n|i1 | 360 | 65 | 275 | 700 |\n|i2 | 420 | 70 | 290 | 780 |\n|i3 | 145 | 5 | 35 | 185 |\n|Total (colonne) | 925 | 140 | 600 | 1 665 |\n:::\n:::\n\n::: {#tbl-afcProfilsLignesCols .cell tbl-cap='Profils des lignes et des colonnes'}\n::: {.cell-output-display}\n`````{=html}\n\n \n \n \n \n \n \n \n \n \n\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
j1 j2 j3 Total
Profil des lignes
i1 0,514 0,093 0,393 1
i2 0,538 0,090 0,372 1
i3 0,784 0,027 0,189 1
Profils des colonnes
i1 0,389 0,464 0,458
i2 0,454 0,500 0,483
i3 0,157 0,036 0,058
Total 1,000 1,000 1,000
\n\n`````\n:::\n:::\n\n\nEn divisant les valeurs du @tbl-afcdataex1 par le grand total (1 665), nous obtenons tous les termes utilisés dans les équations [-@eq-khideuxlignes] et [-@eq-khideuxcolonnes] au @tbl-afcdataex2 :\n\n- Les fréquences relatives dénommées $f_{ij}$. \n- La marge $fi.$ est égale à la somme des fréquences relatives en ligne.\n- La marge $f.j$ est égale à la somme des fréquences relatives en colonne.\n- La somme de toutes les fréquences relatives est donc égale à 1, soit $\\sum{f_{i.}}$ ou $\\sum{f_{.j}}$.\n\n\n\n::: {#tbl-afcdataex2 .cell tbl-cap='Données relatives du tableau de contingence (fij)'}\n::: {.cell-output-display}\n| | j1| j2| j3| Total (fi.)|\n|:-----------|-----:|-----:|-----:|-----------:|\n|i1 | 0,216| 0,039| 0,165| 0,420|\n|i2 | 0,252| 0,042| 0,174| 0,468|\n|i3 | 0,087| 0,003| 0,021| 0,111|\n|Total (f.j) | 0,556| 0,084| 0,360| 1,000|\n:::\n:::\n\n\nIl est possible de calculer les distances entre les différentes modalités de *I* en appliquant l'@eq-khideuxlignes; par exemple, la distance entre les observations `i1` et `i2` est égale à :\n\n$$d_{(i1,i2)}=\\frac{\\mbox{1}}{\\mbox{0,556}}(\\mbox{0,216}-\\mbox{0,252})^2+\\frac{\\mbox{1}}{\\mbox{0,084}}(\\mbox{0,039}-\\mbox{0,042})^2+\n\\frac{\\mbox{1}}{\\mbox{0,360}}(\\mbox{0,165}-\\mbox{0,174})^2=\\mbox{0,003}$$\n\nAvec l'@eq-khideuxcolonnes, la distance entre les modalités `j1` et `j2` de *J* est égale à :\n\n$$d_{(j1,j2)}=\\frac{\\mbox{1}}{\\mbox{0,420}}(\\mbox{0,216}-\\mbox{0,039})^2+ \\frac{\\mbox{1}}{\\mbox{0,468}}(\\mbox{0,252}-\\mbox{0,042})^2 + \\frac{\\mbox{1}}{\\mbox{0,111}}(\\mbox{0,087}-\\mbox{0,003})^2=\\mbox{0,233}$$\n\n\nÀ la lecture du @tbl-MatriceDistKhi, les modalités les plus semblables sont \n`i1` et `i2` (0,003) pour *I* et `j1` et `j3` (0,058) pour *J*.\n\n\n::: {#tbl-MatriceDistKhi .cell tbl-cap='Distances du khi-deux entre les modalités I et les modalités J'}\n::: {.cell-output-display}\n| Ind. | i1 | i2 | i3 | Col. | j1 | j2 | j3 |\n|:----:|:-----:|:-----:|:-----:|:----:|:-----:|:-----:|:-----:|\n| i1 | 0,000 | 0,003 | 0,103 | j1 | 0,000 | 0,233 | 0,058 |\n| i2 | 0,003 | 0,000 | 0,132 | j2 | 0,233 | 0,000 | 0,078 |\n| i3 | 0,103 | 0,132 | 0,000 | j3 | 0,058 | 0,078 | 0,000 |\n:::\n:::\n\n\nFinalement, l'approche pour déterminer les axes factoriels de l'AFC est similaire à celle de l'ACP : les axes factoriels sont les droites orthogonales qui minimisent les distances aux points du profil des lignes, excepté que la métrique pour mesurer ces distances est celle du khi-deux (et non celle la distance euclidienne comme pour l'ACP). Pour plus détails sur le calcul de ces axes (notamment les formulations matricielles), consultez notamment Benzécri [-@benzecri1973analyse], Escofier et Pagès [-@escofier1998analyses] et Lebart et al. [-@lebart1995statistique].\n\n\n### Aides à l'interprétation {#sec-1232}\n\nPour illustrer les aides à l’interprétation de l’AFC, nous utilisons un jeu de données spatiales extrait du [profil du recensement de 2016 de Statistique Canada](https://www12.statcan.gc.ca/census-recensement/2016/dp-pd/prof/index.cfm?Lang=F){target='_blank'} pour les secteurs de recensement de l'île de Montréal. La liste des modalités des variables qu'il comprend est reportée au @tbl-dataAfc. L'AFC est calculée sur un tableau de contingence croisant les secteurs de recensement (lignes) et les modalités d'une variable relative au mode de transport utilisé pour les déplacements domicile-travail (colonnes). Ces modalités sont cartographiées à la @fig-cartovarAFC).\n\n\n::: {#tbl-dataAfc .cell tbl-cap='Jeu de données utilisé pour l\\'analyse factorielle des correspondances'}\n::: {.cell-output-display}\n`````{=html}\n\n \n \n \n \n \n \n \n \n\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
Nom Intitulé Somme
Modalités de la variable utilisée dans l'AFC (mode de transport)
VehCond VehCond Véhicule motorisé (conducteur·trice) 427 560
VehPass VehPass Véhicule motorisé (passager·ère) 26 490
TranspC TranspC Transport en commun 295 800
Apied Apied À pied 69 330
Velo Velo Bicyclette 30 615
AutreMoyen AutreMoyen Autre moyen 7 750
Modalités de la variable supplémentaire (durée du trajet)
T15min T15min Moins de 15 minutes 130 435
T1529min T1529min 15 à 29 minutes 287 500
T3044min T3044min 30 à 44 minutes 244 425
T4559min T4559min 45 à 59 minutes 107 065
T60plus T60plus 60 minutes et plus 88 050
\n\n`````\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Cartographie des modalités de la variable mode de transport utilisée pour l'AFC](12-AnalysesFactorielles_files/figure-html/fig-cartovarAFC-1.png){#fig-cartovarAFC fig-align='center' width=100%}\n:::\n:::\n\n\n#### Résultats de l'AFC pour les valeurs propres {#sec-12321}\n\nAvant de calculer l'AFC, il convient de vérifier s'il y a bien une dépendance entre les modalités des deux variables qualitatives. En effet, si les deux variables sont indépendantes, il n'est pas nécessaire de résumer le tableau de contingence avec une AFC. Pour ce faire, nous utilisons le test du khi-deux largement décrit à la [section @sec-052]. Les résultats de ce test signalent qu’il existe des associations entre les modalités des deux variables ($\\chi$ = 203 971, *p* < 0,001, @tbl-dataafckhi2). Nous pouvons donc appliquer une AFC sur ce tableau de contingence.\n\n\n::: {#tbl-dataafckhi2 .cell tbl-cap='Résultats du test du khi-deux sur le tableau de contingence'}\n::: {.cell-output-display}\n|Mesure | Valeur|\n|:---------------------------------------------------|----------:|\n|Modalités *I* (secteurs de recensement) | 521,00|\n|Modalités *J* (variable mode de transport) | 6,00|\n|Somme des données brutes ($n_{ij}$) | 857 545,00|\n|Khi-deux ($\\chi^2$) | 207 129,27|\n|Degrés de liberté, soit $(c-1)\\times(l-1)$ | 2 600,00|\n|Valeur de *p* | 0,00|\n|Coefficient Phi au carré ($\\phi^2=\\chi^2 / n_{ij})$ | 0,24|\n:::\n:::\n\n\nNous avons vu qu'en ACP normée ([section @sec-12221]), la somme des valeurs propres est égale au nombre de variables puisqu'elles sont centrées réduites. Par contre, en AFC, cette somme est égale à l'inertie totale du tableau de contingence, c'est-à-dire à la valeur du khi-deux divisée par le nombre total des effectifs bruts (soit le coefficient phi au carré, $\\phi^2$) ([section @sec-052]). Le @tbl-dataafcValeurPropres permet de vérifier que la somme des valeurs propres est bien égale au coefficient phi au carré : \n\n$$\\mbox{0,156}+\\mbox{0,046}+\\mbox{0,031}+\\mbox{0,004}+\\mbox{0,004} = \\mbox{0,24}$$\n\n$$\\phi^2 = \\chi^2 / n_{ij}=\\mbox{203 971}/ \\mbox{849 795} = \\mbox{0,24}$$\n\n::: {#tbl-dataafcValeurPropres .cell tbl-cap='Résultats de l\\'AFC pour les valeurs propres'}\n::: {.cell-output-display}\n| | Axe factoriel| Valeur propre| Pourcentage| Pourc. cumulé|\n|:-----|-------------:|-------------:|-----------:|-------------:|\n|dim 1 | 1| 0,156| 64,590| 64,590|\n|dim 2 | 2| 0,046| 19,250| 83,840|\n|dim 3 | 3| 0,031| 12,995| 96,835|\n|dim 4 | 4| 0,004| 1,683| 98,518|\n|dim 5 | 5| 0,004| 1,482| 100,000|\n:::\n:::\n\n\n**Combien d'axes d'une AFC faut-il retenir?**\n\n- **Approche statistique**. Mike Bendixen [-@bendixen1995compositional], cité dans l'excellent site [STHDA](http://www.sthda.com/){target='_blank'}, propose deux critères pour sélectionner les premiers axes d'une AFC : $c_1= 1 / (l-1) \\times 100$ et $c_2= 1 / (c-1) \\times 100$ avec *l* et *c* étant respectivement les nombres de modalités en ligne et en colonne. Autrement dit, lorsque les données sont distribuées aléatoirement, la valeur propre en pourcentage devrait être égale à $c_1$ et celle de l'axe factoriel moyen à $c_2$. Par conséquent, nous pourrions retenir uniquement les axes dont les valeurs propres en pourcentage excèdent : $c_1 = \\mbox{1}/(\\mbox{521}-\\mbox{1})\\times \\mbox{100}=\\mbox{0,19 }%$ et $c_2=\\mbox{1}/(\\mbox{6}-\\mbox{1})\\times \\mbox{100}=\\mbox{20 }%$. En appliquant ces deux critères, seul le premier axe factoriel qui résume 65,6 % mérite d'être retenu.\n\n- **Approche empirique** basée sur la lecture des pourcentages et des pourcentages cumulés. Nous retenons uniquement les deux premières composantes qui résument 85 % de la variance totale. Pour faciliter le choix du nombre d'axes avec cette approche empirique, il est fortement conseillé de construire un histogramme à partir des valeurs propres, soit brutes, soit en pourcentage, soit en pourcentage cumulé (@fig-afcGraphVP).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Histogramme des valeurs propres de l'AFC](12-AnalysesFactorielles_files/figure-html/fig-afcGraphVP-1.png){#fig-afcGraphVP fig-align='center' width=80%}\n:::\n:::\n\n\n#### Résultats de l'AFC pour les variables et les individus {#sec-12322}\nComme pour l'ACP, nous retrouvons les trois mêmes mesures pour les variables et les individus : 1) les coordonnées factorielles, 2) les contributions et 3) les cosinus carrés. \n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Compréhension des axes factoriels de l'AFC : une étape essentielle, incontournable...**\n:::\n::: bloc_objectif-body\nComme en ACP, l'analyse des trois mesures (coordonnées, contributions et cosinus carrés) pour les variables et les individus doit vous permettre de comprendre la signification des axes factoriels retenus de l'AFC. Cette étape d'interprétation est essentielle afin de qualifier les variables latentes (axes factoriels, variables synthétiques) produites par l'AFC.\n:::\n:::\n\n\n- **Les coordonnées factorielles** sont simplement les projections des points-lignes et des points-colonnes sur les axes de l'AFC. Tant pour les lignes que pour les colonnes, ces coordonnées bénéficient de deux propriétés intéressantes. Premièrement, pour chaque axe factoriel *k*, la somme du produit des marges des variables ($f.j$, colonnes) ou des individus ($fi.$, lignes) avec leurs coordonnées respectives ($C^k_j$ et $C^k_i$) est égale à 0 (@eq-CoordPropr1). Deuxièmement, pour chaque axe factoriel *k*, la somme des produits entre les marges (en ligne et en colonne) et les coordonnées au carré (en ligne et en colonne) est égale à la valeur propre de l'axe (@eq-CoordPropr2).\n\n$$\n\\sum{f.j (C^k_j)}= 0 \\text{ et} \\sum{fi. (C^k_i)}= 0\n$$ {#eq-CoordPropr1}\n\n$$\n\\sum{fi. (C^k_i)^2}= \\mu_k \\text{ et} \\sum{f.j (C^k_j)^2}= \\mu_k\n$$ {#eq-CoordPropr2}\n\nEn guise d'exemple, le @tbl-dataafcCoordVars2 permet de vérifier les deux propriétés des coordonnées pour les variables. Les sommes de ${f.j (C^k_j)}$ pour les axes 1 et 2 sont bien égales à 0; et les sommes de ${f.j (C^k_j)^2}$ pour les axes 1 et 2 sont bien égales aux valeurs propres de ces deux axes, soit 0,156 et 0,046 (comparez ces valeurs avec celles reportées au @tbl-dataafcValeurPropres plus haut).\n\n\n::: {#tbl-dataafcCoordVars2 .cell tbl-cap='Vérification des deux propriétés des coordonnées factorielles pour les variables'}\n::: {.cell-output-display}\n`````{=html}\n\n \n\n\n\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
Coord.
f.j x Coord.
f.j x Coord2
Modalité f.j 1 2 1 2 1 2
VehCond 0,499 -0,329 0,077 -0,164 0,038 0,054 0,003
VehPass 0,031 -0,255 0,081 -0,008 0,003 0,002 0,000
TranspC 0,345 0,208 -0,229 0,072 -0,079 0,015 0,018
Apied 0,081 0,813 0,545 0,066 0,044 0,053 0,024
Velo 0,036 0,938 -0,187 0,033 -0,007 0,031 0,001
AutreMoyen 0,009 0,142 0,078 0,001 0,001 0,000 0,000
Somme 1,000 0,000 0,000 0,156 0,046
\n\n`````\n:::\n:::\n\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Particularité de l'AFC**\n:::\n::: bloc_attention-body\nContrairement à l'ACP, les coordonnées factorielles pour les variables en AFC ne sont pas les coefficients de corrélation de Pearson des variables sur les axes!\n:::\n:::\n\n- **Les contributions** des colonnes ou des lignes en AFC permettent de repérer celles qui contribuent le plus à la formation des axes factoriels (de manière analogue à l'ACP). Pour un axe donné, leur sommation est égale à 100 %. Elles s'obtiennent en multipliant la coordonnée au carré avec la marge et en divisant le tout par la valeur propre de l'axe (équations [-@eq-CtrAFCVar] et [-@eq-CtrAFCInd]).\n\n$$\n\\mbox{Ctr}_j^k =\\frac{f.j(C^k_j)^2}{\\mu_{k}}\\times 100\n$$ {#eq-CtrAFCVar}\n\n$$\n\\mbox{Ctr}_i^k =\\frac{fi.(C^k_i)^2}{\\mu_{k}}\\times 100\n$$ {#eq-CtrAFCInd}\n\n- **Les cosinus carrés** (Cos^2^) (appelés aussi les qualités de représentation sur un axe) permettent de repérer le ou les axes qui concourent le plus à donner un sens aux colonnes (variables) et aux lignes (individus), de manière analogue à l'ACP. Pour une variable ou un individu, la sommation des Cos^2^ pour tous les axes de l'AFC est aussi égale à 1.\n\n**Interprétation des résultats pour les colonnes (variables)**\n\nMaintenant, analysons ces trois statistiques pour les variables pour les deux premiers axes de l'AFC (@tbl-dataafcCoordVars et @fig-afc1erplanfactVars).\n\nPour l'axe 1, résumant 65 % de la variance, trois modalités concourent à sa formation : `VehCond` (34,69 %), `Apied` (34,25 %) et `Velo` (20,13 %). À la lecture des coordonnées factorielles sur cet axe, les modes de transport relatifs aux véhicules motorisés (`VehCond` = -0,33 et `VehPass` = -0,25) s'opposent clairement aux modes actifs (`Apied` = 0,81 et `Velo` = 0,94), constat qu'il est possible de confirmer visuellement avec la @fig-afc1erplanfactVars. La modalité `VehCond` a d'ailleurs la plus forte valeur de Cos^2^ sur cet axe (0,92), ce qui signale, sans l'ombre d'un doute, que l'axe 1 est celui qui donne le plus de sens à cette modalité. \n\nPuisque l'axe 2 résume une partie beaucoup plus limitée de la variance du tableau (19,25 %), il n'est pas étonnant qu'un nombre plus limité de modalités concourent à sa formation : seules les contributions de la modalité `Apied` (51,68 %) et secondairement de `TranspC` (38,81 %) sont importantes. Leurs coordonnées factorielles s'opposent d'ailleurs sur cet axe (respectivement 0,81 et 0,21).\n\n\n\n::: {#tbl-dataafcCoordVars .cell tbl-cap='Résultats de l\\'AFC pour les variables'}\n::: {.cell-output-display}\n`````{=html}\n\n \n\n\n\n\n\n\n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
Coordonnées
Cosinus carrés
Contributions (%)
Modalité 1 2 1 2 1 2
VehCond -0,33 0,08 0,92 0,05 34,69 6,33
VehPass -0,25 0,08 0,34 0,03 1,28 0,44
TranspC 0,21 -0,23 0,39 0,47 9,53 38,81
Apied 0,81 0,54 0,67 0,30 34,25 51,61
Velo 0,94 -0,19 0,56 0,02 20,13 2,69
AutreMoyen 0,14 0,08 0,05 0,01 0,12 0,12
\n\n`````\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Premier plan factoriel de l'AFC pour les variables](12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactVars-1.png){#fig-afc1erplanfactVars fig-align='center' width=75%}\n:::\n:::\n\n \n \n**Interprétation des résultats pour les individus**\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Premier plan factoriel pour les variables et les individus**\n:::\n::: bloc_notes-body\nLorsque le jeu de données comprend à la fois peu de modalités en ligne et en colonne, il est judicieux de les représenter simultanément sur le premier plan factoriel (axes 1 et 2). Pour ce faire, vous pouvez utiliser la fonction `fviz_ca_biplot` du *package* `factoextra`.\n:::\n:::\n\nÉtant donné que notre jeu de données comprend 521 secteurs de recensement, nous proposons ici de cartographier les coordonnées factorielles des individus pour les deux premiers axes de l'AFC (@fig-afc1erplanfactInds2). Pour l'axe 1, les secteurs de recensement à l'est et l'ouest de l'île de Montréal présentent les coordonnées les plus fortement négatives (en rouge); dans ces zones, l'usage des véhicules motorisés pour des déplacements domicile-travail est certainement surreprésenté, comparativement aux modes actifs. À l'inverse, dans les secteurs de recensement du centre de l'île présentant de fortes valeurs positives (en rouge), le recours aux modes de transports actifs (marche et vélo) est bien plus important, toutes proportions gardées. Quant à la cartographie des coordonnées pour l'axe 2, elle permet surtout de repérer quelques secteurs de recensement autour du centre-ville (très fortes valeurs positives en vert foncé) où les déplacements domicile-travail à pied sont plus fréquents, toutes proportions gardées.\n\nEn résumé, suite à l'analyse des coordonnées factorielles des variables et des individus, nous pouvons conclure que le premier axe est certainement le plus intéressant puisqu’il permet d'opposer l’usage des modes de transports motorisés versus les modes de transports actifs pour les déplacements domicile-travail sur l'île de Montréal. Cette nouvelle variable synthétique (variable latente) pourrait ainsi être introduite dans des analyses subséquentes (par exemple, dans un modèle de régression). Cela démontre qu’au même titre que l’ACP, l’AFC est une méthode de réduction de données puisque nous sommes passés d’un tableau comprenant 512 secteurs de recensement et six modalités à un tableau comprenant une seule variable synthétique (axe 1).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Cartographie de coordonnées factorielles des individus pour l'AFC](12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactInds2-1.png){#fig-afc1erplanfactInds2 fig-align='center' width=672}\n:::\n:::\n\n\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Ajout de modalités supplémentaires dans une analyse des correspondances (AFC)**\n:::\n::: bloc_aller_loin-body\nComme pour l'ACP, il est possible d'ajouter des variables et des individus supplémentaires une fois l'AFC calculée. En guise d'illustration, nous avons ajouté à l'AFC précédemment analysée des modalités relatives à la durée des temps de déplacements :\tmoins de 15 minutes, 15 à 29, 30 à 44, 45 à 59, 60 minutes et plus. Sans surprise, sur le premier plan factoriel à la @fig-afc1erplanfactInds2, cette dernière modalité, représentant les trajets les plus longs, est la plus proche des modalités relatives à l'usage des véhicules motorisés (`VehCond` et `VehPass`).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Ajout de modalités supplémentaires sur le premier plan factoriel de l'AFC](12-AnalysesFactorielles_files/figure-html/fig-afcAjoutModalites-1.png){#fig-afcAjoutModalites fig-align='center' width=75%}\n:::\n:::\n\n:::\n:::\n\n### Mise en œuvre dans R {#sec-1233}\n\n#### Calcul d’une AFC avec `FactoMineR` {#sec-12331}\n\nPlusieurs *packages* permettent de calculer une AFC dans R, notamment `ca` (fonction `ca`), `MASS` (fonction `corresp`), `ade4` (fonction `dudi.coa`) et `FactoMineR` (fonction `CA`). De nouveau, nous utilisons `FactoMineR` couplé au *package* `factoextra` pour réaliser rapidement des graphiques avec les résultats pour les variables et les coordonnées.\n\nPour calculer l'AFC, il suffit d'utiliser la fonction `CA` de `FactoMineR`, puis la fonction `summary(res.afc)`, qui renvoie les résultats de l'AFC pour : \n\n- Les valeurs propres (section `Eigenvalues`) pour les axes factoriels (`Dim.1` à `Dim.n`) avec leur variance expliquée brute (`Variance`), en pourcentage (`% of var.`) et en pourcentage cumulé (`Cumulative % of var.`).\n\n- Les dix premières observations (section `Rows`) avec les coordonnées factorielles (`Dim.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`). Pour accéder aux résultats pour toutes les observations, utilisez les fonctions `res.afc$row` ou encore `res.afc$row$coord` (uniquement les coordonnées factorielles), `res.afc$row$contrib` (uniquement les contributions) et `res.afc$row$cos2` (uniquement les cosinus carrés).\n\n- Les colonnes (section `Columns`) avec les coordonnées factorielles (D`im.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`).\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Chargement des packages\nlibrary(FactoMineR)\nlibrary(factoextra)\n# Chargement des données\nload(\"data/analysesfactorielles/DonneesAFC.Rdata\")\n# Avant de calculer l'AFC, il convient de vérifier si les deux variables\n# qualitatives sont dépendantes avec le test du khi-deux\nkhideux <- chisq.test(dfDonneesAFC[,1:6])\nprint(khideux)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\n\tPearson's Chi-squared test\n\ndata: dfDonneesAFC[, 1:6]\nX-squared = 207129, df = 2600, p-value < 2.2e-16\n```\n:::\n\n```{.r .cell-code}\nif(khideux$p.value <=0.05){\n cat(\"La valeur de p < 0,05. Les variables sont dépendantes. Calculez l'AFC.\")\n}else {\n cat(\"La valeur de p > 0,05. Les variables sont indépendantes. Inutile de calculer l'AFC\")\n}\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nLa valeur de p < 0,05. Les variables sont dépendantes. Calculez l'AFC.\n```\n:::\n\n```{.r .cell-code}\n# Calcul de l'analyse des correspondances sur les six premières variables\nres.afc <- CA(dfDonneesAFC[,1:6], graph = FALSE)\n# Affichage des résultats de la fonction CA\nprint(res.afc)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n**Results of the Correspondence Analysis (CA)**\nThe row variable has 521 categories; the column variable has 6 categories\nThe chi square of independence between the two variables is equal to 207129.3 (p-value = 0 ).\n*The results are available in the following objects:\n\n name description \n1 \"$eig\" \"eigenvalues\" \n2 \"$col\" \"results for the columns\" \n3 \"$col$coord\" \"coord. for the columns\" \n4 \"$col$cos2\" \"cos2 for the columns\" \n5 \"$col$contrib\" \"contributions of the columns\"\n6 \"$row\" \"results for the rows\" \n7 \"$row$coord\" \"coord. for the rows\" \n8 \"$row$cos2\" \"cos2 for the rows\" \n9 \"$row$contrib\" \"contributions of the rows\" \n10 \"$call\" \"summary called parameters\" \n11 \"$call$marge.col\" \"weights of the columns\" \n12 \"$call$marge.row\" \"weights of the rows\" \n```\n:::\n\n```{.r .cell-code}\n# Visualisation des marges en colonne\nround(res.afc$call$marge.col,4)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n VehCond VehPass TranspC Apied Velo AutreMoyen \n 0.4986 0.0309 0.3449 0.0808 0.0357 0.0090 \n```\n:::\n\n```{.r .cell-code}\n# Visualisation des marges en ligne. Étant donné que nous avons 521 individus, \n# la ligne ci-dessous est en commentaire\n# round(res.afc$call$marge.row,4)\n\n# Sommaire des résultats de l'AFC\n# Remarquez que la première ligne de ce sommaire est le résultat du khi-deux\nsummary(res.afc)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCall:\nCA(X = dfDonneesAFC[, 1:6], graph = FALSE) \n\nThe chi square of independence between the two variables is equal to 207129.3 (p-value = 0 ).\n\nEigenvalues\n Dim.1 Dim.2 Dim.3 Dim.4 Dim.5\nVariance 0.156 0.046 0.031 0.004 0.004\n% of var. 64.590 19.250 12.995 1.683 1.482\nCumulative % of var. 64.590 83.840 96.835 98.518 100.000\n\nRows (the 10 first)\n Iner*1000 Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3\n1 | 0.155 | -0.304 0.095 0.961 | -0.023 0.002 0.006 | 0.048\n2 | 0.123 | -0.232 0.067 0.850 | 0.028 0.003 0.012 | -0.021\n3 | 0.268 | -0.246 0.127 0.737 | -0.002 0.000 0.000 | -0.046\n4 | 0.102 | -0.168 0.034 0.513 | -0.111 0.049 0.222 | -0.117\n5 | 0.118 | -0.251 0.067 0.883 | 0.004 0.000 0.000 | -0.007\n6 | 0.120 | -0.130 0.024 0.313 | -0.103 0.051 0.196 | -0.144\n7 | 0.124 | -0.029 0.002 0.022 | -0.158 0.167 0.626 | -0.079\n8 | 0.073 | -0.157 0.028 0.598 | -0.090 0.031 0.195 | -0.006\n9 | 0.014 | -0.060 0.005 0.506 | -0.033 0.005 0.150 | -0.018\n10 | 0.040 | 0.004 0.000 0.000 | -0.204 0.073 0.838 | 0.053\n ctr cos2 \n1 0.012 0.024 |\n2 0.003 0.007 |\n3 0.022 0.026 |\n4 0.080 0.246 |\n5 0.000 0.001 |\n6 0.146 0.380 |\n7 0.061 0.155 |\n8 0.000 0.001 |\n9 0.002 0.048 |\n10 0.007 0.056 |\n\nColumns\n Iner*1000 Dim.1 ctr cos2 Dim.2 ctr cos2 Dim.3\nVehCond | 58.559 | -0.329 34.687 0.924 | 0.077 6.331 0.050 | 0.051\nVehPass | 5.923 | -0.255 1.283 0.338 | 0.081 0.440 0.035 | 0.001\nTranspC | 38.261 | 0.208 9.534 0.389 | -0.229 38.812 0.472 | -0.124\nApied | 79.193 | 0.813 34.252 0.675 | 0.545 51.610 0.303 | -0.147\nVelo | 55.633 | 0.938 20.126 0.564 | -0.187 2.688 0.022 | 0.802\nAutreMoyen | 3.969 | 0.142 0.117 0.046 | 0.078 0.119 0.014 | 0.070\n ctr cos2 \nVehCond 4.141 0.022 |\nVehPass 0.000 0.000 |\nTranspC 16.995 0.139 |\nApied 5.543 0.022 |\nVelo 73.180 0.413 |\nAutreMoyen 0.140 0.011 |\n```\n:::\n:::\n\n\n#### Exploration graphique des résultats de l'AFC avec `factoextra` {#sec-12332}\n\nComme pour l'ACP, `factoextra` dispose de plusieurs fonctions très intéressantes pour construire rapidement des graphiques avec les résultats de l'AFC. Premièrement, la syntaxe ci-dessous (avec la fonction `fviz_screeplot`) renvoie deux graphiques pour analyser les résultats des valeurs propres de l'AFC (@fig-factoextraAFC1).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(factoextra)\nlibrary(ggplot2)\nlibrary(ggpubr)\n\n# Nombre de modalités en ligne et en colonne\nModalitesLig <- nrow(dfDonneesAFC)\nModalitesCol <- ncol(dfDonneesAFC[,1:6])\n# Critère statistique du profil moyen\ncritere2 <- round(1/(ModalitesCol-1)*100,2)\ntexte <- paste0(\"Critère pour le profil moyen : \", as.character(critere2), \" %\")\n# Graphique avec les valeurs propres\nG1 <- fviz_screeplot(res.afc, choice = \"eigenvalue\",\n ylab = \"Valeurs propres\",\n xlab = \"Axes factoriels\",\n main=\"Valeurs propres\")\nG2 <- fviz_screeplot(res.afc, choice = \"variance\", addlabels = TRUE, ylim = c(0, 70),\n ylab = \"Variance expliquée (%)\",\n xlab = \"Axes factoriels\",\n main=\"Valeurs propres (%)\")+\n geom_hline(yintercept=c2, linetype=1, color = \"red\", linewidth = 1)+\n annotate(geom = \"text\", x = ModalitesCol-.5,\n y = critere2+3, label=texte, \n color = \"red\", hjust=1, linewidth = 4)\n```\n\n::: {.cell-output .cell-output-stderr}\n```\nWarning in annotate(geom = \"text\", x = ModalitesCol - 0.5, y = critere2 + :\nIgnoring unknown parameters: `linewidth`\n```\n:::\n\n```{.r .cell-code}\nggarrange(G1, G2)\n```\n\n::: {.cell-output-display}\n![Graphiques pour les valeurs propres de l'AFC avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-factoextraAFC1-1.png){#fig-factoextraAFC1 fig-align='center' width=65%}\n:::\n:::\n\n\nAvec les fonctions `fviz_contrib` et `fviz_cos2`, il est très facile de réaliser des histogrammes pour les contributions et les cosinus carrés pour les variables (colonnes) ou les individus (lignes), et ce, avec le paramètre `choice = c(\"row\", \"col\")` (@fig-acp1erplanfactVars2a).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(factoextra)\nlibrary(ggplot2)\nlibrary(ggpubr)\nVP1pct <- round(res.afc$eig[1,2],2)\nVP2pct <- round(res.afc$eig[2,2],2)\nG1 <- fviz_contrib (res.afc, choice = \"col\", axes = 1, title = \"Axe 1\")\nG2 <- fviz_contrib (res.afc, choice = \"col\", axes = 2, title = \"Axe 2\")\nggarrange(G1, G2, ncol = 2, nrow = 1)\n```\n\n::: {.cell-output-display}\n![Contributions des variables avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-acp1erplanfactVars2a-1.png){#fig-acp1erplanfactVars2a fig-align='center' width=65%}\n:::\n:::\n\n\nQuant aux fonctions `fviz_ca_col` et `fviz_ca_row`, elles permettent rapidement de construire le premier plan factoriel pour les colonnes (variables) et les lignes (individus) (@fig-afc1erplanfactVars2b). Aussi, la fonction `fviz_ca_biplot` permet de construire un plan factoriel, mais avec les lignes et les colonnes simultanément.\n \n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nG3 <- fviz_ca_col(res.afc,\n repel = TRUE,\n geom = c(\"text\" , \"point\"),\n col.col = \"steelblue\",\n title = \"Mode de transport\",\n xlab = paste0(\"Axe 1 (\", VP1pct, \" %)\"),\n ylab = paste0(\"Axe 2 (\", VP2pct, \" %)\"))\nG4 <- fviz_ca_row(res.afc,\n repel = TRUE,\n geom = c(\"point\"),\n col.row = \"steelblue\",\n title = \"Secteurs de recensement\",\n xlab = paste0(\"Axe 1 (\", VP1pct, \" %)\"),\n ylab = paste0(\"Axe 2 (\", VP2pct, \" %)\"))\nggarrange(G3, G4, ncol = 2, nrow = 1)\n```\n\n::: {.cell-output-display}\n![Premier plan factoriel de l'AFC pour les variables et les individus avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactVars2b-1.png){#fig-afc1erplanfactVars2b fig-align='center' width=65%}\n:::\n:::\n\n\n\nLa syntaxe ci-dessous permet d'ajouter des modalités supplémentaires dans l'AFC et de constuire le graphique du premier plan factoriel (@fig-afcAjoutModalites2).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Les colonnes 7 à 11 sont mises comme des variables supplémentaires dans l'AFC\nres.afc2 <- CA(dfDonneesAFC, col.sup = 7:11, graph = FALSE)\nVP1pct <- round(res.afc2$eig[1,2],2)\nVP2pct <- round(res.afc2$eig[2,2],2)\nfviz_ca_col(res.afc2,\n repel = TRUE,\n geom= c(\"text\" , \"point\"),\n col.col = \"steelblue\",\n title = \"\",\n xlab=paste0(\"Axe 1 (\", VP1pct, \" %)\"),\n ylab=paste0(\"Axe 2 (\", VP2pct, \" %)\"))\n```\n\n::: {.cell-output-display}\n![Ajout de modalités supplémentaires sur le premier plan factoriel l'AFC avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-afcAjoutModalites2-1.png){#fig-afcAjoutModalites2 fig-align='center' width=65%}\n:::\n:::\n\n\nFinalement, la syntaxe ci-dessous permet de cartographier les coordonnées factorielles des individus de l’AFC avec le *package* `tmap` (@fig-afc1erplanfactInds2B).\n \n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(tmap)\nlibrary(stringr)\ndfAFCInd <- data.frame(Coord = res.afc$row$coord, \n Cos2 = res.afc$row$cos2, \n Ctr = res.afc$row$contrib)\nnames(dfAFCInd) <- str_replace(names(dfAFCInd), \".Dim.\", \"Comp\")\nCartoAFC <- cbind(sfDonneesAFC, dfAFCInd)\nVP1pct <- tofr(round(res.afc$eig[1,2],2))\nVP2pct <- tofr(round(res.afc$eig[2,2],2))\nCarte1 <- tm_shape(CartoAFC) +\n tm_fill(col = \"CoordComp1\", style = \"cont\", midpoint = 0, title = \"Coordonnées\")+\n tm_layout(title = paste0(\"Axe 1 (\", VP1pct,\"%)\"), attr.outside = TRUE, frame = FALSE)\nCarte2 <- tm_shape(CartoAFC) +\n tm_fill(col = \"CoordComp2\", style = \"cont\", midpoint = 0, title = \"Coordonnées\")+\n tm_layout(title = paste0(\"Axe 2 (\", VP2pct,\"%)\"), attr.outside = TRUE, frame = FALSE)\ntmap_arrange(Carte1, Carte2, nrow = 1)\n```\n\n::: {.cell-output-display}\n![Cartographie de coordonnées factorielles des individus pour l'AFC](12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactInds2B-1.png){#fig-afc1erplanfactInds2B fig-align='center' width=85%}\n:::\n:::\n\n\n\n## Analyse de correspondances multiples (ACM) {#sec-124}\n\nL'analyse des correspondances multiples (ACM) est particulièrement adaptée à l'exploration de données issues d'une enquête par sondage, puisqu'elle permet de résumer/synthétiser l'information d'un tableau comprenant uniquement des variables qualitatives (@fig-AnalysesFactoriellesTabACM). \n\n\n![Lieu de pèlerinage de R](images/Chap12/AnalysesFactoriellesTabACM.png){#fig-AnalysesFactoriellesTabACM width=\"60%\" fig-align=\"center\"}\n\nPar exemple, une enquête sur la mobilité d'une population donnée pourrait comprendre plusieurs variables qualitatives, dont celles reportées au @tbl-ACM1.\n\n\n::: {#tbl-ACM1 .cell tbl-cap='Exemple de variables qualitatives issues d\\'une enquête'}\n::: {.cell-output-display}\n`````{=html}\n\n \n \n \n \n \n \n\n \n\n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
Modalités des variables Codage
Sexe
Homme 1
Femme 2
Groupe d'âge
Moins de 20 ans 1
20 à 39 ans 2
40 à 59 ans 3
60 ans et plus 4
Mode de transport
Automobile 1
Transport en commun 2
Marche 3
Vélo 4
\n\n`````\n:::\n:::\n\n\nPour analyser de telles données, il suffit de transformer le tableau condensé (de données brutes) en un tableau disjonctif complet dans lequel chaque modalité des variables qualitatives devient une variable binaire prenant les valeurs de 0 ou 1 (tableaux [-@tbl-ACM2] et [-@tbl-ACM3]). Notez que la somme de chaque ligne est alors égale au nombre de variables qualitatives.\n\n\n::: {#tbl-ACM2 .cell tbl-cap='Tableau condensé (données brutes)'}\n::: {.cell-output-display}\n| | Sexe | Groupe d'âge | Mode de transport |\n|:------|:----:|:------------:|:-----------------:|\n|Ind. 1 | 1 | 1 | 2 |\n|Ind. 2 | 1 | 2 | 3 |\n|Ind. 3 | 2 | 3 | 1 |\n|Ind. 4 | 1 | 2 | 1 |\n|Ind. 5 | 2 | 4 | 2 |\n|Ind. 6 | 1 | 4 | 4 |\n:::\n:::\n\n::: {#tbl-ACM3 .cell tbl-cap='Tableau disjonctif complet'}\n::: {.cell-output-display}\n`````{=html}\n\n \n\n\n\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
Sexe
Groupe d'âge
Mode de transport
Individu Homme Femme Moins de 20 ans 20 à 39 ans 40 à 59 ans 60 ans et plus Auto. T.C. Marche Vélo
Ind. 1 1 0 1 0 0 0 0 1 0 0
Ind. 2 1 0 0 1 0 0 0 0 1 0
Ind. 3 0 1 0 0 1 0 1 0 0 0
Ind. 4 1 0 0 1 0 0 1 0 0 0
Ind. 5 0 1 0 0 0 1 0 1 0 0
Ind. 6 1 0 0 0 0 1 0 0 0 1
\n\n`````\n:::\n:::\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**ACM versus AFC**\n:::\n::: bloc_astuce-body\nNous avons vu que l'AFC permet d'analyser un tableau de contingence avec deux variables qualitatives. En ACM, les colonnes sont les différentes modalités des variables qualitatives et les lignes sont les observations (par exemple, les individus ayant répondu à une enquête). En résumé, l'analyse des correspondances multiples (ACM) est simplement **une analyse des correspondances (AFC) appliquée sur un tableau disjonctif complet**. \n\nL'ACM permet ainsi de révéler les ressemblances entre les différentes modalités des variables qualitatives et les ressemblances entre les différents individus. Par conséquent, elle produit également des variables synthétiques (axes factoriels) résumant l'information contenue dans le tableau initial. L'évaluation de ces ressemblances et la détermination des axes factoriels sont aussi basées sur la **distance du khi-deux**.\n:::\n:::\n\n\n### Aides à l'interprétation {#sec-1241}\n\nPuisque l'ACM est une extension de l'AFC, nous retrouvons les mêmes aides à l'interprétation : les valeurs propres pour les axes, les coordonnées factorielles, les contributions et les cosinus carrés pour les variables et les individus. \n\nPour présenter l'ACM, nous utilisons des données ouvertes de la Ville de Montréal et, plus particulièrement, celles d'un [sondage auprès de la population de l’île de Montréal sur l'agriculture urbaine](https://www.donneesquebec.ca/recherche/dataset/vmtl-agriculture-urbaine-sondage){target='_blank'}. Pour ce faire, nous avons conservé uniquement les personnes pratiquant l'agriculture urbaine (n = 352). Les variables qualitatives extraites pour l'ACM sont reportées au @tbl-dataACM) avec la description des questions, leurs modalités respectives avec les effectifs bruts et en pourcentage. Au final, l'ACM est calculée de la manière suivante :\n\n- Neuf variables qualitatives relatives à la pratique de l'agriculture urbaine sont retenues (`q3`, `q4`, `q5`, `q8`, `q9`, `q10`, `q11`, `q12` et `q13`).\n\n- Quatre variables relatives au profil socioéconomique des personnes répondantes sont introduites comme variables supplémentaires (`q15`, `q16`, `q17` et `q21`).\n\n- Chaque ligne est pondérée avec la variable `pond`.\n\nL'objectif de cette ACM est double : \n\n1. Montrer les ressemblances entre les différentes modalités relatives à la pratique de l'agriculture urbaine. L'analyse des axes factoriels devrait nous permettre d'identifier différents profils des personnes pratiquant l'agriculture urbaine.\n\n2. Projeter les modalités des variables socioéconomiques afin de vérifier si elles sont ou non associées aux axes factoriels, c'est-à-dire aux différents profils révélés par les axes.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Bloc attention**\n:::\n::: bloc_attention-body\nL'analyse du sondage sur l'agriculture urbaine réalisée ici est purement exploratoire : elle vise uniquement à démontrer que l'ACM est un outil particulièrement intéressant pour analyser les données d'un sondage. Par contre, cette analyse n'a aucune prétention scientifique puisque nous ne sommes pas des spécialistes de l'agriculture urbaine. Dans ce champ de recherche très fertile qu'est l'agriculture urbaine (surement pas la meilleure blague du livre...), vous pourrez consulter plusieurs études montréalaises [@mcclintock2018urban; @audate2021motivations; @bhatt2016cultivating].\n:::\n:::\n\n\n::: {#tbl-dataACM .cell tbl-cap='Variables qualitatives extraites du sondage sur l\\'agriculture urbaine de la Ville de Montréal'}\n::: {.cell-output-display}\n`````{=html}\n\n \n \n \n \n \n \n \n\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n\n
Modalité N %
Q3. Depuis combien de temps cultivez-vous des fruits, des fines herbes ou des légumes?
Q3. Moins de 1 an 35 9,9
Q3. De 1 à 4 ans 101 28,7
Q3. De 5 à 9 ans 66 18,8
Q3. 10 ans ou plus 150 42,6
Q4. Selon vous, quelle proportion des fruits, des fines herbes et des légumes que vous consommez durant l'été provient de votre propre production?
Q4. Moins de 10% 192 54,5
Q4. 10 à 25% 70 19,9
Q4. 26 à 50% 47 13,4
Q4. Plus de 50% 43 12,2
Q5. Utilisez-vous du compost provenant de vos déchets verts ou alimentaires pour faire pousser des fruits, des fines herbes ou des légumes?
Q5. Oui 90 25,6
Q5. Non 262 74,4
Q8. Récupérez-vous l'eau de pluie pour irriguer vos cultures de fruits, de fines herbes ou des légumes ou encore votre jardin?
Q8. Oui 72 20,5
Q8. Non 280 79,5
Q9. Combien de sortes de fruits, de fines herbes ou de légumes cultivez-vous?
Q9. Moins de 5 sortes 170 48,3
Q9. 5 à 9 sortes 124 35,2
Q9. 10 à 14 sortes 42 11,9
Q9. 15 sortes ou plus 16 4,5
Q10. Cultivez-vous suffisamment de fruits, de fines herbes ou de légumes pour partager avec d'autres personnes?
Q10. Oui 143 40,6
Q10. Non 209 59,4
Q11. Échangez-vous vos semis ou vos récoltes de fruits, de fines herbes ou de légumes avec d'autres personnes?
Q11. Oui 90 25,6
Q11. Non 262 74,4
Q12. Selon vous, l'agriculture urbaine contribue-t-elle à améliorer les rapports entre les gens?
Q12. Oui 283 80,4
Q12. Non 46 13,1
Q12. NSP/NRP 23 6,5
Q13. Saviez-vous que la Ville de Montréal encourage et soutient l'agriculture urbaine sur l'île de Montréal?
Q13. Oui 203 57,7
Q13. Non 149 42,3
Q15. À quel groupe d'âge appartenez-vous?
Q15. 18 à 34 ans 54 15,3
Q15. 35 à 49 ans 110 31,2
Q15. 50 à 64 ans 101 28,7
Q15. 65 ans et plus 87 24,7
Q16. Quelle est votre occupation principale?
Q16. Travail temps plein 177 50,3
Q16. Travail. temps partiel 26 7,4
Q16. Étudiant 14 4,0
Q16. Retraité 101 28,7
Q16. Sans emploi 10 2,8
Q16. À la maison 24 6,8
Q17. Quel est le plus haut niveau de scolarité que vous avez complété?
Q17. Aucun certificat ou dipl. 25 7,1
Q17. Dipl. secondaires 80 22,7
Q17. Dipl. collégiales 75 21,3
Q17. Études universitaires 172 48,9
Q21. Êtes-vous propriétaire ou locataire de votre résidence ?
Q21. Propriétaire 250 71,0
Q22. Locataire 102 29,0
\n\n`````\n:::\n:::\n\n \n \n#### Résultats de l'ACM pour les valeurs propres {#sec-12411}\n\nLes résultats pour les valeurs propres sont reportés au @tbl-ACMValeursPropresTab et à la @fig-ACMValeursPropresFig.\nEn ACM, l'inertie totale du tableau des variables qualitatives est égale au nombre moyen de modalités par variable moins un, soit $\\frac{K}{J}-1$ avec *K* et *J* étant respectivement les nombres de modalités et de variables. Aussi, le nombre d'axes produits par l'ACM est égal à $K - J$. Pour notre tableau, l'inertie est donc égale à $\\mbox{25} / \\mbox{9} = \\mbox{1,77}$ avec $\\mbox{25}-\\mbox{9} = \\mbox{16}$ axes. Le nombre d'axes à retenir est souvent plus difficile à déterminer puisque, tel que signalé judicieusement par Jérôme Pagès [-@pages2002analyse, p.53] : « en pratique, comparée à l'ACP, l'ACM conduit, dans l'ensemble à : des pourcentages d'inertie plus petits; une décroissance de ces pourcentages plus douce ».\n\nL'histogramme des valeurs propres (@fig-ACMValeursPropresFig) révèle plusieurs sauts importants dans les valeurs propres qui pourraient justifier le choix du nombre d'axes factoriels, soit aux axes 1, 2, 3 et 6. Pour l'exercice, nous retenons les trois premiers axes qui résument 30 % de l'inertie du tableau initial.\n\n\n::: {#tbl-ACMValeursPropresTab .cell tbl-cap='Résultats de l\\'ACM pour les valeurs propres'}\n::: {.cell-output-display}\n| | Axe factoriel| Valeur propre| Pourcentage| Pourc. cumulé|\n|:------|-------------:|-------------:|-----------:|-------------:|\n|dim 1 | 1| 0,248| 13,940| 13,940|\n|dim 2 | 2| 0,156| 8,792| 22,732|\n|dim 3 | 3| 0,135| 7,620| 30,352|\n|dim 4 | 4| 0,127| 7,161| 37,513|\n|dim 5 | 5| 0,126| 7,065| 44,579|\n|dim 6 | 6| 0,123| 6,916| 51,494|\n|dim 7 | 7| 0,114| 6,385| 57,879|\n|dim 8 | 8| 0,107| 6,003| 63,882|\n|dim 9 | 9| 0,101| 5,671| 69,553|\n|dim 10 | 10| 0,095| 5,327| 74,880|\n|dim 11 | 11| 0,093| 5,234| 80,115|\n|dim 12 | 12| 0,086| 4,822| 84,937|\n|dim 13 | 13| 0,077| 4,340| 89,277|\n|dim 14 | 14| 0,071| 4,011| 93,288|\n|dim 15 | 15| 0,064| 3,619| 96,906|\n|dim 16 | 16| 0,055| 3,094| 100,000|\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output .cell-output-stderr}\n```\nWarning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.\nℹ Please use `linewidth` instead.\n```\n:::\n\n::: {.cell-output-display}\n![Graphiques pour les valeurs propres pour l'ACM](12-AnalysesFactorielles_files/figure-html/fig-ACMValeursPropresFig-1.png){#fig-ACMValeursPropresFig fig-align='center' width=672}\n:::\n:::\n\n\n#### Résultats de l'ACM pour les modalités des variables {#sec-12412}\n\nÀ titre de rappel, comme pour l’ACP et l'AFC, nous retrouvons les trois mêmes mesures pour les variables et les individus (coordonnées factorielles, contributions et cosinus carrés). Plus les variables qualitatives du jeu de données comprennent de modalités, plus la taille du tableau des résultats des modalités est importante et plus il est fastidieux de l'analyser. Il est donc recommandé de construire des histogrammes avec les coordonnées factorielles et les contributions des modalités, mais aussi un nuage de points avec les coordonnées des modalités des variables qualitatives sur le premier, voire le deuxième plan factoriel.\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Compréhension des axes factoriels de l'ACM : une étape essentielle, incontournable...**\n:::\n::: bloc_objectif-body\nComme en ACP et en AFC, l'analyse des trois mesures (coordonnées, contributions et cosinus carrés) pour les variables et les individus doit vous permettre de comprendre la signification des axes factoriels retenus de l'ACM. Prenez le temps de bien réaliser cette étape d'interprétation souvent plus fastidieuse qu'en ACP et ACM, en raison du nombre élevé de modalités. Cette étape est en effet essentielle afin de qualifier les variables latentes (axes factoriels, variables synthétiques) produites par l'ACM.\n:::\n:::\n\nLes résultats pour les variables sont reportés 1) au @tbl-ACMValeursCoordTab, 2) aux figures [-@fig-ACMValeursCoordFig1], [-@fig-ACMValeursCoordFig2] et [-@fig-ACMValeursCoordFig3] pour les coordonnées et les contributions et à la [-@fig-ACMValeursPlanFacto1] pour le premier plan factoriel.\n\n\n**Interprétation des résultats de l'axe 1 pour les variables**\n\nSept modalités concourent le plus à la formation de l'axe 1 résumant 13,9 % de la variance : `Q9. 10 à 14 sortes` (10,35 %), `Q10. Oui`\t(9,99 %), `Q9. Moins de 5 sortes` (9,71 %), `Q5. Oui`\t(9,19 %), `Q11. Oui` (8,20 %), `Q4. Moins de 10%`\t(7,87 %) et `Q10. Non` (7,10 %). Aussi, les modalités suivantes sont aux deux extrémités de cet axe :\n\n* **Coordonnées négatives** : `Q12. Non` (-0,84), `Q3. Moins de 1 an` (-0,73), `Q9. Moins de 5 sortes` (-0,67), `Q4. Moins de 10%` (-0,56), `Q10. Non` (-0,521). Cela signifie que lorsque les coordonnées des individus sont fortement négatives sur cet axe, les personnes pratiquant l'agriculture urbaine : \n + *ne pensent pas que l'agriculture urbaine contribue à améliorer les rapports entre les gens* (`Q12`);\n + *cultivent des fruits, des fines herbes ou de légumes depuis moins d'un an* (`Q3`);\n + *cultivent moins de cinq sortes de fruits, de fines herbes ou de légumes* (`Q9`);\n + *moins de 10 % de la proportion des fruits, des fines herbes et des légumes consommés durant l’été provient de leur propre production *(`Q4`);\n + *ne cultivent pas suffisamment pour partager avec d'autres personnes* (`Q10`).\n \n* **Coordonnées positives** : `Q9. 15 sortes ou plus` (1,36), `Q9. 10 à 14 sortes` (1,28), `Q5. Oui` (0,95) et `Q11. Oui` (0,85). Cela signifie que lorsque les coordonnées des individus sont fortement positives sur cet axe, les personnes pratiquant l'agriculture urbaine :\n + *cultivent plus de dix sortes de fruits, de fines herbes ou de légumes* (`Q9`);\n + *utilisent du compost provenant de leurs déchets verts ou de leurs déchets alimentaires pour faire pousser des fruits, des fines herbes ou de légumes* (`Q5`);\n + *échangent leurs semis ou leurs récoltes de fruits, de fines herbes ou des légumes avec d’autres personnes* (`Q11`).\n\nEn résumé, l'axe 1 oppose clairement les **néophytes en agriculture** versus les **personnes expérimentées** cultivant des fruits et de légumes variés avec leur propre compost et échangeant leurs semis ou leurs récoltes.\n\n\n\n::: {#tbl-ACMValeursCoordTab .cell tbl-cap='Résultats de l\\'ACM pour les modalités des variables'}\n::: {.cell-output-display}\n`````{=html}\n\n \n\n\n\n\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
Coordonnées
Cosinus carrés
Contributions (%)
Modalité 1 2 3 1 2 3 1 2 3
Q3. Moins de 1 an -0,73 0,68 0,63 2,70 3,68 3,64 0,07 0,06 0,05
Q3. De 1 à 4 ans -0,29 -0,79 0,39 1,26 15,30 4,30 0,04 0,33 0,08
Q3. De 5 à 9 ans 0,12 0,38 -1,11 0,12 2,02 19,43 0,00 0,04 0,29
Q3. 10 ans ou plus 0,45 0,35 0,02 3,19 3,01 0,02 0,11 0,07 0,00
Q4. Moins de 10% -0,56 0,03 0,07 7,87 0,04 0,22 0,40 0,00 0,01
Q4. 10 à 25% 0,74 -0,76 -0,11 4,92 8,22 0,19 0,14 0,14 0,00
Q4. 26 à 50% 0,78 0,64 0,15 3,82 4,18 0,28 0,10 0,07 0,00
Q4. Plus de 50% 0,53 0,40 -0,37 1,31 1,17 1,19 0,03 0,02 0,02
Q5. Oui 0,95 0,56 -0,13 9,19 5,01 0,29 0,27 0,09 0,00
Q5. Non -0,28 -0,16 0,04 2,70 1,47 0,09 0,27 0,09 0,00
Q8. Oui 0,55 0,37 1,21 2,58 1,86 23,31 0,07 0,03 0,35
Q8. Non -0,13 -0,09 -0,29 0,62 0,45 5,60 0,07 0,03 0,35
Q9. Moins de 5 sortes -0,67 0,01 0,47 9,71 0,00 8,83 0,42 0,00 0,21
Q9. 5 à 9 sortes 0,24 0,11 -0,79 0,89 0,30 17,31 0,03 0,01 0,32
Q9. 10 à 14 sortes 1,28 -0,97 0,07 10,35 9,42 0,06 0,27 0,15 0,00
Q9. 15 sortes ou plus 1,36 2,15 0,65 3,62 14,42 1,50 0,08 0,21 0,02
Q10. Oui 0,73 -0,15 0,07 9,99 0,63 0,18 0,38 0,02 0,00
Q10. Non -0,52 0,10 -0,05 7,10 0,45 0,13 0,38 0,02 0,00
Q11. Oui 0,85 -0,83 0,32 8,20 12,45 2,11 0,25 0,23 0,03
Q11. Non -0,29 0,28 -0,11 2,79 4,24 0,72 0,25 0,23 0,03
Q12. Oui 0,16 0,02 0,01 0,97 0,02 0,01 0,11 0,00 0,00
Q12. Non -0,84 -0,38 0,09 4,12 1,32 0,08 0,11 0,02 0,00
Q12. NSP/NRP -0,36 0,56 -0,31 0,36 1,39 0,48 0,01 0,02 0,01
Q13. Oui 0,17 0,31 0,31 0,70 3,91 4,37 0,04 0,13 0,12
Q13. Non -0,22 -0,40 -0,40 0,91 5,05 5,66 0,04 0,13 0,12
\n\n`````\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Graphiques pour les résultats des modalités de l'axe 1 de l'ACM](12-AnalysesFactorielles_files/figure-html/fig-ACMValeursCoordFig1-1.png){#fig-ACMValeursCoordFig1 fig-align='center' width=90%}\n:::\n:::\n\n\n\n**Interprétation des résultats de l'axe 2 pour les variables**\n\nQuatre modalités concourent le plus à la formation de l'axe 2 résumant 8,8 % de la variance : `Q3. De 1 à 4 ans` (15,30 %), `Q9. 15 sortes ou plus`\t(14,42 %), `Q11. Oui`\t(12,45 %) et `Q9. 10 à 14 sortes`\t(9,42 %). Les modalités suivantes sont présentes aux deux extrémités de l'axe 2 :\n\n- **Coordonnées négatives** : `Q9. 10 à 14 sortes` (-0,97), `Q11. Oui` (-0,83), `Q3. De 1 à 4 ans` (-0,79), `Q4. 10 à 25%` (-0,76). Cela signifie que lorsque les coordonnées des individus sont fortement négatives sur cet axe, les personnes pratiquant l'agriculture urbaine : \n + *cultivent de 10 à 14 sortes de fruits, de fines herbes ou de légumes* (`Q9`); \n + *échangent leurs semis ou leurs récoltes de fruits, de fines herbes ou de légumes avec d’autres personnes* (`Q11`);\n + *cultivent des fruits, des fines herbes ou des légumes depuis 1 à 4 ans* (`Q3`);\n + *de 10 à 25 % de la proportion des fruits, des fines herbes et des légumes consommés durant l’été provient de leur propre production *(`Q4`).\n\n- **Coordonnées positives** : seule la modalité `Q9. 15 sortes ou plus` (2,15) présente une forte coordonnée positive.\n\n**En résumé, l'axe 2** permet surtout d'identifier des personnes pratiquant l'agriculture urbaine depuis quelques années (de 1 à 4 ans), mais cultivant déjà de nombreuses sortes de fruits et légumes et partageant aussi leurs semis ou récoltes.\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Graphiques pour les résultats des modalités de l'axe 2 de l'ACM](12-AnalysesFactorielles_files/figure-html/fig-ACMValeursCoordFig2-1.png){#fig-ACMValeursCoordFig2 fig-align='center' width=90%}\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Premier plan factoriel de l'ACM pour les modalités](12-AnalysesFactorielles_files/figure-html/fig-ACMValeursPlanFacto1-1.png){#fig-ACMValeursPlanFacto1 fig-align='center' width=75%}\n:::\n:::\n\n\n**Interprétation des résultats de l'axe 3 pour les variables**\n\nTrois modalités concourent le plus à la formation de l'axe 3 résumant 7,6 % de la variance : `Q8. Oui` (23,31), `Q3. De 5 à 9 ans` (19,43) et `Q9. 5 à 9 sortes` (17,31). Les modalités suivantes sont présentes aux deux extrémités de l'axe 3 :\n\n- **Coordonnées négatives** : `Q3. De 5 à 9 ans` (-1,11), `Q9. 5 à 9 sortes` (-0,79). \n- **Coordonnées positives** : seule la modalité `Q8. Oui` présente une coordonnée fortement positive (1,21).\n\nPar conséquent, cet axe semble plus complexe à analyser et surtout moins intéressant que les deux premiers.\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Graphiques pour les résultats des modalités de l'axe 3 de l'ACM](12-AnalysesFactorielles_files/figure-html/fig-ACMValeursCoordFig3-1.png){#fig-ACMValeursCoordFig3 fig-align='center' width=100%}\n:::\n:::\n\n\n\n**Analyse des variables supplémentaires dans l'ACM**\n\nIl est ensuite possible de projeter les modalités supplémentaires sur les axes de l'ACM retenus (@tbl-ACMValeursCoordSuppl et @fig-ACMValeursPlanFactoSupp1). Les faibles valeurs des coordonnées factorielles des modalités supplémentaires sur les deux axes semblent indiquer que le profil socioéconomique des personnes pratiquant l'agriculture urbaine ne semble pas (ou peu) relié aux profils identifiés par les axes factoriels.\n\n\n::: {#tbl-ACMValeursCoordSuppl .cell tbl-cap='Résultats de l\\'ACM pour les modalités des variables supplémentaires'}\n::: {.cell-output-display}\n`````{=html}\n\n \n\n\n\n\n\n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
Coordonnées
Cosinus carrés
Modalité 1 2 1 2
Q15. 18 à 34 ans -0,09 -0,27 0,00 0,04
Q15. 35 à 49 ans -0,06 -0,01 0,00 0,00
Q15. 50 à 64 ans 0,14 0,25 0,01 0,02
Q15. 65 ans et plus 0,11 0,25 0,00 0,01
Q16. Travail temps plein -0,10 -0,06 0,01 0,01
Q16. Travail. temps partiel 0,36 -0,15 0,01 0,00
Q16. Étudiant -0,14 -0,11 0,00 0,00
Q16. Retraité 0,17 0,25 0,01 0,02
Q16. Sans emploi 0,44 -0,14 0,01 0,00
Q16. À la maison -0,06 0,18 0,00 0,00
Q17. Aucun certificat ou dipl. 0,28 0,16 0,00 0,00
Q17. Dipl. secondaires -0,09 0,01 0,00 0,00
Q17. Dipl. collégiales 0,01 0,19 0,00 0,01
Q17. Études universitaires 0,00 -0,10 0,00 0,01
Q21. Propriétaire 0,03 0,02 0,00 0,00
Q22. Locataire -0,06 -0,03 0,00 0,00
\n\n`````\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Premier plan factoriel de l'ACM avec toutes les modalités incluant celles supplémentaires](12-AnalysesFactorielles_files/figure-html/fig-ACMValeursPlanFactoSupp1-1.png){#fig-ACMValeursPlanFactoSupp1 fig-align='center' width=672}\n:::\n:::\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Visualisation de variables qualitatives ordinales sur un plan factoriel**\n:::\n::: bloc_astuce-body\nLorsque les variables qualitatives sont ordinales et non nominales, il peut être intéressant de relier les différentes modalités avec une ligne. Cela permet de comprendre en un coup d'œil la trajectoire que suivent les modalités sur les deux axes factoriels. En guise d'exemple, nous réalisons cet exercice pour les variables `Q3` et `Q9` (@fig-ACMordinaleTrajectoire).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Trajectoires des variables ordinales sur le premier plan factoriel de l'ACM](12-AnalysesFactorielles_files/figure-html/fig-ACMordinaleTrajectoire-1.png){#fig-ACMordinaleTrajectoire fig-align='center' width=70%}\n:::\n:::\n\n:::\n:::\n\n#### Résultats de l'ACM pour les individus {#sec-12413}\n\nComme toute méthode factorielle, les coordonnées factorielles, les cosinus carrés et les contributions sont aussi disponibles pour les individus en ACM. Nous proposons ici simplement de réaliser le premier plan factoriel pour les individus en attribuant un dégradé de couleurs avec les cosinus carrés (@fig-ACMPlanFacto12Ind1). Il est aussi possible d'attribuer des couleurs aux différentes modalités d'une variable. Par exemple, sur le premier plan factoriel, nous avons utilisé la variable `Q12. Selon vous, l’agriculture urbaine contribue-t-elle à améliorer les rapports entre les gens?`. Cela permet de repérer visuellement que les personnes ayant répondu négativement à cette question ont surtout des coordonnées négatives sur l'axe 1.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Premier plan factoriel de l'ACM pour les individus](12-AnalysesFactorielles_files/figure-html/fig-ACMPlanFacto12Ind1-1.png){#fig-ACMPlanFacto12Ind1 fig-align='center' width=100%}\n:::\n:::\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Premier plan factoriel de l'ACM pour les individus avec coloration d'une variable](12-AnalysesFactorielles_files/figure-html/fig-ACMPlanFacto12Ind2-1.png){#fig-ACMPlanFacto12Ind2 fig-align='center' width=100%}\n:::\n:::\n\n\n### Mise en œuvre dans R {#sec-1242}\n\n#### Calcul d’une ACM avec `FactoMineR` {#sec-12421}\n\nPlusieurs *packages* permettent de calculer une ACM dans R, notamment `ExPosition` (fonction `epMCA`), `ade4` (fonction `dudi.mca`) et `FactoMineR` (fonction `MCA`). De nouveau, nous utilisons `FactoMineR` couplé au *package* `factoextra` pour réaliser rapidement des graphiques.\n\nPour calculer l'ACM, il suffit d'utiliser la fonction `MCA` de `FactoMineR`, puis la fonction `summary(res.acm)` qui renvoie les résultats de l'ACM pour : \n\n- Les valeurs propres (section `Eigenvalues`) pour les axes factoriels (`Dim.1` à `Dim.n`) avec leur variance expliquée brute (`Variance`), en pourcentage (`% of var.`) et en pourcentage cumulé (`Cumulative % of var.`).\n\n- Les dix premières observations (section `Individuals`) avec les coordonnées factorielles (`Dim.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`). Pour accéder aux résultats pour toutes les observations, utilisez les fonctions `res.acm$ind` ou encore `res.acm$ind$coord` (uniquement les coordonnées factorielles), `res.acm$ind$contrib` (uniquement les contributions) et `res.acm$ind$cos2` (uniquement les cosinus carrés).\n\n- Les dix premières modalités des variables (section `Categories`) avec les coordonnées factorielles (D`im.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`).\n\nLa syntaxe ci-dessous permet, dans un premier temps, de calculer l'ACM, puis de créer un *DataFrame* pour les résultats des valeurs propres.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(FactoMineR)\n# Calcul de l'AFC\nres.acm <- MCA(dfACM, # Nom du DataFrame\n ncp = 3, # Nombre d'axes retenus\n quali.sup=10:13, # Variables supplémentaires\n graph = FALSE, \n row.w = dfenquete$pond) # Variables pour la pondération des lignes\n# Affichage des résultats\nprint(res.acm)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n**Results of the Multiple Correspondence Analysis (MCA)**\nThe analysis was performed on 352 individuals, described by 13 variables\n*The results are available in the following objects:\n\n name description \n1 \"$eig\" \"eigenvalues\" \n2 \"$var\" \"results for the variables\" \n3 \"$var$coord\" \"coord. of the categories\" \n4 \"$var$cos2\" \"cos2 for the categories\" \n5 \"$var$contrib\" \"contributions of the categories\" \n6 \"$var$v.test\" \"v-test for the categories\" \n7 \"$var$eta2\" \"coord. of variables\" \n8 \"$ind\" \"results for the individuals\" \n9 \"$ind$coord\" \"coord. for the individuals\" \n10 \"$ind$cos2\" \"cos2 for the individuals\" \n11 \"$ind$contrib\" \"contributions of the individuals\" \n12 \"$quali.sup\" \"results for the supplementary categorical variables\"\n13 \"$quali.sup$coord\" \"coord. for the supplementary categories\" \n14 \"$quali.sup$cos2\" \"cos2 for the supplementary categories\" \n15 \"$quali.sup$v.test\" \"v-test for the supplementary categories\" \n16 \"$call\" \"intermediate results\" \n17 \"$call$marge.col\" \"weights of columns\" \n18 \"$call$marge.li\" \"weights of rows\" \n```\n:::\n\n```{.r .cell-code}\nsummary(res.acm)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nCall:\nMCA(X = dfACM, ncp = 3, quali.sup = 10:13, graph = FALSE, row.w = dfenquete$pond) \n\n\nEigenvalues\n Dim.1 Dim.2 Dim.3 Dim.4 Dim.5 Dim.6 Dim.7\nVariance 0.248 0.156 0.135 0.127 0.126 0.123 0.114\n% of var. 13.940 8.792 7.620 7.161 7.065 6.916 6.385\nCumulative % of var. 13.940 22.732 30.352 37.513 44.579 51.494 57.879\n Dim.8 Dim.9 Dim.10 Dim.11 Dim.12 Dim.13 Dim.14\nVariance 0.107 0.101 0.095 0.093 0.086 0.077 0.071\n% of var. 6.003 5.671 5.327 5.234 4.822 4.340 4.011\nCumulative % of var. 63.882 69.553 74.880 80.115 84.937 89.277 93.288\n Dim.15 Dim.16\nVariance 0.064 0.055\n% of var. 3.619 3.094\nCumulative % of var. 96.906 100.000\n\nIndividuals (the 10 first)\n Dim.1 ctr cos2 Dim.2 ctr cos2 \n4 | 0.261 0.063 0.052 | 0.327 0.155 0.081 |\n10 | -0.533 0.688 0.278 | 0.050 0.010 0.002 |\n11 | 0.135 0.020 0.014 | -0.120 0.025 0.011 |\n15 | 0.020 0.000 0.000 | 0.271 0.073 0.061 |\n17 | -0.133 0.014 0.012 | -0.264 0.088 0.049 |\n18 | 0.196 0.024 0.018 | 0.279 0.078 0.037 |\n19 | -0.193 0.041 0.014 | -0.063 0.007 0.002 |\n21 | 0.845 0.731 0.369 | -0.337 0.184 0.059 |\n23 | -0.253 0.155 0.058 | -0.020 0.002 0.000 |\n26 | 0.802 0.552 0.170 | 0.460 0.288 0.056 |\n Dim.3 ctr cos2 \n4 0.251 0.105 0.048 |\n10 -0.413 0.757 0.167 |\n11 -0.354 0.252 0.097 |\n15 -0.503 0.291 0.209 |\n17 0.835 1.019 0.486 |\n18 0.104 0.012 0.005 |\n19 0.159 0.051 0.010 |\n21 -0.390 0.285 0.079 |\n23 -0.375 0.624 0.128 |\n26 0.098 0.015 0.003 |\n\nCategories (the 10 first)\n Dim.1 ctr cos2 v.test Dim.2 ctr\nQ3. Moins de 1 an | -0.731 2.704 0.068 -4.940 | 0.677 3.681\nQ3. De 1 à 4 ans | -0.286 1.259 0.043 -3.921 | -0.791 15.299\nQ3. De 5 à 9 ans | 0.119 0.122 0.003 1.102 | 0.385 2.023\nQ3. 10 ans ou plus | 0.450 3.189 0.110 6.271 | 0.347 3.006\nQ4. Moins de 10% | -0.562 7.874 0.395 -11.913 | 0.033 0.044\nQ4. 10 à 25% | 0.745 4.918 0.137 7.006 | -0.765 8.220\nQ4. 26 à 50% | 0.775 3.815 0.099 5.966 | 0.644 4.176\nQ4. Plus de 50% | 0.527 1.310 0.033 3.424 | 0.395 1.167\nQ5. Oui | 0.950 9.194 0.265 9.760 | 0.557 5.008\nQ5. Non | -0.279 2.701 0.265 -9.760 | -0.164 1.471\n cos2 v.test Dim.3 ctr cos2 v.test \nQ3. Moins de 1 an 0.058 4.578 | 0.627 3.636 0.050 4.236 |\nQ3. De 1 à 4 ans 0.328 -10.855 | 0.390 4.304 0.080 5.360 |\nQ3. De 5 à 9 ans 0.035 3.556 | -1.110 19.427 0.293 -10.261 |\nQ3. 10 ans ou plus 0.065 4.835 | 0.023 0.016 0.000 0.327 |\nQ4. Moins de 10% 0.001 0.704 | 0.070 0.221 0.006 1.477 |\nQ4. 10 à 25% 0.144 -7.194 | -0.109 0.191 0.003 -1.021 |\nQ4. 26 à 50% 0.068 4.957 | 0.154 0.276 0.004 1.187 |\nQ4. Plus de 50% 0.018 2.566 | -0.372 1.195 0.016 -2.417 |\nQ5. Oui 0.091 5.720 | -0.126 0.294 0.005 -1.290 |\nQ5. Non 0.091 -5.720 | 0.037 0.086 0.005 1.290 |\n\nCategorical variables (eta2)\n Dim.1 Dim.2 Dim.3 \nq3 | 0.162 0.338 0.334 |\nq4 | 0.400 0.191 0.023 |\nq5 | 0.265 0.091 0.005 |\nq8 | 0.071 0.032 0.352 |\nq9 | 0.548 0.340 0.338 |\nq10 | 0.381 0.015 0.004 |\nq11 | 0.245 0.235 0.034 |\nq12 | 0.121 0.038 0.007 |\nq13 | 0.036 0.126 0.122 |\n\nSupplementary categories (the 10 first)\n Dim.1 cos2 v.test Dim.2 cos2 v.test \nQ15. 18 à 34 ans | -0.091 0.004 -1.221 | -0.271 0.037 -3.630 |\nQ15. 35 à 49 ans | -0.060 0.001 -0.731 | -0.014 0.000 -0.175 |\nQ15. 50 à 64 ans | 0.140 0.006 1.419 | 0.251 0.018 2.543 |\nQ15. 65 ans et plus | 0.107 0.002 0.874 | 0.248 0.011 2.020 |\nQ16. Travail temps plein | -0.096 0.012 -2.084 | -0.065 0.005 -1.404 |\nQ16. Travail. temps partiel | 0.364 0.010 1.875 | -0.147 0.002 -0.757 |\nQ16. Étudiant | -0.139 0.002 -0.774 | -0.111 0.001 -0.617 |\nQ16. Retraité | 0.166 0.006 1.521 | 0.254 0.015 2.331 |\nQ16. Sans emploi | 0.440 0.006 1.433 | -0.142 0.001 -0.464 |\nQ16. À la maison | -0.056 0.000 -0.279 | 0.175 0.002 0.878 |\n Dim.3 cos2 v.test \nQ15. 18 à 34 ans 0.092 0.004 1.232 |\nQ15. 35 à 49 ans -0.112 0.005 -1.360 |\nQ15. 50 à 64 ans -0.002 0.000 -0.020 |\nQ15. 65 ans et plus 0.015 0.000 0.122 |\nQ16. Travail temps plein -0.025 0.001 -0.540 |\nQ16. Travail. temps partiel 0.291 0.006 1.497 |\nQ16. Étudiant -0.088 0.001 -0.488 |\nQ16. Retraité 0.031 0.000 0.284 |\nQ16. Sans emploi -0.495 0.007 -1.611 |\nQ16. À la maison 0.144 0.001 0.720 |\n\nSupplementary categorical variables (eta2)\n Dim.1 Dim.2 Dim.3 \nq15 | 0.010 0.048 0.007 |\nq16 | 0.027 0.020 0.015 |\nq17 | 0.006 0.014 0.014 |\nq21 | 0.002 0.001 0.007 |\n```\n:::\n\n```{.r .cell-code}\n# Construction d'un DataFrame pour les valeurs propres\ndfACMvp <- data.frame(res.acm$eig)\nnames(dfACMvp) <- c(\"VP\" , \"VP_pct\" , \"VP_pctCumul\")\ndfACMvp$Axe <- factor(1:nrow(dfACMvp), levels = rev(1:nrow(dfACMvp)))\ndfACMvp <- dfACMvp[, c(4,1:3)]\n```\n:::\n\n\n#### Exploration graphique des résultats de l'ACM pour les valeurs propres {#sec-124212}\n\nPour créer un histogramme des valeurs propres de l'ACM, vous pouvez utiliser la fonction `fviz_screeplot` de `factoextra`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(factoextra)\nlibrary(ggplot2)\n\nfviz_screeplot(res.acm, addlabels = TRUE,\n x = \"Composantes\", y = \"Valeur propre\", title = \"\")\n```\n\n::: {.cell-output-display}\n![Graphique pour les valeurs propres de l'ACM avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-ACMCodePartie1VPb-1.png){#fig-ACMCodePartie1VPb fig-align='center' width=75%}\n:::\n:::\n\n\nAvec un peu plus de lignes de code, il est relativement facile d'exploiter le *DataFrame* des valeurs propres créé précédemment (`dfACMvp`) pour construire des graphiques plus personnalisés.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(factoextra)\nlibrary(ggplot2)\n\ncouleursAxes <- c(\"steelblue\" , \"skyblue2\")\ng1 <- ggplot(dfACMvp, aes(x = VP, y = Axe))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"skyblue2\")+\n labs(x = \"Valeur propre\", y = \"Axe factoriel\")\ng2 <- ggplot(dfACMvp, aes(x = VP_pct, y = Axe))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"skyblue2\")+\n theme(legend.position = \"none\")+\n labs(x = \"Variance expliquée (%)\", y = \"Axe factoriel\")\ng3 <- ggplot(dfACMvp, aes(x = VP_pctCumul, y = Axe, group=1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"skyblue2\")+\n geom_line(colour = \"brown\", linetype = \"solid\", size=.8) +\n geom_point(size=3, shape=21, color = \"brown\", fill = \"brown\")+\n theme(legend.position = \"none\")+\n labs(x = \"Variance expliquée (% cumulé)\", y = \"Axe factoriel\")\nggarrange(g2, g3, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Graphiques pour les valeurs propres de l'ACM avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-ACMCodePartie1VPc-1.png){#fig-ACMCodePartie1VPc fig-align='center' width=75%}\n:::\n:::\n\n\nLa syntaxe ci-dessous permet de construire un tableau avec les coordonnées factorielles, les cosinus carrés et les contributions pour les modalités des variables qualitatives.\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(stringr)\nnAxes <- 3\ndfmodalites <- data.frame(Modalite =rownames(res.acm$var$coord),\n Coord = round(res.acm$var$coord[, 1:nAxes],3),\n Cos2 = round(res.acm$var$cos2[, 1:nAxes],3),\n ctr = round(res.acm$var$contrib[, 1:nAxes],3))\nrownames(dfmodalites) <- 1:nrow(dfmodalites)\nnames(dfmodalites) <- str_replace(names(dfmodalites), \".Dim.\", \"F\")\n```\n:::\n\n\n\n#### Exploration graphique des résultats de l'ACM pour les modalités {#sec-124213}\n\nAvant d'explorer graphiquement les résultats pour les modalités, il est judicieux de construire un *DataFrame* avec les coordonnées factorielles, les contributions et les cosinus carrés des modalités (voir la syntaxe ci-dessous).\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(kableExtra)\nlibrary(stringr)\nnAxes <- 3\ndfmodalites <- data.frame(Modalite =rownames(res.acm$var$coord),\n Coord = round(res.acm$var$coord[, 1:nAxes],2),\n ctr = round(res.acm$var$contrib[, 1:nAxes],2),\n Cos2 = round(res.acm$var$cos2[, 1:nAxes],2))\nrownames(dfmodalites) <- 1:nrow(dfmodalites)\nnames(dfmodalites) <- str_replace(names(dfmodalites), \".Dim.\", \"F\")\n```\n:::\n\n\nPlusieurs fonctions très faciles à utiliser de `factoextra` permettent de construire rapidement des graphiques : `fviz_mca_var` pour un nuage de points d'un plan factoriel, `fviz_cos2` et `fviz_contrib` (en utilisant le paramètre `choice=var.cat`) pour des histogrammes avec les cosinus carrés et les contributions des modalités.\n\nIl est aussi possible de créer vos propres graphiques avec `ggplot2` en utilisant le *DataFrame* créé précédemment avec les modalités. Par exemple, la syntaxe ci-dessous renvoie deux histogrammes pour l'axe 1 : l'un avec les coordonnées, l'autre avec les contributions. Dans la syntaxe, repérez le terme `CoordF1`. Dupliquez la syntaxe et changez ce terme pour `CoordF2` et `CoordF3` pour réaliser les graphiques des axes 2 et 3.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# Histogrammes pour les coordonnées des modalités\ncouleursCoords <- c(\"lightsalmon\" , \"steelblue\")\nplotCoordF1 <- ggplot(dfmodalites,\n aes(y = reorder(Modalite, CoordF1),\n x = CoordF1, fill = CoordF1<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords,\n labels = c(\"Positive\" , \"Négative\"))+\n labs(x = \"Coordonnées sur l'axe 1\", y = \"Modalité\")+\n theme(legend.position = \"none\", axis.text.y = element_text(size = 7))\n\nplotCtrF1 <- ggplot(dfmodalites, aes(y = reorder(Modalite, ctrF1), x = ctrF1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"steelblue\")+\n labs(x = \"Contributions sur l'axe 1\", y = \"Modalité\")+\n theme(legend.position = \"none\", axis.text.y = element_text(size = 7))\n\nggarrange(plotCoordF1, plotCtrF1, ncol = 1, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Exemple de graphiques pour les résultats des modalités](12-AnalysesFactorielles_files/figure-html/fig-ACMMiseEnOeuvreVars1-1.png){#fig-ACMMiseEnOeuvreVars1 fig-align='center' width=100%}\n:::\n:::\n\n\nLa syntaxe suivante permet de construire le premier plan factoriel pour les modalités avec la fonction `fviz_mca_var` de `factoextra` (@fig-ACMMiseEnOeuvreVars2).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nres.acm2 <- MCA(dfACM[1:9], ncp = 3, graph = FALSE, row.w = dfenquete$pond)\nfviz_mca_var(res.acm2, repel = TRUE,\n choice = \"var.cat\",\n axes = c(1, 2),\n # col.var = \"black\",\n title = \"\", xlab = \"Axe 1\", ylab = \"Axe 2\",\n ggtheme = theme_minimal ())\n```\n\n::: {.cell-output-display}\n![Premier plan factoriel de l'ACM pour les modalités](12-AnalysesFactorielles_files/figure-html/fig-ACMMiseEnOeuvreVars2-1.png){#fig-ACMMiseEnOeuvreVars2 fig-align='center' width=75%}\n:::\n:::\n\n\nLa syntaxe suivante permet de construire le premier plan factoriel pour les modalités supplémentaires avec la fonction `fviz_mca_var` de `factoextra` (@fig-ACMMiseEnOeuvreVars3).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nfviz_mca_var(res.acm, repel = TRUE,\n choice = \"var.cat\",\n axes = c(1, 2),\n col.var = \"gray23\",\n col.quali.sup = \"darkred\",\n labelsize = 3,\n title = \"\", xlab = \"Axe 1\", ylab = \"Axe 2\", \n ggtheme = theme_minimal ())\n```\n\n::: {.cell-output-display}\n![Premier plan factoriel de l'ACM pour les modalités supplémentaires](12-AnalysesFactorielles_files/figure-html/fig-ACMMiseEnOeuvreVars3-1.png){#fig-ACMMiseEnOeuvreVars3 fig-align='center' width=75%}\n:::\n:::\n\n\nFinalement, la syntaxe ci-dessous renvoie un graphique avec la trajectoire de la variable `Q3` (@fig-ACMMiseEnOeuvreVars4).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggpubr)\nQ3 <- dfmodalites[1:4, 1:3]\nggplot(Q3, aes(x = CoordF1, y = CoordF2, label=Modalite))+\n xlim(-1, .75)+ylim(-1, 1)+\n labs(title = \"Q3. Depuis combien de temps cultivez-vous \\n\n des fruits, des fines herbes ou des légumes?\",\n x = \"Axe 1\", y = \"Axe 2\")+\n geom_label(nudge_x=0, nudge_y = 0.07) +\n geom_line( color = \"black\", linewidth = .2)+\n geom_point(shape=21, color = \"black\", fill = \"steelblue\", size=4)\n```\n\n::: {.cell-output-display}\n![Trajectoires des variables ordinales sur le premier plan factoriel de l'ACM](12-AnalysesFactorielles_files/figure-html/fig-ACMMiseEnOeuvreVars4-1.png){#fig-ACMMiseEnOeuvreVars4 fig-align='center' width=70%}\n:::\n:::\n\n\n#### Exploration graphique des résultats de l'ACM pour les individus {#sec-124214}\n\nD'autres fonctions de `factoextra` produisent rapidement des graphiques pour les individus :\n\n- `fviz_cos2` et `fviz_contrib` (en utilisant le paramètre `choice=ind`) pour construire des histogrammes pour les cosinus carrés et les contributions des individus.\n- `fviz_mca_ind` pour un nuage de points d'un plan factoriel (axes 1 et 2 habituellement).\n\nLa syntaxe ci-dessous produit le premier axe factoriel pour les individus (@fig-ACMPlanFactoInd1Facto).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nfviz_mca_ind(res.acm, col.ind = \"cos2\",\n gradient.cols = c(\"#00AFBB\", \"#E7B800\", \"#FC4E07\"),\n repel = TRUE,\n xlab = \"Axe 1\", ylab = \"Axe 2\", title = \"\",\n ggtheme = theme_minimal())\n```\n\n::: {.cell-output-display}\n![Premier plan factoriel de l'ACM pour les individus avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-ACMPlanFactoInd1Facto-1.png){#fig-ACMPlanFactoInd1Facto fig-align='center' width=70%}\n:::\n:::\n\n\nLa syntaxe ci-dessous produit aussi le premier plan factoriel pour les individus, mais en attribuant une couleur différente aux modalités de la variable `q12` (@fig-ACMPlanFactoInd2Facto).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nfviz_mca_ind (res.acm,\n label = \"none\",\n habillage = \"q12\", # colorer par groupes\n xlab = \"Axe 1\", ylab = \"Axe 2\", title = \"\",\n palette = c (\"darkred\", \"steelblue\", \"gray23\"),\n ggtheme = theme_minimal ())\n```\n\n::: {.cell-output-display}\n![Premier plan factoriel de l'ACM pour les individus avec coloration d'une variable avec factoextra](12-AnalysesFactorielles_files/figure-html/fig-ACMPlanFactoInd2Facto-1.png){#fig-ACMPlanFactoInd2Facto fig-align='center' width=70%}\n:::\n:::\n\n\n## Quiz de révision du chapitre {#sec-125}\n\n\n
\n\n\n\n
\n
Des variables latentes ne sont pas directement observées, mais plutôt produites par la méthode factorielle afin de résumer les relations/associations entre plusieurs variables mesurées initialement.
\n
Relisez au besoin l'introduction du [chapitre @sec-chap12].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quelles sont les métriques utilisées pour les trois principales méthodes factorielles?
\n
Relisez au besoin la [section @sec-1211].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
En ACP normée, la somme des valeurs propres (inertie totale) est égale au :
\n
Relisez au besoin le début de la [section @sec-12221].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
En ACP normée, la coordonnée factorielle d'une variable sur un axe est :
\n
Relisez au besoin la [section @sec-12222].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quelles affirmations sont exactes pour toutes les méthodes factorielles?
\n
Relisez au besoin chacune des sections intitulées aides à l'interprétation pour les trois méthodes factorielles.
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
L'analyse des correspondances multiples (ACM) est simplement une analyse des correspondances (AFC) sur un tableau disjonctif complet?
\n
Relisez au besoin la [section @sec-124].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Dans une ACM, les variables du tableau disjonctif complet sont :
\n
Relisez au besoin la [section @sec-124].
\n
\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quelles sont les étapes essentielles pour bien interpréter une analyse factorielle (ACP, AFC ou ACM)?
\n
Relisez le deuxième encadré à la [section @sec-1221].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n\n
\n\n
\n
\n", + "supporting": [ + "12-AnalysesFactorielles_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": { + "include-in-header": [ + "\r\n\r\n" + ] + }, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMCodePartie1VPb-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMCodePartie1VPb-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMCodePartie1VPb-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMCodePartie1VPb-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMCodePartie1VPc-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMCodePartie1VPc-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMCodePartie1VPc-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMCodePartie1VPc-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMMiseEnOeuvreVars1-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMMiseEnOeuvreVars1-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMMiseEnOeuvreVars1-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMMiseEnOeuvreVars1-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMMiseEnOeuvreVars2-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMMiseEnOeuvreVars2-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMMiseEnOeuvreVars2-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMMiseEnOeuvreVars2-1.png diff --git a/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMMiseEnOeuvreVars3-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMMiseEnOeuvreVars3-1.png new file mode 100644 index 0000000..3d51bbc Binary files /dev/null and b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMMiseEnOeuvreVars3-1.png differ diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMMiseEnOeuvreVars4-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMMiseEnOeuvreVars4-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMMiseEnOeuvreVars4-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMMiseEnOeuvreVars4-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMPlanFactoInd1Facto-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMPlanFacto12Ind1-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMPlanFactoInd1Facto-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMPlanFacto12Ind1-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMPlanFacto12Ind2-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMPlanFacto12Ind2-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMPlanFacto12Ind2-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMPlanFacto12Ind2-1.png diff --git a/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMPlanFactoInd1Facto-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMPlanFactoInd1Facto-1.png new file mode 100644 index 0000000..e14f86b Binary files /dev/null and b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMPlanFactoInd1Facto-1.png differ diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMPlanFactoInd2Facto-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMPlanFactoInd2Facto-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMPlanFactoInd2Facto-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMPlanFactoInd2Facto-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMValeursCoordFig1-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursCoordFig1-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMValeursCoordFig1-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursCoordFig1-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMValeursCoordFig2-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursCoordFig2-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMValeursCoordFig2-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursCoordFig2-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMValeursCoordFig3-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursCoordFig3-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMValeursCoordFig3-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursCoordFig3-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMValeursPlanFacto1-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursPlanFacto1-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMValeursPlanFacto1-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursPlanFacto1-1.png diff --git a/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursPlanFactoSupp1-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursPlanFactoSupp1-1.png new file mode 100644 index 0000000..4a6f404 Binary files /dev/null and b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursPlanFactoSupp1-1.png differ diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMValeursPropresFig-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursPropresFig-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMValeursPropresFig-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMValeursPropresFig-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-ACMordinaleTrajectoire-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMordinaleTrajectoire-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-ACMordinaleTrajectoire-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-ACMordinaleTrajectoire-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-acp1erplanfactIndiv-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acp1erplanfactIndiv-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-acp1erplanfactIndiv-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acp1erplanfactIndiv-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-acp1erplanfactVars-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acp1erplanfactVars-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-acp1erplanfactVars-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acp1erplanfactVars-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-acp1erplanfactVars2a-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acp1erplanfactVars2a-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-acp1erplanfactVars2a-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acp1erplanfactVars2a-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-acpcartoindiv-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpcartoindiv-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-acpcartoindiv-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpcartoindiv-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-acpgraphvarscoords-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpgraphvarscoords-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-acpgraphvarscoords-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpgraphvarscoords-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-acpgraphvp-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpgraphvp-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-acpgraphvp-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpgraphvp-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs1-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpmesgraphs1-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs1-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpmesgraphs1-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs2-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpmesgraphs2-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs2-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpmesgraphs2-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs5-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpmesgraphs5-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs5-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpmesgraphs5-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs6-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpmesgraphs6-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-acpmesgraphs6-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-acpmesgraphs6-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactInds2-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afc1erplanfactInds2-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactInds2-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afc1erplanfactInds2-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactInds2B-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afc1erplanfactInds2B-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactInds2B-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afc1erplanfactInds2B-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactVars-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afc1erplanfactVars-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactVars-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afc1erplanfactVars-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactVars2b-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afc1erplanfactVars2b-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-afc1erplanfactVars2b-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afc1erplanfactVars2b-1.png diff --git a/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afcAjoutModalites-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afcAjoutModalites-1.png new file mode 100644 index 0000000..c3c93ec Binary files /dev/null and b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afcAjoutModalites-1.png differ diff --git a/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afcAjoutModalites2-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afcAjoutModalites2-1.png new file mode 100644 index 0000000..43a6699 Binary files /dev/null and b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afcAjoutModalites2-1.png differ diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-afcGraphVP-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afcGraphVP-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-afcGraphVP-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-afcGraphVP-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-cartovarAFC-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-cartovarAFC-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-cartovarAFC-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-cartovarAFC-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra1-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra1-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra1-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra1-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra2-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra2-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra2-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra2-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra3-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra3-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra3-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra3-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra4-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra4-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra4-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra4-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra5-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra5-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra5-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra5-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra6-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra6-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-factoextra6-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextra6-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/fig-factoextraAFC1-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextraAFC1-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/fig-factoextraAFC1-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/fig-factoextraAFC1-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-1.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/unnamed-chunk-15-1.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-1.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/unnamed-chunk-15-1.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-2.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/unnamed-chunk-15-2.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-2.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/unnamed-chunk-15-2.png diff --git a/docs/12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-3.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/unnamed-chunk-15-3.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-3.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/unnamed-chunk-15-3.png diff --git a/.quarto/_freeze/12-AnalysesFactorielles/figure-html/unnamed-chunk-15-4.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/unnamed-chunk-15-4.png new file mode 100644 index 0000000..ae85642 Binary files /dev/null and b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/unnamed-chunk-15-4.png differ diff --git a/docs/12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-5.png b/.quarto/_freeze/12-AnalysesFactorielles/figure-html/unnamed-chunk-15-5.png similarity index 100% rename from docs/12-AnalysesFactorielles_files/figure-html/unnamed-chunk-15-5.png rename to .quarto/_freeze/12-AnalysesFactorielles/figure-html/unnamed-chunk-15-5.png diff --git a/.quarto/_freeze/13-MethodeClassification/execute-results/html.json b/.quarto/_freeze/13-MethodeClassification/execute-results/html.json new file mode 100644 index 0000000..584eef7 --- /dev/null +++ b/.quarto/_freeze/13-MethodeClassification/execute-results/html.json @@ -0,0 +1,20 @@ +{ + "hash": "78ac80e0c043424845ec33a4c3ba93c6", + "result": { + "markdown": "# Méthodes de classification non supervisée {#sec-chap13}\n\nDans le cadre de ce chapitre, nous présentons les méthodes les plus utilisées en sciences sociales pour explorer la présence de groupes homogènes au sein d'un jeu de données, soit les méthodes de classification non supervisée. Le qualificatif *non supervisé* signifie que ces classes/groupes ne sont pas connus a priori et doivent être identifiés à partir des données. Autrement dit, nous cherchons à regrouper les observations partageant des caractéristiques similaires sur la base de plusieurs variables. Ces méthodes descriptives et exploratoires multivariées peuvent être vues comme une façon de réduire le nombre d'observations d'un jeu de données à un ensemble d'observations synthétiques, représentant le mieux possible la population à l’étude.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2` le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes.\n* Outils généraux pour faciliter les classifications :\n - `clusterCrit` pour calculer des indicateurs de qualité de classification.\n - `NbClust` pour trouver le bon nombre de groupe dans une classification.\n - `cluster` pour appliquer la méthode GAP.\n - `proxy` pour calculer plusieurs types de distances.\n - `Gmedian` pour calculer le k-médianes.\n - `geocmeans` pour explorer les résultats de classifications floues.\n:::\n:::\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Pourquoi recourir à des méthodes de classification non supervisée en sciences sociales?**\n:::\n::: bloc_objectif-body\nLes méthodes de classification sont très utilisées en sciences sociales. Elles visent à identifier des groupes cohérents au sein d'un ensemble d'observations sur la base de plusieurs variables (@fig-ClassifNonNSuperv). Ces groupes peuvent ensuite être analysés et nous renseigner sur les caractéristiques communes partagées par les individus qui les composent. \n\n![Principe de base des méthodes de classification non supervisée](images/Chap13/ClassifNonNSuperv.png){#fig-ClassifNonNSuperv width=\"40%\" fig-align=\"center\"}\n\nUn exemple classique est l'identification de profils d'individus ayant répondu à un sondage, en fonction de plusieurs caractéristiques (par exemple, l'âge, le sexe, la situation de famille, le revenu, etc.). En identifiant ces groupes homogènes, il est ensuite possible d'explorer les associations entre ces profils et d'autres variables.\n\nUn second exemple serait de regrouper les secteurs d'une ville selon leurs caractéristiques environnementales (végétation, niveau de bruit, pollution atmosphérique, etc.) et socioéconomiques (revenu médian des ménages, pourcentage d’immigrants, pourcentage de personnes à faible scolarité, taux de chômage, etc.).\n:::\n:::\n\n\n## Méthodes de classification : un aperçu {#sec-131}\n\nIl existe une multitude de méthodes de classification généralement regroupées dans plusieurs familles imbriquées à partir de deux distinctions importantes.\n\nLa première distinction vise à séparer les méthodes **supervisées** des **non supervisées**. Pour les premières, les catégories/groupes/classes des observations sont connues à l'avance. L'enjeu n'est pas de trouver les catégories puisqu’elles sont connues, mais **de déterminer des règles ou un modèle permettant d'attribuer des observations à ces catégories**. Parmi les méthodes de classification supervisée, les plus connues sont les forêts d’arbres décisionnels, les réseaux de neurones artificiels ou encore l’analyse factorielle discriminante. Nous n'abordons pas ces méthodes dans ce chapitre dédié uniquement aux méthodes de classification non supervisée. Pour ces dernières, les catégories ne sont pas connues à l'avance et l'enjeu est de **faire ressortir les structures des groupes propres aux données**. Ainsi, les méthodes de classification non supervisée « relèvent de la statistique exploratoire multidimensionnelle et permettent de classifier automatiquement les observations sans connaissance a priori sur la nature des classes présentes dans le jeu de données; les plus connues sont sans conteste les algorithmes de classification ascendante hiérarchique (CAH) et du *k-means* (k-moyennes) » [@2021_4, p.1]. Notez également qu'à la frontière entre ces deux familles, se situent les méthodes de classification semi-supervisée. Il s'agit de cas spécifiques où des informations partielles sont connues sur les groupes à détecter : seulement le groupe final de certaines observations est connu, certaines observations sont supposées appartenir à un même groupe même s'il est indéfini en lui-même [@bair2013semi].\n\nLa seconde distinction vise à séparer les méthodes **strictes** des **floues**. Les premières ont pour objectif d'assigner chaque observation à une et une seule catégorie, alors que les secondes décrivent le degré d’appartenance de chaque observation à chaque catégorie. Autrement dit, « dans une classification stricte, chaque observation appartient à une seule classe. Mathématiquement parlant, l’appartenance à une classe donnée est binaire (0 ou 1) tandis que dans une classification floue, chaque observation a une probabilité d’appartenance variant de 0 à 1 à chacune des classes » [@2021_4, p.1]. Bien entendu, pour chaque observation, la somme des degrés d’appartenance à chacune des classes est égale à 1 (@fig-floueVSstrict). En termes de données, cela signifie que pour les méthodes strictes, le groupe d'appartenance d'une observation est contenu dans une seule variable nominale (une colonne d'un *DataFrame*). Pour les méthodes floues, il est nécessaire de disposer d’autant de variables continues (plusieurs colonnes numériques d'un *DataFrame*), soit une par groupe, dans lesquelles sont enregistrées le degré d'appartenance de chaque observation à chacun des groupes. Parmi les méthodes de classification supervisée floue, notez que nous avons déjà abordé la régression logistique multinomiale dans le chapitre sur les GLM ([section @sec-0824]).\n\n![Classifications stricte et floue](images/Chap13/floueVSstricte.png){#fig-floueVSstrict width=\"35%\" fig-align=\"center\"}\n\nEn résumé, le croisement de ces deux distinctions permet ainsi de différencier les méthodes **supervisées strictes**, **supervisées floues**, **non supervisées strictes** et **non supervisées floues** (@fig-methoClassif), auxquelles s'ajoutent les méthodes semi-supervisées discutées brièvement.\n\n![Synthèse des principales méthodes de classification (Gelb et Apparicio 2021)](images/Chap13/syntheseClassif.png){#fig-methoClassif width=\"60%\" fig-align=\"center\"}\n\nDans ce chapitre, nous décrivons les trois méthodes de classification non supervisée les plus utilisées et faciles à mettre en œuvre : la classification ascendante hiérarchique, les nuées dynamiques strictes (*k-means* et *k-medians*) et nuées dynamiques floues (*c-means* et *c-medians*). \n\n## Notions essentielles en classification {#sec-132}\n\nAvant de décrire différentes méthodes de classification non supervisées, il convient de définir deux notions centrales, soit la **distance** et l'**inertie**.\n\n### Distance {#sec-1321}\n\nLa distance en analyse de données est définie comme une fonction (*d*) permettant de déterminer à quel point deux observations sont semblables ou différentes l'une de l'autre. Elle doit respecter les conditions suivantes :\n\n* **la non-négativité** : la distance minimale entre deux objets est égale à 0; $d(x,y) \\geq 0$.\n\n* **le principe d'identité des indiscernables** : la distance entre deux objets $x$ et $y$ est égale à 0, si $x = y$; $d(x,y)=0\\text{ si et seulement si }x=y$.\n\n* **la symétrie** : la distance entre $x$ et $y$ est la même qu'entre $y$ et $x$; $d(x,y) = d(y,x)$.\n\n* **le triangle d'inégalité** : passer d'un point $x$ à un point $z$ est toujours plus court ou égal que de passer par $y$ entre $x$ et $z$; $d(x,z)\\leq d(x,y)+d(y,z)$.\n\nIl existe un grand nombre de types de distance qui peuvent être utilisés pour déterminer le degré de similarité entre les observations. Nous présentons ici les six types les plus fréquemment utilisés en sciences sociales, mais retenez qu’il en existe bien d'autres.\n\n#### Distance euclidienne {#sec-13211}\n\nIl s'agit vraisemblablement de la distance la plus couramment utilisée, soit la longueur de la ligne droite la plus courte entre les deux objets considérés. Pour la représenter, admettons que nous nous intéressons à trois classes d'étudiants et d'étudiantes A, B et C pour lesquelles nous avons calculé la moyenne de leurs notes dans les cours de méthodes quantitatives et qualitatives. Ces deux variables sont mesurées dans la même unité et varient de 0 à 100. Le nuage de points à la @fig-dist0 illustre cette situation avec des données fictives.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Situation de base pour le calcul de distance](13-MethodeClassification_files/figure-html/fig-dist0-1.png){#fig-dist0 fig-align='center' width=60%}\n:::\n:::\n\n\nLes distances euclidiennes entre les classes B et C et les classes C et A sont représentées par les lignes noires à la @fig-dist1. Nous pouvons constater que la distance entre les classes C et B est plus petite que celle entre les classes A et C, ce qui signale que les deux premières se ressemblent davantage.\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Représentation de la distance euclidienne](13-MethodeClassification_files/figure-html/fig-dist1-1.png){#fig-dist1 fig-align='center' width=60%}\n:::\n:::\n\n\n\nLa formule de la distance euclidienne (@eq-euclideandist) est simplement la racine carrée de la somme des écarts au carré pour chacune des variables décrivant les observations *a* et *b*.\n\n$$ \nd(a,b) = \\sqrt{\\sum{}^v_{i=1}(a_i-b_i)^2}\n$$ {#eq-euclideandist}\n\navec *v* le nombre de variables décrivant les observations *a* et *b*.\n\nNous pouvons facilement calculer la distance euclidienne pour notre jeu de données : \n\n* $d(A,B)=\\sqrt{(\\mbox{85}-\\mbox{80})^2+(\\mbox{80}-\\mbox{77})^2} = \\mbox{5,83}$\n* $d(B, c)=\\sqrt{(\\mbox{80}-\\mbox{83})^2+(\\mbox{79}-\\mbox{77})^2} = \\mbox{3,60}$\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Distance et unité de mesure **\n:::\n::: bloc_attention-body\nIl est très important de garder à l'esprit que la distance entre deux observations dépend directement des unités de mesure utilisées. Cela est très souvent problématique, car il est rare que toutes les variables utilisées pour décrire des observations soient mesurées dans la même unité. Ainsi, une variable dont les valeurs numériques sont plus grandes risque de déséquilibrer les calculs de distance. À titre d'exemple, une variable mesurée en mètres plutôt qu'en kilomètres produit des distances euclidiennes 1000 fois plus grandes.\n\nIl est donc nécessaire de standardiser les variables utilisées avant de calculer des distances. Cette opération permet de transformer les variables originales vers une échelle commune. Plusieurs types de transformations peuvent être utilisés tels que décrits à la [section @sec-02552] :\n\n* **Le centrage et la réduction** qui consistent à soustraire de chaque valeur sa moyenne, puis à la diviser par son écart-type. La nouvelle variable obtenue s'exprime alors en écart-type (appelé aussi score-z). La formule de la transformation est $f(x) = \\frac{x - \\bar{x}}{\\sigma_x}$, avec $\\bar{x}$ la moyenne de $x$ et $\\sigma_x$ l'écart-type de $x$.\n\n* **La transformation sur une mise à l'échelle de 0 à 1** qui permet de modifier l'étendue d'une variable afin que sa valeur maximale soit de 1 et sa valeur minimale soit de 0. La formule de cette transformation est $f(x) = \\frac{x-min(x)}{max(x)-min(x)}$.\n\n* **La transformation en rang** qui consiste à remplacer les valeurs d'une variable par leur rang. La valeur la plus faible est remplacée par 1, et la plus forte par *n* (nombre d'observations). Notez que cette transformation modifie la distribution de la variable originale contrairement aux deux transformations précédentes. Cette propriété peut être désirable si les écarts absolus entre les valeurs ont peu d'importance, si la variable n'a pas été mesurée avec précision ou encore si des valeurs extrêmes sont présentes.\n\n* **La transformation en percentile** qui consiste à remplacer les valeurs d'une variable par leur percentile correspondant. Elle peut être vue comme une standardisation de la transformation en rang, car elle ne dépend pas du nombre d'observations.\n\nLa @fig-impactTransform montre l'effet de ces transformations sur l'histogramme d'une variable.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Effets de différentes transformations sur la distribution d'une variable](13-MethodeClassification_files/figure-html/fig-impactTransform-1.png){#fig-impactTransform fig-align='center' width=80%}\n:::\n:::\n\n:::\n:::\n\n#### Distance de Manhattan {#sec-13212}\n\nCette seconde distance est également couramment utilisée. Elle doit son nom au réseau de rue de l'île de Manhattan qui suit un plan quadrillé. La distance de Manhattan correspond à la somme des écarts absolus entre les valeurs des différentes variables décrivant les observations (@eq-manhattandist). La @fig-dist2 illustre que la distance Manhattan (lignes noires) représente les deux côtés opposés de l'hypoténuse d’un triangle rectangle; l'hypoténuse représentant quant à elle la distance euclidienne.\n\n$$\nd(a,b) = \\sum{}^v_{i=1}(|a_i-b_i|)\n$$ {#eq-manhattandist}\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Représentation de la distance de Manhattan](13-MethodeClassification_files/figure-html/fig-dist2-1.png){#fig-dist2 fig-align='center' width=60%}\n:::\n:::\n\n\nLa distance de Manhattan doit être privilégiée à la distance euclidienne lorsque les données considérées ont un très grand nombre de dimensions (variables). En effet, lorsque le nombre de variables est important (supérieur à 30), la distance euclidienne tend à être grande pour toutes les paires d’observations et à moins bien discriminer les observations proches et lointaines les unes des autres. Du fait de sa nature additive, la distance de Manhattan est moins sujette à ce problème [@aggarwal2001surprising].\n\nCalculons la distance de Manhattan pour nos deux paires d'observations :\n\n* $d(A,B)=|85-80|+|80-77| = 8$\n* $d(B, c)=|80-83|+|79-77| = 5$\n\n#### Distance du khi-deux {#sec-13213}\n\nLa distance du khi-deux est basée sur le test du khi-deux ([chapitre @sec-chap05]) et est généralement utilisée pour calculer la distance entre deux histogrammes, deux images ou deux ensembles de mots. Plus précisément, elle permet de mesure la distance entre deux observations A et B, pour lesquelles nous disposons d'un ensemble de variables étant toutes des variables de comptage.\n\nPrenons un exemple concret en générant trois histogrammes A, B et C sur l'intervalle [0,50] à partir des distributions normale, log-normale et Gamma, puis comptons le nombre de valeurs de chaque unité (1, 2, 3, 4, etc.). Ces histogrammes sont représentés à la @fig-dist3.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Trois histogrammes pour illustrer le calcul de la distance du khi-deux](13-MethodeClassification_files/figure-html/fig-dist3-1.png){#fig-dist3 fig-align='center' width=75%}\n:::\n:::\n\n\nNous pouvons calculer les distances du khi-deux entre les paires d'histogrammes (@tbl-tabdist3). Nous constatons ainsi que les histogrammes B et C sont les plus semblables.\n\n\n::: {#tbl-tabdist3 .cell tbl-cap='Distance du khi-deux entre trois histogrammes'}\n::: {.cell-output-display}\n|Histogrammes | Distance du khi-deux|\n|:------------|--------------------:|\n|A-B | 284,8375|\n|A-C | 376,7862|\n|B-C | 219,5133|\n:::\n:::\n\n\nLa formule de cette distance est la suivante : \n\n$$ \nd_{\\chi^2}(a,b) = \\frac{1}{2}\\sum^n_{i=1}\\frac{(a_i-b_i)^2}{(a_i+b_i)}\n$$ {#eq-chi2dist}\n\navec $a_i$ et $b_i$ les comptages pour les histogrammes. Notez que si $a_i$ et $b_i$ valent tous les deux 0, il faut retirer ces valeurs avant le calcul, car cela provoquerait une division par 0.\n\nÀ première vue, cette distance peut paraître moins utile que les deux précédentes. Pourtant, de nombreuses données sont collectées comme des histogrammes. Un premier exemple serait des images que nous pouvons représenter sous forme de trois histogrammes, un pour chaque canal de couleur (rouge, vert et bleu). Un second exemple serait des données sonores, souvent synthétisées sous forme d'histogrammes des fréquences sonores enregistrées (octaves ou tiers d'octaves). Un dernier exemple pourrait être le nombre d'accidents de la route enregistré à diverses intersections d'une ville chaque heure. Dans ce contexte, un histogramme serait formé par l'intersection avec les heures de la journée comme limites des bandes et le nombre d'accidents comme hauteur des bandes.\n\n#### Distance de Mahalanobis {#sec-13214}\n\nProposée dans les années 1930 par le statisticien indien Prasanta Chandra Mahalanobis [-@chandra1936generalised], cette distance se base sur la matrice de covariance des variables analysées. Plus spécifiquement, elle est utilisée pour calculer la distance entre un point et une distribution normale multivariée. Elle permet notamment de tenir compte du fait que certaines variables sont corrélées et ainsi d'éviter de surestimer les distances entre des observations dans des jeux de données comprenant des variables corrélées entre elles.\n\nLa formule permettant de calculer cette distance est la suivante : \n\n\n$$ \nd(a,b) = \\sqrt{(a-b)^TS^{-1}(a-b)}\n$$ {#eq-mahalanobis}\n\navec *S* étant la matrice de covariance.\n\n#### Distance de Hamming {#sec-13215}\n\nCette distance est utilisée quand les écarts entre les variables de deux observations sont uniquement binaires. Un bon exemple serait un jeu de données ne comprenant que des variables qualitatives pouvant avoir une valeur identique pour deux observations (distance = 0) ou différente (distance = 1). La distance de Hamming est la simple addition de ces écarts.\n\nPrenons un exemple très simple en prenant trois maisons pour lesquelles nous connaissons cinq caractéristiques (@tbl-dist4).\n\n\n::: {#tbl-dist4 .cell tbl-cap='Exemple de données pour la distance de Hamming'}\n::: {.cell-output-display}\n|couleur |jardin |garage |cheminée |sous-sol |\n|:-------|:------|:------|:--------|:--------|\n|blanc |non |oui |oui |non |\n|blanc |non |non |oui |non |\n|rouge |oui |oui |non |oui |\n:::\n:::\n\n\nNous pouvons utiliser la distance de Hamming pour estimer le niveau de dissimilarité entre ces différentes maisons et l'organiser dans une matrice de distances. À la lecture du @tbl-dist5), les maisons 2 et 3 sont les plus dissimilaires (distance de Hamming = 5), et les maisons 1 et 2 les plus similaires (distance de Hamming = 1).\n\n\n::: {#tbl-dist5 .cell tbl-cap='Distance de Hamming entre les maisons'}\n::: {.cell-output-display}\n| |maison 1 | maison 2 | maison 3 |\n|:--------|:--------|:--------:|:--------:|\n|maison 1 |0 | 1 | 4 |\n|maison 2 |1 | 0 | 5 |\n|maison 3 |4 | 5 | 0 |\n:::\n:::\n\n\n#### Distance de Gower {#sec-13216}\n\nLa distance de Gower [-@gower1971general] peut être utilisée pour mesurer la distance entre deux observations lorsque les données sont à la fois qualitatives et quantitatives. Cette distance est comprise dans un intervalle de 0 à 1, 0 signifiant que les deux observations sont identiques et 1, que les observations sont radicalement différentes.\n\nElle se calcule de la façon suivante : \n\n$$\n\\begin{aligned}\n&d(a,b) = 1-\\frac{1}{p}\\sum^p_{j=1}s_{12j}\\\\\n&\\left\\{\\begin{array}{c}\ns_{xyj} = 1 \\text{ si } x_j = y_j \\text{, 0 autrement pour une variable qualitative} \\\\\ns_{xyj} = 1 - \\frac{|x_j-y_j|}{max(j)-min(j)} \\text{ pour une variable quantitative}\n\\end{array}\\right.\n\\end{aligned}\n$$ {#eq-gower}\n\n\navec *p* le nombre de variables, *x* et *y* deux observations et *j* une variable.\n\nAutrement dit, si la valeur d'une variable qualitative diffère entre deux observations, la distance entre ces deux observations augmente de $1/p$. Pour une variable quantitative, la distance augmente selon la différence absolue entre les valeurs de la variable divisée par l'étendue totale de la variable, le tout à nouveau divisé par *p*.\n\nSi cette mesure semble intéressante puisqu'elle permet de combiner des variables quantitatives et qualitatives, elle souffre de deux limites importantes :\n\n* Elle ne prend pas en compte le fait que certaines modalités des variables qualitatives sont moins fréquentes ni que certaines combinaisons sont également moins fréquentes.\n\n* Les variables qualitatives tendent à affecter bien plus la distance que les variables quantitatives. En effet, pour obtenir un écart de 1 sur une variable quantitative, il faut que les deux valeurs soient respectivement le maximum et le minimum de cette variable.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**D'autres distances pour des données mixtes**\n:::\n::: bloc_aller_loin-body\nIl existe bien d'autres distances qui peuvent être utilisées dans le cas de données mixtes. Le *package* `kmed` en implémente cinq (auxquelles s'ajoute la distance de Gower) dans sa fonction `distmix` : les distances de Wishart, de Podani, d'Huang, d'Harikumar et d'Ahmad. Ces différentes distances ont toutes leurs avantages et leurs défauts respectifs; pour plus d'information, référez-vous à la documentation de la fonction `distmix`.\n:::\n:::\n\n#### Distance du Phi^2^ {#sec-13217}\n\nLa distance du $\\Phi^2$ (Phi^2^) est une variante de la distance du $\\chi^2$. Il s'agit donc d'une distance à utiliser lorsque les données à analyser sont uniquement qualitatives. Elle calcule la distance entre deux observations en additionnant les différences entre les valeurs de chaque variable (1 si différentes, 0 si identiques, pour chaque variable), divisées respectivement par la fréquence totale d'occurrences de chaque modalité dans le jeu de données. En d'autres termes, cette distance tient compte du fait que certaines valeurs pour des variables qualitatives peuvent être observées plus fréquemment que d'autres et qu'une distance plus grande devrait être obtenue entre deux observations si l'une des deux présente des modalités rares comparativement au reste du jeu de données.\n\nElle peut être calculée de la façon suivante : \n\n$$\nd_{\\Phi^2}(i,j) = \\frac{1}{Q}\\sum_k\\frac{(\\delta_{ik} - \\delta_{jk})^2}{f_k}\n$$ {#eq-phidist}\n\navec *i* et *j* deux observations, *k* une modalité d'une variable qualitative, *Q* le nombre total de modalités des variables qualitatives, $\\delta_{ik} = 1$ si l'observation i a la modalité *k*, 0 sinon et $f_k$ la fréquence de la modalité *k* dans le jeu de données.\n\nLa distance du $\\Phi^2$ est très utile pour analyser les résultats de questionnaires.\n\n### Inertie {#sec-1322}\n\nUne notion importante à saisir dans le cadre des méthodes de classification non supervisée est celui celle l'**inertie** d'un jeu de données. Elle est proche de la notion de variance qui a été présentée dans le chapitre sur la statistique univariée ([section @sec-0253]).\n\nL'inertie est une quantité permettant de décrire la dispersion des observations d'un jeu de données. Cette mesure dépend à la fois des données (nombres d'observations et de variables, échelle des variables) et de la mesure de distance retenue entre deux observations. Plus spécifiquement, l'inertie correspond à la somme des distances entre chaque observation et le centre du jeu de données. \n\n$$\ninertie= \\sum{}^n_{i=1} d(c,x_i)\n$$ {#eq-inertia}\n\navec *c* le centre du jeu de données, *n* le nombre d'observations, *x* une observation et *d* la fonction calculant la distance entre deux observations.\n\nL'enjeu est de définir *c* dans un contexte où la distance euclidienne est utilisée. Il s'agit simplement d'une observation fictive dont les coordonnées sont les moyennes des différentes variables du jeu de données. Dans le cas d'autres distances, il peut s'agir de l'observation minimisant la distance à toutes les autres observations.\n\nPour bien visualiser la notion d'inertie, prenons une fois encore le jeu de données `IRIS` comme exemple. Admettons que nous ne nous intéressons qu'à deux variables de ce jeu de données : `sepal.Length` et `sepal.Width`. Nous pouvons représenter l'inertie totale du jeu de données à la @fig-dist6.\n\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Représentation de l'inertie du jeu de données IRIS](13-MethodeClassification_files/figure-html/fig-dist6-1.png){#fig-dist6 fig-align='center' width=75%}\n:::\n:::\n\n\nChaque ligne bleue représente la contribution de chaque point à l'inertie totale du jeu de données. Pour chaque iris, nous connaissons son espèce (Setosa, Versicolor ou Virginica). Nous pouvons donc attribuer chaque point de ce jeu de données à un groupe (une espèce dans notre cas). Il devient alors possible de calculer l'inertie de chacun des sous-groupes de notre jeu de données. Pour cela, nous devons calculer le centre de chaque groupe (généralement les moyennes des variables des observations au sein d'un groupe) et ensuite calculer l'inertie entre chaque observation et le centre de son groupe. Nous représentons cette situation à la @fig-dist7.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Représentation de l'inertie par groupe pour le jeu de données IRIS](13-MethodeClassification_files/figure-html/fig-dist7-1.png){#fig-dist7 fig-align='center' width=75%}\n:::\n:::\n\n\nCette inertie propre aux groupes est toujours inférieure ou égale à l'inertie totale du jeu de données. Il s'agit en réalité de l'inertie que la structure de groupe n'est pas en mesure d'expliquer. En utilisant ces concepts, il est possible de calculer la part de l'inertie totale expliquée par les groupes (@eq-explainedinertia) : \n\n$$ \n\\text{inertie expliquée} = 1-\\frac{\\text{inertie totale}}{\\text{inertie restante}}\n$$ {\\#eq-explainedinertia}\n\nCette valeur nous renseigne sur la capacité d'une classification à bien réduire l'inertie totale d'un jeu de données. Elle est comprise entre 0 et 1. Si l'inertie expliquée est à 0, c'est que la classification n'explique absolument aucune part de l'inertie totale. Si l'inertie expliquée est à 1, la classification utilisée explique l'intégralité de l'inertie, ce qui en pratique n'est atteignable que si le nombre de groupes de la classification est égal au nombre d'observations. En d'autres termes, chaque observation est attribuée à un groupe dont elle est la seule représentante. Un telle situation n'a aucun intérêt puisque l'objectif d'une classification est bien de réduire la complexité d'un jeu de données en regroupant les observations.\n\n\n## Classification ascendante hiérarchique {#sec-133}\n\nLa classification ascendante hiérarchique (CAH) est un algorithme de classification non supervisée dont l'objectif est de créer un arbre de classification des observations. Cet arbre est ensuite utilisé pour déterminer le nombre de groupes à former et à quel groupe appartient chaque observation.\n\n### Fonctionnement de l'algorithme {#sec-1331} \n\nLa classification ascendante hiérarchique est un algorithme permettant de regrouper les observations d'un jeu de données de façon itérative. À chaque itération, deux observations similaires sont agrégées en un groupe représenté par le point central entre les deux observations. Le processus est ensuite répété en considérant le nouveau point comme une observation jusqu'à ce que toutes les observations soient fusionnées en un seul groupe.\n\nCes regroupements successifs créent un arbre de classification appelé dendrogramme. La racine de cet arbre est le groupe unique fusionnant toutes les observations, et ses branches correspondent aux différentes agrégations effectuées jusqu'aux observations individuelles. Cet arbre peut être vu comme une hiérarchie de classification. Chaque niveau de l'arbre est un regroupement de plus en plus généraliste au fur et à mesure que nous nous approchons de sa racine.\n\nPour appliquer cette méthode, il est nécessaire de sélectionner une **fonction de distance** pour mesurer la dissimilarité ou la ressemblance entre deux observations. L'algorithme fonctionne avec n'importe quelle fonction de distance, ce qui permet de l'appliquer aussi bien à des données qualitatives que quantitatives. En effet, l'opération de regroupement des observations se base sur une matrice de distance, soit un tableau de taille *n x n* indiquant pour chaque paire d'observations leur degré de dissimilarité. La @fig-tablvsmat illustre cette transformation en appliquant la distance du $\\Phi^2$ à un jeu de données comprenant cinq observations et 5 variables qualitatives.\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Du tableau de données à la matrice de distance](13-MethodeClassification_files/figure-html/fig-tablvsmat-1.png){#fig-tablvsmat fig-align='center' width=80%}\n:::\n:::\n\n\n\nEn plus de la fonction de distance, il est également nécessaire de sélectionner un **critère d'agrégation**, soit la règle permettant de décider à chaque itération quelles observations doivent être regroupées. Les méthodes les plus courantes sont : \n\n* Le critère de Ward [-@ward1963hierarchical] : cette méthode consiste à agréger à chaque itération les deux observations permettant de minimiser la variance (ou l'inertie) intra-groupe, ce qui revient à maximiser l'inertie inter-groupe (autrement dit, à rendre les groupes les plus homogènes possibles et les plus dissemblables entre eux). Ainsi, l'enjeu est de fusionner les deux observations permettant d'avoir les groupes les plus dissimilaires possible après fusion.\n\n* Le lien complet : à chaque itération, les deux groupes d'observations associés sont ceux pour lesquels la distance maximale entre les observations les composant est la plus petite parmi tous les groupes.\n\n* Le lien simple : à chaque itération, les deux groupes d'observations associés sont ceux pour lesquels la distance minimum entre les observations les composant est la plus petite parmi tous les groupes.\n\nLa plus utilisée est de loin la méthode de Ward. La méthode du lien complet produit généralement des résultats similaires. En revanche, la méthode du lien simple peut produire des groupes non sphériques (non centrés sur leur moyenne) plus difficile à interpréter.\n\nPrenons un instant pour visualiser cet algorithme (@fig-animhclust). Cette animation a été réalisée par David Sheehan et est également accessible sur son [blog](https://dashee87.github.io/data%20science/general/Clustering-with-Scikit-with-GIFs/). Elle présente bien le processus d'agglomération de la classification ascendante hiérarchique et la construction progressive du dendrogramme.\n\n![Principe de fonctionnement de la classification ascendante hiérarchique (auteur : David Sheehan)](images/Chap13/CAH.gif){#fig-animhclust width=\"75%\" fig-align=\"center\"}\n\n### Choisir le bon nombre de groupes {#sec-1332}\n\nUne fois que l'algorithme a été appliqué aux données et le dendrogramme obtenu, il faut encore choisir le nombre optimal de groupes pour la classification finale. Chaque embranchement du dendrogramme constitue une classification possible, allant de la plus complexe (chaque observation appartient à un groupe formé d'elle seule) à la plus simple (toutes les observations appartiennent au même groupe). Si le nombre de groupes n'est pas connu à l'avance et qu'aucune forte justification théorique n'existe, il est possible d'utiliser plusieurs techniques pour déterminer un nombre de groupes judicieux à partir des données. Nous en présentons ici trois, mais il convient de ne pas s'en tenir uniquement à ses critères arbitraires. Il est important d'explorer les résultats de la classification obtenue pour plusieurs valeurs de *k* candidates et de tenir compte de la qualité des informations qu'elles fournissent. Au final, il est pertinent de retenir la classification dont les résultats offrent l'interprétation la plus claire avec un nombre de groupes réduit (principe de parcimonie).\n\n#### Méthode du coude {#sec-13321}\n\nCette première approche est la plus simple à mettre en œuvre. Il s'agit simplement de produire plusieurs classifications à partir du dendrogramme avec différentes valeurs de *k* (nombre de groupes) et de calculer à chaque fois la part de l'inertie expliquée. Chaque groupe supplémentaire ne peut qu'améliorer l'inertie expliquée, car pour rappel, si $k=n$, alors nous expliquons 100 % de l'inertie totale. L'objectif est de déterminer à quel moment l'ajout d'un groupe supplémentaire ne contribue que de façon marginale à améliorer l'inertie expliquée. Si nous représentons les valeurs d'inertie expliquée pour les différentes valeurs de *k* dans un graphique, une rupture (un coude) indiquerait le point au-delà duquel les groupes supplémentaires ne captent finalement que du bruit et non plus de l'information.\n\nSi nous reprenons l'exemple du jeu de données `IRIS`, nous pouvons créer ce graphique avec *k* allant de 2 à 8 (@fig-kmeans2). Un premier coude très net est observable pour $k = 3$ et un second plus faible, mais tout de même marqué pour $k = 4$. \n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Méthode du coude](13-MethodeClassification_files/figure-html/fig-kmeans2-1.png){#fig-kmeans2 fig-align='center' width=75%}\n:::\n:::\n\n\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Inertie expliquée et centre de groupe**\n:::\n::: bloc_notes-body\nPour calculer l'inertie expliquée, il est nécessaire de pouvoir déterminer pour le centre de gravité (ou centroïde) chaque groupe. Lorsque la distance euclidienne est utilisée, il s'agit simplement de calculer pour chaque groupe la valeur moyenne des différentes colonnes des observations. Cependant, lorsque d'autres distances sont utilisées, il peut être plus difficile de déterminer le centre d'un groupe. Avec la distance de Manhattan, il est par exemple recommandé d'utiliser la médiane des colonnes plutôt que la moyenne. Pour la distance de Hamming, la moyenne peut aussi être utilisée, car elle représente pour cette distance la fréquence d'occurrence des différentes modalités des variables qualitatives. Pour d'autres distances plus complexes, il est préférable de définir le centre d'un groupe comme le point de ce groupe minimisant les distances à tous les autres points du groupe. Il s'agit du médoïde du groupe.\n:::\n:::\n\n#### Indicateur de silhouette {#sec-13322}\n\nSi un coude net ne s'observe pas pour la méthode précédente, il est possible d'utiliser l'indicateur de silhouette. Il permet de mesurer pour une classification à quel point une observation est similaire à celles dans son propre groupe (cohésion) comparativement aux observations des autres groupes. Elle se calcule de la façon suivante : \n\n$$\n\\begin{aligned}\ns(i) &= \\frac{b(i)-a(i)}{\\max \\{a(i), b(i)\\}} \\\\\na(i) &= \\frac{1}{|C_i|-1}\\sum_{j \\in C_i,i \\neq j}d(i,j) \\\\\nb(i) &= min_{i \\neq j}\\frac{1}{|C_j|}\\sum_{j \\in C_j}d(i,j)\n\\end{aligned}\n$$ {#eq-silhouetteidx}\n\navec $s(i)$ la valeur de l'indice de silhouette pour l'observation *i*, $a(i)$ la distance moyenne entre l'observation *i* et son groupe $C_i$ et $b(i)$ la distance minimale entre l'observation *i* et le centre de chaque autre groupe $C_j$.\n\n\nLa valeur totale de l'indice est simplement la moyenne des valeurs moyennes des indices de silhouette au sein de chaque groupe. Une valeur plus élevée indique une meilleure classification. Il est nécessaire de déterminer le centre des groupes pour calculer cet indicateur, ce qui peut être un exercice difficile quand une distance autre que la distance euclidienne est utilisée. Référez-vous à la note de la section précédente pour plus d'informations. L'indice de silhouette semble indiquer que seulement trois groupes serait un choix optimal, soit la valeur la plus haute (@fig-kmeans3).\n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Méthode de l'indice de silhouette](13-MethodeClassification_files/figure-html/fig-kmeans3-1.png){#fig-kmeans3 fig-align='center' width=75%}\n:::\n:::\n\n\n\n#### Méthode GAP {#sec-13323}\n\nCette méthode, proposée par @tibshirani2001estimating, consiste à comparer l'inertie intra-groupe (inexpliquée) avec l'inertie observée pour un jeu de données généré aléatoirement (distribution uniforme des valeurs entre le minimum et le maximum de chaque variable) pour différentes valeurs successives de *k*. Une fois ces calculs effectués, l'objectif est de trouver la valeur de *k* telle que la valeur de GAP à *k + 1* n'est pas plus grande qu'un écart type pour GAP à *k + 1*.\n\nLa statistique GAP est calculée ainsi : \n\n$$\n\\begin{aligned}\nGAP(k) = \\frac{1}{\\text{nsim}} \\sum^{\\text{nsim}}_{\\text{sim} = 1} log(W_{ksim}) - log(W_k)\n\\end{aligned}\n$$ {#eq-gapidx}\n\navec $W_k$ l'inertie non expliquée (intra-groupe), $W_{ksim}$ l'inertie non expliquée (intra-groupe) obtenue pour un jeu de données simulé et *k* le nombre de groupes.\n\nL'idée est qu'une bonne classification doit produire des résultats plus structurés que ce que nous pourrions attendre du hasard. Chaque groupe supplémentaire permet de réduire l'inertie, mais lorsque l'ajout d'un groupe ne permet pas un gain significatif comparativement au hasard, alors l'ajout de ce groupe ne se justifie pas. À nouveau, il est possible de visualiser la situation avec un simple graphique (@fig-kmeans4). Selon cette méthode, il faudrait sélectionner quatre groupes, car il s'agit de la première valeur de *k* validant le critère de cette méthode. La seconde valeur retenue par cette méthode est 6.\n \n\n\n::: {.cell layout-align=\"center\"}\n::: {.cell-output-display}\n![Méthode GAP](13-MethodeClassification_files/figure-html/fig-kmeans4-1.png){#fig-kmeans4 fig-align='center' width=75%}\n:::\n:::\n\n\n### Limites de la classification ascendante hiérarchique {#sec-1333}\n\nBien que très flexible (choix de la fonction de distance et du critère d'agrégation), la CAH fait face à un enjeu majeur : la vitesse d'exécution et la consommation de mémoire lorsque de grands jeux de données sont utilisés. En effet, il est nécessaire de calculer à chaque étape une matrice de distance entre les groupes. Si un jeu de données comprend 1000 observations, cette matrice comprend donc 1000 x 1000 cases, soit un million de distances. Même en divisant ce nombre par deux (les éléments de la matrice sont symétriques, donc $d(ij) = d(ji)$), ce nombre augmente avec le carré du nombre d'observations. Pour de grands jeux de données, la CAH peut donc échouer à cause des limites de l'ordinateur utilisé. Il existe des versions plus performantes de l'algorithme réduisant cette limite, mais il convient de la garder en mémoire. Quand un très grand jeu de données doit être analysé, les méthodes des nuées dynamiques sont une solution à considérer.\n\n### Mise en œuvre dans R {#sec-1334}\n\nNous proposons ici un exemple issu d'un article portant sur les parcs urbains de Montréal [@apparicio2010accessibilite], dont l'objectif était notamment de classifier ces parcs en fonction de leur superficie et des équipements qu'ils comprennent, et ce, en utilisant la classification ascendante hiérarchique. Nous proposons ici de reproduire l'étape de classification effectuée dans cet article. La base de données comporte 653 parcs pour lesquels la présence de 18 équipements est codée comme un ensemble de variables binaires (0 signifiant absence et 1 présence). Nous disposons également de la taille de ces parcs, recodée en cinq catégories : moins d'un hectare, de 1 à 5 hectares, de 5 à 10 hectares, de 10 à 20 hectares et 20 hectares et plus. Le @tbl-exampleHclust1DF indique le nombre d'équipements recensés dans les parcs.\n\n\n::: {#tbl-exampleHclust1DF .cell tbl-cap='Équipements recensés dans les différents parcs de Montréal'}\n::: {.cell-output-display}\n`````{=html}\n\n \n \n \n \n \n \n\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n\n
Équipements N
Équipements pour les 0 à 4 ans
Aire de jeux 601
Pataugeoire 161
Jeux d’eau 28
Terrains de sport
Baseball 188
Soccer (football) 169
Basketball 144
Tennis 125
Football 36
Volleyball 24
Athlétisme 20
Équipements d'hiver
Patinoire extérieure 241
Glissade 30
Piste de ski de fond 14
Piste de raquette 9
Équipements spécialisés
Parc de planches à roulettes 18
Patins à roues alignées 8
Autres équipements
Piscine intérieure 92
Chemin de randonnée 15
\n\n`````\n:::\n:::\n\n\nPuisque notre jeu de données ne comporte que des variables qualitatives, nous utilisons la distance du $\\Phi^2$ pour construire notre matrice de distance entre les parcs. Notons que, dans l'article original, la distance euclidienne au carré avait été utilisée, alors nous n'obtiendrons probablement pas les mêmes résultats, car la distance du $\\Phi^2$ tient compte des fréquences d'occurrence des modalités des variables qualitatives.\n\n#### Calcul de la matrice de distance {#sec-13341}\n\nLa première étape consiste donc à charger notre jeu de données et à calculer la matrice de distance.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# chargement du jeu de données et sélection des colonnes pour l'analyse\nparcs <- read.csv(\"data/classification/Parcs.txt\", header = TRUE, stringsAsFactors = FALSE)\nX <- parcs[c(5:22, 27)]\n```\n:::\n\n\nPour calculer la distance du $\\Phi^2$, nous utilisons la fonction `dist` du *package* `proxy` avec le paramètre `method = \"Phi-squared\"`. Elle requiert que l'ensemble des variables catégorielles soient converties en variables binaires. Pour cela, nous pouvons utiliser la fonction `dummy_cols` du *package* `fastDummies`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(fastDummies)\nlibrary(proxy)\n\nX <- dummy_cols(X, select_columns = \"HaTypo\", remove_selected_columns = TRUE)\nparc_distances <- dist(as.matrix(X), method = \"Phi-squared\")\n```\n:::\n\n\n#### Application de l'algorithme de classification ascendante hiérarchique {#sec-13342}\n\nUne fois la matrice obtenue, il ne reste plus qu'à appliquer la fonction `hclust` disponible de base dans R pour obtenir le dendrogramme. Comme dans l'article, nous utilisons le critère d'agrégation de Ward pour la création des groupes.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndendogramme_parcs <- hclust(parc_distances, method = \"ward.D\")\n```\n:::\n\n\nPuisque nous n'utilisons pas la distance euclidienne, nous optons ici pour l'indice de silhouette pour déterminer le nombre adéquat de groupes à former. Nous testons toutes les valeurs comprises entre 2 et 10.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(cluster)\nks <- 2:10\n\n# Calcul des indices de silhouette pour les différentes valeurs de k\nvalues <- sapply(ks, function(k){\n # découpage du dendrogramme\n groupes <- cutree(dendogramme_parcs, k = k)\n # calcul des valeurs de silhouette\n sil <- silhouette(groupes, dist = parc_distances)\n # extraction de l'indice global (moyenne des moyennes)\n idx <- mean(summary(sil)$clus.avg.widths)\n return(idx)\n})\n\n# Création d'un graphique avec les résultats\ndf <- data.frame(k = ks, silhouette = values)\nggplot(df) + \n geom_line(aes(x = k, y = silhouette)) + \n geom_point(aes(x = k, y = silhouette), color = \"red\") + \n labs(x = \"nombre de groupes\", y = \"indice global de silhouette\")\n```\n\n::: {.cell-output-display}\n![Valeur de l'indice de silhouette pour différents nombres de groupes](13-MethodeClassification_files/figure-html/fig-exampleHclust4-1.png){#fig-exampleHclust4 fig-align='center' width=75%}\n:::\n:::\n\nSi nous écartons d'emblée les résultats pour k = 2 et k = 3 (trop peu de groupes pour l'interprétation), nous constatons que la solution optimale selon ce critère est k = 5. Dans l'article original, la solution k = 6 avait été retenue en examinant le dendrogramme. Comparons les résultats pour k = 5 et k = 6.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nresk5 <- cutree(dendogramme_parcs, k = 5)\nresk6 <- cutree(dendogramme_parcs, k = 6)\nsil5 <- silhouette(resk5, dist = parc_distances)\nsil6 <- silhouette(resk6, dist = parc_distances)\n\n# résumé pour l'indice de silhouette pour k = 5\nsummary(sil5)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nSilhouette of 693 units in 5 clusters from silhouette.default(x = resk5, dist = parc_distances) :\n Cluster sizes and average silhouette widths:\n 116 212 246 84 35 \n 0.07029553 1.00000000 -0.11827930 -0.19969707 1.00000000 \nIndividual silhouette widths:\n Min. 1st Qu. Median Mean 3rd Qu. Max. \n-0.62041 -0.08502 0.09814 0.30200 1.00000 1.00000 \n```\n:::\n\n```{.r .cell-code}\n# résumé pour l'indice de silhouette pour k = 6\nsummary(sil6)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nSilhouette of 693 units in 6 clusters from silhouette.default(x = resk6, dist = parc_distances) :\n Cluster sizes and average silhouette widths:\n 116 212 197 49 84 35 \n 0.05906553 1.00000000 -0.10289391 0.07935325 -0.19969707 1.00000000 \nIndividual silhouette widths:\n Min. 1st Qu. Median Mean 3rd Qu. Max. \n-0.62041 -0.06414 0.10998 0.31846 1.00000 1.00000 \n```\n:::\n:::\n\nNous constatons que le groupe supplémentaire vient séparer le groupe trois comprenant 246 parcs dans la solution avec k = 5. Ce dernier ne comprend plus que 197 parcs pour la solution k = 6 et le nouveau groupe en compte 49. Ce nouveau groupe à un indice de silhouette moyen relativement faible (0,079), et le fait de découper le groupe trois améliore très peu sa propre valeur (passant de -0,12 à -0,10). Nous retenons cependant ici la solution avec k = 6 afin de tenter de reproduire les résultats de l'article.\n\n#### Interprétation des résultats {#sec-13343}\n\nLa dernière étape consiste à identifier les groupes obtenus et leur attribuer un intitulé en fonction de leurs caractéristiques. Dans notre cas, la classification ne comporte que des variables binaires, nous pouvons donc calculer le pourcentage de valeurs à 1 (présence d'un équipement) dans chacun des groupes.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# calcul du nombre de fois où chaque modalité est observée dans un groupe\nX$groupe <- resk6\ndf_groupes <- X %>% \n group_by(groupe) %>% summarise_all(.funs = sum)\n\n# calcul du nombre d'observations par groupe\nnb_gp <- table(resk6)\ngroupe_ratios <- round(100 * as.matrix(df_groupes)[,2:ncol(df_groupes)] / as.vector(nb_gp),1)\ngroupe_ratios <- as.data.frame(t(groupe_ratios))\nnames(groupe_ratios) <- paste0(\"groupe \", 1:ncol(groupe_ratios))\n\n# calcul du nombre moyen d'équipements par catégorie par parc\nequip_class <- list(\n c(\"AIRE_JEUX\", \"JEUX_EAU\", \"PATAUGEOIRE\"),\n c(\"ATHLETISME\", \"BASEBALL_S\", \"BASKETBALL\", \"FOOTBALL\", \"SOCCER\", \"TENNIS\", \"VOLLEY_BALL\"),\n c(\"TOBBOGAN_G\", \"PATINOIRE_E\", \"RAQUETTES\", \"SKI_FOND\"),\n c(\"PATIN_ROUE\", \"ROULI_ROUL\"),\n c(\"PISC_EXT\", \"RANDONNEE\")\n)\n\nclass_compte <- data.frame(sapply(equip_class, function(equip){\n rowSums(X[equip])\n}))\nnames(class_compte) <- c(\"enfants\", \"terrain_sport\", \"hiver\", \"specialise\", \"autre\")\nclass_compte$groupe <- resk6\ndf_class_equip <- class_compte %>% \n group_by(groupe) %>% \n summarise_all(mean)\n\ndf_class_equip <- t(df_class_equip[2:ncol(df_class_equip)])\ncolnames(df_class_equip) <- paste0(\"groupe \", 1:ncol(df_class_equip))\n\n# comptage du nombre moyen total d'équipements\ndf_equip_tot <- data.frame(\n nb = rowSums(X[1:18]),\n groupe = resk6\n)\ndf_equip_tot_mean <- df_equip_tot %>% \n group_by(groupe) %>% \n summarize_all(mean)\n\n# mise dans l'ordre de la première partie du tableau\nall_types <- do.call(c, equip_class)\nidxs <- match(all_types, row.names(groupe_ratios[1:length(all_types),]))\ngroupe_ratios <- rbind(groupe_ratios[idxs,],\n groupe_ratios[(length(all_types)+1):nrow(groupe_ratios),])\n\n# combinaison des deux tableaux\ngroupe_ratios <- rbind(groupe_ratios, df_class_equip, df_equip_tot_mean$nb, as.integer(nb_gp))\n```\n:::\n\n\nIl est ensuite possible d'afficher le tableau obtenu pour l'interpréter. Les résultats sont ici rapportés au @tbl-exampleHclust7.\n\n\n::: {#tbl-exampleHclust7 .cell layout-align=\"center\" tbl-cap='Caractéristiques des groupes obtenus lors de la CAH'}\n::: {.cell-output-display}\n`````{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n\n
groupe 1 groupe 2 groupe 3 groupe 4 groupe 5 groupe 6
Équipements pour les 0 à 4 ans (%)
Aire de jeux 69,8 100 83,2 71,4 88,1 100
Jeux d'eau 7,8 0 2,5 18,4 6,0 0
Pataugeoire 36,2 0 47,2 2,0 29,8 0
Terrains de sport (%)
Athlétisme 12,1 0 2,0 2,0 1,2 0
Baseball 62,1 0 50,8 0,0 19,0 0
Basketball 37,9 0 36,0 16,3 21,4 0
Football américain 15,5 0 7,1 8,2 0,0 0
Soccer (football) 52,6 0 29,9 87,8 7,1 0
Tennis 38,8 0 32,5 8,2 14,3 0
Volleyball 7,8 0 4,6 12,2 0,0 0
Équipements d'hiver (%)
Glissade 19,8 0 3,0 2,0 0,0 0
Patinoire 58,6 0 59,4 34,7 46,4 0
Piste de ski de fond 7,8 0 0,0 0,0 0,0 0
Raquettes 12,1 0 0,0 0,0 0,0 0
Équipements spécialisés (%)
Parc de planches à roulettes 6,0 0 0,5 0,0 0,0 0
Patins à roues alignées 8,6 0 4,1 0,0 0,0 0
Autres équipements (%)
Piscine extérieure 27,6 0 27,4 4,1 4,8 0
Chemin de randonnée 12,9 0 0,0 0,0 0,0 0
Superficie (%)
Moins d'un hectare 0,0 100 0,0 0,0 100,0 0
1 à 5 hectares 5,2 0 98,5 100,0 0,0 100
5 à 10 hectares 61,2 0 0,0 0,0 0,0 0
10 à 20 hectares 17,2 0 1,0 0,0 0,0 0
20 hectares et plus 16,4 0 0,5 0,0 0,0 0
Nombre moyen d'équipements selon le type
Équipements pour les 0 à 4 ans 1,1 1 1,3 0,9 1,2 1
Terrains de sport 2,3 0 1,6 1,3 0,6 0
Équipements d'hiver 1,0 0 0,6 0,4 0,5 0
Équipements spécialisés 0,1 0 0,0 0,0 0,0 0
Autres équipements 0,4 0 0,3 0,0 0,0 0
Tous les équipements 4,9 1 3,9 2,7 2,4 1
Nombre d'observations par groupe
116,0 212 197,0 49,0 84,0 35
\n\n`````\n:::\n:::\n\n\n* Le premier groupe correspond à de grands parcs (superficie généralement comprise entre 5 et plus de 20 hectares), il comporte 116 observations. Ces grands parcs sont en moyenne équipés de deux terrains de sport et d'un équipement d'hiver. Il s'agit vraisemblablement des grands parcs identifiés dans l'article original, dans lesquels se retrouvent également les parcs à vocation métropolitaine.\n\n* Le second groupe (212 parcs) correspond à de très petits parcs (moins d'un hectare) comportant uniquement une aire de jeu.\n\n* Le troisième groupe (197 parcs) correspond à de petits parcs (entre 1 et 5 hectares), souvent équipés d'une piscine extérieure (27,4 % des cas), et en moyenne de deux terrains de sports (essentiellement des terrains de tennis et de soccer). Ces parcs comprennent en moyenne plus de 4 équipements et doivent donc correspondre à la classe D dans l'article original (Petit parc (1 à 5 ha) avec en moyenne six équipements, dont une patinoire et une piscine).\n\n* Le quatrième groupe (49 parcs) comprend de petits parcs (entre 1 et 5 hectares) qui ressemblent aux parcs du groupe 2 mais tendent à disposer en plus d'un terrain de sport (baseball ou basketball).\n\n* Le quatrième groupe (84 parcs) correspond à de petits parcs, il est caractérisé par une présence plus marquée de pataugeoires (39 %).\n\n* Le cinquième groupe (35 parcs) est très similaire au second groupe (uniquement une aire de jeux), excepté sont les parcs qui s'y trouvent sont de taille supérieure (de 1 à 5 hectares).\n\nConsidérant les différences minimes entre certains des groupes que nous avons obtenus, il est clair que retenir seulement trois ou cinq groupes serait préférable. Notez également l'importance du choix de la distance, car nous obtenons des résultats sensiblement différents de ceux de l'article original en ayant opté pour la distance du $\\Phi^2$ plutôt que la distance euclidienne au carré.\n\n#### Utilisation de la matrice de distance euclidienne au carré {#sec-13344}\n\nPour obtenir des résultats plus proches de ceux de l'article original, nous pouvons reprendre notre analyse et utiliser cette fois-ci une distance euclidienne au carré.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nX$groupe <- NULL\n# calcule de la matrice de distance\nparc_distances_euc <- dist(as.matrix(X), method = \"Euclidean\")**2\n\n# Application de la CAH\ndendogramme_parcs_euc <- hclust(parc_distances_euc, method = \"ward.D\")\n\n# calcul de l'indice de silhouette\nks <- 2:10\nvalues <- sapply(ks, function(k){\n # découpage du dendrogramme\n groupes <- cutree(dendogramme_parcs_euc, k = k)\n # calcul des valeurs de silhouette\n sil <- silhouette(groupes, dist = parc_distances_euc)\n # extraction de l'indice global (moyenne des moyennes)\n idx <- mean(summary(sil)$clus.avg.widths)\n return(idx)\n})\n\n# création d'un graphique avec les résultats\n\ndf <- data.frame(\n k = ks,\n silhouette = values\n)\n\nggplot(df) + \n geom_line(aes(x = k, y = silhouette)) + \n geom_point(aes(x = k, y = silhouette), color = \"red\") + \n labs(x = \"nombre de groupes\", y = \"indice global de silhouette\")\n```\n\n::: {.cell-output-display}\n![Valeur de l'indice de silhouette pour différents nombres de groupes (distance euclidienne au carré)](13-MethodeClassification_files/figure-html/fig-exampleHclust8-1.png){#fig-exampleHclust8 fig-align='center' width=75%}\n:::\n:::\n\n\nNous constatons cette fois-ci, que quatre groupes serait probablement le meilleur choix et qu'au-delà de ce nombre, l'indice global de silhouette ne fait que diminuer. Tentons cependant de reproduire les résultats de l'article avec k = 6.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nresk6 <- cutree(dendogramme_parcs_euc, k = 6)\n\n# calcul du nombre de fois ou chaque modalité est observée dans un groupe\nX$groupe <- resk6\ndf_groupes <- X %>% \n group_by(groupe) %>% summarise_all(.funs = sum)\n\n# calcul du nombre d'observations par groupe\nnb_gp <- table(resk6)\n\ngroupe_ratios <- round(100 * as.matrix(df_groupes)[,2:ncol(df_groupes)] / as.vector(nb_gp),1)\ngroupe_ratios <- as.data.frame(t(groupe_ratios))\nnames(groupe_ratios) <- paste0(\"groupe \", 1:ncol(groupe_ratios))\n\n# calcul du nombre moyen d'équipements par catégorie par parc\nequip_class <- list(\n c(\"AIRE_JEUX\", \"JEUX_EAU\", \"PATAUGEOIRE\"),\n c(\"ATHLETISME\", \"BASEBALL_S\", \"BASKETBALL\", \"FOOTBALL\", \"SOCCER\", \"TENNIS\", \"VOLLEY_BALL\"),\n c(\"TOBBOGAN_G\", \"PATINOIRE_E\", \"RAQUETTES\", \"SKI_FOND\"),\n c(\"PATIN_ROUE\", \"ROULI_ROUL\"),\n c(\"PISC_EXT\", \"RANDONNEE\")\n)\n\nclass_compte <- data.frame(sapply(equip_class, function(equip){\n rowSums(X[equip])\n}))\nnames(class_compte) <- c(\"enfants\", \"terrain_sport\", \"hiver\", \"specialise\", \"autre\")\nclass_compte$groupe <- resk6\ndf_class_equip <- class_compte %>% \n group_by(groupe) %>% \n summarise_all(mean)\n\ndf_class_equip <- t(df_class_equip[2:ncol(df_class_equip)])\ncolnames(df_class_equip) <- paste0(\"groupe \", 1:ncol(df_class_equip))\n\n# comptage du nombre moyen d'équipements\ndf_equip_tot <- data.frame(\n nb = rowSums(X[1:18]),\n groupe = resk6\n)\ndf_equip_tot_mean <- df_equip_tot %>% \n group_by(groupe) %>% \n summarize_all(mean)\n\n# mise dans l'ordre de la première partie du tableau\nall_types <- do.call(c, equip_class)\nidxs <- match(all_types, row.names(groupe_ratios[1:length(all_types),]))\ngroupe_ratios <- rbind(groupe_ratios[idxs,],\n groupe_ratios[(length(all_types)+1):nrow(groupe_ratios),])\n\n# combinaison des deux tableaux\ngroupe_ratios <- rbind(groupe_ratios, df_class_equip, df_equip_tot_mean$nb, as.integer(nb_gp))\n```\n:::\n\n\nRecréons le tableau final des résultats au @tbl-exampleHclust10. Si vous comparez ce tableau avec celui de l'article original, vous verrez que notre groupe 3 correspond exactement à la classe A et que notre groupe 5 correspond exactement à la classe F. Pour les autres groupes, nous pouvons observer de légères variations, ce qui correspond vraisemblablement à des divergences d'implémentation des algorithmes entre le logiciel utilisé pour l'article (SAS) et R.\n\n\n::: {#tbl-exampleHclust10 .cell layout-align=\"center\" tbl-cap='Caractéristiques des groupes obtenus lors de la CAH (distance euclidienne au carré)'}\n::: {.cell-output-display}\n`````{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n\n
groupe 1 groupe 2 groupe 3 groupe 4 groupe 5 groupe 6
Équipements pour les 0 à 4 ans (%)
Aire de jeux 79,6 74,2 96,6 100,0 20,0 79,3
Jeux d'eau 11,1 3,0 1,7 5,1 0,0 5,9
Pataugeoire 59,3 42,4 8,4 61,0 0,0 19,7
Terrains de sport (%)
Athlétisme 13,0 15,2 0,3 0,0 0,0 1,0
Baseball 88,9 63,6 5,4 89,8 6,7 13,8
Basketball 83,3 30,3 6,1 35,6 0,0 18,2
Football 31,5 12,1 0,0 10,2 0,0 2,5
Soccer (football) 75,9 57,6 2,0 27,1 0,0 33,5
Tennis 90,7 19,7 4,1 35,6 0,0 14,8
Volleyball 20,4 3,0 0,0 1,7 0,0 4,9
Équipements d'hiver (%)
Glissade 14,8 16,7 0,0 1,7 33,3 2,5
Patinoire 87,0 57,6 13,2 86,4 26,7 30,5
Piste de ski de fond 1,9 1,5 0,0 0,0 46,7 0,0
Raquettes 0,0 1,5 0,0 0,0 86,7 0,0
Équipements spécialisés (%)
Parc de planches à roulettes 0,0 0,0 0,0 1,7 46,7 0,0
Patins à roues alignées 16,7 7,6 0,0 5,1 0,0 0,5
Autres équipements (%)
Piscine extérieure 75,9 16,7 1,4 11,9 6,7 13,8
Chemin de randonnée 1,9 0,0 0,0 0,0 93,3 0,0
Superficie (%)
Moins d'un hectare 0,0 0,0 100,0 0,0 0,0 0,0
1 à 5 hectares 42,6 1,5 0,0 98,3 0,0 99,5
5 à 10 hectares 46,3 69,7 0,0 0,0 0,0 0,0
10 à 20 hectares 1,9 27,3 0,0 0,0 13,3 0,5
20 hectares et plus 9,3 1,5 0,0 1,7 86,7 0,0
Nombre moyen d'équipements selon le type
Équipements pour les 0 à 4 ans 1,5 1,2 1,1 1,7 0,2 1,0
Terrains de sport 4,0 2,0 0,2 2,0 0,1 0,9
Équipements d'hiver 1,0 0,8 0,1 0,9 1,9 0,3
Équipements spécialisés 0,2 0,1 0,0 0,1 0,5 0,0
Autres équipements 0,8 0,2 0,0 0,1 1,0 0,1
Tous les équipements 7,5 4,2 1,4 4,7 3,7 2,4
Nombre d'observations par groupe
54,0 66,0 296,0 59,0 15,0 203,0
\n\n`````\n:::\n:::\n\n\n## Nuées dynamiques {#sec-134}\n\nLes méthodes des nuées dynamiques regroupent plusieurs algorithmes, tous plus ou moins liés avec l'algorithme le plus connu : *k-means*, originalement proposé par James MacQueen [-@macqueen1967]. Nous présentons également ici plusieurs variantes du *k-means*, soit le *k-medians*, le *k-medioids*, le *c-means* et le *c-medians*.\n\n### *K-means* {#sec-1341}\n\n#### Fonctionnement de l'algorithme {#sec-13411}\n\nNous commençons ici par détailler le fonctionnement de cet algorithme afin de mieux le cerner. D'emblée, cet algorithme nécessite que certains éléments soient définis d'avance : \n\n* Une matrice de données *X* comportant *n* lignes (nombre d'observations) et *p* colonnes (nombre de variables). Chaque variable de cette matrice doit être quantitative et continue et de préférence dans une échelle standardisée (par exemple des variables centrées réduites).\n\n* Le nombre de groupes à identifier *k* doit être choisi par l'utilisateur ou l'utilisatrice. \n\n* La distance *d* à utiliser entre les observations.\n\nLe fonctionnement classique du *k-means* est le suivant :\n\n1. Définir *k* centres de groupes de façon aléatoire.\n\n2. Déterminer pour chaque observation le centre de son groupe le plus proche en utilisant la fonction de distance.\n\n3. Pour chacun des groupes ainsi formés, recalculer le centre du groupe en calculant le centroïde (moyennes le plus souvent) des observations appartenant à ce groupe.\n\n4. Répéter l'opération 2 avec les nouveaux centres.\n\n5. Calculer l'inertie expliquée par la nouvelle classification.\n\n6. Comparer cette inertie expliquée avec celle obtenue lors de l'itération précédente.\n\n7. Si la variation entre les deux valeurs est supérieure à une certaine limite, reprendre à l'étape 2, sinon, l'algorithme prend fin.\n\nAinsi, l'algorithme *k-means* part d'une première classification obtenue aléatoirement et la raffine jusqu'au point où l'amélioration de la classification devient négligeable. Du fait de ce point de départ aléatoire, cet algorithme est dit heuristique, car deux exécutions risquent de ne pas donner exactement le même résultat. Par conséquent, en relaçant l'algorithme, vous pourriez obtenir des résultats légèrement différents, avec par exemple des groupes similaires, mais obtenus dans un autre ordre, le groupe 1 étant devenu le groupe 3 et vice-versa. Il est aussi possible d'obtenir des résultats radicalement différents d'une tentative à l'autre, ce qui signifie que les groupes formés sont très instables et ne sont pas représentatifs de la population étudiée.\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Réplicabilité des résultats dans R**\n:::\n::: bloc_astuce-body\nLorsqu'une méthode heuristique ou faisant appel au hasard est utilisée dans R, il est nécessaire de s'assurer que les résultats sont reproductibles. Cela permet notamment de relancer le même code et de réobtenir exactement les mêmes résultats : l'idée étant de figer le hasard.\n\nUltimement, un programme informatique est incapable de générer un résultat véritablement aléatoire, car il ne fait que suivre une suite d'opérations prédéterminées. Pour générer des résultats qui ressemblent au hasard, des algorithmes ont été proposés, partant d'une configuration initiale et appliquant une série d'opérations complexes permettant de générer des nombres semblant se distribuer aléatoirement. Si nous connaissons le point de départ de la suite d'opérations et que nous réappliquons ces dernières, alors nous sommes certains d'obtenir le même résultat. Il est possible, dans R, de définir un *état initial de hasard* à l'aide de la fonction `set.seed`. Avec ce point de départ défini, nous sommes certains d'obtenir les mêmes résultats en relançant les mêmes opérations. \n\nPrenons un exemple concret en sélectionnant aléatoire 3 chiffres dans un vecteur allant de 1 à 10.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nvec <- 1:10\n\n# prenons un premier échantillon\nsample(vec, size = 3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 4 9 3\n```\n:::\n\n```{.r .cell-code}\n# et un second échantillon \nsample(vec, size = 3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 6 10 8\n```\n:::\n:::\n\nNous obtenons bien deux échantillons différents. Recommençons en utilisant la fonction `set.seed` pour obtenir cette fois-ci des résultats identiques.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nvec <- 1:10\n\n# prenons un premier échantillon\nset.seed(123)\nsample(vec, size = 3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 3 10 2\n```\n:::\n\n```{.r .cell-code}\n# et un second échantillon \nset.seed(123)\nsample(vec, size = 3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 3 10 2\n```\n:::\n\n```{.r .cell-code}\n# prenons un troisème échantillon\nset.seed(4568997)\nsample(vec, size = 3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 5 6 7\n```\n:::\n\n```{.r .cell-code}\n# et un quatrième échantillon \nset.seed(4568997)\nsample(vec, size = 3)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1] 5 6 7\n```\n:::\n:::\n\n\nVous constatez que nous utilisons cette fonction plusieurs fois au cours de cette section. Elle nous permet de nous assurer que les résultats obtenus ne changent pas entre le moment où nous écrivons le livre et le moment où nous le formatons. Sinon, le texte pourrait ne plus être en phase avec les images ou les tableaux.\n:::\n:::\n\nPour mieux comprendre le fonctionnement du *k-means*, nous proposons ici une visualisation de ses différentes itérations (@fig-kmeansA). \nNous pouvons constater que, pour ce jeu de données relativement simple, l'algorithme converge très rapidement et que sa solution varie peu au-delà de la troisième itération. \nL'amination de la @fig-kmeansA illustre pourquoi le *k-means* est appelé algorithme de nuées dynamiques.\n\n![Algorithme K-means](images/Chap13/kmeansGif.gif){#fig-kmeansA width=\"80%\" fig-align=\"center\"}\n\n\n\n\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Centre de groupe et _k-means_**\n:::\n::: bloc_notes-body\nÀ nouveau, puisque chaque itération du *k-means* nécessite de recalculer les centres des groupes formés, des problèmes peuvent être rencontrés avec certains types de distance. C'est pourquoi il est recommandé d'utiliser la distance euclidienne avec le *k-means* original. Si des distances plus complexes doivent être utilisées, il est préférable d'utiliser la classification ascendante hiérarchique.\n:::\n:::\n\n#### Choix du nombre optimal de groupes {#sec-13412}\n\nComme pour la CAH, le principal enjeu avec le *k-means* est de déterminer le nombre idéal de groupes pour effectuer la classification. Si ce nombre n'est pas connu à l'avance et qu'aucune forte justification théorique n'existe, il est possible d'utiliser les mêmes techniques que pour la CAH, soit la méthode du coude, l'indicateur de silhouette ou la méthode GAP.\n\n\n### K-médianes {#sec-1342}\n\nLe *k-medians* est une variante du *k-means*. Contrairement au *k-means* privilégiant la distance euclidienne, le *k-medians* est à utiliser en priorité avec une distance de Manhattan. En effet, le centre d'un groupe n'est pas déterminé comme la moyenne des variables des observations appartenant à ce groupe (*k-means*), mais comme la médiane pour chaque variable (*k-medians*). En dehors de ces deux spécificités, il reprend le fonctionnement décrit plus haut pour le *k-means*. Il est particulièrement pertinent de l'utiliser quand un jeu de données comprend un très grand nombre de colonnes, car dans ce contexte, la distance euclidienne peine à représenter les différences entre les observations. De plus, l'utilisation de la médiane le rend moins sensible aux valeurs extrêmes.\n\n\n### K-médoïds {#sec-1343}\n\nLe *k-médoïds* est également une variante du *k-means*. Le *k-means* crée des groupes en cherchant les centres de ces groupes dans l'espace multidimensionnel des données. Ces centres de groupes peuvent très bien ne pas correspondre à un point du jeu de données, au même titre que la moyenne d'une variable ne coïncide que rarement avec une observation réelle de cette variable. Pour le *k-médoïds*, les groupes sont formés en cherchant les centres de ces groupes **parmi** les observations du jeu de données. Ainsi, chaque groupe est centré sur une observation réelle, la plus similaire à l'ensemble des observations du groupe.\n\nL'algorithme effectue les opérations suivantes : \n\n1. Sélectionner aléatoirement *k* observations du jeu de données, elles constituent les centres des groupes initiaux.\n\n2. Attribuer chaque observation au centre du groupe le plus proche.\n\n3. Tant que la nouvelle solution est plus efficace, effectuer les opérations suivantes : \n * pour chaque centre *m* et pour chaque observation *o*,\n * considérer l'inversion de *m* et *o*\n * si cette permutation est meilleure que les précédentes, la conserver en mémoire\n * effectuer la meilleure permutation retenue si elle améliore la classification, sinon l'algorithme prend fin.\n \nLe *k-médoïds* est moins utilisé que le *k-means*, mais il est plus performant quand des distances autres que la distance euclidienne sont utilisées ou encore que des valeurs aberrantes/extrêmes sont présentes dans les données.\n\n### Mise en œuvre dans R {#sec-1344}\n\nPour cet exemple, nous proposons d'utiliser le jeu de données spatiales `LyonIris` du *package* `geocmeans`. Ce jeu de données spatiales pour l'agglomération lyonnaise (France) comprend dix variables, dont quatre environnementales (EN) et six socioéconomiques (SE), pour les îlots regroupés pour l'information statistique (IRIS) de l'agglomération lyonnaise (@tbl-datageocmeans et @fig-datacartoacp). Nous proposons de réaliser une analyse similaire à celle de l'article de @2021_4, soit de classer les IRIS de Lyon selon ces caractéristiques pour déterminer si certains groupes d'IRIS combinent des situations désavantageuses sur les plans sociaux et environnementaux, dans une perspective d'équité environnementale.\n\nNotez ici que la fonction `st_drop_geometry` provenant du package `sf` permet de retirer l'information géographique du jeu de données `LyonIris` pour obtenir un simple `dataframe`.\n\n\n::: {#tbl-datageocmeans .cell tbl-cap='Statistiques descriptives du jeu de données LyonIris'}\n::: {.cell-output-display}\n| |Nom |Intitulé | Type | Moy.| E.-T.| Min.| Max.|\n|:----------|:----------|:--------------------------------|:----:|--------:|-------:|--------:|--------:|\n|Lden |Lden |Bruit routier (Lden dB(A)) | EN | 55,6| 4,9| 33,9| 71,7|\n|NO2 |NO2 |Dioxyde d'azote (ug/m^3^) | EN | 28,7| 7,9| 12,0| 60,2|\n|PM25 |PM25 |Particules fines (PM$_{2,5}$) | EN | 16,8| 2,1| 11,3| 21,9|\n|VegHautPrt |VegHautPrt |Canopée (%) | EN | 18,7| 10,1| 1,7| 53,8|\n|Pct0_14 |Pct0_14 |Moins de 15 ans (%) | SE | 18,5| 5,7| 0,0| 54,0|\n|Pct_65 |Pct_65 |65 ans et plus (%) | SE | 16,2| 5,9| 0,0| 45,1|\n|Pct_Img |Pct_Img |Immigrants (%) | SE | 14,5| 9,1| 0,0| 59,8|\n|TxChom1564 |TxChom1564 |Taux de chômage | SE | 14,8| 8,1| 0,0| 98,8|\n|Pct_brevet |Pct_brevet |Personnes à faible scolarité (%) | SE | 23,5| 12,6| 0,0| 100,0|\n|NivVieMed |NivVieMed |Médiane du niveau de vie (Euros) | SE | 21 804,5| 4 922,5| 11 324,0| 38 707,0|\n:::\n:::\n\n\n\n#### Préparation des données {#sec-13441}\n\nLa première étape consiste donc à charger les données et à les préparer pour l'analyse. Toutes les variables que nous utilisons sont des variables continues. Cependant, elles ne sont pas exprimées dans la même échelle, nous proposons donc de les standardiser ici en les centrant (moyenne = 0) et en les réduisant (écart-type = 1). Cette opération peut être effectuée simplement dans R en utilisant la fonction `scale`.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Chargement des données\nlibrary(geocmeans)\nlibrary(sf)\n\ndata(LyonIris)\n\n# NB : LyonIris est un objet spatial, il faut donc extraire uniquement son DataFrame\nX <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\" , \"Pct0_14\" , \"Pct_65\" , \"Pct_Img\",\n \"TxChom1564\" , \"Pct_brevet\" , \"NivVieMed\")])\n\n# Centrage et réduction de chaque colonne du DataFrame\nfor (col in names(X)){\n X[[col]] <- scale(X[[col]], center = TRUE, scale = TRUE)\n}\n```\n:::\n\n\n#### Choix du nombre de groupes optimal {#sec-13442}\n\nLa seconde étape consiste à déterminer le nombre de groupes optimal. Pour cela, nous comparons les résultats des trois méthodes proposées : la méthode du coude, l'indice de silhouette et la méthode GAP. Pour chaque méthode, nous testons les nombres de groupes de 2 à 10.\n\n##### Méthode du coude {#sec-134421}\n\nCommençons par appliquer la méthode du coude. Nous calculons donc l'inertie expliquée par la classification pour différentes valeurs de *k* (nombre de groupes) avant de construire la @fig-kmeansC.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nks <- 2:10\n\n## ---- Méthode du coude ---- ##\ninertie_exps <- sapply(ks, function(k){\n # calcul du kmeans avec k\n resultat <- kmeans(X, centers = k)\n # calcul de l'inertie expliquée (1 - inertie intragroupe / inertie totale)\n inertie_exp <- 1-(sum(resultat$withinss) / resultat$totss)\n return(inertie_exp)\n})\n\ndf <- data.frame(\n k = ks,\n inertie_exp = inertie_exps\n)\n\nggplot(df) + \n geom_line(aes(x = k, y = inertie_exp)) + \n geom_point(aes(x = k, y = inertie_exp), color = \"red\") + \n labs(x = \"nombre de groupes\", y = \"inertie expliquée (%)\")\n```\n\n::: {.cell-output-display}\n![Inertie expliquée pour différents nombres de groupes pour le k-means](13-MethodeClassification_files/figure-html/fig-kmeansC-1.png){#fig-kmeansC width=75%}\n:::\n:::\n\nDans l'article original, quatre groupes avaient été retenus. Nous pouvons constater ici qu'un coude fort se situe à k = 3 et qu'au-delà de cette limite, l'ajout d'un groupe supplémentaire contribue à expliquer une plus petite partie de l'inertie supplémentaire comparativement au précédent.\n\n##### Indice de silhouette {#sec-134422}\n\nPoursuivons avec l'indice de silhouette calculé de nouveau avec des valeurs de *k* allant de 2 à 10. Notez que nous devons au préalable créer une matrice de distances entre les observations du jeu de données pour construire notre indice de silhouette. Puisque nous utilisons l'algorithme *k-means*, nous utilisons la distance euclidienne.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nks <- 2:10\n\n# calcul d'une matrice de distance euclidienne entre les observations\ndist_mat <- dist(X, method = \"euclidean\")\n\n## ---- indice de silhouette ---- ##\nvalues <- sapply(ks, function(k){\n resultat <- kmeans(X, centers = k)\n groupes <- resultat$cluster\n # calcul des valeurs de silhouette\n sil <- silhouette(groupes, dist = dist_mat)\n # extraction de l'indice global (moyenne des moyennes)\n idx <- mean(summary(sil)$clus.avg.widths)\n return(idx)\n})\n\ndf <- data.frame(\n k = ks,\n silhouette = values\n)\n\nggplot(df) + \n geom_line(aes(x = k, y = silhouette)) + \n geom_point(aes(x = k, y = silhouette), color = \"red\") + \n labs(x = \"nombre de groupes\", y = \"Indice de silhouette\")\n```\n\n::: {.cell-output-display}\n![Indice de silhouette pour différents nombres de groupes pour le k-means](13-MethodeClassification_files/figure-html/fig-kmeansD-1.png){#fig-kmeansD width=75%}\n:::\n:::\n\n\nÀ nouveau, la @fig-kmeansD indique que le nombre de groupes optimal est trois selon l'indice de silhouette.\n\n##### Méthode GAP {#sec-134423}\n\nPour appliquer la méthode GAP, nous proposons d'utiliser la fonction `clusGap` du *package* `NbClust`. Pour l'utiliser, il est nécessaire de définir une fonction renvoyant pour le nombre de groupes *k* et le jeu de données *x* une liste comprenant un vecteur attribuant chaque observation à chaque groupe. Il est possible de considérer ce type de fonction comme un « adaptateur ».\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(NbClust)\n\n# définition de la fonction adaptateur\nadaptor <- function(x, k){\n clust <- kmeans(x, k)\n return(list(\n \"cluster\" = clust$cluster\n ))\n}\n\n# calcul de la méthode GAP\nvals <- clusGap(X, adaptor, K.max = 10, verbose = FALSE)\ntab <- data.frame(vals$Tab)\ntab$k <- 1:nrow(tab)\n\n# détermination des valeurs de k retenues par la méthode (1ere et 2e)\nis_valid <- sapply(2:nrow(tab), function(i){\n tab[i-1,\"gap\"] >= (tab[i,\"gap\"] - tab[i,\"SE.sim\"])\n})\nvalids <- subset(tab, is_valid)[1,]\nvalids2 <- subset(tab, is_valid)[2,]\n\n# réalisation du graphique\nggplot(tab) + \n geom_line(aes(x = k, y = gap)) + \n geom_segment(x = valids$k, xend = valids$k, y = min(tab$gap), yend = valids$gap, \n linetype = \"dashed\") +\n geom_segment(x = valids2$k, xend = valids2$k, y = min(tab$gap), yend = valids2$gap, \n linetype = \"dashed\") +\n geom_point(aes(x = k, y = gap), color = \"red\") + \n scale_x_continuous(breaks = 1:10) + \n labs(x = \"nombre de groupes\", y = \"GAP\")\n```\n\n::: {.cell-output-display}\n![Méthode GAP pour différents nombres de groupes pour le k-means](13-MethodeClassification_files/figure-html/fig-kmeansE-1.png){#fig-kmeansE fig-align='center' width=75%}\n:::\n:::\n\nLa @fig-kmeansE indique également que le nombre de groupes à retenir est trois. Nous retenons cependant quatre groupes pour pouvoir plus facilement comparer nos résultats avec ceux de l'article original.\n\n#### Application l'algorithme du *k-means* {#sec-13443}\n\nMaintenant que nous avons choisi le nombre de groupes à former, nous pouvons simplement appliquer la fonction `kmeans` présente de base dans R.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nset.seed(145)\nresultats <- kmeans(X, centers = 4)\n```\n:::\n\n\n#### Interprétation des résultats {#sec-13444}\n\nUne fois les groupes obtenus, l'étape la plus importante est de parvenir à interpréter ces groupes. Pour cela, il est nécessaire de les explorer en profondeur au travers des variables utilisées pour les constituer. Dans notre cas, le jeu de données `LyonIris` est spatialisé, nous pouvons donc commencer par cartographier les groupes.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(tmap)\nLyonIris$groupes <- paste(\"groupe\", resultats$cluster, sep = \" \")\n\ntm_shape(LyonIris) + \n tm_polygons(col = \"groupes\", palette =\n c(\"#EFBE89\", \"#4A6A9F\", \"#7DB47C\", \"#FAF29C\"), lty = 1, lwd = 0.1)\n```\n\n::: {.cell-output-display}\n![Cartographie des groupes obtenus avec la méthode du k-means](13-MethodeClassification_files/figure-html/fig-kmeansG-1.png){#fig-kmeansG fig-align='center' width=75%}\n:::\n:::\n\n\nIl est ainsi possible de constater que le groupe 3 forme un ensemble assez compact d'IRIS au centre de Lyon. Le groupe 4 correspond quant à lui à des IRIS situés en périphérie plutôt éloignée, essentiellement à l'ouest. Le groupe 1 correspond à une périphérie proche du groupe 2 et apparaît comme un ensemble d'enclaves dispersées.\n\nPour distinguer rapidement les profils des différents groupes, il est possible d'utiliser un graphique en radar. La construction d'un tel graphique peut être un peu fastidieuse dans R, cependant le *package* `geocmeans` propose une fonction assez pratique : `spiderPlots`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(geocmeans)\n\n# création d'une matrice d'appartenance binaire des groupes\nmatrice_gp <- fastDummies::dummy_cols(resultats$cluster, remove_selected_columns = TRUE)\n\n# réalisation du graphique\npar(mfrow=c(3,2), mai = c(0.1,0.1,0.1,0.1))\nplots <- spiderPlots(X, matrice_gp, \n chartcolors = c(\"#EFBE89\", \"#4A6A9F\", \"#7DB47C\", \"#FAF29C\"))\n```\n\n::: {.cell-output-display}\n![Graphiques en radar pour les groupes issus du k-means](13-MethodeClassification_files/figure-html/fig-kmeansH-1.png){#fig-kmeansH fig-align='center' width=90%}\n:::\n:::\n\n\nIl est ainsi possible de constater, à la @fig-kmeansH, que le groupe 3 est caractérisé par un niveau de vie élevé, mais par des niveaux de concentration de pollution atmosphérique plus élevés également. Le groupe 4 en revanche est caractérisé par un important couvert végétal, un niveau de vie médian élevé et une plus forte proportion de personnes de plus de 65 ans. Le groupe 1 est quant à lui marqué par des niveaux sonores plus élevés. Enfin, le groupe 2 se caractérise par une plus grande proportion de population ayant obtenu comme diplôme le plus élevé le brevet des collèges, d'immigrants, de jeunes de moins de 15 ans et un taux de chômage plus élevé.\n\nNotez que ces graphiques nous permettent rapidement de nous faire une idée des caractéristiques des groupes, mais uniquement sur une échelle relative. En effet, ils ne nous indiquent à aucun moment la taille des écarts entre les groupes. Pour cela, il est nécessaire de réaliser des graphiques en violon pour chaque variable. Pour ce type de graphique, il est préférable d'utiliser les données originales non transformées pour pouvoir mieux appréhender si les différences entre les groupes sont importantes ou négligeables.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(ggpubr)\nX2 <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\" , \"Pct0_14\",\n \"Pct_65\" , \"Pct_Img\" , \"TxChom1564\" , \"Pct_brevet\",\n \"NivVieMed\")])\n\nplots <- violinPlots(X2, as.character(resultats$cluster))\nggarrange(plotlist = plots, ncol = 2, nrow = 5)\n```\n\n::: {.cell-output-display}\n![Graphiques en violon pour les groupes issus du k-means](13-MethodeClassification_files/figure-html/fig-kmeansI-1.png){#fig-kmeansI fig-align='center' width=100%}\n:::\n:::\n\n\nIl est également recommandé de calculer des statistiques descriptives par groupe et de les rapporter dans un tableau.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# obtention d'un tableau par groupe\ntableaux <- summarizeClusters(X2, matrice_gp, dec = 1, silent = TRUE)\n\n# concaténation des tableaux\ntableau_tot <- do.call(rbind, tableaux)\n```\n:::\n\n::: {#tbl-kmeansK .cell layout-align=\"center\" tbl-cap='Descriptions des quatre groupes obtenus'}\n::: {.cell-output-display}\n`````{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
Lden NO2 PM25 VegHautPrt Pct014 Pct65 PctImg TxChom1564 Pctbrevet NivVieMed
groupe 1
Q5 53,8 25,2 15,6 6,6 12,4 10,0 8,1 7,6 17,4 15 822,7
Q10 54,5 26,4 15,9 8,0 13,9 11,4 9,2 9,8 18,1 16 976,0
Q25 56,3 29,3 17,0 11,0 16,3 13,6 11,8 11,5 20,8 18 454,0
Q50 58,9 32,3 18,2 15,3 18,3 16,6 15,9 13,7 24,1 19 559,0
Q75 62,5 36,5 18,7 22,3 20,5 19,5 18,6 16,9 30,0 21 575,2
Q90 64,7 39,3 19,0 30,3 22,7 22,8 21,1 19,8 33,0 23 544,7
Q95 66,7 40,7 19,3 35,6 24,9 25,1 23,0 21,9 37,7 24 765,7
Mean 59,6 32,7 17,8 17,2 18,2 16,7 15,7 14,1 25,5 19 948,0
Std 4,2 5,2 1,2 8,5 4,0 4,7 6,5 4,3 7,6 2 637,2
groupe 2
Q5 50,8 19,3 13,9 6,1 18,3 6,4 17,7 16,5 30,5 12 323,5
Q10 52,0 20,2 14,3 7,8 20,0 8,7 20,2 16,8 32,9 12 747,0
Q25 53,9 23,0 15,3 11,2 22,8 10,7 23,5 19,6 36,2 13 530,5
Q50 56,4 25,1 16,2 14,5 25,2 13,6 28,0 24,5 39,9 15 340,0
Q75 58,4 29,4 17,0 18,1 27,8 16,9 33,5 32,5 46,0 16 342,0
Q90 63,1 33,7 18,5 24,4 31,3 20,2 38,2 36,3 50,2 18 363,9
Q95 64,9 39,0 19,1 28,1 32,8 21,4 41,1 38,0 60,2 20 128,6
Mean 56,8 26,3 16,2 15,4 25,4 13,8 28,5 26,6 42,0 15 401,4
Std 4,1 6,3 1,5 6,8 6,2 4,8 8,0 10,5 11,3 2 340,4
groupe 3
Q5 50,2 28,3 17,0 5,0 6,8 5,2 5,8 7,7 6,7 19 029,9
Q10 51,2 29,5 17,6 6,6 9,5 7,2 6,7 8,5 7,7 19 546,4
Q25 53,2 31,3 18,6 9,2 11,4 9,5 7,9 11,0 9,5 21 652,0
Q50 55,2 35,4 19,3 12,6 14,1 12,4 11,0 12,9 12,0 23 342,0
Q75 58,0 39,6 19,8 16,0 16,2 16,0 13,1 15,1 14,8 25 954,1
Q90 60,0 43,0 20,1 21,0 18,2 18,9 16,3 18,0 16,6 28 951,0
Q95 61,2 44,4 20,4 29,3 19,5 20,9 17,7 19,3 19,1 31 922,5
Mean 55,6 35,8 19,0 13,6 13,8 12,6 11,1 13,1 12,1 23 999,7
Std 3,7 5,6 1,0 6,8 4,2 4,7 4,6 4,4 4,0 3 870,3
groupe 4
Q5 44,9 14,7 12,7 8,2 13,1 12,7 3,8 6,7 10,8 19 496,0
Q10 46,6 15,7 13,0 11,8 14,9 13,5 4,4 7,0 12,4 20 257,0
Q25 50,3 19,0 13,8 16,7 17,1 16,1 6,0 8,0 15,7 21 963,0
Q50 52,6 22,0 14,7 24,9 18,9 19,3 8,1 9,8 20,0 24 109,8
Q75 54,9 25,2 15,5 32,6 20,8 22,8 10,9 12,0 25,6 26 698,0
Q90 57,7 27,5 16,3 41,2 22,3 27,4 14,5 14,7 30,6 29 947,0
Q95 59,1 28,7 16,8 43,6 22,7 29,7 18,1 16,6 33,1 32 386,5
Mean 52,3 21,8 14,7 25,5 18,6 20,1 8,8 10,4 21,1 24 761,6
Std 4,3 4,4 1,2 11,0 3,1 5,6 4,2 3,4 7,6 4 008,7
\n\n`````\n:::\n:::\n\n\nLes constats que nous avons faits précédemment sont confirmés par la @fig-kmeansI et le @tbl-kmeansK. Nous retrouvons ici les groupes originaux décrits dans l'article de @2021_4 : \n\n* **Groupe 1** : les espaces interstitiels, formant une périphérie proche du centre et relativement hétérogène sur les variables étudiées, mais caractérisée par des niveaux de bruit importants.\n\n* **Groupe 2** : les banlieues jeunes et défavorisées, avec des niveaux d'exposition aux pollutions atmosphérique et sonore relativement élevés comparativement à l'ensemble de la région.\n\n* **Groupe 3** : les quartiers centraux aisés, mais marqués par les plus hauts niveaux de pollution atmosphérique.\n\n* **Groupe 4** : les communes rurales, aisées et vieillissantes.\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Interprétation interactive**\n:::\n::: bloc_astuce-body\nSi, comme dans notre exemple, vos données comportent une dimension spatiale, le *package* `geocmeans` propose une fonction intéressante appelée `sp_clust_explorer` démarrant une application permettant d'explorer les résultats de votre classification. Le seul enjeu est de créer un objet de la classe `FCMres`. Voici un court exemple : \n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# création d'une matrice binaire d'appartenance\nkmeans_mat <- dummy_cols(resultats$cluster, remove_selected_columns = TRUE)\n\n# extraction des centres de notre classification\ncentres <- resultats$centers\n\n# création de l'objet FCMres\nkmeansres <- FCMres(list(\n \"Centers\" = centres,\n \"Belongings\" = kmeans_mat,\n \"Data\" = X2,\n \"m\" = 1,\n \"algo\" = \"kmeans\"\n))\n\n# démarrage de l'application shiny\nsp_clust_explorer(object = kmeansres, spatial = LyonIris)\n```\n:::\n\n:::\n:::\n\n#### K-médianes et K-médoides {#sec-13455}\n\nNous présentons simplement ici comment effectuer la même analyse en utilisant les variantes du *k-means*, soit le *k-medians* et le *k-mediods*.\n\nIl existe relativement peu d'implémentation du *k-medians* dans R, nous optons donc ici pour la fonction `kGmedian` du *package* `Gmedian`. Pour le *k-mediods*, nous avons retenu la fonction `pam` du *package* `cluster`.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(Gmedian)\nk_median_res <- kGmedian(X, 4)\n\nlibrary(cluster)\nk_mediods_res <- pam(X,4)\n```\n:::\n\n\nJuste pour le plaisir des yeux, nous pouvons cartographier les trois classifications obtenues en nous assurant au préalable de faire coïncider les groupes les plus similaires de nos trois classifications.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nmatrice_gp_kmeans <- dummy_cols(resultats$cluster,\n remove_selected_columns = TRUE)\nmatrice_gp_kmedians <- dummy_cols(as.vector(k_median_res$cluster),\n remove_selected_columns = TRUE)\nmatrice_gp_kmedioids <- dummy_cols(k_mediods_res$cluster,\n remove_selected_columns = TRUE)\n\n# Appariement des groupes du k-medians avec ceux du kmeans\nmatrice_gp_kmedians <- geocmeans::groups_matching(as.matrix(matrice_gp_kmeans),\n as.matrix(matrice_gp_kmedians))\n\n# Appariement des groupes du k-medioids avec ceux du kmeans\nmatrice_gp_kmedioids <- geocmeans::groups_matching(as.matrix(matrice_gp_kmeans),\n as.matrix(matrice_gp_kmedioids))\n\n# ajouts des colonnes nécessaires à LyonIris\ncolnames(matrice_gp_kmeans) <- paste0(\"groupe_\", 1:4)\ncolnames(matrice_gp_kmedians) <- paste0(\"groupe_\", 1:4)\ncolnames(matrice_gp_kmedioids) <- paste0(\"groupe_\", 1:4)\n\nLyonIris$kmeans <- colnames(matrice_gp_kmeans)[max.col(matrice_gp_kmeans)]\nLyonIris$kmedians <- colnames(matrice_gp_kmedians)[max.col(matrice_gp_kmedians)]\nLyonIris$kmedioids <- colnames(matrice_gp_kmedioids)[max.col(matrice_gp_kmedioids)]\n\n# construction de la figure\ncouleurs <- c(\"#EFBE89\", \"#4A6A9F\", \"#7DB47C\", \"#FAF29C\")\n\nmap1 <- tm_shape(LyonIris) + \n tm_polygons(col = \"kmeans\", palette = couleurs, lty = 1, lwd = 0.1)\nmap2 <- tm_shape(LyonIris) + \n tm_polygons(col = \"kmedians\", palette = couleurs, lty = 1, lwd = 0.1)\nmap3 <- tm_shape(LyonIris) + \n tm_polygons(col = \"kmedioids\", palette = couleurs, lty = 1, lwd = 0.1)\n\ntmap_arrange(map1, map2, map3, \n ncol = 2, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Comparaison géographique des résultats obtenus pour le k-means, le k-medians et le k-medoids](13-MethodeClassification_files/figure-html/fig-kmeansM-1.png){#fig-kmeansM fig-align='center' width=100%}\n:::\n:::\n\n\nLes trois cartes sont très similaires (@fig-kmeansM), ce qui signifie que les trois algorithmes tendent à attribuer les observations aux mêmes groupes. Cependant, nous observons des différences, notamment au nord avec des observations alternant entre les groupes 2 et 3 selon la méthode employée. Cela peut notamment signifier que ces observations sont « indécises », qu'il est difficile de les attribuer définitivement à une catégorie en particulier. Pour prendre en compte cette forme d'incertitude, il est possible d'opter pour des méthodes de classification en logique floue.\n\n### Extensions en logique floue : *c-means*, *c-medoids* {#sec-1346}\n\nComme nous l'avons mentionné en introduction de cette section, les méthodes de classification floues ont pour objectif d'évaluer le degré d'appartenance de chaque observation à chaque groupe plutôt que d'attribuer chaque observation à un seul groupe. Il est ainsi possible de repérer des observations incertaines, à cheval entre plusieurs groupes. Nous présentons ici deux algorithmes appartenant à cette famille : le *c-means* et le *c-medoids*. Il s'agit dans les deux cas d'extensions des *k-means* et *k-medoids* vus précédemment.\n\nPour ces deux méthodes, comme pour le *k-means*, le nombre de groupes *k* doit être spécifié. Elles comprennent cependant un paramètre supplémentaire : *m*, appelé paramètre de floutage qui contrôle à quel point le résultat obtenu sera flou ou strict. Une valeur de 1 produit une classification stricte (chaque observation appartient à un seul groupe) et une valeur plus grande conduit à des classifications de plus en plus floues, jusqu'à ce que chaque observation appartienne à un degré identique à chacun des groupes. Il est recommandé de sélectionner *m* en même temps que *k*, car ces deux valeurs influencent simultanément la qualité de la classification. La meilleure approche consiste à tester un ensemble de combinaisons de *m* et de *k* et à comparer les valeurs obtenues pour différents indicateurs de qualité de classification floue. Parmi ces indicateurs, il est notamment recommandé d'utiliser le pourcentage de l'inertie expliquée, l'indice de silhouette pour classification floue, l'indice de Xie et Beni [-@xie1991validity], et de Fukuyama et Sugeno [@fukuyama1989].\n\n#### Mise en œuvre du *c-means* dans R {#sec-13461}\n\nLe *package* `fclust` comprend un très grand nombre de méthodes pour effectuer des classifications floues, nous l'utilisons donc en priorité ici en combinaison avec des fonctions d'interprétation du *package* `geocmeans`.\n\n##### Préparation des données\n\nComme pour le *k-means*, cette méthode nécessite de disposer d'un jeu de données ne comprenant que des variables quantitatives dans la même échelle. Nous commençons donc à nouveau par standardiser nos données. Pour varier les plaisirs, nous optons cette fois-ci pour une transformation des variables dans une échelle allant de 0 à 100.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(fclust)\n\ndata(LyonIris)\n\n# NB : LyonIris est un objet spatial, il faut donc extraire uniquement son DataFrame\nX <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\" , \"Pct0_14\",\n \"Pct_65\" , \"Pct_Img\",\n \"TxChom1564\" , \"Pct_brevet\" , \"NivVieMed\")])\n\n# changement d'échelle des données (0 à 100)\nto_0_100 <- function(x){\n return((x-min(x)) / (max(x) - min(x)) * 100)\n}\n\nfor (col in names(X)){\n X[[col]] <- to_0_100(X[[col]])\n}\n```\n:::\n\n\n##### Sélection de *k* et de *m*\n\nLa seconde étape consiste à sélectionner les valeurs optimales pour *k* et *m*. Nous testons ici toutes les valeurs de k de 2 à 7, et les valeurs de *m* de 1,5 à 2,5 (avec des écarts de 0,1).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nlibrary(e1071)\nset.seed(123)\nms <- seq(1.5,2.5,by = 0.1)\nks <- 2:7\n\n\n# calcul de toutes les combinaisons\ncombinaisons <- expand.grid(ms, ks)\n\neval_indices <- c(\"Explained.inertia\", \"Silhouette.index\", \"FukuyamaSugeno.index\")\n\nvalues <- apply(combinaisons, MARGIN = 1, FUN = function(row){\n m <- row[[1]]\n k <- row[[2]]\n resultats <- FKM(X, k, m)\n idx <- geocmeans::calcqualityIndexes(as.matrix(X),\n as.matrix(resultats$U), \n m = m,\n indices = eval_indices)\n return(c(k, m, unlist(idx)))\n})\n\ndf_scores <- data.frame(t(values))\nnames(df_scores) <- c(\"k\", \"m\", \"inertie\", \"silhouette\", \"FukuyamaSugeno\")\n\n# changer l'échelle de l'indice pour un graphique plus joli\ndf_scores$FukuyamaSugeno <- round(df_scores$FukuyamaSugeno/10000,2)\n\n# création de trois figures pour représenter les trois indicateurs\nlibrary(viridis)\n\nplot1 <- ggplot(df_scores) + \n geom_raster(aes(x = k, y = m, fill = inertie)) + \n scale_fill_viridis() + \n scale_x_continuous(breaks = c(2,3,4,5,6,7)) +\n coord_fixed(ratio=4) + \n guides(fill = guide_colourbar(barwidth = 5, barheight = 0.5)) +\n labs(fill = \"Inertie expliquée\") + \n theme(legend.position = \"bottom\", legend.box = \"horizontal\",\n legend.title = element_text( size=9), legend.text=element_text(size=8))\n\nplot2 <- ggplot(df_scores) + \n geom_raster(aes(x = k, y = m, fill = silhouette)) + \n scale_fill_viridis() + \n scale_x_continuous(breaks = c(2,3,4,5,6,7)) +\n coord_fixed(ratio=4) + \n guides(fill = guide_colourbar(barwidth = 5, barheight = 0.5)) +\n labs(fill = \"Indice de silhouette\") + \n theme(legend.position = \"bottom\", legend.box = \"horizontal\",\n legend.title = element_text( size=9), legend.text=element_text(size=8))\n\nplot3 <- ggplot(df_scores) + \n geom_raster(aes(x = k, y = m, fill = FukuyamaSugeno)) + \n scale_fill_viridis() + \n scale_x_continuous(breaks = c(2,3,4,5,6,7)) +\n coord_fixed(ratio=4) + \n guides(fill = guide_colourbar(barwidth = 5, barheight = 0.5)) +\n labs(fill = \"Indice de Fukuyama et Sugeno\") + \n theme(legend.position = \"bottom\", legend.box = \"horizontal\",\n legend.title = element_text( size=9), legend.text=element_text(size=8))\n\nggarrange(plot1, plot2, plot3, ncol = 2, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Sélection des paramètres k et m pour l'algorithme c-means](13-MethodeClassification_files/figure-html/fig-cmeansB-1.png){#fig-cmeansB fig-align='center' width=75%}\n:::\n:::\n\n\nLes trois graphiques à la @fig-cmeansB semblent indiquer des solutions différentes. Sans surprise, augmenter le niveau de flou (*m*) réduit l'inertie expliquée, alors qu'augmenter le nombre de groupes (*k*) augmente l'inertie expliquée. L'indice de silhouette indique assez clairement que le nombre de trois groupes serait le meilleur choix, suivi par deux ou quatre groupes, si *m* est inférieur à 1,8. Cependant, ne retenir que trois groupes ne permet d'expliquer que 30% de l'inertie. Afin de nous rapprocher des résultats de l'article original [@2021_4], nous retenons `m = 1,5` et `k = 4`.\n\n##### Application l'algorithme *c-means*\n\nAvec *k* et *m* définis, il ne reste plus qu'à appliquer l'algorithme à nos observations.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nset.seed(123)\ncmeans_resultats <- FKM(X, 4, 1.5)\n```\n:::\n\n\nL'objet obtenu `cmeans_resultats` contient les résultats de la classification. Plus spécifiquement, `cmeans_resultats$U` est la matrice d'appartenance, soit une matrice de taille *n* x *k*, dont chaque case $U_{ij}$ indique la probabilité pour l'observation *i* d'appartenir au groupe *j*. `cmeans_resultats$H` contient le centre des groupes, et `cmeans_resultats$Clus`, le groupe auquel chaque observation à le plus de chances d'appartenir. Pour comparer plus facilement nos résultats avec ceux du *k-means*, nous pouvons changer l'ordre des groupes obtenus pour les faire coïncider avec les groupes les plus similaires obtenus avec la méthode *k-means*.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# changeons l'ordre des groupes\nU <- cmeans_resultats$U\nU2 <- geocmeans::groups_matching(as.matrix(matrice_gp_kmeans), as.matrix(U))\n\n# mais aussi du centre des classes\nidx <- as.integer(gsub(\"Clus \" , \"\", colnames(U2), fixed = TRUE))\nH2 <- cmeans_resultats$H[idx,]\n\n# et recalcul du groupe le plus probable\nClus2 <- data.frame(\n \"Cluster\" = (1:4)[max.col(U2, ties.method=\"first\")],\n \"Membership degree\" = apply(U2, MARGIN = 1, max)\n)\n\ncolnames(U2) <- paste(\"Clus\",1:4, sep = \" \")\nrownames(H2) <- paste(\"Clus\",1:4, sep = \" \")\n\ncmeans_resultats$U <- U2\ncmeans_resultats$H <- H2\ncmeans_resultats$Clus <- Clus2\n```\n:::\n\n\n##### Interprétation des résultats\n\nGlobalement, les approches pour interpréter les résultats issus d'une classification obtenue par *c-means* sont les mêmes que pour une classification obtenue par *k-means*.\n\nCommençons donc par créer plusieurs cartes des probabilités d'appartenir aux différents groupes.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\nmaps <- mapClusters(LyonIris, cmeans_resultats$U)\n\ntmap_arrange(maps$ProbaMaps, ncol = 2, nrow = 2)\n```\n\n::: {.cell-output-display}\n![Cartographie des probabilités d'appartenir aux quatre groupes identifiés par l'algorithme c-means](13-MethodeClassification_files/figure-html/fig-cmeansD-1.png){#fig-cmeansD fig-align='center' width=100%}\n:::\n:::\n\n\nSur les cartes de la @fig-cmeansD, l'intensité de bleu correspond à la probabilité pour chaque IRIS d'appartenir aux différents groupes. Nous retrouvons les principales structures spatiales que nous avons identifiées avec le *k-means*; cependant, nous pouvons à présent constater que le groupe 1 est bien plus incertain que les autres. Nous pouvons une fois encore générer un graphique en radar pour comparer les profils des quatre groupes.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\npar(mfrow=c(3,2), mai = c(0.1,0.1,0.1,0.1))\nspiderPlots(X, cmeans_resultats$U,\n chartcolors = c(\"#EFBE89\", \"#4A6A9F\", \"#7DB47C\", \"#FAF29C\"))\n```\n\n::: {.cell-output-display}\n![Graphique en radar pour les résultats du c-means](13-MethodeClassification_files/figure-html/fig-cmeansE-1.png){#fig-cmeansE fig-align='center' width=100%}\n:::\n:::\n\n\nSans surprise, nous retrouvons essentiellement les profils que nous avons obtenus avec le *k-means* dans la @fig-cmeansE. Pour compléter la lecture des résultats, il est nécessaire de se pencher sur le tableau des statistiques descriptives des différents groupes. Une fois encore, nous proposons d'utiliser la fonction `summarizeClusters` du *package* `geocmeans`. Notez que cette fonction calcule les statistiques descriptives pondérées en fonction de l'appartenance des observations aux groupes. Ainsi, une observation ayant une faible chance d'appartenir à un groupe ne contribue que faiblement aux statistiques descriptives de ce groupe.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndf <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\" , \"Pct0_14\",\n \"Pct_65\" , \"Pct_Img\", \"TxChom1564\",\n \"Pct_brevet\" , \"NivVieMed\")])\n\ntableaux <- summarizeClusters(data = df, \n belongmatrix = cmeans_resultats$U,\n weighted = TRUE, dec = 1)\n\ntableau_tot <- do.call(rbind, tableaux)\n```\n:::\n\n::: {#tbl-cmeansG .cell tbl-cap='Description des groupes avec la méthode c-means'}\n::: {.cell-output-display}\n`````{=html}\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n
Lden NO2 PM25 VegHautPrt Pct014 Pct65 PctImg TxChom1564 Pctbrevet NivVieMed
groupe 1
Q5 48,7 15,8 13,5 6,2 12,2 9,5 4,3 6,7 10,7 16 191,5
Q10 50,5 18,7 13,9 7,4 14,2 11,4 5,7 7,6 13,7 17 616,0
Q25 52,4 20,9 14,7 11,4 16,8 14,2 7,8 9,3 18,4 19 559,0
Q50 54,7 25,0 15,6 15,8 19,0 17,7 11,2 12,1 24,0 21 947,5
Q75 57,6 28,6 16,8 22,3 21,3 21,1 15,6 15,1 29,8 24 069,2
Q90 60,7 33,0 18,5 29,8 23,2 24,4 20,3 18,5 34,7 26 164,0
Q95 63,1 37,8 19,0 34,3 25,4 27,5 23,5 22,3 39,0 28 931,0
Mean 55,1 25,4 15,8 17,5 18,9 17,9 12,4 13,0 24,7 21 951,6
Std 4,4 6,3 1,7 8,6 4,5 5,7 6,8 6,8 10,3 3 744,1
groupe 2
Q5 50,8 19,6 14,0 6,4 12,9 7,5 8,4 9,4 15,5 12 392,0
Q10 52,1 21,4 14,6 7,7 16,6 8,8 12,9 13,0 22,0 12 920,0
Q25 54,5 23,2 15,8 10,8 20,1 11,1 19,6 16,8 30,5 14 078,0
Q50 57,1 26,6 16,6 14,5 23,6 13,9 25,8 22,0 37,5 15 985,0
Q75 59,5 31,9 17,8 19,0 27,0 17,4 32,1 30,1 44,2 18 566,2
Q90 63,3 37,4 18,8 25,4 29,7 20,7 37,8 33,9 48,6 21 146,0
Q95 64,7 39,6 19,3 30,7 32,3 23,3 39,4 37,7 52,9 23 712,5
Mean 57,3 28,1 16,7 15,8 23,4 14,4 25,5 23,0 36,9 16 658,7
Std 4,4 6,6 1,6 7,6 6,3 5,1 9,7 9,3 12,3 3 611,9
groupe 3
Q5 50,6 27,5 16,3 6,2 8,6 6,8 6,0 7,6 7,5 16 976,0
Q10 51,9 28,8 17,1 7,7 10,4 8,4 7,0 8,6 8,7 18 434,0
Q25 53,8 30,9 18,3 10,2 12,6 10,8 9,1 11,1 11,0 19 785,0
Q50 56,5 35,0 18,9 13,4 15,2 14,1 12,3 13,1 14,8 22 289,0
Q75 59,4 38,7 19,6 17,6 17,9 17,5 15,9 15,5 21,5 24 522,0
Q90 62,7 41,1 20,0 24,8 20,5 20,5 18,9 18,4 27,6 27 600,0
Q95 64,3 44,3 20,2 30,6 21,8 23,5 21,0 20,6 32,2 29 732,8
Mean 56,8 34,9 18,7 14,8 15,3 14,2 12,8 13,7 16,9 22 595,1
Std 4,4 5,9 1,3 7,2 4,6 5,2 5,8 5,5 9,1 3 969,2
groupe 4
Q5 44,2 14,7 12,4 11,3 12,5 11,1 4,0 6,7 9,3 18 686,5
Q10 45,7 15,6 12,9 16,4 14,1 13,0 4,5 7,2 11,2 20 220,0
Q25 49,3 18,7 13,7 24,7 16,5 15,8 5,8 7,9 14,2 22 622,0
Q50 52,3 22,0 14,6 30,4 18,6 19,0 7,5 9,7 17,9 24 843,0
Q75 55,1 26,3 15,9 37,9 20,8 22,3 10,1 12,1 22,8 28 590,0
Q90 58,9 30,9 17,1 42,3 22,4 27,2 14,4 15,3 30,1 31 294,0
Q95 60,8 34,5 18,3 45,7 23,2 28,9 19,3 18,6 33,2 34 574,0
Mean 52,3 22,8 14,9 30,3 18,4 19,4 8,8 10,9 19,5 25 547,4
Std 5,1 6,3 1,7 10,0 4,1 5,9 5,5 6,2 9,2 4 603,5
\n\n`````\n:::\n:::\n\n\n#### Mise en œuvre du *c-medoids* dans R {#sec-13462}\n\nLa méthode du *c-medoids* dans R peut être mise en œuvre avec la fonction `FKM.med` du *package* `fclust`. Le processus d'analyse et de validation est identique à celui présenté ci-dessus pour le *c-means*. Nous ne donnons donc pas un exemple complet de la méthode.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Stabilité des groupes obtenus par les méthodes de nuées dynamiques**\n:::\n::: bloc_aller_loin-body\nPuisque la méthode *k-means* et ses variantes reposent sur une initialisation aléatoire de leur algorithme, les résultats peuvent varier en fonction de cet état de départ. Dans certains contextes, il est possible que les résultats obtenus varient significativement, ce qui signifie que les groupes obtenus ne sont pas représentatifs de la population étudiée. Une solution pour vérifier si ce problème se pose est simplement de relancer l'algorithme un grand nombre de fois (généralement 1000) et de comparer les résultats obtenus au cours de ces réplications.\n\nCette méthode est rarement implémentée directement et requiert d'écrire sa propre fonction. `geocmeans` dispose d'une fonction déjà existante, mais ne pouvant être appliquée qu'avec l'algorithme *c-means*. Nous proposons ici une implémentation pour la méthode *k-means* qui peut facilement être adaptée aux autres méthodes de classifications heuristiques.\n\nLa démarche à suivre est la suivante : \n\n1. Appliquer l'algorithme une première fois pour obtenir une classification de référence à laquelle nous comparerons toutes les réplications.\n\n2. Effectuer 1000 itérations au cours desquelles : \n + Une nouvelle classification est calculée.\n + Les groupes obtenus sont comparés à ceux de la classification de référence.\n + L'indice de Jacard est calculé entre les groupes des deux classifications.\n + Les valeurs de l'indice de Jacard sont enregistrées.\n + Les centres des groupes sont enregistrés.\n \nAinsi, nous obtenons 1000 valeurs de l'indice de Jacard pour chaque groupe. Cet indice permet de mesurer le degré d'accord entre deux variables (ici les probabilités d'appartenance des observations au même groupe pour deux classifications différentes.) Une valeur moyenne en dessous de 0,5 indique qu'un groupe est très instable, car nous obtenons des résultats très différents lors des réplications. Une valeur entre 0,6 et 0,75 indique qu'un groupe semble bien exister dans les données, bien que marqué par une certaine incertitude. Une valeur au-dessus de 0,8 indique un groupe bien identifié et stable.\n\nNous obtenons également les centres des groupes des 1000 classifications. Il est ainsi possible de représenter leurs histogrammes et de déterminer si les centres des groupes sont stables (unimodalité et faible variance) ou incertains (plusieurs modes et/ou forte variance).\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\n# X sera le jeu de données pour la classification\n# clust_ref sera le vecteur indiquant le groupe de chaque observation obtenu par kmeans\n# nsim sera le nombre de simulations à effectuer\nkmeans_stability <- function(X, clust_ref, nsim, verbose = TRUE){\n \n # définition de la matrice d'appartenance originale\n k <- length(unique(clust_ref))\n ref_mat <- dummy_cols(clust_ref, remove_selected_columns = TRUE)\n colnames(ref_mat) <- paste0(\"groupe_\",1:k)\n \n # lancement des itérations\n sim_resultats <- lapply(1:nsim, function(i){\n \n # afficher la progression si requis\n if(verbose){\n print(paste0(\"iteration numeros : \", i, \"/\", nsim))\n }\n # calculer le kmeans\n km_res <- kmeans(X, k)\n sim_mat <- dummy_cols(km_res$cluster, remove_selected_columns = TRUE)\n \n # ajustement de l'ordre des groupes avec geocmeans\n sim_mat <- groups_matching(as.matrix(ref_mat), as.matrix(sim_mat))\n \n # calcul des indices de jacard\n jac_idx <- sapply(1:k, function(j){\n calc_jaccard_idx(sim_mat[,j], ref_mat[,j])\n })\n \n # récuperation des centres des groupes\n idx <- as.integer(gsub(\".data_\" , \"\", colnames(sim_mat), fixed = TRUE))\n centers <- data.frame(km_res$centers)\n centers <- centers[idx,]\n centers$groupe <- 1:k\n \n return(list(\n \"jac_idx\" = jac_idx,\n \"centers\" = centers\n ))\n \n })\n \n # les simulations sont finies, nous pouvons combiner les résultats\n all_jac_values <- do.call(rbind, lapply(sim_resultats, function(x){x$jac_idx}))\n all_centers <- do.call(rbind, lapply(sim_resultats, function(x){x$centers}))\n return(list(\n \"jacard_values\" = all_jac_values,\n \"centers\" = all_centers\n ))\n}\n```\n:::\n\n\nIl ne nous reste plus qu'à utiliser notre nouvelle fonction pour déterminer si les groupes obtenus avec notre *k-means* sont stables.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ndata(LyonIris)\nset.seed(123)\n\n# NB : LyonIris est un objet spatial, il faut donc extraire uniquement son DataFrame\nX <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\" , \"Pct0_14\" , \"Pct_65\" , \"Pct_Img\",\n \"TxChom1564\" , \"Pct_brevet\" , \"NivVieMed\")])\n\n# Centrage et réduction de chaque colonne du DataFrame\nfor (col in names(X)){\n X[[col]] <- scale(X[[col]], center = TRUE, scale = TRUE)\n}\n\n# calcul du kmeans de référence\nkmeans_ref <- kmeans(X, 4)\n\n# application de la fonction de stabilité\nstab_results <- kmeans_stability(X, kmeans_ref$cluster, nsim = 1000, verbose = FALSE)\n```\n:::\n\n\nNous pouvons à présent vérifier la stabilité de nos quatre groupes.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\njacard_values <- data.frame(stab_results$jacard_values)\nnames(jacard_values) <- paste(\"groupe\", 1:4, sep = \"_\")\n\ndf <- reshape2::melt(jacard_values)\ndf$groupes <- as.factor(df$variable)\n\nggplot(df) + \n geom_histogram(aes(x = value), bins = 30) + \n facet_wrap(vars(groupes), ncol = 2) + \n labs(x = \"\", y = \"Indice de Jacard\")\n```\n\n::: {.cell-output-display}\n![Indices de Jacard obtenus sur 1000 réplications du k-means](13-MethodeClassification_files/figure-html/fig-kmeansStab3-1.png){#fig-kmeansStab3 fig-align='center' width=90%}\n:::\n:::\n\n\nLa @fig-kmeansStab3 indique clairement que les groupes 1 et 2 sont très stables, car les valeurs de Jacard obtenues sont le plus souvent supérieures à 0,75. Le groupe 3 a le plus souvent des valeurs légèrement inférieures aux deux premiers groupes, mais tout de même bien supérieures à 0,5. En revanche, le groupe 4 a un grand nombre de valeurs inférieures à 0,5 indiquant une tendance du groupe à se dissoudre lors des réplications.\n\nConsidérant que le dernier groupe est le plus instable, nous décidons d'observer les valeurs des centres qu'il obtient pour les différentes réplications.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ncenters_groupe4 <- subset(stab_results$centers, stab_results$centers$groupe == 4)\ncenters_groupe4$groupe <- NULL\n\ndf <- reshape2::melt(centers_groupe4)\ndf$variable <- as.factor(df$variable)\n\nggplot(df) + \n geom_histogram(aes(x = value), bins = 30) + \n facet_wrap(vars(variable), ncol = 3, scales = \"free\") + \n labs(x = \"\", y = \"\")\n```\n\n::: {.cell-output-display}\n![Distributions des valeurs des centres du groupe 4 sur 1000 itérations](13-MethodeClassification_files/figure-html/fig-kmeansStab4-1.png){#fig-kmeansStab4 fig-align='center' width=90%}\n:::\n:::\n\n\nLes différents histogrammes de la @fig-kmeansStab4 indiquent clairement que pour plusieurs variables (`Lden`, `NO2`, `PM25`, `Pct_Img`, et `NivVieMed`) les caractéristiques du groupe 4 varient grandement sur l'ensemble des réplications. Nous pouvons comparer ce graphique à celui du groupe 2 qui est bien plus stable.\n\n\n::: {.cell layout-align=\"center\"}\n\n```{.r .cell-code}\ncenters_groupe2 <- subset(stab_results$centers, stab_results$centers$groupe == 2)\ncenters_groupe2$groupe <- NULL\n\ndf <- reshape2::melt(centers_groupe2)\ndf$variable <- as.factor(df$variable)\n\nggplot(df) + \n geom_histogram(aes(x = value), bins = 30) + \n facet_wrap(vars(variable), ncol = 3, scales = \"free\") + \n labs(x = \"\", y = \"\")\n```\n\n::: {.cell-output-display}\n![Distributions des valeurs des centres du groupe 2 sur 1000 itérations](13-MethodeClassification_files/figure-html/fig-kmeansStab5-1.png){#fig-kmeansStab5 fig-align='center' width=90%}\n:::\n:::\n\n\nNous pouvons constater une plus faible variance des résultats obtenus (en regardant notamment l'axe horizontal) pour les centres des groupes à la @fig-kmeansStab5.\n:::\n:::\n\n\n## Conclusion sur la cinquième partie {#sec-135}\n\nDans le cadre de cette cinquième partie du livre, nous avons abordé les principales méthodes factorielles et les principales méthodes de classification non supervisée. Les premières sont des méthodes de réduction de données puisqu'elles permettent de résumer l'information d'un tableau en quelques nouvelles variables synthétiques. Les secondes permettent de regrouper les observations d'un tableau en plusieurs groupes homogènes. Il existe donc une complémentarité évidente entre ces deux groupes de méthodes : si le tableau initial comprend un grand nombre de variables, il est possible de lui appliquer une méthode factorielle produisant de nouvelles variables synthétiques qui sont ensuite utilisées pour calculer une méthode de classification non supervisée.\n\n![Complémentarité entre les méthodes factorielles et les méthodes de classification non supervisée](images/Chap13/AnalysesFactoClassif.png){#fig-MFMCComplementarite width=\"45%\" fig-align=\"center\"}\n\n## Quiz de révision du chapitre {#sec-136}\n\n\n
\n\n\n\n
\n
Les méthodes de classification non supervisée sont appelées ainsi puisque :
\n
Relisez au besoin la [section @sec-131].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
En quoi se distinguent les méthodes de classifications strictes et floues?
\n
Relisez au besoin la [section @sec-131].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Quels paramètres doivent être définis pour exécuter l'algorithme c-means?
\n
Relisez au besoin la [section @sec-1344].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
La classification ascendante hiérarchique nécessite de calculer :
\n
Relisez au besoin la [section @sec-133].
\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n\n\n\n
\n
\n
\n
\n
Pour effectuer une classification non supervisée floue utilisant comme centres de groupes de réelles observations plutôt que des moyennes fictives, quelle méthode peut-on utiliser?
\n
Relisez au besoin la [section @sec-1344].
\n
\n\n
\n
\n\n
\n\n
\n
\n", + "supporting": [ + "13-MethodeClassification_files" + ], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": { + "include-in-header": [ + "\r\n\r\n" + ] + }, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/docs/13-MethodeClassification_files/figure-html/fig-cmeansB-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-cmeansB-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-cmeansB-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-cmeansB-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-cmeansD-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-cmeansD-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-cmeansD-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-cmeansD-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-cmeansE-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-cmeansE-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-cmeansE-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-cmeansE-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-dist0-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-dist0-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-dist0-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-dist0-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-dist1-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-dist1-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-dist1-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-dist1-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-dist2-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-dist2-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-dist2-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-dist2-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-dist3-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-dist3-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-dist3-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-dist3-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-dist6-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-dist6-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-dist6-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-dist6-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-dist7-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-dist7-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-dist7-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-dist7-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-exampleHclust4-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-exampleHclust4-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-exampleHclust4-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-exampleHclust4-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-exampleHclust8-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-exampleHclust8-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-exampleHclust8-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-exampleHclust8-1.png diff --git a/.quarto/_freeze/13-MethodeClassification/figure-html/fig-impactTransform-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-impactTransform-1.png new file mode 100644 index 0000000..ac9560a Binary files /dev/null and b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-impactTransform-1.png differ diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeans2-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeans2-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeans2-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeans2-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeans3-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeans3-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeans3-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeans3-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeans4-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeans4-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeans4-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeans4-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeansC-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansC-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeansC-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansC-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeansD-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansD-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeansD-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansD-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeansE-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansE-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeansE-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansE-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeansG-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansG-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeansG-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansG-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeansH-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansH-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeansH-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansH-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeansI-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansI-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeansI-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansI-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeansM-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansM-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeansM-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansM-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeansStab3-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansStab3-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeansStab3-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansStab3-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeansStab4-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansStab4-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeansStab4-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansStab4-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-kmeansStab5-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansStab5-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-kmeansStab5-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-kmeansStab5-1.png diff --git a/docs/13-MethodeClassification_files/figure-html/fig-tablvsmat-1.png b/.quarto/_freeze/13-MethodeClassification/figure-html/fig-tablvsmat-1.png similarity index 100% rename from docs/13-MethodeClassification_files/figure-html/fig-tablvsmat-1.png rename to .quarto/_freeze/13-MethodeClassification/figure-html/fig-tablvsmat-1.png diff --git a/.quarto/_freeze/14-Annexes/execute-results/html.json b/.quarto/_freeze/14-Annexes/execute-results/html.json new file mode 100644 index 0000000..ee381c0 --- /dev/null +++ b/.quarto/_freeze/14-Annexes/execute-results/html.json @@ -0,0 +1,14 @@ +{ + "hash": "ee40a4c089e022b5f1de8222db5447e0", + "result": { + "markdown": "# Annexes {#sec-chap14}\n\n## Table des valeurs critiques de khi-deux {#sec-141}\n\nLa courte syntaxe R ci-dessous permet de générer le @tbl-tableCritiqueKhi2 avec les valeurs critiques du khi-deux pour différents degrés de signification (valeurs de *p*).\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(stargazer)\n\n# vecteur pour les degrés de liberté de 1 à 30, puis 40 et 50\ndl <- c(1:30, 40, 50, 100, 250, 500) \n# la fonction qchisq permet d'obtenir la valeur théorique en fonction \n# d'une valeur de p et d'un nombre de degrés de liberté\ntableKhi2 <- cbind(dl,\n p0.10 = round(qchisq(p = 0.90, df = dl, lower.tail = TRUE), 3),\n p0.05 = round(qchisq(p = 0.95, df = dl, lower.tail = TRUE), 3),\n p0.01 = round(qchisq(p = 0.99, df = dl, lower.tail = TRUE), 3),\n p0.001 =round(qchisq(p = 0.999, df = dl, lower.tail = TRUE), 3))\n# Impression du tableau avec la library stargazer\nstargazer(tableKhi2, type = \"text\", summary = FALSE, rownames = FALSE, align = TRUE, digits = 2,\n title = \"Distribution des valeurs critiques du Khi2\")\n```\n:::\n\n::: {#tbl-tableCritiqueKhi2 .cell tbl-cap='Distribution des valeurs critiques du khi-deux'}\n::: {.cell-output-display}\n| dl| p = 0,10| p = 0,05| p = 0,01| p = 0,001|\n|---:|--------:|--------:|--------:|---------:|\n| 1| 2,71| 3,84| 6,64| 10,83|\n| 2| 4,61| 5,99| 9,21| 13,82|\n| 3| 6,25| 7,82| 11,35| 16,27|\n| 4| 7,78| 9,49| 13,28| 18,47|\n| 5| 9,24| 11,07| 15,09| 20,52|\n| 6| 10,64| 12,59| 16,81| 22,46|\n| 7| 12,02| 14,07| 18,48| 24,32|\n| 8| 13,36| 15,51| 20,09| 26,12|\n| 9| 14,68| 16,92| 21,67| 27,88|\n| 10| 15,99| 18,31| 23,21| 29,59|\n| 11| 17,27| 19,68| 24,73| 31,26|\n| 12| 18,55| 21,03| 26,22| 32,91|\n| 13| 19,81| 22,36| 27,69| 34,53|\n| 14| 21,06| 23,68| 29,14| 36,12|\n| 15| 22,31| 25,00| 30,58| 37,70|\n| 16| 23,54| 26,30| 32,00| 39,25|\n| 17| 24,77| 27,59| 33,41| 40,79|\n| 18| 25,99| 28,87| 34,80| 42,31|\n| 19| 27,20| 30,14| 36,19| 43,82|\n| 20| 28,41| 31,41| 37,57| 45,31|\n| 21| 29,61| 32,67| 38,93| 46,80|\n| 22| 30,81| 33,92| 40,29| 48,27|\n| 23| 32,01| 35,17| 41,64| 49,73|\n| 24| 33,20| 36,42| 42,98| 51,18|\n| 25| 34,38| 37,65| 44,31| 52,62|\n| 26| 35,56| 38,88| 45,64| 54,05|\n| 27| 36,74| 40,11| 46,96| 55,48|\n| 28| 37,92| 41,34| 48,28| 56,89|\n| 29| 39,09| 42,56| 49,59| 58,30|\n| 30| 40,26| 43,77| 50,89| 59,70|\n| 40| 51,80| 55,76| 63,69| 73,40|\n| 50| 63,17| 67,50| 76,15| 86,66|\n| 100| 118,50| 124,34| 135,81| 149,45|\n| 250| 279,05| 287,88| 304,94| 324,83|\n| 500| 540,93| 553,13| 576,49| 603,45|\n:::\n:::\n\n\n\n## Table des valeurs critiques de Fisher {#sec-142}\n\nLa courte syntaxe R ci-dessous permet de générer les tableaux [-@tbl-CritiqueF1], [-@tbl-CritiqueF2] et [-@tbl-CritiqueF3] avec les valeurs critiques de *F* avec *p* = 0,05.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(stargazer)\n\ndl1 <- c(1:10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400, 500, 1000)\ndl2 <- c(1:10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 500, 1000, 2000)\nmatrice <- matrix(ncol = length(dl1), nrow = length(dl2), byrow = TRUE)\nfor(r in 1:length(dl1)){\n for(c in 1:length(dl2)){\n matrice[c,r] <- round(qf(p = 0.05, dl1[r], dl2[c], lower.tail = FALSE), 2)\n }\n}\n\ntableF_p0.05 <- data.frame(dl2 = dl2, matrice)\nnames(tableF_p0.05) <- c(\"dl2\", paste0(\"dl1=\",dl1))\n\nstargazer(tableF_p0.05, type = \"text\", summary = FALSE, rownames = FALSE, align = TRUE, digits = 3,\n title = \"Distribution des valeurs critiques de F avec p = 0,05\")\n```\n:::\n\n::: {#tbl-CritiqueF1 .cell tbl-cap='Distribution des valeurs critiques de F avec p = 0,05'}\n::: {.cell-output-display}\n| dl2| dl1=1| dl1=2| dl1=3| dl1=4| dl1=5| dl1=6| dl1=7| dl1=8| dl1=9| dl1=10|\n|-----:|------:|------:|------:|------:|------:|------:|------:|------:|------:|------:|\n| 1| 161,45| 199,50| 215,71| 224,58| 230,16| 233,99| 236,77| 238,88| 240,54| 241,88|\n| 2| 18,51| 19,00| 19,16| 19,25| 19,30| 19,33| 19,35| 19,37| 19,38| 19,40|\n| 3| 10,13| 9,55| 9,28| 9,12| 9,01| 8,94| 8,89| 8,85| 8,81| 8,79|\n| 4| 7,71| 6,94| 6,59| 6,39| 6,26| 6,16| 6,09| 6,04| 6,00| 5,96|\n| 5| 6,61| 5,79| 5,41| 5,19| 5,05| 4,95| 4,88| 4,82| 4,77| 4,74|\n| 6| 5,99| 5,14| 4,76| 4,53| 4,39| 4,28| 4,21| 4,15| 4,10| 4,06|\n| 7| 5,59| 4,74| 4,35| 4,12| 3,97| 3,87| 3,79| 3,73| 3,68| 3,64|\n| 8| 5,32| 4,46| 4,07| 3,84| 3,69| 3,58| 3,50| 3,44| 3,39| 3,35|\n| 9| 5,12| 4,26| 3,86| 3,63| 3,48| 3,37| 3,29| 3,23| 3,18| 3,14|\n| 10| 4,96| 4,10| 3,71| 3,48| 3,33| 3,22| 3,14| 3,07| 3,02| 2,98|\n| 20| 4,35| 3,49| 3,10| 2,87| 2,71| 2,60| 2,51| 2,45| 2,39| 2,35|\n| 30| 4,17| 3,32| 2,92| 2,69| 2,53| 2,42| 2,33| 2,27| 2,21| 2,16|\n| 40| 4,08| 3,23| 2,84| 2,61| 2,45| 2,34| 2,25| 2,18| 2,12| 2,08|\n| 50| 4,03| 3,18| 2,79| 2,56| 2,40| 2,29| 2,20| 2,13| 2,07| 2,03|\n| 60| 4,00| 3,15| 2,76| 2,53| 2,37| 2,25| 2,17| 2,10| 2,04| 1,99|\n| 70| 3,98| 3,13| 2,74| 2,50| 2,35| 2,23| 2,14| 2,07| 2,02| 1,97|\n| 80| 3,96| 3,11| 2,72| 2,49| 2,33| 2,21| 2,13| 2,06| 2,00| 1,95|\n| 90| 3,95| 3,10| 2,71| 2,47| 2,32| 2,20| 2,11| 2,04| 1,99| 1,94|\n| 100| 3,94| 3,09| 2,70| 2,46| 2,31| 2,19| 2,10| 2,03| 1,97| 1,93|\n| 200| 3,89| 3,04| 2,65| 2,42| 2,26| 2,14| 2,06| 1,98| 1,93| 1,88|\n| 300| 3,87| 3,03| 2,63| 2,40| 2,24| 2,13| 2,04| 1,97| 1,91| 1,86|\n| 500| 3,86| 3,01| 2,62| 2,39| 2,23| 2,12| 2,03| 1,96| 1,90| 1,85|\n| 1 000| 3,85| 3,00| 2,61| 2,38| 2,22| 2,11| 2,02| 1,95| 1,89| 1,84|\n| 2 000| 3,85| 3,00| 2,61| 2,38| 2,22| 2,10| 2,01| 1,94| 1,88| 1,84|\n:::\n:::\n\n::: {#tbl-CritiqueF2 .cell tbl-cap='Distribution des valeurs critiques de F avec p = 0,05 (suite)'}\n::: {.cell-output-display}\n| dl2| dl1=15| dl1=20| dl1=30| dl1=40| dl1=50| dl1=60| dl1=70| dl1=80| dl1=90|\n|-----:|------:|------:|------:|------:|------:|------:|------:|------:|------:|\n| 1| 245,95| 248,01| 250,10| 251,14| 251,77| 252,20| 252,50| 252,72| 252,90|\n| 2| 19,43| 19,45| 19,46| 19,47| 19,48| 19,48| 19,48| 19,48| 19,48|\n| 3| 8,70| 8,66| 8,62| 8,59| 8,58| 8,57| 8,57| 8,56| 8,56|\n| 4| 5,86| 5,80| 5,75| 5,72| 5,70| 5,69| 5,68| 5,67| 5,67|\n| 5| 4,62| 4,56| 4,50| 4,46| 4,44| 4,43| 4,42| 4,41| 4,41|\n| 6| 3,94| 3,87| 3,81| 3,77| 3,75| 3,74| 3,73| 3,72| 3,72|\n| 7| 3,51| 3,44| 3,38| 3,34| 3,32| 3,30| 3,29| 3,29| 3,28|\n| 8| 3,22| 3,15| 3,08| 3,04| 3,02| 3,01| 2,99| 2,99| 2,98|\n| 9| 3,01| 2,94| 2,86| 2,83| 2,80| 2,79| 2,78| 2,77| 2,76|\n| 10| 2,85| 2,77| 2,70| 2,66| 2,64| 2,62| 2,61| 2,60| 2,59|\n| 20| 2,20| 2,12| 2,04| 1,99| 1,97| 1,95| 1,93| 1,92| 1,91|\n| 30| 2,01| 1,93| 1,84| 1,79| 1,76| 1,74| 1,72| 1,71| 1,70|\n| 40| 1,92| 1,84| 1,74| 1,69| 1,66| 1,64| 1,62| 1,61| 1,60|\n| 50| 1,87| 1,78| 1,69| 1,63| 1,60| 1,58| 1,56| 1,54| 1,53|\n| 60| 1,84| 1,75| 1,65| 1,59| 1,56| 1,53| 1,52| 1,50| 1,49|\n| 70| 1,81| 1,72| 1,62| 1,57| 1,53| 1,50| 1,49| 1,47| 1,46|\n| 80| 1,79| 1,70| 1,60| 1,54| 1,51| 1,48| 1,46| 1,45| 1,44|\n| 90| 1,78| 1,69| 1,59| 1,53| 1,49| 1,46| 1,44| 1,43| 1,42|\n| 100| 1,77| 1,68| 1,57| 1,52| 1,48| 1,45| 1,43| 1,41| 1,40|\n| 200| 1,72| 1,62| 1,52| 1,46| 1,41| 1,39| 1,36| 1,35| 1,33|\n| 300| 1,70| 1,61| 1,50| 1,43| 1,39| 1,36| 1,34| 1,32| 1,31|\n| 500| 1,69| 1,59| 1,48| 1,42| 1,38| 1,35| 1,32| 1,30| 1,29|\n| 1 000| 1,68| 1,58| 1,47| 1,41| 1,36| 1,33| 1,31| 1,29| 1,27|\n| 2 000| 1,67| 1,58| 1,46| 1,40| 1,36| 1,32| 1,30| 1,28| 1,27|\n:::\n:::\n\n::: {#tbl-CritiqueF3 .cell tbl-cap='Distribution des valeurs critiques de F avec p = 0,05 (suite)'}\n::: {.cell-output-display}\n| dl2| dl1=100| dl1=200| dl1=300| dl1=400| dl1=500| dl1=1000|\n|-----:|-------:|-------:|-------:|-------:|-------:|--------:|\n| 1| 253,04| 253,68| 253,89| 254,00| 254,06| 254,19|\n| 2| 19,49| 19,49| 19,49| 19,49| 19,49| 19,49|\n| 3| 8,55| 8,54| 8,54| 8,53| 8,53| 8,53|\n| 4| 5,66| 5,65| 5,64| 5,64| 5,64| 5,63|\n| 5| 4,41| 4,39| 4,38| 4,38| 4,37| 4,37|\n| 6| 3,71| 3,69| 3,68| 3,68| 3,68| 3,67|\n| 7| 3,27| 3,25| 3,24| 3,24| 3,24| 3,23|\n| 8| 2,97| 2,95| 2,94| 2,94| 2,94| 2,93|\n| 9| 2,76| 2,73| 2,72| 2,72| 2,72| 2,71|\n| 10| 2,59| 2,56| 2,55| 2,55| 2,55| 2,54|\n| 20| 1,91| 1,88| 1,86| 1,86| 1,86| 1,85|\n| 30| 1,70| 1,66| 1,65| 1,64| 1,64| 1,63|\n| 40| 1,59| 1,55| 1,54| 1,53| 1,53| 1,52|\n| 50| 1,52| 1,48| 1,47| 1,46| 1,46| 1,45|\n| 60| 1,48| 1,44| 1,42| 1,41| 1,41| 1,40|\n| 70| 1,45| 1,40| 1,39| 1,38| 1,37| 1,36|\n| 80| 1,43| 1,38| 1,36| 1,35| 1,35| 1,34|\n| 90| 1,41| 1,36| 1,34| 1,33| 1,33| 1,31|\n| 100| 1,39| 1,34| 1,32| 1,31| 1,31| 1,30|\n| 200| 1,32| 1,26| 1,24| 1,23| 1,22| 1,21|\n| 300| 1,30| 1,23| 1,21| 1,20| 1,19| 1,17|\n| 500| 1,28| 1,21| 1,18| 1,17| 1,16| 1,14|\n| 1 000| 1,26| 1,19| 1,16| 1,14| 1,13| 1,11|\n| 2 000| 1,25| 1,18| 1,15| 1,13| 1,12| 1,09|\n:::\n:::\n\n\n## Table des valeurs critiques de *t* {#sec-143}\n\nLa courte syntaxe R ci-dessous permet de générer le @tbl-tableCritiqueT avec les valeurs critiques de *t* avec *p* = 0,10, 0,05, 0,01 et 0,01.\n\n\n::: {.cell}\n\n```{.r .cell-code}\nlibrary(stargazer)\n\n# vecteur pour les degrés de liberté de 1 à 30, puis 40 et 50\ndl <- c(1:30, 40, 50, 60, 70, 80, 90, 100, 250, 500, 1000, 2500) \n# la fonction qchisq permet d'obtenir la valeur théorique en fonction \n# d'une valeur de p et d'un nombre de degrés de liberté\ntableT <- cbind(dl,\n p0.10 = round(qt(p = 1 - (0.10/2), df = dl),2),\n p0.05 = round(qt(p = 1 - (0.05/2), df = dl),2),\n p0.01 = round(qt(p = 1 - (0.01/2), df = dl),2),\n p0.001 = round(qt(p = 1 - (0.001/2), df = dl),2))\n# Impression du tableau avec la library stargazer\nstargazer(tableT, type = \"text\", summary = FALSE, rownames = FALSE, align = TRUE, digits = 2,\n title=\"Distribution des valeurs critiques de t\")\n```\n:::\n\n::: {#tbl-tableCritiqueT .cell tbl-cap='Distribution des valeurs critiques de t'}\n::: {.cell-output-display}\n| dl| p = 0,10| p = 0,05| p = 0,01| p = 0,001|\n|-----:|--------:|--------:|--------:|---------:|\n| 1| 6,31| 12,71| 63,66| 636,62|\n| 2| 2,92| 4,30| 9,92| 31,60|\n| 3| 2,35| 3,18| 5,84| 12,92|\n| 4| 2,13| 2,78| 4,60| 8,61|\n| 5| 2,02| 2,57| 4,03| 6,87|\n| 6| 1,94| 2,45| 3,71| 5,96|\n| 7| 1,89| 2,36| 3,50| 5,41|\n| 8| 1,86| 2,31| 3,36| 5,04|\n| 9| 1,83| 2,26| 3,25| 4,78|\n| 10| 1,81| 2,23| 3,17| 4,59|\n| 11| 1,80| 2,20| 3,11| 4,44|\n| 12| 1,78| 2,18| 3,05| 4,32|\n| 13| 1,77| 2,16| 3,01| 4,22|\n| 14| 1,76| 2,14| 2,98| 4,14|\n| 15| 1,75| 2,13| 2,95| 4,07|\n| 16| 1,75| 2,12| 2,92| 4,01|\n| 17| 1,74| 2,11| 2,90| 3,97|\n| 18| 1,73| 2,10| 2,88| 3,92|\n| 19| 1,73| 2,09| 2,86| 3,88|\n| 20| 1,72| 2,09| 2,85| 3,85|\n| 21| 1,72| 2,08| 2,83| 3,82|\n| 22| 1,72| 2,07| 2,82| 3,79|\n| 23| 1,71| 2,07| 2,81| 3,77|\n| 24| 1,71| 2,06| 2,80| 3,75|\n| 25| 1,71| 2,06| 2,79| 3,73|\n| 26| 1,71| 2,06| 2,78| 3,71|\n| 27| 1,70| 2,05| 2,77| 3,69|\n| 28| 1,70| 2,05| 2,76| 3,67|\n| 29| 1,70| 2,05| 2,76| 3,66|\n| 30| 1,70| 2,04| 2,75| 3,65|\n| 40| 1,68| 2,02| 2,70| 3,55|\n| 50| 1,68| 2,01| 2,68| 3,50|\n| 60| 1,67| 2,00| 2,66| 3,46|\n| 70| 1,67| 1,99| 2,65| 3,44|\n| 80| 1,66| 1,99| 2,64| 3,42|\n| 90| 1,66| 1,99| 2,63| 3,40|\n| 100| 1,66| 1,98| 2,63| 3,39|\n| 250| 1,65| 1,97| 2,60| 3,33|\n| 500| 1,65| 1,96| 2,59| 3,31|\n| 1 000| 1,65| 1,96| 2,58| 3,30|\n| 2 500| 1,65| 1,96| 2,58| 3,29|\n:::\n:::\n\n\n", + "supporting": [], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/.quarto/_freeze/index/execute-results/html.json b/.quarto/_freeze/index/execute-results/html.json new file mode 100644 index 0000000..7849ec0 --- /dev/null +++ b/.quarto/_freeze/index/execute-results/html.json @@ -0,0 +1,14 @@ +{ + "hash": "a19d4070542bd238c563a55dbf639f4f", + "result": { + "markdown": "```{=tex}\n\\renewcommand{\\partname}{} % Réinitialiser partie\n```\n\n\n**Résumé :** Ce livre vise à décrire une panoplie de méthodes quantitatives utilisées en sciences sociales avec le logiciel ouvert R. Il a d'ailleurs été écrit intégralement dans R avec Quarto. Le contenu est pensé pour être accessible à tous et toutes, même à ceux et celles n'ayant presque aucune base en statistique ou en programmation. Les personnes plus expérimentées y découvriront des sections sur des méthodes plus avancées comme les modèles à effets mixtes, les modèles multiniveaux, les modèles généralisés additifs ainsi que les méthodes factorielles et de classification. Ceux et celles souhaitant migrer progressivement d'un autre logiciel statistique vers R trouveront dans cet ouvrage les éléments pour une transition en douceur. La philosophie de ce livre est de donner toutes les clefs de compréhension et de mise en œuvre des méthodes abordées dans R. La présentation des méthodes est basée sur une approche compréhensive et intuitive plutôt que mathématique, sans pour autant que la rigueur statistique soit négligée.\n\n**Remerciements :** Ce manuel a été réalisé avec le soutien de la fabriqueREL. Fondée en 2019, la fabriqueREL est portée par divers établissements d'enseignement supérieur du Québec et agit en collaboration avec les services de soutien pédagogique et les bibliothèques. Son but est de faire des ressources éducatives libres (REL) le matériel privilégié en enseignement supérieur au Québec.\n\n**Maquette de la page couverture et identité graphique du livre :** Andrés Henao Florez.\n\n**Mise en page :** Philippe Apparicio et Marie-Hélène Gadbois Del Carpio.\n\n**Révision linguistique :** Denise Latreille.\n\n© Philippe Apparicio et Jérémy Gelb.\n\n\n**Pour citer cet ouvrage :** Apparicio P. et J. Gelb (2024). *Méthodes quantitatives en sciences sociales : un grand bol d’R*. Université de Sherbrooke, Département de géomatique appliquée. fabriqueREL. Licence CC BY-SA.

\n\n![](images/introduction/CouvertureP2.png){width=\"80%\" fig-align=\"left\"}\n\n\n# Préface {.unnumbered}\n\nCe livre vise à décrire une panoplie de méthodes quantitatives utilisées en sciences sociales avec le logiciel ouvert R. Il a d'ailleurs été écrit intégralement dans R avec [Quatro](https://quarto.org/). Le contenu est pensé pour être accessible à tous et toutes, même à ceux et celles n'ayant presque aucune base en statistique ou en programmation. Les personnes plus expérimentées y découvriront des sections sur des méthodes plus avancées comme les modèles à effets mixtes, les modèles multiniveaux, les modèles généralisés additifs ainsi que les méthodes factorielles et de classification. Ceux et celles souhaitant migrer progressivement d'un autre logiciel statistique vers R trouveront dans cet ouvrage les éléments pour une transition en douceur. La philosophie de ce livre est de donner toutes les clefs de compréhension et de mise en œuvre des méthodes abordées dans R. La présentation des méthodes est basée sur une approche compréhensive et intuitive plutôt que mathématique, sans pour autant que la rigueur statistique ne soit négligée. Servez-vous votre boisson chaude ou froide favorite et installez-vous dans votre meilleur fauteuil. Bonne lecture!\n\n## Un manuel sous la forme d'une ressource éducative libre {-#sect001}\n\n**Pourquoi un manuel sous licence libre?**\n\nLes logiciels libres sont aujourd'hui très répandus. Comparativement aux logiciels propriétaires, l'accès au code source permet à quiconque de l'utiliser, de le modifier, de le dupliquer et de le partager. Le logiciel R, dans lequel sont mises en œuvre les méthodes quantitatives décrites décrites dans ce livre, est d'ailleurs à la fois un langage de programmation et un logiciel libre (sous la licence publique générale [GNU GPL2](https://fr.wikipedia.org/wiki/Licence_publique_g%C3%A9n%C3%A9rale_GNU)). Par analogie aux logiciels libres, il existe aussi des **ressources éducatives libres (REL)** « dont la licence accorde les permissions désignées par les 5R (**Retenir --- Réutiliser --- Réviser --- Remixer --- Redistribuer**) et donc permet nécessairement la modification » ([***fabriqueREL***](https://fabriquerel.org/rel/)). La licence de ce livre, CC BY-SA (@fig-Licence), permet donc de :\n\n- **Retenir**, c'est-à-dire télécharger et imprimer gratuitement le livre. Notez qu'il aurait été plutôt surprenant d'écrire un livre payant sur un logiciel libre et donc gratuit. Aussi, nous aurions été très embarrassés que des personnes étudiantes avec des ressources financières limitées doivent payer pour avoir accès au livre, sans pour autant savoir préalablement si le contenu est réellement adapté à leurs besoins.\n\n- **Réutiliser**, c'est-à-dire utiliser la totalité ou une section du livre sans limitation et sans compensation financière. Cela permet ainsi à d'autres personnes enseignantes de l'utiliser dans le cadre d'activités pédagogiques.\n\n- **Réviser**, c'est-à-dire modifier, adapter et traduire le contenu en fonction d'un besoin pédagogique précis puisqu'aucun manuel n'est parfait, tant s'en faut! Le livre a d'ailleurs été écrit intégralement dans R avec [Quatro](https://quarto.org/). Quiconque peut ainsi télécharger gratuitement le code source du livre sur [github](https://github.com/SerieBoldR/MethodesQuantitatives) et le modifier à sa guise (voir l'encadré intitulé *Suggestions d'adaptation du manuel*).\n\n- **Remixer**, c'est-à-dire « combiner la ressource avec d'autres ressources dont la licence le permet aussi pour créer une nouvelle ressource intégrée » ([***fabriqueREL***](https://fabriquerel.org/rel/)).\n\n- **Redistribuer**, c'est-à-dire distribuer, en totalité ou en partie, le manuel ou une version révisée sur d'autres canaux que le site Web du livre (par exemple, sur le site Moodle de votre université ou en faire une version imprimée).\n\nLa licence de ce livre, CC BY-SA (@fig-Licence), oblige donc à :\n\n- Attribuer la paternité de l'auteur dans vos versions dérivées, ainsi qu'une mention concernant les grandes modifications apportées, en utilisant la formulation suivante : Apparicio Philippe et Jérémy Gelb (2024). *Méthodes quantitatives en sciences sociales : un grand bol d'R*. Université de Sherbrooke. fabriqueREL. Licence CC BY-SA.\n\n- Utiliser la même licence ou une licence similaire à toutes versions dérivées.\n\n![Licence Creative Commons du livre](images/introduction/Licence.JPG){#fig-Licence width=\"80%\" fig-align=\"center\"}\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n\n**Suggestions d'adaptation du manuel**\n:::\n\n::: bloc_astuce-body\nPour chaque méthode d'analyse spatiale abordée dans le livre, une description détaillée et une mise en œuvre dans R sont disponibles. Par conséquent, plusieurs adaptations du manuel sont possibles :\n\n- Conserver uniquement les chapitres sur les méthodes ciblées dans votre cours.\n\n- En faire une version imprimée et la distribuer aux personnes étudiantes.\n\n- Modifier la description d'une ou de plusieurs méthodes en effectuant les mises à jour directement dans les chapitres.\n\n- Insérer ses propres jeux de données dans les sections intitulées *Mise en œuvre dans R*.\n\n- Modifier les tableaux et figures.\n\n- Ajouter une série d'exercices.\n\n- Modifier les quiz de révision.\n\n- Rédiger un nouveau chapitre.\n\n- Modifier des syntaxes R. Plusieurs *packages* R peuvent être utilisés pour mettre en œuvre telle ou telle méthode. Ces derniers évoluent aussi très vite et de nouveaux *packages* sont proposés fréquemment. Par conséquent, il peut être judicieux de modifier une syntaxe R du livre en fonction de ses habitudes de programmation dans R (utilisation d'autres *packages* que ceux utilisés dans le manuel par exemple) ou de bien mettre à jour une syntaxe à la suite de la parution d'un nouveau *package* plus performant ou intéressant.\n\n- Toute autre adaptation qui permet de répondre au mieux à un besoin pédagogique.\n:::\n:::\n\n## Un manuel conçu comme un projet collaboratif {-#sect002}\n\nIl existe actuellement de nombreux livres sous licence ouverte écrits avec [rmarkdown](https://rmarkdown.rstudio.com/) ou [Quarto](https://quarto.org/), répertoriés sur les sites de [https://bookdown.org/](https://bookdown.org/) et de [https://quarto.org/docs/gallery/#books](https://quarto.org/docs/gallery/#books). Sans surprise, R étant un logiciel libre dédié aux méthodes statistiques et à la science des données, plusieurs abordent les méthodes quantitatives, notamment :\n\n- [Beyond Multiple Linear Regression: Applied Generalized Linear Models and Multilevel Models in R](https://bookdown.org/roback/bookdown-BeyondMLR/) [@roback2021beyond], CC BY-NC-SA.\n\n- [Introduction to Econometrics with R](https://www.econometrics-with-r.org/) [@hanck2019introduction], CC BY-NC-SA.\n\n- [Statistical Inference via Data Science: A ModernDive into R and the Tidyverse](https://moderndive.com/) [@ismay2019statistical], CC BY-NC-SA.\n\n- [R Graphics Cookbook, 2nd edition](https://r-graphics.org/) [@Chang2018], CC BY.\n\nPar contre, la grande majorité de ces livres numériques rédigés avec R sont en anglais. À notre connaissance, ce projet constitue le premier manuel numérique en français sur les méthodes quantitatives appliquées aux sciences sociales réalisé avec `Quatro`. La première version du livre étant lancée, il est grand temps de planifier les suivantes! Pour ce faire, nous considérons ce livre comme un **projet collaboratif visant à mobiliser la communauté universitaire francophone qui enseigne les statistiques en sciences sociales avec R**. Plusieurs raisons motivent cette vision collaborative :\n\n- **Rien n'est parfait!** Cette première version comprend sûrement des coquilles et certaines sections mériteraient d'être améliorées. Les commentaires et suggestions visant à améliorer son contenu sont les bienvenus.\n\n- **La table des matières doit être impérativement extensible!** De nombreuses méthodes statistiques très utilisées en sciences sociales ne sont pas abordées dans ce livre et mériteraient d'être ajoutées dans une version ultérieure : certaines extensions des régressions linéaires (régressions Rigge et Lasso, Tobit, quantile, etc.), les modèles d'équations simultanées, les analyses de données longitudinales (entre autres, modèles de survie, régression par panel), les modèles d'équations structurelles et bien d'autres! Par conséquent, si vous êtes intéressé(e)s, à ajouter un nouveau chapitre ou une partie du livre, nous vous invitons vivement à communiquer avec nous ou à diffuser sous une licence similaire votre version dérivée. L’objectif étant de continuer à faire tourner la roue du libre et, idéalement, que les futures versions soient corédigées par une communauté d’auteurs et d'autrices spécialistes en méthodes quantitatives.\n\n\n## Comment lire ce livre? {-#sect003}\n\nLe livre comprend plusieurs types de blocs de texte qui en facilitent la lecture.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n\n**Bloc *packages***\n:::\n\n::: bloc_package-body\nHabituellement localisé au début d'un chapitre, il comprend la liste des *packages* R utilisés pour un chapitre.\n:::\n:::\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Bloc objectif**\n:::\n::: bloc_objectif-body\nIl comprend une description des objectifs d'un chapitre ou d'une section.\n:::\n:::\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Bloc notes**\n:::\n::: bloc_notes-body\nIl comprend une information secondaire sur une notion, une idée abordée dans une section.\n:::\n:::\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Bloc pour aller plus loin**\n:::\n::: bloc_aller_loin-body\nIl comprend des références ou des extensions d'une méthode abordée dans une section.\n:::\n:::\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Bloc astuce**\n:::\n::: bloc_astuce-body\nIl décrit un élément qui vous facilitera la vie : une propriété statistique, un *package*, une fonction, une syntaxe R.\n:::\n:::\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Bloc attention**\n:::\n::: bloc_attention-body\nIl comprend une notion ou un élément important à bien maîtriser.\n:::\n:::\n\n::: bloc_exercice\n::: bloc_exercice-header\n::: bloc_exercice-icon\n:::\n\n**Bloc exercice**\n:::\n\n::: bloc_exercice-body\nIl comprend un court exercice de révision à la fin de chaque chapitre.\n:::\n:::\n\n## Comment utiliser les données du livre pour reproduire les exemples? {-#sect003B}\n\nCe livre comprend des exemples détaillés et appliqués dans R pour chacune des méthodes abordées. Ces exemples se basent sur des jeux de données structurés et mis à disposition avec le livre. Ils sont disponibles sur le *repo github* dans le sous-dossier `data`, à l'adresse . \n\nUne autre option est de télécharger le *repo* complet du livre directement sur *github* () en cliquant sur le bouton `Code`, puis le bouton `Download ZIP` (@fig-downloaffromgit). Les données se trouvent alors dans le sous-dossier nommé `data`.\n\n![Téléchargement de l'intégralité du livre](images/introduction/download_github.png){#fig-downloaffromgit width=\"40%\" fig-align=\"center\"}\n\n## Liste des *packages* utilisés {-#sect004}\n\nPour écrire ce livre, nous avons utilisé de nombreux *packages* que vous pouvez installer avec le code ci-dessous.\n\n\n::: {.cell}\n\n```{.r .cell-code}\n# Liste des packages\nListePackages <- c(\"actuar\", \"AER\", \"apaTables\", \"boot\", \"car\", \"caret\", \"chorddiag\", \"classInt\", \n \"cluster\", \"clusterCrit\", \"correlation\", \"corrplot\", \"DescTools\", \"DHARMa\", \n \"dplyr\", \"effectsize\", \"ellipse\", \"FactoMineR\", \"fastDummies\", \"fitdistrplus\", \n \"fmsb\", \"foreign\", \"gamlss\", \"gamlss.add\", \"gamlss.dist\", \"geocmeans\", \"gganimate\",\n \"ggeffects\", \"ggplot2\", \"ggpubr\", \"ggpubr\", \"ggpubr\", \"ggpubr\", \"ggspatial\",\n \"ggthemes\", \"gmodels\", \"grid\", \"gridExtra\", \"Hmisc\", \"itsadug\", \"kableExtra\", \n \"LaplacesDemon\", \"lme4\", \"lmtest\", \"lubridate\", \"MASS\", \"merTools\", \"metR\", \n \"mgcv\", \"moments\", \"MuMIn\", \"NbClust\", \"nortest\", \"pdftools\", \"performance\", \n \"ppcor\", \"proxy\", \"qqplotr\", \"QuantPsyc\", \"QuantPsyc\", \"QuantPsyc\",\n \"RColorBrewer\", \"reshape2\", \"ROCR\", \"rstatix\", \"sandwich\", \"sas7bdat\", \"segmented\",\n \"sf\", \"SimDesign\", \"sjstats\", \"snow\", \"splines2\", \"stargazer\", \"stats\", \"stringr\", \n \"textrank\", \"tmap\", \"tmap\", \"treemap\", \"udpipe\", \"vcd\", \"VGAM\", \"VGAM\", \"viridis\", \n \"Weighted.Desc.Stat\", \"wordcloud2\", \"xlsx\")\n# Packages non installés dans la liste\nPackagesNonInstalles <- ListePackages[!(ListePackages %in% installed.packages()[,\"Package\"])]\n# Installation des packages manquants\nif(length(new.packages)) install.packages(PackagesNonInstalles)\n```\n:::\n\n\n## Structure du livre {-#sect005}\n\nLe livre est organisé autour de cinq grandes parties.\n\n\n**Partie 1. La découverte de R.** Dans cette première partie, nous discutons brièvement de l’histoire et de la philosophie de R. Nous voyons ensuite comment installer R et RStudio. Les bases du langage R (particulièrement les principaux objets que sont le vecteur, la matrice, la liste et le *dataframe*) ainsi que la manipulation des données avec R sont aussi largement abordés dans le [chapitre @sec-chap01].\n\n**Partie 2. Analyses univariées et représentations graphiques**. Cette seconde partie comprend deux chapitres. Dans le [chapitre @sec-chap02], nous décrivons dans un premier temps les différents types de données (primaires *versus* secondaires, transversales *versus* longitudinales, spatiales *versus* aspatiales, individuelles *versus* agrégées), les différents types de variables quantitatives (discrètes et continues) et qualitatives (nominales et ordinales) et les principales distributions de variables utilisées en sciences sociales (uniforme, Bernoulli, binomiale, géométrique, binomiale négative, poisson, poisson avec excès de zéros, gaussienne, gaussienne asymétrique, log-normale, Student, Cauchy, Chi-carré, exponentielle, Gamma, bêta, Weibull et Pareto). Dans un second temps, nous abordons les statistiques descriptives pour des variables quantitatives (paramètres de tendance centrale, paramètres de position, paramètres de dispersion, paramètres de forme), puis qualitatives (fréquences absolues, relatives et cumulées).\n\nDans le [chapitre @sec-chap03], nous illustrons les incroyables capacités graphiques de R en mettant en œuvre les principaux graphiques (histogramme, graphique de densité, nuage de points, graphique en lignes, boîtes à moustache, graphique en violon, graphique en barre, graphique circulaire), quelques graphiques particuliers (graphique en radar, diagramme d'accord, nuage de mots, carte proportionnelle) et une initiation aux cartes choroplèthes.\n\n**Partie 3. Analyses bivariées.** Cette troisième partie comprend trois chapitres dans lesquelles sont présentées les principales méthodes exploratoires et confirmatoires bivariées permettant d'évaluer la relation entre deux variables. Plus spécifiquement, nous présentons puis mettons en œuvre dans R les méthodes permettant d'explorer les relations entre deux variables quantitatives (covariance, corrélation et régression linéaire simple) dans le [chapitre @sec-chap04], deux variables qualitatives (tableau de contingence et test du khi-deux) dans le [chapitre @sec-chap05] et une variable quantitative avec une variable qualitative avec deux modalités (tests de Student, de Welch et de Wilcoxon) ou avec plus de deux modalités (ANOVA et test de Kruskal-Wallis) dans le [chapitre @sec-chap06].\n\n\n**Partie 4. Modèles de régression**. Dans cette quatrième partie sont présentées les principales méthodes de statistique inférentielle utilisées en sciences sociales : la régression linéaire multiple ([chapitre @sec-chap07]), les régressions linéaires généralisées ([chapitre @sec-chap08]), les régressions à effets mixtes ([chapitre @sec-chap09]), les régressions multiniveaux ([chapitre @sec-chap10]), et les modèles généralisés additifs ([chapitre @sec-chap11]).\n\n**Partie 5. Analyses exploratoires multivariées**. Dans cette cinquième partie sont abordées les méthodes de statistique exploratoire et descriptive permettant de décrire des tableaux de données comprenant plusieurs variables. Nous décrivons d'abord les méthodes de réduction de données : les méthodes factorielles dans le [chapitre @sec-chap12] (analyses de composantes principales, analyses factorielles de correspondances, analyses factorielles de correspondances multiples) et les méthodes de classification non supervisées dans le [chapitre @sec-chap13] (classification ascendante hiérarchique, k-moyennes, k-médianes, k-médoïdes et leurs extensions en logique floue comme les c-moyennes et c-médianes).\n\n\n## Pourquoi faut-il programmer en sciences sociales? {-#sect006}\n\nVous contrasterez rapidement que R est un véritable langage de programmation. L'apprentissage de ce langage de programmation est-il pour autant pertinent pour les étudiants et étudiantes en sciences sociales? Il est vrai que la programmation n'est pas une compétence qui vient d'emblée à l'esprit lorsque l'on s'intéresse à la recherche aux sciences sociales. Pourtant, elle est de plus en plus importante, et ce, pour plusieurs raisons :\n\n* Une part toujours plus grande des phénomènes sociaux se produisent ou peuvent s'observer au travers d'environnements numériques. Être capable d'exploiter efficacement ces outils permet d'extraire des données riches sur des phénomènes complexes, tel qu’en témoignent des études récentes sur la propagation de la désinformation sur les réseaux sociaux [@allcott2017social], la migration des personnes [@spyratos2019quantifying], la propagation et les risques de contamination de la COVID-19 [@boulos2020geographical]. Le plus souvent, les interfaces (API par exemple) permettant d'accéder à ces données nécessitent des habiletés en programmation.\n\n* La quantité de données numériques ouvertes et accessibles en ligne croit chaque année sur des sujets très divers. La plupart des villes et des gouvernements ont maintenant leur portail de données ouvertes auxquelles s'ajoutent les données produites par des projets collaboratifs comme [OpenStreetMap](https://www.openstreetmap.org) ou [NoisePlanet](https://noise-planet.org/map_noisecapture/index.html). Récupérer ces données et les structurer pour les utiliser à des fins de recherche nécessitent le plus souvent des compétences en programmation.\n\n* Les méthodes quantitatives connaissent également un développement très important. Les logiciels propriétaires peinent à suivre la cadence de ce développement, contrairement aux logiciels à code source ouvert (comme R) qui permettent d'avoir accès aux dernières méthodes. Il est souvent long et coûteux de développer une interface graphique pour un logiciel, ce qui explique que la plupart de ces programmes en sont dépourvus et nécessitent alors de savoir programmer pour les utiliser.\n\n* Savoir programmer donne une liberté considérable en recherche. Cette compétence permet notamment de ne plus être limité(e) aux fonctionnalités proposées par des logiciels spécifiques. Il devient possible d'innover tant en matière de structuration, d'exploration et d'analyse des données que de représentation des résultats en écrivant ses propres fonctions. Cette flexibilité contribue directement à la production d'une recherche de meilleure qualité et plus diversifiée.\n\n* Programmer permet également d'automatiser des tâches qui autrement seraient extrêmement répétitives comme : déplacer et renommer une centaine de fichiers; retirer les lignes inutiles dans un ensemble de fichiers et les compiler dans une seule base de données; vérifier parmi des milliers d'adresses lesquelles sont valides; récupérer chaque jour les messages postés sur un forum. Autant de tâches faciles à automatiser si l'on sait programmer.\n\n* Dans un logiciel avec une interface graphique, il est compliqué de conserver un historique des opérations effectuées. Programmer permet au contraire de garder une trace de l'ensemble des actions effectuées au cours d'un projet de recherche. En effet, le code utilisé reste disponible et permet de reproduire (ou d'adapter) la méthode et les résultats obtenus, ce qui est essentiel dans le monde de la recherche. À cela s'ajoute le fait que chaque ligne de code que vous écrivez vient s'ajouter à un capital de code que vous possédez, car elles pourront être réutilisées dans d'autres projets!\n\n\n## Remerciements {-#sect007}\n\nDe nombreuses personnes ont contribué à l'élaboration de ce manuel. Ce projet a bénéficié du soutien pédagogique et financier de la [**_fabriqueREL_**](https://fabriquerel.org/) (ressources éducatives libres). Les différentes rencontres avec le comité de suivi nous ont permis de comprendre l'univers des ressources éducatives libres (REL) et notamment leurs [fameux 5R](https://fabriquerel.org/rel/) (Retenir — Réutiliser — Réviser — Remixer — Redistribuer), de mieux définir le besoin pédagogique visé par ce manuel, d'identifier des outils et des ressources pédagogiques pertinents pour son élaboration. Ainsi, nous remercions chaleureusement les membres de suivi de la *fabriqueREL* pour leur support inconditionnel : \n\n- Myriam Beaudet, bibliothécaire à l'Université de Sherbrooke.\n- Marianne Dubé, conseillère pédagogique à l'Université de Sherbrooke et coordonnatrice de la fabriqueREL.\n-\tMyrian Grondin, bibliothécaire à l'Institut national de la recherche scientifique (INRS).\n- Claude Potvin, conseiller en formation à l'Université Laval.\n- Serge Allary, vice-recteur adjoint aux études de l'Université de Sherbrooke.\n\nNous tenons aussi à remercier sincèrement les étudiants et étudiantes du cours **Méthodes quantitatives appliquées aux études urbaines (EUR8219)** du programme de maîtrise en études urbaines de l'INRS. Leurs commentaires et suggestions nous ont permis d'améliorer grandement les versions préliminaires de ce manuel qui ont été utilisées dans le cadre de ce cours.\n\nNous remercions les membres du comité de révision pour leurs commentaires et suggestions très constructifs. Ce comité est composé de trois étudiantes et deux professeurs de l’[INRS](https://inrs.ca/) :\n\n-\tVictoria Gay-Gauvin, étudiante à la maîtrise en études urbaines.\n- Salomé Vallette, étudiante au doctorat en études urbaines.\n- Diana Pena Ruiz, étudiante au doctorat en études des populations.\n- [Benoît Laplante](https://inrs.ca/la-recherche/professeurs/benoit-laplante/), professeur enseignant aux programmes de maîtrise et de doctorat en études des populations.\n- [Xavier Leloup](https://inrs.ca/la-recherche/professeurs/xavier-leloup/), professeur enseignant au programme de doctorat en études urbaines.\n\nFinalement, nous remercions Denise Latreille, réviseure linguistique et chargée de cours à l'Université Sherbrooke, pour la révision du manuel.\n\n## Dédicace toute spéciale à Cargo et Ambrée {-#sect008}\n\nFait cocasse, l'écriture de ce livre a démarré lorsque Philippe Apparicio était famille d'accueil d'un chiot de la [Fondation Mira](https://www.mira.ca/fr/), un organisme à but non lucratif qui forme des chiens-guides et d’assistance pour accroître l’autonomie et l’inclusion sociale des personnes vivant avec un handicap visuel ou moteur, ainsi que des jeunes présentant un trouble du spectre de l’autisme (TSA). En fin de rédaction du livre, ce fut au tour de Jérémy Gelb d'être famille d'accueil d'un autre chiot Mira. Nous remercions chaleureusement la [Fondation Mira](https://www.mira.ca/fr/) pour nous avoir donné l'occasion de vivre cette expérience incroyable. Ce livre est donc dédié au beau Cargo et à la belle Ambrée qui nous ont tant supportés dans l'écriture du livre. Il n’y a rien de plus relaxant que d’écrire un livre de statistique avec un chiot qui dort à ses pieds!\n\n\n![Cargo et Ambrée, chiots de la Fondation Mira](images/introduction/CargoAmbre.png){#fig-CargoAmbre width=\"60%\" fig-align=\"center\"}\n\n\n\n\n", + "supporting": [], + "filters": [ + "rmarkdown/pagebreak.lua" + ], + "includes": {}, + "engineDependencies": {}, + "preserve": {}, + "postProcess": true + } +} \ No newline at end of file diff --git a/.quarto/cites/index.json b/.quarto/cites/index.json new file mode 100644 index 0000000..3270e67 --- /dev/null +++ b/.quarto/cites/index.json @@ -0,0 +1 @@ +{"02-univarie.qmd":["gilles1994elements","audrin2021localisation","lebart1995statistique","lebart1995statistique","SeanOwendist","William_pareto_ville","William_pareto","pumain1994","2020_1","joanes1998comparing","joanes1998comparing","joanes1998comparing","razali2011power","yap2011comparisons","razali2011power","yap2011comparisons","razali2011power","yap2011comparisons","tabachnick2007","field2012discovering","field2012discovering","Sobol1993","de2018accessibilite","de2018accessibilite","de2018accessibilite","de2018accessibilite"],"06-bivarieeQualiQuanti.qmd":["cohen1992","cohen2013","sawilowsky2009","carrier2014","glass1972consequences","lix1996consequences","2018_1"],"05-bivarieeQualiQuali.qmd":["TheseApparicio","TheseApparicio","TheseApparicio"],"index.qmd":["roback2021beyond","hanck2019introduction","ismay2019statistical","Chang2018","allcott2017social","spyratos2019quantifying","boulos2020geographical"],"11-GAM.qmd":["2020_3","wood2004stable"],"09-GLMM.qmd":["gelman2005analysis","mcelreath2020statistical","NakagawaICC","aly2014reliability","stryhn2006interpretation","wu2012comparison","gelman2006data","burdenski2000evaluating","bolker2009generalized","bolker2009generalized"],"14-Annexes.qmd":[],"07-regressionlineaire.qmd":["tabachnick2007","2020_3","bressoux2010","bressoux2010","apparicio2016spatial","hanck2019introduction","bressoux2010","hanck2019introduction","tabachnick2007"],"12-AnalysesFactorielles.qmd":["lebart1995statistique","pages2013analyse","hotelling1933analysis","benzecri1973analyse","escofier1979traitement","pages2002analyse","benzecri1973analyse","escofier1998analyses","lebart1995statistique","pages2013analyse","sanders1989analyse","2021_4","kaiser1960application","lebart1995statistique","pages2013analyse","lebart1995statistique","rivest1988analyse","hubert2005robpca","FactoMineR","benzecri1973analyse","benzecri1973analyse","escofier1998analyses","lebart1995statistique","bendixen1995compositional","mcclintock2018urban","audate2021motivations","bhatt2016cultivating","pages2002analyse"],"04-bivarieeQuantiQuanti.qmd":["PhamApparicioSeguin2012","wilcox1994percentage","wilcox1994percentage","Schwarzkopf2012","Messerli","Messerli"],"references.qmd":[],"10-Multiniveau.qmd":["philibert2007statistiques","atkinson2001disentangling","apparicio2017disentangling","raudenbush2002hierarchical","gelman2006data","tabachnick2007","bressoux2010","apparicio2017disentangling","bressoux2010","raudenbush2002hierarchical","gelman2006data","bressoux2010","bressoux2010"],"00-auteurs.qmd":[],"13-MethodeClassification.qmd":["2021_4","bair2013semi","2021_4","aggarwal2001surprising","chandra1936generalised","gower1971general","ward1963hierarchical","tibshirani2001estimating","apparicio2010accessibilite","macqueen1967","2021_4","2021_4","xie1991validity","fukuyama1989","2021_4"],"08-GLM.qmd":["GLMnelder","RandomizedResid","gelman2006data","NeymanLemma","hilbe2009logistic","zeileis2004econometric","brant1990assessing","teubner2017price","wang2017price","zhang2017key","Sasmultinom","mcfadden2016examining","mcfadden2016examining","Saspoiss","cloutier2014carrefours","cloutier2014carrefours","anastasopoulos2012analysis","frank2008urban","smithson2006better","harlan2007shade","sanchez2019cooling","huang2011everyone","fox1992generalized"],"03-magiedesgraphiques.qmd":["wickham2010layered","wickham2010layered","mihalcea2004textrank"],"01-priseenmainR.qmd":[]} diff --git a/.quarto/idx/00-auteurs.qmd.json b/.quarto/idx/00-auteurs.qmd.json new file mode 100644 index 0000000..21b0a14 --- /dev/null +++ b/.quarto/idx/00-auteurs.qmd.json @@ -0,0 +1 @@ +{"title":"À propos des auteurs","markdown":{"headingText":"À propos des auteurs","headingAttr":{"id":"auteurs","classes":["unnumbered"],"keyvalue":[]},"containsRefs":false,"markdown":"\n[**Philippe Apparicio**](https://www.usherbrooke.ca/recherche/fr/specialistes/details/philippe.apparicio) est professeur titulaire au [Département de géomatique appliquée](https://www.usherbrooke.ca/geomatique/) de l'[Université de Sherbrooke](https://www.usherbrooke.ca/). Il y enseigne aux [programmes de 1^er^ et 2^e^ cycles de géomatique](https://www.usherbrooke.ca/geomatique/etudes/programmes) les cours *Transport et mobilité durable*, *Modélisation et analyse spatiale* et *Géomatique appliquée à la gestion urbaine*. Durant les dernières années, il a offert plusieurs formations aux Écoles d'été du Centre interuniversitaire québécois de statistiques sociales ([CIQSS](https://www.ciqss.org/)). Géographe de formation, ses intérêts de recherche incluent la justice et l'équité environnementale, la mobilité durable, les pollutions atmosphérique et sonore, et le vélo en ville. Il a publié une centaine d'articles scientifiques dans différents domaines des études urbaines et de la géographie mobilisant la géomatique et l'analyse spatiale.\n\n**Jérémy Gelb** a obtenu un doctorat en études urbaines à l'INRS en 2022 (*L'exposition des cyclistes aux pollutions atmosphérique et sonore en milieu urbain : comparaison empirique de plusieurs villes à travers le monde*), sous la supervision de Philippe Apparicio. Il utilise quotidiennement des systèmes d'information géographique (SIG) et des méthodes d'analyses spatiales. Il est tombé dans la marmite de l'*open source* avec le triptyque QGIS, R et Python au début de sa maîtrise. Il a développé deux *packages* : [`geocmeans`](https://cran.r-project.org/web/packages/geocmeans/index.html) et [`spNetwork`](https://cran.r-project.org/web/packages/spNetwork/index.html), permettant respectivement d'effectuer des analyses de classification floue non supervisée pondérée spatialement et des estimations de densité par kernel sur réseau. Il travaille actuellement comme conseiller en science des données à l'[Autorité régionale de transport métropolitain](https://www.artm.quebec/a-propos-de-l-artm/mission/) qui gère la planification du transport collectif dans la région de Montréal. Ces travaux portent sur la qualité des milieux urbains, l'accessibilité spatiale, le transport, l'équité environnementale, les SIG et l'analyse spatiale.\n\nPhilippe et Jérémy travaillent étroitement ensemble depuis plusieurs années. Avec d'autres collègues, ils ont copublié une vingtaine d'articles scientifiques et un autre manuel intitulé [*Méthodes d’analyse spatiale : un grand bol d’R*](https://serieboldr.github.io/MethodesAnalyseSpatiale), avec le soutien de [la fabriqueREL](https://fabriquerel.org/).\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"markdown"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"00-auteurs.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/01-priseenmainR.qmd.json b/.quarto/idx/01-priseenmainR.qmd.json new file mode 100644 index 0000000..9ba863c --- /dev/null +++ b/.quarto/idx/01-priseenmainR.qmd.json @@ -0,0 +1 @@ +{"title":"Prise en main de R","markdown":{"headingText":"Prise en main de R","headingAttr":{"id":"sec-chap01","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans ce chapitre, nous revenons brièvement sur l’histoire de R et la philosophie qui entoure le logiciel. Nous donnons quelques conseils pour son installation et la mise en place d’un environnement de développement. Nous présentons les principaux objets qui sous-tendent le travail effectué avec R (*DataFrame*, vecteur, matrice, etc.) et comment les manipuler avec des exemples appliqués. Si vous maîtrisez déjà R, nullement besoin de lire ce chapitre!\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n* Pour importer des fichiers externes :\n - `foreign` pour entre autres les fichiers *dbase* et ceux des logiciels SPSS et Stata.\n - `sas7bdat` pour les fichiers du logiciel SAS.\n - `xlsx` pour les fichiers Excel.\n* Pour manipuler des chaînes de caractères et des dates : \n - `stringr` pour les chaînes de caractères.\n - `lubridate` pour les dates.\n* Pour manipuler des données :\n - `dplyr` du `tidyverse` propose une grammaire pour manipuler et structurer des données.\n:::\n:::\n\n\n## Histoire et philosophie de R{#sec-011}\n\nR est à la fois un langage de programmation et un logiciel libre (sous la licence publique générale GNU) dédié à l'analyse statistique et soutenu par une fondation : _R Foundation for Statistical Computing_. Il est principalement écrit en C et en Fortran, deux langages de programmation de « bas niveau », proches du langage machine. À l'inverse, R est un langage de « haut niveau », car plus proche du langage humain.\n\n\nR a été créé par Ross Ihaka et Robert Gentleman à l'Université d'Auckland en Nouvelle-Zélande. Si vous avez un jour l'occasion de passer dans le coin, une plaque est affichée dans le département de statistique de l'université; ça mérite le détour (@fig-Plaque). Une version expérimentale a été publiée en 1996, mais la première version stable ne date que de 2000. Il s'agit donc d'un logiciel relativement récent si nous le comparons à ses concurrents SPSS (1968), SAS (1976) et Stata (1984).\n\n\n![Lieu de pèlerinage de R](images/Chap01/plaque.jpg){#fig-Plaque width=\"40%\" fig-align=\"center\"}\n\n\nR a cependant réussi à s'imposer tant dans le milieu de la recherche que dans le secteur privé. Pour s'en convaincre, il suffit de lire l'excellent article concernant la popularité des logiciels d'analyse de données tiré du site [r4stats.com](http://r4stats.com/articles/popularity){target=\"_blank\"} (@fig-ArticlesR).\n\n![Nombre d'articles trouvés sur Google Scholar (source : Robert A. Muenchen)](images/Chap01/r_citations.jpg){#fig-ArticlesR width=\"50%\" fig-align=\"center\"}\n\nLes nombreux atouts de R justifient largement sa popularité sans cesse croissante : \n\n* R est un logiciel à code source ouvert (*open source*) et ainsi accessible à tous gratuitement.\n\n* Le développement du langage R est centralisé, mais la communauté peut créer et partager facilement des *packages*. Les nouvelles méthodes sont ainsi rapidement implémentées comparativement aux logiciels propriétaires.\n\n* R est un logiciel multiplateforme, fonctionnant sur Linux, Unix, Windows et Mac.\n\n* Comparativement à ses concurrents, R dispose d'excellentes solutions pour manipuler des données et réaliser des graphiques.\n\n* R dispose de nombreuses interfaces lui permettant de communiquer, notamment avec des systèmes de bases de données SQL et non SQL (MySQL, PostgresSQL, MongoDB, etc.), avec des systèmes de *big data* (Spark, Hadoop), avec des systèmes d'information géographique (QGIS, ArcGIS) et même avec des services en ligne comme Microsoft Azure ou Amazon AWS.\n\n* R est un langage de programmation à part entière, ce qui lui donne plus de flexibilité que ses concurrents commerciaux (SPSS, SAS, STATA). Avec R, vous pouvez accomplir de nombreuses tâches : monter un site web, créer un robot collectant des données en ligne, combiner des fichiers PDF, composer des diapositives pour une présentation ou même éditer un livre (comme celui-ci), mais aussi, et surtout, réaliser des analyses statistiques.\n\nUn des principaux attraits de R est la quantité astronomique de *packages* actuellement disponibles. **Un *package* est un ensemble de nouvelles fonctionnalités développées par des personnes utilisatrices de R et mises à disposition de l'ensemble de la communauté**. Par exemple, le *package* `ggplot2` est dédié à la réalisation de graphiques; les *packages* `data.table` et `dplyr` permettent de manipuler des tableaux de données; le *package* `car` offre de nombreux outils pour faciliter l'analyse de modèles de régressions, etc. Ce partage de *packages* rend accessible à tous des méthodes d'analyses complexes et récentes et favorise grandement la reproductibilité de la recherche. Cependant, ce fonctionnement implique quelques désavantages : \n\n* Il existe généralement plusieurs *packages* pour effectuer le même type d'analyse, ce qui peut devenir une source de confusion.\n\n* Certains *packages* cessent d'être mis à jour au fil des années, ce qui nécessite de trouver des solutions de rechange (et ainsi apprendre la syntaxe de nouveaux *packages*).\n\n* Il est impératif de s'assurer de la fiabilité des *packages* que vous souhaitez utiliser, car n'importe qui peut proposer un *package*.\n\nIl nous semble important de relativiser d'emblée la portée du dernier point. Il est rarement nécessaire de lire et d'analyser le code source d'un *package* pour s'assurer de sa fiabilité. Nous ne sommes pas des spécialistes de tous les sujets et il peut être extrêmement ardu de comprendre la logique d'un code écrit par une autre personne. Nous vous recommandons donc de privilégier l'utilisation de *packages* qui :\n\n* ont fait l'objet d'une publication dans une revue à comité de lecture ou qui ont déjà été cités dans des études ayant fait l'objet d'une publication revue par les pairs;\n\n* font partie de projets comme [ROpensci](https://ropensci.org/){target=\"_blank\"} prônant la vérification par les pairs ou subventionnés par des organisations comme [R Consortium](https://www.r-consortium.org/){target=\"_blank\"};\n\n* sont disponibles sur l'un des deux principaux répertoires de *packages* R, soit [CRAN](https://cran.r-project.org/){target=\"_blank\"} et [Bioconductor](https://www.bioconductor.org/){target=\"_blank\"}.\n\nToujours pour nuancer notre propos, il convient de distinguer *package* de *package*! Certains d'entre eux sont des ensembles très complexes de fonctions permettant de réaliser des analyses poussées alors que d'autres sont des projets plus modestes dont l'objectif principal est de simplifier le travail des personnes utilisant R. Ces derniers ressemblent à de petites boîtes à outils et font généralement moins l'objet d'une vérification intensive.\n\nPour conclure cette section, l'illustration partagée sur Twitter par Darren L Dahly résume avec humour la force du logiciel R et de sa communauté\n(@fig-fig03) : R apparaît clairement comme une communauté hétéroclite, mais diversifiée et adaptable.\n\n\n![Métaphore sur les langages et programmes d'analyse statistique](images/Chap01/softwares_and_cars.jpeg){#fig-fig03 width=\"60%\" fig-align=\"center\"}\n\n\nDans ce livre, nous détaillons les *packages* utilisés dans chaque section avec un encadré spécifique.\n\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n\n**Bloc *packages***\n:::\n\n::: bloc_package-body\nHabituellement localisé au début d'un chapitre, il comprend la liste des *packages* R utilisés pour un chapitre.\n:::\n:::\n\n\n## Environnement de travail{#sec-012}\n\nDans cette section, nous vous proposons une visite de l'environnement de travail de R.\n\n### Installation de R {#sec-0121}\n\nLa première étape pour travailler avec R est bien sûr de l'installer. Pour cela, il suffit de visiter le site web de [CRAN](https://cran.r-project.org/){target=\"_blank\"} et de télécharger la dernière version de R en fonction de votre système d'exploitation : Windows, Linux ou Mac. Une fois installé, si vous démarrez R immédiatement, vous aurez accès à une console, plutôt rudimentaire, attendant sagement vos instructions (@fig-fig05).\n\n![Console de base de R](images/Chap01/r_console.jpeg){#fig-fig05 width=\"85%\" fig-align=\"center\"}\n\nNotez que vous pouvez aussi télécharger des versions plus anciennes de R en allant sur ce [lien](https://cran.r-project.org/bin/windows/base/old/){target=\"_blank\"}. Cela peut être intéressant lorsque vous voulez reproduire des résultats d'une autre étude ou que certains *packages* ne sont plus disponibles dans les nouvelles versions.\n\n### Environnement RStudio{#sec-0122}\n\nRares sont les adeptes de R qui préfèrent travailler directement avec la console classique. Nous vous recommandons vivement d'utiliser RStudio, un environnement de développement (*IDE*) dédié à R offrant une intégration très intéressante d'une console, d'un éditeur de texte, d'une fenêtre de visualisation des données et d'une autre pour les graphiques, d'un accès à la documentation, etc. En d'autres termes, si R est un vélo minimaliste, RStudio permet d'y rajouter des freins, des vitesses, un porte-bagages, des garde-boues et une selle confortable. Vous pouvez [télécharger](https://rstudio.com/products/rstudio/download){target=\"_blank\"} et installer RStudio sur Windows, Linux et Mac. La version de base est gratuite, mais l'entreprise qui développe ce logiciel propose aussi des versions commerciales du logiciel qui assurent essentiellement une assistance technique. Il existe d'autres environnements de développement pour travailler avec R (Visual Studio Code, Jupyter, Tinn-R, Radiant, RIDE, etc.), mais RStudio offre à ce jour la meilleure option en termes de facilité d'installation, de prise en main et de fonctionnalités proposées (voir l'interface de RStudio à la @fig-fig06).\n\n\n![Environnement de base de RStudio](images/Chap01/r_studio_01.jpeg){#fig-fig06 width=\"85%\" fig-align=\"center\"}\n\nAvant d'aller plus loin, notez que : \n\n* La console actuellement ouverte dans RStudio vous informe de la version de R que vous utilisez. Vous pouvez en effet avoir plusieurs versions de R installées sur votre ordinateur et passer de l'une à l'autre avec RStudio. Pour cela, naviguez dans l'onglet *Tools/Global Options* et dans le volet *General*, puis sélectionnez la version de R que vous souhaitez utiliser.\n\n* L'aspect de RStudio peut être modifié en naviguant dans l'onglet *Tools/Global Options* et dans le volet *Appearance*. Nous avons une préférence pour le mode sombre avec le style *pastel on dark* (@fig-fig07), mais libre à vous de choisir le style qui vous convient.\n\n\n![RStudio avec le style pastel on dark](images/Chap01/r_studio_02.jpeg){#fig-fig07 width=\"85%\" fig-align=\"center\"}\n\nUne fois ces détails réglés, vous pouvez ouvrir votre première feuille de code en allant dans l'onglet *File/New File/R Script*. Votre environnement est maintenant découpé en quatre fenêtres (@fig-fig08) : \n\n1. L'éditeur de code, vous permettant d'écrire le script que vous voulez exécuter et de garder une trace de votre travail. Ce script peut être enregistré sur votre ordinateur avec l'extension **.R**, mais ce n'est qu'un simple fichier texte.\n\n2. La console vous permettant d'exécuter votre code R et de voir les résultats s'afficher au fur et à mesure.\n\n3. La fenêtre d'environnement vous montrant les objets, les fonctions et les jeux de données actuellement disponibles dans votre session (chargés dans la mémoire vive).\n\n4. La fenêtre de l'aide, des graphiques et de l'explorateur de fichiers. Vous pouvez accéder ici à la documentation de R et des *packages* que vous utilisez, aux sorties graphiques que vous produisez et aux dossiers de votre environnement de travail.\n\n\n![Fenêtres de RStudio](images/Chap01/r_studio_03.jpeg){#fig-fig08 width=\"85%\" fig-align=\"center\"}\n\nPrenons un bref exemple : tapez la syntaxe suivante dans l'éditeur de code (fenêtre 1 à la @fig-fig08) : \n\n```{r}\n#| label: \"ma_somme\"\nma_somme <- 4+4\n```\n\nSélectionnez ensuite cette syntaxe (mettre en surbrillance avec la souris) et utilisez le raccourci *Ctrl+Entrée* ou cliquez sur le bouton *Run* (avec la flèche verte) pour envoyer cette syntaxe à la console qui l'exécutera immédiatement. Notez que rien ne se passe tant que le code n'est pas envoyé à la console. Il s'agit donc de deux étapes distinctes : écrire son code, puis l'envoyer à la console. Constatez également qu'un objet *ma_somme* est apparu dans votre environnement et que sa valeur est bien 8. Votre console se « souvient » de cette valeur : elle est actuellement stockée dans votre mémoire vive sous le nom de *ma_somme* (@fig-fig09).\n\n\n![Exécuter du code dans RStudio](images/Chap01/r_studio_04.jpeg){#fig-fig09 width=\"85%\" fig-align=\"center\"}\n\nPour conclure cette section, nous vous invitons à enregistrer votre première syntaxe R (*File/Save As*) dans un fichier **.R** que vous pouvez appeler `mon_premier_script.R` par exemple. Fermez ensuite RStudio, redémarrez-le et ouvrez (*File/Open File*) votre fichier `mon_premier_script.R`. Vous pouvez constater que votre code est toujours présent, mais que votre environnement est vide tant que vous n'exécutez pas votre syntaxe. En effet, lorsque vous fermez RStudio, l'environnement est vidé pour libérer de la mémoire vive. Cela peut poser problème lorsque certains codes sont très longs à exécuter, nous verrons donc plus tard comment enregistrer l'environnement en cours pour le recharger par la suite.\n\n\n### Installation et chargement un *package*{#sec-0123}\n\nDans la section sur la Philosophie de R, nous avons souligné la place centrale jouée par les *packages*. Notez que les termes *paquet* et plus rarement *librairie* sont parfois utilisés en français. Voyons ensemble comment installer un *package*, par exemple celui intitulé `lubridate`, qui nous permettra plus tard de manipuler des données temporelles.\n\n#### Installation d'un *package* depuis *CRAN*{#sec-01231}\n\nPour installer un *package*, il est nécessaire d'être connecté à Internet puisque R va accéder au répertoire de *packages* *CRAN* pour télécharger le *package* et l'installer sur votre machine. Cette opération est réalisée avec la fonction `install.packages`.\n\n```{r}\n#| message: false\n#| warning: false\n#| eval: false\ninstall.packages(\"lubridate\")\n```\n\nNotez qu'une fois que le *package* est installé, il demeure disponible localement sur votre ordinateur, à moins de le désinstaller explicitement avec la fonction `remove.packages`.\n\n#### Installation d'un *package* depuis GitHub{#sec-01232}\n\n*CRAN* est le répertoire officiel des *packages* de R. Vous pouvez cependant télécharger des *packages* provenant d'autres sources. Très souvent, les *packages* sont disponibles sur le site web [GitHub](https://github.com/){target=\"_blank\"} et nous pouvons même y trouver des versions en développement avec des fonctionnalités encore non intégrées dans la version sur *CRAN*. Reprenons le cas de `lubridate`, mais sur GitHub (il est disponible [ici](https://github.com/tidyverse/lubridate){target=\"_blank\"}). Pour l'installer, nous devons d'abord installer un autre *package* appelé `remotes` (depuis *CRAN*).\n\n```{r}\n#| message: false\n#| warning: false\n#| eval: false\ninstall.packages(\"remotes\")\n```\n\nMaintenant que nous disposons de `remotes`, nous pouvons utiliser la fonction d'installation `remotes::install_github` pour directement télécharger `lubridate` depuis GitHub.\n\n```{r}\n#| message: false\n#| warning: false\n#| eval: false\nremotes::install_github(\"tidyverse/lubridate\")\n```\n\n#### Chargement d'un *package* {#sec-01233}\n\nMaintenant que `lubridate` est installé, nous pouvons le charger dans notre session actuelle de R et accéder aux fonctions qu'il propose. Pour cela, il suffit d'utiliser la fonction `library`. Conventionnellement, l'appel des *packages* se fait au tout début du script que vous rédigez. Rien ne vous empêche de le faire au fur et à mesure de votre code, mais ce dernier perd alors en lisibilité. Notez que pour chaque nouvelle session (redémarrage de R), il faut recharger les *packages* dont vous avez besoin avec la fonction `library`.\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(lubridate)\n```\n\nSi vous obtenez un message d'erreur du type : \n\n`Error in library(monPackage) : aucun package nommé ‘monPackage’ n'est trouvé`\n\nCela signifie que le *package* que vous tentez de charger n'est pas encore installé sur votre ordinateur. Dans ce cas, réessayer de l'installer avec la fonction `install.packages`. Si le problème persiste, vérifiez que vous n'avez pas fait une faute de frappe dans le nom du *package.* Vous pouvez également redémarrer RStudio et réessayer d'installer ce *package*.\n\n### Aide disponible\n\nLorsque vous installez des *packages* dans R, vous téléchargez aussi leur documentation. Tous les *packages* de *CRAN* disposent d'une documentation, ce qui n'est pas forcément vrai pour ceux sur *GitHub*. Dans RStudio, vous pouvez accéder à la documentation des *packages* dans l'onglet **Packages** (@fig-fig010). Vous pouvez utiliser la barre de recherche pour retrouver rapidement un *package* installé. Si vous cliquez sur le nom du *package*, vous accédez directement à sa documentation dans cette fenêtre.\n\n\n![Description des packages](images/Chap01/rstudio_packages.jpeg){#fig-fig010 width=\"45%\" fig-align=\"center\"}\n\nVous pouvez également accéder à ces informations en utilisant la syntaxe suivante dans votre console : \n\n```{r}\n#| eval: false\nhelp(package = 'lubridate')\n```\n\nSouvent, vous aurez besoin d'accéder à la documentation d'une fonction spécifique d'un *package*. Affichons la documentation de la fonction `now` de `lubridate` : \n\n```{r}\n#| eval: false\nhelp(now, package = 'lubridate')\n```\n\nou plus simplement :\n```{r}\n#| eval: false\n?lubridate::now\n```\n\nVous pouvez aussi utiliser le raccourci suivant.\n\n```{r}\n#| eval: false\n?now\n```\n\nSi vous ne vous souvenez plus à quel *package* la fonction appartient, lancez une recherche en utilisant un double point d'interrogation : \n\n```{r}\n#| eval: false\n??now\n```\n\nVous découvrirez ainsi que la fonction `now` n'existe pas que dans `lubridate`, ce qui souligne l'importance de bien connaître les *packages* que nous installons et que nous chargeons dans notre session ! \n\nMaintenant que nous avons fait le tour de l'environnement de travail, nous pouvons passer aux choses sérieuses, soit les bases du langage R.\n\n## Bases du langage R {#sec-013}\n\nR est un langage de programmation. Il vous permet de communiquer avec votre ordinateur pour lui donner des tâches à accomplir. Dans cette section, nous abordons les bases du langage. Ce type de section introductive à R est présente dans tous les manuels sur R; elle est donc incontournable. À la première lecture, elle vous semblera probablement aride, et ce, d'autant plus que nous ne réalisons pas d'analyse à proprement parler. Gardez en tête que l'analyse de données requiert au préalable une phase de structuration de ces dernières, opération qui nécessite la maîtrise des notions abordées dans cette section. Nous vous recommandons une première lecture de ce chapitre pour comprendre les manipulations que vous pouvez effectuer avec R, avant de poursuivre avec de la lecture des chapitres suivants dédiés aux analyses statistiques. Vous pourrez revenir consulter cette section au besoin. Notez aussi que la maîtrise des différents objets et des différentes opérations de base de R ne s’acquiert qu'en pratiquant. Vous gagnerez cette expertise au fil de vos prochains codes R, période durant laquelle vous pourrez consulter ce chapitre tel un guide de référence des objets et des notions fondamentales de R.\n\n\n### *Hello World*! {#sec-0131}\n\nUne introduction à un langage de programmation se doit de commencer par le rite de passage *Hello World*. Il s'agit d'une forme de tradition consistant à montrer aux néophytes comment afficher le message `Hello World` à l'écran avec le langage en question.\n\n```{r}\nprint(\"Hello World\")\n```\n\nBravo! Vous venez officiellement de faire votre premier pas dans R!\n\n### Objets et expressions {#sec-0132}\n\nDans R, nous passons notre temps à manipuler des **objets** à l'aide d'**expressions**. Prenons un exemple concret : si vous tapez la syntaxe `4 + 3`, vous manipulez deux objets (4 et 3) avec une expression indiquant que vous souhaitez obtenir la somme des deux objets.\n\n```{r}\n4 + 3\n```\n\nCette expression est correcte, R comprend vos indications et effectue le calcul.\n\nIl est possible d'enregistrer le résultat d'une expression et de le conserver dans un nouvel objet. On appelle cette opération : « déclarer une variable ».\n\n```{r}\nma_somme <- 4 + 3\n```\n\nConcrètement, nous venons de demander à R d'enregistrer le résultat de `4 + 3` dans un espace spécifique de notre mémoire vive. Si vous regardez dans votre fenêtre **Environment**, vous verrez en effet qu'un objet appelé ma_somme est actuellement en mémoire et a pour valeur 7.\n\nNotez ici que le nom des variables ne peut être composé que de lettres, de chiffres, de points (.) et de tirets bas (_) et doit commencer par une lettre. R est sensible à la casse; en d'autres termes, les variables `Ma_somme`, `ma_sommE`, `ma_SOMME`, et `MA_SOMME` renvoient toutes à un objet différent. Attention donc aux fautes de frappe. Si vous déclarez une variable en utilisant le nom d'une variable existante, la première est écrasée par la seconde : \n\n```{r}\nage <- 35\nage\n\nage <- 45\nage\n```\n\nPortez alors attention aux noms de variables que vous utilisez et réutilisez. Réutilisons notre objet `ma_somme` dans une nouvelle expression : \n\n```{r}\nma_somme2 <- ma_somme + ma_somme\n```\n\nAvec cette nouvelle expression, nous indiquons à R que nous souhaitons déclarer une nouvelle variable appelée `ma_somme2`, et que cette variable aura pour valeur `ma_somme + ma_somme`, soit `7 + 7`. Sans surprise, `ma_somme2` a pour valeur 14.\n\nNotez que la mémoire vive (l'environnement) est vidée lorsque vous fermez R. Autrement dit, R perd complètement la mémoire lorsque vous le fermez. Vous pouvez bien sûr recréer vos objets en relançant les mêmes syntaxes. C'est pourquoi vous devez conserver vos feuilles de codes et ne pas seulement travailler dans la console. La console ne garde aucune trace de votre travail. Pensez donc à bien enregistrer votre code!\n\nNous verrons dans une prochaine section comment sauvegarder des objets et les recharger dans une session ultérieure de R ([section @sec-017]). Ce type d'opération est pertinent quand le temps de calcul nécessaire à la production de certains objets est très long.\n\n### Fonctions et arguments {#sec-0_133}\n\nDans R, nous manipulons le plus souvent nos objets avec des **fonctions**. Une fonction est elle-même un objet, mais qui a la particularité de pouvoir effectuer des opérations sur d'autres objets. Par exemple, déclarons l'objet `taille` avec une valeur de 175,897 : \n\n```{r}\ntaille <- 175.897\n```\n\nNous utilisons la fonction `round`, dont l'objectif est d'arrondir un nombre avec décimales pour obtenir un nombre entier.\n\n```{r}\nround(taille)\n```\n\nPour effectuer leurs opérations, les fonctions ont généralement besoin d'**arguments**. Ici, `taille` est un argument passé à la fonction `round`. Si nous regardons la documentation de `round` avec `help(round)` (@fig-fig011), nous constatons que cette fonction prend en réalité deux arguments : *x* et *digits*. Le premier est le nombre que nous souhaitons arrondir et le second est le nombre de décimales à conserver. Nous pouvons lire dans la documentation que la valeur par défaut de *digits* est 0, ce qui explique que `round(taille)` a produit le résultat de 176.\n\n\n![Arguments de la fonction `round`](images/Chap01/help_round.jpeg){#fig-fig011 width=\"35%\" fig-align=\"center\"}\n\nRéutilisons maintenant la fonction `round`, mais en gardant une décimale : \n\n```{r}\nround(taille, digits = 1)\n```\n\nIl est aussi possible que certaines fonctions ne requièrent pas d'argument. Par exemple, la fonction `now` indique la date précise (avec l'heure) et n'a besoin d'aucun argument pour le faire : \n\n```{r}\nnow()\n```\n\nPar contre, si nous essayons de lancer la fonction `round` sans argument, nous obtenons une erreur :\n\n```{r}\n#| eval: false\nround()\n```\n\n`Erreur : 0 argument passé à 'round' qui en exige 1 ou 2`\n\nLe message est très clair, `round` a besoin d'au moins un argument pour fonctionner. Si, au lieu d'un nombre, nous avions donné du texte à la fonction `round`, nous aurions aussi obtenu une erreur : \n\n```{r}\n#| eval: false\nround(\"Hello World\")\n```\n\n`Erreur dans round(\"Hello World\") : argument non numérique pour une fonction mathématique`\n\nÀ nouveau le message est très explicite : nous avons passé un argument non numérique à une fonction mathématique. Lisez toujours vos messages d'erreurs : ils permettent de repérer les coquilles et de corriger votre code!\n\nNous terminons cette section avec une fonction essentielle, `print`, qui permet d'afficher la valeur d'une variable.\n\n```{r}\nprint(ma_somme)\n```\n\n\n### Principaux types de données {#sec-0134}\n\nDepuis le début de ce chapitre, nous avons déclaré plusieurs variables et essentiellement des données numériques. Dans R, il existe trois principaux types de données de base : \n\n* Les données numériques qui peuvent être des nombres entiers (appelés *integers*) ou des nombres décimaux (appelés *floats* ou *doubles*), par exemple `15` et `15.3`.\n\n* Les données de type texte qui sont des chaînes de caractères (appelées *strings*) et déclarées entre guillemets `\"abcdefg\"`.\n\n* Les données booléennes (*booleans*) qui peuvent n'avoir que deux valeurs : vrai (`TRUE`) ou faux (`FALSE`).\n\nDéclarons une variable pour chacun de ces types : \n\n```{r}\nage <- 35\ntaille <- 175.5\nadresse <- '4225 rue de la gauchetiere'\nproprietaire <- TRUE\n```\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Simples ou doubles quotes?**\n:::\n::: bloc_notes-body\nPour déclarer des données de type texte, il est possible d'utiliser des quotes simples `'` (apostrophe) ou des quotes doubles `\"` (guillemets), cela ne fait aucune différence pour R. Cependant, si la chaîne de caractères que vous créez contient une apostrophe, il est nécessaire d'utiliser des quotes doubles et inversement si votre chaîne de caractère contient des guillemets.\n\n```{r}\nphrase1 <- \"J'adore le langage R!\"\nphrase2 <- 'Je cite : \"il est le meilleur langage de statistique\".'\n```\n\nSi la chaîne de caractère contient des guillemets et des apostrophes, il est nécessaire d'utiliser la barre oblique inversée `\\` pour indiquer à R que ces apostrophes ou ces guillemets ne doivent pas être considérés comme la fin de la chaîne de caractère.\n\n```{r}\nphrase3 <- \"Je cite : \\\"j'en rêve la nuit\\\".\"\ncat(phrase3)\n```\n\nLes barres obliques inversées ne font pas partie de la chaîne de caractère, ils sont là pour \"échapper\" les guillemets qui doivent rester dans la chaîne de caractère. Si une chaîne de caractère doit contenir une barre oblique inversée, alors il faut l'échapper également en utilisant une deuxième barre oblique inversée.\n\n```{r}\nphrase4 <- \"Une phrase avec une barre oblique inversée : \\\\\"\ncat(phrase4)\n```\nFaites attention à la coloration syntaxique de RStudio! Elle peut vous aider à repérer facilement une chaîne de caractère qui aurait été interrompue par un guillemet ou une apostrophe mal placés.\n:::\n:::\n\nSi vous avez un doute sur le type de données stockées dans une variable, vous pouvez utiliser la fonction `typeof`. Par exemple, cela permet de repérer si des données qui sont censées être numériques sont en fait stockées sous forme de texte comme dans l'exemple ci-dessous.\n\n```{r}\ntypeof(age)\ntypeof(taille)\n\n# Ici tailletxt est définie comme une chaîne de caractère car la valeur est \n# définie entre des guillemets.\ntailletxt <- \"175.5\"\ntypeof(tailletxt)\n\n```\n\n\nNotez également qu'il existe des types pour représenter l'absence de données : \n\n* pour représenter un objet vide, nous utilisons l'objet `NULL`,\n\n* pour représenter une donnée manquante, nous utilisons l'objet `NA`,\n\n* pour représenter un texte vide, nous utilisons une chaîne de caractère de longueur 0, soit `\"\"`.\n\n```{r}\nage2 <- NULL\ntaille2 <- NA\nadresse2 <- ''\n```\n\n### Opérateurs {#sec-0135}\n\nNous avons vu que les fonctions permettent de manipuler des objets. Nous pouvons également effectuer un grand nombre d'opérations avec les opérateurs.\n\n#### Opérateurs mathématiques {#sec-01351}\n\nLes opérateurs mathématiques (@tbl-OperateurMath) permettent d'effectuer des calculs avec des données de type numérique.\n\n```{r}\n#| label: tbl-OperateurMath\n#| tbl-cap: Opérateurs mathématiques\n#| echo: false\n#| message: false\n#| warning: false\n\ndf <- data.frame(\n Operateur = c(\"`+`\" , \"`-`\" , \"`*`\" , \"`/`\", \"`^`\", \"`**`\",\n \"`%%`\", \"`%/%`\"),\n Description = c(\"Addition\", 'Soustraction', 'Multiplication',\n 'Division', 'Exponentiel', 'Exponentiel',\n 'Reste de division', 'Division entière'),\n Syntaxe = c(\"`4 + 4`\", \"`4 - 3`\", \"`4 * 3`\", \"`12 / 4`\",\n \"`4 ^ 3`\", '`4 ** 3`', \"`15,5 %% 2`\",\n \"`15,5 %/% 2`\"), \n Resultat = c(8,1,12,3,64,64,1.5,7))\n\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Opérateur\" , \"Description\" , \"Syntaxe\" , \"Résultat\"),\n align= c(\"l\", \"l\", \"l\", \"r\")\n )\n```\n\n#### Opérateurs relationnels {#sec-01352}\n\nLes opérateurs relationnels (@tbl-OperateurRelationnels) permettent de vérifier des conditions dans R. Ils renvoient un booléen, `TRUE` si la condition est vérifiée et `FALSE` si ce n'est pas le cas.\n\n```{r}\n#| label: tbl-OperateurRelationnels\n#| tbl-cap: Opérateurs relationnels\n#| echo: false\n#| message: false\n#| warning: false\n\ndf <- data.frame(\n Operateur = c(\"`==`\" , \"`!=`\" , \"`>`\" , \"`<`\", \"`>=`\", \"`<=`\"),\n Description = c(\"Égalité\", 'Différence', 'Est supérieur ', 'Est inférieur', 'Est supérieur ou égal', 'Est inférieur ou égal'),\n Syntaxe = c(\"`4 == 4`\", \"`4 != 4`\", \"`5 > 4`\", \"`5 < 4`\", \"`5 >= 4`\", '`5 <= 4`'), \n Resultat = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE))\n\nknitr::kable(df,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Opérateur\" , \"Description\" , \"Syntaxe\" , \"Résultat\"),\n align= c(\"l\", \"l\", \"l\", \"l\"))\n```\n\n#### Opérateurs logiques {#sec-01353}\n\nLes opérateurs logiques (@tbl-tableOperateurLogi) permettent de combiner plusieurs conditions :\n\n* L'opérateur **ET** (`&`) permet de vérifier que deux conditions (l'une ET l'autre) sont TRUE. Si l'une des deux est FALSE, il renvoie FALSE.\n\n* L'opérateur **OU** (`|`) permet de vérifier que l'une des deux conditions est TRUE (l'une OU l'autre). Si les deux sont FALSE, alors il renvoie FALSE.\n\n* L'opérateur **NOT** (`!`) permet d'inverser une condition. Ainsi, NOT TRUE donne FALSE et NOT FALSE donne TRUE.\n\n\n```{r}\n#| label: tbl-tableOperateurLogi\n#| tbl-cap: Opérateurs logiques\n#| echo: false\n#| message: false\n#| warning: false\ndf <- data.frame(\n Operateur = c(\"`&`\" , \"`|`\" , \"`!`\"),\n Description = c(\"ET\", \"OU\", \"NOT\"),\n Syntaxe = c(\"`TRUE & FALSE`\", \"`TRUE | FALSE`\", \"`! TRUE`\"), \n Resultat = c(FALSE, TRUE, FALSE))\n\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Opérateur\" , \"Description\" , \"Syntaxe\" , \"Résultat\"),\n align= c(\"l\", \"l\", \"l\", \"l\")\n )\n```\n\nPrenons le temps pour un rapide exemple : \n\n```{r}\n\nA <- 4 \nB <- 10\nC <- -5\n\n# Produit TRUE car A est bien plus petit que B et C est bien plus petit que A\nA < B & C < A\n\n# Produit FALSE car si A est bien plus petit que B, \n# B est en revanche plus grand que c\nA < B & B < C\n\n# Produit TRUE car la seconde condition est inversée\nA < B & ! B < C\n\n# Produit TRUE car au moins une des deux conditions est juste\nA < B | B < C\n\n```\n\nNotez que l'opérateur **ET** est prioritaire sur l'opérateur **OU** et que les parenthèses sont prioritaires sur tous les opérateurs : \n\n```{r}\n# Produit TRUE car nous commençons par tester A < B puis B < C ce qui donne FALSE\n# On obtient ensuite\n# FALSE | A > C\n# Enfin, A est bien supérieur à C, donc l'une des deux conditions est vraie\nA < B & B < C | A > C\n\n```\n\nNotez qu'en arrière-plan, les opérateurs sont en réalité des fonctions déguisées. Il est donc possible de définir de nouveaux comportements pour les opérateurs. Il est par exemple possible d'additionner ou de comparer des objets spéciaux comme des dates, des géométries, des graphes, etc.\n\n### Structures de données {#sec-0136}\n\nJusqu'à présent, nous avons utilisé des objets ne comprenant qu'une seule valeur. Or, des analyses statistiques nécessitent de travailler avec des volumes de données bien plus grands. Pour stocker des valeurs, nous travaillons avec différentes structures de données : les vecteurs, les matrices, les tableaux de données et les listes.\n\n#### Vecteurs {#sec-01361}\n\nLes vecteurs sont la brique élémentaire de R. Ils permettent de stocker une série de valeurs **du même type** dans une seule variable. Pour déclarer un vecteur, nous utilisons la fonction `c()` : \n\n```{r}\nages <- c(35,45,72,56,62)\ntailles <- c(175.5,180.3,168.2,172.8,167.6)\nadresses <- c('4225 rue de la gauchetiere',\n '4223 rue de la gauchetiere',\n '4221 rue de la gauchetiere',\n '4219 rue de la gauchetiere',\n '4217 rue de la gauchetiere')\nproprietaires <- c(TRUE, TRUE, FALSE, TRUE, TRUE)\n```\n\nNous venons ainsi de déclarer quatre nouvelles variables étant chacune un vecteur de longueur cinq (comprenant chacun cinq valeurs). Ces vecteurs représentent, par exemple, les réponses de plusieurs personnes à un questionnaire.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Distinction entre un vecteur de type texte et un vecteur de type facteur**\n:::\n\n::: bloc_attention-body\nIl existe dans R une subtilité à l'origine de nombreux malentendus : la distinction entre un vecteur de type **texte** et un vecteur de type **facteur**. Dans l'exemple précédent, le vecteur *adresses* est un vecteur de type texte. Chaque nouvelle valeur ajoutée dans le vecteur peut être n'importe quelle nouvelle adresse. Déclarons un nouveau vecteur qui contient cette fois-ci la couleur des yeux de personnes ayant répondu au questionnaire.\n\n```{r}\ncouleurs_yeux <- c('marron', 'marron', 'bleu', 'bleu', 'marron', 'vert')\n```\n\nContrairement aux adresses, il y a un nombre limité de couleurs que nous pouvons mettre dans ce vecteur. Il est donc intéressant de fixer les valeurs possibles du vecteur pour éviter d'en ajouter de nouvelles par erreur. Pour cela, nous devons convertir ce vecteur texte en vecteur de type facteur, ci-après nommé simplement facteur, avec la fonction `as.factor`.\n\n```{r}\ncouleurs_yeux_facteur <- as.factor(couleurs_yeux)\n```\n\nNotez qu'à présent, nous pouvons ajouter une nouvelle couleur dans le premier vecteur, mais pas dans le second.\n\n```{r}\ncouleurs_yeux[7] <- \"rouge\"\ncouleurs_yeux_facteur[7] <- \"rouge\"\n```\n\nLe message d'erreur nous informe que nous avons tenté d'introduire une valeur invalide dans le facteur.\n\nLes facteurs peuvent sembler restrictifs et, très régulièrement, nous préférons travailler avec de simples vecteurs de type texte plutôt que des facteurs. Cependant, de nombreuses fonctions d'analyse nécessitent d'utiliser des facteurs, car ils assurent une certaine cohérence dans les données. Il est donc essentiel de savoir passer du texte au facteur avec la fonction `as.factor`. À l'inverse, il est parfois nécessaire de revenir à une variable de type texte avec la fonction `as.character`.\n\nNotez que des vecteurs numériques peuvent aussi être convertis en facteurs : \n\n```{r}\ntailles_facteur <- as.factor(tailles)\n```\n\nCependant, si vous souhaitez reconvertir ce facteur en format numérique, il faudra passer dans un premier temps par le format texte : \n\n```{r}\nas.numeric(tailles_facteur)\n```\n\nComme vous pouvez le voir, convertir un facteur en valeur numérique renvoie des nombres entiers. Ceci est dû au fait que les valeurs dans un facteur sont recodées sous forme de nombres entiers, chaque nombre correspondant à une des valeurs originales (appelées niveaux). Si nous convertissons un facteur en valeurs numériques, nous obtenons donc ces nombres entiers.\n\n```{r}\nas.numeric(as.character(tailles_facteur))\n```\n\nMorale de l'histoire : ne confondez pas les données de type texte et de type facteur. Dans le doute, vous pouvez demander à R quel est le type d'un vecteur avec la fonction `class`.\n\n```{r}\nclass(tailles)\nclass(tailles_facteur)\nclass(couleurs_yeux)\nclass(couleurs_yeux_facteur)\n```\n:::\n:::\n\n\nQuasiment toutes les fonctions utilisent des vecteurs. Par exemple, nous pouvons calculer la moyenne du vecteur *ages* en utilisant la fonction `mean` présente de base dans R.\n\n```{r}\nmean(ages)\n```\n\nCela démontre bien que le vecteur est la brique élémentaire de R! Toutes les variables que nous avons déclarées dans les sections précédentes sont aussi des vecteurs, mais de longueur 1.\n\n#### Matrices {#sec-01362}\n\nIl est possible de combiner des vecteurs pour former des matrices. Une matrice est un tableau en deux dimensions (colonnes et lignes) et est généralement utilisée pour représenter certaines structures de données comme des images (pixels), effectuer du calcul matriciel ou plus simplement présenter des matrices de corrélations. Vous aurez rarement à travailler directement avec des matrices, mais il est bon de savoir ce qu'elles sont. Créons deux matrices à partir de nos précédents vecteurs.\n\n```{r}\nmatrice1 <- cbind(ages, tailles)\n# Afficher la matrice 1\nprint(matrice1)\n# Afficher les dimensions de la matrice 1 (1er chiffre : lignes; 2e chiffre : colonnes)\nprint(dim(matrice1))\n\nmatrice2 <- rbind(ages, tailles)\n# Afficher la matrice 2\nprint(matrice2)\n# Afficher les dimensions de la matrice 2\nprint(dim(matrice2))\n```\n\nComme vous pouvez le constater, la fonction `cbind` permet de concaténer des vecteurs comme s'ils étaient les colonnes d'une matrice, alors que `rbind` les combine comme s'ils étaient les lignes d'une matrice. La @fig-fig012 présente graphiquement le passage du vecteur à la matrice.\n\n![Du vecteur à la matrice](images/Chap01/vecteur_to_matrix.png){#fig-fig012 width=\"30%\" fig-align=\"center\"}\n\nNotez que vous pouvez transposer une matrice avec la fonction `t`. Si nous essayons maintenant de comparer la matrice 1 à la matrice 2 nous allons avoir une erreur, car elles n'ont pas les mêmes dimensions.\n\n```{r}\n#| eval: false\nmatrice1 == matrice2\n```\n\n`Erreur dans matrice1 == matrice2 : tableaux de tailles inadéquates`\n\nEn revanche, nous pouvons transposer la matrice 1 et refaire cette comparaison : \n\n```{r}\nt(matrice1) == matrice2\n```\n\nLe résultat souligne bien que nous avons les mêmes valeurs dans les deux matrices. Il est aussi possible de construire des matrices directement avec la fonction `matrix`, ce que nous montrons dans la prochaine section.\n\n#### *Arrays* {#sec-01363}\n\nS'il est rare de travailler avec des matrices, il est encore plus rare de manipuler des *arrays*. Un *array* est une matrice spéciale qui peut avoir plus que deux dimensions. Un cas simple serait un *array* en trois dimensions : lignes, colonnes, profondeur, que nous pourrions représenter comme un cube, ou une série de matrices de mêmes dimensions et empilées. Au-delà de trois dimensions, il devient difficile de les représenter mentalement. Cette structure de données peut être utilisée pour représenter les différentes bandes spectrales d'une image satellitaire. Les lignes et les colonnes délimiteraient les pixels de l'image et la profondeur délimiterait les différentes bandes composant l'image (@fig-fig012).\n\n\n![Un array avec trois dimensions](images/Chap01/array.png){#fig-fig013 width=\"15%\" fig-align=\"center\"}\n\nCréons un *array* en combinant trois matrices avec la fonction `array`. Chacune de ces matrices est composée respectivement de 1, de 2 et de 3 et a une dimension de 5 x 5. L'*array* final a donc une dimension de 5 x 5 x 3.\n\n```{r}\nmat1 <- matrix(1, nrow = 5, ncol = 5)\nmat2 <- matrix(2, nrow = 5, ncol = 5)\nmat3 <- matrix(3, nrow = 5, ncol = 5)\n\nmon_array <- array(c(mat1, mat2, mat3), dim = c(5,5,3))\n\nprint(mon_array)\n```\n\n\n#### *DataFrames* {#sec-01364}\n\nS'il est rare de manipuler des matrices et des *arrays*, le *DataFrame* (tableau de données en français) est la structure de données la plus souvent utilisée. Dans cette structure, chaque ligne du tableau représente un individu et chaque colonne représente une caractéristique de cet individu. Ces colonnes ont des noms qui permettent facilement d'accéder à leurs valeurs. Créons un *DataFrame* (@tbl-tabfirsttable) à partir de nos quatre vecteurs et de la fonction `data.frame`.\n\n```{r}\ndf <- data.frame(\n \"age\" = ages,\n \"taille\" = tailles,\n \"adresse\" = adresses,\n \"proprietaire\" = proprietaires\n)\n```\n\n```{r}\n#| label: tbl-tabfirsttable\n#| tbl-cap: Premier DataFrame\n#| echo: false\n#| message: false\n#| warning: false\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n align= c(\"c\", \"c\", \"l\", \"l\")\n)\n```\n\nDans RStudio, vous pouvez visualiser votre tableau de données avec la fonction `View(df)`. Comme vous pouvez le constater, chaque vecteur est devenu une colonne de votre tableau de données *df*. La @fig-fig013 résume ce passage d'une simple donnée à un *DataFrame* en passant par un vecteur.\n\n\n![De la donnée au DataFrame](images/Chap01/vecteur_to_dataframe.png){#fig-fig013 width=\"25%\" fig-align=\"center\"}\n\nPlusieurs fonctions de base de R fournissent des informations importantes sur un *DataFrame* : \n\n* `names` renvoie les noms des colonnes du *DataFrame*;\n* `nrow` renvoie le nombre de lignes;\n* `ncol` renvoie le nombre de colonnes.\n\n```{r}\nnames(df)\nnrow(df)\nncol(df)\n```\n\nVous pouvez accéder à chaque colonne de *df* en utilisant le symbole `$` ou `[[\"nom_de_la_colonne\"]]`. Recalculons ainsi la moyenne des âges :\n\n```{r}\nmean(df$age)\nmean(df[[\"age\"]])\n```\n\n#### Listes {#sec-01365}\n\nLa dernière structure de données à connaître est la liste. Elle ressemble à un vecteur, au sens où elle permet de stocker un ensemble d'objets les uns à la suite des autres. Cependant, une liste peut contenir n'importe quel type d'objets. Vous pouvez ainsi construire des listes de matrices, des listes d'*arrays*, des listes mixant des vecteurs, des graphiques, des *DataFrames*, des listes de listes...\n\nCréons ensemble une liste qui va contenir des vecteurs et des matrices à l'aide de la fonction `list.`\n\n```{r}\nma_liste <- list(c(1,2,3,4),\n matrix(1, ncol = 3, nrow = 5),\n matrix(5, ncol = 3, nrow = 7),\n 'A'\n )\n```\n\nIl est possible d'accéder aux éléments de la liste par leur position dans cette dernière en utilisant les doubles crochets `[[ ]]` : \n\n```{r}\nprint(ma_liste[[1]])\nprint(ma_liste[[4]])\n```\n\nIl est aussi possible de donner des noms aux éléments de la liste et d'utiliser le symbole `$` pour y accéder. Créons une nouvelle liste de vecteurs et donnons-leur des noms avec la fonction `names`.\n\n```{r}\nliste2 <- list(c(35, 45, 72, 56, 62), \n c(175.5, 180.3, 168.2, 172.8, 167.6),\n c(TRUE, TRUE, FALSE, TRUE, TRUE)\n)\nnames(liste2) <- c(\"age\", \"taille\", \"proprietaire\")\n\nprint(liste2$age)\n```\n\nSi vous avez bien suivi, vous devriez avoir compris qu'un *DataFrame* n'est en fait rien d'autre qu'une liste de vecteurs avec des noms!\n\nBravo! Vous venez de faire le tour des bases du langage R. Vous allez apprendre désormais à manipuler des données dans des *DataFrames*!\n\n## Manipulation de données {#sec-014}\n\nDans cette section, vous apprendrez à charger et à manipuler des *DataFrames* en vue d'effectuer des opérations classiques de gestion de données.\n\n\n### Chargement d'un *DataFrame* depuis un fichier {#sec-0141}\n\nIl est rarement nécessaire de créer vos *DataFrames* manuellement. Le plus souvent, vous disposerez de fichiers contenant vos données et utiliserez des fonctions pour les importer dans R sous forme d'un *DataFrame*. Les formats à importer les plus répandus sont : \n\n* *.csv*, soit un fichier texte dont chaque ligne représente une ligne du tableau de données et dont les colonnes sont séparées par un délimiteur (généralement une virgule ou un point-virgule);\n\n* *.dbf*, ou fichier *dBase*, souvent associés à des fichiers d'information géographique au format *ShapeFile*;\n\n* *.xls* et *.xlsx*, soit des fichiers générés par Excel;\n\n* *.json*, soit un fichier texte utilisant la norme d'écriture propre au langage JavaScript.\n\nPlus rarement, il se peut que vous ayez à charger des fichiers provenant de logiciels propriétaires : \n\n* *.sas7bdat* (SAS);\n* *.sav* (SPSS);\n* *.dta* (STATA).\n\nPour lire la plupart de ces fichiers, nous utilisons le *package* `foreign` dédié à l'importation d'une multitude de formats. Nous commençons donc par l'installer (`install.packages(\"foreign\")`). Ensuite, nous chargeons cinq fois le même jeu de données enregistré dans des formats différents (*csv*, *dbf*, *dta*, *sas7bdat* et *xlsx*) et nous mesurons le temps nécessaire pour importer chacun de ces fichiers avec la fonction `Sys.time`.\n\n#### Lecture d'un fichier *csv* {#sec-01411}\n\nPour le format *csv*, il n'est pas nécessaire d'utiliser un *package* puisque R dispose d'une fonction de base pour lire ce format.\n\n```{r}\n#| message: false\n#| warning: false\nt1 <- Sys.time()\ndf1 <- read.csv(\"data/priseenmain/SR_MTL_2016.csv\", \n header = TRUE, sep = \",\", dec = \".\",\n stringsAsFactors = FALSE)\nt2 <- Sys.time()\nd1 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df1 a \", nrow(df1),\" observations\",\n 'et ', ncol(df1),\" colonnes\\n\")\n```\n\nRien de bien compliqué! Notez tout de même que : \n\n* Lorsque vous chargez un fichier *csv*, vous devez connaître le **délimiteur** (ou **séparateur**), soit le caractère utilisé pour délimiter les colonnes. Dans le cas présent, il s'agit d'une virgule (spécifiez avec l'argument `sep = \",\"`), mais il pourrait tout aussi bien être un point virgule (`sep = \";\"`), une tabulation (`sep = \" \"`), etc.\n\n* Vous devez également spécifier le caractère utilisé comme séparateur de décimales. Le plus souvent, ce sera le point (`dec = \".\"`), mais certains logiciels avec des paramètres régionaux de langue française (notamment Excel) exportent des fichiers *csv* avec des virgules comme séparateur de décimales (utilisez alors `dec = \",\"`).\n\n* L'argument `header` indique si la première ligne (l'entête) du fichier comprend ou non les noms des colonnes du jeu de données (avec les valeurs `TRUE` ou `FALSE`). Il arrive que certains fichiers *csv* soient fournis sans entête et que le nom et la description des colonnes soient fournis dans un autre fichier.\n\n* L'argument `stringsAsFactors` permet d'indiquer à R que les colonnes comportant du texte doivent être chargées comme des vecteurs de type texte et non de type facteur.\n\n#### Lecture d'un fichier *dbase* {#sec-01412}\n\nPour lire un fichier *dbase* (.dbf), nous utilisons la fonction `read.dbf` du *package* `foreign` installé précédemment : \n\n```{r}\n#| message: false\n#| warning: false\nlibrary(foreign)\n\nt1 <- Sys.time()\ndf2 <- read.dbf(\"data/priseenmain/SR_MTL_2016.dbf\")\nt2 <- Sys.time()\nd2 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df2 a \", nrow(df2),\" observations\",\n \"et \", ncol(df2),\" colonnes\\n\")\n```\n\nComme vous pouvez le constater, nous obtenons les mêmes résultats qu'avec le fichier *csv*.\n\n#### Lecture d'un fichier *dta* (Stata) {#sec-01413}\n\nSi vous travaillez avec des collègues utilisant le logiciel Stata, il se peut que ces derniers vous partagent des fichiers *dta*. Toujours en utilisant le *package* `foreign`, vous serez en mesure de les charger directement dans R.\n\n```{r}\n#| message: false\n#| warning: false\nt1 <- Sys.time()\ndf3 <- read.dta(\"data/priseenmain/SR_MTL_2016.dta\")\nt2 <- Sys.time()\nd3 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df3 a \", nrow(df3),\" observations \",\n \"et \", ncol(df3), \" colonnes\\n\", sep = \"\")\n```\n\n\n#### Lecture d'un fichier *sav* (SPSS) {#sec-01414}\n\nPour importer un fichier *sav* provenant du logiciel statistique SPSS, utilisez la fonction `read.spss` du *package* `foreign`.\n\n```{r}\n#| message: false\n#| warning: false\nt1 <- Sys.time()\ndf4 <- as.data.frame(read.spss(\"data/priseenmain/SR_MTL_2016.sav\"))\nt2 <- Sys.time()\nd4 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df4 a \", nrow(df4),\" observations \",\n \"et \", ncol(df4), \" colonnes\\n\", sep = \"\")\n```\n\n#### Lecture d'un fichier *sas7bdat* (SAS) {#sec-01415}\n\nPour importer un fichier *sas7bdat* provenant du logiciel statistique SAS, utilisez la fonction `read.sas7bdat` du *package* `sas7bdat`. Installez préalablement le *package* (`install.packages(\"sas7bdat\")`) et chargez-le (`library(sas7bdat)`).\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(sas7bdat)\n\nt1 <- Sys.time()\ndf5 <- read.sas7bdat(\"data/priseenmain/SR_MTL_2016.sas7bdat\")\nt2 <- Sys.time()\nd5 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df5 a \", nrow(df5),\" observations \",\n \"et \", ncol(df5),\" colonnes\\n\", sep = \"\")\n```\n\n\n#### Lecture d'un fichier *xlsx* (Excel) {#sec-01416}\n\nLire un fichier Excel dans R n'est pas toujours une tâche facile. Généralement, nous recommandons d'exporter le fichier en question au format *csv* dans un premier temps, puis de le lire avec la fonction `read.csv` dans un second temps ([section @sec-01411]). \n\nIl est néanmoins possible de lire directement un fichier *xlsx* avec le *package* `xlsx`. Ce dernier requiert que le logiciel JAVA soit installé sur votre ordinateur (Windows, Mac ou Linux). Si vous utilisez la version 64 bit de R, vous devrez télécharger et installer la version 64 bit de JAVA. Une fois que ce logiciel tiers est installé, il ne vous restera plus qu'à installer (`install.packages(\"xlsx\")`) et charger (`library(xlsx)`) le *package* `xlsx`. Sous windows, il est possible que vous deviez également installer manuellement le *package* `rJava` et indiquer à R où se trouve JAVA sur votre ordinateur. La procédure est détaillée [ici](https://cimentadaj.github.io/blog/2018-05-25-installing-rjava-on-windows-10/installing-rjava-on-windows-10/).\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(xlsx)\n\nt1 <- Sys.time()\ndf6 <- read.xlsx(file=\"data/priseenmain/SR_MTL_2016.xlsx\",\n sheetIndex = 1,\n as.data.frame = TRUE)\nt2 <- Sys.time()\nd6 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df6 a \", nrow(df6),\" observations \",\n \"et \", ncol(df6),\" colonnes\\n\", sep = \"\")\n```\n\nIl est possible d'accélérer significativement la vitesse de lecture d'un fichier *xlsx* en utilisant la fonction `read.xlsx2`. Il faut cependant indiquer à cette dernière le type de données de chaque colonne. Dans le cas présent, les cinq premières colonnes contiennent des données de type texte (`character`), alors que les 43 autres sont des données numériques (`numeric`). Nous utilisons la fonction `rep` afin de ne pas avoir à écrire plusieurs fois *character* et *numeric*.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(xlsx)\n\nt1 <- Sys.time()\ndf7 <- read.xlsx2(file=\"data/priseenmain/SR_MTL_2016.xlsx\",\n sheetIndex = 1, \n as.data.frame = TRUE,\n colClasses = c(rep(\"character\",5), rep(\"numeric\",43))\n )\nt2 <- Sys.time()\nd7 <- as.numeric(difftime(t2, t1, units = \"secs\"))\ncat(\"Le DataFrame df6 a \", nrow(df7),\" observations \",\n \"et \", ncol(df7),\" colonnes\\n\", sep = \"\")\n```\n\nSi nous comparons les temps d'exécution (@tbl-tableduration), nous constatons que la lecture des fichiers *xlsx* peut être extrêmement longue si nous ne spécifions pas le type des colonnes, ce qui peut devenir problématique pour des fichiers volumineux. Notez également que la lecture d'un fichier *csv* devient de plus en plus laborieuse à mesure que sa taille augmente. Si vous devez un jour charger des fichiers *csv* de plusieurs gigaoctets, nous vous recommandons vivement d'utiliser la fonction `fread` du *package* `data.table` qui est beaucoup plus rapide.\n\n\n```{r}\n#| label: tbl-tableduration\n#| tbl-cap: Temps nécessaire pour lire les données en fonction du type de fichiers\n#| echo: false\n#| message: false\n#| warning: false\nDureeImportation <- data.frame(\n \"fonction\" = c(\"read.csv\" , \"read.dbf\" , \"read.spss\" , \"read.dta\",\n 'read.sas7bdat',\"read.xlsx\" , \"read.xlsx2\"),\n \"duree\" = c(d1, d2, d3, d4, d5, d6, d7)\n\n)\n\nknitr::kable(DureeImportation, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n digits = 2, \n col.names = c(\"Fonction\", \"Durée (secondes)\"),\n align= c(\"r\", \"l\")\n\t\t )\n```\n\n### Manipulation d'un *DataFrame* {#sec-0142}\n\nUne fois le *DataFrame* chargé, voyons comment il est possible de le manipuler.\n\n#### Petit mot sur le `tidyverse` {#sec-01421}\n\n`tidyverse` est un ensemble de *packages* conçus pour faciliter la structuration et la manipulation des données dans R. Avant d'aller plus loin, il est important d'aborder brièvement un débat actuel dans la Communauté R. Entre 2010 et 2020, l'utilisation du `tidyverse` s'est peu à peu répandue. Développé et maintenu par Hadley Wickham, `tidyverse` introduit une philosophie et une grammaire spécifiques qui diffèrent du langage R traditionnel. Une partie de la communauté a pour ainsi dire complètement embrassé le `tidyverse` et de nombreux *packages*, en dehors du `tidyverse`, ont adopté sa grammaire et sa philosophie. À l'inverse, une autre partie de la communauté est contre cette évolution ([voir l'article du blogue suivant](https://blog.ephorie.de/why-i-dont-use-the-tidyverse){target=\"_blank\"}). Les arguments pour et contre `tidyverse` sont résumés dans le (@tbl-Tidyverse). \n\n\n```{r}\n#| label: tbl-Tidyverse\n#| tbl-cap: Avantages et inconvénients du tidyverse\n#| echo: false\n#| message: false\n#| warning: false\n\ndf <- data.frame(\n Pour = c(\"Simplicité d'écriture et d'apprentissage\",\n \"Ajout de l'opérateur `%>%` permettant d'enchaîner les traitements\",\n \"La meilleure librairie pour réaliser des graphiques : `ggplot2`\",\n \"Crée un écosystème cohérent\",\n \"*Package* en développement et de plus en plus utilisé\"),\n Contre = c(\"Nouvelle syntaxe à apprendre\",\n \"Perte de lisibilité avec l'opérateur `->`\",\n \"Remplacement de certaines fonctions de base par d'autres provenant du `tidyverse` lors de son chargement, pouvant créer des erreurs.\",\n \"Ajout d'une dépendance dans le code\",\n \"Philosophie d'évolution agressive, aucune assurance de rétrocompatibilité\")\n)\n\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Avantage du tidyverse\",\n \"Problème posé par le tidyverse\"),\n align= c(\"l\", \"l\"),\n col.to.resize = c(1,2), \n col.width = \"7cm\")\n```\n\n\nLe dernier point est probablement le plus problématique. Dans sa volonté d'évoluer au mieux et sans restriction, le *package* `tidyverse` n'offre aucune garantie de rétrocompatibilité. En d'autres termes, des changements importants peuvent être introduits d'une version à l'autre rendant potentiellement obsolète votre ancien code. Nous n'avons pas d'opinion tranchée sur le sujet : `tidyverse` est un outil très intéressant dans de nombreux cas; nous évitons simplement de l'utiliser systématiquement et préférons charger directement des sous-*packages* (comme `dplyr` ou `ggplot2`) du `tidyverse`. Notez que le *package* `data.table` offre une alternative au `tidyverse` dans la manipulation de données. Au prix d'une syntaxe généralement un peu plus complexe, le package `data.table` offre une vitesse de calcul bien supérieure au `tidyverse` et assure une bonne rétrocompatibilité.\n\n\n#### Gestion des colonnes d'un *DataFrame* {#sec-01422}\n\nRepartons du *DataFrame* que nous avions chargé précédemment en important un fichier *csv*.\n\n```{r}\n#| message: false\n#| warning: false\ndf <- read.csv(file=\"data/priseenmain/SR_MTL_2016.csv\", \n header = TRUE, sep = \",\", dec = \".\",\n stringsAsFactors = FALSE)\n```\n\n##### Sélection d'une colonne {#sec-014221}\n\nRappelons qu'il est possible d'accéder aux colonnes dans ce *DataFrame* en utilisant le symbole dollar `$ma_colonne` ou les doubles crochets `[[\"ma_colonne\"]]`.\n\n```{r}\n#| message: false\n#| warning: false\n# Calcul de la superficie totale de l'Île de Montréal\nsum(df$KM2)\nsum(df[[\"KM2\"]])\n```\n\n##### Sélection de plusieurs colonnes {#sec-014222}\n\nIl est possible de sélectionner plusieurs colonnes d'un *DataFrame* et de filtrer ainsi les colonnes inutiles. Pour cela, nous pouvons utiliser un vecteur contenant soit les positions des colonnes (1 pour la première colonne, 2 pour la seconde et ainsi de suite), soit les noms des colonnes.\n\n```{r}\n#| message: false\n#| warning: false\n# Conserver les 5 premières colonnes\ndf2 <- df[1:5]\n\n# Conserver les colonnes 1, 5, 10 et 15\ndf3 <- df[c(1,5,10,15)]\n\n# Cela peut aussi être utilisé pour changer l'ordre des champs\ndf3 <- df[c(10,15,1,5)]\n\n# Conserver les colonnes 1 à 5, 7 à 12, 17 et 22\ndf4 <- df[c(1:5,7:12,17,22)]\n\n# Conserver les colonnes avec leurs noms\ndf5 <- df[c(\"SRIDU\" , \"KM2\" , \"Pop2016\" , \"MaisonIndi\" , \"LoyerMed\")]\n```\n\n##### Suppression de colonnes {#sec-014223}\n\nIl est parfois plus intéressant et rapide de supprimer directement des colonnes plutôt que de recréer un nouveau *DataFrame*. Pour ce faire, nous attribuons la valeur `NULL` à ces colonnes.\n\n```{r}\n#| message: false\n#| warning: false\n# Supprimer les colonnes 2, 3 et 5\ndf3[c(2,3,5)] <- list(NULL)\n\n# Supprimer une colonne avec son nom\ndf4$OID <- NULL\n\n# Supprimer plusieurs colonnes par leur nom\ndf5[c(\"SRIDU\" , \"LoyerMed\")] <- list(NULL)\n```\n\nNotez que si vous supprimez une colonne, vous ne pouvez pas revenir en arrière. Il faudra recharger votre jeu de données ou éventuellement relancer les calculs qui avaient produit cette colonne.\n\n##### Modification du nom des colonnes {#sec-014224}\n\nIl est possible de changer le nom d'une colonne. Cette opération est importante pour faciliter la lecture du *DataFrame* ou encore s'assurer que l'exportation du *DataFrame* dans un format particulier (tel que *.dbf* qui ne supporte que les noms de colonnes avec moins de 10 caractères) ne posera pas de problème.\n\n```{r}\n#| message: false\n#| warning: false\n# Voici les noms des colonnes\nnames(df5)\n\n# Renommer toutes les colonnes\nnames(df5) <- c('superficie_km2','population_2016', 'maison_individuelle_prt')\nnames(df5)\n\n# Renommer avec dplyr\nlibrary(dplyr)\ndf4 <- rename(df4, \"population_2016\" = \"Pop2016\",\n \"prs_moins_14ans_prt\" = \"A014\",\n \"prs_15_64_ans_prt\" = \"A1564\",\n \"prs_65plus_ans_prt\" = \"A65plus\"\n )\n```\n\n\n#### Calcul de nouvelles variables {#sec-01423}\n\nIl est possible d'utiliser les colonnes de type numérique pour calculer de nouvelles colonnes en utilisant les opérateurs mathématiques vus dans la [section @sec-0135]. Prenons un exemple concret : calculons la densité de population par secteur de recensement dans notre *DataFrame*, puis affichons un résumé de cette nouvelle variable.\n\n```{r}\n#| message: false\n#| warning: false\n# Calcul de la densité\ndf$pop_density_2016 <- df$Pop2016 / df$KM2\n\n# Statistiques descriptives\nsummary(df$pop_density_2016)\n```\n\nNous pouvons aussi calculer le ratio entre le nombre de maisons et le nombre d'appartements.\n\n```{r}\n#| message: false\n#| warning: false\n\n# Calcul du ratio\ndf$total_maison <- (df$MaisonIndi + df$MaisJumule + df$MaisRangee + df$AutreMais)\ndf$total_apt <- (df$AppDuplex + df$App5Moins + df$App5Plus)\ndf$ratio_maison_apt <- df$total_maison / df$total_apt\n```\n\nRetenez ici que R applique le calcul à chaque ligne de votre jeu de données et stocke le résultat dans une nouvelle colonne. Cette opération est du calcul vectoriel : toute la colonne est calculée en une seule fois. R est d'ailleurs optimisé pour le calcul vectoriel.\n\n#### Fonctions mathématiques {#sec-01424}\n\nR propose un ensemble de fonctions de base pour effectuer du calcul. Voici une liste non exhaustive des principales fonctions : \n\n* `abs` calcule la valeur absolue de chaque valeur d'un vecteur;\n\n* `sqrt` calcule la racine carrée de chaque valeur d'un vecteur;\n\n* `log` calcule le logarithme de chaque valeur d'un vecteur;\n\n* `exp` calcule l'exponentielle de chaque valeur d'un vecteur;\n\n* `factorial` calcule la factorielle de chaque valeur d'un vecteur;\n\n* `round` arrondit la valeur d'un vecteur;\n\n* `ceiling`, `floor` arrondit à l'unité supérieure ou inférieure de chaque valeur d'un vecteur;\n\n* `sin`, `asin`, `cos`, `acos`, `tan`, `atan` sont des fonctions de trigonométrie;\n\n* `cumsum` calcule la somme cumulative des valeurs d'un vecteur.\n\nCes fonctions sont des fonctions vectorielles puisqu'elles s'appliquent à tous les éléments d'un vecteur. Si votre vecteur en entrée comprend cinq valeurs, le vecteur en sortie comprendra aussi cinq valeurs.\n\nÀ l'inverse, les fonctions suivantes s'appliquent directement à l'ensemble d'un vecteur et ne vont renvoyer qu'une seule valeur :\n\n* `sum` calcule la somme des valeurs d'un vecteur;\n\n* `prod` calcule le produit des valeurs d'un vecteur;\n\n* `min`, `max` renvoient les valeurs maximale et minimale d'un vecteur;\n\n* `mean`, `median` renvoient la moyenne et la médiane d'un vecteur;\n\n* `quantile` renvoie les percentiles d'un vecteur.\n\n#### Fonctions pour manipuler des chaînes de caractères {#sec-01425}\n\nOutre les données numériques, vous aurez à travailler avec des données de type texte (`string`). Le `tidyverse` avec le *package* `stringr` offre des fonctions très intéressantes pour manipuler ce type de données. Pour un aperçu de toutes les fonctions offertes par `stringr`, référez-vous à sa [*Cheat Sheet*](https://github.com/rstudio/cheatsheets/blob/master/strings.pdf){target=\"_blank\"}. Commençons avec un *DataFrame* assez simple comprenant des adresses et des noms de personnes.\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(stringr)\n\ndf <- data.frame(\n noms = c(\"Jérémy Toutanplace\" , \"constant Tinople\" , \"dino Resto\" , \"Luce tancil\"),\n adresses = c('15 rue Levy', '413 Blvd Saint-Laurent', '3606 rue Duké', '2457 route St Marys')\n)\n```\n\n##### Majuscules et minuscules {#sec-014251}\n\nPour harmoniser ce *DataFrame*, nous mettons, dans un premier temps, des majuscules à la première lettre des prénoms et des noms des individus avec la fonction `str_to_title`.\n\n```{r}\n#| message: false\n#| warning: false\ndf$noms_corr <- str_to_title(df$noms)\nprint(df$noms_corr)\n```\n\nNous pourrions également tout mettre en minuscules ou tout en majuscules.\n\n```{r}\n#| message: false\n#| warning: false\ndf$noms_min <- tolower(df$noms)\ndf$noms_maj <- toupper(df$noms)\nprint(df$noms_min)\nprint(df$noms_maj)\n```\n\n##### Remplacement du texte {#sec-014252}\n\nLes adresses comprennent des caractères accentués. Ce type de caractères cause régulièrement des problèmes d'encodage. Nous pourrions alors décider de les remplacer par des caractères simples avec la fonction `str_replace_all`.\n\n```{r}\n#| message: false\n#| warning: false\ndf$adresses_1 <- str_replace_all(df$adresses,'é','e')\nprint(df$adresses_1)\n```\n\nLa même fonction peut être utilisée pour remplacer les *St* par *Saint* et les *Blvd* par *Boulevard*.\n\n```{r}\n#| message: false\n#| warning: false\ndf$adresses_2 <- str_replace_all(df$adresses_1,' St ',' Saint ')\ndf$adresses_3 <- str_replace_all(df$adresses_2,' Blvd ',' Boulevard ')\nprint(df$adresses_3)\n```\n\n##### Découpage du texte {#sec-014253}\n\nIl est parfois nécessaire de découper du texte pour en extraire des éléments. Nous devons alors choisir un caractère de découpage. Dans notre exemple, nous pourrions vouloir extraire les numéros civiques des adresses en sélectionnant le premier espace comme caractère de découpage, et en utilisant la fonction `str_split_fixed`.\n\n```{r}\n#| message: false\n#| warning: false\ndf$num_civique <- str_split_fixed(df$adresses_3, ' ', n=2)[,1]\nprint(df$num_civique)\n```\n\nPour être exact, sachez que pour notre exemple, la fonction `str_split_fixed` renvoie deux colonnes de texte : une avec le texte avant le premier espace, soit le numéro civique, et une avec le reste du texte. Le nombre de colonnes est contrôlé par l'argument `n`. Si `n = 1`, la fonction ne fait aucun découpage; avec `n = 2` la fonction découpe en deux parties le texte avec la première occurrence du délimiteur et ainsi de suite. En ajoutant `[,1]` à la fin, nous indiquons que nous souhaitons garder seulement la première des deux colonnes.\n\nIl est également possible d'extraire des parties de texte et de ne garder par exemple que les *N* premiers caractères ou les *N* derniers caractères : \n\n```{r}\n#| message: false\n#| warning: false\n# Ne garder que les 5 premiers caractères\nsubstr(df$adresses_3, start = 1, stop = 5)\n\n# Ne garder que les 5 derniers caractères\nn_caract <- nchar(df$adresses_3)\nsubstr(df$adresses_3, start = n_caract-4, stop = n_caract)\n```\n\nNotez que les paramètres `start` et `stop` de la fonction `substr` peuvent accepter un vecteur de valeurs. Il est ainsi possible d'appliquer une sélection de texte différente à chaque chaîne de caractères dans notre vecteur en entrée. Nous pourrions par exemple vouloir récupérer tout le texte avant le second espace pour garder uniquement le numéro civique et le type de rue.\n\n```{r}\n#| message: false\n#| warning: false\n# Étape 1 : récupérer les positions des espaces pour chaque adresses\npositions <- str_locate_all(df$adresses_3, \" \")\n# Étape 2 : récupérer les positions des seconds espaces\nsec_positions <- sapply(positions, function(i){\n i[2,1]\n})\n# Étape 3 : appliquer le découpage\nsubstr(df$adresses_3, start = 1, stop = sec_positions-1)\n```\n\n\n##### Concaténation du texte {#sec-014254}\n\nÀ l'inverse du découpage, il est parfois nécessaire de concaténer des éléments de texte, ce qu'il est possible de réaliser avec la fonction `paste`.\n\n```{r}\n#| message: false\n#| warning: false\ndf$texte_complet <- paste(df$noms_corr, df$adresses_3, sep = \" : \")\nprint(df$texte_complet)\n```\n\nLe paramètre `sep` permet d'indiquer le ou les caractères à intercaler entre les éléments à concaténer. Notez qu'il est possible de concaténer plus que deux éléments.\n\n```{r}\n#| message: false\n#| warning: false\ndf$ville <- c('Montreal','Montreal','Montreal','Montreal')\npaste(df$noms_corr, df$adresses_3, df$ville, sep = \", \")\n```\n\nSi vous souhaitez concaténer des éléments de texte sans séparateur, la fonction `paste0` peut être plus simple à utiliser.\n\n```{r}\n#| message: false\n#| warning: false\npaste0(\"Please conca\", \"tenate me!\")\n```\n\n#### Manipulation des colonnes de type date {#sec-01426}\n\nNous avons vu que les principaux types de données dans R sont le numérique, le texte, le booléen et le facteur. Il existe d'autres types introduits par différents *packages*. Nous abordons ici les types date et heure (*date* and *time*). Pour les manipuler, nous privilégions l'utilisation du *package* `lubridate` du `tidyverse`. Pour illustrer le tout, nous l'utilisons avec un jeu de données ouvertes de la Ville de Montréal représentant les collisions routières impliquant au moins un cycliste survenues après le 1^er^ janvier 2017.\n\n```{r}\n#| message: false\n#| warning: false\naccidents_df <- read.csv(file=\"data/priseenmain/accidents.csv\", sep = \",\")\nnames(accidents_df)\n```\n\nNous disposons de trois colonnes représentant respectivement l'heure, la date et le nombre de victimes impliquées dans la collision.\n\n##### Du texte à la date {#sec-014261}\n\nActuellement, les colonnes `HEURE_ACCDN` et `DT_ACCDN` sont au format texte. Nous pouvons afficher quelques lignes du jeu de données avec la fonction `head` pour visualiser comment elles ont été saisies.\n\n```{r}\n#| message: false\n#| warning: false\nhead(accidents_df, n = 5)\n```\n\nUn peu de ménage s'impose : les heures sont indiquées comme des périodes d'une heure. Nous utilisons la fonction `str_split_fixed` du *package* `stringr` pour ne garder que la première partie de l'heure (avant le tiret). Ensuite, Nous concaténons l'heure et la date avec la fonction `paste`, puis nous convertissons ce résultat en un objet *date-time*.\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(lubridate)\n\n# Étape 1 : découper la colonne Heure_ACCDN\naccidents_df$heure <- str_split_fixed(accidents_df$HEURE_ACCDN, \"-\", n=2)[,1]\n# Étape 2 : concaténer l'heure et la date\naccidents_df$date_heure <- paste(accidents_df$DT_ACCDN, \n accidents_df$heure,\n sep = ' ')\n# Étape 3 : convertir au format datetime\naccidents_df$datetime <- as_datetime(accidents_df$date_heure,\n format = \"%Y/%m/%d %H:%M:%S\")\n```\n\nPour effectuer la conversion, nous avons utilisé la fonction `as_datetime` du *package* `lubridate`. Elle prend comme paramètre un vecteur de texte et une indication du format de ce vecteur de texte. Il existe de nombreuses façons de spécifier une date et une heure et l'argument *format* permet d'indiquer celle à utiliser. Dans cet exemple, la date est structurée comme suit : \n`année/mois/jour heure:minute:seconde`, ce qui se traduit par le format `%Y/%m/%d %H:%M:%S`.\n\n* %Y signifie une année indiquée avec quatre caractères : 2017;\n\n* %m signifie un mois, indiqué avec deux caractères : 01, 02, 03, ... 12;\n\n* %d signifie un jour, indiqué avec deux caractères : 01, 02, 03, ... 31;\n\n* %H signifie une heure, au format 24 heures avec deux caractères : 00, 02, ... 23;\n\n* %M signifie des minutes indiquées avec deux caractères : 00, 02, ... 59;\n\n* %S signifie des secondes, indiquées avec deux caractères : 00, 02, ... 59.\n\nNotez que les caractères séparant les années, jours, heures, etc. sont aussi à indiquer dans le format. Dans notre exemple, nous utilisons la barre oblique (`/`) pour séparer les éléments de la date et le deux points (`:`) pour l'heure, et une espace pour séparer la date et l'heure.\n\nIl existe d'autres nomenclatures pour spécifier un format *datetime* : par exemple, des mois renseignés par leur nom, l'indication AM-PM, etc. Vous pouvez vous référer à la documentation de la fonction `strptime` (`help(strptime)`) pour explorer les différentes nomenclatures et choisir celle qui vous convient. Bien évidemment, il est nécessaire que toutes les dates de votre colonne soient renseignées dans le même format, pour éviter que la fonction ne retourne la valeur `NA` lorsqu'elle ne peut lire le format. Après toutes ces opérations, rejetons un oeil à notre *DataFrame*.\n\n```{r}\n#| message: false\n#| warning: false\nhead(accidents_df, n = 5)\n```\n\n##### Extraction des informations d'une date {#sec-014262}\n\nÀ partir de la nouvelle colonne `datetime`, nous sommes en mesure d'extraire des informations intéressantes comme : \n\n* le nom du jour de la semaine avec la fonction `weekdays`\n```{r}\n#| message: false\n#| warning: false\naccidents_df$jour <- weekdays(accidents_df$datetime)\n```\n\n* la période de la journée avec les fonctions `am` et `pm` \n```{r}\n#| message: false\n#| warning: false\naccidents_df$AM <- am(accidents_df$datetime)\naccidents_df$PM <- pm(accidents_df$datetime)\nhead(accidents_df[c(\"jour\", \"AM\", \"PM\")], n=5)\n```\n\nIl est aussi possible d'accéder aux sous-éléments d'un *datetime* comme l'année, le mois, le jour, l'heure, la minute et la seconde avec les fonctions `year()`, `month()`,`day()`, `hour()`, `minute()` et `second()`.\n\n##### Calcul d'une durée entre deux *datetime* {#sec-014263}\n\nUne autre utilisation intéressante du format *datetime* est de calculer des différences de temps. Par exemple, nous pourrions utiliser le nombre de minutes écoulées depuis 7 h comme une variable dans une analyse visant à déterminer le moment critique des collisions routières durant l'heure de pointe du matin. \nPour cela, nous devons créer un *datetime* de référence en concaténant la date de chaque observation, et le temps `07:00:00`, qui est notre point de départ.\n\n```{r}\n#| message: false\n#| warning: false\naccidents_df$date_heure_07 <- paste(accidents_df$DT_ACCDN, \n '07:00:00',\n sep = ' ')\naccidents_df$ref_datetime <- as_datetime(accidents_df$date_heure_07,\n format = \"%Y/%m/%d %H:%M:%S\")\n```\nIl ne nous reste plus qu'à calculer la différence de temps entre la colonne *datetime* et notre temps de référence *ref_datetime*.\n\n```{r}\n#| message: false\n#| warning: false\naccidents_df$diff_time <- difftime(accidents_df$datetime,\n accidents_df$ref_datetime,\n units = 'min')\n```\n\nNotez qu'ici la colonne *diff_time* est d'un type spécial : une différence temporelle (*difftime*). Il faut encore la convertir au format numérique pour l'utiliser avec la fonction `as.numeric`. Par curiosité, réalisons rapidement un histogramme avec la fonction `hist` pour analyser rapidement cette variable d'écart de temps!\n\n```{r}\n#| label: fig-fig015\n#| fig-cap: Répartition temporelle des accidents à vélo\n#| warning: false\n#| fig.align: \"center\"\n#| out.width: \"65%\"\n\naccidents_df$diff_time_num <- as.numeric(accidents_df$diff_time)\nhist(accidents_df$diff_time_num, breaks = 50)\n```\n\nNous observons clairement deux pics, un premier entre 0 et 100 (entre 7 h et 8 h 30 environ) et un second plus important entre 550 et 650 (entre 16 h et 17 h 30 environ), ce qui correspond sans surprise aux heures de pointe (@fig-fig015). Il est intéressant de noter que plus d'accidents se produisent à l'heure de pointe du soir qu'à celle du matin.\n\n##### Fuseau horaire {#sec-014264}\n\nLorsque nous travaillons avec des données provenant de différents endroits dans le monde ou que nous devons tenir compte des heures d'été et d'hiver, il convient de tenir compte du fuseau horaire. Pour créer une date avec un fuseau horaire, il est possible d'utiliser le paramètre `tz` dans la fonction `as_datetime` et d'utiliser l’identifiant du fuseau approprié. Dans notre cas, les données d'accident ont été collectées à Montréal, qui a un décalage de -5 heures par rapport au temps de référence UTC (+1 heure en été). Le code spécifique de ce fuseau horaire est *EDT*; il est facile de trouver ces codes avec le site web [timeanddate.com](https://www.timeanddate.com/time/map/).\n\n```{r}\n#| message: false\n#| warning: false\naccidents_df$datetime <- as_datetime(accidents_df$date_heure,\n format = \"%Y/%m/%d %H:%M:%S\",\n tz = \"EDT\")\n```\n\n#### Recodage des variables {#sec-01427}\n\nRecoder une variable signifie changer ses valeurs selon une condition afin d'obtenir une nouvelle variable. Si nous reprenons le jeu de données précédent sur les accidents à vélo, nous pourrions vouloir créer une nouvelle colonne nous indiquant si la collision a eu lieu en heures de pointe ou non. Nous obtiendrions ainsi une nouvelle variable avec seulement deux catégories plutôt que la variable numérique originale. Nous pourrions aussi définir quatre catégories avec l'heure de pointe du matin, l'heure de pointe du soir, le reste de la journée et la nuit.\n\n##### Cas binaire avec `ifelse` {#sec-014271}\n\nSi nous ne souhaitons créer que deux catégories, le plus simple est d'utiliser la fonction `ifelse`. Cette fonction évalue une condition ([section @sec-0135]) pour chaque ligne d'un *DataFrame* et produit un nouveau vecteur. Créons donc une variable binaire indiquant si une collision a eu lieu durant les heures de pointe ou hors heures de pointe. Nous devons alors évaluer les conditions suivantes : \n\nEst-ce que l'accident a eu lieu entre 7 h (0) **ET** 9 h (120), **OU** entre 16 h 30 (570) **ET** 18 h 30 (690)?\n\n```{r}\n#| message: false\n#| warning: false\ntable(is.na(accidents_df$diff_time_num))\n```\n\nNotons dans un premier temps que nous avons 40 observations sans valeur pour la colonne `diff_time_num`. Il s'agit d'observations pour lesquelles nous ne disposions pas de dates au départ.\n\n```{r}\n#| message: false\n#| warning: false\nCond1 <- accidents_df$diff_time_num >= 0 & accidents_df$diff_time_num <= 120\nCond2 <- accidents_df$diff_time_num >= 570 & accidents_df$diff_time_num <= 690\n\naccidents_df$moment_bin <- ifelse(Cond1 | Cond2,\n \"en heures de pointe\",\n \"hors heures de pointe\")\n```\n\nComme vous pouvez le constater, la fonction `ifelse` nécessite trois arguments : \n\n* une condition, pouvant être `TRUE` ou `FALSE`;\n\n* la valeur à renvoyer si la condition est `FALSE`;\n\n* la valeur à renvoyer si la condition est `TRUE`.\n\nAvec la fonction `table`, nous pouvons rapidement visualiser les effectifs des deux catégories ainsi créées : \n\n```{r}\n#| message: false\n#| warning: false\ntable(accidents_df$moment_bin)\n\n# Vérifier si nous avons toujours seulement 40 NA\ntable(is.na(accidents_df$moment_bin))\n```\nLes heures de pointe représentent quatre heures de la journée, ce qui nous laisse neuf heures hors heures de pointe entre 7 h et 20 h.\n\n```{r}\n#| message: false\n#| warning: false\n# Ratio de collisions routières en heures de pointe\n(841 / 2414) / (4 / 13)\n\n# Ratio de collisions routières hors heure de pointe\n(1573 / 2414) / (9 / 13)\n```\n\nEn rapportant les collisions aux durées des deux périodes, nous observons une nette surreprésentation des collisions impliquant un vélo pendant les heures de pointe d'environ 13 % comparativement à la période hors des heures de pointe.\n\n##### Cas multiple avec la `case_when` {#sec-014272}\n\nLorsque nous souhaitons créer plus que deux catégories, il est possible soit d'enchaîner plusieurs fonctions `ifelse` (ce qui produit un code plus long et moins lisible), soit d'utiliser la fonction `case_when` du *package* `dplyr` du `tidyverse`. Reprenons notre exemple et créons quatre catégories : \n\n* en heures de pointe du matin;\n\n* en heures de pointe du soir;\n\n* le reste de la journée (entre 7 h et 20 h);\n\n* la nuit (entre 21 h et 7 h).\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(dplyr)\n\naccidents_df$moment_multi <- case_when(\n accidents_df$diff_time_num >= 0 & accidents_df$diff_time_num <= 120 ~ \"pointe matin\",\n accidents_df$diff_time_num >= 570 & accidents_df$diff_time_num <= 690 ~ \"pointe soir\",\n accidents_df$diff_time_num > 690 & accidents_df$diff_time_num < 780 ~ \"journee\",\n accidents_df$diff_time_num > 120 & accidents_df$diff_time_num < 570 ~ \"journee\",\n accidents_df$diff_time_num < 0 | accidents_df$diff_time_num >= 780 ~ \"nuit\"\n)\n\ntable(accidents_df$moment_multi)\n\n# Vérifions encore les NA\ntable(is.na(accidents_df$moment_multi))\n```\n\nLa syntaxe de cette fonction est un peu particulière. Elle accepte un nombre illimité (ou presque) d'arguments. Chaque argument est composé d'une condition et d'une valeur à renvoyer si la condition est vraie; ces deux éléments étant reliés par le symbole `~`. Notez que toutes les évaluations sont effectuées dans l'ordre des arguments. En d'autres termes, la fonction teste d'abord la première condition et assigne ses valeurs, puis recommence pour les prochaines conditions. Ainsi, si une observation (ligne du tableau de données) obtient `TRUE` à plusieurs conditions, elle obtient au final la valeur de la dernière condition validée. Dans l'exemple précédent, si la première condition est `accidents_df$diff_time_num >= 0 | accidents_df$diff_time_num <= 120`, alors nous obtenons pour seule valeur en résultat `\"pointe matin\"` puisque chaque observation a une valeur supérieure à 0 et que nous avons remplacé l'opérateur `&` (ET) par l'opérateur `|` (OU). \n\n#### Sous-sélection d'un *DataFrame* {#sec-01428}\n\nDans cette section, nous voyons comment extraire des sous-parties d'un *DataFrame*. Il est possible de sous-sélectionner des lignes et des colonnes en se basant sur des conditions ou leur index. Pour cela, nous utilisons un jeu de données fourni avec R : le jeu de données **iris** décrivant des fleurs du même nom.\n\n```{r}\n#| message: false\n#| warning: false\ndata(\"iris\")\n\n# Nombre de lignes et de colonnes\ndim(iris)\n```\n\n##### Sous-sélection des lignes {#sec-014281}\n\nSous-sélectionner des lignes par index est relativement simple. Admettons que nous souhaitons sélectionner les lignes 1 à 5, 10 à 25, 37 et 58.\n\n```{r}\n#| message: false\n#| warning: false\nsub_iris <- iris[c(1:5, 10:25, 37, 58),]\nnrow(sub_iris)\n```\n\nSous-sélectionner des lignes avec une condition peut être effectué soit avec une syntaxe similaire, soit en utilisant la fonction `subset`. Sélectionnons toutes les fleurs de l'espèce Virginica.\n\n```{r}\n#| message: false\n#| warning: false\niris_virginica1 <- iris[iris$Species == \"virginica\",]\niris_virginica2 <- subset(iris, iris$Species == \"virginica\")\n\n# Vérifions que les deux DataFrames ont le même nombre de lignes\nnrow(iris_virginica1) == nrow(iris_virginica2)\n```\n\nVous pouvez utiliser, dans les deux cas, tous les opérateurs vus dans les sections [-@sec-01351] et [-@sec-01353]. L'enjeu est d'arriver à créer un vecteur booléen final permettant d'identifier les observations à conserver.\n\n##### Sous-sélection des colonnes {#sec-014282}\n\nNous avons déjà vu comment sélectionner des colonnes en utilisant leur nom ou leur index dans la [section @sec-014221]. Ajoutons ici un cas particulier où nous souhaitons sélectionner des colonnes selon une condition. Par exemple, nous pourrions vouloir conserver que les colonnes comprenant le mot *Length*. Pour cela, nous utilisons la fonction `grepl`, permettant de déterminer si des caractères sont présents dans une chaîne de caractères.\n\n```{r}\n#| message: false\n#| warning: false\nnom_cols <- names(iris)\nprint(nom_cols)\n\ntest_nom <- grepl(\"Length\", nom_cols, fixed = TRUE)\nok_nom <- nom_cols[test_nom]\n\niris_2 <- iris[ok_nom]\nprint(names(iris_2))\n```\n\nIl est possible d'obtenir ce résultat en une seule ligne de code, mais elle est un peu moins lisible.\n\n```{r}\n#| message: false\n#| warning: false\niris2 <- iris[names(iris)[grepl(\"Length\", names(iris), fixed = TRUE)]]\n```\n\n##### Sélection des colonnes et des lignes {#sec-014283}\n\nNous avons vu qu'avec les crochets `[]`, nous pouvons extraire les colonnes et les lignes d'un *DataFrame*. Il est possible de combiner les deux opérations simultanément. Pour ce faire, il faut indiquer en premier les index ou la condition permettant de sélectionner une ligne, puis les index ou la condition pour sélectionner les colonnes : `[index_lignes , index_colonnes]`. Sélectionnons cinq premières lignes et les trois premières colonnes du jeu de données iris : \n\n```{r}\n#| message: false\n#| warning: false\niris_5x3 <- iris[c(1,2,3,4,5), c(1,2,3)]\nprint(iris_5x3)\n```\n\nCombinons nos deux exemples précédents pour sélectionner uniquement les lignes avec des fleurs de l'espèce *virginica*, et les colonnes avec le mot *Length*.\n\n```{r}\n#| message: false\n#| warning: false\niris_virginica3 <- iris[iris$Species == \"virginica\",\n names(iris)[grepl(\"Length\", names(iris), fixed = TRUE)]]\nhead(iris_virginica3, n=5)\n```\n\n#### Fusion de *DataFrames* {#sec-01429}\n\nTerminons cette section avec la fusion de *DataFrames*. Nous distinguons deux méthodes répondant à des besoins différents : par ajout ou par jointure.\n\n##### Fusion de *DataFrames* par ajout {#sec-014291}\n\nAjouter deux *DataFrames* peut se faire en fonction de leurs colonnes ou en fonction de leurs lignes. Dans ces deux cas, nous utilisons respectivement les fonctions `cbind` et `rbind`. La @fig-fig016 résume graphiquement le fonctionnement des deux fonctions.\n\n![Fusion de DataFrames](images/Chap01/rbind_cbind.png){#fig-fig016 width=\"30%\" fig-align=\"center\"}\n\nPour que `cbind` fonctionne, il faut que les deux *DataFrames* aient le même nombre de lignes. Pour `rbind`, les deux *DataFrames* doivent avoir le même nombre de colonnes. Prenons à nouveau comme exemple le jeu de données iris. Nous commençons par le séparer en trois sous-jeux de données comprenant chacun une espèce d'iris. Puis, nous fusionnons deux d'entre eux avec la fonction `rbind`.\n\n```{r}\n#| message: false\n#| warning: false\niris1 <- subset(iris, iris$Species == \"virginica\")\niris2 <- subset(iris, iris$Species == \"versicolor\")\niris3 <- subset(iris, iris$Species == \"setosa\")\n\niris_comb <- rbind(iris2,iris3)\n```\n\nNous pourrions aussi extraire dans les deux *DataFrames* les colonnes comprenant le mot *Length* et le mot *Width*, puis les fusionner.\n\n```{r}\n#| message: false\n#| warning: false\niris_l <- iris[names(iris)[grepl(\"Length\", names(iris), fixed = TRUE)]]\niris_w <- iris[names(iris)[grepl(\"Width\", names(iris), fixed = TRUE)]]\n\niris_comb <- cbind(iris_l,iris_w)\nnames(iris_comb)\n```\n\n##### Jointure de *DataFrames* {#sec-014292}\n\nUne jointure est une opération un peu plus complexe qu'un simple ajout. L'idée est d'associer des informations de plusieurs *DataFrames* en utilisant une colonne (appelée une clef) présente dans les deux jeux de données. Nous distinguons plusieurs types de jointure : \n\n* Les jointures internes permettant de combiner les éléments communs entre deux *DataFrames* A **et** B.\n\n* La jointure complète permettant de combiner les éléments présents dans A **ou** B.\n\n* La jointure à gauche, permettant de ne conserver que les éléments présents dans A même s'ils n'ont pas de correspondance dans B.\n\nCes trois jointures sont présentées à la @fig-fig017; pour ces trois cas, la colonne commune se nomme *id*.\n\n\n![Jointure de DataFrames](images/Chap01/merging.png){#fig-fig017 width=\"30%\" fig-align=\"center\"}\n\nVous retiendrez que les deux dernières jointures peuvent produire des valeurs manquantes. Pour réaliser ces opérations, nous utilisons la fonction `merge`. Prenons un exemple simple à partir d'un petit jeu de données.\n\n```{r}\n#| message: false\n#| warning: false\nauteurs <- data.frame(\n name = c(\"Tukey\", \"Venables\", \"Tierney\", \"Ripley\", \"McNeil\", \"Apparicio\"),\n nationality = c(\"US\", \"Australia\", \"US\", \"UK\", \"Australia\", \"Canada\"),\n retired = c(\"yes\", rep(\"no\", 5)))\nlivres <- data.frame(\n aut = c(\"Tukey\", \"Venables\", \"Tierney\", \"Ripley\", \"Ripley\", \"McNeil\" , \"Wickham\"),\n title = c(\"Exploratory Data Analysis\",\n \"Modern Applied Statistics ...\",\n \"LISP-STAT\",\n \"Spatial Statistics\", \"Stochastic Simulation\",\n \"Interactive Data Analysis\", \"R for Data Science\"))\n```\n\nNous avons donc deux *DataFrames*, le premier décrivant des auteurs et le second des livres. Effectuons une première jointure interne afin de savoir pour chaque livre la nationnalité de son auteur et si ce dernier est à la retraite.\n\n```{r}\n#| message: false\n#| warning: false\ndf1 <- merge(livres, auteurs, #les deux DataFrames \n by.x = \"aut\", by.y = \"name\", #les noms des colonnes de jointures\n all.x = FALSE, all.y = FALSE)\nprint(df1)\n```\n\nCette jointure est interne, car les deux paramètres *all.x* et *all.y* ont pour valeur `FALSE`. Ainsi, nous indiquons à la fonction que nous ne souhaitons ni garder tous les éléments du premier *DataFrame* ni tous les éléments du second, mais uniquement les éléments présents dans les deux. Vous noterez ainsi que le livre \"R for Data Science\" n'est pas présent dans le jeu de données final, car son auteur \"Wickham\" ne fait pas partie du *DataFrame* auteurs. De même, l'auteur \"Apparicio\" n'apparaît pas dans la jointure, car aucun livre dans le *DataFrame* books n'a été écrit par cet auteur.\n\nPour conserver tous les livres, nous pouvons effectuer une jointure à gauche en renseignant `all.x = TRUE`. Nous forçons ainsi la fonction à garder tous les livres et à mettre des valeurs vides aux informations manquantes des auteurs.\n\n```{r}\n#| message: false\n#| warning: false\ndf2 <- merge(livres, auteurs, #les deux DataFrames \n by.x = \"aut\", by.y = \"name\", #les noms des colonnes de jointures\n all.x = TRUE, all.y = FALSE)\nprint(df2)\n```\n\nPour garder tous les livres et tous les auteurs, nous pouvons faire une jointure complète en indiquant `all.x = TRUE` et `all.y = TRUE`.\n\n```{r}\n#| message: false\n#| warning: false\ndf3 <- merge(livres, auteurs, #les deux DataFrames \n by.x = \"aut\", by.y = \"name\", #les noms des colonnes de jointures\n all.x = TRUE, all.y = TRUE)\nprint(df3)\n```\n\n## Code R bien structuré {#sec-016}\n\nTerminons ici avec quelques conseils sur la rédaction d’un code R. Bien rédiger son code est essentiel pour trois raisons :\n\n1. Pouvoir relire et réutiliser son code dans le futur.\n2. Permettre à d'autres personnes de bien lire et de réutiliser votre code.\n3. Minimiser les risques d'erreurs.\n\nNe négligez pas l'importance d'un code bien rédigé et bien documenté, vous vous éviterez ainsi des migraines lorsque vous devrez exhumer du code écrit il y a plusieurs mois.\n\nVoici quelques lignes directrices peu contraignantes, mais qui devraient vous être utiles : \n\n1. **Privilégier la clarté à la concision** : il vaut mieux parfois scinder une ligne de code en plusieurs sous-étapes afin de faciliter la lecture de l’opération réalisée. Par exemple, si nous reprenons une ligne de code d’une section précédente où nous sélectionnions l'ensemble des colonnes du jeu de données `iris` comprenant le mot `Length` : \n```{r}\n#| message: false\n#| warning: false\niris_l <- iris[names(iris)[grepl(\"Length\", names(iris), fixed = TRUE)]]\n```\n\nNous pouvons simplifier la lecture de ce code en détaillant les différentes étapes comme suit : \n\n```{r}\n#| message: false\n#| warning: false\nnoms_cols <- names(iris)\nsel_noms <- noms_cols[grepl(\"Length\", noms_cols, fixed = TRUE)]\niris_l <- iris[sel_noms]\n```\n\n2. **Documenter et commenter son code le plus possible** : il est possible d'ajouter du texte dans un code R qui ne sera pas exécuté, ce que nous appelons des commentaires. Typiquement, une ligne commençant par un `#` n'est pas interprétée par le logiciel. Utilisez des commentaires le plus souvent possible pour décrire les actions que vous souhaitez effectuer avec votre code. Il sera ainsi plus facile de le relire, de naviguer dedans, mais également de repérer d'éventuelles erreurs. Si nous reprenons l'exemple précédent : \n\n```{r}\n#| message: false\n#| warning: false\n# Récupération du nom des colonnes dans le DataFrame iris\nnoms_cols <- names(iris)\n# Sélection des colonnes avec les caractères \"Length\"\nsel_noms <- noms_cols[grepl(\"Length\", noms_cols, fixed = TRUE)]\n# Extraction des colonnes sélectionnées dans un nouveau DataFrame\niris_l <- iris[sel_noms]\n```\n\n3. **Éviter le code à rallonge…** : typiquement, essayez de vous limiter à des lignes de code d'une longueur maximale de 80 caractères. Au-delà de ce seuil, il est judicieux de découper votre code en plusieurs lignes.\n\n4. **Adopter une convention d'écriture** : une convention d'écriture est un ensemble de règles strictes définissant comment un code doit être rédigé. À titre d'exemple, il est parfois recommandé d'utiliser le *lowerCamelCase*, le *UpperCamelCase*, ou encore de séparer les mots par des tirets bas *upper_camel_case*. Un mélange de ces différentes conventions peut être utilisé pour distinguer les variables, les fonctions et les classes. Il peut être difficile de réellement arrêter une telle convention, car les différents *packages* dans R utilisent des conventions différentes. Dans vos propres codes, il est surtout important d'avoir une certaine cohérence et ne pas changer de convention.\n\n5. **Indenter le code** : l'indentation du code permet de le rendre beaucoup plus lisible. Indenter son code signifie d'insérer, au début de chaque ligne de code, un certain nombre d'espaces permettant d'indiquer à quel niveau de profondeur nous nous situons. Typiquement, lorsque des accolades ou des parenthèses sont ouvertes dans une fonction, une boucle ou une condition, nous rajoutons deux ou quatre espaces en début de ligne. Prenons un exemple très concret : admettons que nous écrivons une fonction affichant un résumé statistique à chaque colonne d'un jeu de données si cette colonne est de type numérique. L'indentation dans cette fonction joue un rôle crucial dans sa lisibilité. \nSans indentation et sans respecter la règle des 80 caractères, nous obtenons ceci : \n\n```{r}\n#| message: false\n#| warning: false\nsummary_all_num_cols <- function(dataset){for(col in names(dataset)){if(class(dataset[[col]] == \"numeric\")){print(summary(dataset[[col]]))}}}\n```\n\nAvec de l'indentation et des commentaires, la syntaxe est beaucoup plus lisible puisqu’elle permet de repérer facilement trois niveaux/paliers dans le code : \n\n```{r}\n#| message: false\n#| warning: false\n# Définition d'une fonction\nsummary_all_num_cols <- function(dataset){\n # Itération sur chaque colonne de la fonction\n for(col in names(dataset)){\n # A chaque itération, testons si la colonne est de type numérique\n if(class(dataset[[col]] == \"numeric\")){\n # Si oui, nous affichons un résumé statistique pour cette colonne\n print(summary(dataset[[col]]))\n } # Ici nous sortons de la condition (niveau 3)\n } # Ici nous sortons de la boucle (niveau 2)\n} # Ici nous sortons de la fonction (niveau 1)\n```\n\n6. **Adopter une structure globale pour vos scripts** : un code R peut être comparé à une recette de cuisine. Si tous les éléments sont dans le désordre et sans structure globale, la recette risque d'être très difficile à suivre. Cette structure risque de changer quelque peu en fonction de la recette ou de l'auteur(e), mais les principaux éléments restent les mêmes. Dans un code R, nous pouvons distinguer plusieurs éléments récurrents que nous vous recommandons d'organiser de la façon suivante : \n \n a. Charger les différents *packages* **utilisés** par le script. Cela permet dès le début du code de savoir quelles sont les fonctions et méthodes qui seront employées dans le script. Cela limite aussi les risques d'oublier des *packages* qui seraient chargés plus loin dans le code.\n \n b. Définir les fonctions dont vous aurez besoin en plus de celles présentes dans les *packages.* Idem, placer nos fonctions en début de code évite d'oublier de les charger ou de les chercher quand nous en avons besoin.\n \n c. Définir le répertoire de travail avec la fonction `setwd` et charger les données nécessaires.\n \n d. Effectuer au besoin les opérations de manipulation sur les données.\n \n e. Effectuer les analyses nécessaires en scindant si possible les différentes étapes. Notez également que l'étape de définition des fonctions complémentaires peut être effectuée dans une feuille de code séparée, et l'ensemble de ces fonctions chargées à l'aide de la fonction `source`. De même, si la manipulation des données est conséquente, il est recommandé de l'effectuer avec un code à part, d'enregistrer les données structurées, puis de les charger directement au début de votre code dédié à l'analyse.\n\n7. **Exploiter les commentaires délimitant les sections dans RStudio** : il est possible d'écrire des commentaires d'une certaine façon pour que l'IDE les détecte comme des délimiteurs de sections. L'intérêt principal est que nous pouvons ensuite facilement naviguer entre ces sections en utilisant RStudio comme montré à la @fig-sectionsRstudio, mais aussi masquer des sections afin de faciliter la lecture du reste du code. Pour délimiter une section, il suffit d'ajouter une ligne de commentaire comprenant quatre fois les caractères `-`, `=` ou `#` à la suite. \n\n\n```{r}\n#| echo: true\n#| eval: false\n\n# Voici ma section 1 ----------------------------------\n\n# Voici ma section 2 ==================================\n\n# Voici ma section 3 ##################################\n\n# Autre exemple pour mieux marquer la rupture dans un code : \n\n#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n#### Titre de ma section 4 ####\n#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n```\n\n![Navigation dans des sections de codes avec RStudio](images/Chap01/sections_rstudio.png){#fig-sectionsRstudio width=\"100%\" fig-align=\"center\"}\n\n8. **Adopter une structure globale pour vos projets** : au-delà du script, il est nécessaire de bien structurer vos projets, le plus important étant d'utiliser une structure commune à chaque projet pour vous faciliter le travail. Nous proposons à la @fig-structFolder un exemple de structure assez générale pouvant être utilisée dans la plupart des cas. Elle sépare notamment les données originales des données structurées, ainsi que les fonctions complémentaires et la structuration des données du principal bloc d'analyse.\n\n\n![Structure de dossier recommandée pour un projet avec R](images/Chap01/structurationprojet.png){#fig-structFolder width=\"50%\" fig-align=\"center\"}\n\n\n**Ne négligez jamais l'importance d'un code bien écrit et documenté !**\n\n## Enregistrement des résultats {#sec-017}\n\nComme nous l'avons indiqué précédemment, l'ensemble des objets actuellement chargés dans votre session R sont perdus si vous la fermez. Cela peut être problématique si certains résultats nécessitent de longs temps de calcul ou si vous avez besoin de partager les objets obtenus avec d'autres personnes, mais pas le code pour les obtenir. Il est possible de retrouver les résultats d'une session précédente si ceux-ci ont été enregistrés sur votre disque dur puisque l'action d'enregistrer permet de faire passer vos objets présents dans votre mémoire vive dans des fichiers stockés sur votre disque dur. Vous pouvez pour cela utiliser la fonction `save.image` ou `save`.\n\n`save.image` enregistre une copie exacte de votre session actuelle avec tous les objets présents dans votre environnement dans un fichier `RData`. La fonction `save` permet d'être plus sélectif et de ne garder que certains objets spécifiques.\n\nVoici la syntaxe pour enregistrer toute votre session :\n\n```{r}\n#| eval: false\nsave.image(file = 'chemin/vers/mon/fichier/session.RData', compress = TRUE)\n```\n\nVous pouvez aussi utiliser le bouton d'enregistrement dans l'onglet *Environnement* dans RStudio (@fig-saveobj).\n\n\n![Bouton enregistrer la session](images/Chap01/save_session.png){#fig-saveobj width=\"25%\" fig-align=\"center\"}\n\nIl est recommandé de compresser ces fichiers (`compress = TRUE`) pour minimiser leur taille. Pour n'enregistrer que certains objets (ici `iris` et `noms_cols`), vous pouvez adapter cette syntaxe :\n\n```{r}\n#| eval: false\nsave(iris, noms_cols, file = 'chemin/vers/mon/fichier/mes_objet.RData', compress = TRUE)\n```\n\nPour récupérer ces objets dans une autre session, il suffit d'utiliser la fonction `load` :\n\n```{r}\n#| eval: false\nload(file = 'chemin/vers/mon/fichier/mes_objet.RData')\n```\n\nou d'utiliser le bouton *ouvrir* de l'onglet *Environnement* dans RStudio (@fig-loadobj).\n\n![Bouton charger un fichier RDA](images/Chap01/load_session.png){#fig-loadobj width=\"25%\" fig-align=\"center\"}\n\n## Session de travail {#sec-018}\n\nComme vous avez pu le constater dans les sections @sec-017 et @sec-0141, il est nécessaire de connaître les chemins vers les fichiers que vous souhaitez utiliser dans votre code R. Si tous ces fichiers sont organisés dans un même dossier (ce que nous vous recommandons à la @fig-structFolder, il est possible de définir un répertoire de travail avec la fonction `setwd`.\nIl est recommandé d'effectuer cette étape au début de votre code R, après le chargement des *packages*. Ainsi, vous n'aurez pas besoin de réécrire à chaque fois le chemin complet pour accéder à vos fichiers.\n\n```{r}\n#| eval: false\n# Chemin complet\nmes_donnes <- read.csv(\"C:/projets/articles/2022/mon_projet/data/mes_donnes.csv\")\n# Utilisation de setwd\nsetwd(\"C:/projets/articles/2022/mon_projet\")\nmes_donnes <- read.csv(\"data/mes_donnes.csv\")\n```\n\nLa fonction `getwd` permet d'afficher le répertoire de travail utilisé actuellement par R.\n\nSi vous utilisez RStudio, il est possible d'utiliser une petite astuce pour définir comme répertoire de travail le dossier dans lequel se trouve le fichier de code R que vous utilisez actuellement :\n\n```{r}\n#| eval: false\nsetwd(dirname(rstudioapi::getActiveDocumentContext()$path))\n```\n\nAdmettons que votre code R se trouve dans un sous dossier appelé *CodeR* de votre répertoire de travail, vous pouvez remonter d'un niveau dans votre arborescence en utilisant la syntaxe suivante :\n\n```{r}\n#| eval: false\nsetwd(paste0(dirname(rstudioapi::getActiveDocumentContext()$path), \"/..\"))\n```\n\nLe double point (`..`) indique que nous souhaitons remonter dans le dossier parent du dossier dans lequel nous se trouvons acutellement.\n\nIl existe deux solutions de rechange à l'utilisation de `setwd` que certains jugent un peu démodé.\n\n* La première est le package `here` permettant de spécifier plus facilement des chemins relatifs et de définir un *top-level directory* pour votre projet.\n* La seconde est l'utilisation de la fonctionnalité [projects](https://support.rstudio.com/hc/en-us/articles/200526207-Using-Projects) de RStudio.\n\n## Conclusion et ressources pertinentes {#sec-019}\n\nVoilà qui conclut ce chapitre sur les bases du langage R. Vous avez maintenant les connaissances nécessaires pour commencer à travailler. N'hésitez pas à revenir sur les différentes sous-sections au besoin! Quelques ressources pertinentes qui pourraient vous être utiles sont aussi reportées au @tbl-tableRessources \n\n\n```{r}\n#| label: tbl-tableRessources\n#| tbl-cap: Ressources pertinente pour en apprendre plus sur R\n#| echo: false\n#| message: false\n#| warning: false\n\ndf <- data.frame(\n Ressource = c(\"[Rbloggers](https://www.r-bloggers.com){target='_blank'}\" , \"[CRAN packages by date](https://cran.r-project.org/web/packages/available_packages_by_date.html){target='_blank'}\", \"[Introduction à R et au TidyVerse](https://juba.github.io/tidyverse/index.html){target='_blank'}\", \"[Numyard](https://www.youtube.com/user/TheLearnR/featured){target='_blank'}\", \"[cheatsheets](https://rstudio.com/resources/cheatsheets){target='_blank'}\"), \n Description = c(\"Un recueil de nombreux blogues sur R : parfait pour être tenu au courant des nouveautés et faire des découvertes.\", \"Les derniers packages publiés sur *CRAN* : cela permet de garder un oeil sur les nouvelles fonctionnalités de vos packages préférés.\", \"Une excellente ressource en français pour en apprendre plus sur le tidyverse.\", \"Une chaîne YouTube pour revoir les bases de R en vidéo.\", \"Des feuilles de triche résumant les fonctionnalités de nombreux packages.\"))\n\nknitr::kable(df,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Ressource\" , \"Description\"),\n col.to.resize = c(2,3),\n col.width = \"6cm\")\n```\n\n## Quiz de révision du chapitre {#sec-0110}\n\n```{r}\n#| label: quizChapitre01\n#| echo: false\n#| warning: false\n#| results: asis\nsource(\"code_complementaire/QuizzFunctions.R\")\nChap01Quiz <- quizz(\"quiz/Chapitre1_manipulerdesdonnees.yml\", \"Chap01\")\nrender_quizz(Chap01Quiz)\n```\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"01-priseenmainR.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/02-univarie.qmd.json b/.quarto/idx/02-univarie.qmd.json new file mode 100644 index 0000000..04f66e5 --- /dev/null +++ b/.quarto/idx/02-univarie.qmd.json @@ -0,0 +1 @@ +{"title":"Statistiques descriptives univariées","markdown":{"headingText":"Statistiques descriptives univariées","headingAttr":{"id":"sec-chap02","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nComprendre la notion de variable et de ses différents types est essentiel en statistiques. En effet, en fonction du type de variable à l'étude, les méthodes de statistique exploratoire ou inférentielle sont différentes. Nous distinguons ainsi cinq types de variables : nominale, ordinale, discrète, continue et semi-quantitative. Aussi, nous abordons un concept central de la statistique : les distributions. Finalement, dans ce chapitre, nous présentons les différentes statistiques descriptives univariées qui peuvent s’appliquer à ces types de variables.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes quantiles-quantiles.\n* Pour créer des distributions :\n - `fitdistrplus` pour générer différentes distributions.\n - `actuar` pour la fonction de densité de Pareto.\n - `gamlss.dist` pour des distributions de Poisson.\n* Pour les statistiques descriptives :\n - `stats` et `moments` pour les statistiques descriptives.\n - `nortest` pour le test de Kolmogorov-Smirnov.\n - `DescTools` pour les tests de Lilliefors, Shapiro-Wilk, Anderson-Darling et Jarque-Bera.\n* Autres *packages* :\n - `Hmisc` et `Weighted.Desc.Stat` pour les statistiques descriptives pondérées.\n - `foreign` pour importer des fichiers externes.\n:::\n:::\n\n## Notion et types de variable {#sec-021}\n\n### Notion de variable {#sec-0211}\n\nD'un point de vue empirique, une variable est une propriété, une caractéristique d'une unité statistique, d'une observation. Il convient alors de bien saisir à quelle unité d'analyse (ou unité d'observation) s'appliquent les valeurs d'une variable : des personnes, des ménages, des municipalités, des entreprises, etc. Par exemple, pour des individus, l'*âge*, le *genre* ou encore le *revenu* sont autant de caractéristiques qui peuvent être mesurées à partir de variables. Autrement dit, une variable permet de mesurer un phénomène (dans un intervalle de valeurs, c'est-à-dire de manière quantitative) ou de le qualifier (avec plusieurs catégories, c'est-à-dire de manière qualitative).\n\nD'un point de vue plus théorique, une variable permet d'opérationnaliser un concept en sciences sociales [@gilles1994elements, p.30], soit une « idée générale et abstraite que se fait l'esprit humain d'un objet de pensée concret ou abstrait, et qui lui permet de rattacher à ce même objet les diverses perceptions qu'il en a, et d'en organiser les connaissances » ([Larousse](https://www.larousse.fr/dictionnaires/francais/concept/17875?q=concept#17749){target=\"_blank\"}). En effet, la construction d'un modèle théorique suppose d'opérationnaliser différents concepts et d'établir les relations qu'ils partagent entre eux. Or, l'opérationnalisation d'un concept nécessite soit de mesurer (dans un intervalle de valeurs, c'est-à-dire de manière quantitative), soit de qualifier (avec plusieurs catégories, c'est-à-dire de manière qualitative) un phénomène. \n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Maîtriser la définition des variables que vous utilisez : un enjeu crucial! **\n:::\n::: bloc_attention-body\nNe pas maîtriser la définition d'une variable revient à ne pas bien saisir la caractéristique ou encore le concept sous-jacent qu'elle tente de mesurer. Si vous exploitez des données secondaires – par exemple, issues d'un recensement de population ou d'une enquête longitudinale ou transversale –, il faut impérativement lire les définitions des variables que vous souhaitez utiliser. Ne pas le faire risque d'aboutir à :\n\n* Une mauvaise opérationnalisation de votre modèle théorique, même si votre analyse est bien menée statistiquement parlant. Autrement dit, vous risquez de ne pas sélectionner les bonnes variables : prenons un exemple concret. Vous avez construit un modèle théorique dans lequel vous souhaitez inclure un concept sur la langue des personnes. Dans le recensement canadien de 2016, plusieurs variables relatives à la langue sont disponibles : [connaissance des langues officielles, langue parlée à la maison, langue maternelle, première langue officielle parlée, connaissance des langues non officielles et langue de travail] (https://www12.statcan.gc.ca/census-recensement/2016/ref/guides/003/98-500-x2016003-fra.cfm). La sélection de l'une de ces variables doit être faite de manière rigoureuse, c'est-à-dire en lien avec votre cadre théorique et suite à une bonne compréhension des définitions des variables. Dans une étude sur le marché du travail, nous sélectionnerions probablement la variable *sur la connaissance des langues officielles du Canada*, afin d'évaluer son effet sur l'employabilité, toutes choses étant égales par ailleurs. Dans une autre étude portant sur la réussite ou la performance scolaire, il est probable que nous utiliserions la *langue maternelle*.\n\n* Une mauvaise interprétation et discussion de vos résultats en lien avec votre cadre théorique.\n\n* Une mauvaise identification des pistes de recherche.\n\nFinalement, la définition d'une variable peut évoluer à travers plusieurs recensements de population : la société évolue, les variables aussi! Par conséquent, si vous comptez utiliser plusieurs années de recensement dans une même étude, assurez-vous que les définitions des variables sont similaires d'un jeu de données à l'autre et qu'elles mesurent ainsi la même chose. \n\n**Comprendre les variables utilisées dans un article scientifique : un exercice indispensable dans l'élaboration d'une revue de littérature**\n\nUne lecture rigoureuse d'un article scientifique suppose, entre autres, de bien comprendre les concepts et les variables mobilisés. Il convient alors de lire attentivement la section méthodologique (pas uniquement la section des résultats ou pire, celle du résumé), sans quoi vous risquez d'aboutir à une revue de littérature approximative. \nAyez aussi un **regard critique** sur les variables utilisées en lien avec le cadre théorique. Certains concepts sont très difficiles à traduire en variables; leurs opérationnalisations (mesures) peuvent ainsi faire l'objet de vifs débats au sein de la communauté scientifique. Très succinctement, c'est notamment le cas du concept de capital social. D'une part, les définitions et ancrages sont bien différents selon Bourdieu (sociologue, ancrage au niveau des individus) et Putman (politologue, ancrage au niveau des collectivités); d'autre part, aucun consensus ne semble clairement se dégager quant à la définition de variables permettant de mesurer le capital social efficacement (de manière quantitative). \n\n**Variable de substitution (*proxy variable* en anglais)**\n\nNous faisons la moins pire des recherches! En effet, les données disponibles sont parfois imparfaites pour répondre avec précision à une question de recherche; nous pouvons toujours les exploiter, tout en signalant honnêtement leurs faiblesses et limites, et ce, tant pour les données que pour les variables utilisées.\n\n* Des bases de données peuvent être en effet imparfaites. Par exemple, en criminologie, lorsqu'une étude est basée sur l'exploitation de données policières, la limite du **chiffre noir** est souvent signalée : les données policières comprennent uniquement les crimes et délits découverts par la police et occultent ainsi les crimes non découverts; ils ne peuvent ainsi refléter la criminalité réelle sur un territoire donné.\n\n* Des variables peuvent aussi être imparfaites. Dans un jeu de données, il est fréquent qu'une variable ne soit pas disponible ou qu'elle n'ait tout simplement pas été mesurée. Nous cherchons alors une variable de substitution (*proxy*) pour la remplacer. Prenons un exemple concret portant sur l'exposition des cyclistes à la pollution atmosphérique ou au bruit environnemental. L'un des principaux facteurs d'exposition à ces pollutions est le trafic routier : plus ce dernier est élevé, plus les cyclistes risquent de rouler dans un environnement bruyant et pollué. Toutefois, il est rare de disposer de mesures du trafic en temps réel qui nécessitent des comptages de véhicules pendant le trajet des cyclistes (par exemple, à partir de vidéos captées par une caméra fixée sur le guidon). Pour pallier l'absence de mesures directes, plusieurs auteur(e)s utilisent des variables de substitution de la densité du trafic, comme la typologie des types d'axes (primaire, secondaire, tertiaire, rue locale, etc.), supposant ainsi qu'un axe primaire supporte un volume de véhicules supérieur à un axe secondaire.\n:::\n:::\n\n### Types de variables {#sec-0212}\nNous distinguons habituellement les variables qualitatives (nominale ou ordinale) des variables quantitatives (discrète ou continue). Comme illustré à la @fig-univarie1, plusieurs mécanismes différents visent à qualifier, à classer, à compter ou à mesurer afin de caractériser les unités statistiques (observations) d'une population ou d'un échantillon.\n\n![Types de variables](images/Chap02/figure1.jpg){#fig-univarie1 width=\"70%\" fig-align=\"center\"}\n\n\n#### Variables qualitatives {#sec-02121}\n\n**Une variable nominale** permet de **qualifier** des observations (individus) à partir de plusieurs catégories dénommées modalités. Par exemple, la variable _couleur des yeux_ pourrait comprendre les modalités _bleu_, _marron_, _vert_, _noir_ tandis que le *type de famille* comprendrait les modalités _couple marié_, _couple en union libre_ et _famille monoparentale_.\n\n**Une variable ordinale** permet de **classer** des observations à partir de plusieurs modalités hiérarchisées. L'exemple le plus connu est certainement l'échelle de Likert, très utilisée dans les sondages évaluant le degré d'accord d'une personne à une affirmation avec les modalités suivantes : *tout à fait d'accord*, *d'accord*, *ni en désaccord ni d'accord*, *pas d'accord* et *pas du tout d'accord*. Une multitude de variantes sont toutefois possibles pour classer la fréquence d'un phénomène (*très souvent*, *souvent*, *parfois*, *rarement*, *jamais*), l'importance accordée à un phénomène (*pas du tout important*, *peu important*, *plus ou moins important*, *important*, *très important*) ou la proximité perçue d'un lieu (*très éloigné*, *loin*, *plus ou moins proche*, *proche*, *très proche*).\n\nEn fonction du nombre de modalités qu'elle comprend, une variable qualitative (nominale ou ordinale) est soit **dichotomique (binaire)** (deux modalités), soit **polytomique** (plus de deux modalités). Par exemple, dans le recensement canadien, le *sexe* est une variable binaire (avec les modalités *sexe masculin*, *sexe féminin*), tandis que le *genre* est une variable polytomique (avec les modalités *genre masculin*, *genre féminin* et *diverses identités de genre*).\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Fréquences pour des variables nominales et ordinales**\n:::\n::: bloc_attention-body\nLes variables nominales et ordinales sont habituellement encodées avec des valeurs numériques entières (par exemple, 1 pour _couple marié_, 2 pour _couple en union libre_ et 3 pour _famille monoparentale_). Toutefois, aucune opération arithmétique (moyenne ou écart-type par exemple) n'est possible sur ces valeurs. Dans R, nous utilisons un facteur pour attribuer un intitulé à chacune des valeurs numériques de la variable qualitative :\n\n`df$Famille <- factor(df$Famille, c(1,2,3), \nlabels = c(\"couple marié\" , \"couple en union libre\", \"famille monoparentale\"))`\n\nNous calculons toutefois les fréquences des différentes modalités pour une variable nominale ou ordinale. Il est aussi possible de calculer la médiane sur une variable ordinale.\n:::\n:::\n\n\n\n#### Variables quantitatives {#sec-02122}\n\n**Une variable discrète** permet de **compter** un phénomène dans un ensemble fini de valeurs, comme le nombre d'accidents impliquant un ou une cycliste à une intersection sur une période de cinq ans ou encore le nombre de vélos en libre-service disponibles à une station. Il existe ainsi une variable binaire sous-jacente : la présence ou non d'un accident à l'intersection ou la disponibilité d'un vélo ou non à la station pour laquelle nous opérons un comptage. Habituellement, une variable discrète ne peut prendre que des valeurs entières (sans décimale), comme le nombre de personnes fréquentant un parc.\n\n**Une variable continue** permet de **mesurer** un phénomène avec un nombre infini de valeurs réelles (avec décimales) dans un intervalle donné. Par exemple, une variable relative à la distance de dépassement d'un ou d'une cycliste par un véhicule motorisé pourrait varier de 0 à 5 mètres ($X \\in \\left[0,5\\right]$); toutefois, cette distance peut être de 0,759421 ou de 4,785612 mètres. Le nombre de décimales de la valeur réelle dépend de la précision et de la fiabilité de la mesure. Pour un capteur de distance de dépassement, le nombre de décimales dépend de la précision du lidar ou du sonar de l'appareil; aussi, l'utilisation de trois décimales – soit une précision au millimètre – est largement suffisante pour mesurer la distance de dépassement. De plus, une variable continue est soit une variable d'intervalle, soit une variable de rapport. Les **variables d'intervalle** ont une échelle relative, c'est-à-dire que les intervalles entre les valeurs de la variable ne sont pas constants; elles n'ont pas de vrai zéro. Autrement dit, ce type de variable a une échelle relative avec un zéro arbitraire. Ces valeurs peuvent être manipulées uniquement par addition et soustraction et non par multiplication et division. La variable d'intervalle la plus connue est certainement celle de la température. S'il fait 10 degrés Celsius à Montréal et 30 °C à Mumbai (soit 50 et 86 degrés en Fahrenheit), nous pouvons affirmer qu'il y a 20 °C ou 36 °F d'écart entre les deux villes, mais ne pouvons pas affirmer qu'il fait trois fois plus chaud à Mumbai. Presque toutes les mesures statistiques sur une variable d'intervalle peuvent être calculées, excepté le coefficient de variation et la moyenne géométrique puisqu'il n'y a pas de vrai zéro ni d'intervalles constants entre les valeurs. À l'inverse, les **variables de rapport** ont une échelle absolue, c'est-à-dire que les intervalles entre les valeurs sont constants et elles ont un vrai zéro. Elles peuvent ainsi être manipulées par addition, soustraction, multiplication et division. Par exemple, le prix d'un produit exprimé dans une unité monétaire ou la distance exprimée dans le système métrique sont des variables de rapport. Un vélo dont le prix affiché est de 1000 \\$ est bien deux fois plus cher qu'un autre à 500 \\$, une piste cyclable hors rue à 25 mètres du tronçon routier le plus proche est bien quatre fois plus proche qu'une autre à 100 mètres.\n\n**Une variable semi-quantitative**, appelée aussi variable quantitative ordonnée, est une variable discrète ou continue dont les valeurs ont été regroupées en classes hiérarchisées. Par exemple, l'âge est une variable continue pouvant être transformée avec les groupes d'âge ordonnés suivants : *moins 25 ans*, *25 à 44 ans*, *45 à 64 ans* et *65 ans et plus*.\n\n\n## Types de données {#sec-022}\n\nDifférents types de données sont utilisés en sciences sociales. L'objectif ici n'est pas de les décrire en détail, mais plutôt de donner quelques courtes définitions. En fonction de votre question de recherche et des bases des données disponibles, il s'agit de sélectionner le ou les types de données les plus appropriés à votre étude.\n\n### Données secondaires *versus* données primaires {#sec-0221}\n\nLes **données secondaires** sont des données qui existent déjà au début de votre projet de recherche : nul besoin de les collecter, il suffit de les exploiter! Une multitude de données de recensements ou d'enquêtes de Statistique Canada sont disponibles et largement exploitées en sciences sociales (par exemple, l'enquête nationale auprès des ménages – ENM, l'enquête sur la dynamique du marché du travail et du revenu – EDTR, l'enquête longitudinale auprès des immigrants – ELIC, etc.). \n\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Accès aux microdonnées**\n:::\n::: bloc_notes-body\nAu Canada, les personnes qui font de la recherche, qui étudient ou qui enseignent, ont accès aux microdonnées des enquêtes de Statistique Canada dans les centres de données de recherche (CDR). Vous pouvez consulter le moteur de recherche du Réseau canadien des Centres de données de recherche (https://crdcn.org/fr/donn%C3%A9es) afin d'explorer les différentes enquêtes disponibles.\n\nAu Québec, l'accès à ces enquêtes est possible dans les différentes antennes du Centre interuniversitaire québécois de statistiques sociales de Statistique Canada (https://www.ciqss.org/).\n:::\n:::\n\nPar opposition, les **données primaires** n'existent pas quand vous démarrez votre projet : vous devez les collecter spécifiquement pour votre étude! Par exemple, une chercheuse souhaitant analyser l'exposition des cyclistes au bruit et à la pollution dans une ville donnée doit réaliser une collecte de données avec idéalement plusieurs personnes participantes (équipées de différents capteurs), et ce, sur plusieurs jours. \nUne collecte de données primaires peut aussi être réalisée avec une enquête par sondage. Brièvement, réaliser une collecte de données primaires nécessite différentes phases complexes comme la définition de la méthode de collecte et de la population à l'étude, l’estimation de la taille de l'échantillon, la validation des outils de collecte avec une phase de test, la réalisation de la collecte, la structuration, la gestion et l'exploitation de données collectées. Finalement, dans le milieu académique, une collecte de données primaires auprès d'individus doit être approuvée par le comité d'éthique de la recherche de l'université à laquelle est affiliée la personne responsable du projet de recherche.\n\n### Données transversales *versus* données longitudinales {#sec-0222}\nLes **données transversales** sont des mesures pour une période relativement courte. L’exemple classique est un jeu de données constitué des variables extraites d’un recensement de population pour une année donnée (comme celui de 2016 de Statistique Canada). \n\nLes **données longitudinales**, appelées aussi données par panel, sont des mesures répétées pour plusieurs observations au cours du temps (*N* observations pour *T* dates). Par exemple, des observations pourraient être des pays, les dates pourraient être différentes années (de 1990 à 2019) pour lesquelles différentes variables seraient disponibles (population totale, taux d’urbanisation, produit intérieur brut par habitant, émissions de gaz à effet de serre par habitant, etc.).\n\n### Données spatiales versus données aspatiales {#sec-0223}\n\nLes observations des **données spatiales** sont des unités spatiales géoréférencées. Elles peuvent être par exemple :\n\n* des points *(x, y)* ou *(lat-long)* représentant des entreprises avec plusieurs variables (adresse, date de création, nombre d'employés, secteurs d'activité, etc.);\n\n* les lignes représentant des tronçons de rues pour lesquels plusieurs variables sont disponibles (type de rue, longueur en mètres, nombre de voies, débit journalier moyen annuel, etc.);\n\n* des polygones délimitant des régions ou des arrondissements pour lesquels une multitude de variables sociodémographiques et socioéconomiques sont disponibles;\n \n* les pixels des bandes spectrales d'une image satellite.\n\nÀ l’inverse, aucune information spatiale n’est disponible pour des **données aspatiales**. \n\n\n### Données individuelles *versus* données agrégées {#sec-0224}\n\nComme son nom l'indique, pour des **données individuelles**, chaque observation correspond à un individu. Les microdonnées de recensements ou d'enquêtes, par exemple, sont des données individuelles pour lesquelles toute une série de variables est disponible. Une étude analysant les caractéristiques de chaque arbre d'un quartier nécessite aussi des données individuelles : l'information doit être disponible pour chaque arbre. Pour les microdonnées des recensements canadiens, « chaque enregistrement au niveau de la personne comprend des identifiants (comme les identifiants du ménage et de la famille), des variables géographiques et des variables directes et dérivées tirées du questionnaire » ([Statistique Canada](https://www150.statcan.gc.ca/n1/pub/12-002-x/2012001/article/11642-fra.htm){target=\"_blank\"}). Comme signalé plus haut, ces microdonnées de recensements ou d'enquêtes sont uniquement accessibles dans les centres de données de recherche (CDR).\n\nLes données individuelles peuvent être **agrégées** à un niveau supérieur. Prenons le cas de microdonnées d'un recensement. Les informations disponibles pour chaque individu sont agrégées par territoire géographique (province, région économique, division de recensement, subdivision de recensement, région et agglomération de recensement, secteurs de recensement, aires de diffusion, etc.) en fonction du lieu de résidence des individus. Des sommaires statistiques – basés sur la moyenne, la médiane, la somme ou la proportion de chacune des variables mesurées au niveau individuel (âge, sexe, situation familiale, revenu, etc.) – sont alors construits pour ces différents découpages géographiques ([Statistique Canada](https://www.statcan.gc.ca/fra/idd/trousse/section5#a4){target=\"_blank\"}).\n\nL'agrégation n'est pas nécessairement géographique. En éducation, il est fréquent de travailler avec des données concernant les élèves, mais agrégées au niveau des écoles. La @fig-univarie1b donne un exemple simple d'agrégation de données individuelles.\n\n![Exemple d'agrégation de données individuelles](images/Chap02/aggregation.png){#fig-univarie1b width=\"65%\" fig-align=\"center\"}\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Erreur écologique et erreur atomiste**: attention aux interprétations abusives\n:::\n::: bloc_attention-body\nIl convient d'être prudent dans l'analyse des données agrégées. Très fréquente en géographie, l'**erreur écologique** (*ecological fallacy* en anglais) est une mauvaise interprétation des résultats. Elle consiste à attribuer des constats obtenus à partir de données agrégées pour un territoire aux individus qui forment la population de ce territoire. À l'inverse, attribuer des résultats à partir de données individuelles à des territoires est une **erreur atomiste**.\n\nPrenons un exemple concret tiré d'une étude récente sur la localisation des écoles primaires et le bruit aérien dans la région métropolitaine de Toronto [@audrin2021localisation]. Un des objectifs de cette étude est de vérifier si les écoles primaires (ns = 1420) avec des niveaux de bruit aérien élevés présentent des niveaux de réussite scolaire plus faibles. Les résultats de leur étude démontrent que les enfants scolarisés dans les écoles primaires avec à des niveaux élevés de bruit aérien sont issus de milieux plus défavorisés et ont plus souvent une langue maternelle autre que la langue d'enseignement. Aussi, les écoles avec des niveaux de bruit aérien élevés présentent des niveaux de réussite scolaire plus faibles. \n\nToutefois, étant donné que les variables sur la réussite scolaire sont mesurées au niveau de l'école (soit les pourcentages d’élèves ayant atteint ou dépassé la norme provinciale en lecture, en écriture et en mathématique, respectivement pour la 3^e^ année et la 6^e^ année) et non au niveau individuel, nous ne pouvons pas conclure que le bruit aérien à un impact significatif sur la réussite scolaire des élèves :\n\n« Nous avons pu démontrer que les écoles primaires localisées dans la zone NEF 25 présentent des taux de réussite plus faibles. Rappelons toutefois qu’une association obtenue avec des données agrégées ne peut pas nous permettre de conclure à une influence directe au niveau individuel, car l’agrégation des données entraîne une perte d’information. Cette erreur d’interprétation dite erreur écologique (*ecological fallacy*) tend à laisser penser que les associations entre les groupes s’appliquent à chaque individu (Robinson, 1950). Nos résultats gagneraient à être corroborés à partir d’analyses reposant sur des données individuelles ».\n:::\n:::\n\n\nPour le cas de l'agrégation géographique, il convient alors de bien comprendre la hiérarchie des régions géographiques délimitées par l’organisme ou l’agence ayant la responsabilité de produire, de gérer et de diffuser les données des recensements et des enquêtes, puis de sélectionner le découpage géographique qui répond le mieux à votre question de recherche.\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\nHiérarchie et définitions des régions géographiques du recensement canadien\n:::\n::: bloc_astuce-body\n* la [hiérarchie des régions géographiques normalisées pour la diffusion](https://www12.statcan.gc.ca/census-recensement/2016/ref/dict/figures/f1_1-fra.cfm)\n\n* le [glossaire illustré](https://www150.statcan.gc.ca/n1/pub/92-195-x/92-195-x2016001-fra.htm) des régions géographiques\n\n* [les différents profils du recensement de 2021](https://www12.statcan.gc.ca/census-recensement/2021/dp-pd/prof/index.cfm?Lang=F) à télécharger pour les différentes régions géographiques.\n:::\n:::\n\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Les différents types de données abordés ci-dessus ne sont pas exclusifs.**\n:::\n::: bloc_notes-body\nPar exemple, des données pour des régions administratives extraites de plusieurs recensements sont en fait des données secondaires, spatiales, agrégées et longitudinales. \n\nDes données sur la pollution atmosphérique et sonore collectées à vélo (avec différents capteurs et un GPS) sont des données spatiales primaires.\n:::\n:::\n\n\n\n\n## Statistique descriptive et statistique inférentielle {#sec-023}\n\n### Population, échantillon et inférence {#sec-0231}\n\nLes notions de **population** et d'**échantillon** sont essentielles en statistique puisqu'elles sont le socle de l'inférence statistique.\nUn échantillon est un **sous-ensemble représentatif** d'une population donnée. Prenons un exemple concret : une chercheuse veut comprendre la mobilité des personnes étudiant dans une université. Bien entendu, elle ne peut interroger toutes les personnes étudiantes de son université. Elle devra donc s’assurer d'obtenir un échantillon de taille suffisante et représentatif de la population étudiante. Une fois les données collectées (avec un sondage par exemple), elle pourra utiliser des techniques inférentielles pour analyser la mobilité des personnes interrogées. Si son échantillon est représentatif, les résultats obtenus pourront être inférés – c'est-à-dire généralisés, extrapolés – à l’ensemble de la population.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Les méthodes d’échantillonnage**\n:::\n::: bloc_aller_loin-body\nNous n’abordons pas ici les méthodes d’échantillonnage. Sachez toutefois qu’il existe plusieurs méthodes probabilistes pour constituer un échantillon, notamment de manière aléatoire, systématique, stratifiée, par grappes. Consultez par exemple cette [publication de Statistique Canada](https://www150.statcan.gc.ca/n1/edu/power-pouvoir/ch13/prob/5214899-fra.htm).\n:::\n:::\n\nAutre exemple, une autre chercheuse souhaite comprendre les facteurs influençant le sentiment de sécurité des cyclistes dans un quartier. De nouveau, elle ne peut pas enquêter sur l'ensemble des cyclistes du quartier et devra constituer un échantillon représentatif. Par la suite, la mise en œuvre de techniques inférentielles lui permettra d'identifier les caractéristiques individuelles (âge, sexe, habiletés à vélo, etc.) et de l'environnement urbain (types de voies empruntés, niveaux de trafic, de pollution, de bruit, etc.) ayant des effets significatifs sur le sentiment de sécurité. Si l'échantillon est représentatif, les résultats pourront être généralisés à l'ensemble des cyclistes du quartier.\n\n\n### Deux grandes familles de méthodes statistiques {#sec-0232}\n\nNous distinguons habituellement deux grandes familles de méthodes statistiques : la statistique descriptive et exploratoire et la statistiques inférentielle et confirmatoire. Il existe de nombreuses définitions de ces deux branches de la statistique, celles proposées de Lebart et al. [-@lebart1995statistique] étant parmi les plus abouties :\n\n* « **La statistique descriptive et exploratoire** : elle permet, par des résumés et des graphiques plus ou moins élaborés, de décrire des ensembles de données statistiques, d’établir des relations entre les variables sans faire jouer de rôle privilégié à une variable particulière. Les conclusions ne portent dans cette phase de travail que sur les données étudiées, sans être inférées à une population plus large. L’analyse exploratoire s’appuie essentiellement sur des notions élémentaires telles que des indicateurs de moyenne et de dispersion, sur des représentations graphiques. [...]\n\n* **La statistique inférentielle et confirmatoire** : elle permet de valider ou d’infirmer, à partir de tests statistiques ou de modèles probabilistes, des hypothèses formulées a priori (ou après une phase exploratoire), et d’extrapoler, c’est-à-dire d’étendre certaines propriétés d’un échantillon à une population plus large. Les conclusions obtenues à partir des données vont au-delà de ces données. La statistique confirmatoire fait surtout appel aux méthodes dites explicatives et prévisionnelles, destinées, comme leurs noms l’indiquent, à expliquer puis à prévoir, suivant des règles de décision, une variable privilégiée à l’aide d’une ou plusieurs variables explicatives (régressions multiples et logistiques, analyse de variance, analyse discriminante, segmentation, etc.) » [@lebart1995statistique, p.209].\n\n\n## Notion de distribution {#sec-024}\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Les distributions : une notion centrale en statistique**\n:::\n::: bloc_objectif-body\nPrenez le temps de lire cette section à tête reposée et assurez-vous de bien comprendre chaque idée avant de passer à la suivante. N’hésitez pas à y revenir plusieurs fois si nécessaire, car la compréhension de ces concepts est essentielle pour utiliser adéquatement les méthodes que nous abordons dans ce livre.\n:::\n:::\n\n### Définition générale\n\nEn probabilité, nous nous intéressons aux résultats d’expériences. Du point de vue de la théorie des probabilités, lancer un dé, mesurer la pollution atmosphérique, compter le nombre de collisions à une intersection, et demander à une personne d’évaluer son sentiment de sécurité sur une échelle de 1 à 10 sont autant d’expériences pouvant produire des résultats.\n\n**Une distribution est un modèle mathématique permettant d’associer pour chaque résultat possible d’une expérience la probabilité d’obtenir ce résultat**. D'un point de vue pratique, si nous disposons de la distribution régissant l’expérience : « mesurer la concentration d’ozone à Montréal à 13 h en été », nous pouvons calculer la probabilité de mesurer une valeur inférieure à 15 μg/m^3^.\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Loi de probabilité et distribution**\n:::\n::: bloc_attention-body\nL'utilisation que nous faisons ici du terme « distribution » est un anglicisme (éhonté diront certaines personnes). En effet, en français, la définition précédente est plus proche du terme « loi de probabilité ». Cependant, la quasi-totalité de la documentation sur R est en anglais et, dans la pratique, ces deux termes ont tendance à se confondre. Nous avons donc fait le choix de poursuivre avec ce terme dans le reste du livre.\n:::\n:::\n\nUne distribution est toujours définie dans un intervalle en dehors duquel elle n'est définie; les valeurs dans cet intervalle sont appelées **l’espace d’échantillonnage**. Il s’agit donc des valeurs possibles que peut produire l’expérience. La somme des probabilités de l’ensemble des valeurs de l’espace d’échantillonnage est 1 (100 %). Intuitivement, cela signifie que si nous réalisons l’expérience, nous obtenons nécessairement un résultat, et que la somme des probabilités est répartie entre tous les résultats possibles de l’expérience. En langage mathématique, nous disons que l’intégrale de la fonction de densité d'une distribution est 1 dans son intervalle de définition.\n\nPrenons un exemple concret avec l’expérience suivante : tirer à pile ou face avec une pièce de monnaie non truquée. Si l’on souhaite décrire la probabilité d’obtenir pile ou face, nous pouvons utiliser une distribution qui aura comme espace d’échantillonnage [pile; face] et ces deux valeurs auront chacune comme probabilité 0,5. Il est facile d’étendre cet exemple au cas d’un dé à six faces. La distribution de probabilité décrivant l’expérience « lancer le dé » a pour espace d’échantillonnage [1,2,3,4,5,6], chacune de ces valeurs étant associée à la probabilité de 1/6.\n\nChacune des deux expériences précédentes est régie par une distribution appartenant à la famille des distributions **discrètes**. Elles servent à représenter des expériences dont le nombre de valeurs possibles est fini. Par opposition, la seconde famille de distributions regroupe les distributions **continues**, décrivant des expériences dont le nombre de résultats possibles est en principe infini. Par exemple, mesurer la taille d’une personne adulte sélectionnée au hasard peut produire en principe un nombre infini de valeurs. Les distributions sont utiles pour décrire les résultats potentiels d’une expérience. Reprenons notre exemple du dé. Nous savons que chaque face a une chance sur six d’être tirée au hasard. Nous pouvons représenter cette distribution avec un graphique (@fig-fig251). \n\n```{r}\n#| label: fig-fig251\n#| fig-cap: Distribution théorique d'un lancer de dé\n#| echo: false\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"50%\"\nlibrary(ggplot2)\ndf <- data.frame(\n face = 1:6,\n prob_theorique = 1/6\n)\nggplot(mapping = aes(x = face, weight = prob_theorique), data = df) + \n geom_bar()+\n geom_bar()+\n labs(x = \"face du dé\",\n y = \"probabilité\")+\n scale_x_continuous(breaks = c(1,2,3,4,5,6))+\n ylim(c(0,0.5))\n```\n\nNous avons donc sous les yeux un modèle statistique décrivant le comportement attendu d’un dé, soit sa distribution **théorique**. Cependant, si nous effectuons dix fois l’expérience (nous collectons donc un échantillon), nous obtiendrons une distribution différente de cette distribution théorique (@fig-fig252).\n\n```{r}\n#| label: fig-fig252\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution empirique d'un lancer de dé (n = 10)\n#| message: false\n#| warning: false\n#| out-width: \"50%\"\nn <- 10\nresults <- sample(c(1,2,3,4,5,6), size = n, replace = TRUE)\ncounts <- table(results) / n\ndf2 <- data.frame(face = as.numeric(names(counts)),\n prob_exp10 = as.vector(counts))\ndf <- merge(df, df2, by = \"face\", all.x = TRUE)\nggplot(mapping = aes(x = face, weight = prob_exp10), data = df) + \n geom_bar()+\n geom_bar()+\n labs(x = \"face du dé\",\n y = \"probabilité\")+\n scale_x_continuous(breaks = c(1,2,3,4,5,6))+\n ylim(c(0,0.5))\n```\n\nIl s'agit de la distribution **empirique**. Chaque échantillon aura sa propre distribution empirique. Cependant, comme le prédit la loi des grands nombres : si une expérience est répétée un grand nombre de fois, la probabilité empirique d’un résultat se rapproche de la probabilité théorique à mesure que le nombre de répétitions augmente. Du point de vue de la théorie des probabilités, chaque échantillon correspond à un ensemble de tirages aléatoires effectués à partir de la distribution théorique du phénomène étudié. \n\nPour nous en convaincre, collectons trois échantillons de lancer de dé de respectivement 30, 100 et 1000 observations (@fig-fig253). Comme le montre la @fig-fig252, nous connaissons la distribution théorique qui régit cette expérience.\n\n```{r}\n#| label: fig-fig253\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution empirique d'un lancer de dé\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nlibrary(reshape2)\nlibrary(dplyr)\n#### empirical, 30 replications\nn <- 30\nresults <- sample(c(1,2,3,4,5,6), size = n, replace = TRUE)\ncounts <- table(results) / n\ndf3 <- data.frame(face = as.numeric(names(counts)),\n prob_exp30 = as.vector(counts))\ndf <- merge(df, df3, by = \"face\", all.x = TRUE)\n#### empirical, 100 replications\nn <- 100\nresults <- sample(c(1,2,3,4,5,6), size = n, replace = TRUE)\ncounts <- table(results) / n\ndf4 <- data.frame(face = as.numeric(names(counts)),\n prob_exp100 = as.vector(counts))\ndf <- merge(df, df4, by = \"face\", all.x = TRUE)\n#### empirical, 10000 réplications\nn <- 10000\nresults <- sample(c(1,2,3,4,5,6), size = n, replace = TRUE)\ncounts <- table(results) / n\ndf5 <- data.frame(face = as.numeric(names(counts)),\n prob_exp10000 = as.vector(counts))\ndf <- merge(df, df5, by = \"face\", all.x = TRUE)\ndf$prob_theorique <- NULL\n# ploting the resul\ndf_melt <- melt(df,id.vars = c('face'))\ndf_melt$variable <- case_when(\n df_melt$variable == 'prob_theorique' ~ \"distribution théorique\",\n df_melt$variable == 'prob_exp10' ~ \"distribution empirique (n = 10)\",\n df_melt$variable == 'prob_exp30' ~ \"distribution empirique (n = 30)\",\n df_melt$variable == 'prob_exp100' ~ \"distribution empirique (n = 100)\",\n df_melt$variable == 'prob_exp10000' ~ \"distribution empirique (n= 10000)\"\n)\ndf_melt$f_exp <- factor(df_melt$variable,\n levels = c(\"distribution théorique\",\n \"distribution empirique (n = 10)\",\n \"distribution empirique (n = 30)\",\n \"distribution empirique (n = 100)\",\n \"distribution empirique (n = 10000)\"))\nggplot(mapping = aes(x = face, weight = value), data = df_melt)+\n geom_bar()+\n labs(x = \"face du dé\",\n y = \"probabilité\")+\n scale_x_continuous(breaks = c(1,2,3,4,5,6))+\n facet_wrap(vars(f_exp), ncol = 2)\n```\nNous constatons bien qu’au fur et à mesure que la taille de l’échantillon augmente, nous tendons vers la distribution théorique.\n\nCette relation a été étudiée pour la première fois au XVIII^e^ siècle par le mathématicien Daniel Bernoulli, qui a montré que la probabilité que la moyenne d’une distribution empirique soit éloignée de la moyenne de la distribution théorique dont elle est tirée diminuait lorsque nous augmentons le nombre des tirages et donc la taille de l’échantillon. Un autre mathématicien, Siméon-Denis Poisson, a fait connaître cette relation sous le nom de « loi des grands nombres ».\n\nLes distributions théoriques sont utilisées pour modéliser des phénomènes réels et sont à la base de presque tous les tests statistiques d'inférence fréquentiste ou bayésienne. En pratique, la question que nous nous posons le plus souvent est : quelle distribution théorique peut le mieux décrire le phénomène empirique à l’étude? Pour répondre à cette question, deux approches sont possibles :\n\n* Considérant la littérature existante sur le sujet, les connaissances accumulées et la nature de la variable étudiée, sélectionner des distributions théoriques pouvant vraisemblablement correspondre au phénomène mesuré.\n\n* Comparer visuellement ou à l’aide de tests statistiques la distribution empirique de la variable et diverses distributions théoriques pour trouver la plus adaptée.\n\nIdéalement, le choix d’une distribution théorique devrait reposer sur ces deux méthodes combinées.\n\n### Anatomie d'une distribution\n\nUne distribution (ou loi de probabilité) est une fonction. Il est possible de la représenter à l’aide d’une formule mathématique (appelée **fonction de masse** pour les distributions discrètes et **fonction de densité** pour les distributions continues) associant chaque résultat possible de l'expérience régie par la distribution à la probabilité d'observer ce résultat. Prenons un premier exemple concret avec la distribution théorique associée au lancer de pièce de monnaie : la distribution de **Bernoulli**. Sa formule est la suivante :\n\n$$\nf(x ; p)=\\left\\{\\begin{array}{ll}\nq=1-p & \\text { si } x=0 \\\\\np & \\text { si } x=1\n\\end{array}\\right.\n$$ {#eq-Bernoulli}\n\navec *p* la probabilité d’obtenir $x = 1$ (pile), et $1 – p$ la probabilité d’avoir $x = 0$ (face). La distribution de Bernoulli ne dépend que d’un paramètre : *p*. Avec différentes valeurs de *p*, nous pouvons obtenir différentes formes pour la distribution de Bernoulli. Si *p* = 1/2, la distribution de Bernoulli décrit parfaitement l’expérience : obtenir pile à un lancer de pièce de monnaie. Si *p* = 1/6, elle décrit alors l’expérience : obtenir 4 (tout comme n’importe quelle valeur de 1 à 6) à un lancer de dé. Pour un exemple plus appliqué, la distribution de Bernoulli est utilisée en analyse spatiale pour étudier la concentration d’accidents de la route ou de crimes en milieu urbain. À chaque endroit du territoire, il est possible de calculer la probabilité qu’un tel évènement ait lieu ou non en modélisant les données observées au moyen de la loi de Bernoulli.\nLa distribution continue la plus simple à décrire est certainement la distribution **uniforme**. Il s’agit d’une distribution un peu spéciale puisqu’elle attribue la même probabilité à toutes ses valeurs dans son espace d’échantillonnage. Elle est définie sur l’intervalle $[-\\infty; +\\infty]$ et a la fonction de densité suivante : \n\n$$\nf(x ; \\mathrm{a} ; \\mathrm{b})=\\left\\{\\begin{array}{cc}\n\\frac{1}{a-b} & \\text { si } a \\geq x \\geq b \\\\\n0 & \\text { sinon }\n\\end{array}\\right.\n$$ {#eq-Uniforme}\n\nLa fonction de densité de la distribution uniforme a donc deux paramètres, *a* et *b*, représentant respectivement les valeurs maximale et minimale au-delà desquelles les valeurs ont une probabilité 0 d’être obtenues. Pour avoir une meilleure intuition de ce que décrit une fonction de densité, il est intéressant de la représenter avec un graphique (@fig-fig254). Notez que sur ce graphique, l'axe des ordonnées n'indique pas précisément la probabilité associée à chaque valeur, car celle-ci est infinitésimale. Il sert uniquement à représenter la valeur de la fonction de densité de la distribution pour chaque valeur de x.\n\n```{r}\n#| label: fig-fig254\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distributions uniformes continues\n#| out-width: \"60%\"\nggplot()+\n xlim(-18,18)+\n stat_function(aes(color = \"#d90429\"), fun = dunif, \n args = list(min = -15, max = 15), linewidth = 1)+\n stat_function(aes(color = \"#8d99ae\"), fun = dunif, \n args = list(min = -10, max = 10), linewidth = 1)+\n stat_function(aes(color = \"#2b2d42\"), fun = dunif, \n args = list(min = 1, max = 11), linewidth = 1)+\n labs(y = \"densité\",\n x = \"x\",\n title = \"distributions uniforme\")+\n scale_color_identity(name = \"Paramètres\",\n breaks = c(\"#d90429\", \"#8d99ae\", \"#2b2d42\"),\n labels = c(\"a = 15; b = -15\", \"a = 10; b = -10\",\n \"a = 1; b = 11\"),\n guide = \"legend\")\n```\n\nNous observons clairement que toutes les valeurs de *x* entre *a* et *b* ont la même probabilité pour chacune de trois distributions uniformes présentées dans le graphique. Plus l’étendue est grande ($a-b$), plus l’espace d’échantillonnage est grand et plus la probabilité totale est répartie dans cet espace. Cette distribution est donc idéale pour décrire un phénomène pour lequel chaque valeur a autant de chance de se produire qu’une autre. Prenons pour exemple un cas fictif avec un jeu de hasard qui vous proposerait la situation suivante : en tirant sur la manette d’une machine à sous, un nombre est tiré aléatoirement entre -60 et +50. Si le nombre est négatif, vous perdez de l’argent et inversement si le nombre est positif. Nous pouvons représenter cette situation avec une distribution uniforme continue et l’utiliser pour calculer quelques informations essentielles : \n\n1. Selon cette distribution, quelle est la probabilité de gagner de l’argent lors d’un tirage (x > 0)? \n\n2. Quelle est la probabilité de perdre de l’argent (x < 0)?\n\n3. Si je perds moins de 30 $ au premier tirage, quelle est la probabilité que j'ai de récupérer au moins ma mise au second tirage (x > 30)?\n\nIl est assez facile de calculer ces probabilités en utilisant la fonction `punif` dans R. Concrètement, cela permet de calculer l’intégrale de la fonction de masse sur un intervalle donné.\n\n```{r}\n# Probabilité d'obtenir une valeur supérieure ou égale à 0\npunif(0, min = -60, max = 50)\n# Probabilité d'obtenir une valeur inférieure à 0\npunif(0, min = -60, max = 50, lower.tail = FALSE)\n# Probabilité d'obtenir une valeur supérieure à 30\npunif(30, min = -60, max = 50, lower.tail = FALSE)\n```\n\nLes paramètres permettent donc d’ajuster la fonction de masse ou de densité d’une distribution afin de lui permettre de prendre des formes différentes. Certains paramètres changent la localisation de la distribution (la déplacer vers la droite ou la gauche de l’axe des X), d’autres changent son degré de dispersion (distribution pointue ou aplatie) ou encore sa forme (symétrie). Les différents paramètres d’une distribution correspondent donc à sa carte d’identité et donnent une idée précise sur sa nature.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Fonction de répartition, de survie et d'intensité**\n:::\n::: bloc_aller_loin-body\nSi les fonctions de densité ou de masse d'une distribution sont le plus souvent utilisées pour décrire une distribution, d'autres types de fonctions peuvent également être employées et disposent de propriétés intéressantes.\n\n1. La fonction de répartition : il s'agit d'une fonction décrivant le cumul de probabilités d'une distribution. Cette fonction a un minimum de zéro qui est obtenu pour la plus petite valeur de l'espace d'échantillonnage de la distribution, et un maximum d'un pour la plus grande valeur de ce même espace. Formellement, la fonction de répartition ($F$) est l’intégrale de la fonction de densité ($f$).\n\n$$F(x) = \\int_{-\\infty}^{x}f(u)du$$\n2. La fonction de survie : soit l'inverse additif de la fonction de répartition ($R$)\n\n$$R(x) = 1-F(x)$$\n3. La fonction de d'intensité, soit le quotient de la fonction de densité et de la fonction de survie ($D$).\n$$D(x) = \\frac{f(x)}{D(x)}$$\nCes fonctions jouent notamment un rôle central dans la modélisation des phénomènes qui régissent la survenue des événements, par exemple la mort, les accidents de la route ou les bris d’équipement.\n:::\n:::\n\n### Principales distributions\n\nIl existe un très grand nombre de distributions théoriques et parmi elles, de nombreuses sont en fait des cas spéciaux d’autres distributions. Pour un petit aperçu du « bestiaire », vous pouvez faire un saut à la page [*Univariate Distribution Relationships*](http://www.math.wm.edu/~leemis/chart/UDR/UDR.html){target='_blank'}, qui liste près de 80 distributions. \n\nNous nous concentrons ici sur une sélection de dix-huit distributions très répandues en sciences sociales. La @fig-distribs présente graphiquement leurs fonctions de masse et de densité présentées dans cette section. Notez que ces graphiques correspondent tous à une forme possible de chaque distribution. En modifiant leurs paramètres, il est possible de produire une figure très différente. Les distributions discrètes sont représentées avec des graphiques en barre, et les distributions continues avec des graphiques de densité.\n\n![Dix-huit distributions essentielles, figure inspirée de @SeanOwendist](images/Chap02/all_distributions.png){#fig-distribs width=\"95%\" fig-align=\"center\"}\n\n\n#### Distribution uniforme discrète\nNous avons déjà abordé cette distribution dans les exemples précédents. Elle permet de décrire un phénomène dont tous les résultats possibles ont exactement la même probabilité de se produire. L’exemple classique est bien sûr un lancer de dé.\n\n#### Distribution de Bernoulli\nLa distribution de Bernoulli permet de décrire une expérience pour laquelle deux résultats sont possibles. Son espace d’échantillonnage est donc $[0; 1]$. Sa fonction de masse est la suivante : \n\n$$\nf(x ; p)=\\left\\{\\begin{array}{ll}\nq=1-p & \\text { si } x=0 \\\\\np & \\text { si } x=1\n\\end{array}\\right.\n$$ {#eq-BernoulliB}\n\navec *p* la probabilité d’obtenir $x = 1$ (réussite) et donc $1 – p$ la probabilité d’avoir $x = 0$ (échec). La distribution de Bernoulli ne dépend que d’un paramètre : *p*, contrôlant la probabilité de réussite de l’expérience. Notez que si $p = 1/2$, alors la distribution de Bernoulli est également une distribution uniforme. Un exemple d’application de la distribution de Bernoulli en études urbaines est la modélisation de la survie d’un ou d'une cycliste (1 pour survie, 0 pour décès) lors d’une collision avec un véhicule motorisé, selon une vitesse donnée.\n\n#### Distribution binomiale\n\nLa distribution binomiale est utilisée pour caractériser la somme de variables aléatoires (expériences) suivant chacune une distribution de Bernoulli. Un exemple simple est l’accumulation des lancers d’une pièce de monnaie. Si nous comptons le nombre de fois où nous obtenons pile, cette expérience est décrite par une distribution binomiale. Son espace d’échantillonnage est donc $[0; +\\infty[$ (limité aux nombres entiers). Sa fonction de masse est la suivante : \n\n$$\nf(x ; n )=\\binom{n}{x}p^x(1-p)^{n-x}\n$$ {#eq-Binomial}\n\navec *x* le nombre de tirages réussis sur *n* essais avec une probabilité *p* de réussite à chaque tirage (@fig-fig256). Pour reprendre l’exemple précédent concernant les accidents de la route, une distribution binomiale permettrait de représenter la distribution du nombre de cyclistes ayant survécu sur dix personnes à vélo impliquées dans un accident avec une voiture à une intersection. \n\n```{r}\n#| label: fig-fig256\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution binomiale\n#| out-width: \"95%\"\ndata <- data.frame(y1 = dbinom(1:15, size = 15, prob = .10),\n y2 = dbinom(1:15, size = 15, prob = .25),\n y3 = dbinom(1:15, size = 15, prob = .5),\n y4 = dbinom(1:15, size = 15, prob = .75),\n x = 1:15)\ndf <- melt(data, id.vars = \"x\")\ndf$f_prob <- case_when(\n df$variable == \"y1\" ~ \"p = 0,10\",\n df$variable == \"y2\" ~ \"p = 0,25\",\n df$variable == \"y3\" ~ \"p = 0,50\",\n df$variable == \"y4\" ~ \"p = 0,75\",\n)\ndf$f_prob <- factor(as.character(df$f_prob),\n levels = c(\"p = 0,10\",\n \"p = 0,25\",\n \"p = 0,50\",\n \"p = 0,75\"))\n \nggplot(df) +\n geom_bar(aes(x = x, weight = value), width = 0.2, fill = \"#99ccff\")+\n ylim(0,0.4)+\n labs(x = \"Nombre de tirages réussis pour 15 tirages\",\n y = \"Probabilité\")+\n facet_wrap(vars(f_prob), ncol = 2)\n```\n\n#### Distribution géométrique\n\nLa distribution géométrique permet de représenter le nombre de tirages qu'il faut faire avec une distribution de Bernoulli avant d’obtenir une réussite. Par exemple, avec un lancer de dé, l’idée serait de compter le nombre de lancers nécessaires avant de tomber sur un 6. Son espace d’échantillonnage est donc $[1; +\\infty[$ (limité aux nombres entiers). Sa distribution de masse est la suivante : \n\n$$\nf(x; p)= (1-p)^xp\n$$ {#eq-geometrique}\n\navec *x* le nombre de tentatives avant d’obtenir une réussite, $f(x)$ la probabilité que le premier succès n’arrive qu’après *x* tentatives et *p* la probabilité de réussite à chaque tentative (@fig-fig257). Cette distribution est notamment utilisée en marketing pour modéliser le nombre d’appels nécessaires avant de réussir une vente.\n\n```{r}\n#| label: fig-fig257\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution géométrique\n#| out-width: \"95%\"\ndata <- data.frame(y1 = dgeom(1:15, prob = .10),\n y2 = dgeom(1:15, prob = .25),\n y3 = dgeom(1:15, prob = .5),\n y4 = dgeom(1:15, prob = .75),\n x = 1:15)\ndf <- melt(data, id.vars = \"x\")\ndf$f_prob <- case_when(\n df$variable == \"y1\" ~ \"p = 0,10\",\n df$variable == \"y2\" ~ \"p = 0,25\",\n df$variable == \"y3\" ~ \"p = 0,50\",\n df$variable == \"y4\" ~ \"p = 0,75\",\n)\ndf$f_prob <- factor(as.character(df$f_prob),\n levels = c(\"p = 0,10\",\n \"p = 0,25\",\n \"p = 0,50\",\n \"p = 0,75\"))\n \nggplot(df) +\n geom_bar(aes(x = x, weight = value), width = 0.2, fill = \"#99ccff\")+\n ylim(0,0.3)+\n scale_x_continuous(breaks = seq(1, 15, by = 2))+\n labs(x = \"Nombre de tirages avant d'obtenir une réussite\",\n y = \"Probabilité\")+\n facet_wrap(vars(f_prob), ncol = 2)\n```\n\n#### Distribution binomiale négative\n\nLa distribution binomiale négative est proche de la distribution géométrique. Elle permet de représenter le nombre de tentatives nécessaires afin d’obtenir un nombre *n* de réussites $[1; +\\infty[$ (limité aux nombres entiers positifs). Sa formule est la suivante : \n\n$$\nf(x; n; p)=\\left(\\begin{array}{c}\nx+n-1 \\\\\nn\n\\end{array}\\right) p^{n}(1-p)^{x}\n$$ {#eq-binomialnegative}\n\navec *x* le nombre de tentatives avant d’obtenir *n* réussites et *p* la probabilité d’obtenir une réussite à chaque tentative (@fig-fig258). Cette distribution pourrait être utilisée pour modéliser le nombre de questionnaires *x* à envoyer pour une enquête pour obtenir au moins *n* réponses, sachant que la probabilité d’une réponse est *p*.\n\n```{r}\n#| label: fig-fig258\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution binomiale négative\n#| out-width: \"95%\"\ndata <- data.frame(y1 = dnbinom(1:15, size = 5, prob = .10),\n y2 = dnbinom(1:15, size = 5, prob = .25),\n y3 = dnbinom(1:15, size = 5, prob = .5),\n y4 = dnbinom(1:15, size = 5, prob = .75),\n x = 1:15)\ndf <- melt(data, id.vars = \"x\")\ndf$f_prob <- case_when(\n df$variable == \"y1\" ~ \"p = 0,10\",\n df$variable == \"y2\" ~ \"p = 0,25\",\n df$variable == \"y3\" ~ \"p = 0,50\",\n df$variable == \"y4\" ~ \"p = 0,75\",\n)\ndf$f_prob <- factor(as.character(df$f_prob),\n levels = c(\"p = 0,10\",\n \"p = 0,25\",\n \"p = 0,50\",\n \"p = 0,75\"))\n \nggplot(df) +\n geom_bar(aes(x = x, weight = value), width = 0.2, fill = \"#99ccff\")+\n ylim(0,0.3)+\n scale_x_continuous(breaks = seq(1, 15, by = 2))+\n labs(x = \"Nombre de tirages avant d'obtenir cinq réussites\",\n y = \"Probabilité\")+\n facet_wrap(vars(f_prob), ncol = 2)\n```\n\n#### Distribution de Poisson\n\nLa distribution de Poisson est utilisée pour modéliser des comptages. Son espace d’échantillonnage est donc $[0; +\\infty[$ (limité aux nombres entiers positifs). Par exemple, il est possible de compter à une intersection le nombre de collisions entre des automobilistes et des cyclistes sur une période donnée. Cet exemple devrait vous faire penser à la distribution binomiale vue plus haut. En effet, il est possible de noter chaque rencontre entre une voiture et un ou une cycliste et de considérer que leur collision est une « réussite » (0 : pas d’accidents, 1 : accident). Cependant, ce type de données est fastidieux à collecter comparativement au simple comptage des accidents. La distribution de Poisson a une fonction de densité avec un seul paramètre généralement noté $\\lambda$ (lambda) et est décrite par la formule suivante : \n\n$$\nf(x; \\lambda)=\\frac{\\lambda^{x}}{x !} e^{-\\lambda}\n$$ {#eq-poisson}\navec *x* le nombre de cas, *f(x)* la probabilité d’obtenir *x* sachant $\\lambda$. $\\lambda$ peut être vu comme le taux moyen d’occurrences (nombre d’évènements divisé par la durée totale de l’expérience). Il permet à la fois de caractériser le centre et la dispersion de la distribution. Notez également que plus le paramètre $\\lambda$ augmente, plus la distribution de Poisson tend vers une distribution normale.\n\n```{r}\n#| label: fig-fig259\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution de Poisson\n#| message: false\n#| warning: false\n#| out-width: \"95%\"\ndata <- data.frame(y1 = dpois(1:20, lambda = 1),\n y2 = dpois(1:20, lambda = 3),\n y3 = dpois(1:20, lambda = 5),\n y4 = dpois(1:20, lambda = 10),\n x = 1:20)\ndf <- melt(data, id.vars = \"x\")\ndf$f_prob <- case_when(\n df$variable == \"y1\" ~ \"lambda = 1\",\n df$variable == \"y2\" ~ \"lambda = 3\",\n df$variable == \"y3\" ~ \"lambda = 5\",\n df$variable == \"y4\" ~ \"lambda = 10\",\n)\ndf$f_prob <- factor(as.character(df$f_prob),\n levels = c(\"lambda = 1\",\n \"lambda = 3\",\n \"lambda = 5\",\n \"lambda = 10\"))\n \nggplot(df) +\n geom_bar(aes(x = x, weight = value), width = 0.2, fill = \"#99ccff\")+\n scale_x_continuous(breaks = seq(1, 20, by = 2))+\n labs(x = \"Nombre de cas\",\n y = \"Probabilité\")+\n facet_wrap(vars(f_prob), ncol = 2)\n```\n\n#### Distribution de Poisson avec excès de zéros {#sec-poissonzero}\n\nIl arrive régulièrement qu’une variable de comptage mesurée produise un très grand nombre de zéros. Prenons pour exemple le nombre de seringues de drogue injectable par tronçon de rue ramassées sur une période d’un mois. À l’échelle de toute une ville, un très grand nombre de tronçons n’auront tout simplement aucune seringue et dans ce contexte, la distribution classique de Poisson n’est pas adaptée. Nous lui préférons alors une autre distribution : la distribution de Poisson avec excès de zéros (ou distribution de Pólya) qui inclut un paramètre contrôlant la forte présence de zéros. Sa fonction de densité est la suivante : \n\n$$\nf(x; \\lambda; p)=(1-p)\\frac{\\lambda^{x}}{x !} e^{-\\lambda}\n$$ {#eq-poissonzi}\n\nPlus exactement, la distribution de Poisson avec excès de zéro (*zero-inflated* en anglais) est une combinaison de deux processus générant des zéros. En effet, un zéro peut être produit par la distribution de Poisson proprement dite (aussi appelé vrai zéro) ou alors par le processus générant les zéros excédentaires dans le jeu de données, capturé par la probabilité *p* (faux zéro). *p* est donc le paramètre contrôlant la probabilité d’obtenir un zéro, indépendamment du phénomène étudié.\n\n```{r}\n#| label: fig-fig259b\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution de Poisson avec excès de zéros\n#| message: false\n#| warning: false\n#| out-width: \"95%\"\nlibrary(VGAM, quietly = TRUE, warn.conflicts = TRUE)\ndata <- data.frame(y1 = dzipois(0:20, lambda = 1, pstr0 = 0.2),\n y2 = dzipois(0:20, lambda = 3, pstr0 = 0.4),\n y3 = dzipois(0:20, lambda = 5, pstr0 = 0.1),\n y4 = dzipois(0:20, lambda = 10, pstr0 = 0.5),\n x = 0:20)\n\ndf <- melt(data, id.vars = \"x\")\ndf$f_prob <- case_when(\n df$variable == \"y1\" ~ \"lambda = 1 & p = 0.2\",\n df$variable == \"y2\" ~ \"lambda = 3 & p = 0.4\",\n df$variable == \"y3\" ~ \"lambda = 5 & p = 0.1\",\n df$variable == \"y4\" ~ \"lambda = 10 & p = 0.5\",\n)\n\ndf$f_prob <- factor(as.character(df$f_prob),\n levels = c(\"lambda = 1 & p = 0.2\",\n \"lambda = 3 & p = 0.4\",\n \"lambda = 5 & p = 0.1\",\n \"lambda = 10 & p = 0.5\"))\n \nggplot(df) +\n geom_bar(aes(x = x, weight = value), width = 0.2, fill = \"#99ccff\")+\n scale_x_continuous(breaks = seq(0, 20, by = 2))+\n labs(x = \"Nombre de cas\",\n y = \"Probabilité\")+\n facet_wrap(vars(f_prob), ncol = 2)\n\n```\n\n#### Distribution gaussienne\nPlus communément appelée la distribution normale, la distribution gaussienne est utilisée pour représenter des variables continues centrées sur leur moyenne. Son espace d’échantillonnage est $]-\\infty; +\\infty[$. Cette distribution joue un rôle central en statistique. Selon la formule consacrée, cette distribution résulte de la superposition d’un très grand nombre de petits effets fortuits indépendants. C’est ce qu’exprime formellement le théorème central limite qui montre que la somme d’un grand nombre de variables aléatoires tend généralement vers une distribution normale. Autrement dit, lorsque nous répétons une même expérience et que nous conservons les résultats de ces expériences, la distribution du résultat de ces expériences tend vers la normalité. Cela s’explique par le fait qu’en moyenne, chaque répétition de l’expérience produit le même résultat, mais qu’un ensemble de petits facteurs aléatoires viennent ajouter de la variabilité dans les données collectées. Prenons un exemple concret : si nous plantons une centaine d’arbres simultanément dans un parc avec un degré d’ensoleillement identique et que nous leur apportons les mêmes soins pendant dix ans, la distribution de leurs tailles suivra une distribution normale. Un ensemble de facteurs aléatoires (composition du sol, exposition au vent, aléas génétiques, passage de nuages, etc.) auront affecté différemment chaque arbre, ajoutant ainsi un peu de hasard dans leur taille finale. Cette dernière est cependant davantage affectée par des paramètres majeurs (comme l'espèce, l'ensoleillement, l'arrosage, etc.), et est donc centrée autour d’une moyenne.\nLa fonction de densité de la distribution normale est la suivante :\n\n$$\nf(x ; \\mu ; \\sigma)=\\frac{1}{\\sigma \\sqrt{2 \\pi}} e^{-\\frac{1}{2}\\left(\\frac{x-\\mu}{\\sigma}\\right)^{2}}\n$$ {#eq-gaussien}\n\navec *x* une valeur dont nous souhaitons connaître la probabilité, *f(x)* sa probabilité, $\\mu$ (mu) la moyenne de la distribution normale (paramètre de localisation) et $\\sigma$ (sigma) son écart-type (paramètre de dispersion). Cette fonction suit une courbe normale ayant une forme de cloche. Notez que :\n\n* 68,2 % de la masse de la distribution normale est comprise dans l’intervalle $[\\mu- \\sigma≤x≤ \\mu+ \\sigma]$ \n* 95,4 % dans l’intervalle $[\\mu- 2\\sigma≤x≤ \\mu+ 2\\sigma]$\n* 99,7 % dans l’intervalle $[\\mu- 3\\sigma≤x≤ \\mu+ 3\\sigma]$\n\nAutrement dit, dans le cas d’une distribution normale, il est très invraisemblable d’observer des données situées à plus de trois écarts types de la moyenne. Ces différentes égalités sont vraies **quelles que soient les valeurs de la moyenne et de l'écart-type**.\nNotez ici que lorsque $\\mu = 0$ et $\\sigma = 1$, nous obtenons la loi normale générale (ou centrée réduite) ([section @sec-02552]).\n\n```{r}\n#| label: fig-fig260\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution gaussienne\n#| out-width: \"70%\"\nlibrary(VGAM)\ngenerate_plot <- function(fun, params, real_names, xlim, colors){\n params_names <- names(params)\n ## creating vectors with the parameters\n layers_labs <- lapply(1:length(params[[1]]), function(i){\n val <- (lapply(params_names, function(n){\n return(params[[n]][[i]])\n }))\n names(val) <- params_names\n label_params <- paste(paste(real_names, val, sep =\" = \"), collapse = \" & \")\n layer <- stat_function(aes(color = colors[[i]]), linewidth = 1,\n fun = fun, args = val)\n return(list(layer, label_params))\n })\n \n final_plot <- ggplot()\n all_labels <- sapply(layers_labs, function(i){i[[2]]})\n all_layers <- lapply(layers_labs, function(i){i[[1]]})\n for(layer in all_layers){\n final_plot <- final_plot + layer\n }\n final_plot <- final_plot + scale_color_identity(name = \"Paramètres\",\n breaks = colors,\n labels = all_labels,\n guide = \"legend\") + theme(\n axis.title.y = element_blank(),\n axis.ticks.y = element_blank(),\n axis.text.y = element_blank(),\n panel.background = element_blank(),\n panel.grid = element_blank()\n ) + xlim(xlim)\n return(final_plot)\n \n}\nparametres <- list(mean = c(-5,0,5),\n sd = c(1.5,1,3))\nreal_names <- c(\"mu\" , \"sigma\")\ncolors <- c(\"#ee6c4d\" , \"#98c1d9\" , \"#293241\")\nxlim <- c(-15,15)\ngenerate_plot(dnorm, parametres, real_names, xlim, colors)\n```\n\n#### Distribution gaussienne asymétrique\n\nLa distribution normale asymétrique (*skew-normal*) est une extension de la distribution gaussienne permettant de lever la contrainte de symétrie de la simple distribution gaussienne. Son espace d’échantillonnage est donc $]-\\infty; +\\infty[$. Sa fonction de densité est la suivante :\n\n$$\nf(x;\\xi;\\omega;\\alpha) = \\frac{2}{\\omega \\sqrt{2 \\pi}} e^{-\\frac{(x-\\xi)^{2}}{2 \\omega^{2}}} \\int_{-\\infty}^{\\alpha\\left(\\frac{x-\\xi}{\\omega}\\right)} \\frac{1}{\\sqrt{2 \\pi}} e^{-\\frac{t^{2}}{2}} d t\n$$ {#eq-skewgaussien}\n\navec $\\xi$ (xi) le paramètre de localisation, $\\omega$ (omega) le paramètre de dispersion (ou d’échelle) et $\\alpha$ (alpha) le paramètre de forme (contrôlant le degré de symétrie). Si $\\alpha = 0$, alors la distribution normale asymétrique est une distribution normale ordinaire. Ce type de distribution est très utile lorsque nous souhaitons modéliser une variable pour laquelle nous savons que des valeurs plus extrêmes s’observeront d’un côté ou de l’autre de la distribution. Les revenus totaux annuels des personnes ou des ménages sont de très bons exemples puisqu’ils sont distribués généralement avec une asymétrie positive : bien qu’une moyenne existe, il y a généralement plus de personnes ou de ménages avec des revenus très faibles que de personnes ou de ménages avec des revenus très élevés.\n\n```{r}\n#| label: fig-fig261\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution gaussienne asymétrique\n#| out-width: \"70%\"\nparametres <- list(location = c(-10,-5,10),\n scale = c(2,2,5),\n shape = c(0,4,-4))\nreal_names <- c(\"xi\" , \"omega\" , \"alpha\")\ncolors <- c(\"#ee6c4d\" , \"#98c1d9\" , \"#293241\")\nxlim <- c(-20,20)\ngenerate_plot(dskewnorm, parametres, real_names, xlim, colors)\n```\n\n#### Distribution log-normale\n\nAu même titre que la distribution normale asymétrique, la distribution log-normale est une version asymétrique de la distribution normale. Son espace d’échantillonnage est $]0; +\\infty[$. Cela signifie que cette distribution ne peut décrire que des données continues et positives. Sa fonction de densité est la suivante : \n\n$$\nf(x ; \\mu ; \\sigma)=\\frac{1}{x \\sigma \\sqrt{2 \\pi}} e^{-\\left(\\frac{(\\ln x-\\mu)^{2}}{2 \\sigma^{2}}\\right)}\n$$ {#eq-loggaussien}\n\nÀ la différence la distribution *skew-normal*, la distribution log-normale ne peut avoir qu’une asymétrie positive (étirée vers la droite). Elle est cependant intéressante puisqu’elle ne compte que deux paramètres ($\\mu$ et $\\sigma$), ce qui la rend plus facile à ajuster. À nouveau, une distribution log-normale peut être utilisée pour décrire les revenus totaux annuels des individus ou des ménages ou les revenus d’emploi. Elle est aussi utilisée en économie sur les marchés financiers pour représenter les cours des actions et des biens (ces derniers ne pouvant pas être inférieurs à 0).\n\n```{r}\n#| label: fig-fig262\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution log-gaussienne\n#| out-width: \"70%\"\nparametres <- list(meanlog = c(1,2,3),\n sdlog = c(1,1.5,1))\nreal_names <- c(\"mu\" , \"sigma\")\ncolors <- c(\"#ee6c4d\" , \"#98c1d9\" , \"#293241\")\nxlim <- c(0,30)\ngenerate_plot(dlnorm, parametres, real_names, xlim, colors)\n```\n\nPlus spécifiquement, la distribution log-normale est une transformation de la distribution normale. Comme son nom l'indique, elle permet de décrire le logarithme d'une variable aléatoire suivant une distribution normale.\n\n#### Distribution de Student {#sec-024311}\n\nLa distribution de Student joue un rôle important en statistique. Elle est par exemple utilisée lors du test *t* pour calculer le degré de significativité du test. Comme la distribution gaussienne, la distribution de Student a une forme de cloche, est centrée sur sa moyenne et définie sur $]-\\infty; +\\infty[$. Elle se distingue de la distribution normale principalement par le rôle que joue son troisième paramètre, $\\nu$ : le nombre de degrés de liberté, contrôlant le poids des queues de la distribution. Une petite valeur de $\\nu$ signifie que la distribution a des « queues plus lourdes » (*heavy tails* en anglais). Entendez par-là que les valeurs extrêmes ont une plus grande probabilité d’occurrence : \n\n$$\np(x ; \\nu ; \\hat{\\mu} ; \\hat{\\sigma})=\\frac{\\Gamma\\left(\\frac{\\nu+1}{2}\\right)}{\\Gamma\\left(\\frac{\\nu}{2}\\right) \\sqrt{\\pi \\nu} \\hat{\\sigma}}\\left(1+\\frac{1}{\\nu}\\left(\\frac{x-\\hat{\\mu}}{\\hat{\\sigma}}\\right)^{2}\\right)^{-\\frac{\\nu+1}{2}}\n$$ {#eq-student}\n\navec $\\mu$ le paramètre de localisation, $\\sigma$ le paramètre de dispersion (qui n’est cependant pas un écart-type comme pour la distribution normale) et $\\nu$ le nombre de degrés de liberté. Plus $\\nu$ est grand, plus la distribution de Student tend vers une distribution normale. Ici, la lettre grecque $\\Gamma$ représente la fonction mathématique gamma (à ne pas confondre avec la distribution Gamma). Un exemple d’application en études urbaines est l’exposition au bruit environnemental de cyclistes. Cette distribution s’approcherait certainement d’une distribution normale, mais les cyclistes croisent régulièrement des secteurs peu bruyants (parcs, rues résidentielles, etc.) et des secteurs très bruyants (artères majeures, zones industrielles, etc.), plus souvent que ce que prévoit une distribution normale, justifiant le choix d'une distribution de Student.\n\n```{r}\n#| label: fig-fig263\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution de Student\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nlibrary(LaplacesDemon)\nparametres <- list(mu = c(-10,0,10),\n sigma = c(1,3,6),\n nu = c(2,10,30)\n )\nreal_names <- c(\"mu\" , \"sigma\", \"nu\")\ncolors <- c(\"#ee6c4d\" , \"#98c1d9\" , \"#293241\")\nxlim <- c(-25,25)\ngenerate_plot(dst, parametres, real_names, xlim, colors)\n```\n\n#### Distribution de Cauchy\n\nLa distribution de Cauchy est également une distribution symétrique définie sur l’intervalle $]-\\infty; +\\infty[$. Elle a comme particularité d'être plus aplatie que la distribution de Student (d’avoir des queues potentiellement plus lourdes). Elle est notamment utilisée pour modéliser des phénomènes extrêmes comme les précipitations maximales annuelles, les niveaux d’inondations maximaux annuels ou les seuils critiques de perte pour les portefeuilles financiers. Il est également intéressant de noter que le quotient de deux variables indépendantes normalement distribuées suit une distribution de Cauchy. Sa fonction de densité est la suivante : \n\n$$\n\\frac{1}{\\pi \\gamma}\\left[\\frac{\\gamma^{2}}{\\left(x-x_{0}\\right)^{2}+\\gamma^{2}}\\right]\n$$ {#eq-cauchy}\n\nElle dépend donc de deux paramètres : $x_0$, le paramètre de localisation indiquant le pic de la distribution et $\\gamma$, un paramètre de dispersion.\n\n```{r}\n#| label: fig-fig264\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution de Cauchy\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nparametres <- list(location = c(-10,0,10),\n scale = c(1,3,6)\n )\nreal_names <- c(\"x0\" , \"gamma\")\ncolors <- c(\"#ee6c4d\" , \"#98c1d9\" , \"#293241\")\nxlim <- c(-25,25)\ngenerate_plot(dcauchy, parametres, real_names, xlim, colors)\n```\n\n#### Distribution du khi-deux\n\nLa distribution du khi-deux est utilisée dans de nombreux tests statistiques. Par exemple, le test du khi-deux de Pearson est utilisé pour comparer les écarts au carré entre des fréquences attendues et observées de deux variables qualitatives.\nLa distribution du khi-deux décrit plus généralement la somme des carrés d’un nombre *k* de variables indépendantes normalement distribuées. Il est assez rare de modéliser un phénomène à l’aide d’une distribution du khi-deux, mais son omniprésence dans les tests statistiques justifie qu’elle soit mentionnée ici. Cette distribution est définie sur l’intervalle $[0; +\\infty[$ et a pour fonction de densité : \n\n$$\nf(x;k) = \\frac{1}{2^{k / 2} \\Gamma(k / 2)} x^{k / 2-1} e^{-x / 2}\n$$ {#eq-chi2}\n\nLa distribution du khi-deux n’a qu’un paramètre *k*, représentant donc le nombre de variables mises au carré et dont nous faisons la somme pour obtenir la distribution du khi-deux.\n\n```{r}\n#| label: fig-fig265\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution du khi-deux\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nparametres <- list(df = c(2,5,10))\nreal_names <- c(\"k\")\ncolors <- c(\"#ee6c4d\" , \"#98c1d9\" , \"#293241\")\nxlim <- c(0,25)\ngenerate_plot(dchisq, parametres, real_names, xlim, colors)\n```\n\n#### Distribution exponentielle\n\nLa distribution exponentielle est une version continue de la distribution géométrique. Pour cette dernière, nous nous intéressons au nombre de tentatives nécessaires pour obtenir un résultat positif, soit une dimension discrète. Pour la distribution exponentielle, cette dimension discrète est remplacée par une dimension continue. L’exemple le plus intuitif est sûrement le cas du temps. Dans ce cas, la distribution exponentielle sert à modéliser le temps d’attente nécessaire pour qu’un évènement se produise. Il peut aussi s’agir d’une force que nous appliquons jusqu’à ce qu’un matériau cède. Cette distribution est donc définie sur l’intervalle [0; +$\\infty$[ et a pour fonction de densité :\n\n$$\nf(x;\\lambda) = \\lambda e^{-\\lambda x}\n$$ {#eq-exponentiel}\n\n\n```{r}\n#| label: fig-fig266\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution exponentielle\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nparametres <- list(rate = c(1/2,1/5,1/10))\nreal_names <- c(\"lambda\")\ncolors <- c(\"#ee6c4d\" , \"#98c1d9\" , \"#293241\")\nxlim <- c(0,25)\ngenerate_plot(dexp, parametres, real_names, xlim, colors)\n```\n\nLa distribution exponentielle est conceptuellement proche de la distribution de Poisson. La distribution de Poisson régit le nombre des événements qui surviennent au cours d’un laps de temps donné. La distribution exponentielle peut servir à modéliser le temps qui s’écoule entre deux événements. \n\n#### Distribution Gamma {#sec-024315}\n\nLa distribution Gamma peut être vue comme la généralisation d’un grand nombre de distributions. Ainsi, les distributions exponentielle et du khi-deux peuvent être vues comme des cas particuliers de la distribution Gamma. Cette distribution est définie sur l’intervalle ]0; +$\\infty$[ (notez que le 0 est exclu) et sa fonction de densité est la suivante : \n\n$$\nf(x ; \\alpha; \\beta)=\\frac{\\beta^{\\alpha} x^{\\alpha-1} e^{-\\beta x}}{\\Gamma(\\alpha)}\n$$ {#eq-gamma}\n\nElle comprend donc deux paramètres : $\\alpha$ et $\\beta$. Le premier est le paramètre de forme et le second un paramètre d’échelle (à l’inverse d’un paramètre de dispersion, plus sa valeur est petite, plus la distribution est dispersée). Notez que cette distribution ne dispose pas d’un paramètre de localisation. Du fait de sa flexibilité, cette distribution est largement utilisée, notamment pour la modélisation des temps d’attente avant un évènement, de la taille des réclamations d’assurance, des quantités de précipitations, etc.\n\n```{r}\n#| label: fig-fig267\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution Gamma\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nparametres <- list(shape = c(1,2,6),\n rate = c(1,0.4,0.8))\nreal_names <- c(\"alpha\" , \"beta\")\ncolors <- c(\"#ee6c4d\" , \"#98c1d9\" , \"#293241\")\nxlim <- c(0,25)\ngenerate_plot(dgamma, parametres, real_names, xlim, colors)\n```\n\n#### Distribution bêta {#sec-024316}\n\nLa distribution bêta est définie sur l’intervalle [0; 1], elle est donc énormément utilisée pour modéliser des variables étant des proportions ou des probabilités.\n\nLa distribution bêta a été élaborée pour modéliser la superposition d’un très grand nombre de petits effets fortuits qui ne sont pas indépendants et notamment pour étudier l’effet de la réalisation d’un événement aléatoire sur la probabilité des tirages subséquents. Elle a aussi une utilité pratique en statistique, car elle peut être combinée avec d’autres distributions (distribution bêta binomiale, bêta négative binomiale, etc.). Un autre usage plus rare mais intéressant est la modélisation de la fraction du temps représentée par une tâche dans le temps nécessaire à la réalisation de deux tâches de façon séquentielle. Cela est dû au fait que la distribution d’une distribution Gamma *g1* divisée par la somme de *g1* et d’une autre distribution Gamma *g2* suit une distribution bêta. Un exemple concret est, par exemple, la fraction du temps effectué à pied dans un déplacement multimodal. La distribution de bêta a la fonction de densité suivante : \n\n$$\nf(x;\\alpha;\\beta) = \\frac{1}{\\mathrm{B}(\\alpha, \\beta)} x^{\\alpha-1}(1-x)^{\\beta-1}\n$$ {#eq-beta}\n\nElle a donc deux paramètres $\\alpha$ et $\\beta$ contrôlant tous les deux la forme de la distribution. Cette caractéristique lui permet d’avoir une très grande flexibilité et même d’adopter des formes bimodales. $B$ correspond à la fonction mathématique Beta : ne pas la confondre avec la distribution Beta et le paramètre Beta ($\\beta$) de cette même distribution.\n\n```{r}\n#| label: fig-fig268\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution bêta\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nparametres <- list(shape1 = c(0.5,5,2,2),\n shape2 = c(0.5,1,2,5))\nreal_names <- c(\"alpha\" , \"beta\")\ncolors <- c(\"#ee6c4d\" , \"#98c1d9\" , \"#293241\" , \"#8C4F47\")\nxlim <- c(0,1)\ngenerate_plot(dbeta, parametres, real_names, xlim, colors)\n```\n\n#### Distribution de Weibull\n\nLa distribution de Weibull est directement liée à la distribution exponentielle, cette dernière étant en fait un cas particulier de distribution Weibull. Elle sert donc souvent à modéliser une quantité *x* (souvent le temps) à accumuler pour qu’un évènement se produise. La distribution de Weibull est définie sur l’intervalle [0; +$\\infty$[ et a la fonction de densité suivante : \n\n$$\nf(x;\\lambda) = \\frac{k}{\\lambda} (\\frac{x}{\\lambda})^{k-1} e^{-(\\frac{x}{\\lambda})^k}\n$$ {#eq-weibull}\n\n$\\lambda$ est le paramètre de dispersion (analogue à celui d’une distribution exponentielle classique) et *k* le paramètre de forme. Pour bien comprendre le rôle de *k*, prenons un exemple : la propagation d’un champignon d’un arbre à son voisin. Si $k<1$, le risque instantané que l’évènement modélisé se produise diminue avec le temps (en d’autres termes, plus le temps passe, plus petite devient la probabilité d’être contaminé). Si $k=1$, alors le risque instantané que l’évènement se produise reste identique dans le temps (la loi de Weibull se résume alors à une loi exponentielle). Si $k > 1$, alors le risque instantané que l’évènement se produise augmente avec le temps (la probabilité pour un arbre d'être contaminé s'il ne l’a pas déjà été — pas seulement le risque cumulé — augmente en fonction du temps). La distribution de Weibull est très utilisée en analyse de survie, en météorologie, en ingénierie des matériaux et dans la théorie des valeurs extrêmes.\n\n```{r}\n#| label: fig-fig269\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution de Weibull\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nparametres <- list(shape = c(1,0.5,5),\n scale = c(1,3,10))\nreal_names <- c(\"k\" , \"lambda\")\ncolors <- c(\"#ee6c4d\" , \"#98c1d9\" , \"#293241\")\nxlim <- c(0,15)\ngenerate_plot(dweibull, parametres, real_names, xlim, colors)\n```\n\n#### Distribution Pareto\n\nCette distribution a été élaborée par Vilfredo Pareto pour donner une forme mathématique à ce qui porte aujourd’hui le nom de principe de Pareto et que nous exprimons souvent de manière imagée — dans une société donnée, 20 % des individus possèdent 80 % de la richesse —, mais qui est plus justement exprimée en écrivant que, de manière générale, dans toute société, la plus grande partie du capital est détenue par une petite fraction de la population. Elle est définie sur l’intervalle $[x_m; +\\infty[$ avec la fonction de densité suivante : \n\n$$\nf(x;x_m;k) = (\\frac{x_m}{x})^k\n$$ {#eq-pareto}\n\nElle comprend donc deux paramètres, $x_m$ étant un paramètre de localisation (décalant la distribution vers la droite ou vers la gauche) et $k$ un paramètre de forme. Plus $k$ augmente, plus la probabilité prédite par la distribution décroît rapidement.\n\n```{r}\n#| label: fig-fig270\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution de Pareto\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nparametres <- list(scale = c(4,3,1),\n shape = c(5,3,1))\nreal_names <- c(\"mx\" , \"k\")\ncolors <- c(\"#ee6c4d\" , \"#98c1d9\" , \"#293241\")\nxlim <- c(0,15)\ngenerate_plot(VGAM::dpareto, parametres, real_names, xlim, colors)\n```\n\nAu-delà de la question de la répartition de la richesse, la distribution de Pareto peut également être utilisée pour décrire la répartition de la taille des villes [@William_pareto_ville], [la popularité des hommes sur Tinder](https://medium.com/@worstonlinedater/tinder-experiments-ii-guys-unless-you-are-really-hot-you-are-probably-better-off-not-wasting-your-2ddf370a6e9a){target=\"_blank\"} ou la taille des fichiers échangés sur Internet [@William_pareto]. Pour ces trois exemples, nous avons les situations suivantes : de nombreuses petites villes, profils peu attractifs, petits fichiers échangés et à l'inverse très peu de grandes villes, profils très attractifs, gros fichiers échangés.\n\nLa loi de Pareto est liée à la loi exponentielle. Si une variable aléatoire suit une loi de Pareto, le logarithme du quotient de cette variable et de son paramètre de localisation est une variable aléatoire qui suit une loi exponentielle.\n\n#### Cas particuliers\n\nSachez également qu’il existe des distributions « plus exotiques » que nous n’abordons pas ici, mais auxquelles vous pourriez être confrontés un jour :\n\n* Les distributions sphériques, servant à décrire des données dont le 0 est équivalent à la valeur maximale. Par exemple, des angles puisque 0 et 360 degrés sont identiques.\n\n* Les distributions composées (*mixture distributions*), permettant de modéliser des phénomènes issus de la superposition de plusieurs distributions. Par exemple, la distribution de la taille de l'ensemble des êtres humains est en réalité une superposition de deux distributions gaussiennes, une pour chaque sexe, puisque ces deux distributions n’ont pas la même moyenne ni le même écart-type.\n\n* Les distributions multivariées permettant de décrire des phénomènes multidimensionnels. Par exemple, la réussite des élèves en français et en mathématique pourrait être modélisée par une distribution gaussienne bivariée plutôt que deux distributions distinctes. Ce choix serait pertinent si nous présumons que ces deux variables sont corrélées plutôt qu'indépendantes.\n\n* Les distributions censurées décrivant des variables pour lesquelles les données sont issues d'un tirage « censuré ». En d'autres termes, la variable étudiée varie sur une certaine étendue, mais du fait du processus de tirage (collecte des données), les valeurs au-delà de certaines limites sont censurées. Un bon exemple est la mesure de la pollution sonore avec un capteur incapable de détecter des niveaux sonores en dessous de 55 décibels. Il arrive parfois en ville que les niveaux sonores descendent plus bas que ce seuil, mais les données collectées ne le montrent pas. Dans ce contexte, il est important d’utiliser des versions censurées des distributions présentées précédemment. Les observations au-delà de la limite sont conservées dans l’analyse, mais nous ne disposons que d’une information partielle à leur égard (elles sont au-delà de la limite).\n\n* Les distributions tronquées, souvent confondues avec les distributions censurées, décrivent des situations où des données au-delà d’une certaine limite sont impossibles à collecter et retirées simplement de l’analyse.\n\n### Conclusion sur les distributions\n\nVoilà qui conclut cette exploration des principales distributions à connaître. L’idée n’est bien sûr pas de toutes les retenir par cœur (et encore moins les formules mathématiques), mais plutôt de se rappeler dans quels contextes elles peuvent être utiles. Vous aurez certainement besoin de relire cette section avant d’aborder le [chapitre @sec-chap08] portant sur les modèles linéaires généralisés (GLM).\nWikipédia dispose d’informations très détaillées sur chaque distribution si vous avez besoin d’informations complémentaires. Pour un tour d’horizon plus exhaustif des distributions, vous pouvez aussi faire un tour sur les projets [ProbOnto](https://sites.google.com/site/probonto/home){target=\"_blank\"} et [*the ultimate probability distribution explorer*](https://blog.wolfram.com/2013/02/01/the-ultimate-univariate-probability-distribution-explorer/){target=\"_blank\"}. \n\n\n## Statistiques descriptives sur des variables quantitatives {#sec-025}\n\n### Paramètres de tendance centrale {#sec-0251}\n\nTrois mesures de tendance centrale permettent de résumer rapidement une variable quantitative :\n\n* La **moyenne arithmétique** est simplement la somme des données d'une variable divisée par le nombre d'observations (*n*), soit $\\frac{\\sum_{i=1}^n x_i}{n}$ notée $\\mu$ (prononcé *mu*) pour des données pour une population et $\\bar{x}$ (prononcé *x barre*) pour un échantillon.\n\n* La **médiane** est la valeur qui coupe la distribution d'une variable d'une population ou d'un échantillon en deux parties égales. Autrement dit, 50 % des valeurs des observations lui sont supérieures et 50 % lui sont inférieures.\n\n* Le **mode** est la valeur la plus fréquente parmi un ensemble d'observations pour une variable. Il s'applique ainsi à des variables discrètes (avec un nombre fini de valeurs discrètes dans un intervalle donné) et non à des variables continues (avec un nombre infini de valeurs réelles dans un intervalle donné). Prenons deux variables : l'une discrète relative au nombre d'accidents par intersection (avec $X \\in \\left[0,20\\right]$) et l'autre continue relative à la distance de dépassement (en mètres) d'une personne à vélo par une personne conduisant un véhicule motorisé (avec $X \\in \\left[0,5\\right]$). Pour la première, le mode – la valeur la plus fréquente – est certainement 0. Pour la seconde, identifier le mode n'est pas pertinent puisqu'il peut y avoir un nombre infini de valeurs entre 0 et 5 mètres.\n\n**Il convient de ne pas confondre moyenne et médiane!** Dans le @tbl-RevMoyMed, nous avons reporté les valeurs moyennes et médianes des revenus des ménages pour les municipalités de l'île de Montréal en 2015. Par exemple, les 8685 ménages résidant à Wesmount disposaient en moyenne d'un revenu de 295 099 \\$; la moitié de ces 8685 ménages avaient un revenu inférieur à 100 153 \\$ et l'autre moitié un revenu supérieur à cette valeur (médiane). Cela démontre clairement que la moyenne peut être grandement affectée par des valeurs extrêmes (faibles ou fortes). Autrement dit, plus l'écart entre les valeurs de la moyenne et la médiane est important, plus les données de la variable sont inégalement réparties. À Westmount, soit la municipalité la plus nantie de l'île de Montréal, les valeurs extrêmes sont des ménages avec des revenus très élevés tirant fortement la moyenne vers le haut. À l'inverse, le faible écart entre les valeurs moyenne et médiane dans la municipalité de Montréal-Est (58 594 \\$ versus 50 318 \\$) souligne que les revenus des ménages sont plus également répartis. Cela explique que pour comparer les revenus totaux ou d'emploi entre différents groupes (selon le sexe, le groupe d'âge, le niveau d'éducation, la municipalité ou région métropolitaine, etc.), nous privilégions habituellement l'utilisation des revenus médians.\n\n```{r}\n#| label: tbl-RevMoyMed\n#| tbl-cap: Revenus moyens et médians des ménages en dollars, municipalités de l'île de Montréal, 2015\n#| echo: false\n#| message: false\n#| warning: false\ndf <- read.csv(\"data/univariee/revenu.csv\")\ndf2 <- df[, c(\"Muni\" , \"NMenages\" , \"RevMoyM\" , \"RevMedM\")]\nknitr::kable(df2,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Municipalité\" , \"Nombre de ménages\", \"Revenu moyen\" , \"Revenu médian\"),\n align= c(\"l\", \"r\", \"r\", \"r\")\n )\n```\n\n### Paramètres de position {#sec-0252}\n\nLes paramètres de position permettent de diviser une distribution en _n_ parties égales.\n\n* Les **quartiles** qui divisent une distribution en quatre parties (25 %) :\n + Q1 (25 %), soit le quartile inférieur ou premier quartile;\n + Q2 (50 %), soit la médiane;\n + Q3 (75 %), soit le quartile supérieur ou troisième quartile.\n* Les **quintiles** qui divisent une distribution en cinq parties égales (20 %).\n* Les **déciles** (de D1 à D9) qui divisent une distribution en dix parties égales (10 %).\n* Les **centiles** (de C1 à C99) qui divisent une distribution en cent parties égales (1 %).\n\nEn cartographie, les quartiles et les quintiles sont souvent utilisés pour discrétiser une variable quantitative (continue ou discrète) en quatre ou cinq classes et plus rarement, en dix classes (déciles). Avec les quartiles, les bornes des classes qui comprennent chacune 25 % des unités spatiales sont définies comme suit : [Min à Q1], [Q1 à Q2], [Q2 à Q3] et [Q3 à Max]. La méthode de discrétisation selon les quartiles ou quintiles permet de repérer, en un coup d'œil, à quelle tranche de 25 % ou de 20 % des données appartient chacune des unités spatiales. Cette méthode de discrétisation est aussi utile pour comparer plusieurs cartes et vérifier si deux phénomènes sont ou non colocalisés [@pumain1994]. En guise d'exemple, les pourcentages de personnes à faible revenu et de locataires par secteur de recensement ont clairement des distributions spatiales très semblables dans la région métropolitaine de Montréal en 2016 (@fig-univarie2).\n\n\n![Exemples de cartographie avec une discrétisation selon les quantiles](images/Chap02/figure2.jpg){#fig-univarie2 width=\"85%\" fig-align=\"center\"}\n\nUne lecture attentive des valeurs des centiles permet de repérer la présence de valeurs extrêmes, voire aberrantes, dans un jeu de données. Il n'est donc pas rare de les voir reportées dans un tableau de statistiques descriptives d'un article scientifique, et ce, afin de décrire succinctement les variables à l'étude. Par exemple, dans une étude récente comparant les niveaux d'exposition au bruit des cyclistes dans trois villes [@2020_1], les auteurs reportent à la fois les valeurs moyennes et celles de plusieurs centiles. Globalement, la lecture des valeurs moyennes permet de constater que, sur la base des données collectées, les cyclistes sont plus exposés au bruit à Paris qu'à Montréal et Copenhague (73,4 dB(A) contre 70,7 et 68,4, @tbl-Centiles). Compte tenu de l'échelle logarithmique du bruit, la différence de 5 dB(A) entre les valeurs moyennes du bruit de Copenhague et de Paris peut être considérée comme une multiplication de l'énergie sonore par plus de 3. Pour Paris, l'analyse des quartiles montre que durant 25 % du temps des trajets à vélo (plus de 63 heures de collecte), les participantes et participants ont été exposés à des niveaux de bruit soit inférieurs à 69,1 dB(A) (premier quartile), soit supérieurs à 74 dB(A) (troisième quartile). Quant à l'analyse des centiles, elle permet de constater que durant 5 % et 10 % du temps, les participantes et participants étaient exposés à des niveaux de bruit très élevés, dépassant 75 dB(A) (C90 = 76 et C90 = 77,2).\n\n```{r}\n#| label: tbl-Centiles\n#| tbl-cap: Stastistiques descriptives de l'exposition au bruit des cyclistes par minute dans trois villes (dB(A), Laeq 1min)\n#| echo: false\n#| message: false\n#| warning: false\noptions(knitr.kable.NA = '')\ndf <- data.frame(\n Centiles = c(\"N\" , \"Moyenne de bruit\" , \"Centiles\" , \"1\" , \"5\" , \"10\", \"25 (premier quartile)\", \"50 (médiane)\", \"75 (troisième quartile)\", \"90\", \"95\", \"99\"),\n C = c(6212,68.4, NA,57.5,59.1,60.3,62.7,66.0,69.2,71.9,73.3,76.5),\n M = c(4723,70.7, NA,59.2,61.1,62.3,64.5,67.7,71.0,73.7,75.2,78.9),\n P = c(3793,73.4, NA,62.3,65.0,66.5,69.1,71.6,74.0,76.0,77.2,81.0))\n\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Statistiques\" , \"Copenhague\", \"Montréal\" , \"Paris\"),\n align= c(\"l\", \"r\", \"r\", \"r\"))\n```\n\n\n### Paramètres de dispersion {#sec-0253}\nCinq principales mesures de dispersion permettent d'évaluer la variabilité des valeurs d'une variable quantitative : l'étendue, l'écart interquartile, la variance, l'écart-type et le coefficient de variation. Notez d'emblée que cette dernière mesure ne s'applique pas à des variables d'intervalle ([section @sec-02122]).\n\n* **L'étendue** est la différence entre les valeurs minimale et maximale d'une variable, soit l'intervalle des valeurs dans lequel elle a été mesurée. Il convient d'analyser avec prudence cette mesure puisqu'elle inclut dans son calcul des valeurs potentiellement extrêmes, voire aberrantes (faibles ou fortes).\n\n* **L'intervalle ou écart interquartile** est la différence entre les troisième et premier quartiles (Q3 − Q1). Il représente ainsi une mesure de la dispersion des valeurs de 50 % des observations centrales de la distribution. Plus la valeur de l'écart interquartile est élevée, plus la dispersion des 50 % des observations centrales est forte. Contrairement à l'étendue, cette mesure élimine l'influence des valeurs extrêmes puisqu'elle ne tient pas compte des 25 % des observations les plus faibles [Min à Q1] et des 25 % des observations les plus fortes [Q3 à Max]. Graphiquement, l'intervalle interquartile est représenté à l'aide d'une boîte à moustaches (*boxplot* en anglais) : plus l'intervalle interquartile est grand, plus la boîte est allongée (@fig-univarie3).\n\n![Graphique en violon, boîte à moustaches et intervalle interquartile](images/Chap02/figure3.jpg){#fig-univarie3 width=\"30%\" fig-align=\"center\"}\n\n\n* **La variance** est la somme des déviations à la moyenne au carré (numérateur) divisée par le nombre d'observations pour une population ($\\sigma^2$) ou divisée par le nombre d'observations moins une ($s^2$) pour un échantillon (@eq-variance). Puisque les déviations à la moyenne sont mises au carré, la valeur de la variance (tout comme celle de l'écart-type) est toujours positive. Plus sa valeur est élevée, plus les observations sont dispersées autour de la moyenne. La variance représente ainsi l'écart au carré moyen des observations à la moyenne. \n\n* **L'écart-type** est la racine carrée de la variance (@eq-ecartype). Rappelez-vous que la variance est calculée à partir des déviations à la moyenne mises au carré. Étant donné que l'écart-type est la racine carrée de la variance, il est donc évalué dans la même unité que la variable, contrairement à la variance. Bien entendu, comme pour la variance, plus la valeur de l'écart-type est élevée, plus la distribution des observations autour de la moyenne est dispersée.\n\n$$ \n\\sigma^2=\\frac{\\sum_{i=1}^n (x_{i}-\\mu)^2}{n} \\text{ ou } s^2=\\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})^2}{n-1}\n$$ {#eq-variance}\n\n$$\n\\sigma=\\sqrt{\\sigma^2}=\\sqrt{\\frac{\\sum_{i=1}^n (x_{i}-\\mu)^2}{n}} \\text{ ou } s=\\sqrt{s^2}=\\sqrt{\\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})^2}{n-1}}\n$$ {#eq-ecartype}\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Formules des variances et des écarts-types**\n:::\n::: bloc_notes-body\nLes formules des variances et des écarts-types pour une population et un échantillon sont très similaires : seul le dénominateur change avec $n$ *versus* $n-1$ observations. Par conséquent, plus le nombre d'observations de votre jeu de données est important, plus l'écart entre ces deux mesures de dispersion pour une population et un échantillon est minime.\n\nComme dans la plupart des logiciels de statistique, les fonctions de base `var` et `sd` de R calculent la variance et l'écart-type pour un échantillon ($n-1$ au dénominateur). Si vous souhaitez les calculer pour une population, adaptez la syntaxe ci-dessous dans laquelle `df$var1` représente la variable intitulée `var1` présente dans un *DataFrame* nommé `df`.\n\n`var.p <- mean((df$var1 - mean(df$var1))^2)` \n\n`sd.p <- sqrt(mean((df$var1 - mean(df$var1))^2))` \n:::\n:::\n\n* **Le coefficient de variation (CV)** est le rapport entre l'écart-type et la moyenne, représentant ainsi une standardisation de l'écart-type ou, en d'autres termes, une mesure de dispersion relative (@eq-cv). L'écart-type étant exprimé dans l'unité de mesure de la variable, il ne peut pas être utilisé pour comparer les dispersions de variables exprimées des unités de mesure différentes (par exemple, en pourcentage, en kilomètres, en dollars, etc.). Pour y remédier, nous utilisons le coefficient de variation : une variable est plus dispersée qu'une autre si la valeur de son CV est plus élevée. Certaines personnes préfèrent multiplier la valeur du CV par 100 : l'écart-type est alors exprimé en pourcentage de la moyenne.\n\n\n$$ \nCV=\\frac{\\sigma}{\\mu} \\text{ ou } CV=\\frac{s^2}{\\bar{x}}\n$$ {#eq-cv}\n\n\nIllustrons comment calculer les cinq mesures de dispersion précédemment décrites à partir de valeurs fictives pour huit observations (colonne intitulée $x_i$ au @tbl-datavar). Les différentes statistiques reportées dans ce tableau sont calculées comme suit :\n\n* La **moyenne** est la somme divisée par le nombre d'observations, soit $\\mbox{248/8}=\\mbox{31}$.\n\n* L'**étendue** est la différence entre les valeurs maximale et minimale, soit $\\mbox{40}-\\mbox{22}=\\mbox{30}$.\n\n* Les quartiles coupent la distribution en quatre parties égales. Avec huit observations triées par ordre croissant, **le premier quartile** est égal à la valeur de la deuxième observation (soit 25), la **médiane** à celle de la quatrième (30), le **troisième quartile** à celle de la sixième (35).\n\n* **L'écart interquartile** est la différence entre Q3 et Q1, soit $\\mbox{35}-\\mbox{25}=\\mbox{10}$.\n\n* La seconde colonne du tableau est l'écart à la moyenne ($x_i-\\bar{x}$), soit $\\mbox{22} - \\mbox{31} = -\\mbox{9}$ pour l'observation *1*; la somme de ces écarts est toujours égale à 0. La troisième colonne est cette déviation mise au carré ($(x_i-\\bar{x})^2$), soit $-\\mbox{9}^2 = \\mbox{81}$, toujours pour l'observation *1*. La somme de ces déviations à la moyenne au carré (268) représente le numérateur de la variance (@eq-variance). En divisant cette somme par le nombre d'observations, nous obtenons la **variance pour une population** ($\\mbox{268}/\\mbox{8}=\\mbox{33,5}$) tandis que la **variance d'un échantillon** est égale à $\\mbox{268}/(\\mbox{8}-\\mbox{1})=\\mbox{38,29}$.\n\n* L'écart-type est la racine carrée de la variance (@eq-ecartype), soit $\\sigma=\\sqrt{\\mbox{33,5}}=\\mbox{5,79}$ et $s=\\sqrt{\\mbox{38,29}}=\\mbox{6,19}$.\n\n* Finalement, les valeurs des coefficients de variation (@eq-cv) sont de $\\mbox{5,79}/\\mbox{31}=\\mbox{0,19}$ pour une population et $\\mbox{6,19}/\\mbox{31}=\\mbox{0,20}$ pour un échantillon. \n\n\n```{r}\n#| label: tbl-datavar\n#| tbl-cap: Calcul des mesures de dispersion sur des données fictives\n#| echo: false\n#| message: false\n#| warning: false\na <- c(22,25,27,30,32,35,37,40)\na <- sort(a)\nn <- length(a)\ndf <- data.frame(\n id = as.character(c(1:n)),\n x = round(a,2),\n xi_mean = a - mean(a),\n numer = (a - mean(a))^2\n)\ndf[n+1,1] <- \"**Statistique**\"\nn <- n+1\ndf[n+1,1] <- \"N\"\ndf[n+2,1] <- \"Somme\"\ndf[n+3,1] <- \"Moyenne ($\\\\bar{x}$ ou $\\\\mu$)\"\ndf[n+1,2] <- length(a)\ndf[n+2,2] <- sum(a)\ndf[n+2,4] <- sum(df$numer, na.rm = TRUE)\ndf[n+2,3] <- sum(df$xi_mean, na.rm = TRUE)\ndf[n+3,2] <- mean(a)\ndf[n+3,3] <- sum(df$xi_mean, na.rm = TRUE)/n\ndf[n+3,4] <- round(mean((a - mean(a))^2),2)\ndf[n+4,1] <- \"Étendue\"\ndf[n+4,2] <- max(a)-min(a)\ndf[n+5,1] <- \"Premier quartile\"\ndf[n+6,1] <- \"Troisième quartile\"\ndf[n+5,2] <- quantile(a, type = 1)[2]\ndf[n+6,2] <- quantile(a, type = 1)[4]\ndf[n+7,1] <- \"Intervalle interquartile\"\ndf[n+7,2] <- quantile(a, type = 1)[4]-quantile(a, type = 1)[2]\ndf[n+8,1] <- \"Variance (population, $\\\\sigma^2$)\"\ndf[n+9,1] <- \"Écart-type (population, $\\\\sigma$)\"\ndf[n+10,1] <- \"Variance (échantillon, $s^2$)\"\ndf[n+11,1] <- \"Écart-type (échantillon, $s$)\"\ndf[n+8,2] <- round(mean((a - mean(a))^2),2)\ndf[n+9,2] <- round(sqrt(mean((a - mean(a))^2)),2)\ndf[n+10,2] <- round(var(a),2)\ndf[n+11,2] <- round(sd(a),2)\ndf[n+12,1] <- \"Coefficient de variation ($\\\\sigma / \\\\mu$)\"\ndf[n+13,1] <- \"Coefficient de variation ($s / \\\\bar{x}$)\"\ndf[n+12,2] <- round(sqrt(mean((a - mean(a))^2))/mean(a),2)\ndf[n+13,2] <- round(sd(a)/mean(a),2)\nopts <- options(knitr.kable.NA = \"\")\n\nknitr::kable(df,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Observation\" , \"$x_i$\" , \"$x_i-\\\\bar{x}$\" , \"$(x_i-\\\\bar{x})^2$\"),\n align= c(\"l\", \"r\", \"c\", \"r\")\n )\n``` \n\nLe @tbl-datavar2 vise à démontrer, à partir de trois variables, comment certaines mesures de dispersion sont sensibles à l'unité de mesure et/ou aux valeurs extrêmes. \n\nConcernant **l'unité de mesure**, nous avons créé deux variables *A* et *B*, où *B* étant simplement *A* multipliée par 10. Pour *A*, les valeurs de la moyenne, de l'étendue et de l'intervalle interquartile sont respectivement 31, 18 et 10. Sans surprise, celles de *B* sont multipliées par 10 (310, 180, 100). La variance étant la moyenne des déviations à la moyenne au carré, elle est égale à 33,50 pour *A* et donc à $\\mbox{33,50}\\times10^2=\\mbox{3350}$ pour *B*; l'écart-type de *B* est égal à celui de *A* multiplié par 10. Cela démontre que l'étendue, l'intervalle interquartile, la variance et l'écart-type sont des mesures de dispersion dépendantes de l'unité de mesure. Par contre, étant donné que le coefficient de variation (CV) est le rapport de l'écart-type avec la moyenne, il a la même valeur pour *A* et *B*, ce qui démontre que le CV est bien une mesure de dispersion relative permettant de comparer des variables exprimées dans des unités de mesure différentes.\n\nConcernant **la sensibilité aux valeurs extrêmes**, nous avons créé la variable *C* pour laquelle seule la huitième observation a une valeur différente (40 pour *A* et 105 pour *B*). Cette valeur de 105 pourrait être soit une valeur extrême positive mesurée, soit une valeur aberrante (par exemple, si l'unité de mesure était un pourcentage variant de 0 à 100 %). Cette valeur a un impact important sur la moyenne (31 contre 39,12) et l'étendue (18 contre 83) et corollairement sur la variance (33,50 contre 641,86), l'écart-type (5,79 contre 25,33) et le coefficient de variation (0,19 contre 0,65). Par contre, comme l'intervalle interquartile est calculé sur 50 % des observations centrales ($\\mbox{Q3}-\\mbox{Q1}$), il n'est pas affecté par cette valeur extrême.\n\n\n```{r}\n#| label: tbl-datavar2\n#| tbl-cap: Illustration de la sensibilité des mesures de dispersion à l'unité de mesure et aux valeurs extrêmes\n#| echo: false\n#| message: false\n#| warning: false\na1 <- c(22,25,27,30,32,35,37,40)\nc1 <- c(22,25,27,30,32,35,37,105)\nb1 <- a*10\nvar.a <- round(mean((a1 - mean(a1))^2),2)\nvar.b <- round(mean((b1 - mean(b1))^2),2)\nvar.c <- round(mean((c1 - mean(c1))^2),2)\nsd.a <- round(sqrt(mean((a1 - mean(a1))^2)),2)\nsd.b <- round(sqrt(mean((b1 - mean(b1))^2)),2)\nsd.c <- round(sqrt(mean((c1 - mean(c1))^2)),2)\na1 <- sort(a1)\nb1 <- sort(b1)\nc1 <- sort(c1)\nn <- length(a1)\ndf <- data.frame(\n id = as.character(c(1:n)),\n A = round(a1,2),\n B = round(b1,2),\n C = round(c1,2)\n)\ndf[n+1,1] <- \"**Statistique**\"\nn <- n+1\ndf[n+1,1] <- \"Moyenne ($\\\\mu$)\"\ndf[n+2,1] <- \"Étendue\"\ndf[n+3,1] <- \"Intervalle interquartile\"\ndf[n+4,1] <- \"Variance (population, $\\\\sigma^2$)\"\ndf[n+5,1] <- \"Écart-type (population, $\\\\sigma$)\"\ndf[n+6,1] <- \"Coefficient de variation ($\\\\sigma / \\\\mu$)\"\ndf[n+1,2] <- mean(a1)\ndf[n+2,2] <- max(a1)-min(a1)\ndf[n+3,2] <- quantile(a1, type = 1)[4]-quantile(a1, type = 1)[2]\ndf[n+4,2] <- round(var.a,2)\ndf[n+5,2] <- round(sd.a,2)\ndf[n+6,2] <- round(sd.a/mean(a1),2)\ndf[n+1,3] <- mean(b1)\ndf[n+2,3] <- max(b1)-min(b1)\ndf[n+3,3] <- quantile(b1, type = 1)[4]-quantile(b1, type = 1)[2]\ndf[n+4,3] <- round(var.b,2)\ndf[n+5,3] <- round(sd.b,2)\ndf[n+6,3] <- round(sd.b/mean(b1),2)\ndf[n+1,4] <- round(mean(c1),2)\ndf[n+2,4] <- max(c1)-min(c1)\ndf[n+3,4] <- quantile(c1, type = 1)[4]-quantile(c1, type = 1)[2]\ndf[n+4,4] <- round(var.c,2)\ndf[n+5,4] <- round(sd.c,2)\ndf[n+6,4] <- round(sd.c/mean(c1),2)\nopts <- options(knitr.kable.NA = \"\")\n\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Observation\" , \"A\" , \"B\" , \"C\"), \n align= c(\"l\", \"r\", \"r\", \"r\"))\n```\n\n\n```{r}\n#| label: tbl-resume\n#| tbl-cap: Résumé de la sensibilité de la moyenne et des mesures de dispersion\n#| echo: false\n#| message: false\n#| warning: false\na1 <- c(\"Moyenne\", \"Étendue\",\n \"Intervalle interquartile\",\n \"Variance\", \"Écart-type\", \"Coefficient de variation\")\nb1 <- c(\"X\" , \"X\" , \"X\" , \"X\" , \"X\" , \"\")\nc1 <- c(\"X\" , \"X\" , \"\" , \"X\" , \"X\" , \"X\")\ndf <- data.frame(\n Stat = a1,\n Unite = b1,\n Outlier = c1\n)\nopts <- options(knitr.kable.NA = \"\")\n\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Statistique\" , \"Unité de mesure\" , \"Valeurs extrêmes\"),\n align= c(\"l\", \"c\", \"c\"))\n```\n\n\n### Paramètres de forme {#sec-0254}\n\n#### Vérification de la normalité d'une variable quantitative\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Normalité d'une variable**\n:::\n::: bloc_objectif-body\nDe nombreuses méthodes statistiques qui sont abordées dans les chapitres suivants – entre autres, la corrélation de Pearson, les test *t* et l'analyse de variance, les régressions simple et multiple – requièrent que la variable quantitative suive une **distribution normale** (nommée aussi **distribution gaussienne**).\n\nDans cette sous-section, nous décrivons trois démarches pour vérifier si la distribution d'une variable est normale : les coefficients d'asymétrie et d'aplatissement (*skewness* et *kurtosis* en anglais), les graphiques (histogramme avec courbe normale et diagramme quantile-quantile), les tests de normalité (tests de Shapiro-Wilk, de Kolmogorov-Smirnov, de Lilliefors, d'Anderson-Darling et de Jarque-Bera).\n\n**Il est vivement recommandé de réaliser les trois démarches!**\n:::\n:::\n\nUne distribution est normale quand elle est symétrique et mésokurtique (@fig-FormeDistr).\n\n![Formes d'une distribution et coefficients d'asymétrie et d'aplatissement](images/Chap02/FormeDistribution.jpg){#fig-FormeDistr width=\"70%\" fig-align=\"center\"}\n\n##### Vérification de la normalité avec les coefficients d'asymétrie et d'aplatissement\n\n**Une distribution est dite symétrique** quand la moyenne arithmétique est au centre de la distribution, c'est-à-dire que les observations sont bien réparties de part et d'autre de la moyenne qui est alors égale à la médiane et au mode (nous utilisons uniquement le mode pour une variable discrète et non pour une variable continue). Pour évaluer l'asymétrie, nous utilisons habituellement le coefficient d'asymétrie (*skewness* en anglais). \n\nSachez toutefois qu'il existe trois façons (formules) pour le calculer [@joanes1998comparing] : $g_1$ est la formule classique (@eq-SkewType1), disponible dans R avec la fonction `skewness` du *package* `moments`), $G_1$ est une version ajustée (@eq-SkewType2), utilisée dans les logiciels SAS et SPSS notamment) et $b_1$ est une autre version ajustée (@eq-SkewType3), utilisée par les logiciels MINITAB et BMDP). Nous verrons qu'avec les *packages* `DescTools` ou `e1071`, il est possible de calculer ces trois méthodes. Aussi, pour de grands échantillons ($n>100$), il y a très peu de différences entre les résultats produits par ces trois formules [@joanes1998comparing]. Quelle que soit la formule utilisée, le coefficient d'asymétrie s'interprète comme suit (@fig-asymetrie) :\n\n* Quand la valeur du *skewness* est négative, la **distribution est asymétrique négative**. La distribution est alors tirée à gauche par des valeurs extrêmes faibles, mais peu nombreuses. Nous employons souvent l'expression *la queue de distribution* est étirée vers la gauche. La moyenne est alors inférieure à la médiane.\n\n* Quand la valeur du *skewness* est égale à 0, **la distribution est symétrique** (la médiane est égale à la moyenne). Pour une variable discrète, les valeurs du mode, de la moyenne et de la médiane sont égales.\n\n* Quand la valeur du *skewness* est positive, la **distribution est symétrique positive**. La distribution est alors tirée à droite par des valeurs extrêmes fortes, mais peu nombreuses. La queue de distribution est alors étirée vers la droite et la moyenne est supérieure à la médiane. En sciences sociales, les variables de revenu (totaux ou d'emploi, des individus ou des ménages) ont souvent des distributions asymétriques positives : la moyenne est affectée par quelques observations avec des valeurs de revenu très élevées et est ainsi supérieure à la médiane. En études urbaines, la densité de la population pour des unités géographiques d'une métropole donnée (secteur de recensement par exemple) a aussi souvent une distribution asymétrique positive : quelques secteurs de recensement au centre de la métropole sont caractérisés par des valeurs de densité très élevées qui tirent la distribution vers la droite.\n\n$$ \ng_1=\\frac{ \\frac{1}{n} \\sum_{i=1}^n(x_i-\\bar{x})^3} { \\left[\\frac{1}{n}\\sum_{i=1}^n(x_i-\\bar{x})^2\\right] ^\\frac{3}{2}}\n$$ {#eq-SkewType1}\n\n$$ \nG_1= \\frac{\\sqrt{n(n-1)}}{n-2} g_1\n$$ {#eq-SkewType2}\n\n$$\nb_1= \\left( \\frac{n-1}{n} \\right) ^\\frac{3}{2} g_1\n$$ {#eq-SkewType3}\n\n\n```{r}\n#| label: fig-asymetrie\n#| fig-cap: Asymétrie d'une distribution\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| out-width: \"100%\"\n\nlibrary(DescTools)\nlibrary(ggplot2)\nlibrary(ggpubr)\nlibrary(SimDesign)\n\ntofr <- function(float){\n return(gsub(\".\" , \",\", as.character(float), fixed = TRUE, useBytes = TRUE))\n}\n\n# Générer des distributions asymétriques\ndf <- data.frame(\n Normale = rnorm(1500,0,1),\n Skewed_L = rValeMaurelli(1500, mean = 0, sigma = 1, skew = -1.4, kurt = 3),\n Skewed_R = rValeMaurelli(1500, mean = 0, sigma = 1, skew = 1.4, kurt = 3),\n L = rValeMaurelli(1500, mean = 0, sigma = 1, skew =0, kurt = 7),\n P = rValeMaurelli(1500, mean = 0, sigma = 1, skew = 0, kurt = -1)\n)\nstatsL <- c(mean(df$Skewed_L), median(df$Skewed_L), Skew(df$Skewed_L), Kurt(df$Skewed_L))\nstatsR <- c(mean(df$Skewed_R), median(df$Skewed_R), Skew(df$Skewed_R), Kurt(df$Skewed_R))\nstatsN <- c(mean(df$Normale), median(df$Normale), Skew(df$Normale) ,Kurt(df$Normale))\nCaptionL <- paste(\"Moyenne = \", tofr(round(statsL[1],2)), \n \"\\nMédiane = \", tofr(round(statsL[2],2)), \n \"\\nSkewness = \", tofr(round(statsL[3],2)), \n sep = \"\")\nCaptionR <- paste(\"Moyenne = \", tofr(round(statsR[1],2)), \n \"\\nMédiane = \", tofr(round(statsR[2],2)), \n \"\\nSkewness = \", tofr(round(statsR[3],2)), \n sep = \"\")\nCaptionN <- paste(\"Moyenne = \", tofr(round(statsN[1],2)), \n \"\\nMédiane = \", tofr(round(statsN[2],2)), \n \"\\nSkewness = \", tofr(round(statsN[3],2)), \n sep = \"\")\nGl <- ggplot(data = df, mapping = aes(x = Skewed_L))+\n geom_histogram(color = \"white\", fill = \"bisque3\", aes(y = ..density..))+\n stat_function(fun = dnorm, args = list(mean = mean(df$Skewed_L), sd = sd(df$Skewed_L)), color = \"black\", linewidth = 1)+\n labs(title = \"a. Asymétrie négative\",\n subtitle = \"Moyenne < Médiane\",\n x = \"\", \n y = \"Densité\",\n caption = CaptionL)+\n geom_vline(xintercept = statsL[1], color = \"cadetblue4\", linewidth = .8)+\n geom_vline(xintercept = statsL[2], color = \"coral4\", linewidth = .8)+\n theme(\n plot.title = element_text(hjust = 0.5, size = 9, face = \"bold\"),\n plot.subtitle = element_text(hjust = 0.5, size = 8, face = \"plain\"),\n plot.caption = element_text(hjust = 0.5, size = 8, face = \"plain\")\n )\n \nGr <- ggplot(data = df, mapping = aes(x = Skewed_R))+\n geom_histogram(color = \"white\", fill = \"bisque3\", aes(y = ..density..))+\n stat_function(fun = dnorm, args = list(mean = mean(df$Skewed_R), sd = sd(df$Skewed_R)), color = \"black\", linewidth = 1)+\n labs(title = \"b. Asymétrie positive\",\n subtitle = \"Moyenne > Médiane\",\n x = \"\", y = \"\",\n caption = CaptionR)+\n geom_vline(xintercept = statsR[1], color = \"cadetblue4\", linewidth = .8)+\n geom_vline(xintercept = statsR[2], color = \"coral4\", linewidth = .8)+\n theme(\n plot.title = element_text(hjust = 0.5, size = 9, face = \"bold\"),\n plot.subtitle = element_text(hjust = 0.5, size = 8, face = \"plain\"),\n plot.caption = element_text(hjust = 0.5, size = 8, face = \"plain\")\n )\nGn <- ggplot(data = df, mapping = aes(x = Normale))+\n geom_histogram(color = \"white\", fill = \"bisque3\", aes(y = ..density..))+\n stat_function(fun = dnorm, args = list(mean = mean(df$Normale), sd = sd(df$Normale)), color = \"black\", linewidth = 1)+\n labs(title = \"c. Asymétrie nulle\", \n subtitle = \"Moy. et méd. très semblables\",\n x = \"\", y = \"\",\n caption = CaptionN)+\n geom_vline(xintercept = statsN[1], color = \"cadetblue4\", linewidth = .8)+\n geom_vline(xintercept = statsN[2], color = \"coral4\", linewidth = .8)+\n theme(\n plot.title = element_text(hjust = 0.5, size = 9, face = \"bold\"),\n plot.subtitle = element_text(hjust = 0.5, size = 8, face = \"plain\"),\n plot.caption = element_text(hjust = 0.5, size = 8, face = \"plain\")\n )\nggarrange(Gl, Gn, Gr, ncol = 2, nrow = 2)\n```\n\n\n**Pour évaluer l'aplatissement d'une distribution**, nous utilisons le coefficient d’aplatissement (*kurtosis* en anglais). Là encore, il existe trois formules pour le calculer (équations [-@eq-KurtType1], [-@eq-KurtType2], [-@eq-KurtType3]) qui renvoient des valeurs très semblables pour de grands échantillons [@joanes1998comparing]. Cette mesure s'interprète comme suit (@fig-asymetrie) :\n\n* Quand la valeur du *kurtosis* est négative, la **distribution est platikurtique**. La distribution est dite plate, c'est-à-dire que la valeur de l'écart-type est importante (comparativement à une distribution normale), signalant une grande dispersion des valeurs de part et d'autre la moyenne.\ns\n* Quand la valeur du *kurtosis* est égale à 0, **la distribution est mésokurtique**, ce qui est typique d'une distribution normale.\n\n* Quand la valeur du *kurtosis* est positive, la **distribution est leptokurtique**, signalant que l'écart-type (la dispersion des valeurs) est plutôt faible. Autrement dit, la dispersion des valeurs autour de la moyenne est faible.\n\n$$\ng_2=\\frac{\\frac{1}{n}\\sum_{i=1}^n(x_i-\\bar{x})^4} {\\left( \\frac{1}{n}\\sum_{i=1}^n(x_i-\\bar{x})^2\\right)^2}-3\n$$ {#eq-KurtType1}\n\n$$ \nG_2 = \\frac{n-1}{(n-2)(n-3)} \\{(n+1) g_2 + 6\\}\n$$ {#eq-KurtType2}\n\n$$ \nb_2 = (g_2 + 3) (1 - 1/n)^2 - 3\n$$ {#eq-KurtType3}\n\n```{r}\n#| label: fig-kurtosis\n#| fig-cap: Applatissement d'une distribution\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| out-width: \"100%\"\nlibrary(DescTools)\nlibrary(ggplot2)\nlibrary(ggpubr)\nlibrary(SimDesign)\n# Générer des distributions asymétriques\nstatsM <- c(mean(df$Normale), median(df$Normale), Skew(df$Normale), Kurt(df$Normale))\nstatsL <- c(mean(df$L), median(df$L), Skew(df$L), Kurt(df$L))\nstatsP <- c(mean(df$P), median(df$P), Skew(df$P), Kurt(df$P))\nCaptionN <- paste(\"\\nKurtosis = \", as.character(round(Kurt(df$Normale), 2)), sep = \"\")\nCaptionL <- paste(\"\\nKurtosis = \", as.character(round(Kurt(df$L), 2)), sep = \"\")\nCaptionP <- paste(\"\\nKurtosis = \", as.character(round(Kurt(df$P), 2)), sep = \"\")\nGl <- ggplot(data = df, mapping = aes(x = L))+\n geom_histogram(color = \"white\", fill = \"bisque3\", aes(y = ..density..))+\n stat_function(fun = dnorm, args = list(mean = mean(df$L), sd = sd(df$L)), color = \"black\", linewidth = 1)+\n labs(title = \"a. Distribution leptokurtique\",\n x = \"\",\n y = \"Densité\",\n subtitle = CaptionL)+\n geom_vline(xintercept = statsL[1], color = \"cadetblue4\", linewidth = .8)+\n theme(\n plot.title = element_text(hjust = 0.5, size = 9, face = \"bold\"),\n plot.subtitle = element_text(hjust = 0.5, size = 8, face = \"plain\"),\n plot.caption = element_text(hjust = 0.5, size = 8, face = \"plain\")\n )\nGm <- ggplot(data = df, mapping = aes(x = Normale))+\n geom_histogram(color = \"white\", fill = \"bisque3\", aes(y = ..density..))+\n stat_function(fun = dnorm, args = list(mean = mean(df$Normale), sd = sd(df$Normale)), color = \"black\", linewidth = 1)+\n labs(title = \"b. Distribution mésokurtique\",\n x = \"\", y = \"\",\n subtitle = CaptionN)+\n geom_vline(xintercept = statsM[1], color = \"cadetblue4\", linewidth = .8)+\n theme(\n plot.title = element_text(hjust = 0.5, size = 9, face = \"bold\"),\n plot.subtitle = element_text(hjust = 0.5, size = 8, face = \"plain\"),\n plot.caption = element_text(hjust = 0.5, size = 8, face = \"plain\")\n )\nGp <- ggplot(data = df, mapping = aes(x = P))+\n geom_histogram(color = \"white\", fill = \"bisque3\", aes(y = ..density..))+\n stat_function(fun = dnorm, args = list(mean = mean(df$P), sd = sd(df$P)), color = \"black\", linewidth = 1)+\n labs(title = \"c. Distribution platikurtique\",\n x = \"\", y = \"\",\n subtitle = CaptionP)+\n geom_vline(xintercept = statsN[1], color = \"cadetblue4\", linewidth = .8)+\n theme(\n plot.title = element_text(hjust = 0.5, size = 9, face = \"bold\"),\n plot.subtitle = element_text(hjust = 0.5, size = 8, face = \"plain\"),\n plot.caption = element_text(hjust = 0.5, size = 8, face = \"plain\")\n )\nggarrange(Gp, Gm, Gl, ncol = 2, nrow = 2)\n```\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Kurtosis normalisé**\n:::\n::: bloc_attention-body\nRegardez attentivement les équations [-@eq-KurtType1], [-@eq-KurtType2], [-@eq-KurtType3]; vous remarquez que pour $g_2$ et $b_2$, il y a une soustraction de 3 et une addition 6 pour $G_2$. Nous parlons alors de *kurtosis* normalisé (*excess kurtosis* en anglais). Pour une distribution normale, il prend la valeur de 0, comparativement à la valeur de 3 pour un *kurtosis* non normalisé. Par conséquent, avant de calculer le *kurtosis*, il convient de s'assurer que la fonction que vous utilisez implémente une méthode de calcul normalisée (donnant une valeur de 0 pour une distribution normale). Par exemple, la fonction `Kurt` du *package* `DescTools` calcule les trois formules normalisées tandis que la fonction `kurtosis` du *package* `moments` renvoie un *kurtosis* non normalisé.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(DescTools)\nlibrary(moments)\n# Générer une variable normalement distribuée avec 1000 observations\nNormale <- rnorm(1500,0,1)\nround(DescTools::Kurt(Normale),3)\nround(moments::kurtosis(Normale),3)\n```\n:::\n:::\n\n##### Vérification de la normalité avec des graphiques\n\nLes graphiques sont un excellent moyen de vérifier visuellement si une distribution est normale ou pas. Bien entendu, les histogrammes, que nous avons déjà largement utilisés, sont un incontournable. À titre de rappel, ils permettent de représenter la forme de la distribution des données (@fig-CourbeNormale). Un autre type de graphique intéressant est le **diagramme quantile-quantile** (*Q-Q plot* en anglais), qui permet de comparer la distribution d'une variable avec une distribution gaussienne (normale). Trois éléments composent ce graphique comme illustré à la @fig-qqplot :\n\n* les points, représentant les observations de la variable;\n* la distribution gaussienne (normale), représentée par une ligne;\n* l'intervalle de confiance à 95 % de la distribution normale (en marron sur la figure).\n\nQuand la variable est normalement distribuée, les points sont situés le long de la ligne. Plus les points localisés en dehors de l'intervalle de confiance (bande marron) sont nombreux, plus la variable est alors anormalement distribuée.\n\n\n```{r}\n#| label: fig-CourbeNormale\n#| fig-cap: Histogrammes et courbe normale\n#| fig-align: center\n#| out-width: \"90%\"\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(ggplot2)\nlibrary(reshape2)\nlibrary(qqplotr)\nmelted_dist <- melt(df,\n distributions = c(\"Normale\", \"Skewed_L\",\n \"Skewed_R\" , \"student\", \"L\", \"P\"))\nnames(melted_dist) <- c(\"distribution\", \"valeur\")\nmelted_dist$distribution <- factor(melted_dist$distribution,\n levels = c(\"Normale\" , \"Skewed_L\" , \"Skewed_R\" , \"L\" , \"P\"),\n labels = c(\"Normale\",\n \"Asymétrie négative\",\n \"Asymétrie positive\",\n \"Leptokurtique\",\n \"Platikurtique\"))\nggplot(data = melted_dist, mapping = aes(x = valeur))+\n labs(caption = paste0(\"Skewness\", \"Kurtosis\", sep = \"\"))+\n geom_histogram(color = \"white\", fill = \"bisque3\", aes(y = ..density..))+\n stat_function(fun = dnorm, args = list(mean = mean(melted_dist$valeur), sd = sd(melted_dist$valeur)), color = \"black\", linewidth = 1)+\n geom_vline(xintercept = mean(melted_dist$valeur), color = \"cadetblue4\", linewidth = .8)+\n labs(y = \"Densité\", x = \"\", title = \"\", caption= \"\")+\n facet_wrap(vars(distribution), ncol = 2, scales = \"free\")\n```\n\n```{r}\n#| label: fig-qqplot\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Diagrammes quantile-quantile\n#| out-width: \"90%\"\nggplot(data = melted_dist, aes(sample=valeur))+\n stat_qq_band(fill = \"bisque3\")+\n stat_qq_line(color = \"black\", size=.3) +\n stat_qq(color = \"black\", size = 1)+\n labs(y = \"Échantillon\", x = \"théorique\", title = \"\", caption= \"\")+\n facet_wrap(vars(distribution), ncol = 2, scales = \"free\")\n```\n\n##### Vérification de la normalité avec des tests de normalité {#sec-025413}\n\nCinq principaux tests d'hypothèse permettent de vérifier la normalité d'une variable : les tests de **Kolmogorov-Smirnov** (KS), de **Lilliefors** (LF), de **Shapiro-Wilk** (SW), d'**Anderson-Darling** et de **Jarque-Bera** (JB). Sachez toutefois qu'il y en a d'autres non discutés ici (tests d’Agostino–Pearson, de Cramer–von Mises, de Ryan-Joiner, de Shapiro–Francia, etc.). Pour les formules et une description détaillée de ces tests, vous pouvez consulter Razali et al. [-@razali2011power] ou Yap et Sim [-@yap2011comparisons]. **Quel test choisir?** Plusieurs auteur(e)s ont comparé ces différents tests à partir de plusieurs échantillons, et ce, en faisant varier la forme de la distribution et le nombre d'observations [@razali2011power;@yap2011comparisons]. Selon Razali et al. [-@razali2011power], le meilleur test semble être celui de Shapiro-Wilk, puis ceux d'Anderson-Darling, de Lilliefors et de Kolmogorov-Smirnov. Yap et Sim [-@yap2011comparisons] concluent aussi que le Shapiro-Wilk semble être le plus performant.\n\nQuoi qu'il en soit, ces cinq tests postulent que la variable suit une distribution gaussienne (hypothèse nulle, H~0~). \n\nCela signifie que si la valeur de *p* associée à la valeur de chacun des tests est inférieure ou égale au seuil alpha choisi (habituellement $\\alpha=\\mbox{0,05}$), la distribution est anormale. À l'inverse, si $p>\\mbox{0,05}$, la distribution est normale.\n\n```{r}\n#| label: tbl-testnormalites\n#| tbl-cap: Différents tests d'hypothèse pour la normalité\n#| echo: false\n#| message: false\n#| warning: false\noptions(knitr.kable.NA = '')\n\ndf <- data.frame(\n Test = c(\"Kolmogorov-Smirnov\",\n \"Lilliefors\",\n \"Shapiro-Wilk\",\n \"Anderson-Darling\",\n \"Jarque-Bera\"),\n Interpretation =\n c(\"Plus sa valeur est proche de zéro, plus la distribution est normale. L'avantage de ce test est qu'il peut être utilisé pour vérifier si une variable suit la distribution de n'importe quelle loi (autre que la loi normale).\",\n \"Ce test est une adaptation du test de Kolmogorov-Smirnov. Plus sa valeur est proche de zéro, plus la distribution est normale.\",\n \"Si la valeur de la statistique de Shapiro-Wilk est proche de 1, alors la distribution est normale; anormale quand elle est inférieure à 1.\",\n \"Ce test est une modification du test de Cramer-von Mises (CVM). Il peut être aussi utilisé pour tester d'autres distributions (uniforme, log-normale, exponentielle, Weibull, distribution de Pareto généralisée, logistique, etc.).\",\n \"Basé sur un test du type multiplicateur de Lagrange, ce test utilise dans son calcul les valeurs du *Skewness* et du *Kurtosis*. Plus sa valeur s'approche de 0, plus la distribution est normale. Ce test est surtout utilisé pour vérifier si les résidus d'un modèle de régression linéaire sont normalement distribués; nous y reviendrons dans le chapitre sur la régression multiple. Il s'écrit $JB=\\\\frac{1}{6} \\\\left({g_1}^2+\\\\frac{{g_1}^2}{4} \\\\right)$ avec $g_1$ et $g_2$ qui sont respectivement les valeurs du *skewness* et du *kurtosis* de la variable (voir les équations [-@eq-SkewType1] et [-@eq-KurtType1].\"),\n Fonction= c(\"`ks.test` du *package* `stats`\",\n \"`lillie.test` du *package* `nortest`\",\n \"`shapiro.test` du *package* `stats`\",\n \"`ad.test` du *package* `stats`\",\n \"`JarqueBeraTest` du *package* `DescTools`\")\n )\n\nknitr::kable(\n df,\n col.names = c(\"Test\" , \"Propriétés et interprétation\", \"Fonction R\"),\n col.to.resize = c(2,3),\n col.width = \"6cm\"\n)\n```\n\nDans le @tbl-calcultestnormalites sont reportées les valeurs des différents tests pour les cinq types de distribution générés à la @fig-CourbeNormale. Sans surprise, pour l'ensemble des tests, la valeur de *p* est inférieure à 0,05 pour la distribution normale.\n\n```{r}\n#| label: tbl-calcultestnormalites\n#| tbl-cap: Tests de normalité pour différentes distributions\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(DescTools)\nlibrary(nortest)\ndf <- data.frame(\n Normale = rnorm(500,0,1),\n Skewed_L = rValeMaurelli(500, mean = 0, sigma = 1, skew = 1.4, kurt = 3),\n Skewed_R = rValeMaurelli(500, mean = 0, sigma = 1, skew = -1.4, kurt = 3),\n L = rValeMaurelli(500, mean = 0, sigma = 1, skew = 0, kurt = 7),\n P = rValeMaurelli(500, mean = 0, sigma = 1, skew = 0, kurt = -1)\n)\nvars <- names(df)\nS <- c()\nK <- c()\nKS <- c()\nKS.p <- c()\nLF <- c()\nLF.p <- c()\nSW <- c()\nSW.p <- c()\nAD <- c()\nAD.p <- c()\nJB <- c()\nJB.p <- c()\ni <- 1\nfor (e in vars){\n ksmirnov <- ks.test(df[[e]], \"pnorm\", mean=mean(df[[e]]), sd=sd(df[[e]]))\n lillie <- lillie.test(df[[e]])\n shapiro <- shapiro.test(df[[e]])\n AndDarling <- ad.test(df[[e]])\n JarqueB <- JarqueBeraTest(df[[e]], robust = TRUE)\n \n S[i] <- Skew(df[[e]])\n K[i] <- Kurt(df[[e]])\n \n KS[i] <- ksmirnov$statistic\n KS.p[i] <- ksmirnov$p.value \n \n LF[i] <- lillie$statistic\n LF.p[i] <- lillie$p.value \n \n SW[i] <- shapiro$statistic\n SW.p[i] <- shapiro$p.value\n AD[i] <- AndDarling$statistic\n AD.p[i] <- AndDarling$p.value\n \n JB[i] <- JarqueB$statistic\n JB.p[i] <- JarqueB$p.value\n i <- i+1\n}\nTests <- data.frame(\n \"S\" = round(S,3),\n \"K\" = round(K,3),\n \"KS\" = round(KS,3),\n \"LF\" = round(LF,3),\n \"SW\" = round(SW,3),\n \"AD\" = round(AD,3),\n \"JB\" = round(JB,3),\n \"KS.p\" = round(KS.p,3),\n \"LF.p\" = round(LF.p,3),\n \"SW.p\" = round(SW.p,3),\n \"AD.p\" = round(AD.p,3),\n \"JB.p\" = round(JB.p,3)\n)\nTests <- t(Tests)\nTests <- data.frame(Statistique= c(\"Skewness\" , \n\t\t\t\t\t\t\t \"Kurtosis\",\n\t\t\t\t\t\t\t \"Kolmogorov-Smirnov (KS)\",\n\t\t\t\t\t\t\t \"Lilliefors (LF)\",\n\t\t\t\t\t\t\t \"Shapiro-Wilk (SW)\",\n\t\t\t\t\t\t\t \"Anderson-Darling (AD)\",\n\t\t\t\t\t\t\t \"Jarque-Bera (JB)\",\n\t\t\t\t\t\t\t \"KS (valeur p)\",\n\t\t\t\t\t\t\t \"LF (valeur p)\",\n\t\t\t\t\t\t\t \"SW (valeur p)\",\n\t\t\t\t\t\t\t \"AD (valeur p)\",\n\t\t\t\t\t\t\t \"JB (valeur p)\"),\n Tests)\nknitr::kable(Tests,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"\" , \"Normale\" , \"Asymétrie négative\",\n \"Asymétrie positive\" , \"Leptokurtique\", \"Platikurtique\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\"))\n```\n\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Des tests restrictifs...**\n:::\n::: bloc_attention-body\nLa plupart des auteurs s'entendent sur le fait que ces tests sont très restrictifs : plus la taille de votre échantillon est importante, plus les tests risquent de vous signaler que vos distributions sont anormales (à la lecture des valeurs de *p*).\n\nCertains conseillent même de ne pas les utiliser quand $n>200$ et de vous fier uniquement aux graphiques (histogramme et diagramme Q-Q)!\n\n:::\n:::\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Combiner plusieurs méthodes pour vérifier la normalité d'une variable**\n:::\n::: bloc_astuce-body\nBref, vérifier la normalité d'une variable n'est pas une tâche si simple. De nouveau, nous vous conseillons vivement de :\n\n* Construire les graphiques pour analyser visuellement la forme de la distribution (histogramme avec courbe normale et diagramme Q-Q).\n\n* Calculer le *skewness* et le *kurtosis*.\n\n* Calculer plusieurs tests (minimalement Shapiro-Wilk et Kolmogorov-Smirnov).\n\n* Accorder une importance particulière aux graphiques lorsque vous traitez de grands échantillons ($n>200$).\n:::\n:::\n\n\n#### Tests pour d'autres formes de distribution{#sec-02adjdistrib}\n\nComme nous l'avons vu, la distribution normale n'est que l'une des multiples distributions existantes. Dans de nombreuses situations, elle ne sera pas adaptée pour décrire vos variables. La démarche à adopter pour trouver une distribution adaptée est la suivante : \n\n1. Définissez la nature de votre variable : identifier si elle est discrète ou continue et l'intervalle dans lequel elle est définie. Une variable dont les valeurs sont positives ou négatives ne peut pas être décrite avec une distribution Gamma par exemple (à moins de la décaler).\n\n2. Explorez votre variable : affichez son histogramme et son graphique de densité pour avoir une vue générale de sa morphologie.\n\n3. Présélectionnez un ensemble de distributions candidates en tenant compte des observations précédentes. Vous pouvez également vous reporter à la littérature existante sur votre sujet d'étude pour inclure d'autres distributions. Soyez flexible! Une variable strictement positive pourrait tout de même avoir une forme normale. De même, une variable décrivant des comptages suffisamment grands pourrait être mieux décrite par une distribution normale qu'une distribution de Poisson.\n\n4. Tentez d'ajuster chacune des distributions retenues à vos données et comparez les qualités d'ajustements pour retenir la plus adaptée.\n\nPour ajuster une distribution à un jeu de données, il faut trouver les valeurs des paramètres de cette distribution qui lui permettent d'adopter une forme la plus proche possible des données. Nous appelons cette opération **ajuster un modèle**, puisque la distribution théorique est utilisée pour modéliser les données. L'ajustement des paramètres est un problème d'optimisation que plusieurs algorithmes sont capables de résoudre (*gradient descent*, *Newton-Raphson method*, *Fisher scoring*, etc.). Dans R, le *package* `fitdistrplus` permet d'ajuster pratiquement n'importe quelle distribution à des données en offrant plusieurs stratégies d'optimisation grâce à la fonction `fitdist`. Il suffit de disposer d'une fonction représentant la distribution de densité ou de masse de la distribution en question, généralement noté `dnomdeladistribution` (`dnorm`, `dgamma`, `dpoisson`, etc.) dans R. Notez que certains *packages* comme `VGAM` ou `gamlss.dist` ajoutent un grand nombre de fonctions de densité et de masse à celles déjà disponibles de base dans R.\n\nPour comparer l'ajustement de plusieurs distributions théoriques à des données, trois approches doivent être combinées : \n\n* Observer graphiquement l'ajustement de la courbe théorique à l'histogramme des données. Cela permet d'éliminer au premier coup d'œil les distributions qui ne correspondent pas.\n\n* Comparer les *loglikelihood*. Le *loglikelihood* est un score d'ajustement des distributions aux données. Pour faire simple, plus le *loglikelihood* est grand, plus la distribution théorique est proche des données. Référez-vous à l'encadré suivant pour une description plus en profondeur du *loglikelihood*.\n\n* Utiliser le test de Kolmogorov-Smirnov pour déterminer si une distribution particulière est mieux ajustée pour les données.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Qu'est-ce que le _loglikelihood_**? \n:::\n::: bloc_aller_loin-body\nLe *loglikelihood* est une mesure de l'ajustement d'un modèle à des données. Il est utilisé à peu près partout en statistique. Comprendre sa signification est donc un exercice important pour développer une meilleure intuition du fonctionnement général de nombreuses méthodes. Si les concepts de fonction de densité et de fonction de masse vous semblent encore flous, reportez-vous à la [section @sec-024] sur les distributions dans un premier temps.\n\nAdmettons que nous disposons d'une variable continue *v* que nous tentons de modéliser avec une distribution *d* (il peut s'agir de n'importe quelle distribution). *d* a une fonction de densité avec laquelle il est possible de calculer, pour chacune des valeurs de *v*, la probabilité d'être observée selon le modèle *d*.\n\nPrenons un exemple concret dans R. Admettons que nous avons une variable comprenant 10 valeurs (oui, c'est un petit échantillon, mais c'est pour faire un exemple simple).\n\n```{r}\nv <- c(5,8,7,8,10,4,7,6,9,7)\nmoyenne <- mean(v)\necart_type <- sd(v)\n```\n\nEn calculant la moyenne et l'écart-type de la variable, nous obtenons les paramètres d'une distribution normale que nous pouvons utiliser pour représenter les données observées. En utilisant la fonction `dnorm` (la fonction de densité de la distribution normale), nous pouvons calculer la probabilité d'observer chacune des valeurs de *v* selon cette distribution normale.\n\n```{r}\nprobas <- dnorm(v, moyenne, ecart_type)\ndf <- data.frame(valeur = v,\n proba = probas)\nprint(df)\n```\nNous observons ainsi que les valeurs 7 et 8 sont très probables selon le modèle alors que les valeurs 4 et 10 sont très improbables.\n\nLe *likelihood* est simplement le produit de toutes ces probabilités. Il s'agit donc de **la probabilité conjointe** d'avoir observé toutes les valeurs de *v* **sous l'hypothèse** que *d* est la distribution produisant ces valeurs. Si *d* décrit efficacement *v*, alors le *likelihood* est plus grand que si *d* ne décrit pas efficacement *v*. Il s'agit d'une forme de raisonnement par l'absurde : après avoir observé *v*, nous calculons la probabilité d'avoir observé *v* (*likelihood*) si notre modèle *d* était vrai. Si cette probabilité est très basse, alors c'est que notre modèle est mauvais puisqu'on a bien observé *v*.\n\n```{r}\nlikelihood_norm <- prod(probas)\nprint(likelihood_norm)\n```\nCependant, multiplier un grand nombre de valeurs inférieures à zéro tend à produire des chiffres infiniment petits et donc à complexifier grandement le calcul. Nous préférons donc utiliser le *loglikelihood* : l'idée étant transformer les probabilités obtenues avec la fonction *log* puis d'additionner leurs résultats, puisque $log(xy) = log(x)+log(y)$. \n\n```{r}\nloglikelihood_norm <- sum(log(probas))\nprint(loglikelihood_norm)\n```\nComparons ce *loglikelihood* à celui d'un second modèle dans lequel nous utilisons toujours la distribution normale, mais avec une moyenne différente (faussée en ajoutant +3) : \n\n```{r}\nprobas2 <- dnorm(v, moyenne+3, ecart_type)\nloglikelihood_norm2 <- sum(log(probas2))\nprint(loglikelihood_norm2)\n```\nCe second *loglikehood* est plus faible, indiquant clairement que le premier modèle est plus adapté aux données.\n:::\n:::\n\nPassons à la pratique avec deux exemples.\n\n##### Temps de retard des bus de la ville de Toronto\n\nAnalysons les temps de retard pris par les bus de la ville de Toronto lorsqu'un évènement perturbe la circulation. Ce jeu de données est disponible sur le [site des données ouvertes de la Ville de Toronto](https://open.toronto.ca/catalogue/?search=bus%20delay&sort=score%20desc){target=\"_blank\"}. Compte tenu de la grande quantité d'observations, nous avons fait le choix de nous concentrer sur les évènements ayant eu lieu durant le mois de janvier 2019. Puisque la variable étudiée est une durée exprimée en minutes, elle est strictement positive (supérieure à 0), car un bus avec zéro minute de retard est à l'heure! Nous considérons également qu'un bus ayant plus de 150 minutes de retard (2 heures 30) n'est tout simplement pas passé (personne ne risque d'attendre 2 heures 30 pour prendre son bus). Commençons par charger les données et observer leur distribution empirique.\n\n```{r}\n#| label: fig-bustrt\n#| fig-align: center\n#| fig-cap: Distribution empirique des temps de retard des bus à Toronto en janvier 2019\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\nlibrary(ggplot2)\n# charger le jeu de données\ndata_trt_bus <- read.csv('data/univariee/bus-delay-2019_janv.csv', sep =';')\n# retirer les observations aberrantes\ndata_trt_bus <- subset(data_trt_bus, data_trt_bus$Min.Delay > 0 &\n data_trt_bus$Min.Delay < 150)\n# représenter la distribution empirique du jeu de données\nggplot(data = data_trt_bus) + \n geom_histogram(aes(x = Min.Delay, y = ..density..), bins = 40)+\n geom_density(aes(x = Min.Delay), color = \"blue\", bw = 2, size = 0.8)+\n labs(x = \"temps de retard (en minutes)\",\n y = \"\")\n```\n\nCompte tenu de la forme de la distribution empirique et de sa nature, quatre distributions sont envisageables : \n\n* La distribution Gamma, strictement positive et asymétrique, est aussi une généralisation de la distribution exponentielle utilisée pour modéliser des temps d'attente. Pour des raisons similaires, nous pouvons aussi retenir la distribution de Weibull et la distribution log-normale. Nous écartons ici la distribution normale asymétrique puisque le jeu de données n'a clairement pas une forme normale au départ.\n\n* La distribution de Pareto, strictement positive et permettant de représenter ici le fait que la plupart des retards durent moins de 10 minutes, mais que quelques retards sont également beaucoup plus longs.\n\nCommençons par ajuster les quatre distributions avec la fonction `fitdist` du *package* `fitdistrplus` et représentons-les graphiquement pour éliminer les moins bons candidats. Nous utilisons également le *package* `actuar` pour la fonction de densité de Pareto (`dpareto`).\n\n```{r}\n#| label: fig-bustrt2\n#| fig-align: center\n#| fig-cap: Comparaison des distributions ajustées aux données de retard des bus\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\nlibrary(fitdistrplus)\nlibrary(actuar)\nlibrary(ggpubr)\n# ajustement des modèles\nmodel_gamma <- fitdist(data_trt_bus$Min.Delay, distr = \"gamma\")\nmodel_weibull <- fitdist(data_trt_bus$Min.Delay, distr = \"weibull\")\nmodel_lognorm <- fitdist(data_trt_bus$Min.Delay, distr = \"lnorm\")\nmodel_pareto <- fitdist(data_trt_bus$Min.Delay, distr = \"pareto\", \n start = list(shape = 1, scale = 1),\n method = \"mse\") # différentes méthodes d'optimisation\n# réalisation des graphiques\nplot1 <- ggplot(data = data_trt_bus) + \n geom_histogram(aes(x = Min.Delay, y = ..density..), bins = 40)+\n stat_function(fun = dgamma, color = \"red\", size = 0.8, \n args = as.list(model_gamma$estimate))+\n labs(x = \"temps de retard (en minutes)\",\n y = \"\",\n subtitle = \"Modèle Gamma\")\nplot2 <- ggplot(data = data_trt_bus) + \n geom_histogram(aes(x = Min.Delay, y = ..density..), bins = 40)+\n stat_function(fun = dweibull, color = \"red\", linewidth = 0.8, \n args = as.list(model_weibull$estimate))+\n labs(x = \"temps de retard (en minutes)\",\n y = \"\",\n subtitle = \"Modèle Weibull\")\nplot3 <- ggplot(data = data_trt_bus) + \n geom_histogram(aes(x = Min.Delay, y = ..density..), bins = 40)+\n stat_function(fun = dlnorm, color = \"red\", linewidth = 0.8, \n args = as.list(model_lognorm$estimate))+\n labs(x = \"temps de retard (en minutes)\",\n y = \"\",\n subtitle = \"Modèle log-normal\")\nplot4 <- ggplot(data = data_trt_bus) + \n geom_histogram(aes(x = Min.Delay, y = ..density..), bins = 40)+\n stat_function(fun = dpareto, color = \"red\", linewidth = 0.8, \n args = as.list(model_pareto$estimate))+\n labs(x = \"temps de retard (en minutes)\",\n y = \"\",\n subtitle = \"Modèle Pareto\")\nggarrange(plotlist = list(plot1, plot2, plot3, plot4),\n ncol = 2, nrow = 2)\n```\n\nVisuellement, nous constatons que la distribution de Pareto est un mauvais choix. Pour les trois autres distributions, la comparaison des valeurs de *loglikelihood* s'impose (@tbl-distribs).\n\n```{r}\n#| label: tbl-distribs\n#| tbl-cap: Comparaison des LogLikelihood des trois distributions\n#| echo: false\n#| #| message: false\n#| warning: false\n#| out-width: \"50%\"\ndf <- data.frame(model = c(\"Gamma\" , \"Weibull\",\n \"log-normal\"), \n loglikelihood = c(model_gamma$loglik, \n model_weibull$loglik,\n model_lognorm$loglik))\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Distribution\" , \"LogLikelihood\"),\n align= c(\"l\", \"r\"))\n```\nLe plus grand *logLikelihood* est obtenu par la distribution Gamma qui s'ajuste donc le mieux à nos données. Pour finir, nous pouvons tester formellement, avec le test de Kolmogorov-Smirnov, si les données proviennent bien de cette distribution Gamma.\n\n```{r}\n#| message: false\n#| warning: false\nparams <- as.list(model_gamma$estimate)\nks.test(data_trt_bus$Min.Delay,\n y = pgamma, shape = params$shape, rate = params$rate)\n```\n\nComme la valeur de *p* est inférieure à 0,05, nous ne pouvons pas accepter l'hypothèse que notre jeu de données suit effectivement une loi de Gamma. Considérant le nombre d'observations et le fait que de nombreux temps d'attente sont identiques (ce à quoi le test est très sensible), ce résultat n'est pas surprenant. La distribution Gamma reste cependant la distribution qui représente le mieux nos données. Nous pouvons estimer grâce, à cette distribution, la probabilité qu'un bus ait un retard de plus de 10 minutes de la façon suivante : \n\n```{r}\n#| message: false\n#| warning: false\npgamma(10, shape = params$shape, rate = params$rate, lower.tail = FALSE)\n```\n\nce qui correspond à 54 % de chance. \n\nPour moins de 10 minutes : \n```{r}\n#| message: false\n#| warning: false\npgamma(10, shape = params$shape, rate = params$rate, lower.tail = TRUE)\n```\n\nsoit 46 %.\n\nUn dernier exemple avec la probabilité qu'un retard dépasse 45 minutes : \n\n```{r}\n#| message: false\n#| warning: false\npgamma(45, shape = params$shape, rate = params$rate, lower.tail = FALSE)\n```\nSoit seulement 1,3 %. \n\nPar conséquent, si un matin à Toronto votre bus a plus de 45 minutes de retard, bravo, vous êtes tombé sur une des très rares occasions où un tel retard se produit!\n\n##### Accidents de vélo à Montréal\n\nLe second jeu de données représente le nombre d'accidents de la route impliquant un vélo sur les intersections dans les quartiers centraux de Montréal (@fig-accmtl). Le jeu de données complet est disponible sur le site des [données ouvertes](http://donnees.ville.montreal.qc.ca/dataset/collisions-routieres){target=\"_blank\"} de la Ville de Montréal. Puisque ces données correspondent à des comptages, la première distribution à envisager est la distribution de Poisson. Cependant, puisque nous aurons également un grand nombre d'intersections sans accident, il serait judicieux de tester la distribution de Poisson avec excès de zéro.\n\n```{r}\n#| label: fig-accmtl\n#| fig-align: center\n#| fig-cap: Distribution empirique du nombre d'accidents par intersection impliquant un ou une cycliste à Montréal en 2017 dans les quartiers centraux\n#| out-width: \"65%\"\nlibrary(ggplot2)\n# charger le jeu de données\ndata_accidents <- read.csv('data/univariee/accidents_mtl.csv', sep =',')\ncounts <- data.frame(table(data_accidents$nb_accident))\nnames(counts) <- c(\"nb_accident\",'frequence')\ncounts$nb_accident <- as.numeric(as.character(counts$nb_accident))\ncounts$prop <- counts$frequence / sum(counts$frequence)\n# représenter la distribution empirique du jeu de donnée\nggplot(data = counts) + \n geom_bar(aes(x = nb_accident, weight = frequence), width = 0.5)+\n labs(x = \"nombre d'accidents\",\n y = \"fréquence\")\n```\nNous avons effectivement de nombreux zéros, alors essayons d'ajuster nos deux distributions à ce jeu de données. Dans la @fig-accmtldist, les barres grises représentent la distribution empirique du jeu de données et les barres rouges, les distributions théoriques ajustées. Nous utilisons ici le *package* `gamlss.dist` pour avoir la fonction de masse d'une distribution de Poisson avec excès de zéros.\n\n```{r}\n#| label: fig-accmtldist\n#| fig-align: center\n#| fig-cap: Ajustement des distributions de Poisson et Poisson avec excès de zéros\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\nlibrary(gamlss.dist)\n# Ajuster le modèle de poisson\nmodel_poisson <- fitdist(data_accidents$nb_accident, distr = \"pois\")\n# Ajuster le modèle de poisson avec excès de zéros\nmodel_poissonzi <- fitdist(data_accidents$nb_accident, \"ZIP\",\n start = list(mu = 4, sigma = 0.15), # valeurs pour faciliter la convergence\n optim.method = \"L-BFGS-B\", # méthode d'optimisation recommandée dans la documentation\n lower = c(0.00001, 0.00001), # valeurs minimales des deux paramètres\n upper = c(Inf, 1)# valeurs maximales des deux paramètres\n )\ndfpoisson <- data.frame(x=c(0:10),\n y = dpois(0:10, model_poisson$estimate)\n )\nplot1 <- ggplot() + \n geom_bar(aes(x = nb_accident, weight = prop), width = 0.6, data = counts)+\n geom_bar(aes(x = x, weight = y), width = 0.15, data = dfpoisson, fill = \"red\")+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n labs(subtitle = \"Modèle de Poisson\",\n x = \"nombre d'accidents\",\n y = \"\")\ndfpoissonzi <- data.frame(x=c(0:10),\n y = dZIP(0:10, model_poissonzi$estimate[[1]],\n model_poissonzi$estimate[[2]])\n )\nplot2 <- ggplot() + \n geom_bar(aes(x = nb_accident, weight = prop), width = 0.6, data = counts)+\n geom_bar(aes(x = x, weight = y), width = 0.15, data = dfpoissonzi, fill = \"red\")+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n labs(subtitle = \"Modèle de Poisson avec excès de zéro\",\n x = \"nombre d'accident\",\n y = \"\")\nggarrange(plotlist = list(plot1, plot2), ncol = 2)\n```\n\nVisuellement, comme nous pouvons l'observer à la @fig-accmtldist), le modèle avec excès de zéro semble s'imposer. Nous pouvons vérifier cette impression avec la comparaison des *loglikelihood*.\n```{r}\nprint(model_poisson$loglik)\nprint(model_poissonzi$loglik)\n#afficher les paramètres ajustés\nmodel_poisson$estimate\nmodel_poissonzi$estimate\n```\nNous avons donc la confirmation que le modèle de Poisson avec excès de zéros est mieux ajusté. Nous apprenons donc que 70 % (sigma = 0,70) des intersections sont en fait exclues du phénomène étudié (probablement parce que très peu de cyclistes les utilisent ou parce qu'elles sont très peu accidentogènes) et que pour les autres, le taux d'accidents par année en 2017 était de 0,67 (*mu* = 0,669, *mu* signifiant $\\lambda$ pour le *package* `gamlss`). À nouveau, nous pouvons effectuer un test formel avec le fonction `ks.test`.\n\n```{r}\n#| message: false\n#| warning: false\nparams <- as.list(model_poissonzi$estimate)\nks.test(data_accidents$nb_accident,\n y = pZIP, mu = params$mu, sigma = params$sigma)\n```\n\nEncore une fois, nous devons rejeter l'hypothèse selon laquelle le test suit une distribution de Poisson avec excès de zéros. Ces deux exemples montrent à quel point ce test est restrictif.\n\n### Transformation des variables {#sec-0255}\n\n#### Transformations visant à atteindre la normalité {#sec-02551}\n\nComme énoncé au début de cette section, plusieurs méthodes statistiques nécessitent que la variable quantitative soit normalement distribuée. C'est notamment le cas de l'analyse de variance et des tests *t* (abordés dans les chapitres suivants) qui fournissent des résultats plus robustes lorsque la variable est normalement distribuée. Plusieurs transformations sont possibles, les plus courantes étant la racine carrée, le logarithme et l'inverse de la variable. Selon plusieurs auteur(e)s (notamment, les statisticiennes Barbara G. Tabacknick et Linda S. Fidell [-@tabachnick2007, p.89]), en fonction du type (positive ou négative) et du degré d'asymétrie, les transformations suivantes sont possibles afin d'améliorer la normalité de la variable :\n\n* Asymétrie positive modérée : la racine carrée de la variable *X* avec la fonction `sqrt(df$x)`. \n* Asymétrie positive importante : le logarithme de la variable avec `log10(df$x)`.\n* Asymétrie positive sévère : l'inverse de la variable avec `1/(df$x)`.\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Transformation avec des variables avec des valeurs négatives**\n:::\n::: bloc_astuce-body\nPour une valeur égale ou inférieure à 0, nous ne pouvons pas calculer une racine carrée ou un logarithme. Par conséquent, il convient de décaler simplement la distribution vers la droite afin de s'assurer qu'il n'y ait plus de valeurs négatives ou égales à 0 :\n\n* `sqrt(df$x - min(df$x+1))`pour une asymétrie positive avec des valeurs négatives ou égales à 0.\n* `log(df$x - min(df$x+1))`pour une asymétrie positive avec des valeurs négatives ou égales à 0.\n\nPar exemple, si la valeur minimale de la variable est égale à -10, la valeur minimale de variable décalée sera ainsi de 11.\n\n\n* Asymétrie négative modérée : `sqrt(max(df$x+1) - df$x)`\n* Asymétrie négative importante : `log(max(df$x+1) - df$x)`\n* Asymétrie négative sévère : `1/(max(df$x+1) - df$x)`\n:::\n:::\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Transformation des variables pour atteindre la normalité : ce n'est pas toujours la panacée!**\n:::\n::: bloc_attention-body\nLa transformation des données fait et fera encore longtemps débat à la fois parmi les statisticien(ne)s, et les personnes utilisatrices débutantes ou avancées des méthodes quantitatives. Field et al. [-@field2012discovering, p.193] résument le tout avec humour : « to transform or not transform, that is the question ».\n\n**Avantages de la transformation**\n\n* L'obtention de *résultats plus robustes*.\n\n* Dans une régression linéaire multiple, la transformation de la variable dépendante peut *remédier au non-respect des hypothèses de base liées à la régression* (linéarité et homoscédasticité des erreurs, absence de valeurs aberrantes, etc.).\n\n**Inconvénients de la transformation**\n\n* *Une variable transformée est plus difficile à interpréter* puisque cela change l'unité de mesure de la variable. Prenons un exemple concret : vous souhaitez comparer les moyennes de revenu de deux groupes *A* et *B*. Vous obtenez une différence de 15 000 $, soit une valeur facile à interpréter. Par contre, si la variable a été préalablement transformée en logarithme, il est possible que vous obteniez une différence de 9, ce qui est beaucoup moins parlant. Aussi, en transformant la variable en *log*, vous ne comparez plus les moyennes arithmétiques des deux groupes, mais plutôt leurs moyennes géométriques [@field2012discovering, p.193].\n\n* *Pourquoi perdre la forme initiale de la distribution du phénomène à expliquer?* Il est possible, pour de nombreuses méthodes de choisir la distribution que nous souhaitons utiliser, il n'est donc pas nécessaire de toujours se limiter à la distribution normale. Par exemple, dans les modèles de régression généralisés (GLM), nous pourrions indiquer que la variable indépendante suit une distribution de Student plutôt que de vouloir à tout prix la rendre normale. De même, certains tests non paramétriques permettent d'analyser des variables ne suivant pas une distribution normale.\n\n**Démarche à suivre avant et après la transformation**\n\n* *La transformation est-elle nécessaire?* Ne transformez jamais une variable sans avoir analysé rigoureusement sa forme (histogramme avec courbe normale, *skewness* et *kurtosis*, tests de normalité).\n\n* *D'autres options à la transformation d'une variable dépendante (VD) sont-elles envisageables?* Identifiez la forme de la distribution de la VD et utilisez au besoin un modèle GLM adapté à cette distribution. Autrement dit, ne transformez pas automatiquement votre VD simplement pour l'introduire dans une régression linéaire multiple.\n\n* *La transformation a-t-elle un apport significatif?* Premièrement, vérifiez si la transformation utilisée (logarithme, racine carrée, inverse, etc.) améliore la normalité de la variable. Ce n'est pas toujours le cas, parfois c'est pire! Prenez soin de comparer les histogrammes, les valeurs de *skewness*, de *kurtosis* et des différents tests de normalité avant et après la transformation. Deuxièmement, comparez les résultats de vos analyses statistiques sans et avec transformation, et ce, dans une démarche coût-avantage. Vos résultats sont-ils bien plus robustes? Par exemple, un R^2^ qui passe de 0,597 à 0,602 (avant et après la transformation des variables) avec des associations significatives similaires, mais qui sont plus difficiles à interpréter (du fait des transformations), n'est pas forcément un gain significatif. La modélisation en sciences sociales ne vise pas à prédire la trajectoire d'un satellite ou l'atterrissage d'un engin sur Mars! La précision à la quatrième décimale n'est pas une condition! Par conséquent, un modèle un peu moins robuste, mais plus facile à interpréter est parfois préférable.\n:::\n:::\n\n#### Autres types de transformations {#sec-02552}\n\nLes trois transformations les plus couramment utilisées sont :\n\n* **La côte $z$** (*z score* en anglais) qui consiste à soustraire à chaque valeur sa moyenne (soit un centrage), puis à la diviser par son écart-type (soit une réduction) (@eq-scorez). Par conséquent, nous parlons aussi de variable centrée réduite qui a comme propriétés intéressantes une moyenne égale à 0 et un écart-type égal à 1 (la variance est aussi égale à 1 puisque 1^2^ = 1). Nous verrons que cette transformation est largement utilisée dans les méthodes de classification ([chapitre @sec-chap13]) et les méthodes factorielles ([chapitre @sec-chap12]).\n\n$$\nz= \\frac{x_i-\\mu}{\\sigma}\n$$ {#eq-scorez}\n\n\n* **La transformation en rang** qui consiste simplement à trier une variable en ordre croissant, puis à affecter le rang de chaque observation de 1 à $n$. Cette transformation est très utilisée quand la variable est très anormalement distribuée, notamment pour calculer le coefficient de corrélation de Spearman ([section @sec-0433]) et certains tests non paramétriques (sections [-@sec-0612] et [-@sec-0622]). \n\n* **La transformation sur une échelle de 0 à 1** (ou de 0 à 100) qui consiste à soustraite à chaque observation la valeur minimale et à diviser le tout par l'étendue (@eq-t01). \n\n$$\nX_{\\in\\lbrack0-1\\rbrack}= \\frac{x_i-max}{max-min} \\text{ ou } X_{\\in\\lbrack0-100\\rbrack}= \\frac{x_i-min}{max-min}\\times100\n$$ {#eq-t01}\n\n\n```{r}\n#| label: tbl-AutresTransformation\n#| tbl-cap: Illustration des trois transformations\n#| echo: false\n#| message: false\n#| warning: false\n\na <- c(22,27,25,30,37,32,35,40)\nb <- (a-mean(a))/sd(a)\nd <- (a-min(a))/(max(a)-min(a))\n\ndf <- data.frame(\n id = as.character(c(1:length(a))),\n A = round(a,2),\n B = round(b,2),\n C = rank(a),\n D = round(d,2)\n)\ndf[9,1] <- \"Moyenne\"\ndf[10,1] <- \"Écart-type\"\ndf[9,2] <- round(mean(a),2)\ndf[10,2] <- round(sd(a),2)\ndf[9,3] <- round(mean(b),2)\ndf[10,3] <- round(sd(b),2)\nopts <- options(knitr.kable.NA = \"\")\n\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Observation\" , \"$x_i$\" , \"Côte $z$\" , \"Rang\" , \"0 à 1\"),\n align= c(\"l\", \"r\", \"r\", \"c\", \"r\"),\n )\n```\n\nPour un *DataFrame*, nommé *df*, comprenant une variable *X*, la syntaxe ci-dessous illustre comment obtenir quatre transformations (côte $z$, rang, 0 à 1 et 0 à 100).\n\n```{r}\n#| label: tbl-AutresTransformation2\n#| echo: true\n#| message: false\n#| warning: false\ndf2 <- data.frame(X = c(22,27,25,30,37,32,35,40))\n\n# Transformation centrée réduite : côte Z\ndf2$zX <- (df2$X-mean(df2$X))/sd(df2$X)\n# ou encore avec la fonction scale\ndf2$zX <- scale(df2$X, center = TRUE, scale = TRUE)\n\n# Transformation en rang avec la fonction rank\ndf2$rX <- rank(df2$X)\n\n# Transformation de 0 à 1 ou de 0 à 100\ndf2$X01 <- (df2$X-min(df2$X))/(max(df2$X)-min(df2$X))\ndf2$X0100 <- (df2$X-min(df2$X))/(max(df2$X)-min(df2$X))*100\n```\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Utilité des transformations**\n:::\n::: bloc_aller_loin-body\nCes trois transformations sont parfois utilisées pour générer un indice composite à partir de plusieurs variables ou encore dans une analyse de sensibilité avec les indices de Sobol [-@Sobol1993].\n:::\n:::\n\n### Mise en œuvre dans R {#sec-0256}\nIl existe une multitude de *packages* dédiés au calcul des statistiques descriptives univariées. Par parcimonie, nous en utiliserons uniquement trois : `DescTools`, `nortest` et `stats`. Libre à vous de faire vos recherches sur Internet pour utiliser d'autres *packages* au besoin. Les principales fonctions que nous utilisons ici sont :\n\n* `summary` : pour obtenir un résumé sommaire des statistiques descriptives (minimum, Q1, Q2, Q3, maximum)\n* `mean` : moyenne\n* `min` : minimum\n* `max` : maximum\n* `range` : minimum et maximum\n* `quantile` : quartiles\n* `quantile((x, probs = seq(.0, 1, by = .2))` : quintiles\n* `quantile((x, probs = seq(.0, 1, by = .1))` : déciles\n* `var` : variance\n* `sd` : écart-type\n* `Skew` du *package* `DescTools` : coefficient d'asymétrie\n* `Kurt` du *package* `DescTools` : coefficient d'aplatissement\n* `ks.test(x, \"pnorm\", mean=mean(x), sd=sd(x))` du *package* `nortest` : test de Kolmogorov-Smirnov\n* `shapiro.test` du *package* `DescTools` : test de Shapiro-Wilk\n* `lillie.test` du *package* `DescTools` : du package `nortest` : test de Lilliefors\n* `ad.test` du *package* `DescTools` : test d'Anderson-Darling\n* `JarqueBeraTest` du *package* `DescTools` : test de Jarque-Bera\n\n\n#### Application à une seule variable {#sec-02561}\n\nAdmettons que vous voulez obtenir des statistiques pour une seule variable présente dans un *DataFrame* (`dataMTL$PctFRev`) :\n\n```{r}\n#| label: StatDesc1\n#| echo: true\n#| message: false\n#| warning: false\n\nlibrary(DescTools)\nlibrary(stats)\nlibrary(nortest)\n\n# Importation du fichier csv dans un DataFrame\ndataMTL <- read.csv(\"data/univariee/DataSR2016.csv\")\n# Tableau sommaire pour la variable PctFRev\nsummary(dataMTL$PctFRev)\n\n# PARAMÈTRES DE TENDANCE CENTRALE\nmean(dataMTL$PctFRev) # Moyenne\nmedian(dataMTL$PctFRev) # Médiane\n\n\n# PARAMÈTRES DE POSITION\n# Quartiles\nquantile(dataMTL$PctFRev)\n# Quintiles\nquantile(dataMTL$PctFRev, probs = seq(.0, 1, by = .2))\n# Déciles\nquantile(dataMTL$PctFRev, probs = seq(.0, 1, by = .1))\n# Percentiles personnalisés avec apply\nquantile(dataMTL$PctFRev, probs = c(0.01,.05,0.10,.25,.50,.75,.90,.95,.99))\n\n# PARAMÈTRES DE DISPERSION\nrange(dataMTL$PctFRev) # Min et Max\n# Étendue\nmax(dataMTL$PctFRev)-min(dataMTL$PctFRev)\n# Écart interquartile\nquantile(dataMTL$PctFRev)[4]-quantile(dataMTL$PctFRev)[2]\n\nvar(dataMTL$PctFRev) # Variance\nsd(dataMTL$PctFRev) # Écart-type\nsd(dataMTL$PctFRev) / mean(dataMTL$PctFRev) # CV\n\n# PARAMÈTRES DE FORME\nSkew(dataMTL$PctFRev) # Skewness\nKurt(dataMTL$PctFRev) # Kurtosis\n\n# TESTS D'HYPOTHÈSE SUR LA NORMALITÉ\n# K-Smirnov\nks.test(dataMTL$PctFRev, \"pnorm\", mean=mean(dataMTL$PctFRev), sd=sd(dataMTL$PctFRev))\nshapiro.test(dataMTL$PctFRev) \nlillie.test(dataMTL$PctFRev) \nad.test(dataMTL$PctFRev) \nJarqueBeraTest(dataMTL$PctFRev) \n```\n\nPour construire un histogramme avec la courbe normale, consultez la [section @sec-03213] ou la syntaxe ci-dessous.\n\n```{r}\n#| label: fig-GcourbeNormale\n#| fig-align: center\n#| fig-cap: Histogramme avec courbe normale\n#| out-width: \"65%\"\nmoyenne <- mean(dataMTL$PctFRev)\necart_type <- sd(dataMTL$PctFRev)\n\nggplot(data = dataMTL) +\n geom_histogram(aes(x = PctFRev, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = \"personnes à faible revenu (%)\", y = \"densité\")+\n stat_function(fun = dnorm, args = list(mean = moyenne, sd = ecart_type), \n color = \"#e63946\", linewidth = 1.2, linetype = \"dashed\")\n```\n\n#### Application à plusieurs variables {#sec-02562}\n\nPour obtenir des sorties de statistiques descriptives pour plusieurs variables, nous vous conseillons :\n\n* de créer un vecteur avec les noms des variables (*VarsSelect* dans la syntaxe ci-dessous);\n* d'utiliser ensuite les fonctions `sapply` et `apply.`\n\n```{r}\n#| label: StatDesc2\n#| echo: true\n#| message: false\n#| warning: false\n\n# Noms des variables du DataFrame\nnames(dataMTL)\n\n# Vecteur pour trois variables\nVarsSelect <- c(\"HabKm2\", \"TxChomage\", \"PctFRev\" )\n\n# Tableau sommaire pour les 3 variables\nsummary(dataMTL[VarsSelect])\n\n# PARAMÈTRES DE TENDANCE CENTRALE\nsapply(dataMTL[VarsSelect], mean) # Moyenne\nsapply(dataMTL[VarsSelect], median) # Médiane\n\n# PARAMÈTRES DE POSITION\n# Quartiles\nsapply(dataMTL[VarsSelect], quantile)\n# Quintiles\napply(dataMTL[VarsSelect], 2, function(x) quantile(x, probs = seq(.0, 1, by = .2)))\n# Déciles\napply(dataMTL[VarsSelect], 2, function(x) quantile(x, probs = seq(.0, 1, by = .1)))\n# Percentiles personnalisés avec apply\napply(dataMTL[VarsSelect], 2, \n function(x) quantile(x, probs = c(0.01,.05,0.10,.25,.50,.75,.90,.95,.99)))\n\n# PARAMÈTRES DE DISPERSION\nsapply(dataMTL[VarsSelect], range) # Min et Max\n# Étendue\nsapply(dataMTL[VarsSelect], max) - sapply(dataMTL[VarsSelect], min)\n# Écart interquartile\nsapply(dataMTL[VarsSelect], quantile)[4,] - sapply(dataMTL[VarsSelect], quantile)[2,]\n\nsapply(dataMTL[VarsSelect], var) # Variance\nsapply(dataMTL[VarsSelect], sd) # Écart-type\n# Coefficient de variation\nsapply(dataMTL[VarsSelect], sd) / sapply(dataMTL[VarsSelect], mean)\n\n# PARAMÈTRES DE FORME\nsapply(dataMTL[VarsSelect], Skew) # Skewness\nsapply(dataMTL[VarsSelect], Kurt) # Kurtosis\n\n# TESTS D'HYPOTHÈSE POUR LA NORMALITÉ\n# K-Smirnov\napply(dataMTL[VarsSelect], 2, function(x) ks.test(x, \"pnorm\", mean=mean(x), sd=sd(x)))\nsapply(dataMTL[VarsSelect], shapiro.test) # Shapiro-Wilk\nsapply(dataMTL[VarsSelect], lillie.test) # Lilliefors\nsapply(dataMTL[VarsSelect], ad.test) # Anderson-Darling\nsapply(dataMTL[VarsSelect], JarqueBeraTest) # Jarque-Bera\n```\n\n#### Transformation d'une variable dans R {#sec-02563}\n\nLa syntaxe ci-dessous illustre trois exemples de transformation (logarithme, racine carrée et inverse de la variable). Rappelez-vous qu'il faut comparer les valeurs de *skewness* et de *kurtosis* et des tests de Shapiro-Wilk avant et après les transformations pour identifier celle qui est la plus efficace.\n\n```{r}\n#| label: fig-GTranf\n#| fig-cap: Histogramme des transformations\n#| fig-align: center\n#| out-width: \"75%\"\n\nlibrary(ggpubr)\n\n# Importation du fichier csv dans un DataFrame\ndataMTL <- read.csv(\"data/univariee/DataSR2016.csv\")\n\n# Noms des variables du DataFrame\nnames(dataMTL)\n\n# Transformations\ndataMTL$HabKm2_log <- log10(dataMTL$HabKm2)\ndataMTL$HabKm2_sqrt <- sqrt(dataMTL$HabKm2)\ndataMTL$HabKm2_inv <- 1/dataMTL$HabKm2\n\n# Vecteur pour la variable et les trois transformations\nVarsSelect <- c(\"HabKm2\", \"HabKm2_log\", \"HabKm2_sqrt\", \"HabKm2_inv\")\n\n# Paramètres de forme\nsapply(dataMTL[VarsSelect], Skew) # Skewness\nsapply(dataMTL[VarsSelect], Kurt) # Kurtosis\n\n# TESTS D'HYPOTHÈSE SUR LA NORMALITÉ\nsapply(dataMTL[VarsSelect], shapiro.test) \n\n# Histogrammes avec courbe normale\nGraph1 <- ggplot(data = dataMTL) +\n geom_histogram(aes(x = HabKm2, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = expression(\"Habitants au km\"^2), \n y = \"densité\")+\n stat_function(fun = dnorm, \n args = list(mean = mean(dataMTL$HabKm2), \n sd = sd(dataMTL$HabKm2)), \n color = \"#e63946\", linewidth = 1.2)\n\nGraph2 <- ggplot(data = dataMTL) +\n geom_histogram(aes(x = HabKm2_log, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = expression(\"Logarithme d'habitants au km\"^2),\n y = \"densité\")+\n stat_function(fun = dnorm, \n args = list(mean = mean(dataMTL$HabKm2_log), \n sd = sd(dataMTL$HabKm2_log)), \n color = \"#e63946\", linewidth = 1.2)\n\nGraph3 <- ggplot(data = dataMTL) +\n geom_histogram(aes(x = HabKm2_sqrt, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = expression(\"Racine carrée d'habitants au km\"^2),\n y = \"densité\")+\n stat_function(fun = dnorm, \n args = list(mean = mean(dataMTL$HabKm2_sqrt), \n sd = sd(dataMTL$HabKm2_sqrt)), \n color = \"#e63946\", linewidth = 1.2)\n\nGraph4 <- ggplot(data = dataMTL) +\n geom_histogram(aes(x = HabKm2_inv, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = expression(\"Inverse d'habitants au km\"^2),\n y = \"densité\")+\n stat_function(fun = dnorm, \n args = list(mean = mean(dataMTL$HabKm2_inv), \n sd = sd(dataMTL$HabKm2_inv)), \n color = \"#e63946\", linewidth = 1.2)\n\nggarrange(plotlist = list(Graph1, Graph2, Graph3, Graph4), ncol = 2, nrow = 2)\n```\n\nLa variable *HabKm2* est asymétrique positive et leptokurtique. Les valeurs des statistiques de forme et du test de Shapiro-Wilk ainsi que les histogrammes semblent démontrer que la transformation la plus efficace est la racine carrée. Si la variable originale est asymétrique positive, sa transformation logarithmique est par contre asymétrique négative. Cela démontre que la transformation logarithmique n'est pas toujours la panacée.\n\n## Statistiques descriptives sur des variables qualitatives et semi-qualitatives {#sec-026}\n\n### Fréquences {#sec-0261}\n\nEn guise de rappel, les variables nominales, ordinales et semi-quantitatives comprennent plusieurs modalités pour lesquelles plusieurs types de fréquences sont généralement calculées. Pour illustrer le tout, nous avons extrait du recensement de 2016 de Statistique Canada les effectifs des modalités de la variable sur le principal mode de transport utilisé pour les déplacements domicile-travail, et ce, pour la subdivision de recensement (MRC) de l'île de Montréal (@tbl-Frequences). Les différents types de fréquences sont les suivantes :\n\n* Les fréquences absolues simples (**FAS**) ou fréquences observées représentent le nombre d'observations pour chacune des modalités. Par exemple, sur 857 540 personnes réalisant des trajets domicile-travail (ligne totale), seulement 30 645 optent pour le vélo, alors que 427 530 conduisent un véhicule motorisé (automobile, camion ou fourgonnette) comme principal mode de transport.\n\n* Les fréquences relatives simples (**FRS**) sont les proportions de chaque modalité sur le total ($\\mbox{30 645}/\\mbox{857 540}=\\mbox{0,036}$); leur somme est égale à 1. Elles peuvent bien entendu être exprimées en pourcentage ($\\mbox{30 645}/\\mbox{857 540} \\times \\mbox{100}=\\mbox{3,57}$); leur somme est alors égale à 100 %. Par exemple, 3,7 % de ces personnes utilisent le vélo comme mode de transport principal.\n\n* Les fréquences absolues cumulées (**FAC**) représentent la fréquence observée (FAS) de la modalité à laquelle sont additionnées celles qui la précèdent. La valeur de la FAC pour la dernière est donc égale au total.\n\n* À partir des fréquences absolues cumulées (FAC), il est alors possible de calculer les fréquences relatives cumulées (**FRC**) en proportion ($\\mbox{453 930}/\\mbox{857 540} = \\mbox{0,529}$) et en pourcentage ($\\mbox{453 930} / \\mbox{857 540} \\times \\mbox{100}= \\mbox{52,93}$). Par exemple, plus de la moitié des personnes utilisent l'automobile comme mode de transport principal (passagère ou conductrice).\n\n```{r}\n#| label: tbl-Frequences\n#| tbl-cap: Différents types de fréquences sur une variable qualitative ou semi-qualitative\n#| echo: false\n#| message: false\n#| warning: false\nM <- c(\"Véhicule motorisé (conducteur(trice))\",\n \"Véhicule motorisé (passager(ère))\",\n \"Transport en commun\",\n \"À pied\",\n \"Bicyclette\",\n \"Autre moyen\")\nFreq <- c(427530, 26400,295860,69410,30645,7695)\ndf <- data.frame(\n Mode = M,\n FAS = Freq\n)\n# Somme des fréquences aboslues simples\nsumFAS <- sum(df$FA)\n# Fréquences relatives simples\ndf$FRS <- round(df$FAS / sum(df$FAS),3)\nsumFRS <- sum(df$FAS / sum(df$FAS))\n# Fréquences relatives simples en pourcentages\ndf$FRSpct <- round(df$FAS / sum(df$FAS)*100,2)\nsumFRSpct <- sum(df$FAS / sum(df$FAS)*100)\n# Fréquences absolues cumulées\ndf$FAC <- cumsum(df$FAS)\n# Fréquences relatives cumulées\ndf$FRC <- round(cumsum(df$FAS)/sum(df$FAS),3)\n# Fréquences relatives cumulées en pourcentages\ndf$FRCpct <- round(cumsum(df$FAS)/sum(df$FAS)*100,2)\nn <- nrow(df)\ndf[n+1,1] <- \"Total\"\ndf[n+1,2] <- sumFAS\ndf[n+1,3] <- sumFRS\ndf[n+1,4] <- sumFRSpct\nopts <- options(knitr.kable.NA = \"\")\n\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Mode de transport\" , \"FAS\" , \"FRS\" , \"FRS (%)\" , \"FAC\", \"FRC\", \"FRC (%)\"), \n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\") )\n```\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Les fréquences cumulées : peu pertinentes pour les variables nominales**\n:::\n::: bloc_attention-body\nLe calcul et l'analyse des fréquences cumulées (absolues et relatives) sont très souvent inutiles pour les variables nominales.\n\nPar exemple, au @tbl-Frequences, la fréquence cumulée relative (en %) est de 87,43 % pour la troisième ligne. Cela signifie que 87,43 % des navetteur(ve)s se déplacent en véhicule motorisé (personne conductrice ou passagère) ou en transport en commun. Par contre, si la troisième modalité avait été *à pied*, le pourcentage aurait été de 61,02 ($\\mbox{52,93}+\\mbox{8,09}$). Si vous souhaitez calculer les fréquences cumulées sur une variable nominale, assurez-vous que l'ordre des modalités vous convient et de le modifier au besoin. Sinon, abstenez-vous de les calculer!\n\n\n**Les fréquences cumulées : très utiles pour l'analyse des variables ordinales ou semi-quantitatives**\n\nPour des modalités hiérarchisées (variable ordinale ou semi-quantitative), l'analyse des fréquences cumulées (absolues et relatives) est par contre très intéressante. Par exemple, au @tbl-Frequences2, elle permet de constater rapidement que sur l'île de Montréal, plus du quart de la population à moins de 25 ans (27,91 %) et 83,33 %, moins de 65 ans.\n:::\n:::\n\n```{r}\n#| label: tbl-Frequences2\n#| tbl-cap: Différents types de fréquences sur une variable semi-qualitative\n#| echo: false\n#| message: false\n#| warning: false\nM <- c(\"0 à 14 ans\",\n \"15 à 24 ans\",\n \"25 à 44 ans\",\n \"45 à 64 ans\",\n \"65 à 84 ans\",\n \"85 ans et plus\")\nFreq <- c(304470,237555,582150,494205,271560,52100)\ndf <- data.frame(\n Mode = M,\n FAS = Freq\n)\n# Somme des fréquences aboslues simples\nsumFAS <- sum(df$FA)\n# Fréquences relatives simples\ndf$FRS <- round(df$FAS / sum(df$FAS),3)\nsumFRS <- sum(df$FAS / sum(df$FAS))\n# Fréquences relatives simples en pourcentages\ndf$FRSpct <- round(df$FAS / sum(df$FAS)*100,2)\nsumFRSpct <- sum(df$FAS / sum(df$FAS)*100)\n# Fréquences absolues cumulées\ndf$FAC <- cumsum(df$FAS)\n# Fréquences relatives cumulées\ndf$FRC <- round(cumsum(df$FAS)/sum(df$FAS),3)\n# Fréquences relatives cumulées en pourcentages\ndf$FRCpct <- round(cumsum(df$FAS)/sum(df$FAS)*100,2)\nn <- nrow(df)\ndf[n+1,1] <- \"Total\"\ndf[n+1,2] <- sumFAS\ndf[n+1,3] <- sumFRS\ndf[n+1,4] <- sumFRSpct\nopts <- options(knitr.kable.NA = \"\")\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Groupes d'âge\" , \"FAS\" , \"FRS\" , \"FRS (%)\" , \"FAC\", \"FRC\", \"FRC (%)\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\nDifférents graphiques peuvent être construits pour illustrer la répartition des observations : les graphiques en barres (verticales et horizontales) avec les fréquences absolues et les diagrammes circulaires ou en anneau pour les fréquences relatives (@fig-GraphiquesFreq1). Ces graphiques seront présentés plus en détail dans le chapitre suivant.\n\n```{r}\n#| label: fig-GraphiquesFreq1\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Différents graphiques pour représenter les fréquences absolues et relatives\n#| out-width: \"75%\"\nlibrary(dplyr)\nCode <- c(\"A\" , \"B\" , \"C\" , \"D\" , \"E\" , \"F\")\nM <- c(\"0 à 14 ans\",\n \"15 à 24 ans\",\n \"25 à 44 ans\",\n \"45 à 64 ans\",\n \"65 à 84 ans\",\n \"85 ans et plus\")\nFreq <- c(304470,237555,582150,494205,271560,52100)\ndf <- data.frame(\n Groupe = M,\n FAS = Freq\n)\ndf <- data.frame(\n Code = Code,\n Groupe = M,\n FAS = Freq\n)\ndf$FRSpct <- round(df$FAS / sum(df$FAS),3)*100\nmycols <- c(\"#0c2c84\", \"#67000d\", \"#99000d\", \"#ef3b2c\" , \"#006d2c\", \"#41ab5d\")\n# BARRRES\noptions(scipen = 999)\nG1 <- ggplot(data = df)+\n geom_bar(aes(x = Code, weight = FAS, fill = Groupe))+\n scale_fill_manual(values = mycols) +\n labs(x = \"Groupe d'âge\",\n y = \"Navetteur(ve)s\")\n# BARRRES\nG2 <- ggplot(data = df)+\n geom_bar(aes(y = Code, weight = FAS, fill = Groupe))+\n scale_fill_manual(values = mycols) +\n labs(x = \"Groupe d'âge\",\n y = \"Navetteur(ve)s\")\n# DIAGRAMME CIRCULAIRE\n# Ajouter la position de l'étiquette\ndf <- df %>%\n arrange(desc(Groupe)) %>%\n mutate(ypos = cumsum(FRSpct) - 0.5*FRSpct)\nG3 <- ggplot(df, aes(x = \"\", y = FRSpct, fill = Groupe)) +\n geom_bar(width = 1, stat = \"identity\", color = \"white\") +\n coord_polar(\"y\", start=0) +\n theme_void() +\n geom_text(aes(y = ypos, label = FRSpct), color = \"white\", size=3) +\n scale_fill_manual(values = mycols)\n# ANNEAU\ndf$ymax <- cumsum(df$FRSpct)\ndf$ymin <- c(0, head(df$ymax, n=-1))\nG4 <- ggplot(df, aes(ymax = ymax, ymin = ymin,\n xmax = 4, xmin = 3,\n y = FRSpct, fill = Groupe)) +\n geom_rect(stat = \"identity\", color = \"white\") +\n coord_polar(\"y\", start=0) +\n theme_void() +\n geom_text(aes(x = 3.5, y = ypos, label = FRSpct), color = \"white\", size=3) +\n scale_fill_manual(values = mycols) +\n xlim(c(2,4))\nlist_plot <- list(G1, G2, G3, G4)\nggarrange(plotlist = list_plot, ncol = 2, nrow = 2,\n common.legend = TRUE, legend = \"bottom\")\noptions(scipen = 0)\n```\n\n### Mise en œuvre dans R {#sec-0262}\n\nLa syntaxe ci-dessous permet de calculer les différentes fréquences présentées au @tbl-Frequences2. Notez que pour les fréquences cumulées, nous utilisons la fonction `cumsum`.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Vecteur pour les noms des modalités\nModalite <- c(\"0 à 14 ans\",\n \"15 à 24 ans\",\n \"25 à 44 ans\",\n \"45 à 64 ans\",\n \"65 à 84 ans\",\n \"85 ans et plus\")\n# Vecteur pour les fréquences absolues simples (FAS)\nNavetteurs <- c(304470,237555,582150,494205,271560,52100)\n# Somme des FAS\nsumFAS <- sum(Navetteurs)\n# Construction du DataFrame avec les deux vecteurs\ndf <- data.frame(\n GroupeAge = Modalite, \n FAS = Navetteurs,\n FRS = Navetteurs / sumFAS, \n FRSpct = Navetteurs / sumFAS * 100,\n FAC = cumsum(Navetteurs),\n FRC = cumsum(Navetteurs) / sumFAS,\n FRCpct = cumsum(Navetteurs) / sumFAS * 100\n )\ndf\n```\n\n## Statistiques descriptives pondérées : pour aller plus loin {#sec-027}\n\nDans la [section @sec-025], les différentes statistiques descriptives sur des variables quantitatives – paramètres de tendance centrale, de position, de dispersion et de forme – ont été largement abordées. Il est possible de calculer ces différentes statistiques en tenant compte d’une pondération. La statistique descriptive pondérée la plus connue est certainement la moyenne arithmétique pondérée. Son calcul est très simple. Pour chaque observation, deux valeurs sont disponibles : \n\n* $x_i$, soit la valeur de la variable $X$ pour l'observation $i$\n* $w_i$, soit la valeur de la pondération pour $i$.\n\nPrenez soin de comparer les deux équations ci-dessous (à gauche, la moyenne arithmétique; à droite, la moyenne arithmétique pondérée). Vous constaterez rapidement qu'il suffit de multiplier chaque observation par sa pondération (numérateur) et de diviser ce produit par la somme des pondérations (dénominateur; et non par $n$, soit le nombre d’observations comme pour la moyenne arithmétique non pondérée). \n\n$$ \n\\bar{x}=\\frac{\\sum_{i=1}^n x_i}{n} \\text { versus } \\bar{m}=\\frac{\\sum_{i=1}^n w_ix_i}{\\sum_{i=1}^nw_i}\n$$ {#eq-moypond}\n\n\n```{r}\n#| label: tbl-MoyPondCalcul\n#| tbl-cap: Calcul de la moyenne pondérée\n#| echo: false\n#| message: false\n#| warning: false\nx <- c(200,225,275,300)\nw <- c(20,80,50,200)\n\ndf <- data.frame(\n id = as.character(c(1:length(x))),\n x = round(x,0),\n w = round(w,0),\n wx = x*w\n)\ndf[5,1] <- \"Somme\"\ndf[6,1] <- \"Moyenne\"\ndf[7,1] <- \"Moyenne pondérée\"\n\ndf[5,2] <- sum(x)\ndf[5,3] <- sum(w)\ndf[5,4] <- sum(x*w)\ndf[6,2] <- round(mean(x),0)\ndf[7,4] <- round(sum(x*w)/sum(w),0)\n\nopts <- options(knitr.kable.NA = \"\")\nknitr::kable(df,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Observation\" , \"$x_i$\" , \"$w_i$\" , \"$x_i \\\\times w_i$\"),\n align= c(\"l\", \"r\", \"r\", \"r\")\n )\n```\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Calcul d’autres statistiques descriptives pondérées**\n:::\n::: bloc_notes-body\nNous ne reportons pas ici les formules des versions pondérées de toutes les statistiques descriptives. Retenez toutefois le principe suivant permettant de les calculer à partir de l’exemple du @tbl-MoyPondCalcul. Pour la variable *X*, dupliquons respectivement 20, 80, 50, 200 fois les observations 1 à 4. Si nous calculons la moyenne arithmétique sur ces valeurs dupliquées, alors cette valeur est identique à celle de la moyenne arithmétique pondérée. Le même principe reposant sur la duplication des valeurs s'applique à l'ensemble des statistiques descriptives.\n:::\n:::\n\nDans un article récent, Alvarenga et al. [-@de2018accessibilite] évaluent l'accessibilité aux aires de jeux dans les parcs de la Communauté métropolitaine de Montréal (CMM). Pour les 881 secteurs de recensement de la CMM, ils ont calculé la distance à pied à l'aire de jeux la plus proche à travers le réseau de rues. Ce résultat, cartographié à la @fig-ParcCMM), permet d'avancer le constat suivant : « la quasi-totalité des secteurs de recensement de l’agglomération de Montréal présente des distances de l’aire de jeux la plus proche inférieures à 500 m, alors que les secteurs situés à plus d’un kilomètre d’une aire de jeux sont très majoritairement localisés dans les couronnes\nnord et sud de la CMM » [@de2018accessibilite, p.238].\n\nPour chaque secteur de recensement, Alvarenga et al. [-@de2018accessibilite] disposent des données suivantes :\n\n* $x_i$, soit la distance à l'aire de jeux la plus proche pour le secteur de recensement *i*;\n* $w_i$, la pondération, soit le nombre d'enfants de moins de dix ans.\n\nIl est alors possible de calculer les statistiques descriptives de la proximité à l'aire de jeux la plus proche en tenant compte du nombre d'enfants résidant dans chaque secteur de recensement (@tbl-MoyPondParc). Cet exercice permet de conclure que : « [...] globalement, les enfants ont une bonne accessibilité aux aires de jeux sur le territoire de la CMM. [...] Les enfants sont en moyenne à un peu plus de 500 m de l’aire de jeux la plus proche (moyenne = 559; médiane = 512). Toutefois, les valeurs percentiles extrêmes signalent que respectivement 10 % et 5 % des enfants résident à près de 800 m et à plus de 1000 m de l’aire de jeux la plus proche » [-@de2018accessibilite, p.236].\n\n\n![Accessibilité aux aires de jeux par secteur de recensement, Communauté métropolitaine de Montréal, 2016](images/Chap02/BivarieeFigureParc.jpg){#fig-ParcCMM width=\"85%\" fig-align=\"center\"}\n\n```{r}\n#| label: tbl-MoyPondParc\n#| tbl-cap: Statistiques de l'aire de jeux la plus proche, par secteur de recensement, pondérées par la population de moins de 10 ans\n#| echo: false\n#| message: false\n#| warning: false\nparc <- c(881,559,282,327,408,512,640,799,1006)\nstat <- c(\"N\" , \"Moyenne\" , \"P5\" , \"P10\" , \"Q1\" , \"Médiane\" , \"Q3\" , \"P90\" , \"P95\")\n\ndf <- data.frame(\n \"Parc\" = parc\n)\ndf <- data.frame(t(df))\n\nopts <- options(knitr.kable.NA = \"\")\nknitr::kable(df,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = stat,\n align= c(\"c\", \"c\", \"c\", \"c\", \"c\", \"c\", \"c\", \"c\", \"c\")\n )\n```\n\nDe nombreux *packages* sont disponibles pour calculer des statistiques pondérées, dont notamment `Weighted.Desc.Stat` et `Hmisc` utilisés dans la syntaxe ci-dessous.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(foreign)\nlibrary(Hmisc)\nlibrary(Weighted.Desc.Stat)\n\ndf <- read.dbf(\"data/bivariee/SR_AireJeux_PopMoins10.dbf\")\n\nhead(df, n = 5)\n\n# xi (variable) et wi (pondération)\nx <- df$AireJeux\nw <- df$PopMoins10\n\n# Calcul des paramètres de position\n# Moyenne\nHmisc::wtd.mean(x, w)\nWeighted.Desc.Stat::w.mean(x, w)\n# Quartiles et percentile\nHmisc::wtd.quantile(x, weights=w, probs=c(.05, .10, .25, .50, .75, .90, .95))\n\n# Paramètres de dispersion avec le package Weighted.Desc.Stat\n# Variance, écart-type et coefficient de variation\nw.var(x, w)\nw.sd(x, w)\nw.cv(x, w)\n\n# Paramètres de forme avec le package Weighted.Desc.Stat\n# Skewness et kurtosis \nw.skewness(x, w)\nw.kurtosis(x, w)\n```\n\n\n## Quiz de révision du chapitre {#sec-028}\n\n```{r}\n#| label: quizChapitre02\n#| echo: false\n#| warning: false\n#| results: asis\nsource(\"code_complementaire/QuizzFunctions.R\")\nChapitre2_univariees <- quizz(\"quiz/Chapitre2_univariees.yml\", \"Chapitre2_univariees\")\nrender_quizz(Chapitre2_univariees)\n```\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"02-univarie.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/03-magiedesgraphiques.qmd.json b/.quarto/idx/03-magiedesgraphiques.qmd.json new file mode 100644 index 0000000..29a76c9 --- /dev/null +++ b/.quarto/idx/03-magiedesgraphiques.qmd.json @@ -0,0 +1 @@ +{"title":"Magie des graphiques","markdown":{"headingText":"Magie des graphiques","headingAttr":{"id":"sec-chap03","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans ce chapitre, nous découvrons les incroyables capacités graphiques de R. Pour ce faire, nous couvrons en profondeur les fonctionnalités du *package* `ggplot2` du `tidyverse`. Selon nous, il s'agit de loin du meilleur *package* pour réaliser des graphiques.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques.\n - `ggthemes` pour utiliser des thèmes complémentaires pour les graphiques. \n* Pour les couleurs : \n - `RColorBrewer` pour accéder à des palettes de couleurs.\n* Pour les graphiques spéciaux : \n - `chorddiag` pour construire des graphiques d'accord.\n - `fmsb` pour construire des graphiques en radar.\n - `treemap` pour construire une carte proportionnelle.\n - `wordcloud2` et `textrank` pour construire un nuage de mots.\n* Pour les cartes : \n - `classInt` pour calculer les intervalles des classes.\n - `ggspatial` pour afficher une échelle avec `ggplot2`.\n - `tmap` pour la cartographie.\n* Autres *packages* : \n - `dplyr` et `reshape2` pour manipuler des données.\n - `pdftools` pour extraire les textes des fichiers *pdf*.\n - `udpipe` pour obtenir des dictionnaires linguistiques.\n - `sf` pour manipuler des *simple feature collections*.\n:::\n:::\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Qu'est-ce que la visualisation de données?**\n:::\n::: bloc_notes-body\nLa représentation visuelle de données consiste à transposer des informations en une représentation graphique facilitant la lecture de ces dernières. Il s'agit autant d'un ensemble de méthodes, d'un art que d'un moyen de communication. Voici deux exemples marquants avant de détailler ce propos.\n\nLa première illustration permet de visualiser le volume de plastique que représente la consommation d'eau en bouteille : 480 milliards de bouteilles vendues en 10 ans! Ce chiffre astronomique est inimaginable. En revanche, une [montagne de plastique](https://graphics.reuters.com/ENVIRONMENT-PLASTIC/0100B275155/index.html){target='_blank'} de 2400 mètres surplombant Manhattan marque davantage les esprits.\n\nLe [second graphique](https://www.maplecroft.com/insights/analysis/84-of-worlds-fastest-growing-cities-face-extreme-climate-change-risks/){target='_blank'} représente quatre informations pour 234 villes à travers le monde : \n\n* la croissance démographique (axe des abscisses),\n\n* la vulnérabilité au changement climatique (axe des ordonnées),\n\n* la taille des villes (taille des cercles),\n\n* le continent sur lequel est localisée chaque ville (couleur des cercles).\n\nLe graphique est à la fois très accrocheur et esthétique. En un coup d'œil, nous constatons que les villes avec une forte croissance démographique sont aussi les plus vénérables (lecture des deux axes) et qu'elles sont surtout localisées en Afrique et secondairement en Asie (en rouge et orange), quelle que soit leur taille (taille du cercle). À l'inverse, les villes européennes et américaines (en bleu) sont beaucoup moins vulnérables aux changements climatiques et une croissance démographique plus faible, qu'elles soient de petites, de moyennes ou de grandes villes.\n\nSouvent négligée, la visualisation de données est perçue comme une tâche triviale : il s'agit simplement de représenter une donnée sous forme d'un graphique, car c'est l'option la plus pratique ou qui prend le moins d'espace. Pourtant, les avantages de la visualisation des données sont nombreux. Par exemple, la visualisation de données intègre aujourd'hui des supports dynamiques comme des animations, des figures interactives ou des applications web. R offre d'ailleurs des possibilités très intéressantes en la matière avec des *packages* comme `shiny`, `plotly` ou `leaflet`. Toutefois, nous ne couvrons pas ici ces méthodes plus récentes en visualisation des données qui devraient faire l'objet d'un autre livre.\n\n**Les principaux avantages de la visualisation des données** : \n\n* **Analyse exploratoire des données** (*exploratory data analysis - EDA* en anglais). Visualiser des données est crucial pour détecter des problèmes en tout genre (données manquantes, valeurs extrêmes ou aberrantes, non-respect de conditions d'application de tests statistiques, etc.), mais aussi pour repérer de nouvelles associations entre les variables.\n\n* **Communication de vos résultats**. La raison d'être d'un graphique est de livrer un message clair relatif à un résultat obtenu suite à une analyse rigoureuse de vos données. Si votre graphique n'apporte aucune information claire, il vaut mieux ne pas le présenter, ni le diffuser. Les représentations ne sont pas neutres. Les couleurs et les formes ont des significations particulières en fonction de la culture et du contexte. Posez-vous donc toujours la question : à quel public est destiné le message? Évitez de surcharger vos visualisations de données, sinon l'essence du message sera perdue.\n\n* **Aide à la décision**. Une illustration (graphique ou carte) peut être un outil facilitant la prise de décisions. \n:::\n:::\n\n## Philosophie du ggplot2 {#sec-031}\n\nLe *package* `ggplot2` fait partie du `tidyverse` et dispose d'une logique de fonctionnement particulière. Cette dernière se nomme *The Grammar of Graphics* (les deux G sont d'ailleurs à l'origine du nom `ggplot2`), proposée par Hadley Wickham (le créateur du `tidyverse`!) dans un article intitulé *A layered grammar of graphics* [@wickham2010layered]. Nous proposons de synthétiser ici les concepts et principes centraux qui sous-tendent la production de graphiques avec `ggplot2`.\n\n### Grammaire {#sec-0311}\n\nHadley Wickham propose une grammaire pour unifier la création de graphiques. L'idée est donc de dépasser les simples dénominations comme un nuage de points, un diagramme en boîte, un graphique en ligne, etc., pour comprendre ce qui relie tous ces graphiques. Ces éléments communs et centraux sont les géométries, les échelles et systèmes de coordonnées, et les annotations (@fig-fig30) : \n\n![Trois composantes d'un graphique, adapté de @wickham2010layered](images/Chap03/composantes.png){#fig-fig30 width=\"70%\" fig-align=\"center\"}\n\n* Les **géométries** sont les formes utilisées pour représenter les données. Il peut s'agir de points, de lignes, de cercles, de rectangles, d'arcs de cercle, etc. \n\n* Les **échelles et systèmes de coordonnées** permettent de contrôler la localisation des éléments dans un graphique en convertissant les données depuis leur échelle originale (dollars, kilomètres, pourcentages, etc.) vers l'échelle du graphique (pixels).\n\n* Les **annotations** recoupent l'ensemble des informations complémentaires ajoutées au graphique comme son titre et sous-titre, la source des données, la mention sur les droits d'auteurs, etc.\n\nEn plus de ces trois éléments, il est bien sûr nécessaire de disposer de **données**. Ces dernières sont assignées à des dimensions du graphique pour être représentées (notamment les axes *X* et *Y* et la couleur). Cette étape est appelée **aesthetics mapping** dans `ggplot2`.\n\nLorsque nous combinons des données, leur assignation a des dimensions, un type de géométries, des échelles et un système de coordonnées, nous obtenons un **calque** (*layer* en anglais). Un graphique peut comprendre plusieurs calques comme nous le verrons dans les prochaines sections.\n\nPrenons un premier exemple très simple et construisons un nuage de points à partir du jeu de données *iris* fourni de base dans R. Nous représentons la relation qui existe entre la longueur et la largeur des sépales de ces fleurs. Pour commencer, nous devons charger le *package* `ggplot2` et instancier un graphique avec la fonction `ggplot`.\n\n```{r}\n#| label: fig-fig31\n#| fig-align: center\n#| fig-cap: Base d'un graphique\n#| out-width: \"65%\"\nlibrary(ggplot2)\ndata(iris)\nnames(iris)\n\nggplot()\n```\n\nPour le moment, le graphique est vide (@fig-fig31). La seconde étape consiste à lui ajouter des données (au travers du paramètre `data`) et à définir les dimensions à associer aux données (avec le paramètre `mapping` et la fonction `aes()`). Dans notre cas, nous voulons utiliser les coordonnées *X* pour représenter la largeur des sépales, et les coordonnées *Y* pour représenter la longueur des sépales. Enfin, nous souhaitons représenter les observations par des points, nous utiliserons donc la géométrie `geom_point`.\n\n```{r}\n#| label: fig-fig32\n#| fig-align: center\n#| fig-cap: Ajout des dimensions au graphique\n#| out-width: \"65%\"\nggplot(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n geom_point()\n```\n\nCe graphique ne comprend qu'un seul calque avec une géométrie de type point (@fig-fig32). Chaque calque est ajouté avec l'opérateur `+` qui permet de superposer des calques, le dernier apparaissant au-dessus des autres. Les arguments `mapping` et `data` sont définis ici dans la fonction `ggplot` et sont donc appliqués à tous les calques qui composent le graphique. Il est aussi possible de définir `mapping` et `data` au sein des fonctions des géométries : \n\n```{r}\n#| label: fig-fig33\n#| fig-align: center\n#| fig-cap: Autre spécification des arguments mapping et data\n#| out-width: \"65%\"\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris)\n```\n\nLa troisième étape consiste à ajouter au graphique des annotations. Pour notre cas, il faudrait ajouter un titre, un sous-titre et des intitulés plus clairs pour les axes *X* et *Y*, ce qu'il est possible de faire avec la fonction `labs` (@fig-fig34).\n\n```{r}\n#| label: fig-fig34\n#| fig-align: center\n#| fig-cap: Ajout de titres\n#| out-width: \"65%\"\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\")\n```\n\n### Types de géométries {#sec-0312}\n\nLe *package* `ggplot2` permet d'utiliser un très grand nombre de géométries différentes. Dans le @tbl-geometries, nous avons reporté les principales géométries disponibles afin que vous puissiez vous faire une idée du « bestiaire » existant. Il ne s'agit que d'un extrait des principales fonctions. Sachez qu'il existe aussi des *packages* proposant des géométries supplémentaires pour compléter `ggplot2`.\n\n```{r}\n#| label: tbl-geometries\n#| tbl-cap: Principales géométries proposées par `ggplot2`\n#| echo: false\n#| message: false\n#| warning: false\n\ndf <- data.frame(\n noms = c(\"Point\", \"Ligne\", \"Chemin\", \"Boîte à moustaches\", \"Diagramme violon\", \"Histogramme\", \"Barre\", \"Densité\", \"Texte\", \"Barre d'erreur\", \"Surface\"),\n fonctions = c(\"`geom_point`\", \"`geom_line`\", \"`geom_path`\", \"`geom_boxplot`\", \"`geom_violin`\", \"`geom_histogram`\", \"`geom_bar`\", \"`geom_density`\", \"`geom_label`\", \"`geom_errorbar`\", \"`geom_ribbon`\")\n )\n\nknitr::kable(df,\n col.names = c(\"Géométrie\" , \"Fonction\"),\n align= c(\"l\", \"l\")\n )\n```\n\n\n### Habillage {#sec-0313}\n\nDans le premier exemple, nous avons montré comment ajouter le titre, le sous-titre et les titres des axes sur un graphique. Il est aussi possible d'ajouter du texte sous le graphique (généralement la source des données avec l'argument `caption`) et des annotations textuelles (`annotate`). Pour ces dernières, il convient de spécifier leur localisation (coordonnées `x` et `y`) et le texte à intégrer (`label`); elles sont ensuite ajoutées au graphique avec l'opérateur `+`. Ajoutons deux annotations pour identifier deux fleurs spécifiques.\n\n```{r}\n#| label: fig-fig35\n#| fig-align: center\n#| fig-cap: Ajout d'annotations textuelles\n#| out-width: \"65%\"\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") +\n annotate(\"text\", x = 6.7, y = 2.5, # position de la note\n label = \"une virginica\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\") + \n annotate(\"text\", x = 5.7, y = 4.4, # position de la note\n label = \"une setosa\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\") \n```\n\nComme vous pouvez le constater, de nombreux paramètres permettent de contrôler le style des annotations. Pour avoir la liste des arguments disponibles, n'hésitez pas à afficher l'aide de la fonction : `help(annotate)`.\n\nEn plus des annotations de type texte, il est possible d'ajouter des annotations de type géométrique. Nous pourrions ainsi délimiter une boîte encadrant les fleurs de l'espère setosa.\n\n```{r}\n#| label: fig-fig36\n#| fig-align: center\n#| fig-cap: Ajout d'annotations géométriques\n#| out-width: \"65%\"\n\nsetosas <- subset(iris, iris$Species == \"setosa\")\nsepal.length_extent <- c(min(setosas$Sepal.Length), max(setosas$Sepal.Length))\nsepal.width_extent <- c(min(setosas$Sepal.Width), max(setosas$Sepal.Width))\n\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") +\n annotate(\"text\", x = 6.7, y = 2.5, # position de la note\n label = \"une virginica\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\") + \n annotate(\"text\", x = 5.7, y = 4.4, # position de la note\n label = \"une setosa\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\") +\n annotate(\"rect\", \n ymin = sepal.width_extent[[1]],\n ymax = sepal.width_extent[[2]],\n xmin = sepal.length_extent[[1]],\n xmax = sepal.length_extent[[2]],\n fill = rgb(0.7,0.7,0.7,.5), # remplissage transparent à 50%\n color = \"black\") # contour de couleur verte\n```\n\nComme le dernier calque ajouté au graphique est le rectangle, vous noterez qu'il recouvre tous les calques existant, y compris les précédentes annotations. Pour corriger cela, il suffit de changer l'ordre des calques.\n\n```{r}\n#| label: fig-fig37\n#| fig-align: center\n#| fig-cap: Gestion de l'ordre des annotations\n#| out-width: \"65%\"\n\nggplot() +\n annotate(\"rect\", \n ymin = sepal.width_extent[[1]],\n ymax = sepal.width_extent[[2]],\n xmin = sepal.length_extent[[1]],\n xmax = sepal.length_extent[[2]],\n fill = rgb(0.7,0.7,0.7,.5), # remplissage transparent à 50%\n color = \"green\") + # contour de couleur verte\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") +\n\n annotate(\"text\", x = 6.7, y = 2.5, # position de la note\n label = \"une virginica\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\") + \n annotate(\"text\", x = 5.7, y = 4.4, # position de la note\n label = \"une setosa\", # texte de la note\n hjust = \"left\", vjust = \"top\", # ajustement\n size = 3, fontface = \"italic\")\n```\n\n### Utilisation des thèmes\n\nDe nombreux autres éléments peuvent être modifiés dans un graphique comme les paramètres des polices, l'arrière-plan, la grille de repères, etc. Il peut être fastidieux de paramétrer tous ces éléments. Une option intéressante est d'utiliser des thèmes déjà préconstruits. Le *package* `ggplot2` propose une dizaine de thèmes : constatons leur impact sur le graphique précédent.\n\n* Le thème classique (`theme_classic`) (@fig-fig38)\n```{r}\n#| label: fig-fig38\n#| fig-align: center\n#| fig-cap: Thème classique\n#| out-width: \"65%\"\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_classic()\n```\n\n* Le thème gris (`theme_gray`) (@fig-fig39)\n```{r}\n#| label: fig-fig39\n#| fig-align: center\n#| fig-cap: Thème gris\n#| out-width: \"65%\"\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_gray()\n```\n\n* Le thème noir et blanc (`theme_bw`) (@fig-fig310)\n```{r}\n#| label: fig-fig310\n#| fig-align: center\n#| fig-cap: Thème noir et blanc\n#| out-width: \"65%\"\n\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_bw()\n```\n\n* Le thème minimal (`theme_minimal`) (@fig-fig311)\n```{r}\n#| label: fig-fig311\n#| fig-align: center\n#| fig-cap: Thème minimal\n#| out-width: \"65%\"\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_minimal()\n```\n\nIl est aussi possible d'utiliser le *package* `ggthemes` qui apporte des thèmes complémentaires intéressants dont : \n\n* Le thème *tufte* (`theme_tufte`, à l'ancienne...) (@fig-fig312)\n```{r}\n#| label: fig-fig312\n#| fig-align: center\n#| fig-cap: Thème tufte\n#| out-width: \"65%\"\nlibrary(ggthemes)\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_tufte()\n```\n\n* Le thème *economist* (`theme_economist`, inspiré de la revue du même nom) (@fig-fig313)\n```{r}\n#| label: fig-fig313\n#| fig-align: center\n#| fig-cap: Thème economist\n#| out-width: \"65%\"\n\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_economist()\n```\n\n* Le thème *solarized* (`theme_solarized`, plus original) (@fig-fig314)\n```{r}\n#| label: fig-fig314\n#| fig-align: center\n#| fig-cap: Thème solarized\n#| out-width: \"65%\"\n\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") + \n theme_solarized()\n```\n\nIl en existe bien d'autres et vous pouvez composer vos propres thèmes. N'hésitez pas à explorer la documentation de `ggplot2` et de `ggthemes` pour en apprendre plus!\n\n### Composition d'une figure avec plusieurs graphiques {#sec-0314}\n\nIl est très fréquent de vouloir combiner plusieurs graphiques dans une même figure. Deux cas se distinguent : \n\n1. Les données pour les différents graphiques proviennent du même *DataFrame* et peuvent être distinguées selon une variable catégorielle. L'objectif est alors de dupliquer le même graphique, mais pour des sous-groupes de données. Dans ce cas, nous recommandons d'utiliser la fonction `facet_wrap` de `ggplot2`.\n\n2. Les graphiques sont complètement indépendants. Dans ce cas, nous recommandons d'utiliser la fonction `ggarrange` du *package* `ggpubr`.\n\n#### `ggplot2` et ses facettes {#sec-03141}\n\nNous pourrions souhaiter réaliser une figure composite avec le jeu de données *iris* et séparer notre nuage de points en trois graphiques distincts selon l'espèce des iris (@fig-fig315). Pour cela, il faut au préalable convertir la variable *espèce* en facteur.\n\n```{r}\n#| label: fig-fig315\n#| fig-align: center\n#| fig-cap: Graphique à facettes\n#| out-width: \"65%\"\n\niris$Species_fac <- as.factor(iris$Species)\n\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") +\n facet_wrap(vars(Species_fac), ncol = 2)\n\n```\nNotez que le nom de la variable (ici `Species_fac`) doit être spécifié au sein d'une sous-fonction `vars` : `vars(Species_fac)`. Nous aurions aussi pu réaliser le graphique sur une seule ligne en spécifiant `ncol = 3` (@fig-fig316).\n\n```{r}\n#| label: fig-fig316\n#| fig-align: center\n#| fig-cap: Graphique à facettes en une ligne\n#| out-width: \"65%\"\n\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +\n labs(title = \"Morphologie des sépales des iris\", subtitle = \"n = 150\",\n x = \"Longueur des sépales\", \n y = \"Largeur des sépales\",\n caption = \"Source : jeu de données iris\") +\n facet_wrap(vars(Species_fac), ncol = 3)\n```\n\n#### Arrangement des graphiques {#sec-03142}\n\nLa solution avec les facettes est très pratique, mais également très limitée puisqu'elle ne permet pas de créer une figure avec des graphiques combinant plusieurs types de géométries. `ggarrange` du *package* `ggpubr` permet tout simplement de combiner des graphiques déjà existant. Créons deux nuages de points comparant plusieurs variables en fonction de l'espèce des iris, puis combinons-les (@fig-fig317). Attribuons également aux points une couleur en fonction de l'espèce des fleurs, afin de mieux les distinguer en associant la variable `Species` au paramètre `color`.\n\n```{r}\n#| label: fig-fig317\n#| fig-align: center\n#| fig-cap: Figure avec plusieurs graphiques avec ggarrange\n#| out-width: \"65%\"\nlibrary(ggpubr)\n\nplot1 <- ggplot(data = iris) +\n geom_point(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +\n labs(subtitle = \"Caractéristiques des sépales\",\n x = \"Longueur\", \n y = \"Largeur\",\n color = \"Espèce\")\n\nplot2 <- ggplot(data = iris) +\n geom_point(aes(x = Petal.Length, y = Petal.Width, color = Species)) +\n labs(subtitle = \"Caractéristiques des pétales\",\n x = \"Longueur\", \n y = \"Largeur\",\n color = \"Espèce\")\n\nliste_plots <- list(plot1, plot2)\ncomp_plot <- ggarrange(plotlist = liste_plots, ncol = 2, nrow = 1,\n common.legend = TRUE, legend = \"bottom\") #gérer la légende\n\nannotate_figure(comp_plot,\n top = text_grob(\"Morphologie des sépales et pétales des iris\",\n face = \"bold\", size = 12, just = \"center\"),\n bottom = text_grob(\"Source : jeu de données iris\",\n face = \"italic\", size = 8, just = \"left\")\n )\n```\n\nQuatre étapes sont nécessaires : \n\n1. Créer les graphiques et les enregistrer dans des objets (ici *plot1* et *plot2*).\n2. Encapsuler ces objets dans une liste (ici *liste_plots*).\n3. Composer la figure finale avec la fonction `ggarrange`.\n4. Ajouter les annotations à la figure composite.\n\nL'argument `common.legend` permet d'indiquer à la fonction `ggarrange` de regrouper les légendes des deux graphiques. Dans notre cas, les deux graphiques ont les mêmes légendes, il est donc judicieux de les regrouper. L'argument `legend` contrôle la position de la légende et peut prendre les valeurs : *top*, *bottom*, *left*, *right* ou *none* (absence de légende). La fonction `annotate_figure` permet d'ajouter des éléments de texte au-dessus, au-dessous et sur les cotés de la figure composite.\n\n### Couleur {#sec-0315}\n\nDans un graphique, la couleur peut être utilisée à la fois pour représenter une variable quantitative (dégradé de couleur ou mise en classes), ou une variable qualitative (couleur par catégorie). Dans `ggplot2`, il est possible d'attribuer une couleur au contour des géométries avec l'argument `color` et au remplissage avec l'argument `fill`. Il est possible de spécifier une couleur de trois façons dans R : \n\n* En utilisant le nom de la couleur dans une chaîne de caractère : `\"chartreuse4\"`. R dispose de 657 noms de couleurs prédéfinis. Pour tous les afficher, utilisez la fonction `colors()`, qui permet de les visualiser (@fig-colors).\n\n![Couleurs de base](images/Chap03/all_colors.png){#fig-colors width=\"100%\" fig-align=\"center\"}\n\n* En indiquant le code hexadécimal de la couleur. Il s'agit d'une suite de six lettres et de chiffres précédée par un dièse : `\"#99ff33\"`.\n\n* En utilisant une notation RGB (rouge, vert, bleu, transparence). Cette notation doit contenir quatre nombres entre 0 et 1 (0 % et 100 %), indiquant respectivement la quantité de rouge, de vert, de bleu et la transparence. Ces quatre nombres sont donnés comme argument à la fonction `rgb` : `rgb(0.6, 1, 0.2, 0)`.\n\nLe choix des couleurs est un problème plus complexe que la manière de les spécifier. Il existe d'ailleurs tout un pan de la sémiologie graphique dédié à la question du choix et de l'association des couleurs. Une première ressource intéressante est [ColorBrewer](https://colorbrewer2.org/#type=sequential&scheme=BuGn&n=3){target=\"_blank\"}. Il s'agit d'une sélection de palettes de couleurs particulièrement efficaces et dont certaines sont même adaptées pour les personnes daltoniennes (@fig-colorBrewer). Il est possible d'accéder directement aux palettes dans R grâce au *package* `RColorBrewer` et la fonction `brewer.pal` : \n\n```{r}\n#| label: fig-colorBrewer\n#| fig-align: center\n#| fig-cap: Palette de couleurs de ColorBrewer\n#| out-width: \"85%\"\n\nlibrary(RColorBrewer)\ndisplay.brewer.all()\n```\n\nUne autre ressource pertinente est le site web [coolors.co](https://coolors.co/palettes/trending){target=\"_blank\"} qui propose de nombreuses palettes à portée de clic.\n\n## Principaux graphiques {#sec-032}\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Construire des graphiques avec `ggplot2`**\n:::\n::: bloc_objectif-body\nPuisque vous avez désormais une certaine connaissance des bases de la grammaire des graphiques implémentées par `ggplot2`, vous apprendrez dans les sous-sections suivantes à construire les principaux graphiques que vous utiliserez régulièrement ou que vous présenterez dans un article scientifique.\n:::\n:::\n\n### Histogramme {#sec-0321}\n\nL'histogramme permet de décrire graphiquement la forme de la distribution d'une variable. Pour le réaliser, nous utilisons la fonction `geom_histogram`. Le paramètre le plus important est le nombre de barres (`bins`) qui composent l'histogramme. Plus ce nombre est grand, plus l'histogramme est précis et, à l'inverse, plus il est petit, plus l'histogramme est simplifié. En revanche, il faut éviter d'utiliser un nombre de barres trop élevé comparativement au nombre d'observations disponibles dans le jeu de données, sinon l'histogramme risque d'avoir plein de trous.\n\n#### Histogramme simple {#sec-03211}\n\nGénérons quatre variables ayant respectivement une distribution gaussienne, Student, Gamma et bêta, puis réalisons un histogramme pour chacune de ces variables et combinons-les avec la fonction `ggarrange` (@fig-fig318).\n\n```{r}\n#| label: fig-fig318\n#| fig-align: center\n#| fig-cap: Histogrammes\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\ndistribs <- data.frame(\n gaussien = rnorm(1000, mean = 5, sd = 1.5),\n gamma = rgamma(1000, shape = 2, rate = 12),\n beta = rbeta(1000, shape1 = 5, shape2 = 1, ncp = 2),\n student = rt(1000, ncp = 20, df = 5)\n)\n\nplot1 <- ggplot(data = distribs) +\n geom_histogram(aes(x = gaussien), bins = 50, color = \"#343a40\", fill = \"#e63946\")+\n labs(y = \"fréquences\")+ylim(c(0,130))\n\nplot2 <- ggplot(data = distribs) +\n geom_histogram(aes(x = gamma), bins = 50, color = \"#343a40\", fill = \"#f1faee\")+\n labs(y = \"fréquences\")+ylim(c(0,130))\n\nplot3 <- ggplot(data = distribs) +\n geom_histogram(aes(x = beta), bins = 50, color = \"#343a40\", fill = \"#a8dadc\")+\n labs(y = \"fréquences\")+ylim(c(0,130))\n\nplot4 <- ggplot(data = distribs) +\n geom_histogram(aes(x = student), bins = 50, color = \"#343a40\", fill = \"#1d3557\")+\n labs(y = \"fréquences\")+ylim(c(0,130))\n\nhistogrammes <- list(plot1, plot2, plot3, plot4)\n\nggarrange(plotlist = histogrammes, ncol = 2, nrow = 2)\n\n```\n\n\nNotez que cette syntaxe est très lourde. Dans le cas présent, il serait plus judicieux d'utiliser la fonction `facet_wrap`. Pour cela, nous devons au préalable empiler nos données, ce qui signifie changer la forme du *DataFrame* actuel, qui comprend quatre colonnes (gaussien, Gamma, bêta et student) et 1000 observations, pour qu'il n'ait plus que deux colonnes (la valeur originale et le nom de l'ancienne colonne) et 4000 observations. La @fig-fig319 décrit graphiquement ce processus qui peut être effectué avec la fonction `melt` du *package* `reshape2`.\n\n![Empiler les données d'un DataFrame](images/Chap03/melting.png){#fig-fig319 width=\"30%\" fig-align=\"center\"}\n\n```{r}\n#| label: fig-fig320\n#| fig-align: center\n#| fig-cap: Histogrammes à facettes\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\nlibrary(reshape2)\n\n# Faire fondre le jeu de données\nmelted_distribs <- melt(distribs, measure.vars = c(\"gaussien\", \"gamma\",\n \"beta\" , \"student\"))\n# Renommer les colonnes du nouveau DataFrame\nnames(melted_distribs) <- c(\"distribution\", \"valeur\")\n# Convertir la variable catégorielle en facteur\nmelted_distribs$distribution <- as.factor(melted_distribs$distribution)\n\nggplot(data = melted_distribs)+\n geom_histogram(aes(x = valeur, fill = distribution), bins = 50, color = \"#343a40\") +\n ylim(c(0,130)) + \n labs(x = \"valeur\", \n y = \"fréquences\")+\n scale_fill_manual(values = c(\"#e63946\" , \"#f1faee\" , \"#a8dadc\" , \"#1d3557\"))+\n facet_wrap(vars(distribution), ncol = 2, scales = \"free\")+\n theme(legend.position = \"none\")\n```\n\n#### Histogramme de densité {#sec-03212}\n\nLes histogrammes que nous venons de construire utilisent la fréquence des observations pour délimiter la hauteur des barres. Il est possible de changer ce comportement pour plutôt utiliser la densité. L'intérêt est notamment de se rapprocher encore de la définition d'une distribution puisqu'avec cette configuration, la somme totale de la surface de l'histogramme est égale à 1. La hauteur de chaque barre représente alors la probabilité d'obtenir l'étendue de valeurs représentées par cette barre. Prenons pour exemple la variable avec la distribution normale que nous venons de voir.\n\n```{r}\n#| label: fig-fig321\n#| fig-align: center\n#| fig-cap: Histogrammes de densité\n#| out-width: \"65%\"\n\nplot1 <- ggplot(data = distribs) +\n geom_histogram(aes(x = gaussien, y = after_stat(density)),\n bins = 30, color = \"#343a40\", fill = \"#1d3557\")+\n labs(x = \"gaussien\", y = \"densité\")\n\nplot2 <- ggplot(data = distribs) +\n geom_histogram(aes(x = gaussien, y = ..count..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\")+\n labs(x = \"gaussien\", y = \"fréquences\")\n\nggarrange(plotlist = list(plot1, plot2), ncol = 2)\n```\n\nLe graphique de droite (fréquence) nous indique donc que plus de 60 observations ont une valeur d'environ 5 (entre 4,76 et 5,34, compte tenu de la largeur de la barre), ce qui se traduit par une probabilité de presque 30 % d'obtenir cette valeur en tirant une observation au hasard dans le jeu de données.\n\n#### Histogramme avec courbe de distribution {#sec-03213}\n\nLes histogrammes sont souvent utilisés pour vérifier graphiquement si une distribution empirique s'approche d'une courbe normale. Pour cela, nous ajoutons sur l'histogramme de la variable empirique la forme qu'aurait une distribution normale parfaite en utilisant la moyenne et l'écart type de la distribution empirique. Pour créer cette figure dans `ggplot2`, il suffit d'utiliser la fonction `stat_function` pour créer un nouveau calque. Il est aussi possible d'ajouter une ligne verticale (`geom_vline`) pour indiquer la moyenne de la distribution.\n\n```{r}\n#| label: fig-fig322\n#| fig-align: center\n#| fig-cap: Histogramme et courbe normale\n#| out-width: \"65%\"\n\nmoyenne <- mean(distribs$gaussien)\necart_type <- sd(distribs$gaussien)\n\nggplot(data = distribs) +\n geom_histogram(aes(x = gaussien, y = after_stat(density)),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n labs(x = \"gaussien\", \n y = \"densité\")+\n stat_function(fun = dnorm, args = list(mean = moyenne, sd = ecart_type), \n color = \"#e63946\", linewidth = 1.2, linetype = \"dashed\") +\n geom_vline(xintercept = moyenne, color = \"red\", linetype = 1)+\n annotate(\"text\", x = round(moyenne,2)+0.5, y = 0.31, hjust = 'left',\n label = paste('moyenne : ', round(moyenne,2), sep=''))\n```\n\nDans notre cas, nous savons que notre variable est normalement distribuée (car produite avec la fonction `rnorm`), et nous pouvons constater la grande proximité entre l'histogramme et la courbe normale.\n\n#### Histogramme avec coloration des valeurs extrêmes {#sec-03214}\n\nIl peut être nécessaire d'attirer le regard sur certaines parties de l'histogramme, comme sur des valeurs extrêmes. Si nous reprenons notre distribution de Student, nous pouvons clairement distinguer un ensemble de valeurs fortes à droite de la distribution. Nous pourrions, dans notre cas, considérer que des valeurs au-delà de 50 constituent des cas extrêmes que nous souhaitons représenter dans une autre couleur. Pour cela, nous devons créer une variable catégorielle nous permettant de distinguer ces cas particuliers.\n\n```{r}\n#| label: fig-fig323\n#| fig-align: center\n#| fig-cap: Histogramme coloré\n#| out-width: \"65%\"\n\ndistribs$cas_extreme <- ifelse(distribs$student >=50, \"extrême\", \"normale\")\n\nggplot(data = distribs) +\n geom_histogram(aes(x = student, y = ..count.., fill = cas_extreme),\n bins = 30, color = \"#343a40\")+\n scale_fill_manual(\"\", values = c(\"#a8dadc\" , \"#e63946\"))+\n labs(title = \"Distribution de Student\", x = \"valeur\", y = \"fréquence\")\n\n```\n\n### Graphique de densité {#sec-0322}\n\nL'histogramme est utilisé pour approximer graphiquement la distribution d'une variable. Sa principale limite est de représenter la variable de façon discontinue. Une option intéressante est d'utiliser une version lissée de l'histogramme, soit le graphique de densité. Cette opération de lissage est réalisée le plus souvent à partir de fonctions kernel. Reconstruisons notre figure avec les quatre distributions, mais en utilisant cette fois-ci des graphiques de densité.\n\n```{r}\n#| label: fig-fig324\n#| fig-align: center\n#| fig-cap: Graphiques de densité à facette\n#| out-width: \"65%\"\n\nggplot(data = melted_distribs)+\n geom_density(aes(x = valeur, fill = distribution), color = \"#343a40\") +\n scale_fill_manual(values = c(\"#e63946\" , \"#f1faee\" , \"#a8dadc\" , \"#1d3557\"))+\n facet_wrap(vars(distribution), ncol = 2, scales = \"free\")+\n theme(legend.position = \"none\")\n```\n\nLes graphiques de densité sont souvent utilisés pour comparer la distribution d'une variable pour plusieurs sous-groupes d'une population. Si nous reprenons le jeu de données *iris*, nous pouvons comparer les longueurs de sépales en fonction des espèces. Nous constatons ainsi que les setosas ont une nette tendance à avoir des sépales plus courts et qu'à l'inverse, les virginicas ont les sépales généralement les plus longs.\n\n```{r}\n#| label: fig-fig325\n#| fig-align: center\n#| fig-cap: Graphiques de densité superposés\n#| out-width: \"65%\"\n\nggplot(data = iris)+\n geom_density(aes(x = Sepal.Length, fill = Species), \n color = \"#343a40\", alpha = 0.4)+\n labs(x = \"Longueur de sépales\",\n y = \"\",\n fill = \"Espèce\")\n```\n\n\n### Nuage de points {#sec-0323}\n\nUn nuage de points est un outil très intéressant pour visualiser la relation existante entre deux variables. Prenons un exemple concret et analysons le volume de CO~2~ produit annuellement par habitant en comparaison avec le niveau d'urbanisation dans l'ensemble des pays à travers le monde. Nous avons extrait ces données sur le site web de la [Banque mondiale](https://donnees.banquemondiale.org/indicateur){target=\"_blank\"}, puis nous les avons structurés dans un fichier *csv*.\n\n```{r}\ndata_co2 <- read.csv(\"data/graphique/world_urb_co2.csv\", encoding = \"UTF-8\")\nnames(data_co2)\n```\n\n#### Nuage de points simple {#sec-03231}\n\nCommençons par un nuage de points simple avec l'ensemble des données.\n\n```{r}\n#| echo: true\n#| eval: false\nggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab))+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\n\n```{r}\n#| label: fig-fig326\n#| echo: false\n#| fig-align: center\n#| fig-cap: Nuage de points simple\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\n ggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab))+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\nÀ la première lecture de ce graphique, nous observons immédiatement un ensemble de points étranges dont le volume de CO~2~ par habitant annuel est au-dessus de 150 tonnes et dont le niveau d'urbanisation est proche de 50 %. Isolons ces données pour observer de quoi il s'agit.\n\n```{r}\ncas_etrange <- subset(data_co2, data_co2$CO2t_hab >= 150)\nprint(cas_etrange$Country.Name)\n```\n\nIl s'agit d'une petite île néerlandaise des Caraïbes nommée Aruba disposant d'une faible population, mais avec des activités très polluantes (raffinerie et extraction d'or). Nous faisons ici le choix de retirer ces observations puisqu'elles sont assez peu représentatives de la tendance mondiale. Cette démarche si simple relève ainsi de l'analyse exploratoire des données! Sans ce graphique, nous n'aurions probablement jamais identifié ces cas problématiques.\n\n\n```{r}\ndata_co2 <- subset(data_co2, data_co2$CO2t_hab <= 150)\n```\n\nReconstruisons le nuage de points maintenant que ces données aberrantes ont été retirées.\n\n```{r}\n#| label: fig-fig327\n#| fig-align: center\n#| fig-cap: Nuage de points simple sans données aberrantes\n#| warning: false\n#| out-width: \"65%\"\n\ngraphique <- ggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab))+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\nVoilà qui est mieux! Cependant, le grand nombre de points restant rend la lecture du graphique assez difficile puisqu'ils se superposent. Une première option à envisager, dans ce cas, est à la fois d'ajouter de la transparence aux points et de réduire leur taille : \n\n```{r}\n#| label: fig-fig328\n#| fig-align: center\n#| fig-cap: Nuage de points simple avec transparence\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\nggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab), alpha = 0.2, size = 0.5)+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\n\n#### Nuage de points avec densité {#sec-03232}\n\nBien que la transparence nous aide un peu à distinguer les secteurs du graphique avec le plus de points, il serait plus efficace d'abandonner la géométrie des points pour la remplacer par une géométrie de densité en deux dimensions. Une première approche consiste à diviser l'espace du graphique en petits carrés et à compter le nombre de points tombant dans chaque carré (en somme, un histogramme en deux dimensions).\n\n```{r}\n#| label: fig-fig329\n#| fig-align: center\n#| fig-cap: Nuage de points simple\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\nggplot(data = data_co2)+\n geom_bin2d(aes(x = Urbanisation, y = CO2t_hab), bins = 50) +\n scale_fill_continuous(type = \"viridis\") +\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n fill = \"Effectif\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\nNous observons ainsi une forte concentration dans le bas du graphique; les pays avec des rejets annuels de CO~2~ supérieurs à 15 tonnes par habitant sont relativement rares. Pour les personnes préférant les représentations plus élaborées, il est aussi possible de diviser l'espace du graphique avec des hexagones en utilisant le *package* `hexbin`.\n\n```{r}\n#| label: fig-fig330\n#| fig-align: center\n#| fig-cap: Densité en deux dimensions par hexagones\n#| warning: false\n#| out-width: \"65%\"\n\nggplot(data = data_co2)+\n geom_hex(aes(x = Urbanisation, y = CO2t_hab), bins = 50) +\n scale_fill_continuous(type = \"viridis\") +\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n fill = \"Effectif\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\nEnfin, il est aussi possible de réaliser une version lissée de ces graphiques avec une fonction kernel en deux dimensions (`stat_density_2d`) : \n\n```{r}\n#| label: fig-fig331\n#| fig-align: center\n#| fig-cap: Densité lissée en deux dimensions\n#| warning: false\n#| out-width: \"65%\"\n\nggplot(data = data_co2)+\n stat_density_2d(aes(x = Urbanisation, y = CO2t_hab, fill = ..density..), \n geom = \"raster\", n = 50, contour = FALSE) +\n scale_fill_continuous(type = \"viridis\") +\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n fill = \"densité\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")+\n ylim(0,25)\n```\n\n#### Nuage de points et droite de régression {#sec-03233}\n\nAfin de faire ressortir une éventuelle relation entre les variables représentées sur les deux axes, il est possible d'afficher la droite de régression sur le graphique entre X et Y. Cette opération s'effectue avec la fonction `geom_smooth`.\n\n\n```{r}\n#| label: fig-fig332\n#| fig-align: center\n#| fig-cap: Nuage de points avec droite de régression\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\nggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab), alpha = 0.2, size = 0.5)+\n geom_smooth(aes(x = Urbanisation, y = CO2t_hab), method = lm, color = \"red\")+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\nNotez que l'argument `method = lm` permet d'indiquer que nous souhaitons utiliser une régression linéaire (*linear model*) pour tracer la géométrie (une droite de régression). La droite semble bien indiquer une relation positive entre les deux variables : une augmentation de l'urbanisation serait associée à une augmentation de la production annuelle de CO~2~ par habitant. Nous pourrions également vérifier si une relation non linéaire serait plus adaptée au jeu de données. Dans notre cas, une relation quadratique pourrait produire un meilleur ajustement.\n\n\n```{r}\n#| label: fig-fig333\n#| fig-align: center\n#| fig-cap: Nuage de points avec droite de régression quadratique\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\nggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab), alpha = 0.2, size = 0.7)+\n geom_smooth(aes(x = Urbanisation, y = CO2t_hab), method = lm, \n color = \"red\", formula = y ~ I(x**2))+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\nLa régression quadratique (avec *x* au carré) nous indique ainsi que l'impact du niveau d'urbanisation est plus important à mesure que ce niveau augmente. Vous pouvez également constater que la courbe ne prédit pas de valeurs négatives comparativement à la droite précédente. Il est également possible d'ajuster une courbe sans choisir au préalable sa forme (dans le cas précédent $x^2$) en utilisant une méthode d'ajustement local appelée *loess*.\n\n\n```{r}\n#| label: fig-fig334\n#| fig-align: center\n#| fig-cap: Nuage de points avec droite de régression non linéaire\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\nggplot(data = data_co2)+\n geom_point(aes(x = Urbanisation, y = CO2t_hab), alpha = 0.2, size = 0.5)+\n geom_smooth(aes(x = Urbanisation, y = CO2t_hab), method = loess, \n color = \"red\")+\n labs(x = \"Niveau d'urbanisation (%)\",\n y = \"Tonnes de CO2 par année et par habitant\",\n title = \"Relation entre urbanisation et production de CO2 par habitant\")\n```\n\nLa relation non linéaire révèle davantage d'informations : l'augmentation de l'urbanisation est associée à une augmentation de l'émission de CO~2~ par habitant uniquement jusqu'à 75 % d'urbanisation; au-delà de ce seuil, la relation ne tient plus. Ces résultats semblent cohérents avec l'évolution classique de l'économie d'un pays passant progressivement d'une économie agricole, à une économie industrialisée et finalement une économie de services.\n\n### Graphique en ligne {#sec-0324}\n\nUn graphique en ligne permet de représenter l'évolution d'une variable, généralement dans le temps. Dans le jeu de données précédent, nous disposons des émissions de CO~2~ par habitant de nombreux pays sur plusieurs années. Nous pouvons ainsi représenter l'évolution des émissions pour chaque pays avec un graphique en ligne. Pour éviter de le surcharger, cet exercice est réalisé uniquement sur les pays de l'Europe de l'Ouest.\n\n```{r}\n#| label: fig-fig335\n#| fig-align: center\n#| fig-cap: Graphique en ligne\n#| out-width: \"65%\"\n#| warning: false\n#| message: false\n\n# conversion de la variable year textuelle en variable numérique\ndata_co2$an <- as.numeric(data_co2$year)\n# extraction des données d'Europe de l'Ouest\ndata_europe <- subset(data_co2, data_co2$region23 == \"Europe de l'Ouest\")\n# choix des valeurs pour l'axe des x\nx_ticks <- seq(1960,2020,10)\n\nggplot(data = data_europe)+\n geom_path(aes(x = an, y = CO2t_hab, color = Country.Name))+\n labs(x = \"Années\",\n y = \"Tonnes de CO2 par année et par habitant\",\n color = \"Pays\",\n title = \"Évolution de la production de CO2 par habitant\") +\n scale_x_continuous(breaks = x_ticks, labels = x_ticks)+\n theme_tufte()\n\n```\n\nNous remarquons notamment qu'aucune donnée, avant 2005, n'est disponible pour le Liechtenstein.\n\n#### Barre d'erreur et en bande {#sec-03241}\n\nSur un graphique, il est souvent pertinent de représenter l'incertitude que nous avons sur nos données. Cela peut être fait à l'aide de barres d'erreur ou à l'aide de polygones délimitant les marges d'incertitude. En guise d'exemple, admettons que les données précédentes sont fiables à plus ou moins 10 %. En d'autres termes, la valeur d'émission de CO~2~ annuelle serait relativement incertaine et pourrait se situer dans un intervalle de 10 % autour de la valeur fournie par la Banque mondiale. Nous obtenons ainsi une borne inférieure (valeur donnée - 10 %) et une borne supérieure (valeur donnée + 10 %). Nous pouvons facilement calculer ces bornes et les faire apparaître dans notre graphique précédent.\n\n```{r}\n#| label: fig-fig336\n#| fig-align: center\n#| fig-cap: Graphique en ligne avec barres d'erreur\n#| out-width: \"65%\"\n\ndata_europe$borne_basse <- data_europe$CO2t_hab - 0.1 * data_europe$CO2t_hab\ndata_europe$borne_haute <- data_europe$CO2t_hab + 0.1 * data_europe$CO2t_hab\n\nggplot(data = data_europe)+\n geom_point(aes(x = an, y = CO2t_hab, color = Country.Name), size = 0.7)+\n geom_errorbar(aes(x = an, ymin = borne_basse, ymax = borne_haute, color = Country.Name))+\n labs(x = \"Années\",\n y = \"Tonnes de CO2 par année et par habitant\",\n color = \"Pays\",\n title = \"Évolution de la production de CO2 par habitant\") +\n scale_x_continuous(breaks = x_ticks, labels = x_ticks)+\n theme_tufte()\n```\n\nCes barres d'erreurs indiquent notamment qu'il n'y a finalement aucun écart significatif entre la Belgique, les Pays-Bas et l'Allemagne à partir des années 1990. Une autre option de représentation est d'utiliser des polygones avec la fonction `geom_ribbon`.\n\n```{r}\n#| label: fig-fig337\n#| fig-align: center\n#| fig-cap: Graphique en ligne avec marge d'erreur\n#| out-width: \"65%\"\n\nggplot(data = data_europe)+\n geom_path(aes(x = an, y = CO2t_hab, color = Country.Name), size = 0.7)+\n geom_ribbon(aes(x = an, ymin = borne_basse, ymax = borne_haute,\n fill = Country.Name), alpha = 0.4)+\n labs(x = \"Années\",\n y = \"Tonnes de CO2 par année et par habitant\",\n color = \"Pays\",\n title = \"Évolution de la production de CO2 par habitant\") +\n scale_x_continuous(breaks = x_ticks, labels = x_ticks)+\n theme_tufte()+\n guides(fill = FALSE, scale = \"none\")\n```\n\nLe message du graphique est le même. Notez que nous avons utilisé ici la fonction `guides` pour retirer de la légende les couleurs associées au remplissage des marges d'erreur. Ces couleurs sont les mêmes que celles des lignes et il n'est pas utile de dédoubler la légende. De nombreuses méthodes statistiques produisent des résultats accompagnés d'une mesure de l'incertitude associée à ces résultats. Représenter cette incertitude est crucial pour que le lecteur puisse délimiter la portée des conclusions de vos analyses.\n\n### Boîte à moustaches {#sec-0325}\n\nLes boîtes à moustaches (*box plot* en anglais) sont des graphiques permettant de comparer les moyennes et les intervalles interquartiles d'une variable continue selon plusieurs groupes d'une population. Si nous reprenons notre exemple précédent, nous pourrions comparer, en fonction de la région du monde, la moyenne de production annuelle de CO~2~ par habitant. Pour cela, il suffit d'utiliser la fonction `geom_boxplot`.\n\n```{r}\n#| label: fig-fig338\n#| fig-align: center\n#| fig-cap: Boîtes à moustaches\n#| out-width: \"65%\"\n\n# Retirer les observations n'étant pas associées à une région\ndata_co2_comp <- subset(data_co2, is.na(data_co2$region7) == FALSE)\n\nggplot(data = data_co2_comp)+\n geom_boxplot(aes(y = region7, x = CO2t_hab))+\n labs(x = \"Tonnes de CO2 par an et habitant\", y = \"Région\")\n```\n\nLa barre centrale d'une boîte représente la moyenne. Les extrémités de la boîte représentent le premier et le troisième quartile. Plus une boîte est allongée, plus les situations sont diversifiées pour les observations appartenant au groupe représenté par la boîte. Au contraire, une boîte étroite indique un groupe homogène. Notez qu'en inversant les variables dans les axes *X* et *Y*, nous obtiendrions des boîtes à moustaches verticales. Cependant, les noms des régions étant assez longs, cela nécessiterait d'avoir un graphique très large. Améliorons quelque peu le rendu de ce graphique en ajoutant des titres.\n\n```{r}\n#| label: fig-fig339\n#| fig-align: center\n#| fig-cap: Boîtes à moustaches améliorées\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\nggplot(data = data_co2_comp)+\n geom_boxplot(aes(y = region7, x = CO2t_hab))+\n xlim(c(0,50))+\n labs(x = \"Tonnes de CO2 par an et habitant\",\n y = \"Région\")\n```\n\nLes points noirs sur le graphique représentent des valeurs extrêmes, soit des observations situées à plus de 1,5 intervalle interquartile d'une extrémité de la boîte. Pour mieux rendre compte de la densité d'observations le long de chaque boîte à moustaches, il est possible de les représenter directement avec la fonction `geom_jitter`.\n\n```{r}\n#| label: fig-fig340\n#| echo: false\n#| fig-align: center\n#| fig-cap: Boîtes à moustaches avec observations\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\nggplot(data = data_co2_comp)+\n geom_boxplot(aes(y = region7, x = CO2t_hab), outlier.shape = NA)+\n geom_jitter(aes(y = region7, x = CO2t_hab), size = 0.2, alpha = 0.2)+\n xlim(c(0,50))+\n labs(x = \"Tonnes de CO2 annuelle par habitant\",\n y = \"Région\")\n```\nNotez que pour éviter que les valeurs extrêmes identifiées par la fonction `geom_boxplot` se superposent avec les points représentant les observations, nous les avons supprimées avec l'argument `outlier.shape = NA`.\n\n### Graphique en violon {#sec-0326}\n\nLes boîtes à moustaches donnent des informations pertinentes sur le centre et la dispersion d'une variable en fonction de sous groupes de la population. Cependant, une grande partie de l'information reste masquée par la représentation sous forme de boîte. Une solution est de remplacer la simple boîte par la distribution de la variable étudiée. Nous obtenons ainsi des graphiques en violon (`geom_violin`). Considérant les très grands écarts que nous avons observés entre les régions avec les boîtes à moustaches, il est préférable de tracer les graphiques en violon en excluant les régions Afrique Sub-Saharienne et Asie du Sud.\n\n```{r}\n#| label: fig-fig341\n#| fig-align: center\n#| fig-cap: Graphiques en violon\n#| warning: false\n#| out-width: \"65%\"\n\n# Retirons les observations de régions que nous ne souhaitons pas garder\ndata_co2_comp <- subset(data_co2, (! data_co2$region7 %in% \n c(\"Sub-Saharan Africa\", \"South Asia\")) \n & is.na(data_co2$region7) == FALSE)\n\nggplot(data = data_co2_comp)+\n geom_violin(aes(y = region7, x = CO2t_hab))+\n xlim(c(0,50))+\n labs(x = \"Tonnes de CO2 par année et par habitant\",\n y = \"\")+\n geom_vline(xintercept = 12, linetype = 'dashed', color = \"blue\")\n```\n\nCes distributions permettent notamment de souligner que deux groupes distincts se retrouvent en Amérique du Nord. L'un dont les émissions annuelles de CO~2~ par habitant sont inférieures à 12 tonnes (ligne bleue) et l'autre pour lequel elles sont supérieures. En explorant les données, nous constatons que les Bermudes appartiennent au groupe Amérique du Nord, mais ont des niveaux d'émission inférieurs à ceux du Canada et des États-Unis, ce qui explique cette distribution bimodale. Cette information était masquée avec les boîtes à moustaches. Finalement, il est aussi possible de superposer un graphique en violon et une boîte à moustaches pour bénéficier des avantages des deux.\n\n```{r}\n#| label: fig-fig342\n#| fig-align: center\n#| fig-cap: Graphiques en violon et boîtes à moustaches\n#| warning: false\n#| out-width: \"65%\"\n\nggplot(data = data_co2_comp)+\n geom_violin(aes(y = region7, x = CO2t_hab))+\n geom_boxplot(aes(y = region7, x = CO2t_hab), width = 0.15)+\n xlim(c(0,50))+\n labs(x = \"Tonnes de CO2 par année et par habitant\",\n y = \"\")\n```\n\n### Graphique en barres {#sec-0327}\n\nLes graphiques en barres permettent de représenter des quantités (hauteur des barres) réparties dans des catégories (une barre par catégorie). Nous proposons ici un exemple avec des données de déplacements issues de l'*Enquête origine-destination 2017 - Région Québec-Lévis*, au niveau des grands secteurs. La @fig-fig342, tirée du [rapport](https://www.transports.gouv.qc.ca/fr/ministere/Planification-transports/enquetes-origine-destination/quebec/2017/Documents/EOD17_faits_saillants_VF.pdf) intitulé *La mobilité des personnes dans la région de Québec-Lévis (Volet Enquête-ménages : faits saillants)* délimite ces grands secteurs.\n\n![Grands secteurs de Québec](images/Chap03/carte_secteurs.jpg){#fig-fig343 width=\"100%\" fig-align=\"center\"}\n\nNous représentons pour chaque secteur le nombre moyen de déplacements entrant et sortant un jour de semaine en heures de pointe. Les données sont présentées sous forme d'une matrice carrée (avec autant de lignes que de colonnes). L'intersection de la ligne A et de la colonne C indique le nombre de personnes partant du secteur A pour se rendre au secteur C. À l'inverse, l'intersection de la ligne C et de la colonne A indique le nombre de personnes partant du secteur C pour se rendre au secteur A. En sommant les valeurs de chaque ligne, nous obtenons le nombre total de départs par secteur tandis que le nombre d'arrivées est la somme de chaque colonne. Ces opérations peuvent simplement être effectuées avec les fonctions `rowSums` et `colSums`.\n\n```{r}\n#| label: fig-fig344\n#| fig-align: center\n#| fig-cap: Graphiques en barre simples\n#| out-width: \"75%\"\n\n# Chargement des données\nmatriceOD <- read.csv('data/graphique/Quebec_2017_OD_MJ.csv',\n header = FALSE, sep = ';') # fichier csv sans entête\n\n# Calcul des sommes en lignes et en colonnes\ntot_depart <- rowSums(matriceOD)\ntot_arrivee <- colSums(matriceOD)\n\n# Création d'un DataFrame avec les valeurs et les noms des secteurs\ndf <- data.frame(depart = tot_depart,\n arrivee = tot_arrivee, \n secteur = c('Arr. de Beauport (Québec)',\n 'Arr. de Charlesbourg (Québec)',\n 'Arr. des Rivières (Québec)',\n 'Arr. de la Cité-Limoilou (Québec)',\n 'Arr. de la Haute-Saint-Charles (Québec)',\n 'Arr. de Sainte-Foy-Sillery-Cap-Rouge (Québec)',\n 'Arr.de Desjardins (Lévis)',\n 'Arr. des Chutes–de-la-Chaudière-Est (Lévis)',\n 'Arr. des Chutes de la Chaudière-Ouest (Lévis)',\n 'Ceinture Nord',\n 'Ceinture Sud',\n 'Hors Territoire'),\n code = c('A','B','C','D','E','F','G','H','I','J','K','X'))\n\n# Création des deux graphiques en barre\nplot1 <- ggplot(data = df)+\n geom_bar(aes(x = code, weight = depart))+\n labs(subtitle = \"Départs\",\n x = \"total\",\n y = \"\")\n\nplot2 <- ggplot(data = df)+\n geom_bar(aes(x = code, weight = arrivee))+\n labs(subtitle = \"Arrivées\",\n x = \"total\",\n y = \"\")\n\n# Stocker les graphiques dans une liste et composer une figure\nlist_plot <- list(plot1, plot2)\ntot_plot <- ggarrange(plotlist = list_plot, ncol = 1)\n\n# Création d'une légende pour associer le code de chaque secteur \n# à son nom. Pour cela nous concaténons en premier les lettres et les noms.\n# Nous fusionnons ensuite le tout en les séparant par le symbole \\n représentant \n# un saut de ligne.\nnom_secteurs <- paste(df$code, df$secteur, sep= ' : ')\nstring_names <- paste(nom_secteurs, collapse = '\\n')\n\ntitre <- \"Déplacements journaliers moyens en heures de pointe\"\n# Production finale de la figure\nannotate_figure(tot_plot,\n top = text_grob(titre, face = \"bold\", size = 11, just = \"left\"),\n right = text_grob(string_names, face = \"italic\", size = 8,\n just = \"left\", x = 0.05) # position du texte\n )\n\n```\n\nPlutôt que de représenter les arrivées et les départs dans deux graphiques séparés, il est possible de les empiler dans un même graphique en barres. Nous devons au préalable « faire fondre nos données » avec la fonction `melt`.\n\n```{r}\n#| label: fig-fig345\n#| fig-align: center\n#| fig-cap: Graphique en barre empilée\n#| out-width: \"65%\"\n\n# Faire fondre le jeu de données (empiler les colonnes depart et arrivee)\nmelted_df <- melt(df, id.vars = c('code'), measure.vars = c('depart','arrivee'))\nnames(melted_df) <- c('code','deplacement','effectif')\n# Ajouter les accents dans la colonne déplacement\nmelted_df$deplacement <- ifelse(melted_df$deplacement == 'depart', 'départs', 'arrivées')\n# Comparaison du format original et du format \"fondu\"\nhead(df)\nhead(melted_df)\n# Réalisation du graphique\nplot1 <- ggplot(data = melted_df)+\n geom_bar(aes(x = code, weight = effectif, fill = deplacement), color = '#e3e3e3')+\n scale_fill_manual(values = c(\"#e63946\" , \"#1d3557\"))+\n labs(title = titre,\n y = \"Effectifs\",\n x = \"\",\n fill = \"Déplacements\")\n\nannotate_figure(plot1, right = text_grob(string_names, face = \"italic\", size = 7,\n just = \"left\", x = 0.05)) # position du texte)\n```\n\n### Graphique circulaire {#sec-0328}\n\nUne option directe au graphique en barres est le graphique ou diagramme circulaire, appelé aussi graphique en tarte (pour les personnes à la dent sucrée) ou en camembert (pour celles amatrices de fromage). Il est suffisamment connu et utilisé pour qu'aucune présentation ne s'impose. Pour être exact, un graphique en tarte n'est rien d'autre qu'un graphique en barres dont le système de coordonnées a été modifié. Cela impose cependant de calculer à l'avance la position des étiquettes que nous souhaitons ajouter sur le graphique. Reprenons les données de production mondiale de CO~2~ et calculons les productions totales par région géographique en 2015.\n\n```{r}\n#| label: fig-fig346\n#| fig-align: center\n#| fig-cap: Graphique en tarte\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\nlibrary(dplyr)\n\n# Extraire les données de 2018 pour lesquelles nous connaissons la région\ndata_co2_2015 <- subset(data_co2, data_co2$year == \"2015\" & ! is.na(data_co2$region7))\n\n# Effectuer la somme du CO2 par région\nco2_2015 <- data_co2_2015 %>% \n group_by(region7) %>% \n summarise(total_co2 = sum(CO2_kt, na.rm = TRUE))\n\n# Attribuer un code à chaque région pour faciliter la lecture\nco2_2015$code <- c(\"A\" , \"B\" , \"C\" , \"D\" , \"E\" , \"F\" , \"G\")\n\n# Modifier l'ordre des données, calculer les proportions et la position des labels\ndf <- co2_2015 %>% \n arrange(desc(code)) %>%\n mutate(prop = total_co2 / sum(co2_2015$total_co2) *100) %>%\n mutate(ypos = cumsum(prop)- 0.5*prop )\n\n# Préparer la légende (pourcentages et vrais noms)\nnom_region <- rev(paste(df$code, \" : \", df$region7, \"(\", round(df$prop,1),\"%)\"))\nstring_region <- paste(nom_region, collapse = '\\n')\n\n# Construire le graphique\nplot1 <- ggplot(df, aes(x = \"\", y = prop, fill = code)) +\n geom_bar(stat = \"identity\", width=1, color = \"white\") +\n coord_polar(\"y\", start=0) +\n theme_void() + \n theme(legend.position = \"none\") +\n geom_text(aes(y = ypos, label = code), color = \"white\", size=3) +\n scale_fill_grey()+\n labs(title = \"Proportion du CO2 émis en 2015\")\n\n# Ajouter la légende\nannotate_figure(plot1, right = text_grob(string_region, face = \"italic\", size = 9,\n just = \"left\", x = 0.05)) # position du texte)\n\n```\n\nSi à la place de la géométrie `geom_bar`, vous utilisez `geom_rect`, vous pouvez convertir votre graphique en tarte en graphique en anneau (ou en beigne, pour les personnes à la dent sucrée) : \n\n```{r}\n#| label: fig-fig347\n#| fig-align: center\n#| fig-cap: Graphique en anneau\n#| out-width: \"65%\"\n# Calculer la limite inférieure et supérieure du beigne\ndf$ymax <- cumsum(df$prop)\ndf$ymin <- c(0, head(df$ymax, n=-1))\n\n# Construire le graphique\nplot1 <- ggplot(df, aes(ymax = ymax, ymin = ymin, \n xmax = 4, xmin = 3,\n y = prop, fill = code)) +\n geom_rect(stat = \"identity\", color = \"white\") +\n coord_polar(\"y\", start=0) +\n theme_void() + \n theme(legend.position = \"none\") +\n geom_text(aes(x = 3.5, y = ypos, label = code), color = \"white\", size=3) +\n scale_fill_grey()+\n xlim(c(2,4))+\n labs(title = \"Proportion du CO2 émis en 2015\")\n\n# Ajouter la légende\nannotate_figure(plot1, right = text_grob(string_region, face = \"italic\", size = 8,\n just = \"left\", x = 0.05)) # position du texte)\n\n```\n\n## Graphiques spéciaux {#sec-033}\n\nDans cette dernière section, nous abordons des graphiques plus rarement utilisés. Ils sont toutefois très utiles dans certains contextes du fait de leur capacité à synthétiser des informations complexes.\n\n### Graphique en radar {#sec-0331}\n\nLes graphiques en radar (ou en toile d'araignée) sont utilisés pour comparer une série de variables continues pour plusieurs observations ou groupes d'observations. Chaque variable est associée à un axe et chaque observation est représentée avec un polygone. Prenons l'exemple de données relatives aux logements par secteur de recensement dans la région métropolitaine de Montréal en 2016. Nous pourrions souhaiter comparer la moyenne des pourcentages des différents types de logements pour les régions des Laurentides, de la Montérégie, de Laval, de Longueuil et de Montréal. Malheureusement, `ggplot2` ne permet pas de dessiner des graphiques en radar satisfaisants, nous devons donc utiliser le *package* `fmsb`.\n\n```{r}\n#| label: fig-fig348\n#| fig-align: center\n#| fig-cap: Graphique en anneau\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\nlibrary(fmsb)\n\ndata <- read.csv('data/bivariee/sr_rmr_mtl_2016.csv', header = TRUE, encoding = 'UTF-8')\n\n# Agréger les données au niveau des régions en calculant la moyenne des pourcentages\nvariables <- c(\"MaisonIndi\" , \"App5Plus\" , \"MaisRangee\" , \"AppDuplex\" , \"Proprio\" , \"Locataire\")\n\ndata_region <- data[c(\"Region\", variables)] %>% \n group_by(Region) %>%\n summarise_all(.funs = list(mean))\n\n# Gérer le nom des colonnes pour ajuster les données aux besoins de \n# la fonction radachart\nnew_names <- c(\"Region\", paste(variables,\"_mean\", sep = \"\"))\nnames(data_region) <- new_names\ndata_region <- data.frame(data_region)\nrownames(data_region) <- data_region$Region\ndata_region$Region <- NULL\n\n# Ajouter deux lignes aux données avec les valeurs maximales et minimales \n# de chaque colonne. Ces informations aideront la fonction radachart à\n# dessiner chacun des axes du radar\ndata_chart <- rbind(apply(data_region, MARGIN = 2, FUN = max),\n apply(data_region, MARGIN = 2, FUN = min),\n data_region\n )\n\n# Choisir les couleurs pour l'intérieur des polygones (avec transparence)\ncouleurs <- c(\n rgb(0.94, 0.28, 0.44, 0.25),\n rgb(1.00, 0.82, 0.40, 0.25),\n rgb(0.02, 0.84, 0.63, 0.25),\n rgb(0.07, 0.54, 0.70, 0.25),\n rgb(0.03, 0.23, 0.30, 0.25)\n)\n\n# Choisir les couleurs pour l'intérieur des polygones (sans transparence)\ncouleurs_contour <- c(\n rgb(0.94, 0.28, 0.44),\n rgb(1.00, 0.82, 0.40),\n rgb(0.02, 0.84, 0.63),\n rgb(0.07, 0.54, 0.70),\n rgb(0.03, 0.23, 0.30)\n)\n\n# Dessiner du graphique\nradarchart(data_chart,\n title = \"Comparaison des types de logements dans la RMR\",\n pcol = couleurs_contour, pfcol = couleurs,\n plwd = 2, plty = 1,\n cglcol = \"grey\", cglty = 1, axislabcol=\"grey\", cglwd=0.8,\n vlcex = 0.8,\n vlabels = c(\"maison individuelle\", \"immeuble d'appartements\",\n \"maison \\nen rangée\", \"duplex\",\n \"propriétaire\", \"locataire\")\n )\n\n# Ajouter une légende\nlegend(x = 1.3, y = 1, legend = rownames(data_chart[-c(1,2),]), bty = \"n\", \n pch=20 , col=couleurs , text.col = \"black\", cex = 0.9, pt.cex = 1.5)\n```\n\nÀ la lecture du graphique, nous constatons rapidement que l'île de Montréal a une situation très différente des trois autres régions. Laval se distingue également avec une part importante de logements dans des immeubles d'appartements. Ce type de graphique a pour objectif d'orienter le regard sur de potentielles différences dans un contexte multidimensionnel, mais il présente quelques inconvénients : \n\n* Les échelles de chaque axe sont différentes. Il est donc essentiel de se rapporter aux valeurs exactes pour estimer si les écarts sont importants en termes absolus.\n\n* La superposition de plusieurs polygones peut rendre la lecture difficile. Une solution envisageable est de réaliser un graphique par polygone, mais cela prend beaucoup de place dans un document.\n\n* L'utilisation de polygones donne parfois de fausses impressions d'écarts. Dans le précédent graphique, l'œil est attiré en bas à gauche par le polygone de Montréal qui est très différent des autres. Cependant, les écarts sur l'axe *maison en rangée* sont relativement petits comparativement à l'axe *locataire* situé à l'opposé.\n\n### Diagramme d'accord {#sec-0332}\n\nLes diagrammes d'accord (*chord diagram* en anglais) sont utilisés pour représenter des échanges ou des connexions entre des entités. Il peut s'agir par exemple de marchandises importées / exportées entre pays, des messages envoyés entre personnes via un réseau social, de flux de population, etc. Reprenons nos données de l'*Enquête origine-destination 2017 - Région Québec-Lévis* pour illustrer le tout. Nous utilisons le *package* `chorddiag`, très facile d'utilisation et produisant des graphiques interactifs, pour faciliter grandement la lecture de ce type de graphique. Cependant, ce *package* ne fait pas partie du répertoire CRAN, nous devons l'installer directement depuis *github* avec la fonction `devtools::install_github`.\n\n```{r}\n#| eval: false\ndevtools::install_github('mattflor/chorddiag')\n```\n\n```{r}\n#| label: fig-fig349\n#| fig-align: center\n#| fig-cap: Diagramme d'accord\n#| message: false\n#| warning: false\n#| out-width: \"100%\"\nlibrary(chorddiag)\n\n# Chargement des données\nmatriceOD <- read.csv('data/graphique/Quebec_2017_OD_MJ.csv',\n header = FALSE, sep = ';') # fichier csv sans entête\n\n# Transformation du DataFrame en matrice\nmatriceOD <- as.matrix(matriceOD)\ncodes <- c('A','B','C','D','E','F','G','H','I','J','K','X')\nsecteurs <- c('Arr. de Beauport',\n 'Arr. de Charlesbourg',\n 'Arr. des Rivières',\n 'Arr. de la Cité-Limoilou',\n 'Arr. de la Haute-St-Charles',\n 'Arr. de Sainte-Foy-Sillery-Cap-Rouge',\n 'Arr.de Desjardins',\n 'Arr. des Chutes–de-la-Chaudière-Est',\n 'Arr. Les Chutes de la-Chaudière-Ouest',\n 'Ceinture Nord',\n 'Ceinture Sud',\n 'Hors Territoire')\n\n# Ajout de noms aux colonnes et aux lignes de la matrice\nrownames(matriceOD) <- secteurs\ncolnames(matriceOD) <- secteurs\n\n# Nous supprimons les trois secteurs Ceinture Nord, Sud et Hors territoire \n# qui comprennent de toute façon peu de déplacements\nmat <- matriceOD[1:8, 1:8]\n\n# Choix aléatoire de couleurs pour les lignes\n# col <- sample(colors(), nrow(mat), replace = FALSE)\n\n# Choix de couleurs \ncol <- c(\"#a491d3\", \"#818aa3\", \"#C5DCA0\", \"#F5F2B8\",\n \"#F9DAD0\", \"#F45B69\", \"#22181C\", \"#5A0001\")\n\n# Réalisation du graphique : sortie HTLM\nif(knitr::is_html_output()){\n chorddiag(mat, groupColors = col, showTicks = FALSE,\n type = 'bipartite', chordedgeColor = 'white',\n groupnameFontsize = 12, groupnamePadding = 5)\n}\n```\nLe graphique permet de remarquer que la plupart des flux s’effectuent au sein d’un même secteur. La majorité des déplacements se font au sein du secteur Sainte-Foy (segment rouge central). Nous pouvons cependant constater que les secteurs des Rivières, de la Cité-Limoilou et de la Haute-Saint-Charles attirent une plus grande quantité et diversité de flux. Si vous lisez ce livre dans un navigateur web (et pas au format *pdf*), le graphique est interactif! En plaçant votre souris sur un lien, vous verrez s'afficher le nombre de déplacements qu'il représente.\n\n### Nuage de mots {#sec-0333}\n\nUn nuage de mots est un graphique utilisé en analyse de texte pour représenter les mots les plus importants d'un document. Mesurer l'importance des termes dans un document est une discipline à part entière (*Natural Language Processing*). Nous proposons un simple exemple ici avec la méthode *TextRank* (basée sur la théorie des graphes) proposée par @mihalcea2004textrank et implémentée dans le *package* `textrank`. Nous avons également besoin des *packages* `udpipe` (fournissant des dictionnaires linguistiques), `RColorBrewer` (pour sélectionner une palette de couleurs) et `wordcloud2` (pour générer le graphique). En guise d'exemple, nous avons choisi d'extraire les textes de deux schémas d'aménagement et de développement (SAD), ceux des agglomérations de Québec et de Montréal en vigueur en 2020. Il s'agit de deux documents de planification définissant les lignes directrices de l'organisation physique du territoire des municipalités régionales de comté (MRC) ou des agglomérations. Pour ces deux documents, nous nous concentrons sur le chapitre portant sur les grandes orientations d'aménagement et de développement, soit les pages 30 à 135 pour Québec et 30 à 97 pour Montréal. Pour extraire les textes des fichiers *pdf*, nous utilisons le *package* `pdftools`.\n\nNous devons donc réaliser les étapes suivantes pour produire le nuage de mots : \n\n1. Extraire les sections qui nous intéressent des fichiers *pdf*.\n2. Extraire le texte de ces sections.\n3. Retirer les caractères représentant les sauts de lignes et les sauts de paragraphes (`\\n` et `\\r`).\n4. Concaténer tout le texte en une seule longue chaîne de caractère.\n5. Utiliser un dictionnaire pour déterminer la nature des mots du texte (nom, adjectif, verbe, etc.).\n6. Utiliser l'algorithme *TextRank* pour identifier les mots clefs.\n7. Nettoyer les erreurs potentielles parmi les mots clefs.\n8. Construire le nuage de mots.\n\nNotez que toutes ces étapes de nettoyage ne seraient pas nécessaires si nous utilisions un simple fichier texte comme point de départ. Cependant, comme il est plus courant de rencontrer des fichiers *pdf*, cet exercice est donc davantage révélateur de la difficulté réelle de la réalisation d'un nuage de mots.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| eval: false\nlibrary(wordcloud2)\nlibrary(udpipe)\nlibrary(RColorBrewer)\nlibrary(pdftools)\nlibrary(textrank)\n\n# Étape 1 : extraire les sections pertinentes des fichiers pdf\nextrait_qc <- pdf_subset(\"data/graphique/SAD_quebec.pdf\", pages = c(30:135),\n output = \"data/graphique/SAD_quebec_ext.pdf\")\nextrait_mtl <- pdf_subset(\"data/graphique/SAD_montreal.pdf\", pages = c(30:97),\n output = \"data/graphique/SAD_montral_ext.pdf\")\n\n# Étape 2 : extraire le texte des fichiers pdf sous forme de vecteur de texte\nfile_qc <- pdf_text(extrait_qc)\nfile_mtl <- pdf_text(extrait_mtl)\n\n# Étape 3 : retirer les sauts de lignes et les paragraphes\nfile_qc <- gsub(\"\\r\" , \"\", x = file_qc)\nfile_qc <- gsub(\"\\n\" , \"\", x = file_qc)\n\nfile_mtl <- gsub(\"\\r\" , \"\", x = file_mtl)\nfile_mtl <- gsub(\"\\n\" , \"\", x = file_mtl)\n\n# Étape 4 : créer une seule longue chaîne de caractères\n# à partir des vecteurs de texte\ntext_qc <- paste(file_qc, collapse = \" \")\ntext_mtl <- paste(file_mtl, collapse = \" \")\n\n# charger le modèle linguistique français\nmodel <- udpipe_load_model('data/graphique/french-sequoia-ud-2.4-190531.udpipe')\n\n# pour télécharger le modèle si ce n'est pas encore fait : \n# model <- udpipe_download_model(\"french-sequoia\")\n# model <- udpipe_load_model(model)\n\n# Étape 5 : analyse de la nature des mots du texte avec le dictionnaire fr\n# Nous obtenons des DataFrames décrivant les mots des textes\nannote_qc <- udpipe_annotate(model, text_qc)\ndf_qc <- data.frame(annote_qc)\n\nannote_mtl <- udpipe_annotate(model, text_mtl)\ndf_mtl <- data.frame(annote_mtl)\n\n# Étape 6 : utilisation de la méthode TextRank\nstats_qc <- textrank_keywords(df_qc$lemma,\n relevant = df_qc$upos %in% c(\"NOUN\", \"ADJ\"), ngram_max = 2)\n\nstats_mtl <- textrank_keywords(df_mtl$lemma,\n relevant = df_mtl$upos %in% c(\"NOUN\" , \"ADJ\"), ngram_max = 2)\n\n# Étape 7 : nettoyer les coquilles dans les mots clefs \n# Note : nous faisons ici le choix de garder des mots clefs uniques (ngram == 1)\n# Il serait aussi possible de garder des associations de plusieurs mots\ndfstats_qc <- subset(stats_qc$keywords, stats_qc$keywords$ngram == 1 &\n nchar(stats_qc$keywords$keyword)>2)\ndfstats_qc$keyword <- gsub(\"d’\" , \"\", dfstats_qc$keyword, fixed = TRUE)\ndfstats_qc$keyword <- gsub(\"l’\" , \"\", dfstats_qc$keyword, fixed = TRUE)\n\ndfstats_mtl <- subset(stats_mtl$keywords, stats_mtl$keywords$ngram == 1 &\n nchar(stats_mtl$keywords$keyword)>2)\ndfstats_mtl$keyword <- gsub(\"d’\" , \"\", dfstats_mtl$keyword, fixed = TRUE)\ndfstats_mtl$keyword <- gsub(\"l’\" , \"\", dfstats_mtl$keyword, fixed = TRUE)\n\n# Étape 8 : réaliser les nuages de mots\ncouleurs <- sample(brewer.pal(12, \"Paired\")) # mise en désordre des couleurs\n\nwordcloud2(data = dfstats_mtl[c(\"keyword\", \"freq\")],\n color = couleurs, size = 0.5, shuffle = FALSE)\n\nwordcloud2(data = dfstats_qc[c(\"keyword\", \"freq\")],\n color = couleurs, size = 0.6, shuffle = FALSE)\n```\n\n![Nuage de mots pour le SAD de Montréal](images/Chap03/nuage_mtl.png){#fig-fig350 width=\"85%\" fig-align=\"center\"}\n\n![Nuage de mots pour le SAD de Québec](images/Chap03/nuage_qc.png){#fig-fig351 width=\"85%\" fig-align=\"center\"}\n\nNotez qu'à chaque génération du nuage de mots, vous obtiendrez une disposition différente. N'hésitez pas à en essayer plusieurs jusqu'à ce que vous trouviez celle qui vous semble optimale.\n\n### Carte proportionnelle {#sec-0334}\n\nUne carte proportionnelle ou carte à cases (*treemap* en anglais) est un graphique permettant de représenter une quantité partagée entre plusieurs observations structurées dans une hiérarchie de groupe. Le jeu de données portant sur les émissions de CO~2~ se prête tout à fait à une représentation par *treemap*. La variable de quantité est bien sûr les émissions de CO~2~ par pays; ces pays sont regroupés dans un premier ensemble de régions (découpage en 23 régions), qui elles-mêmes sont regroupées dans des régions plus larges (découpage en sept régions). Pour construire un *treemap*, nous allons utilisons le *package* `treemap`.\n\n```{r}\n#| label: fig-fig352\n#| fig-align: center\n#| fig-cap: Treemap\n#| message: false\n#| warning: false\n#| out-width: \"90%\"\n\nlibrary(treemap)\nlibrary(RColorBrewer)\n\n# extraire les données de CO2 en 2015\ndata_co2_2015 <- subset(data_co2, data_co2$year == \"2015\" & ! is.na(data_co2$region7))\n\n# construire le treemap\n\ntreemap(data_co2_2015, index = c(\"region7\" , \"region23\"),\n vSize = \"CO2_kt\", type = \"index\",\n title = \"CO2 rejetés par pays en 2015\",\n fontsize.labels=c(12,8), # taille des étiquettes \n fontcolor.labels=c(\"white\" , \"black\"), # couleur des étiquettes\n fontface.labels=c(2,1), # style des polices\n bg.labels = 0, # arrière-plan des étiquettes\n align.labels=list(\n c(\"center\", \"center\"), \n c(\"right\", \"bottom\")\n ), # localisation des étiquettes dans les boîtes\n overlap.labels=0.5, # tolérance de superposition\n inflate.labels = FALSE, # agrandir la taille des étiquettes ou non\n palette = brewer.pal(7,'Paired')\n)\n\n```\n\n## Cartes {#sec-034}\n\nToute comme un graphique, une carte est aussi une illustration visuelle. Avec la généralisation des données géographiques, il peut être utile de savoir représenter ce type de données. Si R n'est pas un logiciel de cartographie, il est possible de réaliser des cartes assez facilement, directement avec `ggplot2`. Nous avons cependant une préférence pour le *package* `tmap`, qui propose de nombreuses fonctionnalités. Pour tracer des cartes, `tmap` et `ggplot2` ont besoin d'utiliser un format de données comprenant la géométrie (polygones, lignes ou points), la localisation et le système de projection des entités spatiales étudiées. Le format de fichier le plus courant pour ce type de données est le *shapefile* (*.shp*), mais vous pourrez parfois croiser des fichiers *geojson* (*.js*), ou encore *geopackages* (*.gpkg*). Pour lire ces fichiers, il est possible d'utiliser la fonction `readOGR` du *package* `rgdal`, ou la fonction `st_read` du *package* `sf`. Notez ici que ces deux fonctions ne produisent pas de *DataFrame*, mais respectivement un *SpatialDataFrame* et un objet `sf` (*spatial feature collection*). Sans entrer dans les détails, sachez que deux *packages* permettent de manipuler des objets spatiaux dans R : le traditionnel `sp` (avec les *SpatialDataFrames*) et le plus récent `sf` (avec les *spatial feature collections*). Il est assez facile de convertir un objet de `sp` vers `sf` (et inversement) et cette opération est souvent nécessaire, car de nombreux *packages* dédiés à l'analyse spatiale utilisent l'un ou l'autre des formats. Dans le cas de `tmap`, des objets `sp` et `sf` peuvent être utilisés sans distinction. En revanche, pour cartographier directement avec `ggplot2`, il est plus facile d'utiliser un objet de type `sf`. Toutefois, nous vous recommandons fortement d'utiliser le *package* `sf`, puisque `sp` (et son format *SpatialDataFrame*) est progressivement délaissé dans R.\n\nUne carte thématique permet de représenter la répartition spatiale de variables qualitatives ou quantitatives. Nous la distinguons des cartes topographiques, dont l'objectif est de représenter la localisation d'objets spécifiques (route, habitation, rivière, lac, etc.). La première est relativement facile à construire dans R, car elle se limite à quelques symboles relativement simples. Pour la seconde, nous préférons généralement utiliser un logiciel comme [QGIS](https://qgis.org/en/site/){target=\"_blank\"}.\n\nCréons une carte thématique à partir des données de densité de végétation sur l'île de Montréal avec les *packages* `ggplot2` puis `tmap`.\n\nAvec `ggplot2`, nous avons aussi besoin des *packages* `classInt` pour calculer les intervalles des classes et `ggsn` pour afficher une échelle.\n\n```{r}\n#| label: fig-fig353\n#| fig-align: center\n#| fig-cap: Carte thématique avec ggplot2\n#| message: false\n#| warning: false\n#| out-width: \"85%\"\n\nlibrary(sf)\nlibrary(classInt)\nlibrary(ggspatial)\n\n# Chargement des données\nspatialdf <- st_read(\"data/bivariee/IlotsVeg2006.shp\")\n\n# Création d'une discrétisation en 7 classes égales\nvalues <- c(max(spatialdf$ArbPct)+0.01, spatialdf$ArbPct)\n\nquant <- classIntervals(values, n = 7,\n style = \"quantile\",\n intervalClosure = 'right')\n\nspatialdf$class_col <- cut(spatialdf$ArbPct, breaks = quant$brks, right = FALSE)\n\n# Cartographie avec ggplot2\nggplot(data = spatialdf) + \n geom_sf(aes(fill = class_col), color = rgb(0,0,0,0))+\n scale_fill_brewer(palette = \"Greens\")+\n labs(title = \"Végétation dans les îlos de recensement\",\n 'fill' = 'Densité de la canopée (%)')+\n theme(axis.line=element_blank(), axis.text.x = element_blank(),\n axis.text.y = element_blank(), axis.ticks=element_blank(),\n axis.title.x = element_blank(), axis.title.y = element_blank(),\n panel.background=element_blank(),\n panel.border=element_blank(), panel.grid.major=element_blank(),\n panel.grid.minor=element_blank(), plot.background=element_blank(),\n legend.key.size = unit(0.5, \"cm\"))+\n annotation_scale()\n```\n\nIl est possible d'arriver à un résultat similaire avec `tmap` avec moins de code! \n\n```{r}\n#| label: fig-fig354\n#| fig-align: center\n#| fig-cap: Carte thématique avec tmap\n#| message: false\n#| warning: false\n#| out-width: \"85%\"\n\nlibrary(tmap)\n\ncolors <- brewer.pal(7,\"Greens\")\ntm_shape(spatialdf) +\n tm_polygons(\"ArbPct\", palette = colors, border.alpha = 0,\n n = 7, style = 'quantile',\n title = \"Densité de la canopée (%)\")+\n tm_scale_bar(breaks = c(0,5,10)) + \n tm_layout(title = \"Végétation dans les îlos de recensement\",\n attr.outside = TRUE, frame = FALSE)\n```\n\nLes graphiques créés par `tmap` ne peuvent malheureusement pas être combinés avec la fonction `ggarrange`, mais `tmap` dispose de sa propre fonction `tmap_arrange` si vous souhaitez combiner plusieurs cartes.\n\n```{r}\n#| label: fig-fig355\n#| fig-align: center\n#| fig-cap: Combiner des cartes avec tmap\n#| message: false\n#| warning: false\n#| out-width: \"85%\"\n\nlibrary(tmap)\ncolors <- brewer.pal(7,\"Greens\")\ncolors2 <- brewer.pal(7,\"Reds\")\n\ncarte1 <- tm_shape(spatialdf) +\n tm_polygons(\"ArbPct\", palette = colors, border.alpha = 0,\n n = 7, \n\t\t\tstyle = \"quantile\",\n title = \"Densité de la canopée (%)\") +\n tm_scale_bar(breaks = c(0,5,10)) + \n tm_layout(attr.outside = TRUE, frame = FALSE)\n\ncarte2 <- tm_shape(spatialdf) +\n tm_polygons(\"LogDens\", palette = colors2, border.alpha = 0,\n n = 7, \n\t\t\tstyle = \"quantile\",\n title = \"Densité de logement\") + \n tm_scale_bar(breaks = c(0,5,10)) + \n tm_layout(attr.outside = TRUE, frame = FALSE)\n\ntmap_arrange(carte1, carte2, ncol = 2)\n```\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n\n**Construction de cartes : aller plus loin avec `tmap`...**\n:::\n\n::: bloc_aller_loin-body\nPour explorer les multitudes possibilités du *package* `tmap`, nous vous recommandons les ressources suivantes :\n\n- [La section intitulée *Cartographie avec R*](https://serieboldr.github.io/MethodesAnalyseSpatiale/01-ManipulationDonneesSpatiales.html#sec-016) du manuel [*Méthodes d’analyse spatiale : un grand bol d’R*](https://serieboldr.github.io/MethodesAnalyseSpatiale/).\n\n- L'excellente vignette intitulée [*`tmap`: get started!*](https://cran.r-project.org/web/packages/tmap/vignettes/tmap-getstarted.html)\n\n- [*Visualizing Spatial Data in R with tmap*](http://www.wvview.org/os_sa/10_Maps_with_tmap.html#visualizing-spatial-data-in-r-with-tmap).\n\n- [*Making Maps with R*](https://bookdown.org/nicohahn/making_maps_with_r5/docs/introduction.html).\n\n- Le chapitre [*Making maps with R*](https://geocompr.robinlovelace.net/adv-map.html) du livre [*Geocomputation with R*](https://geocompr.robinlovelace.net/index.html).\n:::\n:::\n\n\n\n## Exportation des graphiques {#sec-035}\n\nTous les graphiques que nous avons construits dans ce chapitre peuvent être exportés assez facilement. Dans RStudio, vous pouvez directement cliquer sur le bouton *Export* (@fig-fig356) pour enregistrer votre figure au format image ou au format *pdf* (vectoriel). Notez qu'avec la seconde option, vous pourrez retoucher votre graphique avec un logiciel externe comme *Inkscape* ou *Illustrator*.\n\n![Exporter un graphique dans RStudio](images/Chap03/export.jpg){#fig-fig356 width=\"40%\" fig-align=\"center\"}\n\nLorsque vous créez un graphique avec `ggplot2`, il est aussi possible de l'exporter avec la fonction `ggsave`. Cette fonctionnalité est très pratique lorsque vous souhaitez automatiser la production de graphiques et ne pas avoir à tous les exporter à la main.\n\n```{r}\n#| warning: false\n#| eval: false\ndata(iris)\n\nplot1 <- ggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris)\n\nggsave(filename = 'graphique.pdf',\n path = 'mon/dossier',\n plot = plot1,\n width = 10, height = 10, units = \"cm\")\n```\nPour les graphiques n'étant pas réalisés avec `ggplot2`, la solution de remplacement à la fonction `ggsave` est l'ensemble de fonctions `png`, `bmp`, `jpeg`, `tiff` et `pdf`, qui permettent d'exporter n'importe quel graphique dans ces différents formats. Le processus comprend trois étapes : \n\n1. Ouvrir une connexion vers le fichier dans lequel le graphique sera exporté avec une des fonctions `png`, `bmp`, `jpeg`, `tiff` et `pdf`.\n\n2. Réaliser son graphique comme si nous souhaitions l'afficher dans RSudio. Il n'apparaîtra cependant pas, car il sera écrit dans le fichier en question à la place.\n\n3. Fermer la connexion au fichier avec la fonction `dev.off` pour définitivement enregistrer le graphique.\n\n```{r}\n#| warning: false\n#| eval: false\ndata(iris)\n\n# 1. Ouvrir la connexion\npng(filename = 'mon/dossier/graphique.png')\n\n# 2. Afficher le graphique\nggplot() +\n geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris)\n\n# 3. fermer la connexion\ndev.off()\n\n```\n\n## Conclusion sur les graphiques {#sec-036}\n\nVous avez pu constater que les capacités de représentation graphique de R sont vastes et pourtant nous n'avons qu'observé la partie émergée de l'iceberg dans ce chapitre. Il est également possible de réaliser une visualisation en 3D dans R (`plot3D`, `rgl`), d'animer des graphiques pour en faire des *GIF* ou des vidéos (`gganimate`), de rendre des graphiques interactifs, ou même de construire des plateformes de visualisation de données disponibles en ligne (`shiny`). Vous continuerez à découvrir de nouvelles formes de représentations au fur et à mesure de votre pratique, en apprenant de nouvelles méthodes nécessitant des visualisations spécifiques.\n\nVoici également deux références très utiles qui nous ont notamment aidé à construire ce chapitre : \n\n* [The R Graph Gallery](https://www.r-graph-gallery.com/){target=\"_blank\"}, probablement **LE** site web proposant le plus de matériel sur la réalisation des graphiques dans R.\n* [Data to viz](https://www.data-to-viz.com/){target=\"_blank\"}, si vous ne savez pas quel graphique pourrait le mieux correspondre à vos données, Data to viz est là pour vous aider. Vous y trouverez un arbre de décision pour vous indiquer quel graphique utiliser dans quelle situation, ainsi que de nombreux conseils sur la visualisation de données.\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"03-magiedesgraphiques.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/04-bivarieeQuantiQuanti.qmd.json b/.quarto/idx/04-bivarieeQuantiQuanti.qmd.json new file mode 100644 index 0000000..1d11002 --- /dev/null +++ b/.quarto/idx/04-bivarieeQuantiQuanti.qmd.json @@ -0,0 +1 @@ +{"title":"Relation linéaire entre deux variables quantitatives","markdown":{"headingText":"Relation linéaire entre deux variables quantitatives","headingAttr":{"id":"sec-chap04","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans le cadre de ce chapitre, nous présentons les trois principales méthodes permettant d'explorer la relation linéaire entre deux variables quantitatives, soit la covariance, la corrélation et la régression linéaire simple.\n\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes quantiles-quantiles.\n* Pour manipuler des données : \n - `dplyr` notamment pour les fonctions `group_by`, `summarize` et les pipes %>%.\n* Pour les corrélations : \n - `boot` pour réaliser des corrélations avec *bootstrap*.\n - `correlation`, de l'ensemble de packages `easy_stats`, offrant une large panoplie de mesures de corrélation.\n - `corrplot` pour créer des graphiques de matrices de corrélation.\n - `Hmisc` pour calculer des corrélations de Pearson et Spearman.\n - `ppcor` pour calculer des corrélations partielles.\n - `psych` pour obtenir une matrice de corrélation (Pearson, Spearman et Kendall), les intervalles de confiance et les valeurs de *p*.\n - `stargazer` pour créer de beaux tableaux d’une matrice de corrélation en HTML, en LaTeX ou en ASCII.\n* Autres *packages* :\n - `foreign` pour importer des fichiers externes.\n - `MASS` pour générer des échantillons normalement distribués.\n - `stargazer` pour imprimer des tableaux.\n:::\n:::\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Deux variables continues varient-elles dans le même sens ou bien en sens contraire?**\n:::\n::: bloc_objectif-body\nRépondre à cette question est une démarche exploratoire classique en sciences sociales puisque les données socioéconomiques sont souvent associées linéairement. En d'autres termes, lorsque l'une des deux variables tant à augmenter, l'autre augmente également ou diminue systématiquement.\n\nEn études urbaines, nous pourrions vouloir vérifier si certaines variables socioéconomiques sont associées positivement ou négativement à des variables environnementales jugées positives (comme la couverture végétale ou des mesures d’accessibilité spatiale aux parcs) ou négatives (pollutions atmosphériques et sonores). \n\nPar exemple, au niveau des secteurs de recensement d’une ville canadienne, nous pourrions vouloir vérifier si le revenu médian des ménages et le coût moyen du loyer varient dans le même sens que la couverture végétale; ou encore s'ils varient en sens inverse des niveaux moyens de dioxyde d’azote ou de bruit routier.\n\nPour évaluer la linéarité entre deux variables continues, deux statistiques descriptives sont utilisées : la **covariance** ([section @sec-042]) et la **corrélation** ([section @sec-043]).\n:::\n:::\n\n\n## Bref retour sur le postulat de la relation linéaire {#sec-041}\n\nVérifier le postulat de la linéarité consiste à évaluer si deux variables quantitatives varient dans le même sens ou bien en sens contraire. Toutefois, la relation entre deux variables quantitatives n’est pas forcément linéaire. En guise d'illustration, la @fig-fig2 permet de distinguer quatre types de relations :\n\n* Le cas **a** illustre une relation linéaire positive entre les deux variables puisqu’elles vont dans le même sens. Autrement dit, quand les valeurs de *X* augmentent, celles de *Y* augmentent aussi. En guise d'exemple, pour les secteurs de recensement d'une métropole donnée, il est fort probable que le coût moyen du loyer soit associé positivement avec le revenu médian des ménages. Graphiquement parlant, il est clair qu'une droite dans ce nuage de points résumerait efficacement la relation entre ces deux variables.\n\n* Le cas **b** illustre une relation linéaire négative entre les deux variables puisqu’elles vont en sens inverse. Autrement dit, quand les valeurs de *X* augmentent, celles de *Y* diminuent, et inversement. En guise d'exemple, pour les secteurs de recensement d'une métropole donnée, il est fort probable que le revenu médian des ménages soit associé négativement avec le taux de chômage. De nouveau, une droite résumerait efficacement cette relation.\n\n* Pour le cas **c**, il y a une relation entre les deux variables, mais qui n’est pas linéaire. Le nuage de points entre les deux variables prend d’ailleurs une forme parabolique qui traduit une relation curvilinéaire. Concrètement, nous observons une relation positive jusqu'à un certain seuil, puis une relation négative. \n \n* Pour le cas **d**, la relation entre les deux variables est aussi curvilinéaire; d'abord négative, puis positive.\n\n\n![Relations linéaires et curvilinéaires entre deux variables continues](images/Chap04/LineaireCurvilineaire.jpg){#fig-fig2 width=\"85%\" fig-align=\"center\"}\n\nPrenons un exemple concret pour illustrer le cas **c**. Dans une étude portant sur l'équité environnementale et la végétation à Montréal, Pham *et al.* [-@PhamApparicioSeguin2012] ont montré qu'il existe une relation curvilinéaire entre l'âge médian des bâtiments résidentiels (axe des abscisses) et les couvertures végétales (axes des ordonnées) :\n\n* La couverture de la végétation totale et celle des arbres augmentent quand l'âge médian des bâtiments croît jusqu'à atteindre un pic autour de 60 ans (autour de 1950). Nous pouvons supposer que les secteurs récemment construits, surtout ceux dans les banlieues, présentent des niveaux de végétation plus faibles. Au fur et à mesure que le quartier vieillit, les arbres plantés lors du développement résidentiel deviennent matures — canopée plus importante –, d'où l'augmentation des valeurs de la couverture végétale totale et de celle des arbres.\n\n* Par contre, dans les secteurs développés avant les années 1950, la densité du bâti est plus forte, laissant ainsi moins de place pour la végétation, ce qui explique une diminution des variables relatives à la couverture végétale (@fig-fig3).\n\n\n![Exemples de relations curvilinéaires](images/Chap04/ExRelCurvi.jpg){#fig-fig3 width=\"65%\" fig-align=\"center\"}\n\nDans les sous-sections suivantes, nous décrivons deux statistiques descriptives et exploratoires – la covariance ([section @sec-042]) et la corrélation ([section @sec-043]) – utilisées pour évaluer la **relation linéaire** entre deux variables continues (cas **a** et **b** à la @fig-fig2). Ces deux mesures permettent de mesurer le degré d'association entre deux variables, sans que l'une soit la variable dépendante (variable à expliquer) et l'autre, la variable indépendante (variable explicative). Puis, nous décrivons la régression linéaire simple ([section @sec-044]) qui permet justement de prédire une variable dépendante (_Y_) à partir d'une variable indépendante (_X_).\n\n## Covariance {#sec-042}\n\n### Formulation {#sec-0421} \n\nLa covariance (@eq-cov), écrite $cov(x,y)$, est égale à la moyenne du produit des écarts des valeurs des deux variables par rapport à leurs moyennes respectives :\n\n\n$$\ncov(x,y) = \\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})(y_{i}-\\bar{y})}{n-1} = \\frac{covariation}{n-1}\n$$ {#eq-cov}\n\navec $n$ étant le nombre d’observations; $\\bar{x}$ et $\\bar{y}$ (prononcez x et y barre) étant les moyennes respectives des variables *X* et *Y*.\n\n### Interprétation {#sec-0422} \n\nLe numérateur de l'@eq-cov représente la covariation, soit la somme du produit des déviations des valeurs $x_{i}$ et $y_{i}$ par rapport à leurs moyennes respectives ($\\bar{x}$ et $\\bar{y}$). La covariance est donc la covariation divisée par le nombre d’observations, soit la moyenne de la covariation. Sa valeur peut être positive ou négative : \n\n* Positive quand les deux variables varient dans le même sens, c'est-à-dire lorsque les valeurs de la variable _X_ s'éloignent de la moyenne, les valeurs de _Y_ s'éloignent aussi dans le même sens; et elle est négative pour une situation inverse. \n\n* Quand la covariance est égale à 0, il n’y a pas de relation entre les variables _X_ et _Y_. Plus sa valeur absolue est élevée, plus la relation entre les deux variables *X* et *Y* est importante. \n \nAinsi, la covariance correspond à un centrage des variables, c’est-à-dire à soustraire à chaque valeur de la variable sa moyenne correspondante. L'inconvénient majeur de l'utilisation de la covariance est qu'elle est tributaire des unités de mesure des deux variables. Par exemple, si nous calculons la covariance entre le pourcentage de personnes à faible revenu et la densité de population (habitants au km^2^) au niveau des secteurs de recensement de la région métropolitaine de Montréal, nous obtenons une valeur de covariance de 33 625. En revanche, si la densité de population est exprimée en milliers d'habitants au km^2^, la valeur de la covariance sera de 33,625, alors que la relation linéaire entre les deux variables reste la même comme illustré à la @fig-covariance. Pour remédier à ce problème, nous privilégions l'utilisation du coefficient de corrélation.\n\n```{r}\n#| label: fig-covariance\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Covariance et unités de mesure\n#| out-width: \"75%\"\nlibrary(\"ggplot2\")\nlibrary(\"ggpubr\")\n\ntofr <- function(float){\n return(gsub(\".\" , \",\", as.character(float), fixed = TRUE, useBytes = TRUE))\n}\n\ndf <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\ncov1 <- round(cov(df$FaibleRev, df$HabKm2),0)\ncor1 <- round(cor(df$FaibleRev, df$HabKm2),3)\ncov2 <- round(cov(df$FaibleRev, df$Hab1000Km2),3)\ncor2 <- round(cor(df$FaibleRev, df$Hab1000Km2),3)\n\nplot1 <- ggplot(data = df, mapping = aes(x = FaibleRev, y = HabKm2))+\n geom_point(colour = \"red\")+\n labs(title=paste0(\"covariance = 33 625\"), \n subtitle = paste0(\"corrélation = \", tofr(cor1)),\n caption = \"Les traits pointillés indiquent les moyennes.\")+\n xlab(\"Personnes à faible revenu (%)\")+\n ylab(expression(\"Densité de population : habitants au\"~km^{2}))+\n geom_vline(xintercept = mean(df$FaibleRev), colour = \"black\", linetype = \"dashed\", linewidth = .5) +\n geom_hline(yintercept = mean(df$HabKm2), colour = \"black\", linetype = \"dashed\", linewidth = .5) +\n stat_smooth(method = \"lm\", se = FALSE)\nplot2 <- ggplot(data = df, mapping = aes(x = FaibleRev, y = Hab1000Km2))+\n geom_point(colour = \"red\")+\n labs(title=paste0(\"covariance =\", tofr(cov2)), \n subtitle = paste0(\"corrélation = \", tofr(cor2)),\n caption = \"Les traits pointillés indiquent les moyennes.\")+\n xlab(\"Personnes à faible revenu (%)\")+\n ylab(expression(\"Densité de population : 1000 habitants au\"~km^{2}))+\n geom_vline(xintercept = mean(df$FaibleRev), colour = \"black\", linetype = \"dashed\", linewidth = .5) +\n geom_hline(yintercept = mean(df$Hab1000Km2), colour = \"black\", linetype = \"dashed\", linewidth = .5) +\n stat_smooth(method = \"lm\", se = FALSE)\nggarrange(plot1, plot2, ncol = 2, nrow = 1)\n```\n\n\n## Corrélation {#sec-043}\n\n### Formulation {#sec-0431} \nLe coefficient de corrélation de Pearson ($r$) est égal à la covariance (numérateur) divisée par le produit des écarts-types des deux variables *X* et *Y* (dénominateur). Il représente une standardisation de la covariance. Autrement dit, le coefficient de corrélation repose sur un centrage (moyenne = 0) et une réduction (variance = 1) des deux variables, c’est-à-dire qu'il faut soustraire de chaque valeur sa moyenne correspondante et la diviser par son écart-type. Il correspond ainsi à la moyenne du produit des deux variables centrées réduites. Il s'écrit alors :\n\n$$\nr_{xy} = \\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})(y_{i}-\\bar{y})}{(n-1)\\sqrt{\\sum_{i=1}^n(x_i - \\bar{x})^2(y_i - \\bar{y})^2}}=\\sum_{i=1}^n\\frac{Zx_iZy_i}{n-1}\n$$ {#eq-cor}\n\navec $n$ étant le nombre d’observations; $\\bar{x}$ et $\\bar{y}$ étant les moyennes respectives des variables *X* et *Y*.\n\nLa syntaxe ci-dessous démontre que le coefficient de corrélation de Pearson est bien égal à la moyenne du produit de deux variables centrées réduites.\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(\"MASS\")\nN <- 1000 # nombre d'observations\nmoy_x <- 50 # moyenne de x\nmoy_y <- 40 # moyenne de y\nsd_x <- 10 # écart-type de x\nsd_y <- 8 # écart-type de y\nrxy <- .80 # corrélation entre X et Y\n## création de deux variables fictives normalement distribuées et corrélées entre elles\n# Création d'une matrice de covariance\ncov <- matrix(c(sd_x^2, rxy*sd_x*sd_y, rxy*sd_x*sd_y, sd_y^2), nrow = 2)\n# Création du tableau de données avec deux variables\ndf1 <- as.data.frame(mvrnorm(N, c(moy_x, moy_y), cov))\n# Centrage et réduction des deux variables\ndf1$zV1 <- scale(df1$V1, center = TRUE, scale = TRUE)\ndf1$zV2 <- scale(df1$V2, center = TRUE, scale = TRUE)\n# Corrélation de Pearson\ncor1 <- cor(df1$V1, df1$V2)\ncor2 <- sum(df1$zV1*df1$zV2) / (nrow(df1)-1)\ncat(\"Corrélation de Pearson = \", round(cor1,5),\n \"\\nMoyenne du produit des variables centrées réduites =\", round(cor2,5))\n```\n\n\n### Interprétation {#sec-0432} \n\nLe coefficient de corrélation $r$ varie de −1 à 1 avec :\n\n* 0 quand il n’y a pas de relation linéaire entre les variables _X_ et _Y_;\n* −1 quand il y a une relation linéaire négative parfaite;\n* 1 quand il y a une relation linéaire positive parfaite (@fig-coeffPearson). \n\n\n```{r}\n#| label: fig-coeffPearson\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Relations entre deux variables continues et coefficients de corrélation de Pearson\n#| out-width: \"75%\"\nlibrary(\"MASS\")\nlibrary(\"ggplot2\")\nlibrary(\"ggpubr\")\nN <- 1000 # nombre d'observations\nmoy_x <- 50 # moyenne de x\nmoy_y <- 40 # moyenne de y\nsd_x <- 10 # écart-type de x\nsd_y <- 8 # écart-type de y\nrxy <- c(.90,-.85,0.01) # corrélation entre X et Y\n # Matrice de covariance\ncov1 <- matrix(c(sd_x^2, rxy[1]*sd_x*sd_y, rxy[1]*sd_x*sd_y, sd_y^2), nrow = 2)\ncov2 <- matrix(c(sd_x^2, rxy[2]*sd_x*sd_y, rxy[2]*sd_x*sd_y, sd_y^2), nrow = 2) \ncov3 <- matrix(c(sd_x^2, rxy[3]*sd_x*sd_y, rxy[3]*sd_x*sd_y, sd_y^2), nrow = 2) \ndata1 <- mvrnorm(N, c(moy_x, moy_y), cov1)\ndata2 <- mvrnorm(N, c(moy_x, moy_y), cov2)\ndata3 <- mvrnorm(N, c(moy_x, moy_y), cov3)\n\ncor1 <- round(cor(data1)[1,2],3)\ncor2 <- round(cor(data2)[1,2],3)\ncor3 <- round(cor(data3)[1,2],3)\n\nplot1 <- ggplot(mapping = aes(x = data1[,1], y = data1[,2]))+\n geom_point(colour = \"red\")+\n ggtitle(\"a. Relation linéaire positive\", subtitle = paste0(\"Corrélation = \", tofr(cor1)))+\n xlab(\"Variable X\")+ylab(\"Variable Y\")+\n stat_smooth(method = \"lm\", se = FALSE)\nplot2 <- ggplot(mapping = aes(x = data2[,1], y = data2[,2]))+\n geom_point(colour = \"red\")+\n ggtitle(\"b. Relation linéaire négative\", subtitle = paste0(\"Corrélation = \", tofr(cor2)))+\n xlab(\"Variable X\")+ylab(\"Variable Y\")+\n stat_smooth(method = \"lm\", se = FALSE)\nplot3 <- ggplot(mapping = aes(x = data3[,1], y = data3[,2]))+\n geom_point(colour = \"red\")+\n ggtitle(\"c. Absence de relation linéaire\", subtitle = paste0(\"Corrélation = \", tofr(cor3)))+\n xlab(\"Variable X\")+ylab(\"Variable Y\")+\n stat_smooth(method = \"lm\", se = FALSE)\nggarrange(plot1, plot2, plot3, ncol = 2, nrow = 2)\n```\n\nConcrètement, le signe du coefficient de corrélation indique si la relation est positive ou négative et la valeur absolue du coefficient indique le degré d’association entre les deux variables. Reste à savoir comment déterminer qu’une valeur de corrélation est faible, moyenne ou forte. En sciences sociales, nous utilisons habituellement les intervalles de valeurs reportés au @tbl-tableIntervallesCorrelation. Toutefois, ces seuils sont tout à fait arbitraires. En effet, dépendamment de la discipline de recherche (sciences sociales, sciences de la santé, sciences physiques, etc.) et des variables à l’étude, l’interprétation d’une valeur de corrélation peut varier. Par exemple, en sciences sociales, une valeur de corrélation de 0,2 est considérée comme très faible alors qu’en sciences de la santé, elle pourrait être considérée comme intéressante. À l’opposé, une valeur de 0,9 en sciences physiques pourrait être considérée comme faible. Il convient alors d’utiliser ces intervalles avec précaution.\n\n```{r}\n#| label: tbl-tableIntervallesCorrelation\n#| tbl-cap: Intervalles pour l’interprétation du coefficient de corrélation habituellement utilisés en sciences sociales\n#| echo: false\n#| message: false\n#| warning: false\ndf <- data.frame(\n Correlation = c(\"Faible\" , \"Moyenne\", \"Forte\"), \n Negative = c(\"de −0,3 à 0,0\" , \"de −0,5 à −0,3\", \"de −1,0 à −0,5\"), \n Positive = c(\"de 0,0 à 0,3\" , \"de 0,3 à 0,5\", \"de 0,5 à 1,0\"))\n\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Corrélation\" , \"Négative\" , \"Positive\"),\n align= c(\"l\", \"l\", \"l\"))\n```\n\nLe coefficient de corrélation mis au carré représente le coefficient de détermination et indique la proportion de la variance de la variable _Y_ expliquée par la variable _X_ et inversement. Par exemple, un coefficient de corrélation de −0,70 signale que 49 % de la variance de la variable de _Y_ est expliquée par _X_ (@fig-coefCorrVar).\n\n```{r}\n#| label: fig-coefCorrVar\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Coefficient de corrélation et proportion de la variance expliquée\n#| out-width: \"75%\"\nlibrary(\"ggplot2\")\nR <- seq(-1, 1, by = 0.01)\nR2 <- R^2\n ggplot(mapping = aes(y = R2,x=R)) +\n geom_rect(xmin = -1, xmax = -.5, ymin =0 , ymax = 1, size = 0, fill = \"#91bfdb\")+\n geom_rect(xmin = -.5,xmax = -.3, ymin = 0, ymax = 1, size = 0, fill = \"#e0f3f8\")+ \n geom_rect(xmin = -.3, xmax = .3, ymin = 0, ymax = 1, size = 0, fill = \"#ffffbf\")+\n geom_rect(xmin = .3, xmax = .5, ymin = 0, ymax = 1, size = 0, fill = \"#fee090\")+ \n geom_rect(xmin = .5, xmax = 1, ymin = 0, ymax = 1, size = 0, fill = \"#fc8d59\")+\n geom_point() +\n ggtitle(\"Corrélation et coefficient de détermination\")+\n xlab(\"Corrélation de Pearson – R\")+\n ylab(expression(\"Coefficient de détermination –\"~ R^{2}))+\n geom_vline(xintercept = -1, colour = \"black\", linetype = \"dashed\", linewidth = .5)+\n geom_vline(xintercept = -0.5, colour = \"black\", linetype = \"dashed\", linewidth = .5)+\n geom_vline(xintercept = -0.3, colour = \"black\", linetype = \"dashed\", linewidth = .5)+\n geom_vline(xintercept = 0.0, colour = \"black\", linetype = \"dashed\", linewidth = .5)+\n geom_vline(xintercept = 0.3, colour = \"black\", linetype = \"dashed\", linewidth = .5)+\n geom_vline(xintercept = 0.5, colour = \"black\", linetype = \"dashed\", linewidth = .5)+\n geom_vline(xintercept = 1, colour = \"black\", linetype = \"dashed\", linewidth = .5) +\n \n annotate(geom = \"text\", x =-.75, y = 0.8, label = \"Forte et \\nnégative\", color = \"black\", hjust = 0.5, size = 3.5)+\n annotate(geom = \"text\", x =.75, y = 0.8, label = \"Forte et \\npositive\", color = \"black\", hjust = 0.5, size = 3.5)+\n annotate(geom = \"text\", x =-.4, y = 0.8, label = \"Modérée \\n et négative\", color = \"black\", hjust = 0.5, size = 3.5)+ \n annotate(geom = \"text\", x =.4, y = 0.8, label = \"Modérée \\n et positive\", color = \"black\", hjust = 0.5, size = 3.5)+ \n annotate(geom = \"text\", x =-.15, y = 0.8, label = \"Faible et \\n négative\", color = \"black\", hjust = 0.5, size = 3.5)+ \n annotate(geom = \"text\", x =.15, y = 0.8, label = \"Faible et \\n positive\", color = \"black\", hjust = 0.5, size = 3.5)\n```\n\n**Condition d'application.** L'utilisation du coefficient de corrélation de Pearson nécessite que les deux variables continues soient normalement distribuées et qu'elles ne comprennent pas de valeurs aberrantes ou extrêmes. D’ailleurs, plus le nombre d’observations est réduit, plus la présence de valeurs extrêmes a une répercussion importante sur le résultat du coefficient de corrélation de Pearson. En guise d’exemple, dans le nuage de points à gauche de la @fig-ValExtremes, il est possible d’identifier des valeurs extrêmes qui se démarquent nettement dans le jeu de données : six observations avec une densité de population supérieure à 20 000 habitants au km^2^ et deux observations avec un pourcentage de 65 ans et plus supérieur à 55 %. Si l'on supprime ces observations (ce qui est défendable dans ce contexte) – soit moins d'un pour cent des observations du jeu de données initial –, la valeur du coefficient de corrélation passe de −0,158 à −0,194, signalant une augmentation du degré d'association entre les deux variables.\n\n```{r}\n#| label: fig-ValExtremes\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Illustation de l’effet des valeurs extrêmes sur le coefficient de Pearson\n#| out-width: \"75%\"\nlibrary(\"ggplot2\")\nlibrary(\"ggpubr\")\nlibrary(\"moments\")\ndf1 <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\ncor1 <- cor(df1$HabKm2, df1$A65plus, method = \"pearson\")\ndf2 <- subset(df1, HabKm2 < 20000 & A65plus < 50)\ncor2 <- cor(df2$HabKm2, df2$A65plus, method = \"pearson\")\n\nplot1 <- ggplot(data = df1, mapping = aes(x = A65plus, y = HabKm2))+\n geom_point(colour = \"red\")+\n ggtitle(paste0(\"N = \", nrow(df1)), subtitle = paste0(\"Corrélation = \", tofr(round(cor1,3))))+\n xlab(\"65 ans et plus (%)\")+\n ylab(expression(\"Densité de population : 1000 habitants au\"~km^{2}))+\n stat_smooth(method = \"lm\", se = FALSE)+\n annotate(geom = \"text\", x = 60, y = 50000, label = paste0(\"Skewness = \", tofr(round(skewness(df1$HabKm2),3))), color = \"black\", hjust = 1, size = 3.5)+\n annotate(geom = \"text\", x = 60, y = 48000, label = paste0(\"Kurtosis = \", tofr(round(kurtosis(df1$HabKm2),3))), color = \"black\", hjust = 1, size = 3.5)+\n annotate(geom = \"text\", x = 60, y = 46000, label = paste0(\"Shapiro = \", tofr(round(shapiro.test(df1$HabKm2)$statistic,3))), color = \"black\", hjust = 1, size = 3.5)\nplot2 <- ggplot(data = df2, mapping = aes(x = A65plus, y = HabKm2))+\n geom_point(colour = \"red\")+\n xlim(0, 50)+\n ggtitle(paste0(\"N = \", nrow(df2)), subtitle = paste0(\"Corrélation = \", tofr(round(cor2,3))))+\n xlab(\"65 ans et plus (%)\")+\n ylab(expression(\"Densité de population : 1000 habitants au\"~km^{2}))+\n stat_smooth(method = \"lm\", se = FALSE)+\n annotate(geom = \"text\", x =50, y = 20000, label = paste0(\"Skewness = \", tofr(round(skewness(df2$HabKm2),3))), color = \"black\", hjust = 1, size = 3.5)+\n annotate(geom = \"text\", x =50, y = 19200, label = paste0(\"Kurtosis = \", tofr(round(kurtosis(df2$HabKm2),3))), color = \"black\", hjust = 1, size = 3.5)+\n annotate(geom = \"text\", x =50, y = 18400, label = paste0(\"Shapiro = \", tofr(round(shapiro.test(df2$HabKm2)$statistic,3))), color = \"black\", hjust = 1, size = 3.5)\nggarrange(plot1, plot2, ncol = 2, nrow = 1)\n```\n\n\n### Corrélations pour des variables anormalement distribuées (coefficient de Spearman, tau de Kendall) {#sec-0433} \n\nLorsque les variables sont fortement anormalement distribuées, le coefficient de corrélation de Pearson est peu adapté pour analyser leurs relations linéaires. Il est alors conseillé d'utiliser deux statistiques non paramétriques : principalement, le coefficient de corrélation de Spearman (_rho_) et secondairement, le tau ($\\tau$) de Kendall, qui varient aussi tous deux de −1 à 1. \nCalculé sur les rangs des deux variables, le **coefficient de Spearman** est le rapport entre la covariance des deux variables de rangs sur les écarts-types des variables de rangs. En d'autres termes, il représente simplement le coefficient de Pearson calculé sur les rangs des deux variables :\n\n$$\nr_{xy} = \\frac{cov(rg_{x}, rg_{y})}{\\sigma_{rg_{x}}\\sigma_{rg_{y}}}\n$$ {#eq-spearman}\n\nLa syntaxe ci-dessous démontre clairement que le coefficient de Spearman est bien le coefficient de Pearson calculé sur les rangs ([section @sec-0431]).\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\ndf <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\n# Transformation des deux variables en rangs\ndf$HabKm2_rang <- rank(df$HabKm2)\ndf$A65plus_rang <- rank(df$A65plus)\n# Coefficient de Spearman avec la fonction cor et la méthode spearman\ncat(\"Coefficient de Spearman = \", \n round(cor(df$HabKm2, df$A65plus, method = \"spearman\"),5))\n# Coefficient de Pearson sur les variables transformées en rangs\ncat(\"Coefficient de Pearson calculé sur les variables transformées en rangs = \", \n round(cor(df$HabKm2_rang, df$A65plus_rang, method = \"pearson\"),5))\n# Vérification avec l'équation\ncat(\"Covariance divisée par le produit des écarts-types sur les rangs :\",\n round(cov(df$HabKm2_rang, df$A65plus_rang) / (sd(df$HabKm2_rang)*sd(df$A65plus_rang)),5))\n```\n\nLe **tau de Kendall** est une autre mesure non paramétrique calculée comme suit :\n\n$$\n\\tau = \\frac{n_{c}-n_{d}}{\\frac{1}{2}n(n-1)}\n$$ {#eq-tau}\n\navec $n_{c}$ et $n_{d}$ qui sont respectivement les nombres de paires d'observations **c**oncordantes et **d**iscordantes; et le dénominateur étant le nombre total de paires d'observations. Des paires sont dites concordantes quand les valeurs des deux observations vont dans le même sens pour les deux variables ($x_{i}>x_{j}$ et $y_{i}>y_{j}$ ou $x_{i}x_{j}$ et $y_{i}y_{j}$). Contrairement au calcul du coefficient de Spearman, celui du tau Kendall peut être chronophage : plus le nombre d'observations est élevé, plus les temps de calcul et la mémoire utilisée sont importants. En effet, avec _n_ = 1000, le nombre de paires d'observations (${\\mbox{0,5}\\times n(n-1)}$) est de 499 500, contre près de 50 millions avec _n_ = 10 000 (49 995 000).\n\n```{r}\n#| label: fig-PearsonSpearmanKendall\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Comparaison des coefficients de Pearson, Spearman et Kendall sur deux variables anormalement distribuées\n#| out-width: \"75%\"\nlibrary(\"moments\")\nlibrary(\"ggpubr\")\ndf <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\ndf$HabKm2 <- df$HabKm2 / 1000\np <- round(cor(df$HabKm2, df$A65plus, method = \"pearson\"),3)\ns <- round(cor(df$HabKm2, df$A65plus, method = \"spearman\"),3)\nk <- round(cor(df$HabKm2, df$A65plus, method = \"kendall\"),3)\nPlot1 <- ggplot(data =df, mapping = aes(x = HabKm2))+\n geom_histogram(color = \"white\", fill = \"#B22222\", aes(y = ..density..))+\n stat_function(fun = dnorm, args = list(mean = mean(df$HabKm2), sd = sd(df$HabKm2)), color = \"blue\", linewidth = 1.2)+\n labs(title = \"Histogramme\")+\n xlab(expression(\"1000 habitants au\"~km^{2}))+\n ylab(\"Densité\")+\n annotate(geom = \"text\", x =60, y = 0.130, label = paste0(\"Skewness = \", tofr(round(skewness(df$HabKm2, na.rm = TRUE),3))), color = \"black\", hjust = 1, size = 3.5)+\n annotate(geom = \"text\", x =60, y = 0.124, label = paste0(\"Kurtosis = \", tofr(round(kurtosis(df$HabKm2, na.rm = TRUE),3))), color = \"black\", hjust = 1, size = 3.5)+\n annotate(geom = \"text\", x =60, y = 0.118, label = paste0(\"Shapiro = \", tofr(round(shapiro.test(df$HabKm2)$statistic,3))), color = \"black\", hjust = 1, size = 3.5)\nPlot2 <- ggplot(data = df, mapping = aes(x = A65plus))+\n geom_histogram(color = \"white\", fill = \"#B22222\", aes(y = ..density..))+\n stat_function(fun = dnorm, args = list(mean = mean(df$A65plus), sd = sd(df$A65plus)), color = \"blue\", linewidth = 1.2)+\n labs(title = \"Histogramme\")+\n xlab(\"65 ans et plus (%)\")+\n ylab(\"Densité\")+\n annotate(geom = \"text\", x =60, y = 0.072, label = paste0(\"Skewness = \", tofr(round(skewness(df$A65plus, na.rm = TRUE),3))), color = \"black\", hjust = 1, size = 3.5)+\n annotate(geom = \"text\", x =60, y = 0.069, label = paste0(\"Kurtosis = \", tofr(round(kurtosis(df$A65plus, na.rm = TRUE),3))), color = \"black\", hjust = 1, size = 3.5)+\n annotate(geom = \"text\", x =60, y = 0.066, label = paste0(\"Shapiro = \", tofr(round(shapiro.test(df$A65plus)$statistic,3))), color = \"black\", hjust = 1, size = 3.5)\nPlot3 <- ggplot(data = df, mapping = aes(x = A65plus, y = HabKm2))+\n geom_point(colour = \"red\")+\n labs(title = \"Nuage de points\")+\n xlab(\"65 ans et plus (%)\")+\n ylab(expression(\"1000 habitants au\"~km^{2}))+\n stat_smooth(method = \"lm\", se = FALSE, cor.coef = TRUE, cor.method = \"pearson\")+\n annotate(geom = \"text\", x =60, y = 50, label = paste0(\"Pearson = \", p), color = \"black\", hjust = 1, size = 3.5)+\n annotate(geom = \"text\", x =60, y = 48, label = paste0(\"Spearman = \", s), color = \"black\", hjust = 1, size = 3.5)+\n annotate(geom = \"text\", x =60, y = 46, label = paste0(\"Kendall = \", k), color = \"black\", hjust = 1, size = 3.5) \nggarrange(Plot1, Plot2, Plot3, ncol = 3, nrow = 1)\n```\n\nÀ la lecture des deux histogrammes à la @fig-PearsonSpearmanKendall, il est clair que les variables *densité de population* et *pourcentage de personnes ayant 65 ou plus* sont très anormalement distribuées. Dans ce contexte, l'utilisation du coefficient de Pearson peut nous amener à mésestimer la relation existant entre les deux variables. Notez que les coefficients de Spearman et de Kendall sont tous les deux plus faibles.\n\n### Corrélations robustes (*Biweight midcorrelation*, *Percentage bend correlation* et la corrélation *pi* de Shepherd) {#sec-0434}\n\nDans l'exemple donné à la @fig-ValExtremes, nous avions identifié des valeurs extrêmes et les avons retiré du jeu de données. Cette pratique peut tout à fait se justifier quand les données sont erronées (un capteur de pollution renvoyant une valeur négative, un questionnaire rempli par un mauvais plaisantin, etc.), mais parfois les cas extrêmes font partie du phénomène à analyser. Dans ce contexte, les identifier et les retirer peut paraître arbitraire. Une solution plus élégante est d'utiliser des méthodes dites **robustes**, c'est-à-dire moins sensibles aux valeurs extrêmes. Pour les corrélations, la *Biweight midcorrelation* [@wilcox1994percentage] est au coefficient de Pearson ce que la médiane est à la moyenne. Il est donc pertinent de l'utiliser pour des jeux de données présentant potentiellement des valeurs extrêmes. Elle est calculée comme suit : \n\n$$\n\\begin{aligned}\n&u_{i} = \\frac{x_{i} - med(x)}{9 \\times (med(|x_{i} - med(x)|))} \\text{ et } v_{i} = \\frac{y_{i} - med(y)}{9 \\times (med(|y_{i} - med(y)|))}\\\\\n&w_{i}^{(x)} = (1 - u_{i}^2)^2 I(1 - |u_{i}|) \\text{ et } w_{i}^{(y)} = (1 - v_{i}^2)^2 I(1 - |v_{i}|)\\\\\n&I(x) = \n\\begin{cases}\n1, \\text{si } x = 1\\\\\n0, \\text{sinon}\n\\end{cases}\\\\\n&\\tilde{x}_{i} = \\frac{(x_{i} - med(x))w_{i}^{(x)}}{\\sqrt{(\\sum_{j=1}^m)[(x_{j} - med(x))w_{j}^{(x)}]^2}} \\text{ et } \\tilde{y}_{i} = \\frac{(y_{i} - med(y))w_{i}^{(y)}}{\\sqrt{(\\sum_{j=1}^m)[(y_{j} - med(y))w_{j}^{(y)}]^2}}\\\\\n&bicor(x,y) = \\sum_{i=1}^m \\tilde{x_i}\\tilde{y_i}\n\\end{aligned}\n$$ {#eq-bicor}\n\n\nComme le souligne l'@eq-bicor, la *Biweight midcorrelation* est basée sur les écarts à la médiane, plutôt que sur les écarts à la moyenne.\n\nAssez proche de la *Biweight midcorrelation*, la *Percentage bend correlation* se base également sur la médiane des variables *X* et *Y*. Le principe général est de donner un poids plus faible dans le calcul de cette corrélation à un certain pourcentage des observations (20 % sont généralement recommandés) dont la valeur est éloignée de la médiane. Pour une description complète de la méthode, vous pouvez lire l'article de @wilcox1994percentage.\n\nEnfin, une autre option est l'utilisation de la corrélation $pi$ de Sherphred [@Schwarzkopf2012]. Il s'agit simplement d'une méthode en deux étapes. Premièrement, les valeurs extrêmes sont identifiées à l'aide d'une approche par *bootstrap* utilisant la distance de Mahalanobis (calculant les écarts multivariés entre les observations). Deuxièmement, le coefficient de *Spearman* est calculé sur les observations restantes.\n\nAppliquons ces corrélations aux données précédentes. Notez que ce simple code d'une dizaine de lignes permet d'explorer rapidement la corrélation entre deux variables selon six mesures de corrélation.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| results: hide\nlibrary(\"correlation\")\ndf1 <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\nmethods <- c(\"Pearson\" , \"Spearman\" , \"Biweight\" , \"Percentage\" , \"Shepherd\")\nrs <- lapply(methods, function(m){\n test <- correlation::cor_test(data = df1, x = \"Hab1000Km2\", y = \"A65plus\", method = m, ci=0.95)\n return(c(test$r, test$CI_low, test$CI_high))\n })\ndfCorr <- data.frame(do.call(rbind, rs))\nnames(dfCorr) <- c(\"r\" , \"IC_2.5\" , \"IC_97.5\")\ndfCorr$method <- methods\n\n# Impression du tableau avec le package stargazer\nlibrary(stargazer)\nstargazer(dfCorr, type = \"text\", summary = FALSE, rownames = FALSE, align = FALSE, digits = 3,\n title = \"Comparaison de différentes corrélations pour les deux variables\")\n\n```\n\n```{r}\n#| label: tbl-robcorr\n#| tbl-cap: Comparaison de différentes corrélations pour les deux variables\n#| echo: false\n#| message: false\n#| warning: false\nknitr::kable(dfCorr,\n digits = 3,\n col.names = c(\"r\" , \"IC 2,5 %\" , \"IC 97,5 %\", \"Méthode\"),\n align= c(\"r\", \"r\", \"r\", \"l\")\n )\n```\n\nIl est intéressant de mentionner que ces trois corrélations sont rarement utilisées malgré leur pertinence dans de nombreux cas d'application. Nous faisons face ici à un cercle vicieux dans la recherche : les méthodes les plus connues sont les plus utilisées, car elles sont plus facilement acceptées par la communauté scientifique. Des méthodes plus élaborées nécessitent davantage de justification et de discussion, ce qui peut conduire à de multiples sessions de corrections/resoumissions pour qu'un article soit accepté, malgré le fait qu'elles puissent être plus adaptées au jeu de données à l'étude.\n\n### Significativité des coefficients de corrélation {#sec-0435} \n\nQuelle que soit la méthode utilisée, il convient de vérifier si le coefficient de corrélation est ou non statistiquement différent de 0. En effet, nous travaillons la plupart du temps avec des données d'échantillonnage, et très rarement avec des populations complètes. En collectant un nouvel échantillon, aurions-nous obtenu des résultats différents? Le calcul de ce degré de significativité permet de quantifier le niveau de certitude quant à l'existence d'une corrélation entre les deux variables, positive ou négative. Cet objectif est réalisé en calculant la valeur de _t_ et le nombre de degrés de liberté : $t=\\sqrt{\\frac{n-2}{1-r^2}}$ et $dl = n-2$ avec $r$ et $n$ étant respectivement le coefficient de corrélation et le nombre d'observations. De manière classique, nous utiliserons la table des valeurs critiques de la distribution de $t$ : si la valeur de $t$ est supérieure à la valeur critique (avec _p_ = 0,05 et le nombre de degrés de liberté), alors le coefficient est significatif à 5 %. En d'autres termes, si la vraie corrélation entre les deux variables (calculable uniquement à partir des populations complètes) était 0, alors la probabilité de collecter notre échantillon serait inférieure à 5 %. Dans ce contexte, nous pouvons raisonnablement rejeter l'hypothèse nulle (corrélation de 0). \n\nLa courte syntaxe ci-dessous illustre comment calculer la valeur de $t$, le nombre de degrés de liberté et la valeur de _p_ pour une corrélation donnée.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\ndf <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\nr <- cor(df$A65plus, df$LogTailInc) # Corrélation\nn <- nrow(df) # Nombre d'observations\ndl <- nrow(df)-2 # degrés de liberté\nt <- r*sqrt((n-2)/(1-r^2)) # Valeur de T\np <- 2*(1-pt(abs(t), dl)) # Valeur de p\ncat(\"\\nCorrélation =\", round(r, 4), \n \"\\nValeur de t =\", round(t, 4),\n \"\\nDegrés de liberté =\", dl,\n \"\\np = \", round(p, 4)) \n```\n\nPlus simplement, la fonction `cor.test` permet d'obtenir en une seule ligne de code le coefficient de corrélation, l'intervalle de confiance à 95 % et les valeurs de _t_ et de _p_, comme illustré dans la syntaxe ci-dessous. Si l'intervalle de confiance est à cheval sur 0, c'est-à-dire que la borne inférieure est négative et la borne supérieure positive, alors le coefficient de corrélation n'est pas significatif au seuil choisi (95 % habituellement). Dans l'exemple ci-dessous, la relation linéaire entre les deux variables est significativement négative avec une corrélation de Pearson de −0,158 (*p* = 0,000) et un intervalle de confiance à 95 % de −0,219 à −0,095.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Intervalle de confiance à 95 %\ncor.test(df$HabKm2, df$A65plus, conf.level = .95)\n# Vous pouvez accéder à chaque sortie de la fonction cor.test comme suit :\np <- cor.test(df$HabKm2, df$A65plus)\ncat(\"Valeur de corrélation = \", round(p$estimate,3), \"\\n\",\n \"Intervalle à 95 % = [\", round(p$conf.int[1],3), \" \", round(p$conf.int[2],3), \"]\", \"\\n\",\n \"Valeur de t = \", round(p$statistic,3), \"\\n\",\n \"Valeur de p = \", round(p$p.value,3),\"\\n\", sep = \"\")\n# Corrélation de Spearman\ncor.test(df$HabKm2, df$A65plus, method = \"spearman\")\n# Corrélation de Kendall\ncor.test(df$HabKm2, df$A65plus, method = \"kendall\")\n```\n\nOn pourra aussi modifier l'intervalle de confiance, par exemple à 90 % ou 99 %. L'intervalle de confiance et le seuil de significativité doivent être définis avant l'étude. Leur choix doit s'appuyer sur les standards de la littérature du domaine étudié, du niveau de preuve attendu et de la quantité de données.\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Intervalle à 90 %\ncor.test(df$HabKm2, df$A65plus, method = \"pearson\", conf.level = .90)\n# Intervalle à 99 %\ncor.test(df$HabKm2, df$A65plus, method = \"pearson\", conf.level = .99)\n```\n\n**Corrélation et _bootstrap_.** Il est possible d'estimer la corrélation en mobilisant la notion de _bootstrap_, soit des méthodes d'inférence statistique basées sur des réplications des données initiales par rééchantillonnage. Concrètement, la méthode du _bootstrap_ permet une mesure de la corrélation avec un intervalle de confiance à partir de _r_ réplications, comme illustré à partir de la syntaxe ci-dessous.\n\n\n```{r}\n#| label: fig-fig9\n#| echo: true\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Histogramme pour les valeurs de corrélation issues du Bootstrap\n#| out-width: \"75%\"\nlibrary(\"boot\")\ndf <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\n# Fonction pour la corrélation\ncorrelation <- function(df, i, X, Y, cor.type = \"pearson\"){\n # Paramètres de la fonction :\n # data : DataFrame\n # X et Y : noms des variables X et Y\n # cor.type : type de corrélation : c(\"pearson\" , \"spearman\" , \"kendall\")\n # i : indice qui sera utilisé par les réplications (à ne pas modifier)\n cor(df[[X]][i], df[[Y]][i], method=cor.type)\n}\n# Calcul du Bootstrap avec 5000 réplications\ncorBootstraped <- boot(data = df, # nom du tableau\n statistic = correlation, # appel de la fonction à répliquer \n R = 5000, # nombre de réplications\n X = \"A65plus\",\n Y = \"HabKm2\", \n cor.type = \"pearson\")\n# Histogramme pour les valeurs de corrélation issues du Bootstrap\nplot(corBootstraped)\n# Corrélation \"bootstrapée\"\ncorBootstraped\n# Intervalle de confiance du bootstrap à 95 %\nboot.ci(boot.out = corBootstraped, conf = 0.95, type = \"all\")\n# Comparaison de l'intervalle classique basé sur la valeur de T\np <- cor.test(df$HabKm2, df$A65plus)\ncat(round(p$estimate,5), \" [\", round(p$conf.int[1],4), \" \", round(p$conf.int[2],4), \"]\", sep = \"\")\n```\n\nLe _bootstrap_ renvoie un coefficient de corrélation de Pearson de −0,158. Les intervalles de confiance obtenus à partir des différentes méthodes d'estimation (normale, basique, pourcentage et BCa) ne sont pas à cheval sur 0, indiquant que le coefficient est significatif à 5 %.\n\n### Corrélation partielle {#sec-0436} \n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Relation entre deux variables une fois prise en compte une autre variable dite de contrôle**\n:::\n::: bloc_objectif-body\nLa corrélation partielle permet d'évaluer la relation linéaire entre deux variables quantitatives continues, après avoir contrôlé une ou plusieurs autres variables quantitatives (dites variables de contrôle).\n\nEn études urbaines, nous pourrions vouloir vérifier si deux variables sont ou non associées après avoir contrôlé la densité de population ou encore la distance au centre-ville.\n:::\n:::\n\n\nLe coefficient de corrélation partielle peut être calculé pour plusieurs mesures de corrélation (notamment, Pearson, Spearman et Kendall). Variant aussi de −1 à 1, il est calculé comme suit :\n\n$$\nr_{ABC} = \\frac{r_{AB}-r_{AC}r_{BC}}{\\sqrt{(1-r_{AC}^2)(1-r_{BC}^2)}}\n$$ {#eq-corpartielle}\n\navec _A_ et _B_ étant les deux variables pour lesquelles nous souhaitons évaluer la relation linéaire, une fois contrôlée la variable _C_; $r$ étant le coefficient de corrélation (Pearson, Spearman ou Kendall) entre deux variables.\n\nDans l'exemple ci-dessous, nous voulons estimer la relation linéaire entre le pourcentage de personnes à faible revenu et la couverture végétale au niveau des îlots de l'île de Montréal, une fois contrôlée la densité de population. En effet, plus cette dernière est forte, plus la couverture végétale est faible ($r$ de Pearson = −0,563). La valeur du $r$ de Pearson s'élève à −0,513 entre le pourcentage de personnes à faible revenu dans la population totale de l'îlot et la couverture végétale. Une fois la densité de population contrôlée, elle chute à −0,316. Pour calculer la corrélation partielle, nous pouvons utiliser la fonction `pcor.test` du package `ppcor`.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(\"foreign\")\nlibrary(\"ppcor\")\ndfveg <- read.dbf(\"data/bivariee/IlotsVeg2006.dbf\")\n# Corrélation entre les trois variables\nround(cor(dfveg[, c(\"VegPct\", \"Pct_FR\" , \"LogDens\")], method = \"p\"), 3)\n# Corrélation partielle avec la fonction pcor.test entre :\n# la couverture végétale de l'îlot (%) et\n# le pourcentage de personnes à faible revenu\n# une fois contrôlée la densité de population\npcor.test(dfveg$Pct_FR, dfveg$VegPct, dfveg$LogDens, method = \"p\")\n# Calcul de la corrélation partielle avec la formule\ncorAB <- cor(dfveg$VegPct, dfveg$Pct_FR, method = \"p\")\ncorAC <- cor(dfveg$VegPct, dfveg$LogDens, method = \"p\")\ncorBC <- cor(dfveg$Pct_FR, dfveg$LogDens, method = \"p\")\nCorP <- (corAB - (corAC*corBC)) / sqrt((1-corAC^2)*(1-corBC^2))\ncat(\"Corr. partielle avec ppcor = \", \n round(pcor.test(dfveg$Pct_FR, dfveg$VegPct, dfveg$LogDens, method=\"p\")$estimate,5),\n \"\\nCorr. partielle (formule) = \", round(CorP, 5))\n```\n\n### Mise en œuvre dans R {#sec-0437}\n\nComme vous l'aurez compris, il est possible d'arriver au même résultat par différents moyens. Pour calculer les corrélations, nous avons utilisé jusqu'à présent les fonctions de base `cor` et `cor.test`. Il est aussi possible de recourir à des fonctions d'autres _packages_, dont notamment :\n\n* `Hmisc`, dont la fonction `rcorr` permet de calculer des corrélations de Pearson et de Spearman (mais non celle de Kendall) avec les valeurs de _p_.\n\n* `psych`, dont la fonction `corr.test` permet d'obtenir une matrice de corrélation (Pearson, Spearman et Kendall), les intervalles de confiance et les valeurs de _p_.\n\n* `stargazer` pour créer de beaux tableaux d'une matrice de corrélation en *HTML*, en *LaTeX* ou en ASCII.\n\n* `apaTables` pour créer un tableau avec une matrice de corrélation dans un fichier Word.\n\n* `correlation` pour aller plus loin et explorer les corrélations bayésiennes, robustes, non linéaires ou multiniveaux.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\ndf1 <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\nlibrary(\"Hmisc\")\nlibrary(\"stargazer\")\nlibrary(\"apaTables\")\nlibrary(\"dplyr\")\n# Corrélations de Pearson et Spearman et valeurs de p \n# avec la fonction rcorr de Hmisc pour deux variables\nHmisc::rcorr(df1$RevMedMen, df1$Locataire, type = \"pearson\")\nHmisc::rcorr(df1$RevMedMen, df1$Locataire, type = \"spearman\")\n# Matrice de corrélation avec la fonction rcorr de Hmisc pour plus de variables\n# Nous créons au préalable un vecteur avec les noms des variables à sélectionner\nVars <- c(\"RevMedMen\" , \"Locataire\", \"LogTailInc\" , \"A65plus\" , \"ImgRec\", \"HabKm2\", \"FaibleRev\")\nHmisc::rcorr(df1[, Vars] %>% as.matrix())\n# Avec la fonction corr.test du package psych pour avoir la matrice de corrélation\n# (Pearson, Spearman et Kendall), les intervalles de confiance et les valeurs de p\nprint(psych::corr.test(df[, Vars], \n method = \"kendall\", \n ci = TRUE, alpha = 0.05), short = FALSE) \n# Création d'un tableau pour une matrice de corrélation\n# changer le paramètre type pour 'html' or 'latex' si souhaité\np <- cor(df1[, Vars], method=\"pearson\")\nstargazer(p, title = \"Correlation Matrix\", type = \"text\")\n# Créer un tableau avec la matrice de corrélation \n# dans un fichier Word (.doc)\napaTables::apa.cor.table(df1[, c(\"RevMedMen\" , \"Locataire\" , \"LogTailInc\")], \n filename = \"data/bivariee/TitiLaMatrice.doc\",\n show.conf.interval = TRUE,\n landscape = TRUE)\n```\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Une image vaut mille mots, surtout pour une matrice de corrélation!**\n:::\n::: bloc_astuce-body\nLe package `corrplot` vous permet justement de construire de belles figures avec une matrice de corrélation (figures [-@fig-corrplot1] et [-@fig-corrplot2]). L'intérêt de ce type de figure est de repérer rapidement des associations intéressantes lorsque nous calculons les corrélations entre un grand nombre de variables.\n:::\n:::\n\n```{r}\n#| label: fig-corrplot1\n#| echo: true\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Matrice de corrélation avec corrplot (chiffres)\n#| out-width: \"60%\"\nlibrary(\"corrplot\")\nlibrary(\"ggpubr\")\ndf1 <- read.csv(\"data/bivariee/sr_rmr_mtl_2016.csv\")\nVars <- c(\"RevMedMen\" , \"Locataire\", \"LogTailInc\" , \"A65plus\" , \"ImgRec\", \"HabKm2\", \"FaibleRev\")\np <- cor(df1[, Vars], method=\"pearson\")\ncouleurs <- colorRampPalette(c(\"#053061\", \"#2166AC\" , \"#4393C3\", \"#92C5DE\",\n \"#D1E5F0\", \"#FFFFFF\", \"#FDDBC7\", \"#F4A582\",\n \"#D6604D\", \"#B2182B\", \"#67001F\"))\ncorrplot::corrplot(p, addrect = 3, method=\"number\",\n diag = FALSE, col=couleurs(100))\n```\n\n```{r}\n#| label: fig-corrplot2\n#| echo: true\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Matrice de corrélation avec corrplot (chiffres et ellipses)\n#| out-width: \"60%\"\nfig2 <- corrplot.mixed(p, lower=\"number\", lower.col = \"black\", \n upper = \"ellipse\", upper.col=couleurs(100))\n```\n\n\n### Comment rapporter des valeurs de corrélations? {#sec-0438}\n\nBien qu'il n'y ait pas qu'une seule manière de reporter des corrélations, voici quelques lignes directrices pour vous guider : \n\n* Signaler si la corrélation est faible, modérée ou forte.\n\n* Indiquer si la corrélation est positive ou négative. Toutefois, ce n'est pas une obligation, car nous pouvons rapidement le constater avec le signe du coefficient.\n\n* Mettre le *r* et le *p* en italique et en minuscules.\n\n* Deux décimales uniquement pour le $r$ (sauf si une plus grande précision se justifie dans le domaine d'étude).\n\n* Trois décimales pour la valeur de *p*. Si elle est inférieure à 0,001, écrire plutôt *p* < 0,001.\n\n* Indiquer éventuellement le nombre de degrés de liberté, soit $r(dl)=...$\n\nVoici des exemples :\n\n* La corrélation entre les variables *revenu médian des ménages* et *pourcentage de locataires* est fortement négative (*r* = −0,78, *p* < 0,001).\n\n* La corrélation entre les variables *revenu médian des ménages* et *pourcentage de locataires* est forte (*r*(949) = −0,78, *p* < 0,001).\n\n* La corrélation entre les variables *densité de population* et *revenu médian des ménages* est modérée (*r* = −0,49, *p* < 0,001).\n\n* La corrélation entre les variables *densité de population* et *pourcentage de 65 ans et plus* n'est pas significative (*r* = −0,08, *p* = 0,07).\n\nPour un texte en anglais, référez-vous à : [https://www.socscistatistics.com/tutorials/correlation/default.aspx](https://www.socscistatistics.com/tutorials/correlation/default.aspx){target=\"_blank\"}.\n\n## Régression linéaire simple {#sec-044}\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Comment expliquer et prédire une variable continue en fonction d'une autre variable?**\n:::\n::: bloc_objectif-body\nRépondre à cette question relève de la statistique inférentielle. Il s'agit en effet d'établir une équation simple du type $Y = a + bX$ pour expliquer et prédire les valeurs d'une variable dépendante (*Y*) à partir d'une variable indépendante (*X*). L'équation de la régression est construite grâce à un jeu de données (un échantillon). À partir de cette équation, il est possible de prédire la valeur attendue de *Y* pour n'importe quelle valeur de *X*. Nous appelons cette équation un modèle, car elle cherche à représenter la réalité de façon simplifiée.\n\nLa régression linéaire simple relève ainsi de la statistique inférentielle et se distingue ainsi de la **covariance** ([section @sec-042]) et de la **corrélation** ([section @sec-043]) qui relèvent quant à eux de la statistique bivariée descriptive et exploratoire. \n\nPar exemple, la régression linéaire simple pourrait être utilisée pour expliquer les notes d'un groupe d'étudiants et d'étudiantes à un examen (variable dépendante *Y*) en fonction du nombre d'heures consacrées à la révision des notes de cours (variable indépendante *X*). Une fois l'équation de régression déterminée et si le modèle est efficace, nous pourrons prédire les notes des personnes inscrites au cours la session suivante en fonction du temps qu'ils ou qu'elles prévoient passer à étudier, et ce, avant l'examen. \n\nFormulons un exemple d'application de la régression linéaire simple en études urbaines. Dans le cadre d'une étude sur les îlots de chaleur urbains, la température de surface (variable dépendante) pourrait être expliquée par la proportion de la superficie de l'îlot couverte par de la végétation (variable indépendante). Nous supposons alors que plus cette proportion est importante, plus la température est faible et inversement, soit une relation linéaire négative. Si le modèle est efficace, nous pourrions prédire la température moyenne des îlots d'une autre municipalité pour laquelle nous ne disposons pas d'une carte de température, et repérer ainsi les îlots de chaleur potentiels. Bien entendu, il est peu probable que nous arrivions à prédire efficacement la température moyenne des îlots avec uniquement la couverture végétale comme variable explicative. En effet, bien d'autres caractéristiques de la forme urbaine peuvent influencer ce phénomène comme la densité du bâti, la couleur des toits, les occupations du sol présentes, l'effet des canyons urbains, etc. Il faudrait alors inclure non pas une, mais plusieurs variables explicatives (indépendantes).\n\nAinsi, nous distinguons la **régression linéaire simple** (une seule variable indépendante) de la **régression linéaire multiple** (plusieurs variables indépendantes); cette dernière est largement abordée au [chapitre @sec-chap07].\n:::\n:::\n\nDans cette section, nous décrivons succinctement la régression linéaire simple. Concrètement, nous voyons comment déterminer la droite de régression, interpréter ses différents paramètres du modèle et évaluer la qualité d'ajustement du modèle. Nous n'abordons ni les hypothèses liées au modèle de régression linéaire des moindres carrés ordinaires (MCO) ni les conditions d'application. Ces éléments sont expliqués au [chapitre @sec-chap07], consacré à la régression linéaire multiple.\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Corrélation, régression simple et causalité : attention aux raccourcis!**\n:::\n::: bloc_attention-body\nSi une variable *X* explique et prédit efficacement une variable *Y*, cela ne veut pas dire pour autant qu'*X* cause *Y*. Autrement dit, la corrélation, soit le degré d'association entre deux variables, ne signifie pas qu'il existe un lien de causalité entre elles.\n\nPremièrement, la variable explicative (*X*, indépendante) doit absolument précéder la variable à expliquer (*Y*, dépendante). Par exemple, l'âge (*X*) peut influencer le sentiment de sécurité (*Y*). Mais, le sentiment de sécurité ne peut en aucun cas influencer l'âge. Par conséquent, l'âge ne peut conceptuellement pas être la variable dépendante dans cette relation.\n\nDeuxièmement, bien qu'une variable puisse expliquer efficacement une autre variable, elle peut être un **facteur confondant**. Prenons deux exemples bien connus :\n\n* Avoir les doigts jaunes est associé au cancer du poumon. Bien entendu, les doigts jaunes ne causent pas le cancer : c'est un facteur confondant puisque fumer augmente les risques du cancer du poumon et jaunit aussi les doigts.\n\n* Dans un article intitulé *Chocolate Consumption, Cognitive Function, and Nobel Laureates*, Messerli [-@Messerli] a trouvé une corrélation positive entre la consommation de chocolat par habitant et le nombre de prix Nobel pour dix millions d'habitants pour 23 pays. Ce résultat a d'ailleurs été rapporté par de nombreux médias, sans pour autant que Messerli [-@Messerli] et les journalistes concluent à un lien de causalité entre les deux variables :\n\n - [Radio Canada](https://ici.radio-canada.ca/nouvelle/582457/chocolat-consommateurs-nobels)\n\n - [La Presse](https://www.lapresse.ca/vivre/sante/nutrition/201210/11/01-4582347-etude-plus-un-pays-mange-de-chocolat-plus-il-a-de-prix-nobel.php)\n\n - [Le Point](https://www.lepoint.fr/insolite/le-chocolat-dope-aussi-l-obtention-de-prix-nobel-12-10-2012-1516159_48.php). \n\nLes chercheurs et les chercheuses savent bien que la consommation de chocolat ne permet pas d'obtenir des résultats intéressants et de les publier dans des revues prestigieuses; c'est plutôt le café ! Plus sérieusement, il est probable que les pays les plus riches investissent davantage dans la recherche et obtiennent ainsi plus de prix Nobel. Dans les pays les plus riches, il est aussi probable que l'on consomme plus de chocolat, considéré comme un produit de luxe dans les pays les plus pauvres.\n\nPour approfondir le sujet sur la confusion entre corrélation, régression simple et causalité, vous pouvez visionner cette courte [vidéo ludique de vulgarisation](https://www.youtube.com/embed/A-_naeATJ6o).\n\nL'association entre deux variables peut aussi être simplement le fruit du hasard. Si nous explorons de très grandes quantités de données (avec un nombre impressionnant d'observations et de variables), soit une démarche relevant du forage ou de la fouille de données (*data mining* en anglais), le hasard fera que nous risquons d'obtenir des corrélations surprenantes entre certaines variables. Prenons un exemple concret : admettons que nous ayons collecté 100 variables et que nous calculons les corrélations entre chaque paire de variables. Nous obtenons une matrice de corrélation de 100 x 100, à laquelle nous pouvons enlever la diagonale et une moitié de la matrice, ce qui nous laisse un total de 4950 corrélations différentes. Admettons que nous choisissions un seuil de significativité de 5 %, nous devons alors nous attendre à ce que le hasard produise des résultats significatifs dans 5 % des cas. Sur 4950 corrélations, cela signifie qu'environ 247 corrélations seront significatives, et ce, indépendamment de la nature des données. Nous pouvons aisément illustrer ce fait avec la syntaxe suivante :\n\n```{r}\n#| label: fig-corraleatoire\n#| eval: false\n#| message: false\n#| warning: false\n#| out-width: \"80%\"\nlibrary(\"Hmisc\")\nnbVars <- 100 # nous utilisons 100 variables générées aléatoirement pour l'expérience\nnbExperiment <- 1000 # nous reproduirons 1000 fois l'expérience avec les 100 variables\n# Le nombre de variables significatives par expérience est enregistré dans Results\nResults <- c()\n# Itérons pour chaque expérimentation (1000 fois)\nfor(i in 1:nbExperiment){\n Datas <- list()\n # Générons 100 variables aléatoires normalement distribuées\n for (j in 1:nbVars){\n Datas[[j]] <- rnorm(150)\n }\n DF <- do.call(\"cbind\", datas)\n # Calculons la matrice de corrélation pour les 100 variables\n cor_mat <- rcorr(DF)\n # Comptons combien de fois les corrélations étaient significatives\n Sign <- table(cor_mat$P<0.05)\n NbPairs <- Sign[[\"TRUE\"]]/2\n # Ajoutons les résultats dans Results\n Results <- c(Results, NbPairs)\n}\n# Transformons Results en un DataFrame\ndf <- data.frame(Values = Results)\n# Affichons le résultat dans un graphique\nggplot(df, aes(x = Values)) + \n geom_histogram(aes(y =..density..), \n colour = \"black\", \n fill = \"white\") +\n stat_function(fun = dnorm, args = list(mean = mean(df$Values), \n sd = sd(df$Values)), color = \"blue\")+\n geom_vline(xintercept = mean(df$Values), color = \"red\", size = 1.2)+\n annotate(\"text\", x=0, y = 0.028, \n label = paste(\"Nombre moyen de corrélations significatives\\n\n sur 1000 réplications : \",\n round(mean(df$Values),0), sep = \"\"), hjust=\"left\")+\n xlab(\"Nombre de corrélations significatives\")+\n ylab(\"densité\")\n```\n\n![Corrélations significatives obtenues aléatoirement](images/Chap04/ReplicationHist.png){#fig-replicationhist width=\"50%\" fig-align=\"center\"}\n\n:::\n:::\n\n### Principe de base de la régression linéaire simple {#sec-0441}\nLa régression linéaire simple vise à déterminer une droite (une fonction linéaire) qui résume le mieux la relation linéaire entre une variable dépendante (*Y*) et une variable indépendante (*X*) :\n$$\n\\widehat{y_i} = \\beta_{0} + \\beta_{1}x_{i}\n$$ {#eq-regsimple}\n\navec $\\widehat{y_i}$ et $x_{i}$ qui sont respectivement la valeur prédite de la variable dépendante et la valeur de la variable indépendante pour l'observation $i$. $\\beta_{0}$ est la constante (*intercept* en anglais) et représente la valeur prédite de la variable *Y* quand *X* est égale à 0. $\\beta_{1}$ est le coefficient de régression pour la variable *X*, soit la pente de la droite. Ce coefficient nous informe sur la relation entre les deux variables : s’il est positif, la relation est positive; s’il est négatif, la relation est négative; s'il est proche de 0, la relation est nulle (la droite est alors horizontale). Plus la valeur absolue de $\\beta_{1}$ est élevée, plus la pente est forte et plus la variable *Y* varie à chaque changement d’une unité de la variable *X*.\n\nConsidérons un exemple fictif de dix municipalités d'une région métropolitaine pour lesquelles nous disposons de deux variables : le pourcentage de personnes occupées se rendant au travail principalement à vélo et la distance entre chaque municipalité et le centre-ville de la région métropolitaine (@tbl-regfictives).\n\n\n```{r}\n#| label: tbl-regfictives\n#| tbl-cap: Données fictives sur l'utilisation du vélo par municipalité\n#| echo: false\n#| message: false\n#| warning: false\n\ndf <- read.csv(\"data/bivariee/Reg.csv\", stringsAsFactors = FALSE)\ndf1 <- df[1:5,]\ndf2 <- df[6:10,]\n\nknitr::kable(rbind(df1, df2),\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Municipalité\" , \"Vélo\" , \"KMCV\"),\n align= c(\"l\", \"c\", \"r\")\n )\n```\n\nD'emblée, à la lecture du nuage de points (@fig-reg), nous décelons une forte relation linéaire négative entre les deux variables : plus la distance entre la municipalité et le centre-ville de la région métropolitaine augmente, plus le pourcentage de cyclistes est faible, ce qui est confirmé par le coefficient de corrélation (*r* = −0,90). La droite de régression (en rouge à la @fig-reg) qui résume le mieux la relation entre `Vélo` (variable dépendante) et `KmCV` (variable indépendante) s'écrit alors : **Vélo = 30,603 − 1,448 x KmCV**.\n\nLa valeur du coefficient de régression ($\\beta_{1}$) est de −1,448. Le signe de ce coefficient décrit une relation négative entre les deux variables. Ainsi, à chaque ajout d'une unité de la distance entre la municipalité et le centre-ville (exprimée en kilomètres), le pourcentage de cyclistes diminue de 1,448. Retenez que l'unité de mesure de la variable dépendante est très importante pour bien interpréter le coefficient de régression. En effet, si la distance au centre-ville n'était pas exprimée en kilomètres, mais plutôt en mètres, $\\beta_1$ serait égal à −0,001448. Dans la même optique, l'ajout de 10 km de distance entre une municipalité et le centre-ville fait diminuer le pourcentage de cyclistes de −14,48 points de pourcentage.\n\nAvec, cette équation de régression, il est possible de prédire le pourcentage de cyclistes pour n'importe quelle municipalité de la région métropolitaine. Par exemple, pour des distances de 5, 10 ou 20 kilomètres, les pourcentages de cyclistes seraient de :\n\n* $\\widehat{y_i} = \\mbox{30,603} + (\\mbox{-1,448} \\times \\mbox{5 km) = 23,363}$\n* $\\widehat{y_i} = \\mbox{30,603} + (\\mbox{-1,448} \\times \\mbox{10 km) = 8,883}$\n* $\\widehat{y_i} = \\mbox{30,603} + (\\mbox{-1,448} \\times \\mbox{20 km) = 1,643}$\n\n```{r}\n#| label: fig-reg\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Relation linéaire entre l'utilisation du vélo et la distance au centre-ville\n#| out-width: \"65%\"\nlibrary(\"ggplot2\")\nmodele <- lm(Velo~KmCV, df)\nb0 <- tofr(round(modele$coefficients[1],3))\nb1 <- tofr(round(modele$coefficients[2],3))\neq <- paste0(\"Vélo = \", b0, \" \", b1, \" x KmCV\")\nr2 <- tofr(round(summary(modele)$r.squared,3))\npearson <- tofr(round(cor(df$Velo, df$KmCV),3))\nsoustitre <- paste0(\"r2 = \", r2, \", r = \", pearson)\nggplot(df, aes(x = KmCV, y = Velo)) +\n stat_smooth(method = \"lm\", se = FALSE, col=\"red\")+\n labs(title= eq, subtitle = soustitre)+\n xlab(\"Distance de la municipalité au centre-ville de la région métropolitaine (km)\")+\n ylab(\"Vélo (%)\")+\n geom_point(colour = \"black\", size=5)\n``` \n\n\n### Formulation de la droite de régression des moindres carrés ordinaires {#sec-0442}\nReste à savoir comment sont estimés les différents paramètres de l'équation, soit $\\beta_0$ et $\\beta_1$. À la @fig-reg2, les points noirs représentent les valeurs observées ($y_i$) et les points bleus, les valeurs prédites ($\\widehat{y_i}$) par l'équation du modèle. Les traits noirs verticaux représentent, pour chaque observation $i$, l'écart entre la valeur observée et la valeur prédite, dénommé résidu ($\\epsilon_i$, prononcez epsilon de _i_ ou plus simplement le résidu pour _i_ ou le terme d'erreur de _i_). Si un point est au-dessus de la droite de régression, la valeur observée est alors supérieure à la valeur prédite ($y_i > \\widehat{y_i}$) et inversement, si le point est au-dessous de la droite ($y_i < \\widehat{y_i}$). Plus cet écart ($\\epsilon_i$) est important, plus l'observation s'éloigne de la prédiction du modèle et, par extension, moins bon est le modèle. Au @tbl-regfictives2, vous constaterez que la somme des résidus est égale à zéro. La méthode des moindres carrés ordinaires (MCO) vise à minimiser les écarts au carré entre les valeurs observées ($y_i$) et prédites ($\\beta_0+\\beta_1 x_i$, soit $\\widehat{y_i}$) :\n\n$$\nmin\\sum_{i=1}^n{(y_i-(\\beta_0+\\beta_1 x_i))^2}\n$$ {#eq-mco}\n\nPour minimiser ces écarts, le coefficient de régression $\\beta_1$ représente le rapport entre la covariance entre *X* et *Y* et la variance de *Y* (@eq-b1), tandis que la constante $\\beta_0$ est la moyenne de la variable *Y* moins le produit de la moyenne de *X* et de son coefficient de régression (@eq-b0).\n\n$$\n\\beta_1 = \\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})(y_{i}-\\bar{y})}{\\sum_{i=1}^n (x_i-\\bar{x})^2} = \\frac{cov(X,Y)}{var(X)}\n$$ {#eq-b1}\n\n$$\n\\beta_0 = \\widehat{Y}-\\beta_1 \\widehat{X}\n$$ {#eq-b0}\n\n```{r}\n#| label: fig-reg2\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Droite de régression, valeurs observées, prédites et résidus\n#| out-width: \"65%\"\ndf <- read.csv(\"data/bivariee/Reg.csv\", stringsAsFactors = FALSE)\nmodele <- lm(Velo~KmCV, df)\ndf$ypredit <- round(modele$fitted.values,3)\ndf$residus <- round(residuals(modele),3)\ndf$sqrtRes <- round(residuals(modele),3)^2\nb0 <- tofr(round(modele$coefficients[1],3))\nb1 <- tofr(round(modele$coefficients[2],3))\neq <- paste0(\"Vélo = \", b0, \" \", b1, \" x KmCV\")\nr2 <- tofr(round(summary(modele)$r.squared,3))\npearson <- tofr(round(cor(df$Velo, df$KmCV),3))\nsoustitre <- paste0(\"r2 = \", r2, \", r = \", pearson)\nseg <- data.frame(x1 = df[3,3], x2 = 12, y1 = df[2,3], y2 = df[2,3]+5)\nggplot(df) +\n aes(\n x = KmCV,\n y = Velo,\n ymin = Velo,\n ymax = ypredit\n ) +\n stat_smooth(method = \"lm\", se = FALSE, col=\"red\")+\n labs(title= eq,\n subtitle = soustitre)+\n xlab(\"Distance de la municipalité au centre-ville de la région métropolitaine (km)\")+\n ylab(\"Vélo (%)\")+\n geom_segment(aes(xend = df[9,3]+.2, x = df[9,3]+2,\n yend = df[9,2], y = df[9,2]+3),\n size=1.2, linetype = \"solid\", colour = \"brown4\",\n arrow = arrow(length = unit(0.2, \"inches\")))+\n geom_segment(aes(xend = df[9,3]+.05, x = df[9,3]+2,\n yend = df[9,2]-abs(df[9,5]/2),\n y = df[9,2]-abs(df[9,5]/2)),\n size=1.2, linetype = \"solid\", colour = \"brown4\",\n arrow = arrow(length = unit(0.2, \"inches\")))+\n geom_segment(aes(xend = df[9,3], x =df[9,3]-.5,\n yend = df[9,4]-.5, y = df[9,4]-9),\n size=1.2, linetype = \"solid\", colour = \"brown4\",\n arrow = arrow(length = unit(0.2, \"inches\")))+\n annotate(geom = \"text\", x =df[9,3]+2.2, y = df[9,2]+4,\n label = \"Valeur observée pour la municipalité I\", color = \"black\", hjust = 0, size = 5)+\n annotate(geom = \"text\", x =df[9,3]+2.2, y = df[9,2]+3,\n label = \"y = 25,3 % et x = 5,225 km\", color = \"black\", hjust = 0, size = 5)+\n annotate(geom = \"text\", x =df[9,3]+2.2, df[9,2]-abs(df[9,5]/2)+.2,\n label = \"résidu = 25,3 - 23,038 = 2,262\", color = \"black\", hjust = 0, size = 5)+\n annotate(geom = \"text\", x =df[9,3], y = df[9,4]-9.5,\n label = \"Valeur prédite pour I\", color = \"black\", hjust = 0.5, size = 5)+\n \n annotate(geom = \"text\", x =df[9,3], y = df[9,4]-10.5,\n label = \"30,603 - 1,448 x 5,225 = 23,038\", color = \"black\", hjust = 0.5, size = 5)+\n geom_pointrange(colour = \"black\", size=.8, linetype = \"solid\", shape=16)+\n geom_point(colour = \"blue\", size=3, aes(x = KmCV, y = ypredit))\n``` \n\n```{r}\n#| label: tbl-regfictives2\n#| tbl-cap: Valeurs observées, prédites et résidus\n#| echo: false\n#| message: false\n#| warning: false\ndf$sqrtRes <- round(df$residus^2,3)\nsqrtres <- round(sum(df$sqrtRes),3)\ndf[11,1] <- \"Somme\"\ndf[11,5] <- 0\ndf[11,6] <- sqrtres\ndf1 <- rbind(df[1:5,], df[11,])\ndf2 <- rbind(df[6:10,], df[11,])\nopts <- options(knitr.kable.NA = \"--\")\n\nknitr::kable(df,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Municipalité\" , \"Vélo\" , \"KmCV\" , \"Valeur prédite\" , \"Résidu\", \"Résidu au carré\"),\n align= c(\"l\", \"c\", \"r\", \"r\", \"r\", \"r\")\n )\n``` \n\n### Mesure de la qualité d'ajustement du modèle {#sec-0443}\nLes trois mesures les plus courantes pour évaluer la qualité d'ajustement d'un modèle de régression linéaire simple sont l'erreur quadratique moyenne (*root-mean-square error* en anglais, *RMSE*), le coefficient de détermination (*R^2^*) et la statistique *F* de Fisher. Pour mieux appréhender le calcul de ces trois mesures, rappelons que l'équation de régression s'écrit : \n\n$$\ny_i = \\beta_0 + \\beta_1 x_1+ \\epsilon_i \\Rightarrow Y= \\beta_0 + \\beta_1 X + \\epsilon\n$$ {#eq-reg2}\n\nElle comprend ainsi une partie de *Y* qui est expliquée par le modèle et une autre partie non expliquée, soit $\\epsilon$, appelée habituellement le terme d'erreur. Ce terme d'erreur pourrait représenter d'autres variables explicatives qui n'ont pas été prises en compte pour prédire la variable indépendante ou une forme de variation aléatoire inexplicable présente lors de la mesure.\n\n$$\nY = \\underbrace{\\beta_0 + \\beta_1 X}_{\\mbox{partie expliquée par le modèle}}+ \\underbrace{\\epsilon}_{\\mbox{partie non expliquée}}\n$$ {#eq-reg3}\n\n\nPar exemple, pour la municipalité *A* au @tbl-regfictives2, nous avons : $y_A = \\widehat{y}_A - \\epsilon_A \\Rightarrow \\mbox{12,5} = \\mbox{10,138}+\\mbox{2,362}$. Souvenez-vous que la variance d'une variable est la somme des écarts à la moyenne, divisée par le nombre d'observations. Par extension, il est alors possible de décomposer la variance de *Y* comme suit :\n\n$$\n\\underbrace{\\sum_{i=1}^n (y_{i}-\\bar{y})^2}_{\\mbox{variance de Y}} = \\underbrace{\\sum_{i=1}^n (\\widehat{y}_i-\\bar{y})^2}_{\\mbox{var. expliquée}} + \\underbrace{\\sum_{i=1}^n (y_{i}-\\widehat{y})^2}_{\\mbox{var. non expliquée}} \\Rightarrow \nSCT = SCE + SCR\n$$ {#eq-reg4}\n\n\navec :\n\n* *SCT* est la somme des écarts au carré des valeurs observées à la moyenne (_total sum of squares_ en anglais)\n\n* *SCE* est la somme des écarts au carré des valeurs prédites à la moyenne (_regression sum of squares_ en anglais)\n\n* *SCR* est la somme des carrés des résidus (_sum of squared errors_ en anglais).\n\nAutrement dit, la variance totale est égale à la variance expliquée plus la variance non expliquée. Au @tbl-computeR, vous pouvez repérer les valeurs de *SCT*, *SCE* et *SCR* et constater que 279,30 = 227,04 + 52,26 et 27,93 = 22,70 + 5,23.\n\n```{r}\n#| label: tbl-computeR\n#| tbl-cap: Calcul du coefficient de détermination\n#| echo: false\n#| message: false\n#| warning: false\n#| out-width: \"85%\"\ndata <- read.csv(\"data/bivariee/Reg.csv\", stringsAsFactors = FALSE)\nmodele <- lm(Velo~KmCV, data)\ndata$yi <- data$Velo\ndata$ypredit <- modele$fitted.values\ndata$ei <- modele$residuals\ndata$Velo <- NULL\ndata$KmCV <- NULL\nn <- nrow(data)\nmoy_y <- mean(data$yi)\nsumy <- sum(data$yi)\ndata$yi_ymean2 <- (data$yi - moy_y)^2\ndata$ypredit_ymean2 <- (data$ypredit - moy_y)^2\ndata$ei2 <- (data$ei)^2\ndf <- data\ndf[11,1] <- \"N\"\ndf[11,2] <- n\ndf[12,1] <- \"Somme\"\ndf[13,1] <- \"Moyenne\"\nfor (i in c(2,4:7))\n{\n df[12,i] <- sum(df[1:10,i])\n df[13,i] <- mean(df[1:10,i])\n df[i] <- round(df[i], 2)\n}\ndf[3] <- round(df[3], 2)\nopts <- options(knitr.kable.NA = \"--\")\n\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Municipalité\", \"$y_i$\", \"$\\\\widehat{y}_i$\", \"$\\\\epsilon_i$\" , \"$(y_i-\\\\bar{y})^2$\" , \"$(\\\\widehat{y}_i-y_i)^2$\", \"$\\\\epsilon_i^2$\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\n\n**Calcul de l'erreur quadratique moyenne**\n\nLa somme des résidus au carré (*SCR*) divisée par le nombre d'observations représente donc le carré moyen des erreurs (en anglais, *mean square error - MSE*), soit la variance résiduelle du modèle (52,26 / 10 = 5,23). Plus sa valeur est faible, plus le modèle est efficace pour prédire la variable indépendante. L'erreur quadratique moyenne (en anglais, *root-mean-square error - RMSE*) est simplement la racine carrée de la somme des résidus au carré divisée par le nombre d'observations ($n$) :\n\n$$\nRMSE = \\sqrt{\\frac{\\sum_{i=1}^n (y_{i}-\\widehat{y})^2}{n}}\n$$ {#eq-reg5}\n\n\nElle représente ainsi une **mesure absolue des erreurs** qui est exprimée dans l'unité de mesure de la variable dépendante. Dans le cas présent, nous avons : $\\sqrt{5,23}=2,29$. Cela signifie qu'en moyenne, l'écart absolu (ou erreur absolue) entre les valeurs observées et prédites est de 2,29 points de pourcentage. De nouveau, une plus faible valeur de **RMSE** indique un meilleur ajustement du modèle. Mais surtout, le RMSE permet d'évaluer avec quelle précision le modèle prédit la variable dépendante. Il est donc particulièrement important si l'objectif principal du modèle est de prédire des valeurs sur un échantillon d'observations pour lequel la variable dépendante est inconnue.\n\n**Calcul du coefficient de détermination**\n\nNous avons largement démontré que la variance totale est égale à la variance expliquée plus la variance non expliquée. La qualité du modèle peut donc être évaluée avec le coefficient de détermination (*R^2^*), soit le rapport entre les variances expliquée et totale : \n\n$$\nR^2 = \\frac{SCE}{SCT} \\mbox{ avec } R^2 \\in \\left[0,1\\right]\n$$ {#eq-reg6}\n\n\nComparativement au RMSE qui est une mesure absolue, le coefficient de détermination est une **mesure relative** qui varie de 0 à 1. Il exprime la proportion de la variance de *Y* qui est expliquée par la variable *X*; autrement dit, plus sa valeur est élevée, plus *X* influence/est capable de prédire *Y*. Dans le cas présent, nous avons : R^2^ = 227,04 / 279,3 = 0,8129, ce qui signale que 81,3 % de la variance du pourcentage de cyclistes est expliquée par la distance entre la municipalité et le centre-ville de la région métropolitaine. Tel que signalé dans la [section @sec-0432], la racine carrée du coefficient de détermination (*R^2^*) est égale au coefficient de corrélation ($r$) entre les deux variables. \n\n**Calcul de la statistique _F_ de Fisher**\n\nLa statistique _F_ de Fisher permet de vérifier la significativité globale du modèle.\n\n$$\nF = (n-2)\\frac{R^2}{1-R^2} = (n-2)\\frac{SCE}{SCR}\n$$ {#eq-reg7}\n\n\nL'hypothèse nulle (*H~0~* avec $\\beta_1=0$) est rejetée si la valeur calculée de *F* est supérieure à la valeur critique de la table *F* avec *1, n-2* degrés de liberté et un seuil $\\alpha$ (*p* = 0,05 habituellement) (voir la table des valeurs critiques de *F*, [section @sec-142]). Notez que nous utilisons rarement la table *F* puisqu'avec la fonction `pf(f obtenu, 1, n-2, lower.tail = FALSE)`, nous obtenons obtient directement la valeur de *p* associée à la valeur de *F*. Concrètement, si le test _F_ est significatif (avec *p* < 0,05), plus la valeur de *F* est élevée, plus le modèle est efficace (et plus le *R^2^* sera également élevé).\n\nNotez que la fonction `summary` renvoie les résultats du modèle, dont notamment le test _F_ de Fisher.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| out-width: \"85%\"\n# utiliser la fonction summary\nsummary(modele)\n```\n\nDans le cas présent, $F = (10 - 2)\\frac{\\mbox{0,8129}}{\\mbox{1-0,8129}} = (10-2)\\frac{\\mbox{227,04}}{\\mbox{52,26}} = \\mbox{34,75}$ avec une valeur de $\\mbox{p < 0,001}$. Par conséquent, le modèle est significatif.\n\n### Mise en œuvre dans R {#sec-0444}\nComment calculer une régression linéaire simple dans R. Rien de plus simple avec la fonction `lm(formula = y ~ x, data= DataFrame)`.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\ndf1 <- read.csv(\"data/bivariee/Reg.csv\", stringsAsFactors = FALSE)\n## Création d'un objet pour le modèle\nmonmodele <- lm(Velo ~ KmCV, df1)\n## Résultats du modèle avec la fonction summary\nsummary(monmodele)\n## Calcul du MSE et du RMSE\nMSE <- mean(monmodele$residuals^2)\nRMSE <- sqrt(MSE)\ncat(\"MSE = \", round(MSE, 2), \"; RMSE = \", round(RMSE,2), sep = \"\")\n```\n\n### Comment rapporter une régression linéaire simple {#sec-0445}\n\nNous avons calculé une régression linéaire simple pour prédire le pourcentage d'actifs occupés utilisant le vélo pour se rendre au travail en fonction de la distance entre la municipalité et le centre-ville de la région métropolitaine (en kilomètres). Le modèle obtient un *F* de Fisher significatif (*F*(1,8) = 34,75, *p* < 0,001) et un *R^2^* de 0,813. Le pourcentage de cyclistes peut être prédit par l'équation suivante : 30,603 - 1,448 x (distance au centre-ville en km).\n\n## Quiz de révision du chapitre {#sec-045}\n\n```{r}\n#| label: quizChapitre4\n#| echo: false\n#| warning: false\n#| results: asis\nsource(\"code_complementaire/QuizzFunctions.R\")\nChapitre4_QuantiQuanti <- quizz(\"quiz/Chapitre4_QuantiQuanti.yml\", \"Chapitre4_QuantiQuanti\")\nrender_quizz(Chapitre4_QuantiQuanti)\n```\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"04-bivarieeQuantiQuanti.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/05-bivarieeQualiQuali.qmd.json b/.quarto/idx/05-bivarieeQualiQuali.qmd.json new file mode 100644 index 0000000..2662af0 --- /dev/null +++ b/.quarto/idx/05-bivarieeQualiQuali.qmd.json @@ -0,0 +1 @@ +{"title":"Relation entre deux variables qualitatives","markdown":{"headingText":"Relation entre deux variables qualitatives","headingAttr":{"id":"sec-chap05","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans le cadre de ce chapitre, nous présentons les deux principales méthodes permettant d'explorer les associations entre deux variables qualitatives : la construction d'un tableau de contingence et le test du khi-deux ($\\chi^2$, appelé aussi khi carré).\n\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* `gmodels` pour construire des tableaux de contingence.\n* `vcd` pour construire un graphique pour un tableau de contingence.\n* `DescTools` pour calculer le khi-deux de Mantel-Haenszel.\n* `stargazer` pour imprimer des tableaux.\n:::\n:::\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Deux variables qualitatives sont-elles associées entre elles?** \n:::\n::: bloc_objectif-body\nPlus spécifiquement, certaines modalités d'une variable qualitative sont-elles associées significativement à certaines modalités d'une autre variable qualitative?\n\nPrenons l'exemple de deux variables qualitatives : l'une intitulée *groupe d'âge* comprenant trois modalités (15 à 29 ans, 30 à 44 ans, 45 à 64 ans); l'autre intitulée *mode de transport habituel pour se rendre au travail* comprenant quatre modalités (véhicule motorisé, transport en commun, vélo, marche). \n\nComparativement aux deux autres groupes, nous pourrions supposer que les jeunes se déplacent proportionnellement plus en modes de transport actif (vélo et marche) et en transport en commun. À l'inverse, il est possible que les 45 à 64 ans se déplacent majoritairement en véhicules motorisés.\n\nPour vérifier l'existence d'associations significatives entre les modalités de deux variables qualitatives, il est possible de construire un **tableau de contingence** ([section @sec-051]), puis de réaliser le **test du khi-deux** ([section @sec-052]).\n:::\n:::\n\n## Construction de tableau de contingence {#sec-051}\n\nLes données du tableau de contingence suivant décrivent 279 projets d'habitation à loyer modique (HLM) dans l'ancienne ville de Montréal, croisant les modalités de la période de construction (en colonne) et de la taille (en ligne) des projets HLM [@TheseApparicio]. Les différents éléments du tableau sont décrits ci-dessous.\n\n* **Les fréquences observées** (*Count* au tableau ci-dessous), nommées communément $f_{ij}$, correspondent aux observations appartenant à la fois à la *i^e^* modalité de la variable en ligne et à la *j^e^* modalité de la variable en colonne. À titre d’exemple, nous comptons 14 projets HLM construits entre 1985 et 1989 comprenant moins de 25 logements.\n\n* **Les marges** du tableau sont les totaux pour chaque modalité en ligne ($n_{i.}$) et en colonne ($n_{j.}$). En guise d’exemple, sur les 279 projets HLM, 53 comprennent de 25 à 49 logements et 56 ont été construites entre 1968 et 1974. Bien entendu, la somme des marges en ligne ($n_{i.}$) est égale au nombre total d'observations ($n_{ij}$), tout comme la somme de marges en colonne ($n_{.j}$).\n\n* **Trois pourcentages** sont disponibles (total, en ligne, en colonne; *Total Percent*, *Row Percent* et *Column Percent* au tableau ci-dessous). Ils sont respectivement la fréquence observée divisée par le nombre d'observations ($f_{ij}/n_{ij}\\times100$), par la marge en ligne ($f_{ij}/n_{i.} \\times 100$) et en colonne ($f_{ij}/n_{.j}\\times100$). En guise d'exemple, 5 % des 279 projets HLM ont été construites entre 1985 et 1989 et comprennent moins de 25 logements (pourcentage total, soit 14 / 279 × 100). Aussi, plus de la moitié des habitations de moins de 25 logements ont été construits entre 1990 et 1994 (pourcentage en ligne, 41 / 80 × 100). Finalement, près de 36 % des logements construits avant 1975 ont 100 logements et plus (20 / 56 × 100).\n\n* **Les fréquences théoriques** (*Expected Values* au tableau ci-dessous), représentent les valeurs que l'on devrait observer théoriquement s'il y avait indépendance entre les modalités des deux variables; autrement dit, si la répartition des deux modalités des deux variables était dû au hasard. Pour le croisement de deux modalités, la fréquence théorique est égale au produit des marges divisé par le nombre total d'observations ($ft_{ij} = (n_{i.}n_{.j})/n_{ij}$). Par exemple, la fréquence théorique pour le croisement des modalités *moins de 25 logements* et *avant 1975* est égale à : (80 × 56) / 279 = 16,06. Nous observons ici que la valeur théorique (16,06) est bien supérieure à la valeur réelle (6). Nous avons donc moins de projets HLM de moins de 25 logements avant 1975 auxquels nous pourrions nous attendre du hasard.\n\n* **La déviation** (*Residual* au tableau ci-dessous) est la différence entre la fréquence observée et la fréquence théorique ($f_{ij}-ft_{ij}$). Plus la déviation est grande, plus nous nous écartons d'une situation d'indépendance entre les deux modalités *i* et *j*. La somme des déviations sur une ligne ou sur une colonne est nulle. Si la déviation *ij* est nulle, la fréquence théorique est égale à la fréquence observée, ce qui signifie qu’il y a indépendance entre les modalités *i* et *j*. Une déviation positive traduit, quant à elle, une attraction entre les modalités *i* et *j* ou, autrement dit, une surreprésentation du phénomène *ij*; tandis qu’une déviation négative renvoie à une répulsion entre les modalités *i* et *j*, soit une sous-représentation du phénomène *ij*. Dans le cas précédent, nous observions six habitations de moins de 25 logements construits avant 1975 et une fréquence théorique de 16,06. La déviation est donc -10,06, soit une sous-représentation du phénomène.\n\n* **La contribution au khi-deux** (*Chi-square contribution* au tableau ci-dessous) est égale à la déviation au carré divisée par la fréquence théorique : $\\chi_{ij}^2 = (f_{ij}-ft_{ij})^2/ft_{ij}$. Plus sa valeur est forte, plus il y a association entre les deux modalités. La somme des contributions au khi-deux représente le khi-deux total pour l'ensemble du tableau de contingence (ici à 63,54), que nous aborderons dans la section suivante.\n\n\n```{r}\n#| label: tablecontingence\n#| echo: false\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nlibrary(\"gmodels\")\nTabKhi2 <- read.csv(\"data/bivariee/hlm.csv\")\n# Création d'un facteur pour les modalités de la période de construction\nTabKhi2$Periode <- factor(TabKhi2$Periode, \n levels = c(1,2,3,4,5), \n labels = c(\"Av. 1975\", \"1975-79\", \"1980-84\", \"1985-89\", \"1990-94\"))\n# Création d'un facteur pour les modalités de la taille\nTabKhi2$Taille <- factor(TabKhi2$Taille, \n levels = c(1,2,3,4), \n labels = c(\"< 25 log.\", \"25-49\", \"50-99\", \"100 et +\"))\n# Tableau de contingence en utilisant la fonction CrossTable du package gmodels\nCrossTable(TabKhi2$Taille, TabKhi2$Periode,\n expected = TRUE, chisq = TRUE, resid = TRUE, digits = 2, format=\"SPSS\")\n```\n\n## Test du khi-deux {#sec-052}\nAvec le test du khi-deux, nous postulons qu'il y a indépendance entre les modalités des deux variables qualitatives, soit l'hypothèse nulle (*H~0~*). Puis, nous calculons le nombre de degrés de liberté : $DL = (n-1)(l-1)$, avec $l$ et $n$ étant respectivement les nombres de modalités en ligne et en colonne. Pour notre tableau de contingence, nous avons 12 degrés de liberté : $(4-1)(5-1)=12$. \n\nÀ partir du nombre de degrés de liberté et d'un seuil critique de significativité (prenons 5 % ici), nous pouvons trouver la valeur critique de khi-deux dans la table des valeurs critiques du khi-deux, soit 21,03 ([section @sec-141]). Puisque la valeur du khi-deux calculée dans le tableau de contingence (63,54) est bien supérieure à celle obtenue dans le tableau des valeurs critiques (21,03), nous pouvons rejeter l'hypothèse d'indépendance au seuil de 5 %. Autrement dit, si les deux variables n'étaient pas associées, nous aurions eu moins de 5 % de chances de collecter des données avec ce niveau d'association, ce qui nous permet de rejeter l'hypothèse nulle (absence d'association). Notez que le test reste significatif avec des seuils de 1 % (*p* = 0,01) et 0,1 % (*p* = 0,001) puisque les valeurs critiques sont de 26,22 et de 32,91.\n\nBien entendu, une fois que nous connaissons le nombre de degrés de liberté, nous pouvons directement calculer les valeurs critiques pour différents seuils de signification et éviter ainsi de recourir à la table du du khi-deux. Dans la même veine, nous pouvons aussi calculer la valeur de *p* d'un tableau de contingence en spécifiant le nombre de degrés de liberté et la valeur du khi-deux obtenue.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\ncat(\"Valeurs critiques du khi-deux avec le nombre de degrés de liberté\", \"\\n\",\n round(qchisq(p=0.95, df=12, lower.tail = FALSE),3), \"avec p=0,05\", \"\\n\",\n round(qchisq(p=0.99, df=12, lower.tail = FALSE),3), \"avec p=0,01\", \"\\n\",\n round(qchisq(p=0.999, df=12, lower.tail = FALSE),3), \"avec p=0,0001\")\ncat(\"Valeur de p du khi-deux obtenu (63,54291) avec 12 degrés de liberté :\", \"\\n\",\n pchisq(q=63.54291, df=12, lower.tail = FALSE))\n```\n\n\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n\n**Autres mesures d'association**\n:::\n\n::: bloc_aller_loin-body\nOutre le khi-deux, d'autres mesures d'association permettent de mesurer le degré d'association entre deux variables qualitatives. Les plus courantes sont reportées dans le @tbl-EncadreAsso. À des fins de comparaison, le khi-deux décrit précédemment est aussi reporté sur la première ligne du tableau.\n\n\n```{r}\n#| label: tbl-EncadreAsso\n#| tbl-cap: Autres mesures d'association entre deux variables qualitatives\n#| echo: false\n#| message: false\n#| warning: false\n\nStatistique = c(\"Khi-deux\",\n \"Ratio de vraisemblance du khi-deux\",\n \"khi-deux de Mantel-Haenszel\",\n \"Corrélation polychorique\",\n \"Coefficient Phi\",\n \"V de Cramer\")\n \nFormule = c(\"$\\\\chi^2 = \\\\sum \\\\frac{(f_{ij}-ft_{ij})^2}{ft_{ij}}$\",\n \"$G^2 = 2 \\\\sum f_{ij} \\\\ln{(\\\\frac{f_{ij}}{ft_{ij}})}$\",\n \"$Q_{MH}=(N−1)r^2$\",\n \"Obtenue itérativement \\n par maximum de vraisemblance\",\n \"$\\\\phi=\\\\sqrt{\\\\frac{\\\\chi^2}{n}}$\",\n \"$V=\\\\sqrt{\\\\frac{\\\\chi^2/n}{min(c-1,l-1)}}$\")\n \nPropr = c(\n\"Mesure classique du khi-deux calculée à partir des différences entre les fréquences observées et attendues. Valeur de *p* disponible.\",\n\"Calculé à partir du ratio entre les fréquences observées et attendues. Valeur de *p* disponible.\",\n\"avec *r* étant le coefficient de corrélation entre les deux variables qualitatives; par exemple, entre les valeurs des modalités de 1 à 5 de la variable *période de construction* et celles de 1 à 4 de la variable *taille du projet* HLM. Ce coefficient est très utile quand les deux variables qualitatives ne sont pas nominales, mais **ordinales**. Valeur de *p* disponible.\",\n\"Dans le même esprit que le khi-deux de Mantel-Haenszel, la corrélation polychorique s'applique à deux variables **ordinales**. Plus spécifiquement, elle formule le postulat que deux variables théoriques normalement distribuées ont été mesurées de façon approximative avec deux échelles ordinales. Par exemple, en psychologie, le sentiment de bien-être et le sentiment de sécurité peuvent être conceptualisés comme deux variables continues normalement distribuées. Cependant, les mesurer directement est très difficile, nous avons donc recours à des échelles de Likert allant de 1 à 10. Pour cet exemple, il est pertinent d'utiliser la corrélation polychorique. Comme pour une corrélation de Pearson, la corrélation polychorique varie de -1 à 1, une valeur négative indiquant une relation inverse entre les deux variables théoriques et inversement. Valeur de *p* disponible.\",\n\"Simplement le khi-deux divisé par le nombre d'observations. Si les deux variables qualitatives comprennent deux modalités chacune alors $\\\\phi$ varie de −1 à 1; sinon, de 0 à $min(\\\\sqrt{c-1}, \\\\sqrt{l-1})$ avec *c* et *l* étant le nombre de modalités en colonne et en ligne. Par conséquent, ce coefficient est surtout utile pour les tableaux comprenant deux modalités pour chacune des variables. Pas de valeur de *p* disponible.\",\n\"Il représente un ajustement du coefficient Phi et varie de 0 à 1. Plus sa valeur est forte, plus les deux variables sont associées. À la lecture des deux formules, vous constaterez que, pour un tableau de 2x2, la valeur du V de Carmer sera égale à celle du Coefficient Phi. Pas de valeur de *p* disponible.\")\n\ndf <- data.frame(Stat=Statistique, Form=Formule, Pro=Propr)\n\nif(knitr::is_latex_output()){\n knitr::kable(df,\n col.names = c(\"Statistique\" , \"Formule\" , \"Propriété et interprétation\"),\n align= c(\"l\", \"l\", \"l\"),\n col.to.resize = c(1,3),\n col.width = c(\"2cm\" , \"8cm\")\n)\n \n}else{\n df[4,2] <- \"Obtenue itérativement par \\\\n maximum de vraisemblance\"\n knitr::kable(df,\n col.names = c(\"Statistique\" , \"Formule\" , \"Propriété et interprétation\"),\n align= c(\"l\", \"l\", \"l\"),\n caption = \"Autres mesures d'association entre deux variables qualitatives\",\n format = \"simple\"\n)\n}\n\n\n```\n:::\n:::\n\n\n\n\n## Mise en œuvre dans R {#sec-053}\n\nPour calculer le khi-deux entre deux variables qualitatives, nous utilisons la fonction de base : \n\n`chisq.test(x = ..., y = ...)` qui renvoie le nombre de degrés de liberté, les valeurs du khi-deux et de *p*.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Importation du csv\ndataHLM <- read.csv(\"data/bivariee/hlm.csv\")\n# Calcul du khi-deux avec la fonction de base chisq.test\nchisq.test(x = dataHLM$Taille, y = dataHLM$Periode)\n```\n\nPour la construction du tableau de contingence, deux options sont possibles dépendamment de la structure de votre tableau de données. Premier cas de figure : votre tableau comprend une ligne par observation avec les différentes modalités dans deux colonnes (ici *Periode* et *Taille*). Dans la syntaxe ci-dessous, pour chacune des deux variables qualitatives, nous créons un facteur afin de spécifier un intitulé à chaque modalité (`factor(levels =c(....), labels = c(..)`). Puis, nous utilisons la fonction `CrossTable` du *package* `gmodels`. Pour obtenir les fréquences théoriques, les contributions locales au khi-deux et les déviations, nous spécifions les options suivantes : `expected = TRUE, chisq=TRUE, resid=TRUE`.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(\"gmodels\")\n# Premiers enregistrements du tableau\nhead(dataHLM)\n# La variable Periode comprend 5 modalités (de 1 à 5)\ntable(dataHLM$Periode)\n# La variable Taille comprend 4 modalités (de 1 à 4)\ntable(dataHLM$Taille)\n# Création d'un facteur pour les cinq modalités de la période de construction\ndataHLM$Periode <- factor(dataHLM$Periode, \n levels = c(1,2,3,4,5), \n labels = c(\"<1975\", \n \"1975-1979\", \n \"1980-1984\", \n \"1985-1989\", \n \"1990-1994\"))\n# Création d'un facteur pour les quatre modalités de la taille des habitations\ndataHLM$Taille <- factor(dataHLM$Taille, \n levels = c(1,2,3,4), \n labels = c(\"<25 log.\", \n \"25-49\", \n \"50-99\", \n \"100 et +\"))\n# Pour construire un tableau de contingence, nous utilisons \n# la fonction CrossTable du package gmodels. \n# Les deux lignes ci-dessous sont mises en commentaire pour ne pas répéter le tableau.\n# CrossTable(x=dataHLM$Taille, y = dataHLM$Periode, digits = 2,\n# expected = TRUE, chisq = TRUE, resid = TRUE, format=\"SPSS\")\n```\n\nDeuxième cas de figure : vous disposez déjà d'un tableau de contingence, soit les fréquences observées ($f_{ij}$). Nous n'utilisons donc pas la fonction `CrossTable`, mais directement la fonction `chisq.test`.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Importation des données\ndf1 <- read.csv(\"data/bivariee/data_transport.csv\", stringsAsFactors = FALSE)\ndf1 # Visualisation du tableau\nMatrice <- as.matrix(df1[, c(\"Homme\" , \"Femme\")])\ndimnames(Matrice) <- list(unique(df1$ModeTransport), Sexe=c(\"Homme\" , \"Femme\"))\n# Notez que vous pouvez saisir vos données directement si vous avez peu d'observations\nFemme <- c(689400, 21315, 181435, 43715, 24295, 8395) # Vecteur de valeurs pour les femmes\nHomme <- c(561830, 40010, 238330, 54360, 13765, 6970) # Vecteur de valeurs pour les hommes\nMatrice <- as.table(cbind(Femme, Homme)) # Création du tableau\n# Nom des deux variables et de leurs modalités respectives\ndimnames(Matrice) <- list(Transport=c(\"Automobile (conducteur)\",\n \"Automobile (passager)\",\n \"Transport en commun\", \n \"À pied\",\n \"Bicyclette\",\n \"Autre moyen\"),\n Sexe=c(\"Homme\" , \"Femme\"))\n# Test du khi-deux\ntest <- chisq.test(Matrice)\nprint(test)\n# Fréquences observées (Fij)\ntest$observed\n# Fréquences théoriques (FTij)\nround(test$expected,0)\n# Déviations (Fij - FTij)\nround(test$observed-test$expected,0)\n# Contributions au khi-deux\nround((test$observed-test$expected)^2/test$expected,2)\n# Marges en ligne et en colonne\ncolSums(Matrice)\nrowSums(Matrice)\n# Grand total\nsum(Matrice)\n# Pourcentages\nround(Matrice/sum(Matrice)*100,2)\n# Pourcentages en ligne\nround(Matrice/rowSums(Matrice)*100,2)\n# Pourcentages en colonne\nround(Matrice/colSums(Matrice)*100,2)\n```\n\nPour obtenir les autres mesures d'association (@tbl-MesuresAssociations), nous pourrons utiliser la syntaxe suivante :\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| results: hide\ndf1 <- read.csv(\"data/bivariee/hlm.csv\")\n# Fonction pour calculer les autres mesures d'association\nAutresMesuresKhi2 <- function(x, y){\n testChi2 <- chisq.test(x, y) # Calcul du khi-deux\n n <- sum(testChi2$observed) # Nombre d'observations\n nc <- ncol(testChi2$observed) # Nombre de colonnes\n l <- nrow(testChi2$observed) # Nombre de lignes\n dl <- (nc-1)*(l-1) # Nombre de degrés de libertés\n chi2 <- testChi2$statistic # Valeur du khi-deux\n Pchi2 <- testChi2$p.value # P pour le khi-deux\n \n #Ratio de vraisemblance du khi-deux\n G <- 2*sum(testChi2$observed*log(testChi2$observed/testChi2$expected)) # G2\n PG <- pchisq(G, df=dl, lower.tail = FALSE) # P pour le G22\n \n # khi-deux de Mantel-Haenszel avec le package DescTools\n MHTest <- DescTools::MHChisqTest(testChi2$observed)\n MH <- MHTest$statistic\n PMH <- MHTest$p.value\n \n # Coefficient de correlation polychorique\n df1 <- data.frame(\"x\" = as.factor(x),\n \"y\" = as.factor(y))\n polychoricCorr <- correlation::cor_test(df1,\"x\" , \"y\", method = \"polychoric\")\n polyR <- polychoricCorr$rho\n polyP <- polychoricCorr$p\n\n # Coefficient Phi et V de Cramer\n phi <- sqrt(chi2/n)\n vc <- sqrt(chi2/(n*min(nc-1,l-1)))\n \n # Tableau pour les résultats\n dfsortie <- data.frame(\n Statistique = c(\"Khi-deux\", \n \"Ratio de vraisemblance du khi-deux\", \n \"Khi-deux de Mantel-Haenszel\",\n \"Corrélation Polychorique\",\n \"Coefficient de Phi\",\n \"V de Cramer\"), \n Valeur = round(c(chi2, G, MH, polyR, phi, vc),3), \n P = round(c(Pchi2, PG, PMH, polyP , NA, NA),10))\n return(dfsortie)\n}\n\ndfkhi2 <- AutresMesuresKhi2(df1$Periode, df1$Taille)\n\n# Impression du tableau avec le package stargazer\nlibrary(stargazer)\nstargazer(dfkhi2, type = \"text\", summary = FALSE, rownames = FALSE, align = FALSE, digits = 3,\n title = \"Mesures d'association entre les deux variables qualitatives\")\n\n```\n\n```{r}\n#| label: tbl-MesuresAssociations\n#| tbl-cap: Mesures d'association entre deux variables qualitatives\n#| echo: false\n#| message: false\n#| warning: false\noptions(knitr.kable.NA = \"\")\nknitr::kable(dfkhi2,\n digits = 3,\n align= c(\"l\", \"r\", \"r\"),\n )\n```\n\n## Interprétation d'un tableau de contingence {#sec-054}\n\nNous vous proposons une démarche très simple pour vérifier l'association entre deux variables qualitatives avec les deux étapes suivantes :\n\n* Nous posons l'hypothèse nulle (*H~0~*), soit l'indépendance entre les deux variables. \n\n* Si la valeur du khi-deux total du tableau de contingence est inférieure à la valeur critique du khi-deux avec *p* = 0,05 et le nombre de degrés de liberté de la table des valeurs critiques de khi-deux, alors il y a bien indépendance. La valeur de *p* est alors supérieure à 0,05. **L'analyse s'arrête donc là!** Autrement dit, il n'est pas nécessaire d'analyser le contenu de votre tableau de contingence puisqu'il n'y a pas d'association significative entre les modalités des deux variables. Vous pouvez simplement signaler que selon les résultats du test du khi-deux, il n'y a pas d'association significative entre les deux variables ($\\chi$ = ... avec *p* = ...).\n\n* S'il y a dépendance ($khi_{observé}^2 > khi_{critique}^2$), trouvez les cellules *ij* où les contributions au khi-deux sont les plus fortes, c'est-à-dire où les associations entre les modalités *i* de la variable en ligne et les modalités *j* de la variable en colonne sont les plus marquées. Pour ces cellules, le phénomène *ij* est surreprésenté si la déviation est positive ou sous-représenté si la déviation est négative. Commentez ces associations et utilisez les pourcentages en ligne ou en colonne pour appuyer vos propos.\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Repérer les contributions au khi-deux les plus importantes**\n:::\n::: bloc_astuce-body\nPour repérer rapidement les cellules où les contributions au khi-deux sont les plus fortes, vous pouvez construire un graphique avec la fonction `mosaic` du *package* `vcd`. À la @fig-VDC, la taille des rectangles représente les effectifs entre les deux modalités tandis que les associations sont représentées comme suit : \nen gris lorsqu'elles ne sont pas significatives, en rouge pour des déviations significatives et négatives et en bleu pour des déviations significatives et positives.\n\n```{r}\n#| label: fig-VDC\n#| echo: true\n#| fig-align: center\n#| out.width: \"65%\"\n#| fig-cap: Figure avec la fonction mosaic du package vcd\n#| message: false\n#| warning: false\n\nlibrary(vcd)\nmosaic(~ Taille+Periode, \n data = dataHLM, shade = TRUE, legend = TRUE,\n labeling = labeling_border(rot_labels = c(45, 90),\n just_labels = c(\"left\", \"center\")))\n```\n:::\n:::\n\n**Exemple d'interprétation.** « Les résultats du test du khi-deux signalent qu'il existe des associations entre les modalités de la taille et de la période de construction des projets d'habitation ($\\chi$ = 63,5, *p* < 0,001). Les fortes contributions au khi-deux et le signe positif ou négatif des déviations correspondantes permettent de repérer cinq associations majeures entre les modalités de taille et de période de construction des projets HLM : **1)** la répulsion entre les projets d’habitation de moins de 25 logements et la période de construction 1964-1974; **2)** l’attraction entre les projets d’habitation de 100 logements et plus et la période de construction de 1969-1974; **3)** l’attraction entre les projets d’habitation de moins de 25 logements et la période de construction de 1990-1994; **4)** la répulsion entre les projets d’habitation de 50 à 99 logements et la période de construction 1990-1994; **5)** la répulsion entre les projets d’habitation de 100 logements et plus et la période de construction 1990-1994.\nOn observe donc une tendance bien marquée dans l’évolution du type de construction entre 1970 et 1994 : entre 1969 et 1974, on a construit de grandes habitations dépassant souvent 100 logements; du milieu des années 1970 à la fin des années 1980, on privilégie la construction d’habitations de taille plus modeste, entre 50 et 100 logements; tandis qu’au début des années 1990, on opte plutôt pour des habitations de taille réduite (moins de 50 logements). Quelques chiffres à l’appui : sur les 56 habitations réalisées entre 1969 et 1974, 20 ont plus de 100 logements, 20 comprennent entre 50 et 99 logements et seules 10 ont moins de 25 logements. Près de la moitié des habitations construites entre 1975 et 1989 regroupent 50 à 99 logements (43,8 % pour la période 1975-1979, 45,8 % pour 1980-1984 et 44,7 % pour 1985-1989). Par contre, 51 % des habitations érigés à partir de 1990 disposent de moins de 25 logements » (@TheseApparicio, p. 117-118). Notez que cette évolution décroissante est aussi soutenue par le coefficient négatif de la corrélation polychorique.\n\nVous pouvez aussi construire un graphique pour appuyer vos constats, soit avec les pourcentages en ligne ou en colonne (@fig-hml tirée de @TheseApparicio).\n\n\n![Taille des projets d'habitation à loyer modique selon la période de construction](images/Chap05/figurehlm.png){#fig-hml width=\"80%\" fig-align=\"center\"}\n\n\n**Comment rapporter succinctement les résultats d'un test du khi-deux?**\n\nLe test du khi-deux a été réalisé pour examiner la relation entre la taille et la période de construction des habitations HLM. Cette relation est significative : $\\chi^2$(12, N = 279) = 63,5, *p* < 0,001. Plus les projets ont été construites récemment, plus ils sont de taille réduite.\n\nPour un texte en anglais, consultez [https://www.socscistatistics.com/tutorials/chisquare/default.aspx](https://www.socscistatistics.com/tutorials/chisquare/default.aspx){target=\"_blank\"}.\n\n## Quiz de révision du chapitre {#sec-055}\n\n```{r}\n#| label: quizChapitre5\n#| echo: false\n#| warning: false\n#| results: asis\nsource(\"code_complementaire/QuizzFunctions.R\")\nChapitre5_QualiQuali <- quizz(\"quiz/Chapitre5_QualiQuali.yml\", \"Chapitre5_QualiQuali\")\nrender_quizz(Chapitre5_QualiQuali)\n```\n\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"05-bivarieeQualiQuali.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/06-bivarieeQualiQuanti.qmd.json b/.quarto/idx/06-bivarieeQualiQuanti.qmd.json new file mode 100644 index 0000000..fcfa0ef --- /dev/null +++ b/.quarto/idx/06-bivarieeQualiQuanti.qmd.json @@ -0,0 +1 @@ +{"title":"Relation entre une variable qualitative et une variable quantitative","markdown":{"headingText":"Relation entre une variable qualitative et une variable quantitative","headingAttr":{"id":"sec-chap06","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans le cadre de ce chapitre, nous présentons les principales méthodes permettant d'explorer les associations entre une variable quantitative et une variable qualitative avec deux modalités (tests de Student, de Welch et de Wilcoxon) ou avec plus de deux modalités (ANOVA et test de Kruskal-Wallis).\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l’unique!\n - `ggpubr` pour combiner des graphiques.\n* Pour manipuler des données : \n - `dplyr`, avec les fonctions `group_by`, `summarize` et les pipes `%>%`.\n* Pour les test *t* : \n - `sjstats` pour réaliser des tests *t* pondérés.\n - `effectsize` pour calculer les tailles d'effet de tests *t*.\n* Pour la section sur les ANOVA : \n - `car` pour les ANOVA classiques.\n - `lmtest` pour le test de Breusch-Pagan d'homogénéité des variances.\n - `rstatix` intégrant de nombreux tests classiques (comme le test de Shapiro) avec `tidyverse`.\n* Autre *package* : \n - `foreign` pour importer des fichiers externes.\n:::\n:::\n\n\n## Relation entre une variable quantitative et une variable qualitative à deux modalités {#sec-061}\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Les moyennes de deux groupes de population sont-elles significativement différentes?**\n:::\n::: bloc_objectif-body\nNous souhaitons ici comparer deux groupes de population en fonction d'une variable continue. \nPar exemple, pour deux échantillons respectivement d'hommes et de femmes travaillant dans le même secteur d'activité, nous pourrions souhaiter vérifier si les moyennes des salaires des hommes et des femmes sont différentes et ainsi vérifier la présence ou l'absence d'une iniquité systématique. En études urbaines, dans le cadre d'une étude sur un espace public, nous pourrions vouloir vérifier si la différence des moyennes du sentiment de sécurité des femmes et des hommes est significative (c'est-à-dire différente de 0).\n\n**Pour un même groupe, la moyenne de la différence d'un phénomène donné mesuré à deux moments est-elle ou non égale à zéro?** \n\nAutrement dit, nous cherchons à comparer un même groupe d'individus avant et après une expérimentation ou dans deux contextes différents. Prenons un exemple d'application en études urbaines. Dans le cadre d'une étude sur la perception des risques associés à la pratique du vélo en ville, 50 personnes utilisant habituellement l'automobile pour se rendre au travail sont recrutées. L'expérimentation pourrait consister à leur donner une formation sur la pratique du vélo en ville et à les accompagner quelques jours durant leurs déplacements domicile-travail. Nous évaluerons la différence de leurs perceptions des risques associés à la pratique du vélo sur une échelle de 0 à 100 avant et après l'expérimentation. Nous pourrions supposer que la moyenne des différences est significativement négative, ce qui indiquerait que la perception du risque a diminué après l'expérimentation; autrement dit, la perception du risque serait plus faible en fin de période. \n:::\n:::\n\n\n\n### Test *t* et ses différentes variantes {#sec-0611}\n\nLe **t de Student**, appelé aussi **test _t_** (*t-test* en anglais), est un test paramétrique permettant de comparer les moyennes de deux groupes (échantillons), qui peuvent être indépendantes ou non :\n\n* **Échantillons indépendants (dits non appariés)** : les observations de deux groupes qui n'ont aucun lien entre eux. Par exemple, nous souhaitons vérifier si les moyennes du sentiment de sécurité des hommes et des femmes, ou encore si, les moyennes des loyers entre deux villes sont statistiquement différentes. Ainsi, les tailles des deux échantillons peuvent être différentes ($n_a \\neq n_b$).\n\n* **Échantillons dépendants (dits appariés)** : les individus des deux groupes sont les mêmes et sont donc associés par paires. Autrement dit, nous avons deux séries de valeurs de taille identique $n_a = n_b$ et $n_{ai}$ est le même individu que $n_{bi}$. Ce type d'analyse est souvent utilisée en études cliniques : pour $n$ individus, nous disposons d'une mesure quantitative de leur état de santé pour deux séries (l'une avant le traitement, l'autre une fois le traitement terminé). Cela permet de comparer les mêmes individus avant et après un traitement; nous parlons alors d'étude, d'expérience ou d'analyse pré-post. Concrètement, nous cherchons à savoir si la moyenne des différences des observations avant et après est significativement différente de 0. Si c'est le cas, nous pouvons conclure que l'expérimentation a eu un impact sur le phénomène mesuré (variable continue). Ce type d'analyse pré-post peut aussi être utilisé pour évaluer l'impact du réaménagement d'un espace public (rue commerciale, place publique, parc, etc.). Par exemple, nous pourrions questionner le même échantillon de commerçant(e)s ou personnes l'utilisant avant et après le réaménagement d'une artère commerciale.\n\n**Condition d'application**. Pour utiliser les tests de Student et de Welch, la variable continue doit être normalement distribuée. Si elle est fortement anormale, nous utiliserons le test non paramétrique de Wilcoxon ([section @sec-0612]). Il existe trois principaux tests pour comparer les moyennes de deux groupes :\n\n* Test de Student (test *t*) avec échantillons indépendants et variances similaires (méthode *pooled*). Les variances de deux groupes sont semblables quand leur ratio varie de 0,5 à 2, soit $\\mbox{0,5}< (S^2_{X_A}/S^2_{X_B})<\\mbox{2}$.\n\n* Test de Welch (appelé aussi Satterthwaite) avec échantillons indépendants quand les variances des deux groupes sont dissemblables.\n\n* Test de Student (test *t*) avec échantillons dépendants.\n\nIl s'agit de vérifier si les moyennes des deux groupes sont statistiquement différentes avec les étapes suivantes :\n\n* Nous posons l'hypothèse nulle (*H~0~*), soit que les moyennes des deux groupes *A* et *B* ne sont pas différentes ($\\bar{X}_{A}=\\bar{X}_{B}$) ou, autrement dit, la différence des deux moyennes est nulle ($\\bar{X}_{A}-\\bar{X}_{B}=0$). L'hypothèse alternative (*H~1~*) est donc $\\bar{X}_{A}\\ne\\bar{X}_{B}$.\n\n* Nous calculons la valeur de *t* et le nombre de degrés de liberté. La valeur de *t* est négative quand la moyenne du groupe A est inférieure au groupe B et inversement.\n\n* Nous comparons la valeur absolue de *t* ($\\mbox{|t|}$) avec celle issue de la table des valeurs critiques de T ([section @sec-132]) avec le bon nombre de degrés de liberté et en choisissant un degré de signification (habituellement, *p* = 0,05). Si $\\mbox{|t|}$ est supérieure à la valeur *t* critique, alors les moyennes sont statistiquement différentes au degré de signification retenu.\n\n* Si les moyennes sont statistiquement différentes, nous pouvons calculer la taille de l'effet.\n\n\n**Cas 1. Test de Student pour des échantillons indépendants avec des variances similaires (méthode *pooled*).** La valeur de *t* est le ratio entre la différence des moyennes des deux groupes (numérateur) et l'erreur type groupée des deux échantillons (dénominateur) :\n\n$$\nt = \\frac{\\bar{X}_{A}-\\bar{X}_{B}}{\\sqrt{\\frac{S^2_p}{n_A}+\\frac{S^2_p}{n_B}}}\\mbox{ avec } S^2_p = \\frac{(n_A-1)S^2_{X_A}+(n_B-1)S^2_{X_B}}{n_A+n_B-2}\n$$ {#eq-cas1pooled}\n\n\navec $n_A$,$n_B$, $S^2_{X_A}$ et $S^2_{X_B}$ étant respectivement les nombres d'observations et les variances pour les groupes *A* et *B*, $S^2_p$ étant la variance groupée des deux échantillons et $n_A+n_B-2$ étant le nombre de degrés de liberté.\n\n**Cas 2. Test de Welch pour des échantillons indépendants (avec variances dissemblables).** Le test de Welch est très similaire au test de Student; seul le calcul de la valeur de _t_ est différent, pour tenir compte des variances respectives des groupes :\n\n$$\nt = \\frac{\\bar{X}_{A}-\\bar{X}_{B}}{\\sqrt{\\frac{S^2_{X_A}}{n_A}+\\frac{S^2_{X_B}}{n_B}}} \\mbox{ et } dl = \\frac{ \\left( \\frac{S^2_{X_A}}{n_A}+\\frac{S^2_{X_B}}{n_B} \\right)^2} {\\frac{S^4_{X_A}}{n^2_A(n_A-1)}+\\frac{S^4_{X_B}}{n^2_B(n_B-1)}}\n$$ {#eq-cas2welch}\n\nDans la syntaxe ci-dessous, nous avons écrit une fonction dénommée `test_independants` permettant de calculer les deux tests pour des échantillons indépendants. Dans cette fonction, vous pouvez repérer comment sont calculés les moyennes, les nombres d'observations et les variances pour les deux groupes, le nombre de degrés de liberté et les valeurs de *t* et de *p* pour les deux tests. Puis, nous avons créé aléatoirement deux jeux de données relativement à la vitesse de déplacement de cyclistes utilisant un vélo personnel ou un vélo en libre-service (généralement plus lourd) :\n\n* Au cas 1, 60 cyclistes utilisant un vélo personnel roulant en moyenne à 18 km/h (écart-type de 1,5) et 50 autres utilisant un système de vélopartage avec une vitesse moyenne de 15 km/h (écart-type de 1,5).\n\n* Au cas 2, 60 cyclistes utilisant un vélo personnel roulant en moyenne à 16 km/h (écart-type de 3) et 50 autres utilisant un système de vélopartage avec une vitesse moyenne de 15 km/h (écart-type de 1,5). Ce faible écart des moyennes, combiné à une plus forte variance réduit la significativité de la différence entre les deux groupes.\n\nD'emblée, l'analyse visuelle des boîtes à moustaches (@fig-ttest1) signale qu'au cas 1, contrairement au cas 2, les groupes sont plus homogènes (boîtes plus compactes) et les moyennes semblent différentes (les boîtes sont centrées différemment sur l'axe des ordonnées). Cela est confirmé par les résultats des tests.\n\n```{r}\n#| label: fig-ttest1\n#| echo: true\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Boîtes à moustaches sur des échantillons fictifs non appariés\n#| out-width: \"75%\"\nlibrary(\"ggplot2\")\nlibrary(\"ggpubr\")\n# fonction ------------------\ntstudent_independants <- function(A, B){\n x_a <- mean(A) # Moyenne du groupe A\n x_b <- mean(B) # Moyenne du groupe B\n var_a <- var(A) # Variance du groupe A\n var_b <- var(B) # Variance du groupe B\n sd_a <- sqrt(var_a) # Écart-type du groupe A\n sd_b <- sqrt(var_b) # Écart-type du groupe B\n ratio_v <- var_a / var_b # ratio des variances\n n_a <- length(A) # nombre d'observation du groupe A\n n_b <- length(B) # nombre d'observation du groupe B\n \n # T-test (variances égales)\n dl_test <- n_a+n_b-2 # degrés de liberté\n PooledVar <- (((n_a-1)*var_a)+((n_b-1)*var_b))/dl_test\n t_test <- (x_a-x_b) / sqrt(((PooledVar/n_a)+(PooledVar/n_b)))\n p_test <- 2*(1-(pt(abs(t_test), dl_test))) \n # Test Welch-Sattherwaite (variances inégales)\n t_welch <- (x_a-x_b) / sqrt( (var_a/n_a) + (var_b/n_b))\n dl_num = ((var_a/n_a) + (var_b/n_b))^2\n dl_dem = ((var_a/n_a)^2/(n_a-1)) + ((var_b/n_b)^2/(n_b-1))\n dl_welch = dl_num / dl_dem # degrés de liberté\n p_welch <- 2*(1-(pt(abs(t_welch), dl_welch))) \n \n cat(\"\\n groupe A (n = \", n_a,\"), moy = \", round(x_a,1),\", \n variance = \", round(var_a,1),\", écart-type = \", round(sd_a,1),\n \"\\n groupe B (n = \", n_b,\"), moy = \", round(x_b,1),\", \n variance = \", round(var_b,1),\", écart-type = \", round(sd_b,1),\n \"\\n ratio variance = \", round(ratio_v,2),\n \"\\n t-test (variances égales): t(dl = \", dl_test, \") = \", round(t_test,4),\n \", p = \", round(p_test,6),\n \"\\n t-Welch (variances inégales): t(dl = \", round(dl_welch,3), \") = \",\n round(t_welch,4), \", p = \", round(p_welch,6), sep = \"\") \n \n if (ratio_v > 0.5 && ratio_v < 2) {\n cat(\"\\n Variances semblables. Utilisez le test de Student!\")\n p <- p_test\n } else {\n cat(\"\\n Variances dissemblables. Utilisez le test de Welch-Satterwaithe!\")\n p <- p_welch\n }\n \n if (p <=.05){\n cat(\"\\n Les moyennes des deux groupes sont significativement différentes.\")\n } else {\n cat(\"\\n Les moyennes des deux groupes ne sont pas significativement différentes.\")\n }\n}\n# CAS 1 : données fictives ------------------\n# Création du groupe A : 60 observations avec une vitesse moyenne de 18 et un écart-type de 1,5\nVelo1A <- rnorm(60,18,1.5)\n# Création du groupe B : 50 observations avec une vitesse moyenne de 15 et un écart-type de 1,5\nVelo1B <- rnorm(50,15,1.5)\ndf1 <- data.frame(\n vitesse = c(Velo1A,Velo1B), \n type = c(rep(\"Vélo personnel\", length(Velo1A)), rep(\"Vélopartage\", length(Velo1B)))\n)\nboxplot1 <- ggplot(data = df1, mapping=aes(x = type, y = vitesse, colour = type)) +\n geom_boxplot(width=0.2)+\n ggtitle(\"Données fictives (cas 1)\")+\n xlab(\"Type de vélo\")+\n ylab(\"Vitesse de déplacement (km/h)\")+\n theme(legend.position = \"none\")\n# CAS 2 : données fictives ------------------\n# Création du groupe A : 60 observations avec une vitesse moyenne de 18 et un écart-type de 3\nVelo2A <- rnorm(60,16,3)\n# Création du groupe B : 50 observations avec une vitesse moyenne de 15 et un écart-type de 1,5\nVelo2B <- rnorm(50,15,1.5)\ndf2 <- data.frame(\n vitesse = c(Velo2A,Velo2B), \n type = c(rep(\"Vélo personnel\", length(Velo2A)), rep(\"Vélopartage\", length(Velo2B)))\n)\nboxplot2 <- ggplot(data = df2, mapping=aes(x = type, y = vitesse, colour = type)) +\n geom_boxplot(width=0.2)+\n ggtitle(\"Données fictives (cas 2)\")+\n xlab(\"Type de vélo\")+\n ylab(\"Vitesse de déplacement (km/h)\")+\n theme(legend.position = \"none\")\nggarrange(boxplot1, boxplot2, ncol = 2, nrow = 1)\n# Appel de la fonction pour le cas 1\ntstudent_independants(Velo1A, Velo1B)\n# Appel de la fonction pour le cas 2\ntstudent_independants(Velo2A, Velo2B)\n```\n\n\n#### Principe de base et formulation pour des échantillons dépendants (appariés) {#sec-06111}\n\nNous disposons de plusieurs personnes pour lesquelles nous avons mesuré un phénomène (variable continue) à deux temps différents : généralement avant et après une expérimentation (analyse pré-post). Il s'agit de vérifier si la moyenne des différences des observations avant et après la période est différente de 0. Pour ce faire, nous réalisons les étapes suivantes :\n\n* Nous posons l'hypothèse nulle (*H~0~*), soit que la moyenne des différences entre les deux séries est égale à 0 ($\\bar{D} = 0$ avec $d = {x}_{t_1}- {x}_{t_2}$). L'hypothèse alternative (*H~1~*) est donc $\\bar{D} \\ne 0$. Notez que nous pouvons tester une autre valeur que 0.\n\n* Nous calculons la valeur de *t* et le nombre de degrés de liberté. La valeur de *t* est négative quand la moyenne des différences entre ${X}_{t_1}$ et ${X}_{t_2}$ est négative et inversement.\n\n* Nous comparons la valeur absolue de *t* ($\\mbox{|t|}$) avec celle issue de la table des valeurs critiques de T avec le nombre de degrés de liberté et en choisissant un degré de signification (habituellement, *p* = 0,05). Si $\\mbox{|t|}$ est supérieure à la valeur *t* critique, alors les moyennes sont statistiquement différentes au degré de signification retenu.\n\nPour le test de Student avec des échantillons appariés, la valeur de *t* se calcule comme suit :\n\n$$\nt = \\frac{\\bar{D}-\\mu_0}{\\sigma_D / \\sqrt{n}}\n$$ {#eq-ttestapparie}\n\n\navec $\\bar{D}$ étant la moyenne des différences entre les observations appariées de la série A et de la série B, $\\sigma_D$ l'écart des différences, *n* le nombre d'observations, et finalement $\\mu_0$ la valeur de l'hypothèse nulle que nous voulons tester (habituellement 0). Bien entendu, il est possible de fixer une autre valeur pour $\\mu_0$ : par exemple, avec $\\mu_0 = 10$, nous chercherions ainsi à vérifier si la moyenne des différences est significativement différente de 10. Le nombre de degrés de liberté est égal à $n-1$.\n\nDans la syntaxe ci-dessous, nous avons écrit une fonction dénommée `tstudent_dependants` permettant de réaliser le test de Student pour des échantillons appariés. Dans cette fonction, vous pouvez repérer comment sont calculés la différence entre les observations pairées, la moyenne et l'écart-type de cette différence, puis le nombre de degrés de liberté, les valeurs de *t* et de *p* pour les deux tests.\n\nPour illustrer l'utilisation de la fonction, nous avons créé aléatoirement deux jeux de données. Imaginons que ces données décrivent 50 personnes utilisant habituellement l'automobile pour se rendre au travail. Pour ces personnes, nous avons généré des valeurs du risque perçu de l'utilisation du vélo (de 0 à 100), et ce, avant et après une période de 20 jours ouvrables durant lesquels elles devaient impérativement se rendre au travail à vélo.\n\n* Au cas 1, les valeurs de risque ont une moyenne de 70 avant l'expérimentation et de 50 après l'expérimentation, avec des écarts-types de 5.\n\n* Au cas 2, les valeurs de risque ont une moyenne de 70 avant et de 66 après, avec des écarts-types de 5.\n\nD'emblée, l'analyse visuelle des boîtes à moustaches (@fig-ttest2) pairées montre que la perception du risque semble avoir nettement diminué après l'expérimentation pour le cas 1, mais pas pour le cas 2. Cela est confirmé par les résultats des tests.\n\n\n```{r}\n#| label: fig-ttest2\n#| echo: true\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Boites à moustaches sur des échantillons fictifs appariés\n#| out-width: \"75%\"\nlibrary(\"ggplot2\")\nlibrary(\"ggpubr\")\ntstudent_dependants <- function(A, B, mu = 0){\n d <- A-B # différences entre les observations pairées\n moy <- mean(d) # Moyenne des différences\n e_t <- sd(d) # Écart-type des différences\n n <- length(A) # nombre d'observations\n dl <- n-1 # nombre de degrés de liberté (variances égales)\n \n t <- (moy- mu) / (e_t/sqrt(n)) # valeur de t\n p <- 2*(1-(pt(abs(t), dl)))\n \n cat(\"\\n groupe A : moy = \", round(mean(A),1),\", var = \", \n round(var(A),1),\", sd = \", round(sqrt(var(A)),1),\n \"\\n groupe B : moy = \", round(mean(B),1),\", var = \", \n round(var(B),1),\", sd = \", round(sqrt(var(B)),1),\n \"\\n Moyenne des différences = \", round(mean(moy),1),\n \"\\n Ecart-type des différences = \", round(mean(e_t),1),\n \"\\n t(dl = \", dl, \") = \", round(t,2),\n \", p = \", round(p,3), sep = \"\")\n \n if (p <=.05){\n cat(\"\\n La moyenne des différences entre les échantillons est significative\")\n }\n else{\n cat(\"\\n La moyenne des différences entre les échantillons n'est pas significative\")\n }\n}\n# CAS 1 : données fictives ------------------\nAvant1 <- rnorm(50,70,5)\nApres1 <- rnorm(50,50,5)\ndf1 <- data.frame(Avant=Avant1, Apres=Apres1)\nboxplot1 <- ggpaired(df1, cond1 = \"Avant\", cond2 = \"Apres\", fill = \"condition\", \n palette = \"jco\", \n xlab = \"\", ylab = \"Sentiment de sécurité\", \n title = \"Données fictives (cas 1)\")\n# CAS 2 : données fictives ------------------\nAvant2 <- rnorm(50,70,5)\nApres2 <- rnorm(50,66,5)\ndf2 <- data.frame(Avant=Avant2, Apres=Apres2)\nboxplot2 <- ggpaired(df2, cond1 = \"Avant\", cond2 = \"Apres\", fill = \"condition\",\n palette = \"jco\", \n xlab = \"\", ylab = \"Sentiment de sécurité\", \n title = \"Données fictives (cas 2)\")\nggarrange(boxplot1, boxplot2, ncol = 2, nrow = 1)\n# Test t : appel de la fonction tstudent_dependants\ntstudent_dependants(Avant1, Apres1, mu = 0)\ntstudent_dependants(Avant2, Apres2, mu = 0)\n```\n\n\n#### Mesure de la taille de l'effet {#sec-06112}\n\nLa taille de l'effet permet d'évaluer la magnitude (force) de l'effet d'une variable (ici la variable qualitative à deux modalités) sur une autre (ici la variable continue). Dans le cas d'une comparaison de moyennes (avec des échantillons pairés ou non), pour mesurer la taille de l'effet, nous utilisons habituellement le *d* de Cohen ou encore le *g* de Hedges; le second étant un ajustement du premier. Notez que nous analysons la taille de l'effet uniquement si le test de Student ou de Welch s'est révélé significatif (p < 0,05).\n\n**Pourquoi utiliser le *d* de Cohen?** Deux propriétés en font une mesure particulièrement intéressante. Premièrement, elle est facile à calculer puisque *d* est le ratio entre la différence de deux moyennes de groupes (A, B) et l'écart-type combiné des deux groupes. Deuxièmement, *d* représente ainsi une mesure standardisée de la taille de l'effet; elle permet ainsi l'évaluation de la taille de l'effet indépendamment de l'unité de mesure de la variable continue. Concrètement, cela signifie que, quelle que soit l'unité de mesure de la variable continue *X*, *d* est toujours exprimée en unité d'écart-type de *X*. Cette propriété facilite ainsi grandement les comparaisons entre des valeurs de *d* calculées sur différentes combinaisons de variables (au même titre que le coefficient de variation ou le coefficient de corrélation, par exemple). Pour des échantillons indépendants de tailles différentes, le *d* de Cohen s'écrit : \n\n\n$$\n\\frac{\\bar{X}_{A}-\\bar{X}_{B}}{\\sqrt{\\frac{(n_A-1)S^2_A+(n_B-1)S^2_B}{n_A+n_B-2}}}\n$$ {#eq-dcohen}\n\navec $n_A$, $n_B$, $S^2_{X_A}$ et $S^2_{X_B}$ étant respectivement les nombres d'observations et les variances pour les groupes *A* et *B*, $S^2_p$.\n\nSi les échantillons sont de tailles identiques ($n_A=n_B$), alors *d* s'écrit :\n\n\n$$\nd = \\frac{\\bar{X}_{A}-\\bar{X}_{B}}{\\sqrt{(S^2_A+\\S^2_B)/2}} = \\frac{\\bar{X}_{A}-\\bar{X}_{B}}{(\\sigma_A+\\sigma_B)/2}\n$$ {#eq-dcohen2}\n\n\navec $\\sigma_A$ et $\\sigma_B$ étant les écarts-types des deux groupes (rappel : l'écart-type est la racine carrée de la variance).\n\nLe *g* de Hedge est simplement une correction de *d*, particulièrement importante quand les échantillons sont de taille réduite.\n\n$$\ng = d- \\left(1- \\frac{3}{4(n_A+n_B)-9} \\right)\n$$ {#eq-ghedge}\n\n\nMoins utilisé en sciences sociales, mais surtout en études cliniques, le delta de Glass est simplement la différence des moyennes des deux groupes indépendants (numérateur) sur l'écart-type du deuxième groupe (dénominateur). Dans une étude clinique, nous avons habituellement un groupe qui subit un traitement (groupe de traitement) et un groupe qui reçoit un placebo (groupe de contrôle ou groupe témoin). L'effet de taille est ainsi évalué par rapport au groupe de contrôle : \n\n$$\n\\Delta = \\frac{\\bar{X}_{A}-\\bar{X}_{B}}{\\sigma_B}\n$$ {#eq-dDelta}\n\nFinalement, pour des échantillons dépendants (pairés), le delta de Glass s'écrit : $d = \\bar{D}/{\\sigma_D}$ avec $\\bar{D}$ et $\\sigma_D$ étant la moyenne et l'écart-type des différences entre les observations.\n\n**Comment interpréter le *d* de Cohen?** Un effet est considéré comme faible avec $\\lvert d \\rvert$ à 0,2, modéré à 0,50 et fort à 0,80 [@cohen1992]. Notez que ces seuils ne sont que des conventions pour vous guider à interpréter la mesure de Cohen. D'ailleurs, dans son livre intitulé *Statistical power analysis for the behavioral sciences*, il écrit : « all conventions are arbitrary. One can only demand of them that they not be unreasonable » [@cohen2013]. Plus récemment, Sawilowsky [-@sawilowsky2009] a ajouté d'autres seuils à ceux proposés par Cohen (@tbl-convcohen).\n\n```{r}\n#| label: tbl-convcohen\n#| tbl-cap: Conventions pour l’interprétation du *d* de Cohen\n#| echo: false\n#| message: false\n#| warning: false\ndf <- data.frame(\n Sawilowsky = c(\"0,1 : Très faible\", \"0,2 : Faible\", \"0,5 : Moyen\" , \"0,8 : Fort\", \"1,2 : Très fort\", \"2,0 : Énorme\"), \n Cohen = c(\"\", \"0,2 : Faible\", \"0,5 : Moyen\" , \"0,8 : Fort\", \"\", \"\"))\n\nknitr::kable(df,\n position = 'HOLD_position',\n align= c(\"l\", \"l\")\n )\n```\n\n\n#### Mise en œuvre dans R {#sec-06113}\n\nNous avons écrit précédemment les fonctions `tstudent_independants` et `tstudent_dependants` uniquement pour décomposer les différentes étapes de calcul des tests de Student et de Welch. Heureusement, il existe des fonctions de base (`t.test` et `var.test`) qui permettent de réaliser l'un ou l'autre de ces deux tests avec une seule ligne de code.\n\nLa fonction `t.test` permet ainsi de calculer les tests de Student et de Welch :\n\n* `t.test(x ~ y, data=, mu = 0, paired = FALSE, var.equal = FALSE, conf.level = 0.95)` ou `t.test(x =, y =, mu = 0, paired = FALSE, var.equal = FALSE, conf.level = 0.95)`. \n\n* Le paramètre `paired` est utilisé pour spécifier si les échantillons sont dépendants (`paired = TRUE`) ou indépendants (`paired = FALSE`).\n\n* Le paramètre `var.equal` est utilisé pour spécifier si les variances sont égales pour le test de Student (`var.equal = TRUE`) ou dissemblables pour le test de Welch (`var.equal = FALSE`).\n\n* `var.test(x, y)` ou `var.test(x ~ y, data=)` pour vérifier au préalable si les variances sont égales ou non et choisir ainsi un *t* de Student ou un *t* de Welch.\n\nLes fonctions `cohens_d` et `hedges_g` du *package* `effectsize` renvoient respectivement les mesures de *d* de Cohen et du *g* de Hedge :\n\n* `cohens_d(x ~ y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)` ou `cohens_d(x, y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)`\n\n* `hedges_g(x ~ y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)` ou `hedges_g(x, y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)`\n\n* `glass_delta(x ~ y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)` ou `glass_delta(x, y, data = DataFrame, paired = FALSE, pooled_sd = TRUE)`\n\n\nNotez que pour toutes ces fonctions, deux écritures sont possibles :\n\n* `x ~ y, data=` avec un `DataFrame` dans lequel `x` est une variable continue et `y` et un facteur binaire\n\n* `x, y` qui sont tous deux des vecteurs numériques (variable continue).\n\n**Exemple de test pour des échantillons indépendants**\n\nLa @fig-locataires représente la cartographie du pourcentage de locataires par secteur de recensement (SR) pour la région métropolitaine de recensement de Montréal (RMR) en 2016, soit une variable continue. L'objectif est de vérifier si la moyenne de ce pourcentage des SR de l'agglomération de Montréal est significativement différente de celles de SR hors de l'agglomération. \n\n\n![Pourcentage de locataires par secteur de recensement, région métropolitaine de recensement de Montréal, 2016](images/Chap06/FigureLocataires.jpg){#fig-locataires width=\"90%\" fig-align=\"center\"}\n\nLes résultats de la syntaxe ci-dessous signalent que le pourcentage de locataires par SR est bien supérieur dans l'agglomération (moyenne = 59,7 %; écart-type = 21,4 %) qu'en dehors de l'agglomération de Montréal (moyenne = 27,3 %; écart-type = 20,1 %). Cette différence de 32,5 points de pourcentage est d'ailleurs significative et très forte (*t* = -23,95; *p* < 0,001, d de Cohen = 1,54).\n\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n#| fig-align: center\n\nlibrary(\"foreign\")\nlibrary(\"effectsize\")\nlibrary(\"ggplot2\")\nlibrary(\"dplyr\")\n# Importation du fichier\ndfRMR <- read.dbf(\"data/bivariee/SRRMRMTL2016.dbf\")\n# Définition d'un facteur binaire \ndfRMR$Montreal <- factor(dfRMR$Montreal, \n levels = c(0,1), \n labels = c(\"Hors de Montréal\" , \"Montréal\"))\n# Comparaison des moyennes ------------------------\n# Boites à moustaches (boxplot)\nggplot(data = dfRMR, mapping=aes(x = Montreal, y = Locataire, colour = Montreal)) +\n geom_boxplot(width=0.2)+\n theme(legend.position = \"none\")+\n xlab(\"Zone\")+ ylab(\"Pourcentage de locataires\")+\n ggtitle(\"Locataires par secteur de recensement\", \n subtitle = \"région métropolitaine de recensement de Montréal, 2016\")\n# Nombre d'observations, moyennes et écarts-types pour les deux échantillons\ngroup_by(dfRMR, Montreal) %>%\n summarise(\n n = n(),\n moy = mean(Locataire, na.rm = TRUE),\n ecarttype = sd(Locataire, na.rm = TRUE)\n )\n# Nous vérifions si les variances sont égales avec la fonction var.test\n# quand la valeur de P est inférieure à 0,05 alors les variances diffèrent\nv <- var.test(Locataire ~ Montreal, alternative = 'two.sided', conf.level = .95, data = dfRMR)\nprint(v)\n```\nLe test indique que nous n'avons aucune raison de rejeter l'hypothèse nulle selon laquelle les variances sont égales. Pour l'île de Montréal, l'écart-type est de 21,4; il est de 20,1 hors de l'île, soit une différence négligeable.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Calcul du T de Student ou du T de Welch\np <- v$p.value\nif(p >= 0.05){\n cat(\"\\n Les variances ne diffèrent pas!\",\n \"\\n Nous utilisons le test de Student avec l'option var.equal = TRUE\", sep = \"\")\n t.test(Locataire ~ Montreal, # variable continue ~ facteur binaire \n data = dfRMR, # nom du DataFrame\n conf.level = .95, # intervalle de confiance pour la valeur de t\n var.equal = TRUE) # variances égales\n} else {\n cat(\"\\n Les variances diffèrent!\",\n \"\\n Nous utilisons le test de Welch avec l'option var.equal = FALSE\", sep = \"\")\n t.test(Locataire ~ Montreal, # variable continue ~ facteur binaire \n data = dfRMR, # nom du DataFrame\n conf.level = .95, # intervalle de confiance pour la valeur de t\n var.equal = FALSE) # variances différentes\n}\n# Effet de taille à analyser uniquement si le test est significatif\ncohens_d(Locataire ~ Montreal, data = dfRMR, paired = FALSE)\nhedges_g(Locataire ~ Montreal, data = dfRMR, paired = FALSE)\n```\nNotez que les valeurs du *d* de Cohen et du *g* de Hedge sont très semblables; rappelons que le second est une correction du premier pour des échantillons de taille réduite. Avec 951 observations, nous disposons d'un échantillon suffisamment grand pour que cette correction soit négligeable.\n\n**Exemple de syntaxe pour un test de Student pour des échantillons dépendants**\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n#| fig-align: center\n\nlibrary(\"ggpubr\")\nlibrary(\"dplyr\")\nPre <- c(79,71,81,83,77,74,76,74,79,70,66,85,69,69,82,\n 69,81,70,83,68,77,76,77,70,68,80,65,65,75,84)\nPost <- c(56,47,40,45,49,51,54,47,44,54,42,56,45,45,48,\n 55,59,58,56,41,56,51,45,55,49,49,48,43,60,50)\n# Première façon de faire un tableau : avec deux colonnes Avant et Après\ndf1 <- data.frame(Avant=Pre, Apres=Post)\nhead(df1)\nggpaired(df1, cond1 = \"Avant\", cond2 = \"Apres\", fill = \"condition\", palette = \"jco\",\n xlab = \"\", ylab = \"Variable continue\")\n# Nombre d'observations, moyennes et écart-types\ncat(nrow(df1), \" observations\",\n \"\\nPOST. moy = \", round(mean(df1$Avant),1), \", e.t. = \", round(sd(df1$Avant),1),\n \"\\nPRE. moy = \", round(mean(df1$Apres),1), \", e.t. = \", round(sd(df1$Apres),1), sep = \"\")\nt.test(Pre, Post, paired = TRUE)\n# Deuxième façon de faire un tableau : avec une colonne pour la variable continue\n# et une autre pour la variable qualitative\nn <- length(Pre)*2\ndf2 <- data.frame(\n id=(1:n),\n participant=(1:length(Pre)),\n risque=c(Pre, Post)\n )\ndf2$periode <- ifelse(df2$id <= length(Pre), \"Pré\", \"Post\")\nhead(df2)\n# nombre d'observations, moyennes et écarts-types pour les deux échantillons\ngroup_by(df2, periode) %>%\n summarise(\n n = n(),\n moy = mean(risque, na.rm = TRUE),\n et = sd(risque, na.rm = TRUE)\n )\nggpaired(data = df2, x = \"periode\", y = \"risque\", fill = \"periode\",\n xlab = \"\", ylab = \"Variable continue\")\nPre <- subset(df2, periode == \"Pré\")$risque\nPost <- subset(df2, periode == \"Post\")$risque\nt.test(Pre, Post, paired = TRUE)\n```\n\n#### Comparaison des moyennes pondérées {#sec-06114}\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Moyennes pondérées**\n:::\n::: bloc_objectif-body\nEn études urbaines et en géographie, le recours aux données agrégées (non individuelles) est fréquent, par exemple au niveau des secteurs de recensement (comprenant généralement entre 2500 à 8000 habitants). Dans ce contexte, un secteur de recensement plus peuplé devrait avoir un poids plus important dans l'analyse. Il est possible d'utiliser les versions pondérées des tests présentés précédemment. Prenons deux exemples pour illustrer le tout :\n\n* Pour chaque secteur de recensement des îles de Montréal et de Laval, nous avons calculé la distance au parc le plus proche à travers le réseau de rues avec un système d'information géographique (SIG). Nous souhaitons vérifier si les personnes âgées de moins de 15 ans résidant sur l'île de Montréal bénéficient en moyenne d'une meilleure accessibilité au parc.\n\n* Dans une étude sur la concentration de polluants atmosphériques dans l'environnement autour des écoles primaires montréalaises, Carrier *et al.* [-@carrier2014] souhaitaient vérifier si les élèves fréquentant les écoles les plus défavorisées sont plus exposé(e)s au dioxyde d'azote (NO~2~) dans leur milieu scolaire. Pour ce faire, ils ont réalisé un test _t_ sur un tableau avec comme observations les écoles primaires et trois variables : la moyenne de NO~2~ (variable continue), les quintiles extrêmes d'un indice de défavorisation (premier et dernier quintiles, variable qualitative) et le nombre d'élèves par école (variable pour la pondération).\n\nPour réaliser un test *t* pondéré, nous pouvons utiliser la fonction `t_test` du package `sjstats`.\n:::\n:::\n\n\nEn guise d'exemple appliqué, dans la syntaxe ci-dessous, nous avons refait le même test *t* que précédemment (`Locataire ~ Montreal`) en pondérant chaque secteur de recensement par le nombre de logements qu'il comprend.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(\"sjstats\")\nlibrary(\"dplyr\")\n# Calcul des statistiques pondérées\ngroup_by(dfRMR, Montreal) %>%\n summarise(\n n = sum(Logement),\n MoyPond = weighted_mean(Locataire, Logement),\n ecarttypePond = weighted_sd(Locataire, Logement)\n )\n# Test t non pondéré\nt.test(Locataire ~ Montreal, dfRMR, \n var.equal = TRUE, conf.level = .95)\n# Test t pondérée\nsjstats::t_test(dfRMR, \n select = \"Locataire\", \n by = \"Montreal\", \n weights = \"Logement\",\n mu = 0,\n paired = FALSE)\n```\n\n#### Comment rapporter un test de Student ou de Welch? {#sec-06115}\n\nPour les différentes versions du test, il est important de rapporter les valeurs de _t_ et de _p_, les moyennes et écarts-types des groupes. Voici quelques exemples.\n\n**Test de Student ou de Welch pour échantillons indépendants**\n\n* Dans la région métropolitaine de Montréal en 2005, le revenu total des femmes (moyenne = 29 117 dollars; écart-type = 258 022) est bien inférieur à celui des hommes (moyenne = 44 463; écart-type = 588 081). La différence entre les moyennes des deux sexes (-15 345) en faveur des hommes est d’ailleurs significative (*t* = -27,09; *p* < 0,001).\n\n* Il y un effet significatif selon le sexe (*t* = -27,09; *p* < 0,001), le revenu total des hommes (moyenne = 44 463; écart-type = 588 081) étant bien supérieur à celui des femmes (moyenne = 29 117; écart-type = 258 022).\n\n* 50 personnes se rendent au travail à vélo (moyenne = 33,7; écart-type = 8,5) contre 60 en automobile (moyenne = 34; écart-type = 8,7). Il n'y a pas de différence significative entre les moyennes d'âge des deux groupes (*t*(108) = -0,79; *p* = 0,427).\n\n\n**Test de Student échantillons dépendants (pairés)**\n\n* Nous constatons une diminution significative de la perception du risque après l'activité (moyenne = 49,9; écart-type = 5,7) comparativement à avant (moyenne = 74,8; écart-type = 6,1), avec une différence de -24,8 (*t*(29) = -18,7; *p* < 0,001).\n\n* Les résultats du pré-test (moyenne = 49,9; écart-type = 5,7) et du post-test (moyenne = 74,8; écart-type = 6,1) montrent qu'il y une diminution significative de la perception du risque (*t*(29) = -18,7; *p* < 0,001).\n\nPour un texte en anglais, consultez\n[https://www.socscistatistics.com/tutorials/ttest/default.aspx](https://www.socscistatistics.com/tutorials/ttest/default.aspx){target=\"_blank\"}.\n\n\n### Test non paramétrique de Wilcoxon {#sec-0612}\n\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Test non paramétrique de Wilcoxon**\n:::\n::: bloc_objectif-body\nSi la variable continue est fortement anormalement distribuée, il est déconseillé d'utiliser les tests de Student et de Welch. Nous privilégions le test des rangs signés de Wilcoxon (*Wilcoxon rank-sum test* en anglais). Attention, il est aussi appelé test U de Mann-Whitney. Ce test permet alors de vérifier si les deux groupes présentent des médianes différentes.\n\nPour ce faire, nous utilisons la fonction `wilcox.test` dans laquelle le paramètre `paired` permet de spécifier si les échantillons sont indépendants ou non (`FALSE` ou `TRUE`).\n:::\n:::\n\nDans l'exemple suivant, nous analysons le pourcentage de locataires dans les secteurs de recensement de la région métropolitaine de Montréal. Plus spécifiquement, nous comparons ce pourcentage entre les secteurs présents sur l'île et les secteurs hors de l'île. Il s'agit donc d'un test avec des échantillons indépendants.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(\"foreign\")\nlibrary(\"dplyr\")\n###############################\n# Échantillons indépendants\n###############################\ndfRMR <- read.dbf(\"data/bivariee/SRRMRMTL2016.dbf\")\n# Définition d'un facteur binaire \ndfRMR$Montreal <- factor(dfRMR$Montreal, \n levels = c(0,1), \n labels = c(\"Hors de Montréal\" , \"Montréal\"))\n# Calcul du nombre d'observations, des moyennes et \n# des écarts-types des rangs pour les deux échantillons\ngroup_by(dfRMR, Montreal) %>%\n summarise(\n n = n(),\n moy_rang = mean(rank(Locataire), na.rm = TRUE),\n med_rang = median(rank(Locataire), na.rm = TRUE),\n ecarttype_rang = sd(rank(Locataire), na.rm = TRUE)\n )\n# Test des rangs signés de Wilcoxon sur des échantillons indépendants\nwilcox.test(Locataire ~ Montreal, dfRMR)\n```\n\nNous observons bien ici une différence significative entre le pourcentage de locataires des secteurs de recensement sur l'île (rang médian = 216) et ceux en dehors de l'île (rang médian = 261).\n\nPour le second exemple, nous générons deux jeux de données au hasard représentant une mesure d'une variable pré-traitement (*pre*) et post-traitement (*post*) pour un même échantillon.\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n###############################\n# Échantillons dépendants\n###############################\npre <- sample(60:80, 50, replace = TRUE)\npost <- sample(30:65, 50, replace = TRUE)\ndf1 <- data.frame(Avant=pre, Apres=post)\n# Nombre d'observations, moyennes et écart-types\ncat(nrow(df1), \" observations\",\n \"\\nPOST. median = \", round(median(df1$Avant), 1), \n \", moy = \", round(mean(df1$Avant), 1),\n \"\\nPRE. median = \", round(median(df1$Apres), 1), \n \", moy = \", round(mean(df1$Apres), 1), sep = \"\")\nwilcox.test(df1$Avant, df1$Apres, paired = TRUE)\n```\n\nÀ nouveau, nous obtenons une différence significative entre les deux variables.\n\n**Comment rapporter un test de Wilcoxon?**\n\nLorsque nous rapportons les résultats d'un test de Wilcoxon, il est important de signaler la valeur du test (*W*), le degré de signification (valeur de *p*) et éventuellement la médiane des rangs ou de la variable originale pour les deux groupes. Voici quelques exemples :\n\n* Les résultats du test des rangs signés de Wilcoxon signalent que les rangs de l'île de Montréal sont significativement plus élevés que ceux de l'île de Laval (*W* = 1223, *p* < 0,001).\n\n* Les résultats du test de Wilcoxon signalent que les rangs post-tests sont significativement plus faibles que ceux du pré-test (*W* = 1273,5, *p* < 0,001).\n\n* Les résultats du test de Wilcoxon signalent que la médiane des rangs pré-tests (médiane = 69) est significativement plus forte que celle du post-test (médiane = 50,5) (*W* = 1273,5, *p* < 0,001).\n\n\n## Relation entre une variable quantitative et une variable qualitative à plus de deux modalités {#sec-062}\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Existe-t-il une relation entre une variable continue et une variable qualitative comprenant plus de deux modalités?**\n:::\n::: bloc_objectif-body\nPour répondre à cette question, nous avons recours à deux méthodes : l’analyse de variance – **ANOVA**, _**AN**alysis **O**f **VA**riance_ en anglais – et le test non paramétrique de Kruskal-Wallis. La première permet de vérifier si les moyennes de plusieurs groupes d'une population donnée sont ou non significativement différentes; la seconde, si leurs médianes sont différentes.\n:::\n:::\n\n\n### Analyse de variance {#sec-0621}\n\nL’analyse de variance (ANOVA) est largement utilisée en psychologie, en médecine et en pharmacologie. Prenons un exemple classique en pharmacologie pour tester l'efficacité d'un médicament. Quatre groupes de population sont constitués :\n\n* un premier groupe d'individus pour lequel nous administrons un placebo (un médicament sans substance active), soit le groupe de contrôle ou le groupe témoin;\n\n* un second groupe auquel nous administrons le médicament avec un faible dosage;\n\n* un troisième avec un dosage moyen;\n\n* un quatrième avec un dosage élevé.\n\nLa variable continue permet d'évaluer l'évolution de l'état de santé des individus (par exemple, la variation du taux de globules rouges dans le sang avant et après le traitement). Si le traitement est efficace, nous nous attendons alors à ce que les moyennes des deuxième, troisième et quatrième groupes soient plus élevées que celle du groupe de contrôle. Les différences de moyennes entre les second, troisième et quatrième groupes permettent aussi de repérer le dosage le plus efficace. Si nous n'observons aucune différence significative entre les groupes, cela signifie que l'effet du médicament ne diffère pas de l'effet d'un placébo.\n\nL'ANOVA est aussi très utilisée en études urbaines, principalement pour vérifier si un phénomène urbain varie selon plusieurs groupes d'une population donnée ou de régions géographiques. En guise d'exemple, le recours à l'ANOVA permet de répondre aux questions suivantes :\n\n* Les moyennes des niveaux d'exposition à un polluant atmosphérique (variable continue) varient-elles significativement selon le mode de transport utilisé (automobile, vélo, transport en commun) pour des trajets similaires en heures de pointe?\n\n* Pour une métropole donnée, les moyennes des loyers (variable continue) sont-elles différentes entre les logements de la ville centre versus ceux localisés dans la première couronne et ceux de la seconde couronne?\n\n\n#### Calcul des trois variances pour l'ANOVA {#sec-06211}\n\nL'ANOVA repose sur le calcul de trois variances :\n\n* **la variance totale** (*VT*) de la variable dépendante continue, soit la somme des carrés des écarts à la moyenne de l'ensemble de la population (@eq-anova1);\n\n* la **variance intergroupe** (*Var~inter~*) ou variance expliquée (*VE*), soit la somme des carrés des écarts entre la moyenne de chaque groupe et la moyenne de l’ensemble du jeu de données multipliées par le nombre d’individus appartenant à chacun des groupes (@eq-anova2);\n\n* la **variance intragroupe** (*Var~intra~*) ou variance non expliquée (*VNE*), soit la somme des variances des groupes de la variable indépendante (@eq-anova3).\n\n$$\nVT=\\sum_{i=1}^n (y_{i}-\\overline{y})^2\n$$ {#eq-anova1}\n\n$$\nVar_{inter} \\mbox{ ou } VE=n_{g_1}\\sum_{i\\in{g_1}}(\\overline{y_{g_1}}-\\overline{y})^2 + n_{g_2}\\sum_{i\\in{g_2}}(\\overline{y_{g_2}}-\\overline{y})^2 + ... + n_{g_k}\\sum_{i\\in{g_n}}(\\overline{y_{g_k}}-\\overline{y})^2\n$$ {#eq-anova2}\n\n$$\nVar_{intra} \\mbox{ ou } VNE=\\sum_{i\\in{g_1}}(y_{i}-\\overline{y_{g_1}})^2 + \\sum_{i\\in{g_2}}(y_{i}-\\overline{y_{g_2}})^2 + ... + \\sum_{i\\in{g_n}}(y_{i}-\\overline{y_{g_k}})^2 \n$$ {#eq-anova3}\n\noù $\\overline{y}$ est la moyenne de l'ensemble de la population; $\\overline{y_{g_1}}$, $\\overline{y_{g_2}}$, $\\overline{y_{g_k}}$ sont respectivement les moyennes des groupes 1 à _k_ (_k_ étant le nombre de modalités de la variable qualitative) et $n_{g_1}$,$n_{g_2}$ et $n_{g_k}$ sont les nombres d'observations dans les groupes 1 à _k_.\n\nLa variance totale (*VT*) est égale à la somme de la variance intergroupe (expliquée) et la variance intragroupe (non expliquée) (@eq-anova5). Le ratio entre la variance intergroupe (expliquée) et la variance totale est dénommé *Eta^2^* (@eq-anova6). Il varie de 0 à 1 et exprime la proportion de la variance de la variable continue qui est expliquée par les différentes modalités de la variable qualitative.\n\n$$\nVT = Var_{inter} + Var_{intra} \\mbox{ ou } VT = VNE + VE\n$$ {#eq-anova5}\n\n$$\n\\eta^2= \\frac{Var_{inter}}{VT} \\mbox{ ou } \\eta^2= \\frac{VE}{VT}\n$$ {#eq-anova6}\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**La décomposition de la variance totale : une notion fondamentale en statistique** \n:::\n::: bloc_astuce-body\nLa **variance totale** est égale à la somme des variances intragroupe et intergroupe. Nous verrons qu'elle est aussi utilisée pour évaluer la qualité d'une partition d'une population en plusieurs groupes dans le chapitre sur les méthodes de classification ([chapitre @sec-chap13]). En ANOVA, nous retenons que :\n\n* plus la variance intragroupe est faible, plus les différents groupes sont homogènes;\n\n* plus la variance intergroupe est forte, plus les moyennes des groupes sont différentes et donc plus les groupes sont dissemblables. \n\nAutrement dit, plus la variance intergroupe (**dissimilarité** des groupes) est maximisée et corollairement plus la variance intragroupe (**homogénéité** de chacun des groupes) est minimisée, plus les groupes sont clairement distincts et plus l'ANOVA est performante.\n:::\n:::\n\n\nExaminons un premier jeu de données fictives sur la vitesse de déplacement de cyclistes (variable continue exprimée en km/h) et une variable qualitative comprenant trois groupes de cyclistes utilisant soit un vélo personnel (*n~A~* = 5), soit en libre-service (*n~B~* = 7), soit électrique (*n~C~* = 6) (@tbl-aovfictive1). D'emblée, nous notons que les moyennes de vitesse des trois groupes sont différentes : 17,6 km/h pour les cyclistes avec leur vélo personnel, 12,3 km/h celles et ceux avec des vélos en libre-service et 23,1 km/h pour les cyclistes avec un vélo électrique. Pour chaque observation, la troisième colonne du tableau représente les écarts à la moyenne globale mis au carré, tandis que les colonnes suivantes représentent la déviation au carré de chaque observation à la moyenne de son groupe d'appartenance. Ainsi, pour la première observation, nous avons $(\\mbox{16,900} - \\mbox{17,339})^2 = \\mbox{0,193}$ et $(\\mbox{16,900} - \\mbox{17,580})^2~ = \\mbox{0,462}$. Les valeurs des trois variances sont les suivantes :\n\n* la **variance totale** (*VT*) est donc égale à la somme de la troisième colonne ($\\mbox{424,663}$).\n* la **variance intergroupe** (expliquée, *VE*), elle est égale à $\\mbox{5}\\times(\\mbox{17,580-17,339})^2+\\mbox{7}\\times(\\mbox{12,257-17,339})^2+\\mbox{6}\\times(\\mbox{23,067-17,339})^2 = \\mbox{377,904}$.\n* la **variance intragroupe** (non expliquée, *VNE*) est égale à $\\mbox{11,228+21,537+13,993=46,758}$. \n\nNous avons donc $VT = Var_{inter} + Var_{intra}$, soit $\\mbox{424,663 = 377,904 + 46,758}$ et $\\eta_2 = \\mbox{377,904 / 424,663 = 0,89}$. Cela signale que 89 % de la variance de la vitesse des cyclistes est expliquée par le type de vélo utilisé.\n\n```{r}\n#| label: tbl-aovfictive1\n#| tbl-cap: Données fictives et calcul des trois variances (cas 1)\n#| #| echo: false\n#| message: false\n#| warning: false\nVeloA <- c(16.9, 20.4, 16.1, 17.7, 16.8)\nVeloB <- c(13.4, 11.3, 14.0, 12.4, 13.7, 8.5, 12.5)\nVeloC <- c(22.9, 26.0, 23.6, 21.0, 22.3, 22.6)\nmoyA <- mean(VeloA)\nmoyB <- mean(VeloB)\nmoyC <- mean(VeloC)\ngrandmoy <- mean(c(VeloA,VeloB,VeloC))\nnA <- length(VeloA)\nnB <- length(VeloB)\nnC <- length(VeloC)\nn <- nA + nB + nC\nVT <- sum((c(VeloA,VeloB, VeloC)-grandmoy)^2)\nVNE_A <- sum((VeloA-moyA)^2)\nVNE_B <- sum((VeloB-moyB)^2)\nVNE_C <- sum((VeloC-moyC)^2)\nVNE <- VNE_A + VNE_B + VNE_C\nVE <- nA*(moyA-grandmoy)^2 + nB*(moyB-grandmoy)^2 + nC*(moyC-grandmoy)^2\nEta2 <- round(VE / VT, 4)\n \ndf <- data.frame(\n velo = c(rep(\"A. personnel\", length(VeloA)), \n rep(\"B. libre-service\", length(VeloB)),\n rep(\"C. électrique\", length(VeloC))),\n kmh = c(VeloA,VeloB, VeloC))\ndf$VT <- (df$kmh - grandmoy)^2\ndf$VNE_A <- ifelse(df$velo == \"A. personnel\", (df$kmh - moyA)^2, NA)\ndf$VNE_B <- ifelse(df$velo == \"B. libre-service\", (df$kmh - moyB)^2, NA)\ndf$VNE_C <- ifelse(df$velo == \"C. électrique\", (df$kmh - moyC)^2, NA)\ndf_cas1 <- df\ntabl <- df\ntabl$velo <- as.character(tabl$velo)\ntabl[19,1] <- \"grande moyenne\"\ntabl[20,1] <- \"moyenne groupe A\"\ntabl[21,1] <- \"moyenne groupe B\"\ntabl[22,1] <- \"moyenne groupe C \"\ntabl[19,2] <- round(grandmoy,3)\ntabl[20,2] <- round(moyA,3)\ntabl[21,2] <- round(moyB,3)\ntabl[22,2] <- round(moyC,3)\ntabl[23,1] <- \"Variance totale\"\ntabl[24,1] <- \"Variance intragroupe\"\ntabl[23,3] <- sum(tabl$VT, na.rm = TRUE)\ntabl[24,4] <- sum(tabl$VNE_A, na.rm = TRUE)\ntabl[24,5] <- sum(tabl$VNE_B, na.rm = TRUE)\ntabl[24,6] <- sum(tabl$VNE_C, na.rm = TRUE)\ntabl$VT <- round(tabl$VT,3)\ntabl$VNE_A <- round(tabl$VNE_A,3)\ntabl$VNE_B <- round(tabl$VNE_B,3)\ntabl$VNE_C <- round(tabl$VNE_C,3)\nopts <- options(knitr.kable.NA = \"--\")\n\nknitr::kable(tabl, \n caption = \"Données fictives et calcul des trois variances (cas 1)\",\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Type de vélo\",\n \"km/h\",\n \"$(y_{i}-\\\\overline{y})^2$\",\n \"$(y_{i}-\\\\overline{y_{A}})^2$\",\n \"$(y_{i}-\\\\overline{y_{B}})^2$\",\n \"$(y_{i}-\\\\overline{y_{C}})^2$\"\n ),\n align= c(\"l\", \"c\", \"r\", \"r\", \"r\", \"r\")\n)\n```\n\nExaminons un deuxième jeu de données fictives pour lequel le type de vélo utilisé n'aurait que peu d'effet sur la vitesse des cyclistes (@tbl-aovfictive2). D'emblée, les moyennes des trois groupes semblent très similaires (19,3, 17,9 et 18,7). Les valeurs des trois variances sont les suivantes :\n\n* la **variance totale** (*VT*) est égale à $\\mbox{121,756}$.\n* la **variance intergroupe** (expliquée, *VE*) est égale à $\\mbox{5}\\times(\\mbox{19,300-18,528})^2+\\mbox{7}\\times(\\mbox{17,871-18,528})^2+\\mbox{6}\\times(\\mbox{18,650-18,528})^2 = \\mbox{6,087}$.\n* la **variance intragroupe** (non expliquée, *VNE*) est égale à $\\mbox{9,140+50,254+56,275 = 115,669}$.\n\nNous avons donc $VT = Var_{inter} + Var_{intra}$, soit $\\mbox{121,756 = 6,087 + 115,669}$ et $\\eta_2 = \\mbox{6,087 / 121,756 = 0,05}$. Cela signale que 5 % de la variance de la vitesse des cyclistes est uniquement expliquée par le type de vélo utilisé.\n\n```{r}\n#| label: tbl-aovfictive2\n#| tbl-cap: Données fictives et calcul des trois variances (cas 2)\n#| echo: false\n#| message: false\n#| warning: false\nVeloA <- c(17.5, 19.0, 19.7, 18.7, 21.6)\nVeloB <- c(13.7, 20.8, 15.1, 18.8, 21.5, 16.5, 18.7)\nVeloC <- c(16.6, 16.3, 15.6, 20.0, 24.6, 18.8)\nmoyA <- mean(VeloA)\nmoyB <- mean(VeloB)\nmoyC <- mean(VeloC)\ngrandmoy <- mean(c(VeloA,VeloB,VeloC))\nnA <- length(VeloA)\nnB <- length(VeloB)\nnC <- length(VeloC)\nn <- nA + nB + nC\nVT <- sum((c(VeloA,VeloB, VeloC)-grandmoy)^2)\nVNE_A <- sum((VeloA-moyA)^2)\nVNE_B <- sum((VeloB-moyB)^2)\nVNE_C <- sum((VeloC-moyC)^2)\nVNE <- VNE_A + VNE_B + VNE_C\nVE <- nA*(moyA-grandmoy)^2 + nB*(moyB-grandmoy)^2 + nC*(moyC-grandmoy)^2\nEta2 <- round(VE / VT, 4)\n \ndf <- data.frame(\n velo = c(rep(\"A. personnel\", length(VeloA)), \n rep(\"B. libre-service\", length(VeloB)),\n rep(\"C. électrique\", length(VeloC))),\n kmh = c(VeloA,VeloB, VeloC))\ndf$VT <- (df$kmh - grandmoy)^2\ndf$VNE_A <- ifelse(df$velo == \"A. personnel\", (df$kmh - moyA)^2, NA)\ndf$VNE_B <- ifelse(df$velo == \"B. libre-service\", (df$kmh - moyB)^2, NA)\ndf$VNE_C <- ifelse(df$velo == \"C. électrique\", (df$kmh - moyC)^2, NA)\ndf_cas2 <- df\ntabl <- df\ntabl$velo <- as.character(tabl$velo)\ntabl[19,1] <- \"grande moyenne\"\ntabl[20,1] <- \"moyenne groupe A\"\ntabl[21,1] <- \"moyenne groupe B\"\ntabl[22,1] <- \"moyenne groupe C \"\ntabl[19,2] <- round(grandmoy,3)\ntabl[20,2] <- round(moyA,3)\ntabl[21,2] <- round(moyB,3)\ntabl[22,2] <- round(moyC,3)\ntabl[23,1] <- \"Variance totale\"\ntabl[24,1] <- \"Variance intragroupe\"\ntabl[23,3] <- sum(tabl$VT, na.rm = TRUE)\ntabl[24,4] <- sum(tabl$VNE_A, na.rm = TRUE)\ntabl[24,5] <- sum(tabl$VNE_B, na.rm = TRUE)\ntabl[24,6] <- sum(tabl$VNE_C, na.rm = TRUE)\ntabl$VT <- round(tabl$VT,3)\ntabl$VNE_A <- round(tabl$VNE_A,3)\ntabl$VNE_B <- round(tabl$VNE_B,3)\ntabl$VNE_C <- round(tabl$VNE_C,3)\nopts <- options(knitr.kable.NA = \"--\")\n\nknitr::kable(tabl, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Type de vélo\",\n \"km/h\",\n \"$(y_{i}-\\\\overline{y})^2$\",\n \"$(y_{i}-\\\\overline{y_{A}})^2$\",\n \"$(y_{i}-\\\\overline{y_{B}})^2$\",\n \"$(y_{i}-\\\\overline{y_{C}})^2$\"),\n align= c(\"l\", \"c\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\n\n#### Test de Fisher {#sec-06212}\n\nPour vérifier si les moyennes sont statistiquement différentes (autrement dit, si leur différence est significativement différente de 0), nous avons recours au test *F* de Fisher. Pour ce faire, nous posons l'hypothèse nulle (*H~0~*), soit que les moyennes des groupes sont égales; autrement dit que la variable qualitative n'a pas d'effet sur la variable continue (indépendance entre les deux variables). L'hypothèse alternative (*H~1~*) est donc que les moyennes sont différentes. Pour nos deux jeux de données fictives ci-dessus comprenant trois groupes, *H~0~* signifie que $\\overline{y_{A}}=\\overline{y_{B}}=\\overline{y_{C}}$. La statistique *F* se calcule comme suit :\n\n\n$$\nF = \\frac{\\frac{Var{inter}}{k-1}}{\\frac{Var{intra}}{n-k}}\\mbox{ ou } F = \\frac{\\frac{VE}{k-1}}{\\frac{VNE}{n-k}}\n$$ {#eq-anovaF}\n\noù $n$ et $k$ sont respectivement les nombres d'observations et de modalités de la variable qualitative. L'hypothèse nulle (les moyennes sont égales) est rejetée si la valeur du *F* calculé est supérieure à la valeur critique de la table *F* avec les degrés de liberté *(k-1, n-k)* et un seuil \n$\\alpha$ (*p*=0,05 habituellement) (voir la table des valeurs critiques de *F*, [section @sec-132]). Notez que nous utilisons rarement la table *F* puisqu'avec la fonction `aov`, nous obtenons directement la valeur *F* et celle de *p* qui lui est associée. Concrètement, si le test _F_ est significatif (avec *p* < 0,05), plus la valeur de *F* est élevée, plus la différence entre les moyennes est élevée.\n\nAppliquons rapidement la démarche du test *F* à nos deux jeux de données fictives qui comprennent 3 modalités pour la variable qualitative et 18 observations. Avec $\\alpha$ = 0,05, 2 degrés de liberté (3-1) au numérateur et 15 au dénominateur (18-3), la valeur critique de F est de 3,68. Nous en concluons alors que :\n\n* Pour le cas A, le *F* calculé est égal à $\\mbox{(377,904 / 2) / (46,758 / 15) = 60,62}$. Il est supérieur à la valeur *F* critique; les moyennes sont donc statistiquement différentes au seuil 0,05. Autrement dit, nous aurions eu moins de 5 % de chance d'obtenir un échantillon produisant ces résultats si en réalité la différence entre les moyennes était de 0.\n\n* Pour le cas B, le *F* calculé est égal à $\\mbox{(6,087 / 2) / (115,669 / 15) = 0,39}$. Il est inférieur à la valeur *F* critique; les moyennes ne sont donc pas statistiquement différentes au seuil de 0,05.\n\n#### Conditions d'application de l'ANOVA et solutions de rechange {#sec-06213}\n\nTrois conditions d'application doivent être vérifiées avant d'effectuer une analyse de variance sur un jeu de données :\n\n* **Normalité des groupes.** Le test de Fisher repose sur le postulat que les échantillons (groupes) sont normalement distribués. Pour le vérifier, nous avons recours au test de normalité de Shapiro–Wilk ([section @sec-025413]). Rappelez-vous toutefois que ce test est très restrictif, surtout pour de grands échantillons.\n\n* **Homoscédasticité**. La variance dans les échantillons doit être la même (homogénéité des variances). Pour vérifier cette condition, nous utilisons les tests de Levene, de Bartlett ou de Breusch-Pagan.\n\n* **Indépendance des observations (pseudo-réplication).** Chaque individu doit appartenir à un et un seul groupe. En d'autres termes, les observations ne sont pas indépendantes si plusieurs mesures (variable continue) sont faites sur un même individu. Si c'est le cas, nous utiliserons alors une analyse de variance sur des mesures répétées (voir le bloc à la fin du chapitre).\n\n**Quelles sont les conséquences si les conditions d'application ne sont pas respectées?** La non-vérification des conditions d'application cause deux problèmes distincts : elle affecte la puissance du test (sa capacité à détecter un effet, si celui-ci existe réellement) et le taux d'erreur de type 1 (la probabilité de trouver un résultat significatif alors qu'aucune relation n'existe réellement, soit un faux positif) [@glass1972consequences; @lix1996consequences].\n\n* Si la distribution est asymétrique plutôt que centrée (comme pour une distribution normale), la puissance et le taux d'erreur de type 1 sont tous les deux peu affectés, car le test est non orienté (la différence de moyennes peut être négative ou positive).\n\n* Si la distribution est leptocurtique (pointue, avec des extrémités de la distribution plus importantes), le taux d'erreur de type 1 est peu affecté; en revanche, la puissance du test est réduite. L'inverse s'observe si la distribution est platicurtique (aplatie, c'est-à-dire avec des extrémités de la distribution plus réduites.\n\n* Si les groupes ont des variances différentes, le taux d'erreur de type 1 augmente légèrement.\n\n* Si les observations ne sont pas indépendantes, à la fois le taux d'erreur de type 1 et la puissance du test sont fortement affectés.\n\n* Si les échantillons sont petits, les effets présentés ci-dessus sont démultipliés.\n\n* Si plusieurs conditions ne sont pas respectées, les conséquences présentées ci-dessus s'additionnent, voire se combinent.\n\n**Que faire quand les conditions d'application relatives à la normalité ou à l'homoscédasticité ne sont vraiment pas respectées?** Signalons d'emblée que le non-respect de ces conditions ne change rien à la décomposition de la variance (*VT = V~intra~+V~inter~*). Cela signifie que vous pouvez toujours calculer *Eta^2^*. Par contre, le test de Fisher ne peut pas être utilisé, car il est biaisé comme décrit précédemment. Quatre solutions sont envisageables :\n\n* Lorsque les échantillons sont fortement anormalement distribués, certains auteurs vont simplement transformer leur variable en appliquant une fonction logarithme (le plus souvent) ou racine carrée, inverse ou exponentielle, et reporter le test de Fisher calculé sur cette transformation. Attention toutefois! Transformer une variable ne va pas systématiquement la rapprocher d'une distribution normale et complique l'interprétation finale des résultats. Par conséquent, avant de recalculer votre test *F*, il convient de réaliser un test de normalité de Shapiro–Wilk et un test d'homoscédasticité (Levene, Bartlett ou Breusch-Pagan) sur la variable continue transformée.\n\n* Détecter les observations qui contribuent le plus à l'anormalité et à l'hétéroscédasticité (valeurs aberrantes ou extrêmes). Supprimez-les et refaites votre ANOVA en vous assurant que les conditions sont désormais respectées. Notez que supprimer des observations peut être une pratique éthiquement questionnable en statistique. Si vos échantillons sont bien constitués et que la mesure collectée n'est pas erronée, pourquoi donc la supprimer? Si vous optez pour cette solution, prenez soin de comparer les résultats avant et après la suppression des observations. Si les conditions sont respectées après la suppression et que les résultats de l'ANOVA (*Eta^2^* et test *F* de Fisher) sont très semblables, conservez donc les résultats de l'ANOVA initiale et signalez que vous avez procédé aux deux tests.\n\n* Lorsque les variances des groupes sont dissemblables, vous pouvez utiliser le test de Welch pour l'ANOVA au lieu du test *F* de Fisher. \n\n* Dernière solution, lorsque les deux conditions ne sont vraiment pas respectées, utilisez le test non paramétrique de Kruskal-Wallis. Par analogie au *t* de Student, il correspond au test des rangs signés de Wilcoxon. Ce test est décrit dans la section suivante.\n\nVous l'aurez compris, dans de nombreux cas en statistique, les choix méthodologiques dépendent en partie de la subjectivité des chercheur(se)s. Il faut s'adapter au jeu de données et à la culture statistique en vigueur dans votre champ d'études. N'hésitez pas à réaliser plusieurs tests différents pour évaluer la robustesse de vos conclusions et fiez-vous en premier lieu à ceux pour lesquels votre jeu de données est le plus adapté.\n\n### Test non paramétrique de Kruskal-Wallis {#sec-0622}\n\nLe test non paramétrique de Kruskal-Wallis est une solution de rechange à l'ANOVA classique lorsque le jeu de données présente de graves problèmes de normalité et d'hétéroscédasticité. Cette méthode représente une ANOVA appliquée à une variable continue transformée préalablement en rangs. Du fait de la transformation en rangs, nous ne vérifions plus si les moyennes sont différentes, mais bel et bien si les médianes de la variable continue sont différentes. Pour ce faire, nous utiliserons la fonction `kruskal.test`.\n\n### Mise en œuvre dans R {#sec-0623}\n\nDans une étude récente, Apparicio *et al.* [-@2018_1] ont comparé les expositions au bruit et à la pollution atmosphérique aux heures de pointe à Montréal en fonction du mode de transport utilisé. Pour ce faire, trois équipes de trois personnes ont été constituées : une personne à vélo, une autre en automobile et une dernière se déplaçant en transport en commun, équipées de capteurs de pollution, de sonomètres, de vêtements biométriques et d’une montre GPS. Chaque matin, à huit heures précises, les membres de chaque équipe ont réalisé un trajet d'un quartier périphérique de Montréal vers un pôle d'enseignement (université) ou d'emploi localisé au centre-ville. Le trajet inverse était réalisé le soir à 17 h. Au total, une centaine de trajets ont ainsi été réalisés. Des analyses de variance ont ainsi permis de comparer les trois modes (automobile, vélo et transport en commun) en fonction des temps de déplacement, des niveaux d'exposition au bruit, des niveaux d'exposition au dioxyde d'azote et de la dose totale inhalée de dioxyde d'azote. Nous vous proposons ici d'analyser une partie de ces données.\n\n\n#### Première ANOVA : différences entre les temps de déplacement {#sec-06231}\nComme première analyse de variance, nous vérifions si les moyennes des temps de déplacement sont différentes entre les trois modes de transport. \n\nDans un premier temps, nous calculons les moyennes des différents groupes. Nous pouvons alors constater que les moyennes sont très semblables : 37,7 minutes pour l'automobile versus 38,4 et 41,6 pour le vélo et le transport en commun. Aussi, les variances des trois groupes sont relativement similaires.\n\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(\"rstatix\")\n# chargement des DataFrames\nload(\"data/bivariee/dataPollution.RData\")\n# Statistiques descriptives pour les groupes (moyenne et écart-type)\ndf_TrajetsDuree %>% # Nom du DataFrame\n group_by(Mode) %>% # Variable qualitative\n get_summary_stats(DureeMinute, type = \"mean_sd\") # Variable continue \n```\n\nPour visualiser la distribution des données pour les trois groupes, vous pouvez créer des graphiques de densité et en violon (@fig-Anova1a). La juxtaposition des trois distributions montre que les distributions des valeurs pour les trois groupes sont globalement similaires. Cela est corroboré par le fait que les boîtes du graphique en violon sont situées à la même hauteur. Autrement dit, à la lecture des deux graphiques, il ne semble pas y avoir de différences significatives entre les trois groupes en termes de temps de déplacement.\n\n```{r}\n#| label: fig-Anova1a\n#| echo: true\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Graphiques de densité et en violon\n#| out-width: \"75%\"\nlibrary(\"ggplot2\")\nlibrary(\"ggpubr\")\n# Graphique de densité\nGraphDens <- ggplot(data = df_TrajetsDuree, \n mapping=aes(x = DureeMinute, colour = Mode, fill = Mode)) +\n geom_density(alpha=0.55, mapping=aes(y = ..scaled..))+\n labs(title = \"a. Graphique de densité\",\n x = \"Densité\",\n y = \"Durée du trajet (en minutes)\")\n# Graphique en violon\nGraphViolon <- ggplot(df_TrajetsDuree, aes(x = Mode, y = DureeMinute)) +\n geom_violin(fill = \"white\") +\n geom_boxplot(width=0.1, aes(x = Mode, y = DureeMinute, fill = Mode))+\n labs(title = \"b. Graphique en violon\",\n x = \"Mode de transport\",\n y = \"Durée du trajet (en minutes)\")+\n theme(legend.position = \"none\")\nggarrange(GraphDens, GraphViolon)\n``` \n\nNous pouvons vérifier si les échantillons sont normalement distribués avec la fonction `shapiro_test` du package `rstatix`. À titre de rappel, l'hypothèse nulle (*H~0~*) de ce test est que la distribution est normale. Par conséquent, quand la valeur de *p* associée à la statistique de Shapiro est supérieure à 0,05, alors nous ne pouvons rejeter l'hypothèse d'une distribution normale (autrement dit, la distribution est anormale). À la lecture des résultats ci-dessous, seul le groupe utilisant le transport en commun présente une distribution proche de la normalité (*p* = 0,0504). Ce test étant très restrictif, il est fortement conseillé de visualiser le diagramme quantile-quantile pour chaque groupe (graphique QQ plot) (@fig-Qqplot). Ces graphiques sont utilisés pour déterminer visuellement si une distribution empirique (observée sur des données), s'approche d'une distribution théorique (ici la loi normale). Si effectivement les deux distributions sont proches, les points du diagramme devraient tous tomber sur une ligne droite parfaite. Un intervalle de confiance (représenté ici en gris) peut être construit pour obtenir une interprétation plus nuancée. Dans notre cas, seules deux observations pour le vélo et deux autres pour l'automobile s'éloignent vraiment de la ligne droite. Nous pouvons considérer que ces trois distributions s'approchent d'une distribution normale.\n\n```{r}\n#| label: fig-Qqplot\n#| echo: true\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: QQ Plot pour les groupes\n#| out-width: \"75%\"\nlibrary(\"dplyr\")\nlibrary(\"ggpubr\")\nlibrary(\"rstatix\")\n# Condition 1 : normalité des échantillons\n# Test pour la normalité des échantillons (groupes) : test de Shapiro\n df_TrajetsDuree %>% # Nom du DataFrame\n group_by(Mode) %>% # Variable qualitative\n shapiro_test(DureeMinute) # Variable continue \n# Graphiques qqplot pour les groupes\nggqqplot(df_TrajetsDuree, \"DureeMinute\", facet.by = \"Mode\", \n xlab = \"Théorique\", ylab = \"Échantillon\")\n\n``` \n\nPour vérifier l’hypothèse d’homogénéité des variances, vous pouvez utiliser les tests de Levene, de Bartlett ou de Breusch-Pagan. Les valeurs de *p*, toutes supérieures à 0,05, signalent que la condition d'homogénéité des variances est respectée.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(\"rstatix\")\nlibrary(\"lmtest\")\nlibrary(\"car\")\n# Condition 2 : homogénéité des variances (homocédasticité)\nleveneTest(DureeMinute ~ Mode, data = df_TrajetsDuree)\nbartlett.test(DureeMinute ~ Mode, data = df_TrajetsDuree)\nbptest(DureeMinute ~ Mode, data = df_TrajetsDuree)\n```\n\nDeux fonctions peuvent être utilisées pour calculer l'analyse de variance : la fonction de base `aov(variable continue ~ variable qualitative, data = votre DataFrame)` ou bien la fonction `anova_test(variable continue ~ variable qualitative, data = votre DataFrame)` du package `rstatix`. Comparativement à `aov`, l'avantage de la fonction `anova_test` est qu'elle calcule aussi le *Eta^2^*.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(\"rstatix\")\nlibrary(\"car\")\nlibrary(\"effectsize\")\n# ANOVA avec la fonction aov\naov1 <- aov(DureeMinute ~ Mode, data = df_TrajetsDuree)\nsummary(aov1)\n# calcul de Eta2 avec la fonction eta_squared du package effectsize\neffectsize::eta_squared(aov1)\n# ANOVA avec la fonction anova_test du package rstatix\nanova_test(DureeMinute ~ Mode, data = df_TrajetsDuree)\n```\n\nLa valeur de *p* associée à la statistique *F* (0,444) nous permet de conclure qu'il n'y a pas de différences significatives entre les moyennes des temps de déplacement des trois modes de transport.\n\n#### Deuxième ANOVA : différences entre les niveaux d'exposition au bruit {#sec-06232}\n\nDans ce second exercice, nous analysons les différences d'exposition au bruit. D'emblée, les statistiques descriptives révèlent que les moyennes sont dissemblables : 66,8 dB(A) pour l’automobile versus 68,8 et 74 pour le vélo et le transport en commun. Aussi, la variance du transport en commun est très différente des autres.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(\"rstatix\")\n# chargement des DataFrames\nload(\"data/bivariee/dataPollution.RData\")\n# Statistiques descriptives pour les groupes (moyenne et écart-type)\n df_Bruit %>% # Nom du DataFrame\n group_by(Mode) %>% # Variable qualitative\n get_summary_stats(laeq, type = \"mean_sd\") # Variable continue \n```\n\nÀ la lecture des graphiques de densité et en violon (@fig-Anova1b), il semble clair que les niveaux d'exposition au bruit sont plus faibles pour les automobilistes et plus élevés pour les cyclistes et surtout les personnes en transport en commun. En outre, la distribution des valeurs d'exposition au bruit dans le transport en commun semble bimodale. Cela s'explique par le fait que les niveaux de bruit sont beaucoup plus élevés dans le métro que dans les autobus.\n\n```{r}\n#| label: fig-Anova1b\n#| echo: true\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Graphique de densité et en violon\n#| out-width: \"75%\"\nlibrary(\"ggplot2\")\nlibrary(\"ggpubr\")\n# Graphique en densité\nGraphDens <- ggplot(data = df_Bruit, \n mapping=aes(x = laeq, colour = Mode, fill = Mode)) +\n geom_density(alpha=0.55, mapping=aes(y = ..scaled..))+\n labs(title = \"a. graphique de densité\",\n x = \"Exposition au bruit (dB(A))\")\n# Graphique en violon\nGraphViolon <- ggplot(df_Bruit, aes(x = Mode, y = laeq)) +\n geom_violin(fill = \"white\") +\n geom_boxplot(width=0.1, aes(x = Mode, y = laeq, fill = Mode))+\n labs(title = \"b. Graphique en violon\",\n x = \"Mode de transport\",\n y = \"Exposition au bruit (dB(A))\")+\n theme(legend.position = \"none\")\nggarrange(GraphDens, GraphViolon)\n``` \n\n\nLe test de Shapiro et les graphiques QQ plot (@fig-Qqplot2) révèlent que les distributions des trois groupes sont anormales. Ce résultat n'est pas surprenant si l'on tient compte de la nature logarithmique de l'échelle décibel.\n\n```{r}\n#| label: fig-Qqplot2\n#| echo: true\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: QQ Plot pour les groupes\n#| out-width: \"75%\"\nlibrary(\"dplyr\")\nlibrary(\"ggpubr\")\nlibrary(\"rstatix\")\n# Condition 1 : normalité des échantillons\n# Test pour la normalité des échantillons (groupes) : test de Shapiro\ndf_Bruit %>% # Nom du DataFrame\n group_by(Mode) %>% # Variable qualitative\n shapiro_test(laeq) # Variable continue \n# Graphiques qqplot pour les groupes\nggqqplot(df_Bruit, \"laeq\", facet.by = \"Mode\", xlab = \"Théorique\", ylab = \"Échantillon\")\n\n``` \n\nEn outre, selon les valeurs des tests de Levene, de Bartlett ou de Breusch-Pagan, les variances ne sont pas égales.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(\"rstatix\")\nlibrary(\"lmtest\")\nlibrary(\"car\")\n# Condition 2 : homogénéité des variances (homocédasticité)\nleveneTest(laeq ~ Mode, data = df_Bruit)\nbartlett.test(laeq ~ Mode, data = df_Bruit)\nbptest(laeq ~ Mode, data = df_Bruit)\n```\n\nÉtant donné que les deux conditions (normalité et homogénéité des variances) ne sont pas respectées, il est préférable d'utiliser un test non paramétrique de Kruskal-Wallis. Calculons toutefois préalablement l'ANOVA classique et l'ANOVA de Welch puisque les variances ne sont pas égales. Les valeurs de *p* des deux tests (Fisher et Welch) signalent que les moyennes d'exposition au bruit sont statistiquement différentes entre les trois modes de transport.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(\"rstatix\")\n# ANOVA avec la fonction anova_test du package rstatix\nanova_test(laeq ~ Mode, data = df_Bruit)\n# ANOVA avec le test de Welch puisque les variances ne sont pas égales\nwelch_anova_test(laeq ~ Mode, data = df_Bruit)\n```\n\nUne fois démontré que les moyennes sont différentes, le test de Tukey est particulièrement intéressant puisqu'il nous permet de repérer les différences de moyennes significatives deux à deux, tout en ajustant les valeurs de *p* obtenues en fonction du nombre de comparaisons effectuées. Ci-dessous, nous constatons que toutes les paires sont statistiquement différentes et que la différence de moyennes entre les automobilistes et les cyclistes est de 1,9 dB(A) et surtout de 7,1 dB(A) entre les automobilistes et les personnes ayant pris le transport en commun.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\naov2 <- aov(laeq ~ Mode, data = df_Bruit)\n# Test de Tukey pour comparer les moyennes entre elles\nTukeyHSD(aov2, conf.level = 0.95)\n```\n\nLe calcul du test non paramétrique de Kruskal-Wallis avec la fonction `kruskal.test` démontre aussi que les médianes des groupes sont différentes (*p* < 0,001). De manière comparable au test de Tukey, la fonction `pairwise.wilcox.test` permet aussi de repérer les différences significatives entre les paires de groupes. Pour conclure, tant l'ANOVA que le test non paramétrique de Kruskal-Wallis indiquent que les trois modes de transport sont significativement différents quant à l'exposition au bruit, avec des valeurs plus faibles pour les automobilistes comparativement aux cyclistes et aux personnes ayant pris le transport en commun.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Test de Kruskal-Wallis\nkruskal.test(laeq ~ Mode, data = df_Bruit)\n# Calcul de la moyenne des rangs pour les trois groupes\ndf_Bruit$laeqRank <- rank(df_Bruit$laeq)\ndf_Bruit %>%\n group_by(Mode) %>%\n get_summary_stats(laeqRank, type = \"mean\")\n# Comparaison des groupes avec la fonction pairwise.wilcox.test\npairwise.wilcox.test(df_Bruit$laeq, df_Bruit$Mode, p.adjust.method = \"BH\")\n```\n\n### Comment rapporter les résultats d'une ANOVA et du test de Kruskal-Wallis {#sec-0624}\n\nPlusieurs éléments doivent être reportés pour détailler les résultats d'une ANOVA ou d'un test de Kruskal-Wallis : la valeur de *F*, de *W* (dans le cas d'une ANOVA de Welch) ou du χ2 (Kruskal-Wallis), les valeurs de *p*, les moyennes ou médianes respectives des groupes et éventuellement un tableau détaillant les écarts intergroupes obtenus avec les tests de Tukey ou Wilcoxon par paires.\n\n* Les résultats de l'analyse de variance à un facteur démontrent que le mode de transport utilisé n'a pas d'effet significatif sur le temps de déplacement en heures de pointe à Montréal (*F*(2,96) = 0,82, *p* = 0,444). En effet, pour des trajets de dix kilomètres entre un quartier périphérique et le centre-ville, les cyclistes (Moy = 38,4, ET = 15,2) arrivent en moyenne moins d'une minute après les automobilistes (Moy = 37,7, ET = 12,8) et moins de quatre minutes comparativement aux personnes ayant pris le transport en commun (Moy = 41,6, ET = 11,4). \n\n* Les résultats de l'analyse de variance à un facteur démontrent que le mode de transport utilisé a un impact significatif sur le niveau d'exposition en heures de pointe à Montréal (*F*(2,96) = 544, *p* < 0,001 et *Welch*(2,96) = 446, *p* < 0,001). En effet, les personnes en transport en commun (Moy = 74,0, ET = 6,79) et les cyclistes (Moy = 68,8, ET = 4,3) ont des niveaux d'exposition au bruit significativement plus élevés que les automobilistes (Moy = 66,8, ET = 4,56). \n\n* Les résultats du test de Kruskal-Wallis démontrent qu'il existe des différences significatives d'exposition au bruit entre les trois modes de transport (χ2(2) = 784,74, *p* < 0,001) avec des moyennes de rangs de 1094 pour l'automobile, de 1124 pour le vélo et de 1207 pour le transport en commun.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Autres extensions de l'ANOVA**\n:::\n::: bloc_aller_loin-body\nNous avons vu que l'ANOVA permet de comparer les moyennes d'une variable continue à partir d'une variable qualitative comprenant plusieurs modalités (facteur) pour des observations indépendantes. Il y a donc une seule variable dépendante (continue) et une seule variable indépendante. Sachez qu'il existe de nombreuses extensions de l'ANOVA classique : \n\n* **Une ANOVA à deux facteurs**, soit avec une variable dépendante continue et deux variables indépendantes qualitatives (_two-way ANOVA_ en anglais). Nous évaluons ainsi les effets des deux variables (*a*, *b*) et de leur interaction (*ab*) sur une variable continue.\n\n* **Une ANOVA multifacteur** avec une variable dépendante continue et plus de deux variables indépendantes qualitatives. Par exemple, avec trois variables qualitatives pour expliquer la variable continue, nous incluons les effets de chaque variable qualitative (*a*, *b*, *c*), ainsi que de leurs interactions (*ab*, *ac*, *bc*, *abc*).\n\n* **L'analyse de covariance** (**ANCOVA**, _**AN**alysis of **COVA**riance_ en anglais) comprend une variable dépendante continue, une variable indépendante qualitative (facteur) et plusieurs variables indépendantes continues dites covariables. L'objectif est alors de vérifier si les moyennes d'une variable dépendante sont différentes pour plusieurs groupes d'une population donnée, après avoir contrôlé l'effet d'une ou de plusieurs variables continues. Par exemple, pour une métropole donnée, nous pourrions vouloir comparer les moyennes de loyers entre la ville-centre et ceux des première et seconde couronnes (facteur), une fois contrôlée la taille de ces derniers (variable covariée continue). En effet, une partie de la variance des loyers s'explique certainement par la taille des logements.\n\n* **L'analyse de variance multivariée** (**MANOVA**, _**M**ultivariate **AN**alysis **O**f **VA**riance_ en anglais) comprend deux variables dépendantes continues ou plus et une variable indépendante qualitative (facteur). Par exemple, nous souhaiterions comparer les moyennes d'exposition au bruit et à différents polluants (dioxyde d'azote, particules fines, ozone) (variables dépendantes continues) selon le mode de transport utilisé (automobile, vélo, transport en commun), soit le facteur.\n\n* **L'analyse de covariance multivariée** (**MANCOVA**, _**M**ultivariate **AN**alysis of **COVA**riance_ en anglais), soit une analyse qui comprend deux variables dépendantes continues ou plus (comme la MANOVA) et une variable qualitative comme variable indépendante (facteur) et une covariable continue ou plus.\n\nPour le test *t*, nous avons vu qu'il peut s'appliquer soit à deux échantillons indépendants (non appariés), soit à deux échantillons dépendants (appariés). Notez qu'il existe aussi des extensions de l'ANOVA pour des échantillons pairés. Nous parlons alors d'**analyse de variance sur des mesures répétées**. Par exemple, nous pourrions évaluer la perception du sentiment de sécurité relativement à la pratique du vélo d'hiver pour un échantillon de cyclistes ayant décidé de l'adopter récemment, et ce, à plusieurs moments : avant leur première saison, à la fin de leur premier hiver, à la fin de leur second hiver. Autre exemple, nous pourrions sélectionner un échantillon d'individus (100, par exemple) pour lesquels nous évaluerions leurs perceptions de l'environnement sonore dans différents lieux de la ville. Comme pour l'ANOVA classique (échantillons non appariés), il existe des extensions de l'ANOVA sur des mesures répétées permettant d'inclure plusieurs facteurs (groupes de population); nous mesurons alors une variable continue pour plusieurs groupes d'individus à différents moments ou pour des conditions différentes. Il est aussi possible de réaliser une ANOVA pour des mesures répétées avec une ou plusieurs covariables continues. \n\nBref, si l'ANOVA était un roman, elle serait certainement « un monde sans fin » de Ken Follett! Notez toutefois que la SUPERNOVA, la BOSSA-NOVA et le CASANOVA ne sont pas des variantes de l'ANOVA!\n:::\n:::\n\n\n## Conclusion sur la troisième partie {#sec-063}\n\nDans le cadre de cette troisième partie du livre, nous avons abordé les principales méthodes exploratoires et confirmatoires bivariées permettant d’évaluer la relation entre deux variables. La @fig-PrincipalesAnalysesBivariees propose un résumé de ces méthodes.\n\n![Principales méthodes bivariées](images/Chap06/PrincipalesMethoBivariees.jpg){#fig-PrincipalesAnalysesBivariees width=\"65%\" fig-align=\"center\"}\n\n## Quiz de révision du chapitre {#sec-064}\n\n```{r}\n#| label: Chapitre6QualiQuanti\n#| echo: false\n#| warning: false\n#| results: asis\nsource(\"code_complementaire/QuizzFunctions.R\")\nChapitre6_QualiQuanti <- quizz(\"quiz/Chapitre6_QualiQuanti.yml\", \"Chapitre6_QualiQuanti\")\nrender_quizz(Chapitre6_QualiQuanti)\n```\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"06-bivarieeQualiQuanti.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/07-regressionlineaire.qmd.json b/.quarto/idx/07-regressionlineaire.qmd.json new file mode 100644 index 0000000..3196a78 --- /dev/null +++ b/.quarto/idx/07-regressionlineaire.qmd.json @@ -0,0 +1 @@ +{"title":"Régression linéaire multiple","markdown":{"headingText":"Régression linéaire multiple ","headingAttr":{"id":"sec-chap07","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans ce chapitre, nous présentons la méthode de régression certainement la plus utilisée en sciences sociales : la régression linéaire multiple. À titre de rappel, dans la [section @sec-044], nous avons vu que la régression linéaire simple, basée sur la méthode des moindres carrés ordinaires (MCO), permet d’expliquer et de prédire une variable continue en fonction d’une autre variable. Toutefois, quel que soit le domaine d’étude, il est rare que le recours à une seule variable explicative (*X*) permette de prédire efficacement une variable continue (*Y*). La régression linéaire multiple est simplement une extension de la régression linéaire simple : elle permet ainsi de prédire et d'expliquer une variable dépendante (*Y*) en fonction de plusieurs variables indépendantes (explicatives).\n\nPlus spécifiquement, nous abordons ici les principes et les hypothèses de la régression linéaire multiple, comment mesurer la qualité d’ajustement du modèle, introduire des variables explicatives particulières (variable qualitative dichotomique ou polytomique, variable d’interaction, etc.), interpréter les sorties d’un modèle de régression et finalement la mettre en œuvre dans R.\n\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l’unique!\n - `ggpubr` pour combiner les graphiques\n* Pour obtenir les coefficients standardisés : \n - `QuantPsyc` avec la fonction `lm.beta` ([section @sec-0742]).\n* Pour les effets marginaux des variables indépendantes : \n - `ggeffects` avec la fonction `ggpredict` ([section @sec-0774]).\n* Pour vérifier la normalité des résidus : \n - `DescTools` avec les fonctions `Skewness` et `Kurtosis` et `JarqueBeraTest` ([section @sec-0762]).\n* Pour vérifier l'homoscédasticité des résidus : \n - `lmtest` avec la fonction `bptest` pour le test de Breusch-Pagan ([section @sec-07733]).\n* Pour vérifier la multicolinéarité excessive : \n - `car` avec la fonction `vif` ([section @sec-07734]).\n* Autre *package* : \n - `foreign` pour importer des fichiers externes.\n:::\n:::\n\n## Objectifs de la régression linéaire multiple et construction d'un modèle de régression {#sec-071}\n\nSelon Barbara G. Tabachnich et Linda S. Fidell [-@tabachnick2007], un modèle de régression permet de répondre à deux objectifs principaux relevant chacun d'une approche de modélisation particulière.\n\nLa première approche a pour objectif d’identifier les relations entre une variable dépendante (VD) et plusieurs variables indépendantes (VI). Il s’agit alors de déterminer si ces relations sont positives ou négatives, significatives ou non et d'évaluer leur ampleur. La construction du modèle de régression repose alors sur un cadre théorique et la formulation d’hypothèses, sur les relations entre chacune des VI et la VD.\n\nLa seconde approche est exploratoire et très utilisée en forage ou en fouille de données (*data mining* en anglais). Parmi un grand ensemble de variables disponibles dans un jeu de données, elle vise à identifier la ou les variables permettant de prédire le plus efficacement (précisément) une variable dépendante. Parfois, ce type de démarche ne repose ni sur un cadre théorique ni sur la formulation d’hypothèses entre les VI et la VD. Dans des cas extrêmes, on s’intéresse uniquement à la capacité de prédiction du modèle, et ce, sans analyser les associations entre les VI et la VD. L’objectif étant d’obtenir le modèle le plus efficace possible afin de prédire à l’avenir la valeur de la variable dépendante pour des observations pour lesquelles elle est inconnue. Pour ce faire, nous avons recours à des régressions séquentielles (*stepwise regressions*) dans lesquelles les variables peuvent être ajoutées une à une au modèle ou retirées de celui-ci; nous conserverons dans le modèle final uniquement celles qui ont un apport explicatif significatif. Signalons d’emblée que dans le reste du chapitre, comme du livre, nous ne nous étendons pas plus sur cette approche de modélisation, et ce, pour deux raisons. D’une part, cette approche met souvent en évidence des relations significatives entre des variables sans qu’il y ait une relation de causalité entre elles. D'autre part, en sciences sociales, un modèle de régression doit être basé sur un cadre théorique et conceptuel élaboré à la suite à d'une revue de littérature rigoureuse.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Cadre conceptuel et élaboration d'un modèle de régression**\n:::\n::: bloc_attention-body\nPour bien construire un modèle de régression, il convient de définir un cadre conceptuel élaboré à la suite à une revue de littérature sur le sujet de recherche. Ce cadre conceptuel permet d’identifier les dimensions et les concepts clefs permettant d’expliquer le phénomène à l’étude. Par la suite, pour chacun de ces concepts ou les dimensions, il est alors possible 1) d’identifier les différentes variables indépendantes qui sont introduites dans le modèle et 2) de formuler une hypothèse pour chacune d’elles. Par exemple, pour telle ou telle variable explicative, on s’attendra à ce qu’elle fasse augmenter ou diminuer significativement la variable dépendante. De nouveau, la formulation de cette hypothèse doit s'appuyer sur une interprétation théorique de la relation entre la VI et la VD.\n\nPrenons en guise d'exemple une étude récente portant sur la multiexposition des cyclistes au bruit et à la pollution atmosphérique [@2020_3]. Dans cet article, les auteurs s’intéressent aux caractéristiques de l’environnement urbain qui contribuent à augmenter ou réduire l’exposition des cyclistes à la pollution de l’air et au bruit routier. Pour ce faire, une collecte de données primaires a été réalisée avec trois cyclistes dans les rues de Paris du 4 au 7 septembre 2017. Au total, 64 heures et 964 kilomètres ont ainsi été parcourus à vélo afin de maximiser la couverture de la ville de Paris et les types d'environnements urbains traversés.\n\nLeur cadre conceptuel est schématisé à la @fig-cadreconcept. Les deux variables indépendantes (à expliquer) sont l'exposition au dioxyde d'azote (NO~2~) et l'exposition au bruit (mesurée en décibel dB(A)). Avant d'identifier les caractéristiques de l'environnement urbain affectant ces deux expositions, plusieurs facteurs, dits **variables de contrôle**, sont considérés. Par exemple, la concentration de NO~2~ varie en fonction des conditions météorologiques (vent, température et humidité) et de la pollution d'arrière-plan (variant selon le moment de la journée, le jour de la semaine et la localisation géographique au sein de la ville). Ces dimensions ne sont pas le centre d'intérêt direct de l'étude. En effet, les auteurs s'intéressent aux impacts des caractéristiques locales de l'environnement urbain. Pour pouvoir les identifier sans biais, il est nécessaire de contrôler (filtrer) l'ensemble de ces autres facteurs.\n\nDans leur cadre conceptuel, les auteurs regroupent les caractéristiques locales de l'environnement urbain en trois grandes dimensions : les caractéristiques du segment (type de rues ou de voies cyclables empruntés, intersections traversées, pente et vitesse), celles de la forme urbaine (densité résidentielle, végétation, ouverture de la rue et occupations du sol) et celles du trafic (nombre et types de véhicules croisés, congestion et zones 30 km/h). Une fois ce cadre conceptuel construit, il reste alors à identifier les variables qui permettent d'opérationnaliser chacun de concepts retenus.\n\n\n![Exemple de cadre conceptuel](images/Chap07/CadreTheorique.jpg){#fig-cadreconcept width=\"80%\" fig-align=\"center\"}\n\n\n**Notion de variables de contrôle *versus* variables explicatives**\n\nDans un modèle de régression, nous distinguons habituellement trois types de variables : la variable dépendante (*Y*) que nous souhaitons prédire ou expliquer et les variables indépendantes (*X*) qui peuvent être soit des variables de contrôle (*covariates* en anglais), soit des variables explicatives. Les premières sont des facteurs qu'il faut prendre en compte (contrôler) avant d'évaluer nos variables d'intérêt (explicatives). \n\nDans l'exemple précédent, les chercheurs voulaient évaluer l'impact des caractéristiques de l'environnement urbain (variables explicatives) sur les expositions des cyclistes au dioxyde d'azote et au bruit, et ce, une fois contrôlés les effets de facteurs reconnus comme ayant un impact significatif sur la concentration de ces polluants (conditions météorologiques et la pollution d’arrière-plan). Autrement dit, si les variables de contrôle n'avaient pas été prises en compte, l'étude des variables d'intérêt serait biaisée par les effets de ces facteurs qui n'auraient pas été contrôlés. À titre d'exemple, il est possible que les zones de circulation limitées à 30 km/h soient concentrées dans les quartiers centraux et denses de Paris. Dans ces quartiers, la pollution d'arrière-plan a tendance à être supérieure. Si nous ne tenons pas compte de cette pollution d'arrière-plan, nous pourrions arriver à la conclusion que les zones de 30 km/h sont des milieux dans lesquels les cyclistes sont plus exposés à la pollution atmosphérique.\n\n**Construction de modèles de régression imbriqués, incrémentiels**\n\nEn lien avec le cadre conceptuel du modèle, il est fréquent de construire plusieurs modèles emboîtés. Par exemple, à partir du cadre conceptuel (@fig-cadreconcept), les auteurs auraient très bien pu construire quatre modèles :\n\n* un premier avec uniquement les variables de contrôle (modèle A);\n\n* un second incluant les variables de contrôle et les variables explicatives de la dimension des caractéristiques du segment (modèle B);\n\n* un troisième reprenant les variables du modèle B dans lequel sont introduites les variables explicatives relatives à la forme urbaine (modèle C);\n\n* un dernier modèle dans lequel sont ajoutées les variables explicatives relatives aux conditions du trafic (modèle D).\n\nL’intérêt d’une telle approche est qu'elle permet d’évaluer successivement l’apport explicatif de chacune des dimensions du modèle; nous y reviendrons dans la [section @sec-0732].\n\nNous disons alors que deux modèles sont imbriqués lorsque le modèle avec le plus de variables comprend également **toutes** les variables du modèle avec le moins de variables.\n:::\n:::\n\n\n## Principes de base de la régression linéaire multiple {#sec-072}\n\n### Un peu d'équations... {#sec-0721}\n\nLa régression linéaire multiple vise à déterminer une équation qui résume le mieux les relations linéaires entre une variable dépendante (*Y*) et un ensemble de variables indépendantes (*X*). L'équation de régression s'écrit alors :\n\n$$ \ny_i = \\beta_{0} + \\beta_{1}x_{1i} + \\beta_{2}x_{2i} +\\ldots+ \\beta_{k}x_{ki} + \\epsilon_{i}\n$$ {#eq-regmultiple1}\n\navec :\n\n* $y_i$, la valeur de la variable dépendante *Y* pour l'observation *i*\n\n* $\\beta_{0}$, la constante, soit la valeur prédite pour *Y* quand toutes les variables indépendantes sont égales à 0\n\n* $k$ le nombre de variables indépendantes\n\n* $\\beta_{1}$ à $\\beta_{k}$, les coefficients de régression pour les variables indépendantes de 1 à *k* ($X_{1}$ à $X_{k}$)\n\n* $\\epsilon_{i}$, le résidu pour l'observation de *i*, soit la partie de la valeur de $y_i$ qui n'est pas expliquée par le modèle de régression.\n\nNotez qu'il existe plusieurs écritures simplifiées de cette équation. D'une part, il est possible de ne pas indiquer l'observation *i* et de remplacer les lettres grecques *bêta* et *epsilon* ($\\beta$ et $\\epsilon$) par les lettres *b* et *e* :\n\n$$\nY = b_{0} + b_{1}X_{1} + b_{2}X_{2} +\\ldots+ b_{k}X_{k} + e\n$$ {#eq-regmultiple2}\n\nD'autre part, cette équation peut être présentée sous forme matricielle. Rappelez-vous que, pour chacune des *n* observations de l'échantillon, une équation est formulée :\n\n$$\n\\left\\{\\begin{array}{l}\ny_{1}=\\beta_{0}+\\beta_{1} x_{1,1}+\\ldots+\\beta_{p} x_{1, k}+\\varepsilon_{1} \\\\\ny_{2}=\\beta_{0}+\\beta_{1} x_{2,1}+\\ldots+\\beta_{p} x_{2, k}+\\varepsilon_{2} \\\\\n\\cdots \\\\\ny_{n}=\\beta_{0}+a_{1} x_{n, 1}+\\ldots+\\beta_{p} x_{n, k}+\\varepsilon_{n}\n\\end{array}\\right.\n$$ {#eq-regmultiple3}\n\nPar conséquent, sous forme matricielle, l'équation s'écrit :\n\n$$\n\\left(\\begin{array}{c}\ny_{1} \\\\\n\\vdots \\\\\ny_{n}\n\\end{array}\\right)=\\left(\\begin{array}{cccc}\n1 & x_{1,1} & \\cdots & x_{1, k} \\\\\n\\vdots & \\vdots & \\ddots & \\vdots \\\\\n1 & x_{n, 1} & \\cdots & x_{n, k}\n\\end{array}\\right)\\left(\\begin{array}{c}\n\\beta_{0} \\\\\n\\beta_{1} \\\\\n\\vdots \\\\\n\\beta_{k}\n\\end{array}\\right)+\\left(\\begin{array}{c}\n\\varepsilon_{1} \\\\\n\\vdots \\\\\n\\varepsilon_{n}\n\\end{array}\\right)\n$$ {#eq-regmultiple4}\n\nou tout simplement :\n\n$$\nY = X\\beta + \\epsilon\n$$ {#eq-regmultiple5}\n\navec :\n\n* $Y$, un vecteur de dimension $n \\times 1$ pour la variable dépendante, soit une colonne avec *n* observations\n\n* $X$, une matrice de dimension $n \\times (k + 1)$ pour les *k* variables indépendantes, incluant une autre colonne (avec la valeur de 1 pour les *n* observations) pour la constante d'où $k + 1$\n\n* $\\beta$, un vecteur de dimension $k + 1$, soit les coefficients de régression pour les *k* variables et la constante\n\n* $\\epsilon$, un vecteur de dimension $n \\times 1$ pour les résidus.\n \n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Parties expliquée et non expliquée de la régression linéaire multiple**\n:::\n::: bloc_attention-body\nVous aurez compris que, comme pour la régression linéaire simple ([section @sec-044]), l'équation de la régression linéaire multiple comprend aussi une partie expliquée et une autre non expliquée (stochastique) par le modèle :\n$$\nY = \\underbrace{\\beta_{0} + \\beta_{1}X_{i} + \\beta_{2}X_{i} +\\ldots+ \\beta_{k}X_{k}}_{\\mbox{partie expliquée par le modèle}}+ \\underbrace{\\epsilon}_{\\mbox{partie non expliquée (stochastique)}}\n$$ {#eq-regmultiple6}\n\n$$\nY = \\underbrace{X\\beta}_{\\mbox{partie expliquée par le modèle}}+ \\underbrace{\\epsilon}_{\\mbox{partie non expliquée (stochastique)}}\n$$ {#eq-regmultiple8}\n:::\n:::\n\n### Hypothèses de la régression linéaire multiple {#sec-0722}\n\nUn modèle est bien construit s'il respecte plusieurs hypothèses liées à la régression, dont les principales étant :\n\n* **Hypothèse 1**. *La variable dépendante doit être continue et non-bornée*. Quant aux variables indépendantes (VI), elles peuvent être quantitatives (discrètes ou continues) et qualitatives (nominale ou ordinale).\n\n* **Hypothèse 2**. *La variance de chaque VI doit être supérieure à 0*. Autrement dit, toutes les observations ne peuvent avoir la même valeur.\n\n* **Hypothèse 3**. *Indépendance des termes d'erreur*. Les résidus des observations ($\\epsilon_{1}, \\epsilon_{2}, \\ldots, \\epsilon_{n}$) ne doivent pas être corrélés entre eux. Autrement dit, les observations doivent être indépendantes les unes des autres, ce qui n'est souvent pas le cas pour des mesures temporelles. Par exemple, l'application du cadre conceptuel sur la modélisation de l'exposition des cyclistes au bruit et à la pollution atmosphérique (@fig-cadreconcept)) est basée sur des données primaires collectées lors de trajets réalisés à vélo dans une ville donnée. Par conséquent, deux observations qui se suivent ont bien plus de chances de se ressembler – du point de vue des mesures de pollution et des caractéristiques de l'environnement urbain – que deux observations tirées au hasard dans le jeu de données. Ce problème d'autocorrélation temporelle doit être contrôlé, sinon, les coefficients de régression seront biaisés.\n\n* **Hypothèse 4**. *Normalité des résidus* avec une moyenne centrée sur zéro.\n\n* **Hypothèse 5**. *Absence de colinéarité parfaite entre les variables explicatives*. Par exemple, dans un modèle, nous ne pouvons pas introduire à la fois les pourcentages de locataires et de propriétaires, car pour chaque observation, la somme des deux donne 100 %. Nous avons donc une corrélation parfaite entre ces deux variables : le coefficient de corrélation de Pearson entre ces deux variables est égal à 1. Par conséquent, le modèle ne peut pas être estimé avec ces deux variables et l'une des deux est automatiquement ôtée.\n\n* **Hypothèse 6**. *Homoscédasticité des erreurs (ou absence d'hétéroscédasticité)*. Les résidus doivent avoir une variance constante, c'est-à-dire qu'elle doit être la même pour chaque observation. Il y a homoscédasticité lorsqu'il y a une absence de corrélation entre les résidus et les valeurs prédites. Si cette condition n'est pas respectée, nous parlons alors d'hétéroscédasticité.\n\n* **Hypothèse 7**. *Le modèle est bien spécifié*. Un modèle est mal spécifié (construit) quand « une ou plusieurs variables non pertinentes sont incluses dans le modèle » ou « qu’une ou plusieurs variables pertinentes sont exclues du modèle » [@bressoux2010, p.138-139]. Concrètement, l'inclusion d'une variable non pertinente ou l'omission d'une variable peut entraîner une mauvaise estimation des effets des variables explicatives du modèle.\n\nPour connaître les conséquences de la violation de chacune de ces hypothèses, vous pourrez notamment consulter l'excellent ouvrage de Bressoux [-@bressoux2010, p.103-110]. Retenez ici que le non-respect de ces hypothèses produit des coefficients de régression biaisés.\n\n\n## Évaluation de la qualité d’ajustement du modèle {#sec-073}\n\nPour illustrer la régression linéaire multiple, nous utilisons un jeu de données tiré d'un article portant sur la distribution spatiale de la végétation sur l'île de Montréal abordée sous l'angle de l'équité environnementale [@apparicio2016spatial]. Dans cette étude, les auteurs veulent vérifier si certains groupes de population (personnes à faible revenu, minorités visibles, personnes âgées et enfants de moins de 15 ans) ont ou non une accessibilité plus limitée à la végétation urbaine. En d’autres termes, cet article tente de répondre à la question suivante : une fois contrôlées les caractéristiques de la forme urbaine (densité de population et âge du bâti), est-ce que les quatre groupes de population résident dans des îlots urbains avec proportionnellement moins ou plus de végétation?\n\nDans le @tbl-datareg, sont reportées les variables utilisées (calculées au niveau des îlots de l'île de Montréal) introduites dans le modèle de régression : \n\n* le pourcentage de la superficie de l'îlot couverte par de la végétation, soit la variable indépendante (VI);\n\n* deux variables indépendantes de contrôle (VC) relatives à la forme urbaine;\n\n* les pourcentages des quatre groupes de population comme variables indépendantes explicatives (VE).\n\n**Notez que ce jeu de données est utilisé tout au long du chapitre.** L'équation de départ du premier modèle de régression est donc :\n\n`VegPct ~ HABHA + AgeMedian + Pct_014 + Pct_65P + Pct_MV + Pct_FR`\n\n```{r}\n#| label: tbl-datareg\n#| tbl-cap: Statistiques descriptives pour les variables du modèle\n#| echo: false\n#| message: false\n#| warning: false\nsource(\"code_complementaire/JG_helper.R\")\nload(\"data/lm/DataVegetation.RData\")\nvars <- c(\"VegPct\" , \"HABHA\" , \"AgeMedian\" , \"Pct_014\" , \"Pct_65P\" , \"Pct_MV\" , \"Pct_FR\")\nintitule <- c(\"Végétation (%)\" , \"Habitants au km2\" , \"Âge médian des bâtiments\" , \"Moins de 15 ans (%)\" , \"65 ans et plus (%)\" , \"Minorités visibles (%)\" , \"Personnes à faible revenu (%)\")\ntype <- c(\"VD\" , \"VC\" , \"VC\" , \"VE\" , \"VE\" , \"VE\" , \"VE\")\n\nmoy <- round(sapply(DataFinal[vars], mean),1)\net <- round(sapply(DataFinal[vars], sd),1)\nq1 <- round(sapply(DataFinal[vars], quantile)[2,],1)\nq2 <- round(sapply(DataFinal[vars], median),1)\nq3 <- round(sapply(DataFinal[vars], quantile)[4,],1)\n\nstats <- data.frame(cbind(moy, et, q1, q2, q3))\nstats <- cbind(vars, intitule, type, stats)\n\nknitr::kable(stats,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n digits = 1,\n col.names = c(\"Nom\" , \"Intitulé\" , \"Type\", \"Moy.\", \"E.-T.\", \"Q1\", \"Q2\", \"Q3\"),\n align= c(\"l\" , \"l\" , \"c\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\n\n### Mesures de la qualité d'un modèle {#sec-0731}\n\nComme pour la régression linéaire simple ([section @sec-044]), les trois mesures les plus couramment utilisées pour évaluer la qualité d'un modèle sont :\n\n* Le **coefficient de détermination** (R^2^) qui indique la proportion de la variance de la variable dépendante expliquée par les variables indépendantes du modèle (@eq-regmR2). Il varie ainsi de 0 à 1.\n\n* La **statistique de Fisher** qui permet d'évaluer la significativité globale du modèle (@eq-regmFFisher). Dans le cas d'une régression linéaire multiple, l'hypothèse nulle du test *F* est que toutes les valeurs des coefficients de régression des variables indépendantes sont égales à 0; autrement dit, qu'aucune des variables indépendantes n'a d'effet sur la variable dépendante. Tel que décrit à la [section @sec-0443], il est possible d'obtenir une valeur de *p* rattachée à la statistique *F* avec *k* degrés de liberté au dénominateur et *n-k-1* degrés de liberté au numérateur (*k* et *n* étant respectivement le nombre de variables indépendantes et le nombre d'observations). Lorsque la valeur de *p* est inférieure à 0,05, nous pourrons en conclure que le modèle est globalement significatif, c'est-à-dire qu'au moins un coefficient de régression est significativement différent de zéro. Notez qu'il est plutôt rare qu'un modèle de régression, comprenant plusieurs variables indépendantes, soit globalement non significatif (P > 0,05), et ce, surtout s'il est basé sur un cadre conceptuel et théorique solide. Le test de la statistique de Fisher est donc facile à passer et ne constitue pas une preuve absolue de la pertinence du modèle.\n\n* **L'erreur quadratique moyenne (RMSE)** qui indique l'erreur absolue moyenne du modèle exprimée dans l'unité de mesure de la variable dépendante, autrement dit l'écart absolu moyen entre les valeurs observées et prédites du modèle (@eq-regmRMSE). Une valeur élevée indique que le modèle se trompe largement en moyenne et inversement.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Rappel sur la décomposition de la variance et calcul du R^2^, de la statistique *F* et du RMSE**\n:::\n::: bloc_attention-body\nRappelez-vous que la variance totale (SCT) est égale à la somme de la variance expliquée (SCE) par le modèle et de la variance non expliquée (SCR) par le modèle.\n\n$$\n\\underbrace{\\sum_{i=1}^n (y_{i}-\\bar{y})^2}_{\\mbox{variance de Y}} = \\underbrace{\\sum_{i=1}^n (\\widehat{y}_i-\\bar{y})^2}_{\\mbox{var. expliquée}} + \\underbrace{\\sum_{i=1}^n (y_{i}-\\widehat{y})^2}_{\\mbox{var. non expliquée}} \\Rightarrow \nSCT = SCE + SCR\n$$ {#eq-regmVariances}\n\navec :\n\n* $y_{i}$ est la valeur observée de la variable dépendante pour *i*;\n* $\\bar{y}$ est la valeur moyenne de la variable dépendante;\n* $\\widehat{y}_i$ est la valeur prédite de la variable dépendante pour *i*.\n\nÀ partir des trois variances (totale, expliquée et non expliquée), il est alors possible de calculer les trois mesures de la qualité d'ajustement du modèle.\n\n$$\nR^2 = \\frac{\\sum_{i=1}^n (\\widehat{y}_i-\\bar{y})^2}{\\sum_{i=1}^n (y_{i}-\\bar{y})^2} = \\frac{SCE}{SCT} \\mbox{ avec } R^2 \\in \\left[0,1\\right]\n$$ {#eq-regmR2}\n\n$$\nF = \\frac{\\frac{\\sum_{i=1}^n (\\widehat{y}_i-\\bar{y})^2}{k}}{\\frac{\\sum_{i=1}^n (y_{i}-\\widehat{y})^2}{n-k-1}} = \\frac{\\frac{SCE}{k}}{\\frac{SCR}{n-k-1}} = \\frac{\\frac{R^2}{k}} {\\frac{1-R^2}{n-k-1}} = \\frac{(n-k-1)R^2}{k(1-R^2)}\n$$ {#eq-regmFFisher}\n\n$$\nRMSE = \\sqrt{\\frac{\\sum_{i=1}^n (y_{i}-\\widehat{y})^2}{n}} = \\sqrt{\\frac{SCR}{n}}\n$$ {#eq-regmRMSE}\n\n:::\n:::\n\nGlobalement, plus un modèle de régression est efficace, plus les valeurs du R^2^ et de la statistique *F* sont élevées et inversement, plus celle de RMSE est faible. En effet, remarquez qu'à l'@eq-regmFFisher, la statistique *F* peut être obtenue à partir du R^2^; par conséquent, plus la valeur du R^2^ est forte (proche de 1), plus celle de *F* est aussi élevée. Notez aussi que plus un modèle est performant, plus la partie expliquée par le modèle (SCE) est importante et plus celle non expliquée (SCR) est faible; ce qui signifie que plus le R^2^ est proche de 1 (@eq-regmR2), plus le RMSE – calculé à partir du SCR – est faible (@eq-regmRMSE).\n\nLa syntaxe R ci-dessous illustre comment calculer les différentes variances (SCT, SCE et SCR) à partir des valeurs observées et prédites par le modèle, puis les valeurs du R^2^, de *F* et du RMSE. Nous verrons par la suite qu'il est possible d'obtenir directement ces valeurs à partir de la fonction `summary(VotreModele)`.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Chargement des données\nload(\"data/lm/DataVegetation.RData\")\n\n# Construction du modèle de régression\nModele1 <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n\n# Nombre d'observations \nn <- nrow(DataFinal)\n# Nombre de variables indépendantes (coefficients moins la constante)\nk <- length(Modele1$coefficients)-1\n# Vecteur pour les valeurs observées\nYobs <- DataFinal$VegPct\n# Vecteur pour les valeurs prédites\nYpredit <- Modele1$fitted.values\n# Variance totale\nSCT <- sum((Yobs-mean(Yobs))^2)\n# Variance expliquée\nSCE <- sum((Ypredit-mean(Yobs))^2)\n# Variance résidelle\nSCR <- sum((Yobs-Ypredit)^2)\n# Calcul du coefficient de détermination (R2)\nR2 <- SCE / SCT\n# Calcul de la valeur de F\nvaleurF <- (R2 / k) /((1-R2)/(n-k-1))\n\ncat(\"R2 =\", round(SCE / SCT,4),\n \"\\nF de Fisher = \", round(valeurF,0),\n \"\\nRMSE =\", round(sqrt(SCR/ n),4)\n )\n```\n\n\n### Comparaison des modèles incrémentiels {#sec-0732}\n\nTel que signalé plus haut, il est fréquent de construire plusieurs modèles de régression imbriqués. Cette démarche est très utile pour évaluer l'apport de l'introduction d'un nouveau bloc de variables dans un modèle. De manière exploratoire, cela permet également de vérifier si l'introduction d'une variable indépendante supplémentaire dans un modèle a ou non un apport significatif et ainsi de décider de la conserver, ou non, dans le modèle final selon le principe de parcimonie. \n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Le principe de parcimonie** \n:::\n::: bloc_notes-body\nLe principe de parcimonie appliqué aux régressions correspond à l'idée qu'il est préférable de disposer d'un **modèle plus simple** que d'un **modèle compliqué** pour expliquer un phénomène si la qualité de leurs prédictions – qualité d’ajustement des deux modèles – est équivalente.\n\nUne première justification de ce principe trouve son origine dans la philosophie des sciences avec le **rasoir d'Ockham**. Il s'agit d'un principe selon lequel il est préférable de privilégier des théories faisant appel à un plus petit nombre d'hypothèses. L'idée centrale étant d'éviter d'apporter des réponses à une question qui soulèveraient davantage de nouvelles questions. Dans le cas d'une régression, nous pourrions être tenté d'ajouter de nombreuses variables indépendantes pour améliorer la capacité de prédiction du modèle. Cette stratégie conduit généralement à observer des relations contraires à nos connaissances entre les variables du modèle, ce qui soulève de nouvelles questions de recherche (pas toujours judicieuses…). Dans notre quotidien, si une casserole tombe de son support, il est plus raisonnable d'imaginer que nous l'avions mal fixée que d'émettre l'hypothèse qu'un fantôme l'a volontairement fait tomber! Cette seconde hypothèse soulève d’autres questions (pas toujours judicieuses…) sur la nature d'un fantôme, son identité, la raison le poussant à agir, etc.\n\nUne seconde justification de ce principe s'observe dans la pratique statistique : des modèles plus complexes ont souvent une plus faible capacité de généralisation. En effet, un modèle complexe et trop bien ajusté aux données observées est souvent incapable d'effectuer des prédictions justes pour de nouvelles données. Ce phénomène est appelé surajustement ou surinterprétation (*overfitting* en anglais). \nLe surajustement résultant de modèles trop complexes entre en conflit direct avec l'enjeu principal de l'inférence en statistique : pouvoir généraliser des observations faites sur un échantillon au reste d'une population.\n\nNotez que ce principe de parcimonie ne signifie pas que vous devez systématiquement retirer toutes les variables non significatives de votre analyse. En effet, il peut y avoir un intérêt théorique à démontrer l'absence de relation entre des variables. Il s'agit plutôt d'une ligne de conduite à garder à l'esprit lors de l'élaboration du cadre théorique et de l'interprétation des résultats.\n:::\n:::\n\nMathématiquement, plus nous ajoutons de variables supplémentaires dans un modèle, plus le R^2^ augmente. On ne peut donc pas utiliser directement le R^2^ pour comparer deux modèles de régression ne comprenant pas le même nombre de variables indépendantes. Nous privilégions alors l'utilisation du R^2^ ajusté qui, comme illustré dans l'@eq-R2ajuste, tient compte à la fois des nombres d'observations et des variables indépendantes utilisées pour construire le modèle.\n\n$$ \nR^2_{\\text {ajusté}}= 1 - \\frac{(1-R^2)(n-1)}{n-k-1} \\mbox{ avec } R^2_{\\text {ajusté}} \\in \\left[0,1\\right]\n$$ {#eq-R2ajuste}\n\nSi le R^2^ ajusté du second modèle est supérieur au premier modèle, cela signifie qu'il y a un gain de la variance expliquée entre le premier et le second modèle. Ce gain est-il pour autant significatif? Pour y répondre, il convient de comparer les valeurs des statistiques *F* des deux modèles. Pour ce faire, nous calculons le *F* incrémentiel et la valeur de *p* qui lui est associé avec comme degrés de liberté, le nombre de variables indépendantes ajoutées ($k_2-k_1$) et $n-k_2-1$. Si la valeur de *p* < 0,05, nous pouvons conclure que le gain de variance expliquée par le second modèle est significatif comparativement au premier modèle (au seuil de 5 %). \n\n$$\nF_{\\text {incrémentiel}}= \\frac{\\frac{R^2_2-R^2_1}{k_2-k_1}} {\\frac{1-R^2_2}{n-k_2-1}}\n$$ {#eq-Fincrementiel}\n\navec $R^2_1$ et $R^2_2$ étant les coefficients de détermination des modèles 1 et 2 et $k_1$ et $k_2$ étant les nombres de variables indépendantes qu'ils comprennent ($k_2 > k_1$).\n\nIllustrons le tout avec deux modèles. Dans la syntaxe R ci-dessous, nous avons construit un premier modèle avec uniquement les variables de contrôle (`modele1`), soit deux variables indépendantes (`HABHA` et `AgeMedian`). Puis, dans un second modèle (`modele2`), nous ajoutons comme variables indépendantes les pourcentages des quatre groupes de population (`Pct_014`, `Pct_65P`, `Pct_MV`, `Pct_FR`). Repérez comment sont calculés les R^2^ ajustés pour les modèles et le *F* incrémentiel.\n\nLe R^2^ ajusté passe de 0,269 à 0,418 des modèles 1 à 2 signalant que l'ajout des quatre variables indépendantes augmente considérablement la variance expliquée. Autrement dit, le second modèle est bien plus performant. Le *F* incrémentiel s'élève à 653,8 et est significatif (*p* < 0,001). Notez que la syntaxe ci-dessous illustre comment calculer les valeurs du R^2^ ajusté et du *F* incrémentiel à partir des équations [-@eq-R2ajuste] et [-@eq-Fincrementiel]. Sachez toutefois qu'il est possible d'obtenir directement le R^2^ ajusté avec la fonction `summary(VotreModele)` et le *F* incrémentiel avec la fonction `anova(modele1, modele2)`. \n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nmodele1 <- lm(VegPct ~ HABHA+AgeMedian, data = DataFinal)\nmodele2 <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n\n# nombre d'observations pour les deux modèles\nn1 <- length(modele1$fitted.values)\nn2 <- length(modele2$fitted.values)\n\n# nombre de variables indépendantes\nk1 <- length(modele1$coefficients)-1\nk2 <- length(modele2$coefficients)-1\n\n# coefficient de détermination\nR2m1 <- summary(modele1)$r.squared\nR2m2 <- summary(modele2)$r.squared\n\n# coefficient de détermination ajusté\nR2ajustm1 <- 1-(((n1-1)*(1-R2m1)) / (n1-k1-1))\nR2ajustm2 <- 1-(((n2-1)*(1-R2m2)) / (n2-k2-1))\n\n# Statistique F\nFm1 <- summary(modele1)$fstatistic[1]\nFm2 <- summary(modele2)$fstatistic[1]\n\n# F incrémentiel\nFincrementiel <- ((R2m2-R2m1) / (k2 - k1)) / ( (1-R2m2)/(n2-k2-1))\npFinc <- pf(Fincrementiel, k2-k1, n2-k2-1, lower.tail = FALSE)\n\ncat(\"\\nR2 (modèle 1) =\", round(R2m1,4), \n \"; R2 ajusté = \", round(R2ajustm1,4), \n \"; F =\", round(Fm1, 1),\n \"\\nR2 (modèle 2) =\", round(R2m2,4), \n \"; R2 ajusté = \", round(R2ajustm2,4), \n \"; F =\", round(Fm2, 1),\n \"\\nF incrémentiel =\", round(Fincrementiel,1), \n \"; p = \", round(pFinc,3)\n)\n\n# F incrémentiel avec la fonction anova\nanova(modele1, modele2)\n```\n\n\n## Différentes mesures pour les coefficients de régression {#sec-074}\n\nLa fonction `summary(nom du modèle)` permet d'obtenir les résultats du modèle de régression. D'emblée, signalons que le modèle est globalement significatif (*F*(6, 10203) = 1123, *p* = 0,000) avec un R^2^ de 0,4182 indiquant que les variables indépendantes du modèle expliquent 41,82 % de la variance du pourcentage de végétation dans les îlots de l'île de Montréal.\n\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nmodelereg <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\nsummary(modelereg)\n```\n\n### Coefficients de régression : évaluer l'effet des variables indépendantes {#sec-0741}\n\nLes différents résultats pour les coefficients sont reportés au @tbl-dataregmodel2. \n\n**La constante** ($\\beta_0$) est la valeur attendue de la variable dépendante (*Y*) quand les valeurs de toutes les variables indépendantes sont égales à 0. Pour ce modèle, quand les variables indépendantes sont égales à 0, plus du quart de la superficie des îlots serait en moyenne couverte par de la végétation ($\\beta_0$ = 26,36). Notez que la constante n'a pas toujours une interprétation pratique. Il est par exemple très invraisemblable d'avoir un îlot avec de la population dans lequel il n'y aurait aucune personne à faible revenu, aucune personne ne déclarant appartenir à une minorité visible, aucun enfant de moins de 15 ans et aucune personne âgée de 65 ans et plus. La constante a donc avant tout un rôle mathématique dans le modèle.\n\n**Le coefficient de régression** ($\\beta_1$ à $\\beta_k$) indique le changement de la variable dépendante (*Y*) lorsque la variable indépendante augmente d'une unité, toutes choses étant égales par ailleurs. Il permet ainsi d'évaluer l'effet d'une augmentation d'une unité dans laquelle est mesurée la VI sur la VD.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Que signifie l'expression *toutes choses étant égales par ailleurs* pour un coefficient de régression?**\n:::\n::: bloc_attention-body\nAprès l'apprentissage du grec, grâce aux nombreuses équations intégrées au livre, passons au latin! L'expression *toutes choses étant égales par ailleurs* vient du latin *ceteris paribus*, à ne pas confondre avec *c'est terrible Paris en bus* (petite blague formulée par un étudiant ayant suivi le cours *Méthodes quantitatives appliquées en études urbaines* à l'INRS il y a quelques années)! Certains auteurs emploient encore *ceteris paribus* : il est donc possible que vous la retrouviez dans un article scientifique... \n\nPlus sérieusement, l'expression *toutes choses étant égales par ailleurs* signifie que l'on estime l'effet de la variable indépendante sur la variable dépendante, si toutes les autres variables indépendantes restent constantes ou autrement dit, une fois contrôlés tous les autres prédicteurs. \n:::\n:::\n\n```{r}\n#| label: tbl-dataregmodel2\n#| tbl-cap: Différentes mesures pour les coefficients\n#| echo: false\n#| message: false\n#| warning: false\n\ntabreg <- build_table(modelereg, confid = TRUE, std_digits = 3, coef_digits = 3, z_digits = 2, p_digits = 3)\n\nknitr::kable(data.frame(tabreg),\n caption = 'Différentes mesures pour les coefficients',\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Variable\" , \"Coef.\" , \"Erreur type\", \"Valeur de T\", \"P\", \"coef. 2,5 %\", \"coef. 97,5 %\", \"\"),\n align=c(\"l\" , \"r\" , \"r\", \"r\", \"r\", \"r\", \"r\", \"r\"),\n )\n```\n\n\nÀ partir des coefficients du @tbl-dataregmodel2, l'équation du modèle de régression s'écrit alors comme suit :\n\n`VegPct = 26,356 − 0,070 HABHA + 0,011 AgeMedian + 1,084 Pct_014 + 0,401 Pct_65P −0,031 Pct_MV − 0,348 Pct_FR + e`\n\n\n**Comment interpréter un coefficient de régression pour une variable indépendante?**\n\nLe signe du coefficient de régression indique si la variable indépendante est associée positivement ou négativement avec la variable dépendante. Par exemple, plus la densité de population est importante à travers les îlots de l'île de Montréal, plus la couverture végétale diminue.\n\nQuant à la valeur absolue du coefficient, elle indique la taille de l'effet du prédicteur. Par exemple, 1,084 signifie que si toutes les autres variables indépendantes restent constantes, alors le pourcentage de végétation dans l'îlot augmente de 1,084 points de pourcentage pour chaque différence d’un point de pourcentage d'enfants de moins de 15 ans. Toutes choses étant égales par ailleurs, une augmentation de 10 % d'enfants dans un îlot entraîne alors une hausse de 10,8 % de la couverture végétale dans l'îlot.\n\nL'analyse des coefficients montre ainsi qu'une fois contrôlées les deux caractéristiques relatives à la forme urbaine (densité de population et âge médian des bâtiments), plus les pourcentages d'enfants et de personnes âgées sont élevés, plus la couverture végétale de l'îlot est importante (B = 1,084 et 0,401), toutes choses étant égales par ailleurs. À l'inverse, de plus grands pourcentages de personnes à faible revenu et de minorités sont associés à une plus faible couverture végétale (B = −0,348 et −0,031).\n\n\n**L'erreur type du coefficient de régression**\n\nL'erreur type d'un coefficient permet d'évaluer son niveau de précision, soit le degré d'incertitude vis-à-vis du coefficient. Succinctement, elle correspond à l'écart-type de l'estimation (coefficient); elle est ainsi toujours positive. Plus la valeur de l'erreur type est faible, plus l'estimation du coefficient est précise. Notez toutefois qu'il n'est pas judicieux de comparer les erreurs types des coefficients pour des variables exprimées dans des unités de mesure différentes. \n\nComme nous le verrons plus loin, l'utilité principale de l'erreur type est qu'elle permet de calculer la valeur de *t* et l'intervalle de confiance du coefficient de régression.\n\n\n### Coefficients de régression standardisés : repérer les variables les plus importantes du modèle {#sec-0742}\n\nUn coefficient de régression est exprimé dans les unités de mesure des variables indépendante (VI) et dépendante (VD) : une augmentation d’une unité de la VI a un effet de $\\beta$ (valeur de coefficient) unité de mesure sur la VD, toutes choses étant égales par ailleurs. Prenons l’exemple d’un modèle fictif dans lequel une variable indépendante mesurée en mètres obtient un coefficient de régression de 0,000502. Si cette variable était exprimée en kilomètres et non en mètres, son coefficient serait alors de 0,502 ($0,000502 \\times 1000 = 0,502$). Cela explique que pour certaines variables, il est souvent préférable de modifier l'unité de mesure, particulièrement pour les variables de distance ou de revenu. Par exemple, dans un modèle de régression, nous introduisons habituellement une variable de revenu par tranche de mille dollars ou le loyer mensuel par tranche de cent dollars, puisque les coefficients du revenu ou de loyer exprimé en dollars risquent d'être extrêmement faibles. Concrètement, cela signifie que nous divisons la variable *revenu* par 1000 et celle du *loyer* par 100 avant de l'introduire dans le modèle.\n\nDu fait de leur unités de mesure souvent différentes, vous aurez compris que nous ne pouvons pas comparer directement les coefficients de régression afin de repérer la ou les variables indépendantes (*X*) qui ont les effets (impacts) les plus importants sur la variable dépendante (*Y*). Pour remédier à ce problème, nous utilisons les **coefficients de régression standardisés**. Ces coefficients standardisés sont simplement les valeurs de coefficients de régression qui seraient obtenus si toutes les variables du modèle (VD et VI) étaient préalablement centrées réduites (soit avec une moyenne égale à 0 et un écart-type égal à 1; consultez la [section @sec-02552] pour un rappel). Puisque toutes les variables du modèle sont exprimées en écarts-types, les coefficients standardisés permettent ainsi d'évaluer **l'effet relatif** des VI sur la VD. Cela permet ainsi de repérer la ou les variables les plus « importantes » du modèle.\n\n**L'interprétation d'un coefficient de régression standardisé est donc la suivante : il indique le changement en termes d'unités d'écart-type de la variable dépendante (Y) à chaque ajout d'un écart-type de la variable indépendante, toutes choses étant égales par ailleurs**. \n\n\nLe coefficient de régression standardisé peut être aussi facilement calculé en utilisant les écarts-types des deux variables VI et VD :\n\n$$\n\\beta_{z}= \\beta \\frac{s_x}{s_y}\n$$ {#eq-CoefStand}\n\nLa syntaxe R ci-dessous illustre trois façons d'obtenir les coefficients standardisés :\n\n* en centrant et réduisant préalablement les variables avec la fonction `scale` avant de construire le modèle avec la fonction `lm`;\n\n* en calculant les écarts-types de VD et de VI et en appliquant l'@eq-CoefStand;\n\n* avec la fonction `lm.beta` du *package* `QuantPsyc`. Cette dernière méthode est moins « verbeuse » (deux lignes de code uniquement), mais nécessite de charger un *package* supplémentaire.\n\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Modèle de régression\nModele1 <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n\n# Méthode 1 : lm sur des variables centrées réduites\nModeleZ <- lm(scale(VegPct) ~ scale(HABHA)+scale(AgeMedian)+\n scale(Pct_014)+scale(Pct_65P)+\n scale(Pct_MV)+scale(Pct_FR), data = DataFinal)\ncoefs <- ModeleZ$coefficients\ncoefs[1:length(coefs)]\n\n# Méthode 2 : à partir de l'équation\n# Écart-type de la variable dépendante\nVDet <- sd(DataFinal$VegPct)\ncat(\"Écart-type de Y =\", round(VDet,3))\n# Écarts-types des variables indépendantes\nVI <- c(\"HABHA\" , \"AgeMedian\" , \"Pct_014\" , \"Pct_65P\" , \"Pct_MV\" , \"Pct_FR\")\nVIet <- sapply(DataFinal[VI], sd)\n# Coefficients de régression du modèle sans la constante\ncoefs <- Modele1$coefficients[1:length(VIet)+1]\n# Coefficients de régression du modèle\ncoefstand <- coefs * (VIet / VDet)\ncoefstand\n\n# Méthode 3 : avec la fonction lm.beta du package QuantPsyc\nlibrary(QuantPsyc)\nlm.beta(lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal))\n\n```\n\n```{r}\n#| label: tbl-CoefStand2\n#| tbl-cap: Calcul des coefficients standardisés\n#| echo: false\n#| message: false\n#| warning: false\n# Construction d'un tableau pour les coefficients\nTabCoef <- data.frame(V1 = VI, V2 = round(VIet,3), V3 = round(coefs,3), V4 = round(coefstand,3))\nknitr::kable(TabCoef,\n digits = 3,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Variable dépendante\", \"Écart-type\" , \"Coef.\", \"Coef. standardisé\"),\n align=c(\"l\" , \"r\" , \"r\" , \"r\")\n )\n```\n\nPar exemple, pour la variable `Pct_014`, le coefficient de régression standardisé est égal à : \n\n$$\n\\beta_{z}= 1,084 \\times \\frac{5,295}{18,562}=0,309\n$$ {#eq-CoefStand2}\n\navec 1,084 étant le coefficient de régression de `Pct_014`, 5,295 et 18,562 étant respectivement les écarts-types de `Pct_014` (variable indépendante) et de `VegPct` (variable dépendante).\n\nAu @tbl-CoefStand2, nous constatons que la valeur absolue du coefficient de régression pour `HABHA` est inférieure à celle de `Pct_65P` (−0,070 *versus* 0,401), ce qui n'est pas le cas pour leur coefficient standardisé (−0,281 *versus* 0,179). Rappelez-vous aussi que nous ne pouvons pas directement comparer les effets de ces deux variables à partir des coefficients de régression puisqu'elles sont exprimées dans des unités de mesure différentes : `HABHA` est exprimée en habitants par hectare et `Pct_65P` en pourcentage. À la lecture des coefficients standardisés, nous pouvons en conclure que la variable `HABHA` a un effet relatif plus important que `Pct_65P` (−0,281 *versus* 0,179).\n\n### Significativité des coefficients de régression : valeurs de *t* et de *p* {#sec-0743}\n\nUne fois les coefficients de régression obtenus, il convient de vérifier s'ils sont ou non significativement différents de 0. Si le coefficient de régression d'une variable indépendante est significativement différent de 0, nous concluons que la variable a un effet significatif sur la variable dépendante, toutes choses étant égales par ailleurs. Pour ce faire, il suffit de calculer la valeur de *t* qui est simplement le coefficient de régression divisé par son erreur type.\n\n$$\nt=\\frac{\\beta_k - 0}{s(\\beta_k)} \n$$ {#eq-ValeurT}\n\navec $s(\\beta_k)$ étant l'erreur type du coefficient de régression. Notez que dans l'@eq-ValeurT, nous indiquons habituellement $-0$, pour signaler que l'on veut vérifier si le coefficient est différent de 0. En guise d'exemple, au @tbl-dataregmodel2, la valeur de *t* de la variable `HABHA` est bien égale à :\n\n$\\mbox{−0,070401 / 0,002202 = −31,975}$.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Démarche pour vérifier si un coefficient est significativement différent de 0**\n:::\n::: bloc_attention-body\n1. Poser l'hypothèse nulle (*H~0~*) stipulant que le coefficient est égal à 0, soit $H_0 : \\beta_k = 0$. L'hypothèse alternative (*H~1~*) est que le coefficient est différent de 0, soit $H_1 : B_k \\neq 0$.\n\n2. Calculer la valeur de *t*, soit le coefficient de régression divisé par son erreur type (@eq-ValeurT).\n\n3. Calculer le nombre de degrés de liberté, soit $dl = n − k - 1$, *n* et *k* étant respectivement les nombres d'observations et de variables indépendantes.\n\n4. Choisir un seuil de signification alpha (5 %, 1 % ou 0,1 %, soit *p* = 0,05, 0,01 ou 0,01).\n\n5. Trouver la valeur critique de *t* dans la table T de Student ([section @sec-143]) avec *p* et le nombre de degrés de liberté (*dl*).\n\n6. Valider ou réfuter l'hypothèse nulle (*H~0~*) :\n\n - si la valeur de *t* est inférieure à la valeur critique de *t* avec *dl* et le seuil choisi, nous confirmons *H~0~* : le coefficient n'est pas significativement différent de 0.\n\n - si la valeur de *t* est supérieure à la valeur critique de *t* avec *dl* et le seuil choisi, nous réfutons l'hypothèse nulle, et choisissons l'hypothèse alternative (*H~1~*) stipulant que le coefficient est significativement différent de 0.\n\n\n**Valeurs critiques de la valeur de *t* à retenir!**\n\nLorsque le nombre de degrés de liberté (*n − k - 1*) est très important (supérieur à 2500), et donc le nombre d'observations de votre jeu de données, nous retenons habituellement les valeurs critiques suivantes : **1,65 (*p* = 0,10), 1,96 (*p* = 0,05)**, **2,58 (*p* = 0,01)** et **3,29 (*p*=0,001)**. Concrètement, cela signifie que :\n\n* une valeur de *t* supérieure à 1,96 ou inférieure à -1,96 nous informe que la relation entre la variable indépendante et la variable dépendante est significative positivement ou négativement au seuil de 5 %. Autrement dit, vous avez moins de 5 % de chances de vous tromper en affirmant que le coefficient de régression est bien significativement différent de 0.\n\n* une valeur de *t* supérieure à 2,58 ou inférieure à -2,58 nous informe que la relation entre la variable indépendante et la variable dépendante est significative positivement ou négativement au seuil de 5 %. Autrement dit, vous avez moins de 1 % de chances de vous tromper en affirmant que le coefficient de régression est bien significativement différent de 0.\n\n* une valeur de *t* supérieure à 3,29 ou inférieure à -3,29 nous informe que la relation entre la variable indépendante et la variable dépendante est significative positivement ou négativement au seuil de 5 %. Autrement dit, vous avez moins de 0,1 % de chances de vous tromper en affirmant que le coefficient de régression est bien significativement différent de 0.\n\nConcrètement, retenez et utilisez les seuils de $\\pm\\mbox{1,96}$, $\\pm\\mbox{2,58}$ et $\\pm\\mbox{3,29}$ pour repérer les variables significatives positivement ou négativement aux seuils respectifs de 0,5, 0,1 et 0,001.\n\n**Que signifient les seuils 0,10, 0,05 et 0,001?**\n\nL'interprétation exacte des seuils de significativité des coefficients d'une régression est quelque peu alambiquée, mais mérite de s'y attarder. En effet, indiquer qu'un coefficient est significatif est souvent perçu comme un argument fort pour une théorie, il est donc nécessaire d'avoir du recul et de bien comprendre ce que l'on entend par **significatif**. \n\nSi un coefficient est significatif au seuil de 5 % dans notre modèle, cela signifie que si, pour l’ensemble d’une population, la valeur du coefficient est de 0 en réalité, alors nous avions moins de 5 % de chances de collecter un échantillon (pour cette population) ayant produit un coefficient aussi fort que celui que nous observons dans notre propre échantillon. Par conséquent, il serait très invraisemblable que le coefficient soit 0 puisque nous avons effectivement collecté un tel échantillon. Il s'agit d'une forme d'argumentation par l'absurde propre à la statistique fréquentiste. \n\nNotez que si 100 études étaient conduites sur le même sujet et dans les mêmes conditions, nous nous attendrions à ce que 5 d'entre elles trouvent un coefficient significatif, du fait de la variation des échantillons. Ce constat souligne le fait que la recherche est un effort collectif et qu'une seule étude n'est pas suffisante pour trancher sur un sujet. Les revues systématiques de la littérature sont donc des travaux particulièrement importants pour la construction du consensus scientifique.\n\n**Ne pas confondre significativité et effet de la variable indépendante**\n\nAttention, un coefficient significatif n’est pas toujours intéressant! Autrement dit, bien qu’il soit significatif à un seuil donné (par exemple, *p* = 0,05), cela ne veut pas dire pour autant qu’il ait un effet important sur la variable dépendante. Il faut donc analyser simultanément les valeurs de *p* et des coefficients de régression.\nAfin de mieux saisir l'effet d'un coefficient significatif, il est intéressant de représenter graphiquement l’effet marginal d’une variable indépendante (VI) sur une variable dépendante (VD), une fois contrôlées les autres VI du modèle de régression ([section @sec-0774]).\n:::\n:::\n\nPrenons deux variables indépendantes du @tbl-dataregmodel2 – `HABHA` et `AgeMedian` – et vérifions si leurs coefficients de régression respectifs (−0,070 et 0,011) sont significatifs. Appliquons la démarche décrite dans l'encadré ci-dessus :\n\n1. Nous posons l'hypothèse nulle stipulant que la valeur de ces deux coefficients est égale à 0, soit $H_0 : \\beta_k = 0$.\n\n2. La valeur de *t* est égale à `−0,070401 / 0,002202 = −31,97139` pour `HABHA` et à `0,010790 / 0,006369 = 1,694144` pour `AgeMedian`.\n\n3. Le nombre de degrés de liberté est égal à $\\mbox{dl} = \\mbox{n}-\\mbox{k}-\\mbox{1} = \\mbox{10 210} − \\mbox{6} - \\mbox{1} = \\mbox{10 203}$.\n\n4. Nous choisissons respectivement les seuils $\\alpha$ de 0,10, 0,05, 0,01 ou 0,001.\n\n5. Avec 10210 degrés de liberté, les valeurs critiques de la table T de Student ([section @sec-133]) sont de 1,65 (*p* = 0,10), 1,96 (*p* = 0,05), 2,58 (*p* = 0,01), 3,29 (*p* = 0,001).\n\n6. Il reste à valider ou réfuter l'hypothèse nulle (*H~0~*) :\n - pour `HABHA`, la valeur absolue de *t* (−31,975) est supérieure à la valeur critique de 3,29. Son coefficient de régression est donc significativement différent de 0. Autrement dit, ce prédicteur a un effet significatif et négatif sur la variable dépendante.\n\n - pour `AgeMedian`, la valeur absolue de *t* (1,694) est supérieure à 1,65 (*p* = 0,10), mais inférieure à 1,96 (*p* = 0,05), à 2,58 (*p* = 0,01), à 3,29 (*p* = 0,001). Par conséquent, ce coefficient est différent de 0 uniquement au seuil de *p* = 0,10 et non au seuil de *p* = 0,05. Cela signifie que bous avons un peu moins de 10 % de chances de se tromper en affirmant que cette variable a un effet significatif sur la variable dépendante.\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Calculer et obtenir des valeurs de *p* dans R**\n:::\n::: bloc_astuce-body\nIl est très rare d'utiliser la table *T* de Student pour obtenir un seuil de significativité. D'une part, il est possible de calculer directement la valeur de *p* à partir de la valeur de *t* et du nombre de degrés de liberté avec la fonction `pt` avec les paramètres suivants :\n\n`pt(q= abs(valeur de T), df= nombre de degrés de liberté, lower.tail = FALSE) *2`\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Degrés de liberté\ndl <- nrow(DataFinal) - (length(Modele1$coefficients) - 1) + 1\n\n# Valeurs de T\nValeurT <- summary(Modele1)$coefficients[,3]\n\n# Calcul des valeurs de P\nValeurP <- pt(q= abs(ValeurT), df= dl, lower.tail = FALSE) *2\n\ndf_tp <- data.frame(\n ValeurT = round(ValeurT,3), \n ValeurP = round(ValeurP,3)\n)\nprint(df_tp)\n```\n\nD'autre part, la fonction `summary` renvoie d'emblée les valeurs de *t* et de *p*. Par convention, R, comme la plupart des logiciels d'analyses statistiques, utilise aussi des symboles pour indiquer le seuil de signification du coefficient (voir @tbl-CoefStand2) : \n\n '***' _p_ <= 0,001\n \n '**' _p_ <= 0,01 \n \n '*' _p_ <= 0,05 \n \n '.' _p_ <= 0,10\n:::\n:::\n\n\n### Intervalle de confiance des coefficients {#sec-0744}\n\nFinalement, il est possible de calculer l'intervalle de confiance d'un coefficient à partir d'un niveau de signification (habituellement 0,95 ou encore 0,99). Pour ce faire, la fonction `confint(nom du modèle, level=.95)` est très utile. L'intérêt de ces intervalles de confiance pour les coefficients de régression est double :\n\n* Il permet de vérifier si le coefficient est ou non significatif au seuil retenu. Pour cela, la borne inférieure et la borne supérieure du coefficient doivent être toutes deux négatives ou positives. À l'inverse, un intervalle à cheval sur 0, soit avec une borne inférieure négative et une borne supérieure positive, n'est pas significatif.\n\n* Il permet d'estimer la précision de l'estimation; plus l'intervalle du coefficient est réduit, plus l'estimation de l'effet de la variable indépendante est précise. Inversement, un intervalle large signale que le coefficient est incertain.\n\nCela explique que de nombreux auteurs reportent les intervalles de confiance dans les articles scientifiques (habituellement à 95 %). Dans le modèle présenté ici, il est alors possible d'écrire : toutes choses étant égales par ailleurs, le pourcentage d'enfants de moins de 15 ans est positivement et significativement associé avec le pourcentage de la couverture végétale dans l'îlot (B = 1,084; IC 95 % = [1,021 - 1,148], *p* < 0,001).\n\nEn guise d'exemple, à la lecture de la sortie R ci-dessous, l'estimation de l'effet de la variable indépendante `AgeMedian` sur la variable `VegPct` se situe dans l'intervalle -0,002 à 0,023 qui est à cheval sur 0. Contrairement aux autres variables, nous ne pouvons donc pas en conclure que cet effet est significatif avec *p* = 0,05.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Intervalle de confiance à 95 % des coefficients\nround(confint(Modele1, level=.95),3)\n```\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Comment est calculé un intervalle de confiance?**\n:::\n::: bloc_astuce-body\nL'intervalle du coefficient est obtenu à partir de : \n\n1. la valeur du coefficient ($\\beta_k$),\n\n2. la valeur de son erreur type $s(\\beta_k)$ et \n\n3. la valeur critique de T ($t_{\\alpha/2}$) obtenue avec $n-k-1$ degrés de liberté et le niveau de significativité retenu (95 %, 99 % ou 99,9 %).\n\n\n$$\nIC_{\\beta_k}= \\left[ \\beta_k - t_{\\alpha/2} \\times s(\\beta_k) ; \\beta_k + t_{\\alpha/2} \\times s(\\beta_k) \\right]\n$$ {#eq-ICcoef}\n\nAutrement dit, lorsque vous disposez d'un nombre très important d'observations, les intervalles de confiance s'écrivent simplement avec les fameuses valeurs critiques de T de 1,96, 2,58, 3,29 :\n\n$$\n\\mbox{Intervalle à 95 \\%\\: } IC_{\\beta_k}= \\left[ \\beta_k - 1,96 \\times s(\\beta_k) ; \\beta_k + 1,96 \\times s(\\beta_k) \\right]\n$$ {#eq-IC95}\n\n\n$$\n\\mbox{Intervalle à 99 \\%\\: } IC_{\\beta_k}= \\left[ \\beta_k - 2,58 \\times s(\\beta_k) ; \\beta_k + 2,58 \\times s(\\beta_k) \\right]\n$$ {#eq-IC99}\n\n$$\n\\mbox{Intervalle à 99,9 \\%\\: } IC_{\\beta_k}= \\left[ \\beta_k - 3,29 \\times s(\\beta_k) ; \\beta_k + 3,29 \\times s(\\beta_k) \\right]\n$$ {#eq-IC999}\n\nLa syntaxe R ci-dessous illustre comment calculer les intervalles de confiance à 95 % à partir de l'@eq-ICcoef. Rappelez-vous toutefois qu'il est bien plus simple d'utiliser la fonction `confint`:\n\n* `round(confint(Modele1, level=.95),3) `\n* `round(confint(Modele1, level=.99),3)`\n* `round(confint(Modele1, level=.999),3)`\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Coeffients de régression\ncoefs <- Modele1$coefficients\n\n# Erreur type des coef.\ncoefs_se <- summary(Modele1)$coefficients[,2]\n\n# Nombre de degrés de liberté\nn <- length(Modele1$fitted.values)\nk <- length(Modele1$coefficients)-1\ndl <- n-k-1\n\n# valeurs critiques de T\nt95 <- qt(p=1 - (0.05/2), df=dl)\nt99 <- qt(p=1 - (0.01/2), df=dl)\nt99.9 <- qt(p=1 - (0.001/2), df=dl)\ncat(\"Valeurs critiques de T en fonction du niveau de confiance\",\n \"\\n et du nombre de degrés de liberté\",\n \"\\n95 % : \", t95,\n \"\\n99 % : \", t99,\n \"\\n99,9 % : \", t99.9\n )\n\n# Intervalle de confiance à 95\ndata.frame(\n IC2.5 = round(coefs-t95*coefs_se,3),\n IC97.5 = round(coefs+t95*coefs_se,3)\n )\n# Intervalle de confiance à 99\ndata.frame(\n IC0.5 = round(coefs-t99*coefs_se,3),\n IC99.5 = round(coefs+t99*coefs_se,3)\n)\n# Intervalle de confiance à 99.9\ndata.frame(\n IC0.05 = round(coefs-t99.9*coefs_se,3),\n IC99.95 = round(coefs+t99.9*coefs_se,3)\n )\n```\n:::\n:::\n\n## Introduction de variables explicatives particulières {#sec-075}\n\n### Exploration des relations non linéaires {#sec-0751}\n\n#### Variable indépendante avec une fonction polynomiale {#sec-07511}\n\nDans la [section @sec-041], nous avons vu que la relation entre deux variables continues n'est pas toujours linéaire; elle peut être aussi curvilinéaire. Pour explorer les relations curvilinéaires, nous introduisons la variable indépendante sous la forme polynomiale d'ordre 2 (voir le prochain encadré). L'équation de régression s'écrit alors :\n\n$$\nY = b_{0} + b_{1}X_{1} + b_{11}X_{1}^2 + b_{2}X_{2} +\\ldots+ b_{k}X_{k} + e\n$$ {#eq-regpolyordre2}\n\nDans l'@eq-regpolyordre2, la première variable indépendante est introduite dans le modèle de régression à la fois dans sa forme originelle et mise au carré : $b_{1}X_{1} + b_{11}X_{1}^2$. Un coefficient différent est ajusté pour chacune de ces deux versions de la variable $X_{1}$.\n\nLa démographie est probablement la discipline des sciences sociales qui a le plus recours aux régressions polynomiales. En effet, la variable `âge` est souvent introduite comme variable explicative dans sa forme originale et mise au carré. L'objectif est de vérifier si l'âge partage ou non une relation curvilinéaire avec un phénomène donné : par exemple, il pourrait y être associé positivement jusqu'à un certain seuil (45 ans par exemple), puis négativement à partir de ce seuil.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Régression polynomiale et nombre d'ordres**\n:::\n::: bloc_aller_loin-body\nSachez qu'il est aussi possible de construire des régressions polynomiales avec plus de deux ordres. Par exemple, une régression polynomiale d'ordre 3 comprend une variable dans sa forme originelle, puis mise au carré et au cube. Cela a l'inconvénient d'augmenter corollairement le nombre de coefficients. Nous verrons au [chapitre @sec-chap11] qu'il existe une solution plus élégante et efficace : le recours aux modèles de régressions linéaires généralisés additifs avec des *splines*. Dans le cadre de cette section, nous nous limitons à des régressions polynomiales d'ordre 2.\n\n$$\n\\mbox{Ordre 2 : } Y = b_{0} + b_{1}X_{1} + b_{11}X_{}^2 + b_{2}X_{2} +\\ldots+ b_{k}X_{k} + e\n$$ {#eq-regpolyordre2b}\n\n$$\n\\mbox{Ordre 3 : } Y = b_{0} + b_{1}X_{1} + b_{11}X_{}^2 + b_{111}X_{}^3 + b_{2}X_{2} +\\ldots+ b_{k}X_{k} + e\n$$ {#eq-regpolyordre3}\n\n$$\n\\mbox{Ordre 4 : } Y = b_{0} + b_{1}X_{1} + b_{11}X_{}^2 + b_{111}X_{}^3 + b_{1111}X_{}^4 + b_{2}X_{2} +\\ldots+ b_{k}X_{k} + e\n$$ {#eq-regpolyordre4}\n\n:::\n:::\n\nPour construire une régression polynomiale dans R, il est possible d'utiliser deux fonctions de R :\n\n* `I(VI^2)` avec `VI` qui est la variable indépendante sur laquelle est appliquée la mise au carré.\n* `poly(VI,2)` qui utilise une forme polynomiale orthogonale pour éviter les problèmes de corrélation entre les deux termes, c'est-à-dire entre **VI** et **VI^2^**.\n\nCes deux méthodes produisent les mêmes résultats pour les autres variables dépendantes et pour la qualité d'ajustement du modèle (R^2^, F, etc.). Nous privilégions la seconde fonction pour éviter de détecter à tort des problèmes de multicolinéarité excessive.\n\nAppliquons cette démarche à la variable `AgeMedian` (âge médian des bâtiments) afin de vérifier si elle partage ou non une relation curvilinéaire avec la couverture végétale de l'îlot. À la lecture des résultats pour les deux modèles, les constats suivants peuvent être avancés :\n\n* Le R^2^ ajusté passe de 0,4179 à 0,4378 du modèle 1 au modèle 2, ce qui signale un gain de variance expliquée.\n\n* Le *F* incrémentiel entre les deux modèles s'élève à 362,64 et est significatif (*p* < 0,001). Nous pouvons donc en conclure que le second modèle est plus performant que le premier, ce qui signale que la forme curvilinéaire pour `AgeMedian` (modèle 2) est plus efficace que la forme linéaire (modèle 1).\n\n* Dans le premier modèle, le coefficient de régression pour `AgeMedian` n'est pas significatif. L'âge médian des bâtiments n'est donc pas associé linéairement avec la variable dépendante.\n\n* Dans le second modèle, la valeur du coefficient de `poly(AgeMedian, 2)1` est positive et celle de `poly(AgeMedian, 2)2` est négative et significative. Cela indique qu'il existe une relation linéaire en forme de U inversé. Si le premier coefficient avait été négatif et le second positif, nous aurions alors conclu que la forme curvilinéaire prend la forme d'un U.\n\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# régression linéaire\nmodele1 <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n# régression polynomiale\nmodele2 <- lm(VegPct ~ HABHA+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n# affichage des résultats du modèle 1\nsummary(modele1)\n# affichage des résultats du modèle 1\nsummary(modele2)\n# test de Fisher pour comparer les modèles\nanova(modele1, modele2)\n```\n\n**Construction d'un graphique des effets marginaux**\n\nPour visualiser la relation linéaire et curvilinéaire, nous vous proposons de réaliser un graphique des effets marginaux à partir de la syntaxe ci-dessous.\n\nLes graphiques des effets marginaux permettent de visualiser l'impact d'une variable indépendante sur la variable dépendante d'une régression. Nous nous basons pour cela sur les prédictions effectuées par le modèle. Admettons que nous nous intéressons à l'effet de la variable *X~1~* sur la variable *Y*. Il est possible de créer de nouvelles données fictives pour lesquelles l'ensemble des autres variables *X* sont fixées à leur moyenne respective, et seule *X~1~* est autorisée à varier. En utilisant l'équation de régression du modèle sur ces données fictives, nous pouvons observer l'évolution de la valeur prédite de *Y* quand *X~1~* augmente ou diminue, et ce, toutes choses étant égales par ailleurs (puisque toutes les autres variables ont une valeur fixe). Cette approche est particulièrement intéressante pour décrire des effets non linéaires obtenus avec des polynomiales, mais aussi des interactions comme nous le verrons plus tard. Elle est également utilisée dans les modèles linéaires généralisés (GLM) et additifs (GAM) (chapitres [-@sec-chap08] et [-@sec-chap11]). Notez qu'il est aussi important de représenter, sur ce type de graphique, l'incertitude de la prédiction. Pour cela, il est possible de construire des intervalles de confiance à 95 % autour de la prédiction en utilisant l'erreur standard de la prédiction (renvoyée par la fonction `predict`).\n\n\n```{r}\n#| label: fig-calculRegPoly2\n#| fig-align: center\n#| fig-cap: Relations linéaire et curvilinéaire\n#| out-width: \"75%\"\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(ggplot2)\n# Statistique sur la variable AgeMedian qui varie de 0 à 226 ans\nsummary(DataFinal$AgeMedian)\n\n# Création d'un DataFrame temporaire\n# remarquez que les autres variables indépendantes sont constantes :\n# nous leur avons attribué leur moyenne correspondante\ndf <- data.frame(\n HABHA = mean(DataFinal$HABHA),\n AgeMedian= seq(0,200, by = 2),\n AgeMedian2 = seq(0,200, by = 2)**2,\n Pct_014= mean(DataFinal$Pct_014),\n Pct_65P= mean(DataFinal$Pct_65P),\n Pct_MV= mean(DataFinal$Pct_MV),\n Pct_FR= mean(DataFinal$Pct_FR)\n)\n\n# Calcul de la valeur de t pour un intervalle à 95 %\nn <- length(modele1$fitted.values) \nk <- length(modele1$coefficients)-1\nt95 <- qt(p=1 - (0.05/2), df=n-k-1)\n\n# Calcul des valeurs prédites pour le 1er modèle\n# avec l'intervalle de confiance à 95 %\npredsM1 <- predict(modele1, se = TRUE, newdata = df)\ndf$predM1 <- predsM1$fit\ndf$lowerM1 <- predsM1$fit - t95*predsM1$se.fit\ndf$upperM1 <- predsM1$fit + t95*predsM1$se.fit\n\n# Calcul des valeurs prédites pour le 2e modèle\n# avec l'intervalle de confiance à 95 %\npredsM2 <- predict(modele2, se = TRUE, newdata = df)\ndf$predM2 <- predsM2$fit\ndf$lowerM2 <- predsM2$fit - t95*predsM2$se.fit\ndf$upperM2 <- predsM2$fit + t95*predsM2$se.fit\n\n# Graphique\nggplot(data = df) + \n geom_ribbon(aes(x = AgeMedian, ymin = lowerM1, ymax = upperM1), \n fill = rgb(0.1,0.1,0.1,0.4)) + \n geom_path(aes(x = AgeMedian, y = predM1), color = \"blue\", size = 1)+\n \n geom_ribbon(aes(x = AgeMedian, ymin = lowerM2, ymax = upperM2), \n fill = rgb(0.1,0.1,0.1,0.4)) + \n geom_path(aes(x = AgeMedian, y = predM2), color = \"red\", size = 1)+\n \n labs(title = \"Effet marginal de l'âge médian des bâtiments sur la\",\n subtitle = \"couverture végétale des îlots de l'île de Montréal\",\n caption = \"bleu : relation linéaire; rouge : curvilinéaire\",\n x = \"Âge médian des bâtiments\",\n y = \"Couverture végétale (%)\")\n```\n\nLa @fig-calculRegPoly2 démontre bien que la relation linéaire n'est pas significative : la pente est extrêmement faible, ce qui signale que l'effet de l'âge médian est presque nul (B = 0,0108, *p* = 0,0902). En revanche, la relation curvilinéaire est plus intéressante : la couverture végétale croît quand l'âge médian des bâtiments dans l'îlot augmente de 0 à 60 ans environ, puis elle décroît.\n\n#### Variable indépendante sous forme logarithmique {#sec-07512}\n\nUne autre manière d'explorer une relation non linéaire est d'intégrer la variable sous forme logarithmique [@hanck2019introduction, p.212-218]. L'interprétation du coefficient de régression est alors plus complexe : 1 % d'augmentation de la variable $X_k$ entraîne un changement de $\\mbox{0,01} \\times \\beta_k$ de la variable dépendante. Autrement dit, il n'est plus exprimé dans les unités de mesure originales des deux variables.\n\nAu @tbl-regmodeleLog, le coefficient de `-6,855` pour la variable `logHABHA` s'interprète alors comme suit : un changement de 1 % de la variable densité de population entraîne une diminution de $\\mbox{0,01} \\times -\\mbox{6,855 =} -\\mbox{0,07}$ de la couverture végétale dans l'île, toutes choses étant égales par ailleurs.\n\n```{r}\n#| label: tbl-regmodeleLog\n#| tbl-cap: Modèle avec une variable indépendante sous forme logarithmique\n#| echo: false\n#| message: false\n#| warning: false\nDataFinal$logHABHA <- log(DataFinal$HABHA)\n \nmodelelog <- lm(VegPct ~ logHABHA+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n\ntabreglog <- build_table(modelelog, confid = TRUE, std_digits = 3, coef_digits = 3, z_digits = 2, p_digits = 3)\n\nknitr::kable(data.frame(tabreglog),\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Variable\" , \"Coef.\" , \"Erreur type\", \"Valeur de T\",\n \"P\", \"coef. 2,5 %\", \"coef. 97,5 %\", \"\"),\n align=c(\"l\" , \"r\" , \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\nPuisque l'interprétation du coefficient de régression de $log(\\beta_k)$ est plus complexe, il convient de s'assurer que son apport au modèle est justifié, et ce, de deux façons :\n\n* **Comparez les mesures d'ajustement des deux modèles (surtout les R^2^ ajustés)**. Si le R^2^ ajusté du modèle avec $log(\\beta_k)$ est plus élevé que celui avec $\\beta_k$, alors la transformation logarithmique fait de votre variable indépendante un meilleur prédicteur, toutes choses étant égales par ailleurs. \n\n* **Construisez les graphiques des effets marginaux** de votre variable afin de vérifier si la relation qu'elle partage avec votre VD est plutôt logarithmique que linéaire (@fig-EffetMarginalVariableLogEtNon). Notez que cette approche graphique peut aussi ne donner aucune indication lorsque vos données sont très dispersées ou que la relation est faible entre votre variable dépendante et indépendante.\n\n```{r}\n#| label: fig-EffetMarginalVariableLogEtNon\n#| fig-cap: Effet marginal de la densité de population\n#| fig-align: center\n#| out-width: \"75%\"\n#| echo: true\n#| message: false\n#| warning: false\n\nlibrary(ggpubr)\nlibrary(ggplot2)\nlibrary(ggeffects)\n\n# Modèles\nmodele1a <- lm(VegPct ~ HABHA+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\nmodele1b <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n\n# Valeurs prédites\nfit1a <- ggpredict(modele1a, terms = \"HABHA\")\nfit1b <- ggpredict(modele1b, terms = \"HABHA\")\n# Graphiques\nG1a <- ggplot(fit1a, aes(x, predicted)) +\n geom_point(data = DataFinal, mapping = aes(x = HABHA, y = VegPct),\n size = 0.2, color = rgb(0.1,0.1,0.1,0.4)) + \n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3, fill = \"red\")+\n geom_line(color = \"red\") +\n labs(title = \"Variable non transformée\",\n y = \"VD: valeur prédite\",\n x = \"Habitants km2\") + \n ylim(0,100) + xlim(0,600)\n\nG1b <- ggplot(fit1b, aes(x, predicted)) +\n geom_point(data = DataFinal, mapping = aes(x = HABHA, y = VegPct),\n size = 0.2, color = rgb(0.1,0.1,0.1,0.4)) + \n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3, fill = \"red\")+\n geom_line(color = \"red\") +\n labs(title = \"Variable transformée (log)\",\n y = \"VD: valeur prédite\",\n x = \"Habitants km2\")\n\nG1aG1b <- ggarrange(G1a, G1b, nrow = 1)\nG1aG1b\n```\n\n### Variable indépendante qualitative dichotomique {#sec-0752}\n\nIl est très fréquent d'introduire une variable qualitative dichotomique comme variable explicative ou de contrôle dans un modèle. À titre de rappel, une variable dichotomique comprend deux modalités ([section @sec-0212]). \n\nDans le modèle ci-dessous, nous voulons vérifier si un îlot situé sur le territoire de la ville de Montréal a proportionnellement moins de végétation qu'un îlot situé dans une autre municipalité de l'île de Montréal, toutes choses étant égales par ailleurs. Pour ce faire, nous créons une variable binaire dénommée `VilleMtl` qui prend la valeur de 1 pour les îlots de la ville de Montréal et 0 pour ceux d'une autre municipalité.\n\nNous obtenons ainsi un coefficient de régression pour `VilleMtl` de -7,699 (@tbl-regmodeleDich2). Cela signifie que si toutes les autres variables indépendantes du modèle étaient constantes, alors un îlot de la ville de Montréal aurait en moyenne une valeur de -7,7 % de moins de végétation comparativement à un îlot situé dans une autre municipalité.\n\n```{r}\n#| label: regmodeleDich\n#| echo: true\n#| message: false\n#| warning: false\n\n# Création d'une variable muette pour Montréal (0 ou 1)\nDataFinal$VilleMtl <- ifelse(DataFinal$SDRNOM == \"Montréal\", 1, 0)\n# Modèle avec la variable dichtonomique\nmodele3 <- lm(VegPct ~ VilleMtl+log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n```\n\n\n```{r}\n#| label: tbl-regmodeleDich2\n#| tbl-cap: Modèle avec une variable dichotomique\n#| echo: false\n#| message: false\n#| warning: false\n\ntabreg <- build_table(modele3, confid = TRUE, std_digits = 3, coef_digits = 3, z_digits = 2, p_digits = 3)\n \n knitr::kable(data.frame(tabreg),\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Variable\" , \"Coef.\" , \"Erreur type\", \"Valeur de T\", \"P\", \"coef. 2,5 %\", \"coef. 97,5 %\", \"\"),\n align=c(\"l\" , \"r\" , \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\n \n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Bien interpréter un coefficient d'une variable dichotomique**\n:::\n::: bloc_astuce-body\nNous avons vu que le coefficient de régression ($\\beta_k$) indique le changement de la variable dépendante (*Y*), lorsque la variable indépendante augmente d’une unité, toutes choses étant égales par ailleurs.\n\nPour une variable dichotomique, le coefficient indique le changement de *Y* quand les observations appartiennent à la modalité qui a la valeur de 1 (ici la ville de Montréal), comparativement à celle qui a la valeur de 0 (autres municipalités de l'île de Montréal), toutes choses étant égales par ailleurs.\n\nLa modalité qui a la valeur de 0 est alors appelée **modalité ou catégorie de référence**.\n\nAutrement dit, si la variable avait été codée : 0 pour la ville de Montréal et 1 pour les autres municipalités, alors le coefficient aurait été de 7,699.\n\nPour éviter d'oublier quelle est la modalité de référence (valeur de 0), nous verrons plus tard (dans la section mise en œuvre des modèles de régression dans R ([section @sec-077]) qu'il peut être préférable de définir un facteur avec la fonction `as.factor` et d'indiquer la catégorie de référence avec la fonction `relevel(x, ref)`.\n:::\n:::\n\nComme pour une variable indépendante introduite avec une fonction polynomiale, il peut être très intéressant d'illustrer l'effet marginal de la variable dichotomique avec un graphique qui montre l'écart entre les moyennes des deux modalités, une fois contrôlées les autres variables indépendantes (@fig-EffetMarginalDich). Notez que dans ce graphique, les barres d'erreurs situées au sommet des rectangles représentent les intervalles à 95 % des prédictions du modèle.\n\n```{r}\n#| label: fig-EffetMarginalDich\n#| fig-align: center\n#| fig-cap: Effet marginal d'une variable dichotomique\n#| echo: false\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nlibrary(ggplot2)\nlibrary(ggeffects)\n\n# Valeurs prédites selon le modèle avec la variable dichotomique\ndfPreds <- ggpredict(modele3, terms = \"VilleMtl\")\n# Graphique\nggplot(dfPreds, aes(x = x, y = predicted)) +\n geom_bar(stat = \"identity\", position = position_dodge(), fill = \"wheat\") +\n geom_errorbar(aes(ymin = conf.low, ymax = conf.high), alpha = .9, position = position_dodge(), width = 0.3)+\n labs(title = \"Effet marginal de la ville de Montréal sur la végétation\",\n x = \"Municipalités de la région de Montréal\",\n y = \"Couverture végétale de l'îlot (%)\")+\n scale_x_continuous(breaks=c(0,1),\n labels = c(\"Autres municipalités\", \"Ville de Montréal\"))\n``` \n \n### Variable indépendante qualitative polytomique {#sec-0753}\n\nIl est possible d'introduire une variable qualitative polytomique comme variable explicative ou de contrôle dans un modèle. À titre de rappel, une variable polytomique comprend plus de deux modalités, qu'elle soit nominale ou ordinale ([section @sec-0212]). \n\nEn guise d'exemple, une variable qualitative pourrait être : différents groupes de population (groupes d'âge, minorités visibles, catégories socioprofessionnelles, etc.), différents territoires ou régions (ville centrale, première couronne, deuxième couronne, etc.), une variable continue transformée en quatre ou cinq catégories ordinales selon les quartiles ou les quintiles.\n\n#### Comment construire un modèle de régression avec une variable explicative qualitative polytomique? {#sec-07531}\n\nPrenons l'exemple d'un modèle de régression comprenant deux variables indépendantes : l'une continue (`X1`), l'autre qualitative (`X2`) avec quatre modalités (A, B, C et D). L'introduction de la variable qualitative dans le modèle revient à :\n\n* Transformer chaque modalité en variable muette (binaire). Nous avons ainsi quatre nouvelles variables binaires : `X2A`, `X2B`, `X2C` et `X2D`. Par exemple, pour `X2A`, les observations de la modalité *A* se verront affecter la valeur de 1 versus 0 pour les autres observations. La même démarche s'applique à `X2B`, `X2C` et `X2D` (voir @tbl-transfVarQMuettes).\n\n* Toutes les modalités transformées en variables muettes sont introduites dans le modèle comme variables indépendantes **sauf celle servant de catégorie de référence**. Pourquoi sauf une? Si nous mettions toutes les modalités en variable muette, alors chaque observation serait repérée par une valeur de 1, « il y aurait alors une parfaite multicolinéarité et aucune solution unique pour les coefficients de régression ne pourrait être trouvée » [@bressoux2010, p.128]. \n\n* Par exemple, si nous choisissons la modalité *A* comme catégorie de référence, l'équation de régression s'écrit alors :\n\n\n$$\nY = b_{0} + b_{1}X_{1} + b_{2B}X_{2B} + b_{2C}X_{2C} + b_{2D}X_{2D}+ e\n$$ {#eq-regvarpoly1}\n\n* Vous aurez compris que choisir la modalité *D* comme catégorie de référence revient à écrire l'équation suivante :\n\n$$\nY = b_{0} + b_{1}X_{1} + b_{2A}X_{2A} + b_{2B}X_{2B} + b_{2C}X_{2C} + e\n$$ {#eq-regvarpoly2}\n\n\n```{r}\n#| label: tbl-transfVarQMuettes\n#| tbl-cap: Transformation d'une variable qualitative en variables muettes pour chaque modalité\n#| echo: false\n#| message: false\n#| warning: false\ndf <- data.frame(\n obs = c(1:10),\n Y= round(rnorm(10, mean=50, sd=10),2),\n X1 = round(rnorm(10, mean=20, sd=5),2),\n X2 = c(\"A\" , \"A\" , \"A\" , \"B\" , \"B\" , \"B\" , \"C\" , \"C\" , \"D\" , \"D\")\n )\n\ndf$X2A <- ifelse(df$X2 == \"A\", 1, 0)\ndf$X2B <- ifelse(df$X2 == \"B\", 1, 0)\ndf$X2C <- ifelse(df$X2 == \"C\", 1, 0)\ndf$X2D <- ifelse(df$X2 == \"D\", 1, 0)\n\nknitr::kable(df,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n align= c(\"r\" , \"r\" , \"r\" , \"c\", \"c\", \"c\", \"c\", \"c\")\n )\n```\n\n\n#### Comment interpréter les coefficients des modalités d'une variable explicative qualitative polytomique {#sec-07532}\n\nLes coefficients des différentes modalités s'interprètent en fonction de la catégorie de référence. Dans l'exemple ci-dessous, nous avons inclus la ville de Montréal comme catégorie de référence (@tbl-ModeleVarPoly1). Toutes choses étant égales par ailleurs, nous pouvons alors constater que  :\n\n* en moyenne, les îlots résidentiels de Senneville et de Baie-D’Urfé ont respectivement 23,235 % et 21,400 % plus de végétation que ceux de la ville de Montréal.\n\n* la seule municipalité comprenant en moyenne moins de végétation dans ses îlots résidentiels est Montréal-Est (-13,334 %).\n\n* nous remarquons aussi que les îlots des municipalités de Sainte-Anne-de-Bellevue, de Montréal-Ouest et de Côte-Saint-Luc ne présentent pas significativement moins ou plus de végétation que ceux de la ville de Montréal (leurs valeurs de *p* sont supérieures à 0,05).\n\nPar conséquent, les valeurs de *t* et de *p* pour une modalité permettent de vérifier si elle est ou non significativement différente de la catégorie de référence.\n\n```{r}\n#| label: tbl-ModeleVarPoly1\n#| tbl-cap: Modèle avec une variable polytomique (ville de Montréal en catégorie de référence)\n#| echo: false\n#| message: false\n#| warning: false\nDataFinal$Municipalité <- relevel(DataFinal$SDRNOM, ref = \"Montréal\")\nmodele4a <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+Municipalité, data = DataFinal)\n\ntabreg <- build_table(modele4a, confid = FALSE, std_digits = 3, coef_digits = 3, z_digits = 2, p_digits = 3)\n \n knitr::kable(data.frame(tabreg),\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Variable\" , \"Coef.\" , \"Erreur type\", \"Valeur de T\" , \"P\", \"\"),\n align=c(\"l\" , \"r\" , \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\nUtilisons maintenant comme référence la municipalité qui avait le coefficient le plus fort dans le modèle précédent, soit Senneville (@tbl-ModeleVarPoly2). Bien entendu, les coefficients des variables continues et de la constante ne changent pas. Par contre, les coefficients de toutes les municipalités sont négatifs puisque la municipalité de Senneville est celle qui a proportionnellement le plus de végétation dans ses îlots, toutes choses étant égales par ailleurs.\n\n```{r}\n#| label: tbl-ModeleVarPoly2\n#| tbl-cap: Modèle avec une variable polytomique (Senneville en catégorie de référence\n#| echo: false\n#| message: false\n#| warning: false\nDataFinal$Municipalité <- relevel(DataFinal$SDRNOM, ref = \"Senneville\")\nmodele4b <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+Municipalité, data = DataFinal)\n\ntabreg <- build_table(modele4b, confid = FALSE, std_digits = 3, coef_digits = 3, z_digits = 2, p_digits = 3)\n \n knitr::kable(data.frame(tabreg),\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Variable\" , \"Coef.\" , \"Erreur type\", \"Valeur de T\" , \"P\", \"\"),\n align=c(\"l\" , \"r\" , \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\nÀ l'inverse, si nous utilisons Montréal-Est comme modalité de référence, soit la municipalité avec le coefficient le plus faible dans le premier modèle, tous les coefficients deviendront positifs (@tbl-ModeleVarPoly3).\n\n\n```{r}\n#| label: tbl-ModeleVarPoly3\n#| tbl-cap: Modèle avec une variable polytomique (Montréal-Est en catégorie de référence)\n#| echo: false\n#| message: false\n#| warning: false\nDataFinal$Municipalité <- relevel(DataFinal$SDRNOM, ref = \"Montréal-Est\")\nmodele4c <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+Municipalité, data = DataFinal)\n\ntabreg <- build_table(modele4c, confid = FALSE, std_digits = 3, coef_digits = 3, z_digits = 2, p_digits = 3)\n \n knitr::kable(data.frame(tabreg),\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Variable\" , \"Coef.\" , \"Erreur type\", \"Valeur de T\" , \"P\", \"\"),\n align=c(\"l\" , \"r\" , \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Comment choisir la catégorie de référence?**\n:::\n::: bloc_astuce-body\nPlusieurs options sont possibles. Vous pouvez retenir :\n\n* la modalité comprenant le plus d'observations;\n\n* la modalité avec la plus forte valeur pour la variable dépendante;\n\n* la modalité avec la plus faible valeur pour la variable dépendante;\n\n* la modalité qui fait le plus de sens avec votre cadre théorique. Prenons l'exemple d'une variable qualitative comprenant plusieurs groupes d'âge (15-29 ans, 30-39 ans, 40-49 ans, 50-54 ans, 65 ans et plus). Si votre étude porte sur les jeunes et que vous souhaitez comparer leur situation comparativement aux autres groupes d'âge, toutes choses étant égales par ailleurs, sélectionnez bien évidemment la modalité des 15 à 29 ans comme catégorie de référence.\n\nMais surtout, évitez de choisir une catégorie comprenant très peu d'observations.\n:::\n:::\n\n\n#### Effet marginal d'une variable explicative qualitative polytomique {#sec-07533}\n\nComme pour une variable dichotomique, il est possible d'illustrer l'effet marginal de la variable qualitative dichotomique avec un graphique. Quelle que soit la catégorie de référence choisie, le graphique est le même. La @fig-EffetMarginalPoly illustre ainsi la valeur moyenne, avec son intervalle de confiance à 95 %, de la végétation dans les îlots résidentiels de chacune des municipalités de la région de Montréal, *ceteris paribus*.\n\n```{r}\n#| label: fig-EffetMarginalPoly\n#| fig-align: center\n#| fig-cap: Effet marginal d'une variable polytomique\n#| out-width: \"90%\"\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(ggplot2)\nlibrary(ggeffects)\n\n# Valeurs prédites selon le modèle avec la variable polytomique\ndfPreds <- ggpredict(modele4a, terms = \"Municipalité\")\n# Graphique\nGraphique <- ggplot(dfPreds, aes(x = x, y = predicted)) +\n geom_bar(stat = \"identity\", position = position_dodge(), fill = \"wheat\") +\n geom_errorbar(aes(ymin = conf.low, ymax = conf.high), alpha = .9, position = position_dodge(), width = 0.3)+\n labs(title = \"Effet marginal des différentes municipalités\",\n x = \"Municipalités de la région de Montréal\",\n y = \"Couverture végétation de l'îlot (%)\")\n\nGraphique + coord_flip()\n\n```\n\n\n### Variables d'interaction {#sec-0754}\n\n#### Variable d'interaction entre deux variables continues {#sec-07541}\n\nUne interaction entre deux variables indépendantes continues consiste à simplement les multiplier ($X_1 \\times X_2$). Le modèle s'écrit alors :\n\n$$\nY = \\beta_{0} + \\beta_{1}X_{1} + \\beta_{2}X_{2} + \\beta_{3}(X_{1}\\times X_{2}) +\\ldots+ \\beta_{k}X_{k} + e \n$$ {#eq-reginteractioncontinues}\n\nUn nouveau coefficient ($\\beta_{3}$) s'ajoute pour l'interaction (la multiplication) entre les deux variables continues. **Pourquoi ajouter une interaction entre deux variables?** L'objectif est d'évaluer l'effet d'une augmentation de $\\beta_{1}$ en fonction d'un niveau donné de $\\beta_{2}$ et inversement. Cela permet ainsi de répondre à la question suivante : l'effet de la variable $\\beta_{1}$ est-il influencé par la variable $\\beta_{2}$ et inversement?\n\nPrenons un exemple concret pour illustrer le tout. Premièrement, nous ajoutons `DistCBDkm` comme VI, soit la distance au centre-ville exprimée en kilomètres. Notez que pour ne pas surspécifier le modèle, les variables dichotomique `VilleMtl` ou polytomique `Municipalité` ont été préalablement ôtées. Le coefficient (B = 0,659, *p* < 0,001) signale que plus nous nous éloignons du centre-ville, plus la couverture végétale des îlots augmente significativement. En guise d'exemple, toutes choses étant égales par ailleurs, un îlot situé à dix kilomètres du centre-ville aura en moyenne 6,59 % plus de végétation (@tbl-ModeleInteraction1).\n\n```{r}\n#| label: tbl-ModeleInteraction1\n#| tbl-cap: Modèle avec la distance au centre-ville (km)\n#| echo: false\n#| message: false\n#| warning: false\nmodele5 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR+\n DistCBDkm, data = DataFinal)\n\ntabreg <- build_table(modele5, confid = FALSE, std_digits = 3, coef_digits = 3, z_digits = 2, p_digits = 3)\n \n knitr::kable(data.frame(tabreg),\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Variable\" , \"Coef.\" , \"Erreur type\", \"Valeur de T\" , \"P\" , \"\"),\n align=c(\"l\" , \"r\" , \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\nDans ce modèle (@tbl-ModeleInteraction1), les pourcentages d'enfants de moins de 15 ans et de 65 ans et plus (`Pct_014` et `Pct_65P`) sont associés positivement à la variable dépendante tandis que le pourcentage de personnes à faible revenu (`Pct_FR`) est associé négativement.\n\nQue se passe-t-il si nous introduisons une variable d'interaction entre `DistCBDkm` et `Pct_FR` (@tbl-ModeleInteraction2)? L’effet du pourcentage de personnes à faible revenu (%) est significatif et négatif lorsqu’il est mis en interaction avec la distance au centre-ville. Cela indique que plus l'îlot est éloigné du centre-ville, plus `Pct_FR` a un effet négatif sur la couverture végétale (B = −0,011, *p* < 0,001).\n\n```{r}\n#| label: tbl-ModeleInteraction2\n#| tbl-cap: Modèle avec une variable d'interaction entre deux VI continues\n#| echo: false\n#| message: false\n#| warning: false\nDataFinal$DistCBDkmX_Pct_014 <- DataFinal$DistCBDkm*DataFinal$Pct_014\nDataFinal$DistCBDkmX_Pct_65P <- DataFinal$DistCBDkm*DataFinal$Pct_65\nDataFinal$DistCBDkmX_Pct_MV <- DataFinal$DistCBDkm*DataFinal$Pct_MV\nDataFinal$DistCBDkmX_Pct_FR <- DataFinal$DistCBDkm*DataFinal$Pct_FR \n\nmodele6 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+\n DistCBDkm+\n DistCBDkmX_Pct_FR,\n data = DataFinal)\n\ntabreg <- build_table(modele6, confid = FALSE, std_digits = 3, coef_digits = 3, z_digits = 2, p_digits = 3)\n \n knitr::kable(data.frame(tabreg),\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Variable\" , \"Coef.\" , \"Erreur type\", \"Valeur de T\" , \"P\" , \"\"),\n align=c(\"l\" , \"r\" , \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\nÀ nouveau, il est possible de représenter l'effet de cette interaction à l'aide d'un graphique des effets marginaux. Notez cependant que nous devons représenter l'effet simultané de deux variables indépendantes sur notre variable dépendante, ce qu'il est possible de faire avec une carte de chaleur. La @fig-ModeleInteraction2heat représente donc l'effet moyen de l'interaction sur la prédiction dans le premier panneau, ainsi que l'intervalle de confiance à 95 % de la prédiction dans les deuxième et troisième panneaux. \n\nNous constatons ainsi que le modèle prédit des valeurs de végétation les plus faibles lorsque le pourcentage de personnes à faible revenu est élevé et que la distance au centre-ville est élevée (en haut à droite à la @fig-ModeleInteraction2heat). En revanche, les valeurs les plus élevées de végétation sont atteintes lorsque la distance au centre-ville est élevée et que le pourcentage de personnes à faible revenu est faible (en bas à droite). Il semble donc que l'éloignement au centre-ville soit associé avec une augmentation de la densité végétale, mais que cette augmentation puisse être mitigée par l'augmentation parallèle du pourcentage de personnes à faible revenu.\n\n```{r}\n#| label: fig-ModeleInteraction2heat\n#| fig-cap: Effet marginal de l'interaction entre deux variables continues\n#| out-width: \"95%\"\n#| echo: false\n#| message: false\n#| warning: false\n\nlibrary(metR) # pour ajouter des labels aux contours\nlibrary(viridis) # pour les jolies couleurs\n\ndf <- expand.grid(\n DistCBDkm = seq(0,33,0.1),\n Pct_FR = seq(0,95,1),\n HABHA = mean(DataFinal$HABHA),\n AgeMedian = mean(DataFinal$AgeMedian),\n Pct_014 = mean(DataFinal$Pct_014),\n Pct_65P = mean(DataFinal$Pct_65P),\n Pct_MV = mean(DataFinal$Pct_MV)\n)\n\ndf$DistCBDkmX_Pct_FR <- df$DistCBDkm * df$Pct_FR\npred <- predict(modele6, newdata = df, se = TRUE)\ndf$pred <- pred$fit\ndf$pred_se <- pred$se.fit\ndf$lower <- df$pred - 1.96 * df$pred_se\ndf$upper <- df$pred + 1.96 * df$pred_se\n\nP1 <- ggplot(data = df) + \n geom_tile(aes(x = DistCBDkm, y = Pct_FR, fill = pred)) +\n stat_contour(aes(x = DistCBDkm, y = Pct_FR, z = pred), \n color = \"black\", linetype = \"dashed\") + \n geom_text_contour(aes(x = DistCBDkm, y = Pct_FR, z = pred), )+\n scale_fill_viridis(discrete = FALSE) + \n labs(x = \"Distance au centre-ville\", \n y = \"Pers. à faible revenu (%)\",\n fill = \"\",\n subtitle = \"Densité de végétation prédite (%)\")\n\nP2 <- ggplot(data = df) + \n geom_tile(aes(x = DistCBDkm, y = Pct_FR, fill = lower)) +\n stat_contour(aes(x = DistCBDkm, y = Pct_FR, z = lower), \n color = \"black\", linetype = \"dashed\") + \n geom_text_contour(aes(x = DistCBDkm, y = Pct_FR, z = lower), )+\n scale_fill_viridis(discrete = FALSE)+ \n labs(x = \"Distance au centre-ville\", \n y = \"Pers. à faible revenu (%)\",\n fill = \"\",\n subtitle = \"IC 2,5 %\")\n\nP3 <- ggplot(data = df) + \n geom_tile(aes(x = DistCBDkm, y = Pct_FR, fill = upper)) +\n stat_contour(aes(x = DistCBDkm, y = Pct_FR, z = upper), \n color = \"black\", linetype = \"dashed\") + \n geom_text_contour(aes(x = DistCBDkm, y = Pct_FR, z = upper), )+\n scale_fill_viridis(discrete = FALSE)+ \n labs(x = \"Distance au centre-ville\", \n y = \"Pers à faible revenu (%)\",\n fill = \"\",\n subtitle = \"IC 97,5 %\")\n\nggarrange(P1, P2, P3, common.legend = FALSE, ncol = 2, nrow = 2)\n```\n\nNotez que dans la @fig-ModeleInteraction2heat, la relation entre les deux variables indépendantes et la variable dépendante apparaît non linéaire du fait de l'interaction. À titre de comparaison, si nous utilisons les prédictions du modèle 5 (sans interaction), nous obtenons les prédictions présentées à la @fig-ModeleInteraction2heat2. Vous pouvez constater sur cette figure sans interaction que les deux effets des variables indépendantes sont linéaires puisque toutes les lignes sont parallèles.\n\n```{r}\n#| label: fig-ModeleInteraction2heat2\n#| fig-cap: Effets marginaux de deux variables continues en cas d'absence d'interaction\n#| echo: false\n#| out-width: \"75%\"\n#| message: false\n#| warning: false\ndf <- expand.grid(\n DistCBDkm = seq(0,33,0.1),\n Pct_FR = seq(0,95,1),\n HABHA = mean(DataFinal$HABHA),\n AgeMedian = mean(DataFinal$AgeMedian),\n Pct_014 = mean(DataFinal$Pct_014),\n Pct_65P = mean(DataFinal$Pct_65P),\n Pct_MV = mean(DataFinal$Pct_MV)\n)\n\ndf$DistCBDkmX_Pct_FR <- df$DistCBDkm * df$Pct_FR\npred <- predict(modele5, newdata = df, se = TRUE)\ndf$pred <- pred$fit\ndf$pred_se <- pred$se.fit\ndf$lower <- df$pred - 1.96 * df$pred_se\ndf$upper <- df$pred + 1.96 * df$pred_se\n\nggplot(data = df) + \n geom_tile(aes(x = DistCBDkm, y = Pct_FR, fill = pred)) +\n stat_contour(aes(x = DistCBDkm, y = Pct_FR, z = pred), \n color = \"black\", linetype = \"dashed\") + \n geom_text_contour(aes(x = DistCBDkm, y = Pct_FR, z = pred), )+\n scale_fill_viridis(discrete = FALSE) + \n labs(x = \"Distance au centre-ville\", \n y = \"Pers à faible revenu (%)\",\n fill = \"\",\n subtitle = \"Prédiction de la densité de végétation (%)\")\n```\n\n#### Variable d'interaction entre une variable continue et une variable dichotomique {#sec-07542}\n\nUne interaction entre une VI continue et une VI dichotomique consiste aussi à les multiplier ($X_1 \\times D_2$); le modèle s'écrit alors :\n\n$$\nY = \\beta_{0} + \\beta_{1}X_{1} + \\beta_{2}D_{2} + \\beta_{3}(X_{1}\\times D_{2}) +\\ldots+ \\beta_{k}X_{k} + e \n$$ {#eq-reginteractioncontinuedicho}\n\nPour interpréter le coefficient $B_3$, il convient alors de bien connaître le nom de la modalité ayant la valeur de 1 (0 étant la modalité de référence). Dans le modèle présenté au @tbl-ModeleInteractionBinaire, nous avons multiplié la variable dichotomique ville de Montréal (`VilleMtl`) avec le pourcentage de personnes à faible revenu (`Pct_FR`). Les résultats de ce modèle démontrent que, toutes choses étant égales par ailleurs :\n\n* À chaque augmentation d'une unité du pourcentage à faible revenu (`Pct_FR`), le pourcentage de la couverture végétale diminue significativement de −0,444.\n\n* Comparativement à un îlot situé dans une autre municipalité de l'île de Montréal, un îlot de la ville de Montréal a en moyenne −9,804 de couverture végétale.\n\n* À chaque augmentation d'une unité de `Pct_FR` pour un îlot de la Ville Montréal, la couverture végétale augmente de 0,166 comparativement à une autre municipalité de l'île. En d'autres termes, le `Pct_FR` sur le territoire de la ville de Montréal est associé à une diminution de la couverture végétale moins forte que les autres municipalités, comme illustré à la @fig-ModeleInteractionBinaire) (pentes en rouge et en bleu).\n\n\n```{r}\n#| label: tbl-ModeleInteractionBinaire\n#| tbl-cap: Modèle avec les variables d'interaction entre une VI continue et une VI dichotomique\n#| echo: false\n#| message: false\n#| warning: false\n\nDataFinal$VilleMtlX_Pct_FR <- DataFinal$VilleMtl*DataFinal$Pct_FR \n\nmodele7 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+\n VilleMtl+ VilleMtlX_Pct_FR,\n data = DataFinal)\n\ntabreg <- build_table(modele7, confid = FALSE, std_digits = 3, coef_digits = 3, z_digits = 2, p_digits = 3)\n \n knitr::kable(data.frame(tabreg),\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Variable\" , \"Coef.\" , \"Erreur type\", \"Valeur de T\" , \"P\" , \"\"),\n align=c(\"l\" , \"r\" , \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\nL'interaction entre une variable qualitative et une variable quantitative peut être représentée par un graphique des effets marginaux. La pente (coefficient) de la variable quantitative varie en fonction des deux catégories de la variable qualitative dichotomique (@fig-ModeleInteractionBinaire).\n\n```{r}\n#| label: fig-ModeleInteractionBinaire\n#| fig-cap: Graphique de l’effet marginal de l’interaction entre une variable quantitative et qualitative\n#| fig-align: center\n#| out-width: \"75%\"\n#| echo: false\n#| message: false\n#| warning: false\ndf <- expand.grid(\n VilleMtl = c(0,1),\n Pct_FR = seq(0,95,1),\n HABHA = mean(DataFinal$HABHA),\n AgeMedian = mean(DataFinal$AgeMedian),\n Pct_014 = mean(DataFinal$Pct_014),\n Pct_65P = mean(DataFinal$Pct_65P),\n Pct_MV = mean(DataFinal$Pct_MV)\n)\ndf$VilleMtlX_Pct_FR <- df$VilleMtl * df$Pct_FR\n\npred <- predict(modele7, se = TRUE, newdata = df)\ndf$pred <- pred$fit\ndf$upper <- df$pred + 1.96*pred$se.fit\ndf$lower <- df$pred - 1.96*pred$se.fit\n\ndf$VilleMtl_str <- ifelse(df$VilleMtl==0,\"Autre municipalité\" , \"Ville de Montréal\")\nDataFinal$VilleMtl_str <- ifelse(DataFinal$VilleMtl==0,\"Autre municipalité\" , \"Ville de Montréal\")\n\ncols <- c(\"Autre municipalité\" =\"#1d3557\" ,\"Ville de Montréal\"=\"#e63946\")\n\nggplot(data = df) + \n geom_point(data = DataFinal, mapping = aes(x = Pct_FR, y = VegPct, color = VilleMtl_str), size = 0.2, alpha = 0.2)+\n geom_ribbon(aes(x = Pct_FR, ymin = lower, ymax = upper, group = VilleMtl_str), fill = rgb(0.1,0.1,0.1,0.4))+\n geom_path(aes(x = Pct_FR, y = pred, color = VilleMtl_str), size = 1) + \n scale_colour_manual(values = cols)+\n labs(x = \"Personnes à faible revenu (%)\",\n y = \"Densité de végétation prédite (%)\",\n color = \"\")\n\n```\n\n\n#### Variable d'interaction entre deux variables dichotomiques {#sec-07543}\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Variable d'interaction entre deux variables dichotomiques**\n:::\n::: bloc_aller_loin-body\nNous avons vu qu'il est possible d'introduire une variable d'interaction entre deux variables continues ou entre une variable continue et une autre dichotomique. Sachez qu’il est aussi possible d’introduire une interaction entre deux variables dichotomiques. Sur le sujet, vous pouvez consulter la section 8.3 de l'excellent ouvrage de Hanck et al. [-@hanck2019introduction].\n:::\n:::\n\n## Diagnostics de la régression {#sec-076}\n\nPour illustrer comment vérifier si le modèle respecte ou non les hypothèses de la régression, nous utilisons le modèle suivant :\n\n`modele3 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)`\n\n\n### Nombre d'observations {#sec-0761}\nTous les auteurs ne s'entendent pas sur le nombre d'observations minimal que devrait comprendre une régression linéaire multiple, tant s'en faut! Parallèlement, d'autres auteurs proposent aussi des méthodes de simulation pour estimer les coefficients de régression sur un jeu de données comprenant peu d'observations. Bien qu'aucune règle ne soit bien établie, la question du nombre d'observations mérite d'être posée puisqu'un modèle basé sur trop peu d'observations risque de produire des coefficients de régression peu fiables. Par faible fiabilité des coefficients, nous entendons que la suppression d’une ou de plusieurs observations pourrait drastiquement changer l’effet et/ou la significativité d’une ou de plusieurs variables explicatives.\n\nDans un ouvrage classique intitulé *Using Multivariate Statistics*, Barbara Tabachnick et Linda Fidell [-@tabachnick2007, p.123-124] proposent deux règles de pouce (à la louche) :\n\n1. $n \\geq 50 + 8k$ avec $n$ et $k$ étant respectivement les nombres d'observations et de variables indépendantes, pour tester le coefficient de corrélation multiple (R^2^).\n\n2. $n \\geq 104 + k$ pour tester individuellement chaque variable indépendante.\n\nDans le modèle, nous avons 10 210 observations et variables indépendantes. Les deux conditions sont donc largement respectées.\n\n\n```{r}\n#| eval: false\n#| message: false\n#| warning: false\n#| include: false\nmodele3 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n\n# Nombre d'observation\nnobs <- length(modele3$fitted.values)\n\n# Nombre de variables indépendantes (coefficients moins la constante)\nk <- length(modele3$coefficients)-1\n\n# Première règle de pouce\ncat(\"\\n\", nobs, \" observations incluses dans le modèle avec\",\n \"\\n\", k, \" variables indépendantes.\",\n sep = \"\")\nif(nobs >= 50+(8*k)){\n cat(\"\\nNombre d'observations suffisant pour tester le R2\")\n}else{\n cat(\"\\nAttention! Nombre d'observations insuffisant pour tester le R2\")\n}\n\n# Deuxième règle de pouce\nif(nobs >= 104+k){\n cat(\"\\nNombre d'observations suffisant pour tester individuellement chaque VI\")\n}else{\n cat(\"\\nAttention! Nombre d'observations insuffisant pour tester individuellement chaque VI\")\n}\n```\n\n### Normalité des résidus {#sec-0762}\n\nPour vérifier si les résidus sont normalement distribués, trois démarches largement décrites dans la [section @sec-0254] peuvent être utilisées :\n\n* le calcul des coefficients d’asymétrie et d’aplatissement;\n* les tests de normalité, particulièrement celui de Jarque-Bera basé sur un test multiplicateur de Lagrange;\n* les graphiques (histogramme avec courbe normale et diagramme quantile-quantile) (@fig-VerifierNormaliteResidus).\n\nLes deux premières démarches étant parfois très restrictives, nous accordons habituellement une attention particulière aux graphiques.\n\nPour notre modèle, les coefficients d’asymétrie (−0,263) et d’aplatissement (1,149) signalent que la distribution est plutôt symétrique, mais leptokurtique, c'est-à-dire que les valeurs des résidus sont bien réparties autour de 0, mais avec une faible dispersion. Puisque la valeur de *p* associée au test de Jarque-Bera est inférieure à 0,05, nous pouvons en conclure que la distribution des résidus est anormale. La forme pointue de la distribution est d'ailleurs confirmée à la lecture de l'histogramme avec la courbe normale et du diagramme quantile-quantile.\n\n```{r}\n#| label: fig-VerifierNormaliteResidus\n#| fig-cap: Vérification de la normalité des résidus\n#| out-width: \"75%\"\n#| fig-align: center\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(DescTools)\nlibrary(ggplot2)\nlibrary(ggpubr)\n\n# Vecteur pour les résidus du modèle\nresidus <- modele3$residuals\n\n# 1. coefficients d’asymétrie et d’aplatissement \nc(Skewness= round(DescTools::Skew(residus),3), \n Kurtosis = round(DescTools::Kurt(residus),3))\n\n# 2. Test de normalité de Jarque-Bera\nJarqueBeraTest(residus)\n\n# 3. Graphiques \nGhisto <- ggplot() +\n geom_histogram(aes(x = residus, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n stat_function(fun = dnorm, \n args = list(mean = mean(residus),\n sd = sd(residus)), \n color = \"#e63946\", linewidth = 1.2, linetype = \"dashed\")+\n labs(title = \"Histogramme et courbe normale\",\n y = \"Densité\", x = \"Résidus du modèle\")\n\nGqqplot <- qplot(sample = residus)+\n geom_qq_line(line.p = c(0.25, 0.75),\n color = \"#e63946\", size = 1.2)+\n labs(title = \"Diagramme quantile-quantile\",\n x = \"Valeurs théoriques\",\n y = \"Résidus du modèle\")\n\nggarrange(Ghisto, Gqqplot, ncol = 2, nrow = 1)\n```\n\n### Linéarité et homoscédasticité des résidus {#sec-0763}\n\nUn modèle est efficace si la dispersion des résidus est homogène sur tout le spectre des valeurs prédites de la variable dépendante. Dans le cas d’une absence d’homoscédasticité – appelée problème d'hétéroscédasticité –, le nuage de points construit à partir des résidus et des valeurs prédites (@fig-VerifierHomoscedasticite) prend la forme d’une trompette ou d'un entonnoir : les résidus sont alors faibles quand les valeurs prédites sont faibles et sont de plus en plus élevés au fur et à mesure que les valeurs prédites augmentent.\n\n\n```{r}\n#| label: fig-VerifierHomoscedasticite\n#| fig-cap: Distribution des résidus en fonction des valeurs prédites\n#| fig-align: center\n#| out-width: \"75%\"\n#| echo: false\n#| message: false\n#| warning: false\n\nresidus <- modele3$residuals\nypredits <- modele3$fitted.values\n\nggplot() +\n geom_point(aes(x = ypredits, y = residus),\n color = \"#343a40\", fill = \"#a8dadc\",\n alpha = 0.2, size = 0.8) +\n geom_smooth(aes(x = ypredits, y = residus), \n method = lm, color = \"red\")+\n labs(x = \"Valeurs prédites\", y = \"Résidus\")\n```\n\nLe test de Breusch-Pagan est souvent utilisé pour vérifier l'homoscédasticité des résidus. Il est construit avec les hypothèses suivantes :\n\n* *H~0~* : homoscédasticité, c'est-à-dire que les termes d'erreur ont une variance constante à travers les valeurs prédites.\n\n* *H~1~* : hétéroscédasticité.\n\nSi la valeur de *p* associée à ce test est inférieure à 0,05, nous réfutons l'hypothèse nulle et nous concluons qu'il y a un problème d'hétéroscédasticité, ce qui est le cas pour notre modèle.\n\n\n```{r}\n#| message: false\n#| warning: false\n#| echo: false\nlibrary(lmtest)\nbptest(modele3)\n```\n\n### Absence de multicolinéarité excessive {#sec-0764}\n\nUn modèle présente un problème de multicolinéarité excessive lorsque deux variables indépendantes ou plus sont très fortement corrélées entre elles. Rappelez-vous qu'un coefficient de régression estime l'effet d'une variable dépendante ($X_k$) si toutes les autres VI restent constantes (c'est-à-dire une fois les autres VI contrôlées, toutes choses étant égales par ailleurs...).\n\nPrenons deux variables indépendantes ($X_1$ et $X_2$) fortement corrélées avec un coefficient de Pearson très élevé (0,90 par exemple). Admettons que chacune des deux VI a un effet important et significatif sur votre VD lorsqu’une seule est introduite dans le modèle. Si les deux variables sont introduites dans le même modèle, vous évaluez donc l’effet de $X_1$ une fois contrôlé $X_2$ et l’effet de $X_2$ une fois contrôlé $X_1$. Par conséquent, l’effet de l’une des deux devient très faible, voire probablement non significatif.\n\n#### Comment évaluer la multicolinéarité? {#sec-07641}\n\nPour ce faire, nous utilisons habituellement le facteur d’inflation de la variance (*Variance Inflation Factor – VIF* en anglais). Le calcul de ce facteur pour chaque VI est basé sur trois étapes. \n\n\n1. Pour chaque VI, nous construisons un modèle de régression multiple où elle est expliquée par toutes les autres variables indépendantes du modèle. Par exemple, pour la première VI ($X_1$), l'équation du modèle s'écrit :\n\n\n$$\nX_1 = b_0 + b_2X_2 +\\ldots+ b_kX_k + e\n$$ {#eq-RegVIF}\n\n\n2. À partir de cette équation, nous obtenons ainsi un $R^2$ qui nous indique la proportion de la variance de $X_1$ expliquée par les autres VI. Par convention, nous calculons la tolérance (@eq-ToleranceVIF) qui indique la proportion de la variance de $X_k$ n'étant pas expliquée par les autres VI. En guise d'exemple, une valeur de tolérance égale à 0,1 signale que 90 % de la variance de $X_k$ est expliqué par les autres variables, ce qui est un problème de multicolinéarité en soit. Concrètement, plus la valeur de la tolérance est proche de zéro, plus c’est problématique.\n\n\n$$\n\\mbox{Tolérance}_k=1-R_k^2=\\frac{1}{VIF_k}\n$$ {#eq-ToleranceVIF}\n\n\n3. Puis, nous calculons le facteur d'inflation de la variance (@eq-VIF). Là encore, des règles de pouce (à la louche) sont utilisées. Certains considéreront une valeur de VIF supérieur à 10 (soit une tolérance à 0,1 ou inférieure) comme problématique, d'autres retiendront le seuil de 5 plus conservateur (soit une tolérance à 0,2 ou inférieure).\n\n\n$$\nVIF_k = \\frac{1}{1-R_k^2} \n$$ {#eq-VIF}\n\nPour notre modèle, toutes les valeurs de VIF sont inférieures à 2, indiquant, sans l'ombre d'un doute, l'absence de multicolinéarité excessive.\n\n```{r}\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(car)\nround(car::vif(modele3),3)\n```\n\n#### Comment régler un problème de multicolinéarité? {#sec-07642}\n\n* La prudence est de mise! Si une ou plusieurs variables présentent une valeur de VIF supérieure à 5, construisez une matrice de corrélation de Pearson ([section @sec-0437]) et repérez les valeurs de corrélation supérieures à 0,8 ou inférieures à −0,8. Vous repérerez ainsi les corrélations problématiques entre deux variables indépendantes du modèle.\n\n * Refaites ensuite un modèle en ôtant la variable indépendante avec la plus forte valeur de VIF (7 ou 12 par exemple), et revérifiez les valeurs de VIF. Refaites cette étape si le problème de multicolinéarité excessive persiste.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Une multicolinéarité excessive n'est pas forcément inquiétante**\n:::\n::: bloc_attention-body\nNous avons vu plus haut comment introduire des variables indépendantes particulières comme des variables d'interaction ($X_1 \\times X_2$) ou des variables sous une forme polynomiale (ordre 2 : $X_1 + X_1^2$; ordre 3 : $X_1 + X_1^2 + X_1^3$, etc.). Bien entendu, ces termes composant les variables d'interaction ou d'une forme polynomiale sont habituellement fortement corrélés entre eux. Cela n'est toutefois pas problématique!\n\nDans l'exemple ci-dessous, nous obtenons deux valeurs de VIF très élevées pour la variable d'interaction `Pct_014:DistCBDkm` (16,713) et l'un des paramètres à partir duquel elle est calculée, soit `DistCBDkm` (12,526). \n\n```{r}\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(car)\nmodele6 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+\n DistCBDkm+DistCBDkm*Pct_014,\n data = DataFinal)\n\nround(car::vif(modele6),3)\n```\n:::\n:::\n\n\n### Absence d'observations aberrantes {#sec-0766}\n\n#### Détection des observations très influentes du modèle {#sec-07661} \n\nLors de l'analyse des corrélations ([section @sec-043]), nous avons vu que des valeurs extrêmes peuvent avoir un impact important sur le coefficient de corrélation de Pearson. Le même principe s'applique à la régression multiple, pour laquelle nous nous s'attendrions à ce que chaque observation joue un rôle équivalent dans la détermination de l'équation du modèle.\n\nAutrement dit, il est possible que certaines observations avec des valeurs extrêmes – fortement dissemblables des autres – aient une influence importante, voire démesurée, dans l’estimation du modèle. Concrètement, cela signifie que si elles étaient ôtées, les coefficients de régression et la qualité d'ajustement du modèle pourraient changer drastiquement. Deux mesures sont habituellement utilisées pour évaluer l’influence de chaque observation sur le modèle :\n\n* **La statistique de la distance de Cook** qui mesure l’influence de chaque observation sur les résultats du modèle. Brièvement, la distance de Cook évalue l’influence de l’observation *i* en la supprimant du modèle (@eq-DistanceCook). Plus sa valeur est élevée, plus l’observation joue un rôle important dans la détermination de l’équation de régression.\n\n\n$$\nD_i = \\frac{\\sum_{j=1}^n(\\widehat{y}_i-\\widehat{y}_{i(j)})^2}{ks^2}\n$$ {#eq-DistanceCook}\n\navec $\\widehat{y}_{i(j)}$ la valeur prédite quand l'observation *i* est ôté du modèle, *k* le nombre de variables indépendantes et $s^2$ l'erreur quadratique moyenne du modèle.\n\n* **La statistique de l'effet levier** (*leverage value* en anglais) qui varie de 0 (aucune influence) à 1 (explique tout le modèle). La somme de toutes les valeurs de cette statistique est égale au nombre de VI dans le modèle.\n\n\n**Quel critère retenir pour détecter les observations avec potentiellement une trop grande influence sur le modèle?**\n\nPour les repérer, voire les supprimer, plusieurs auteur(e)s proposent les seuils suivants : $4/n$ ou $8/n$ ou $16/n$. Avec 10210 observations dans le modèle, les seuils seraient les suivants : \n\n```{r}\n#| echo: false\n#| message: false\n#| warning: false\nnobs <- length(modele3$fitted.values)\nDistanceCook <- cooks.distance(modele3)\nn4 <- length(DistanceCook[DistanceCook > 4/nobs])\nn8 <- length(DistanceCook[DistanceCook > 8/nobs])\nn16 <- length(DistanceCook[DistanceCook > 16/nobs])\ncat(\"Nombre d'observations =\", nobs, \"(100 %)\",\n \"\\n 4/n =\", round(4/nobs,5),\n \"\\n 8/n =\", round(8/nobs,5),\n \"\\n 16/n =\", round(16/nobs,5),\n\"\\nObservations avec une valeur supérieure ou égale aux différents seuils\",\n \"\\n 4/n =\", n4, \"soit\", round(n4/nobs*100,2),\"%\",\n \"\\n 8/n =\", n8, \"soit\", round(n8/nobs*100,2),\"%\",\n \"\\n 16/n =\", n16, \"soit\", round(n16/nobs*100,2), \"%\"\n )\n```\n\nLe critère de $4/n$ étant plutôt sévère, nous privilégions généralement celui de $8/n$, voire $16/n$. Il est aussi possible de construire un nuage de points pour les repérer (@fig-GraphCookLev).\n\n\n```{r}\n#| label: fig-GraphCookLev\n#| fig-cap: Repérage graphique les valeurs influentes du modèle\n#| echo: false\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nlibrary(car)\nlibrary(ggpubr)\nDistanceCook <- cooks.distance(modele3)\nLeverageValue <- hatvalues(modele3)\n\nG1 <- ggplot()+\n geom_point(aes(x = LeverageValue, y = DistanceCook), \n alpha = 0.2, size = 2, col = \"black\", fill = \"red\")+\n labs(x = \"Statistique de l'effet levier\",\n y = \"Distance de Cook\",\n title = \"Repérer les valeurs influentes\",\n subtitle = \"(toutes les observations)\")\n\nG2 <- ggplot()+\n geom_point(aes(x = LeverageValue, y = DistanceCook), \n alpha = 0.2, size = 2, col = \"black\", fill = \"red\")+\n ylim(0,0.01)+\n xlim(0,0.01)+\n labs(x = \"Statistique de l'effet levier\",\n y = \"Distance de Cook\",\n title = \"Repérer les valeurs influentes\",\n subtitle = \"(agrandissement)\")\n\nggarrange(G1, G2, nrow = 1, ncol = 2)\n\n```\n\n#### Quoi faire avec les observations très influentes du modèle {#sec-07662} \n\nTrois approches sont possibles :\n\n* **Recourir à des régressions *boostrap***, ce qui permet généralement de supprimer l'effet de ces observations. Brièvement, le principe général est de créer un nombre élevé d'échantillons du jeu de données initial (1000 à 2000 itérations par exemple) et de construire un modèle de régression pour chacun d'eux. On obtiendra ainsi des intervalles de confiance pour les coefficients de régression et les mesures d'ajustement du modèle.\n\n* **Supprimer les observations trop influentes** (avec l'un des critères de $4/n$, $8/n$ et $16/n$ vus plus haut). Une fois supprimées, il convient 1) de recalculer le modèle, 2) de refaire le diagnostic de la régression au complet et finalement, 3) de comparer les modèles avant et après suppression des valeurs trop influentes, notamment la qualité d'ajustement du modèle (R^2^ ajusté) et les coefficients de régression. Des changements importants indiqueront que le premier modèle est potentiellement biaisé.\n\n* **Utiliser un modèle linéaire généralisé (GLM)** permettant d'utiliser une distribution différente correspondant plus à votre jeu de données ([chapitre @sec-chap08]).\n\n\n## Mise en œuvre dans R {#sec-077}\n\n### Fonctions `lm`, `summary()` et `confint()` {#sec-0771}\n\nLes fonctions de base `lm`, `summary()` et `confint()` permettent respectivement 1) de construire un modèle, 2) d'afficher ces résultats et 3) d'obtenir les intervalles de confiance des coefficients de régression : \n\n* `monModele <- lm(Y ~X1+X2+..+Xk)` avec *Y* étant la variable dépendante et les variables indépendantes (`X1 à Xk`) étant séparées par le signe +.\n\n* `summary(monModele)`\n\n* `confint(monModele, level=.95)`.\n\nDans la syntaxe ci-dessous, vous retrouverez les différents modèles abordés dans les sections précédentes; remarquez que toutes que les lignes `summary` sont mises en commentaires afin de ne pas afficher les résultats des modèles.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Chargement des données\nload(\"data/lm/DataVegetation.RData\")\n\n# 1er modèle de régression\nmodele1 <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR,\n data = DataFinal)\n# summary(Modele1)\n\n# 2e modèle de régression : fonction polynomiale d'ordre 2 (poly(AgeMedian,2))\nmodele2 <- lm(VegPct ~ HABHA+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR,\n data = DataFinal)\n# summary(Modele2)\n\n# 3e modèle de régression : forme logarithmique (log(HABHA))\nmodele3 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR,\n data = DataFinal)\n# summary(Modele3)\n\n# 4e modèle de régression : VI dichotomique\n# création de la variable dichotomique (VilleMtl)\nDataFinal$VilleMtl <- ifelse(DataFinal$SDRNOM == \"Montréal\", 1, 0)\nmodele4 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+\n VilleMtl, # variable dichotomique\n data = DataFinal)\n# summary(Modele4)\n\n# 5e modèle de régression : VI polytomique\n# création de la variable polytomique (Munic)\nDataFinal$Munic <- relevel(DataFinal$SDRNOM, ref = \"Montréal\")\nmodele5 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+\n Munic, data = DataFinal)\n# summary(Modele5)\n\n\n# 6e modèle de régression : interaction entre deux VI continues, \n# soit DistCBDkm*Pct_014\nmodele6 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+\n DistCBDkm+DistCBDkm*Pct_014,\n data = DataFinal)\n# summary(Modele6)\n\n# 7e modèle de régression : interaction entre une VI continue et une VI dichotomique,\n# soit VilleMtl*Pct_FR\nmodele8 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR+\n VilleMtl*Pct_FR,\n data = DataFinal)\n# summary(Modele7)\n```\n\n\nÀ la @fig-OutputRegression, les résultats de la régression linéaire multiple, obtenus avec la `summary(monModele)`, sont présentés en quatre sections distinctes :\n\na. Le rappel de l'équation du modèle.\n\nb. Quelques statistiques descriptives sur les résidus du modèle, soit la différence entre les valeurs observées et prédites.\n\nc. Un tableau pour les coefficients de régression comprenant plusieurs colonnes, à savoir les coefficients de régression (`Estimate`), l'erreur type du coefficient (`Std. Error`), la valeur de *t* (`t value`) et la probabilité associée à la valeur de *t* (`Pr(>|t|)`). La première ligne de ce tableau (`Estimate`) est pour la constante (*Intercept* en anglais) et celles qui suivent sont pour les variables indépendantes.\n\nd. Les mesures d'ajustement du modèle, dont le RMSE (`Residual standard error`), les R^2^ classique (`Multiple R-squared`) et ajusté (`Adjusted R-squared`), la statistique *F* avec le nombre de degrés de liberté en lignes (nombre d'observations) et en colonnes (*n-k-1*) ainsi que la valeur de *p* qui est lui associée (`F-statistic: 1223 on 6 and 10203 DF, p-value: < 2.2e-16`).\n\n![Différentes parties obtenues avec la fonction `summary(Modèle)`](images/Chap07/SortiesLM.jpg){#fig-OutputRegression width=\"75%\" fig-align=\"center\"}\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Intervalle de confiance des coefficients à 95 %\nconfint(modele3)\n```\n\n\n### Comparaison des modèles {#sec-0772}\n\nTel que détaillé à la [section @sec-0732], pour comparer des modèles imbriqués, il convient d'analyser les valeurs du R^2^ ajusté et du *F* incrémentiel, ce qui peut être fait en trois étapes.\n\n**Première étape.** Il peut être judicieux d'afficher l'équation des différents modèles afin de se remémorer les VI introduites dans chacun d'eux, et ce, avec la fonction `MonModèle$call$formula`.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Rappel des équations des huit modèles \nprint(modele1$call$formula)\nprint(modele2$call$formula)\nprint(modele3$call$formula)\nprint(modele4$call$formula)\nprint(modele5$call$formula)\nprint(modele6$call$formula)\nprint(modele7$call$formula)\n```\n\n**Deuxième étape.** La syntaxe ci-dessous vous permet de comparer les R^2^ ajustés des différents modèles. Nous constatons ainsi que :\n\n* La valeur du R^2^ ajusté du modèle 2 est supérieure à celle du modèle 1 (0,4378 versus 0,4179), signalant que la forme polynomiale d'ordre 2 pour l'âge médian des bâtiments (`poly(AgeMedian, 2)`) améliore la prédiction comparativement à la forme originelle de (`AgeMedian`).\n\n* La valeur du R^2^ ajusté du modèle 3 est supérieure à celle du modèle 2 (0,4653 versus 0,4378), signalant que la forme logarithmique pour la densité de population (`log(HABHA)`) améliore la prédiction comparativement à la forme originelle (`HABHA`).\n\n* La valeur du R^2^ ajusté du modèle 4 est supérieure à celle du modèle 3 (0,4863 versus 0,4653), signalant que l'introduction de la variable dichotomique (`VilleMtl`) pour la municipalité apporte un gain de variance expliquée non négligeable.\n\n* La valeur du R^2^ ajusté du modèle 5 est supérieure à celle du modèle 4 (0,5064 versus 0,4863), signalant que l'introduction de la variable polytomique pour les municipalités de l'île de Montréal (`Muni`) améliore la prédiction du modèle comparativement à la variable dichotomique (`VilleMtl`).\n\n* La valeur du R^2^ ajusté du modèle 6 est supérieure à celle du modèle 2 (0,4953 versus 0,4378), signalant que l'introduction d'une variable d'interaction entre deux variables continues (`DistCBDkm + DistCBDkm * Pct_014`) apporte également un gain substantiel comparativement au modèle 2, ne comprenant pas cette variable d'interaction.\n\n* La valeur du R^2^ ajusté du modèle 7 est supérieure à celle du modèle 2 (0,4877 versus 0,4378), signalant que l'introduction d'une variable d'interaction entre une variable continue et la variable dichotomique (`DistCBDkm + DistCBDkm * Pct_014`) apporte également un gain substantiel comparativement au modèle 2, ne comprenant pas cette variable d'interaction.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\ncat(\"\\nComparaison des R2 ajustés :\",\n \"\\nModèle 1.\", round(summary(modele1)$adj.r.squared,4), \n \"\\nModèle 2.\", round(summary(modele2)$adj.r.squared,4), \n \"\\nModèle 3.\", round(summary(modele3)$adj.r.squared,4), \n \"\\nModèle 4.\", round(summary(modele4)$adj.r.squared,4), \n \"\\nModèle 5.\", round(summary(modele5)$adj.r.squared,4), \n \"\\nModèle 6.\", round(summary(modele6)$adj.r.squared,4), \n \"\\nModèle 7.\", round(summary(modele7)$adj.r.squared,4)\n)\n```\n\n**Troisième étape.** La syntaxe ci-dessous permet d'obtenir le *F* incrémentiel pour des modèles ne comprenant pas le même nombre de variables dépendantes, et ce, en utilisant la fonction `anova(modele1, modele2, ..., modelen)`.\n\nPar exemple, la syntaxe `anova(modele1, modele2)` permet de comparer les deux modèles et signale que le gain de variance expliquée entre les deux modèles (R^2^ de 0,4179 et de 0,4378) est significatif (*F* incrémentiel = 362,64; *p* < 0,001).\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Comparaison des deux modèles uniquement (modèles 1 et 2)\nanova(modele1, modele2)\n```\n\nIl est aussi possible de comparer plusieurs modèles simultanément. Notez que dans la syntaxe ci-dessous, le troisième modèle n'est pas inclus, car il comprend le même nombre de variables indépendantes que le second modèle; il en va de même pour le sixième modèle comparativement au cinquième. Ici aussi, l'analyse des valeurs de *F* et de *p* vous permettent de vérifier si les modèles, et donc leurs R^2^ ajustés, sont significativement différents (quand *p* < 0,05).\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Comparaison de plusieurs modèles\nanova(modele1, modele2, modele4, modele5, modele7)\n```\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Quel modèle choisir?** \n:::\n::: bloc_attention-body\nNous avons déjà évoqué le principe de parcimonie. À titre de rappel, l'ajout de variables indépendantes qui s'avèrent significatives fait inévitablement augmenter la variance expliquée et ainsi la valeur R^2^ ajusté. Par contre, elle peut rendre le modèle plus complexe à analyser, voire entraîner un surajustement du modèle. Nous avons vu que l'introduction des variables ditchtomique, polytomique et d'interaction avait pour effet d'augmenter la capacité de prédiction du modèle. Quoi qu'il en soit, le gain de variance expliquée s'élève à environ 4 % entre le troisième modèle versus le cinquième et le sixième :\n\n* Modèle 3 (R^2^=0,465). `VegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + Pct_MV + Pct_FR`\n* Modèle 5 (R^2^=0,506). `VegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + Muni`\n* Modèle 6 (R^2^=0,495). `VegPct ~ log(HABHA) + poly(AgeMedian, 2) + Pct_014 + Pct_65P + Pct_MV + Pct_FR + DistCBDkm + DistCBDkm * Pct_014`\n\nPar conséquent, il est légitime de se questionner sur le bien-fondé de conserver ces variables indépendantes additionnelles : `Muni` pour le modèle 5 et `DistCBDkm + DistCBDkm * Pct_014` pour le modèle 6. Trois options sont alors envisageables :\n\n* Bien entendu, conservez l'une ou l'autre de ces variables additionnelles si elles sont initialement reliées à votre cadre théorique.\n\n* Conservez l'une ou l'autre de ces variables additionnelles si elles permettent de répondre à une question spécifique (non prévue initialement) et si les associations ainsi révélées méritent, selon vous, discussion.\n\n* Supprimez-les si leur apport est limité et ne fait que complexifier le modèle.\n:::\n:::\n\n### Diagnostic sur un modèle {#sec-0773}\n\n#### Vérification le nombre d'observations {#sec-07731}\n\nLa syntaxe suivante permet de vérifier si le nombre d'observations est suffisant pour tester le R^2^ et chacune des variables indépendantes.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nmodele3 <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n# Nombre d'observation\nnobs <- length(modele3$fitted.values)\n# Nombre de variables indépendantes (coefficients moins la constante)\nk <- length(modele3$coefficients)-1\n# Première règle de pouce\nif(nobs >= 50+(8*k)){\n cat(\"\\nNombre d'observations suffisant pour tester le R2\")\n}else{\n cat(\"\\nAttention! Nombre d'observations insuffisant pour tester le R2\")\n}\n# Deuxième règle de pouce\nif(nobs >= 104+k){\n cat(\"\\nNombre d'observations suffisant pour tester individuellement chaque VI\")\n}else{\n cat(\"\\nAttention! Nombre d'observations insuffisant\",\n \"\\npour tester individuellement chaque VI\")\n}\n```\n\n#### Vérification la normalité des résidus {#sec-07732}\n\nLa syntaxe suivante permet de vérifier la normalité des résidus selon les trois démarches classiques : 1) coefficients d’asymétrie et d’aplatissement, 2) test de normalité de Jarque-Bera (fonction `JarqueBeraTest` du *package* `DescTools`) et 3) les graphiques (histogramme avec courbe normale et diagramme quantile-quantile).\n\n\n```{r}\n#| label: fig-VerifierNormaliteResidusDia\n#| fig-cap: \"Diagnostic : la normalité des résidus\"\n#| fig-align: center\n#| echo: true\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nlibrary(DescTools)\nlibrary(stats)\nlibrary(ggplot2)\nlibrary(ggpubr)\n\n# Vecteur pour les résidus du modèle\nresidus <- modele3$residuals\n# 1. coefficients d’asymétrie et d’aplatissement \nc(Skewness= round(DescTools::Skew(residus),3), \n Kurtosis = round(DescTools::Kurt(residus),3))\n# 2. Test de normalité de Jarque-Bera\nJarqueBeraTest(residus)\n# 3. Graphiques \nGhisto <- ggplot() +\n geom_histogram(aes(x = residus, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n stat_function(fun = dnorm, \n args = list(mean = mean(residus),\n sd = sd(residus)), \n color = \"#e63946\", size = 1.2, linetype = \"dashed\")+\n labs(title = \"Histogramme et courbe normale\",\n y = \"densité\", \"Résidus du modèle\")\n\nGqqplot <- qplot(sample = residus)+\n geom_qq_line(line.p = c(0.25, 0.75),\n color = \"#e63946\", size = 1.2)+\n labs(title = \"Diagramme quantile-quantile\",\n x = \"Valeurs théoriques\",\n y = \"Résidus\")\nggarrange(Ghisto, Gqqplot, ncol = 2, nrow = 1)\n```\n\n#### Évaluation de la linéarité et l'homoscédasticité des résidus {#sec-07733}\n\nLa syntaxe suivante permet de vérifier si l'hypothèse d'homoscédasticité des résidus est respectée avec : 1) un nuage de points entre les valeurs prédites et des résidus, 3) les graphiques (histogramme avec courbe normale et diagramme quantile-quantile) et 2) le test de Breusch-Pagan (fonction `bptest` du *package* `lmtest`).\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| fig-show: hide \n\n# 1. Test de Breusch-Pagan pour vérifier l'homoscédasticité\nlibrary(lmtest)\nbptest(modele3)\n\nif(bptest(modele3)$p.value < 0.05){\n cat(\"\\nAttention : problème d'hétéroscédasticité des résidus\")\n}else{\n cat(\"\\nParfait : homoscédasticité des résidus\")\n}\n\n# 2. Graphique entre les valeurs prédites et les résidus\nresidus <- modele3$residuals\nypredits <- modele3$fitted.values\n\nggplot() +\n geom_point(aes(x = ypredits, y = residus),\n color = \"#343a40\", fill = \"#a8dadc\",\n alpha = 0.2, size = 0.8) +\n geom_smooth(aes(x = ypredits, y = residus), \n method = lm, color = \"red\")+\n labs(x = \"Valeurs prédites\", y = \"Résidus\")\n\n```\n\n\n```{r}\n#| label: fig-DiaHomoscedasticite\n#| fig-align: center\n#| fig-cap: Distribution des résidus en fonction des valeurs prédites\n#| echo: false\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nggplot() +\n geom_point(aes(x = ypredits, y = residus),\n color = \"#343a40\", fill = \"#a8dadc\",\n alpha = 0.2, size = 0.8) +\n geom_smooth(aes(x = ypredits, y = residus), \n method = lm, color = \"red\")+\n labs(x = \"Valeurs prédites\", y = \"Résidus\")\n```\n\n#### Vérification la multicolinéarité excessive {#sec-07734}\nPour vérifier la présence ou l'absence de multicolinéarité excessive, nous utilisons habituellement la fonction `vif` du *package* `car`.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(car)\n# facteur d'inflation de la variance\nround(car::vif(modele3),3)\n# problème de multicolinéarité (VIF > 10)?\ncar::vif(modele3) > 10\n# problème de multicolinéarité (VIF > 5)?\ncar::vif(modele3) > 5 \n```\n\n#### Répérage des valeurs très influentes du modèle {#sec-07735}\n\nLa syntaxe suivante permet d'évaluer le nombre de valeurs très influentes dans le modèle avec les critères de $\\mbox{4/n}$, $\\mbox{8/n}$ et $\\mbox{16/n}$ pour la distance de Cook.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nnobs <- length(modele3$fitted.values)\nDistanceCook <- cooks.distance(modele3)\nn4 <- length(DistanceCook[DistanceCook > 4/nobs])\nn8 <- length(DistanceCook[DistanceCook > 8/nobs])\nn16 <- length(DistanceCook[DistanceCook > 16/nobs])\ncat(\"Nombre d'observations =\", nobs, \"(100 %)\",\n \"\\n 4/n =\", round(4/nobs,5),\n \"\\n 8/n =\", round(8/nobs,5),\n \"\\n 16/n =\", round(16/nobs,5),\n\"\\nObservations avec une valeur supérieure ou égale aux différents seuils\",\n \"\\n 4/n =\", n4, \"soit\", round(n4/nobs*100,2),\" %\",\n \"\\n 8/n =\", n8, \"soit\", round(n8/nobs*100,2),\" %\",\n \"\\n 16/n =\", n16, \"soit\", round(n16/nobs*100,2), \" %\"\n )\n```\n\nVous pouvez également construire un nuage de points avec la distance de Cook et l'effet de levier (*leverage value*) pour repérer visuellement les observations très influentes (@fig-DiaGraphCookLev).\n\n```{r}\n#| label: fig-DiaGraphCookLev\n#| echo: true\n#| fig-align: center\n#| fig-cap: Repérage graphique des valeurs influentes du modèle\n#| message: false\n#| warning: false\nlibrary(car)\nlibrary(ggpubr)\nDistanceCook <- cooks.distance(modele3)\nLeverageValue <- hatvalues(modele3)\n\nG1 <- ggplot()+\n geom_point(aes(x = LeverageValue, y = DistanceCook), \n alpha = 0.2, size = 2, col = \"black\", fill = \"red\")+\n labs(x = \"Effet levier\",\n y = \"Distance de Cook\",\n title = \"Repérer les valeurs influentes\",\n subtitle = \"(toutes les observations)\")\n\nG2 <- ggplot()+\n geom_point(aes(x = LeverageValue, y = DistanceCook), \n alpha = 0.2, size = 2, col = \"black\", fill = \"red\")+\n ylim(0,0.01)+\n xlim(0,0.01)+\n labs(x = \"Effet levier\",\n y = \"Distance de Cook\",\n title = \"Repérer les valeurs influentes\",\n subtitle = \"(agrandissement)\")\n\nggarrange(G1, G2, nrow = 1, ncol = 2)\n\n```\n\n\n#### Construction d'un nouveau modèle en supprimant les observations très influentes du modèle {#sec-07736}\n\nDans un premier temps, il convient de construire un nouveau modèle sans les valeurs influentes du modèle de départ.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Nombre d'observation dans le modèle 3\nnobs <-length(modele3$fitted.values)\n# Distance de Cook\ncook <- cooks.distance(modele3)\n# Les observations très influentes avec le critère de 16/n\nDataSansOutliers <- cbind(DataFinal, cook)\nDataSansOutliers <- DataSansOutliers[DataSansOutliers$cook < 8/nobs, ]\nmodele3b <- lm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+Pct_014+Pct_65P+Pct_MV+Pct_FR,\n data = DataSansOutliers)\nnobsb <-length(modele3b$fitted.values)\n```\n\nComparez les valeurs du R^2^ ajusté des deux modèles. Habituellement, la suppression des valeurs très influentes s'accompagne d'une augmentation du R^2^ ajusté. C'est notamment le cas ici puisque sa valeur grimpe de 0,4653 à 0,5684, signalant ainsi un gain important pour la variance expliquée.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\ncat(\"\\nComparaison des R2 ajustés :\",\n \"\\nModèle de départ (n=\", nobs, \"), \",\n round(summary(modele3)$adj.r.squared,4), \n \"\\nModèle sans les observations très influentes (n=\", nobsb, \"), \",\n round(summary(modele3b)$adj.r.squared,4),\n sep = \"\"\n)\n```\n\nPour le modèle, il convient alors de refaire le diagnostic de la régression et de vérifier si la suppression des observations très influentes a amélioré : 1) la normalité, la linéarité et l'homoscédasticité des résidus, 2) la multicolinéarité excessive et 3) l'absence de valeurs trop influentes.\n\n**La normalité des résidus s'est-elle ou non améliorée?**\n\nPour ce faire, comparez les valeurs d’asymétrie, d’aplatissement et du test de Jarque-Bera et les graphiques de normalité. À la lecture des valeurs :\n\n* l'asymétrie est très similaire (-0,260 à -0,265);\n\n* l'aplatissement s'est amélioré (1,183 à 0,164);\n\n* le test de Jarque-Bera signale toujours un problème de normalité (*p* < 0,001), mais sa valeur a nettement diminué (548,7 à 131,24);\n\n* les graphiques démontrent une nette amélioration de la normalité des résidus (@fig-ResidusCompa).\n\n\n```{r}\n#| label: fig-ResidusCompa\n#| echo: true\n#| fig-align: center\n#| fig-cap: Normalité des résidus avant et après la suppression des valeurs influentes\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\n# 1. coefficients d’asymétrie et d’aplatissement \nresmodele3 <- rstudent(modele3)\nresmodele3b <- rstudent(modele3b)\n \nc(Skewness= round(Skew(resmodele3),3), \n Kurtosis = round(Kurt(resmodele3),3))\n\nc(Skewness= round(Skew(resmodele3b),3), \n Kurtosis = round(Kurt(resmodele3b),3))\n\n# 2. Test de normalité de Jarque-Bera\nJarqueBeraTest(resmodele3)\nJarqueBeraTest(resmodele3b)\n\n# 3. Graphiques \nGhisto1 <- ggplot() +\n geom_histogram(aes(x = resmodele3, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n stat_function(fun = dnorm, args = list(mean = mean(resmodele3),\n sd = sd(resmodele3)), \n color = \"#e63946\", size = 1.2, linetype = \"dashed\")+\n labs(title = \"Modèle de départ\", y = \"densité\", x = \"Résidus studentisés\")\n\nGqqplot1 <- qplot(sample = residus)+\n geom_qq_line(line.p = c(0.25, 0.75), color = \"#e63946\", size = 1.2)+\n labs(title = \"Modèle de départ\", x = \"Valeurs théoriques\", y = \"Résidus studentisés\")\n\nGhisto2 <- ggplot() +\n geom_histogram(aes(x = resmodele3b, y = ..density..),\n bins = 30, color = \"#343a40\", fill = \"#a8dadc\") +\n stat_function(fun = dnorm, args = list(mean = mean(resmodele3b),\n sd = sd(resmodele3b)), \n color = \"#e63946\", linewidth = 1.2, linetype = \"dashed\")+\n labs(title = \"Modèle après suppression\", x = \"Valeurs théoriques\", y = \"Résidus studentisés\")\n\nGqqplot2 <- qplot(sample = resmodele3b)+\n geom_qq_line(line.p = c(0.25, 0.75), color = \"#e63946\", size = 1.2)+\n labs(title = \"Modèle après suppression\",x = \"Valeurs théoriques\", y = \"Résidus studentisés\")\n\nlibrary(ggpubr)\nggarrange(Ghisto1, Ghisto2, Gqqplot1, Gqqplot2, ncol = 2, nrow = 2)\n```\n\n**Le problème d’hétéroscédasticité est-il corrigé?**\n\n* la valeur du test de Breusch-Pagan est beaucoup plus faible, mais il semble persister un problème d'hétéroscédasticité.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| fig-show: hide\n\n# homoscédasticité des résidus améliorée ou non?\nlibrary(lmtest)\nlibrary(ggpubr)\n\nbptest(modele3)\nbptest(modele3b)\n\nresmodele3 <- residuals(modele3)\nresmodele3b <- residuals(modele3b)\nypredits3 <- modele3$fitted.values\nypredits3b <- modele3b$fitted.values\n\nG1 <- ggplot() +\n geom_point(aes(x = ypredits3, y = resmodele3),\n color = \"#343a40\", fill = \"#a8dadc\", alpha = 0.2, size = 0.8) +\n geom_smooth(aes(x = ypredits3, y = resmodele3), method = lm, color = \"red\")+\n labs(title = \"Modèle de départ\",x = \"Valeurs prédites\", y = \"Résidus studentisés\")\n\nG2 <- ggplot() +\n geom_point(aes(x = ypredits3b, y = resmodele3b),\n color = \"#343a40\", fill = \"#a8dadc\", alpha = 0.2, size = 0.8) +\n geom_smooth(aes(x = ypredits3b, y = resmodele3b), method = lm, color = \"red\")+\n labs(title = \"Modèle après suppression\",x = \"Valeurs prédites\", y = \"Résidus studentisés\")\n\nggarrange(G1, G2, ncol = 2, nrow = 1)\n\n```\n\n```{r}\n#| label: fig-HomosComp\n#| echo: false\n#| fig-align: center\n#| fig-cap: Amélioration de l'homoscédasticité des résidus\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n\nresmodele3 <- residuals(modele3)\nresmodele3b <- residuals(modele3b)\nypredits3 <- modele3$fitted.values\nypredits3b <- modele3b$fitted.values\n\nG1 <- ggplot() +\n geom_point(aes(x = ypredits3, y = resmodele3),\n color = \"#343a40\", fill = \"#a8dadc\", alpha = 0.2, size = 0.8) +\n geom_smooth(aes(x = ypredits3, y = resmodele3), method = lm, color = \"red\")+\n labs(title = \"Modèle de départ\",x = \"Valeurs prédites\", y = \"Résidus studentisés\")\n\nG2 <- ggplot() +\n geom_point(aes(x = ypredits3b, y = resmodele3b),\n color = \"#343a40\", fill = \"#a8dadc\", alpha = 0.2, size = 0.8) +\n geom_smooth(aes(x = ypredits3b, y = resmodele3b), method = lm, color = \"red\")+\n labs(title = \"Modèle après suppression\",x = \"Valeurs prédites\", y = \"Résidus studentisés\")\n\nggarrange(G1, G2, ncol = 2, nrow = 1)\n```\n\n\nFinalement, il convient de comparer les coefficients de régression.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| out-width: \"85%\"\n# Comparaison des coefficients\nsummary(modele3)\nsummary(modele3b)\n```\n\n### Graphiques pour les effets marginaux {#sec-0774}\nTel que signalé ultérieurement, il est courant de représenter l'effet marginal d'une VI sur une VD, une fois contrôlées les autres VI. Pour ce faire, il est possible d'utiliser les *packages* `ggplot2` et `ggeffects`.\n\n#### Effet marginal pour une variable continue {#sec-07741}\n\nLa syntaxe ci-dessous illustre comment obtenir un graphique pour nos quatre variables explicatives. Bien entendu, si le coefficient de régression est positif (comme pour les pourcentages de jeunes de moins de 15 ans et les personnes âgées), la pente est alors montante, et inversement descendante pour des coefficients négatifs (comme pour les personnes ayant déclaré appartenir à une minorité visible et les personnes à faible revenu). En outre, plus la valeur absolue du coefficient est forte, plus la pente est prononcée.\n\n```{r}\n#| label: fig-EffetMarginalVariablesContinues\n#| echo: true\n#| fig-align: center\n#| fig-cap: Effets marginaux pour des variables continues\n#| message: false\n#| warning: false\n#| out-width: \"85%\"\nlibrary(ggplot2)\nlibrary(ggeffects)\nlibrary(ggpubr)\n\n# Création d'un DataFrame pour les valeurs prédites pour chaque VI continue\nfitV1 <- ggpredict(modele3, terms = \"Pct_014\")\nfitV2 <- ggpredict(modele3, terms = \"Pct_65P\")\nfitV3 <- ggpredict(modele3, terms = \"Pct_MV\")\nfitV4 <- ggpredict(modele3, terms = \"Pct_FR\")\n\n# Construction des graphiques\nG1 <-ggplot(fitV1, aes(x, predicted)) +\n # ligne de régression\n geom_line(color = \"red\", linewidth = 1) +\n # intervalle de confiance à 95 %\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n # Titres\n labs(y = \"valeur prédite Y\", x = \"Moins de 15 ans (%)\")\n\nG2 <-ggplot(fitV2, aes(x, predicted)) +\n geom_line(color = \"red\", linewidth = 1) +\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n labs(y = \"valeur prédite Y\", x = \"65 ans et plus (%)\")\n\nG3 <-ggplot(fitV3, aes(x, predicted)) +\n geom_line(color = \"blue\", linewidth = 1) +\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n labs(y = \"valeur prédite Y\", x = \"Minorités visibles (%)\")\n\nG4 <-ggplot(fitV4, aes(x, predicted)) +\n geom_line(color = \"blue\", linewidth = 1) +\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n labs(y = \"valeur prédite Y\", x = \"Personne à faible revenu (%)\")\n\n# Assemblage des graphiques\nggarrange(G1, G2, G3, G4, ncol =2, nrow =2)\n```\n\n#### Effet marginal pour une variable avec une fonction polynomiale d'ordre 2 {#sec-07742}\n\n```{r}\n#| label: fig-Titi\n#| fig-align: center\n#| fig-cap: Effet marginal d'une variable avec un fonction polynomiale d'ordre 2\n#| echo: true\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nlibrary(ggplot2)\nlibrary(ggeffects)\nlibrary(ggpubr)\n\nfitAgeMedian <- ggpredict(modele3, terms = \"AgeMedian\")\n\n ggplot(fitAgeMedian, aes(x, predicted)) +\n geom_line(color = \"green\", linewidth = 1) +\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n labs(title = \"Variable sous forme polynomiale (ordre 2)\",\n y = \"VD: valeur prédite\", x = \"Âge médian des bâtiments\")\n```\n\n#### Effet marginal pour une variable transformée en logarithme {#sec-07743}\n\n```{r}\n#| label: fig-EffetMarginalVariableLog\n#| fig-cap: Effet du logarithme de la densité\n#| echo: true\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nfitHabHa <- ggpredict(modele3, terms = \"HABHA\")\n\nggplot(fitHabHa, aes(x, predicted)) +\n geom_line(color = \"blue\", linewidth = 1) +\n geom_ribbon(aes(ymin = conf.low, ymax = conf.high), alpha = .3)+\n labs(y = \"VD: valeur prédite\", x = \"Habitants km2\")\n```\n\n#### Effet marginal pour une variable dichotomique {#sec-07744}\n\n```{r}\n#| label: fig-EffetMarginalDichCode\n#| echo: true\n#| fig-align: center\n#| fig-cap: Effet marginal d'une variable dichotomique\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\n# Valeurs prédites selon le modèle avec la variable dichotomique\nfitVilleMtl <- ggpredict(modele4, terms = \"VilleMtl\")\n# Graphique\nggplot(fitVilleMtl, aes(x = x, y = predicted)) +\n geom_bar(stat = \"identity\", position = position_dodge(), fill = \"wheat\") +\n geom_errorbar(aes(ymin = conf.low, ymax = conf.high), alpha = .9, position = position_dodge())+\n labs(title = \"Effet marginal de la ville de Montréal sur la végétation\",\n x = \"Municipalités de la région de Montréal\",\n y = \"Couverture végétation de l'îlot (%)\")+\n scale_x_continuous(breaks=c(0,1),\n labels = c(\"Autre municipalité\", \"Ville de Montréal\"))\n``` \n\n#### Effet marginal pour une variable polytomique {#sec-07745}\n\n```{r}\n#| label: fig-EffetMarginalPolyT\n#| echo: true\n#| fig-align: center\n#| fig-cap: Effet marginal d'une variable polytomique\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\n# Valeurs prédites selon le modèle avec la variable polytomique\nfitVilles <- ggpredict(modele5, terms = \"Munic\")\n# Graphique\nGraphique <- ggplot(fitVilles, aes(x = x, y = predicted)) +\n geom_bar(stat = \"identity\", position = position_dodge(), fill = \"wheat\") +\n geom_errorbar(aes(ymin = conf.low, ymax = conf.high), alpha = .9, position = position_dodge())+\n labs(title = \"Effet marginal de la ville de Montréal sur la végétation\",\n x = \"Municipalités de la région de Montréal\",\n y = \"Couverture végétation de l'îlot (%)\")\n\n# Rotation du graphique\nGraphique + coord_flip()\n``` \n\n#### Effet marginal pour une variable d'interaction (deux VI continues) {#sec-07746}\n\n```{r}\n#| label: fig-ModeleInteraction2heatex\n#| echo: true\n#| fig-align: center\n#| fig-cap: Effet marginal de l'interaction entre deux variables continues\n#| message: false\n#| warning: false\n#| out-width: \"95%\"\n\n\nlibrary(metR) # pour ajouter des labels aux contours\n\ndf <- expand.grid(\n DistCBDkm = seq(0,33,0.1),\n Pct_FR = seq(0,95,1),\n HABHA = mean(DataFinal$HABHA),\n AgeMedian = mean(DataFinal$AgeMedian),\n Pct_014 = mean(DataFinal$Pct_014),\n Pct_65P = mean(DataFinal$Pct_65P),\n Pct_MV = mean(DataFinal$Pct_MV)\n)\n\ndf$DistCBDkmX_Pct_FR <- df$DistCBDkm * df$Pct_FR\npred <- predict(modele6, newdata = df, se = TRUE)\ndf$pred <- pred$fit\ndf$pred_se <- pred$se.fit\ndf$lower <- df$pred - 1.96 * df$pred_se\ndf$upper <- df$pred + 1.96 * df$pred_se\n\nP1 <- ggplot(data = df) + \n geom_tile(aes(x = DistCBDkm, y = Pct_FR, fill = pred)) +\n stat_contour(aes(x = DistCBDkm, y = Pct_FR, z = pred), \n color = \"black\", linetype = \"dashed\") + \n geom_text_contour(aes(x = DistCBDkm, y = Pct_FR, z = pred), )+\n scale_fill_viridis(discrete = FALSE) + \n labs(x = \"Distance au centre-ville\", \n y = \"Pers à faible revenu (%)\",\n fill = \"\",\n subtitle = \"Prédiction\")\n\nP2 <- ggplot(data = df) + \n geom_tile(aes(x = DistCBDkm, y = Pct_FR, fill = lower)) +\n stat_contour(aes(x = DistCBDkm, y = Pct_FR, z = lower), \n color = \"black\", linetype = \"dashed\") + \n geom_text_contour(aes(x = DistCBDkm, y = Pct_FR, z = lower), )+\n scale_fill_viridis(discrete = FALSE)+ \n labs(x = \"Distance au centre-ville\", \n y = \"Pers à faible revenu (%)\",\n fill = \"\",\n subtitle = \"IC 2,5 %\")\n\nP3 <- ggplot(data = df) + \n geom_tile(aes(x = DistCBDkm, y = Pct_FR, fill = upper)) +\n stat_contour(aes(x = DistCBDkm, y = Pct_FR, z = upper), \n color = \"black\", linetype = \"dashed\") + \n geom_text_contour(aes(x = DistCBDkm, y = Pct_FR, z = upper), )+\n scale_fill_viridis(discrete = FALSE)+ \n labs(x = \"Distance au centre-ville\", \n y = \"Pers à faible revenu (%)\",\n fill = \"\",\n subtitle = \"IC 97,5 %\")\n\nggarrange(P1, P2, P3, common.legend = FALSE, ncol = 2, nrow = 2)\n\n```\n\n#### Effet marginal pour une variable d'interaction (une VI continue et une VI dichotomique) {#sec-07747}\n\n```{r}\n#| label: fig-ModeleInteractionBinaireeffectex\n#| fig-cap: Graphique de l’effet marginal de l’interaction entre une variable quantitative et qualitative\n#| fig-align: center\n#| out-width: \"70%\"\n#| echo: true\n#| message: false\n#| warning: false\n\n\n\ndf <- expand.grid(\n VilleMtl = c(0,1),\n Pct_FR = seq(0,95,1),\n HABHA = mean(DataFinal$HABHA),\n AgeMedian = mean(DataFinal$AgeMedian),\n Pct_014 = mean(DataFinal$Pct_014),\n Pct_65P = mean(DataFinal$Pct_65P),\n Pct_MV = mean(DataFinal$Pct_MV)\n)\ndf$VilleMtlX_Pct_FR <- df$VilleMtl * df$Pct_FR\nhead(df, n=5)\npred <- predict(modele7, se = TRUE, newdata = df)\ndf$pred <- pred$fit\ndf$upper <- df$pred + 1.96*pred$se.fit\ndf$lower <- df$pred - 1.96*pred$se.fit\ndf$VilleMtl_str <- ifelse(df$VilleMtl==0,\"Autre municipalité\" , \"Ville de Montréal\")\nDataFinal$VilleMtl_str <- ifelse(DataFinal$VilleMtl==0,\"Autre municipalité\" , \"Ville de Montréal\")\ncols <- c(\"Autre municipalité\" =\"#1d3557\" ,\"Ville de Montréal\"=\"#e63946\")\n\nggplot(data = df) +\n geom_point(data = DataFinal, mapping = aes(x = Pct_FR, y = VegPct, color = VilleMtl_str),\n size = 0.2, alpha = 0.2)+\n geom_ribbon(aes(x = Pct_FR, ymin = lower, ymax = upper, group = VilleMtl_str),\n fill = rgb(0.1,0.1,0.1,0.4))+\n geom_path(aes(x = Pct_FR, y = pred, color = VilleMtl_str), size = 1) +\n scale_colour_manual(values = cols)+\n labs(x = \"Personnes à faible revenu (%)\",\n y = \"Densité de végétation prédite (%)\",\n color = \"\")\n```\n\n## Quiz de révision du chapitre {#sec-078}\n\n```{r}\n#| label: quizChapitre6\n#| echo: false\n#| warning: false\n#| results: asis\nsource(\"code_complementaire/QuizzFunctions.R\")\nChapitre7_Lm <- quizz(\"quiz/Chapitre7_Lm.yml\", \"Chapitre7_Lm\")\nrender_quizz(Chapitre7_Lm)\n```\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"07-regressionlineaire.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/08-GLM.qmd.json b/.quarto/idx/08-GLM.qmd.json new file mode 100644 index 0000000..8b3f60e --- /dev/null +++ b/.quarto/idx/08-GLM.qmd.json @@ -0,0 +1 @@ +{"title":"Régressions linéaires généralisées (GLM)","markdown":{"headingText":"Régressions linéaires généralisées (GLM)","headingAttr":{"id":"sec-chap08","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans ce chapitre, nous présentons les modèles linéaires généralisés plus communément appelés GLM (*generalized linear models* en anglais). Il s’agit d’une extension directe du modèle de régression linéaire multiple (LM) basé sur la méthode des moindres carrés ordinaires, décrite dans le chapitre précédent. Pour aborder cette section sereinement, il est important d’avoir bien compris le concept de distribution présenté dans la [section @sec-024]. À la fin de cette section, vous serez en mesure de :\n\n* Comprendre la distinction entre un modèle LM classique et un GLM.\n* Identifier les composantes d’un GLM.\n*\tInterpréter les résultats d’un GLM.\n*\tEffectuer les diagnostics d’un GLM.\n\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\nDans ce chapitre, nous utilisons principalement les *packages* suivants : \n\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes.\n \n* Pour ajuster des modèles GLM :\n - `VGAM` et `gamlss` offrent tous les deux un très large choix de distributions et de fonctions de diagnostic, mais nécessitent souvent un peu plus de code.\n - `mgcv` offre moins de distributions que les deux précédents, mais est plus simple d'utilisation.\n\n * Pour analyser des modèles GLM :\n - `car` essentiellement pour la fonction `vif`.\n - `DHARMa` pour le diagnostic des résidus simulés.\n - `ROCR` et `caret` pour l'analyse de la qualité d'ajustement de modèles pour des variables qualitatives.\n - `AER` pour des tests de sur-dispersion.\n - `fitdistrplus` pour ajuster des distributions à des données.\n - `LaplacesDemon` pour manipuler certaines distributions.\n - `sandwich` pour générer des erreurs standards robustes pour le modèle GLM logistique binomial.\n:::\n:::\n\n## Qu'est qu'un modèle GLM? {#sec-081}\n\nNous avons vu qu’une régression linéaire multiple (LM) ne peut être appliquée que si la variable dépendante analysée est continue et si elle est normalement distribuée, une fois les variables indépendantes contrôlées. Il s’agit d’une limite très importante puisqu’elle ne peut être utilisée pour modéliser et prédire des variables binaires, multinomiales, de comptage, ordinales ou plus simplement des données anormalement distribuées. Une seconde limite importante des LM est que l’influence des variables indépendantes sur la variable dépendante ne peut être que linéaire. L’augmentation d’une unité de *X* conduit à une augmentation (ou diminution) de $\\beta$ (coefficient de régression) unités de *Y*, ce qui n’est pas toujours représentatif des phénomènes étudiés. Afin de dépasser ces contraintes, @GLMnelder ont proposé une extension des modèles LM, soit les modèles linéaires généralisés (GLM).\n\n### Formulation d'un GLM {#sec-0811}\n\nPuisqu’un modèle GLM est une extension des modèles LM, il est possible de traduire un modèle LM sous forme d’un GLM. Nous utilisons ce point de départ pour détailler la morphologie d’un GLM. Nous avons vu dans la section précédente qu’un modèle LM est formulé de la façon suivante (notation matricielle) :\n\n$$\nY = \\beta_0 + X\\beta + \\epsilon\n$$ {#eq-regmultiple5B}\n\n\nAvec $\\beta_0$ la constante (*intercept* en anglais) et $\\beta$ un vecteur de coefficients de régression pour les *k* variables indépendantes (*X*).\n\nD'après cette formule, nous modélisons la variable *Y* avec une équation de régression linéaire et un terme d’erreur que nous estimons être normalement distribué. Nous pouvons reformuler ce simple LM sous forme d’un GLM avec l’écriture suivante : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\beta X\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glm1}\n\n\nPas de panique! Cette écriture se lit comme suit : la variable *Y* est issue d’une distribution normale $(Y \\sim Normal)$ avec deux paramètres : $\\mu$ (sa moyenne) et $\\sigma$ (son écart-type). $\\mu$ varie en fonction d’une équation de régression linéaire ($\\beta_0 + \\beta X$) transformée par une fonction de lien *g* (détaillée plus loin). Dans ce cas précis, la fonction de lien est appelée fonction identitaire puisqu’elle n’applique aucune transformation ($g(x) = x$). Notez ici que le second paramètre de la distribution normale $\\sigma$ (paramètre de dispersion) a une valeur fixe et ne dépend donc pas des variables indépendantes à la différence de $\\mu$. Dans ce modèle spécifiquement, les paramètres à estimer sont $\\sigma$, $\\beta_0$ et $\\beta$.\nNotez que dans la notation traditionnelle, la fonction de lien est appliquée au paramètre modélisé. Il est possible de renverser cette notation en utilisant la réciproque ($g'$) de la fonction de lien ($g$) :\n\n$$\ng(\\mu) = \\beta_0 + \\beta X \\Longleftrightarrow \\mu = g'(\\beta_0 + \\beta X)\n\\text{ si : }g'(g(x)) = x\n$$ {#eq-glm2}\n\n\nDans un modèle GLM, la distribution attendue de la variable *Y* est déclarée de façon explicite ainsi que la façon dont nos variables indépendantes conditionnent cette distribution. Ici, c’est la moyenne ($\\mu$) de la distribution qui est modélisée, nous nous intéressons ainsi au changement moyen de *Y* provoqué par les variables *X*.\n\nAvec cet exemple, nous voyons les deux composantes supplémentaires d’un modèle GLM :\n\n*\tLa distribution supposée de la variable *Y* conditionnée par les variables *X* (ici, la distribution normale).\n\n*\tUne fonction de lien associant l’équation de régression formée par les variables indépendantes et un paramètre de la distribution retenue (ici, la fonction identitaire et le paramètre $\\mu$).\n\nNotez également que l’estimation des paramètres d’un modèle GLM (ici, $\\beta_0$, $\\beta X$ et $\\sigma$) ne se fait plus avec la méthode des moindres carrés ordinaires utilisée pour les modèles LM. À la place, la méthode par maximum de vraisemblance (*maximum likelihood*) est la plus souvent utilisée, mais certains *packages* utilisent également la méthode des moments (*method of moments*). Ces deux méthodes nécessitent des échantillons plus grands que la méthode des moindres carrés. Dans le cas spécifique d'un modèle GLM utilisant une distribution normale, la méthode des moindres carrés et la méthode par maximum de vraisemblance produisent les mêmes résultats.\n\n### Autres distributions et rôle de la fonction de lien {#sec-0812}\n\nÀ première vue, il est possible de se demander pourquoi ajouter ces deux éléments puisqu’ils ne font que complexifier le modèle. Pour mieux saisir la pertinence des GLM, prenons un exemple appliqué au cas d’une variable binaire. Admettons que nous souhaitons modéliser / prédire la probabilité qu’une personne à vélo décède lors d’une collision avec un véhicule motorisé. Notre variable dépendante est donc binaire (0 = survie, 1 = décès) et nous souhaitons la prédire avec trois variables continues que sont : la vitesse de déplacement du ou de la cycliste ($x_1$), la vitesse de déplacement du véhicule ($x_2$) et la masse du véhicule ($x_3$). Puisque la variable *Y* n’est pas continue, il serait absurde de supposer qu’elle est issue d’une distribution normale. Il serait plus logique de penser qu’elle provient d’une distribution de Bernoulli (pour rappel, une distribution de Bernoulli permet de modéliser un phénomène ayant deux issues possibles comme un lancer de pièce de monnaie ([section @sec-024]). Plus spécifiquement, nous pourrions formuler l’hypothèse que nos trois variables $x_1$, $x_2$ et $x_3$ influencent le paramètre *p* (la probabilité d’occurrence de l’évènement) d’une distribution de Bernoulli. À partir de ces premières hypothèses, nous pouvons écrire le modèle suivant : \n\n$$\n\\begin{aligned}\n&Y \\sim Bernoulli(p)\\\\\n&g(p) = \\beta_0 + \\beta X\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glm3}\n\n\nToutefois, le résultat n’est pas entièrement satisfaisant. En effet, *p* est une probabilité et, par nature, ce paramètre doit être compris entre 0 et 1 (entre 0 et 100 % de « chances de décès », ni plus ni moins). L’équation de régression que nous utilisons actuellement peut produire des résultats compris entre $-\\infty$ et $+\\infty$ pour *p* puisque rien ne contraint la somme $\\beta_0+ \\beta_1x_1+\\beta_2x_2+ \\beta_3x_3$ à être comprise entre 0 et 1. Il est possible de visualiser le problème soulevé par cette situation avec les figures suivantes. Admettons que nous avons observé une variable *Y* binaire et que nous savons qu’elle est influencée par une variable *X* qui, plus elle augmente, plus les chances que *Y* soit 1 augmentent (@fig-linearbinom).\n\n```{r}\n#| label: fig-linearbinom\n#| fig-align: center\n#| fig-cap: Exemple de données issues d'une distribution de Bernoulli\n#| echo: false\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nsource(\"code_complementaire/JG_helper.R\")\nlibrary(ggplot2)\nx1 <- rnorm(150)\nz <- 1 + rnorm(150, mean = 2, sd = 0.5)*x1\npr <- 1/(1+exp(-z))\ny <- ifelse(pr > 0.5,1,0)\ndf <- data.frame(x1 = x1, \n y = y)\nggplot(data = df)+\n geom_point(aes(x = x1, y = y), size = 0.5) + \n labs(x = \"X\", y = \"Y\") + \n ylim(c(-0.25,1.25))\n```\n\nSi nous utilisons l’équation de régression actuelle, cela revient à trouver la droite la mieux ajustée passant dans ce nuage de points (@fig-linearbinom2).\n\n```{r}\n#| label: fig-linearbinom2\n#| fig-align: center\n#| echo: false\n#| fig-cap: Ajustement d'une droite de régression aux données issues d'une distribution de Bernoulli\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\ntofr <- function(float){\n return(gsub(\".\" , \",\", as.character(float), fixed = TRUE, useBytes = TRUE))\n}\n\nggplot(data = df)+\n geom_point(aes(x = x1, y = y), size = 0.5) + \n geom_smooth(aes(x = x1, y = y), method='lm', formula= y~x, se = FALSE) +\n labs(x = \"X\", y = \"Y\") + \n ylim(c(-0.25,1.25))\n```\n\nCe modèle semble bien cerner l’influence positive de *X* sur *Y*, mais la droite est au final très éloignée de chaque point, indiquant un faible ajustement du modèle. De plus, la droite prédit des probabilités négatives lorsque *X* est inférieur à −2,5 et des probabilités supérieures à 1 quand *X* est supérieur à 1. Elle est donc loin de bien représenter les données.\n\nC’est ici qu’intervient la fonction de lien. La fonction identitaire que nous avons utilisée jusqu'ici n’est pas satisfaisante, nous devons la remplacer par une fonction qui conditionnera la somme $\\beta_0+ \\beta_1x_1+\\beta_2x_2+ \\beta_3x_3$ pour donner un résultat entre 0 et 1. Une candidate toute désignée est la fonction *sigmoidale*, plus souvent appelée la fonction *logistique*!\n\n$$\n\\begin{aligned}\n&Y \\sim Bernoulli(p)\\\\\n&S(p) = \\beta_0 + \\beta X\\\\\n&S(x) = \\frac{e^{x}}{e^x+1}\n\\end{aligned}\n$$ {#eq-glm4}\n\n\nLa fonction logistique prend la forme d’un *S*. Plus la valeur entrée dans la fonction est grande, plus le résultat produit par la fonction est proche de 1 et inversement. Si nous reprenons l’exemple précédent, nous obtenons le modèle illustré à la @fig-linearbinom3.\n\n```{r}\n#| label: fig-linearbinom3\n#| fig-align: center\n#| fig-cap: Utilisation de la fonction de lien logistique\n#| echo: false\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nggplot(data = df)+\n geom_point(aes(x = x1, y = y), size = 0.5) + \n geom_smooth(aes(x = x1, y = y), method='lm', formula= y~x, se = FALSE) +\n geom_smooth(aes(x = x1, y = y), method='glm', \n method.args = list(family = \"binomial\"),\n se = FALSE, color = \"red\") + \n labs(x = \"X\", y = \"Y\") + \n ylim(c(-0.25,1.25))\n```\n\nUne fois cette fonction insérée dans le modèle, nous constatons qu’une augmentation de la somme $\\beta_0+ \\beta_1x_1+\\beta_2x_2+ \\beta_3x_3$ conduit à une augmentation de la probabilité *p* et inversement, et que cet effet est non linéaire. Nous avons donc maintenant un GLM permettant de prédire la probabilité d’un décès lors d’un accident en combinant une distribution et une fonction de lien adéquates.\n\n### Conditions d'application {#sec-0813}\n\nLa famille des GLM englobe de (très) nombreux modèles du fait de la diversité de distributions existantes et des fonctions de liens utilisables. Cependant, certaines combinaisons sont plus souvent utilisées que d’autres. Nous présentons donc dans les prochaines sections les modèles GLM les plus communs. Les conditions d’application varient d’un modèle à l’autre, il existe cependant quelques conditions d’application communes à tous ces modèles : \n\n*\tl’indépendance des observations (et donc des erreurs);\n\n*\tl’absence de valeurs aberrantes / fortement influentes;\n\n*\tl’absence de multicolinéarité excessive entre les variables indépendantes.\n\nCes trois conditions sont également valables pour les modèles LM tel qu'abordé dans le [chapitre @sec-chap07]. La distance de *Cook* peut ainsi être utilisée pour détecter les potentielles valeurs aberrantes et le facteur d’inflation de la variance (*VIF*) pour détecter la multicolinéarité.\nLes conditions d’application particulières sont détaillées dans les sections dédiées à chaque modèle.\n\n### Résidus et déviance {#sec-0814}\n\nDans la section sur la régression linéaire simple, nous avons présenté la notion de résidu, soit l’écart entre la valeur observée (réelle) de *Y* et la valeur prédite par le modèle. Pour un modèle GLM, ces résidus traditionnels (aussi appelés résidus naturels) ne sont pas très informatifs si la variable à modéliser est binaire, multinomiale ou même de comptage. Lorsque l’on travaille avec des GLM, nous préférons utiliser trois autres formes de résidus, soit les résidus de Pearson, les résidus de déviance et les résidus simulés.\n\n**Les résidus de Pearson** sont une forme ajustée des résidus classiques, obtenus par la division des résidus naturels par la racine carrée de la variance modélisée. Leur formule varie donc d’un modèle à l’autre puisque l’expression de la variance change en fonction de la distribution du modèle. Pour un modèle GLM gaussien, elle s'écrit :\n\n$$\nr_i = \\frac{y_i - \\mu_i}{\\sigma}\n$$ {#eq-glm5}\n\nPour un modèle GLM de Bernoulli, elle s'écrit : \n\n$$\nr_i = \\frac{y_i - p_i}{\\sqrt{p_i(1-p_i)}}\n$$ {#eq-glm6}\n\navec $\\mu_i$ et $p_i$ les prédictions du modèle pour l'observation *i*.\n\n**Les résidus de déviance** sont basés sur le concept de *likelihood* présenté dans la [section @sec-02adjdistrib]. Pour rappel, le *likelihood*, ou la vraisemblance d’un modèle, correspond à la probabilité conjointe d’avoir observé les données *Y* selon le modèle étudié. Pour des raisons mathématiques (voir [section @sec-02adjdistrib]), le *log likelihood* est plus souvent calculé. Plus cette valeur est forte, moins le modèle se trompe. Cette interprétation est donc inverse à celle des résidus classiques, c’est pourquoi le *log likelihood* est généralement multiplié par −2 pour retrouver une interprétation intuitive. Ainsi, pour chaque observation *i*, nous pouvons calculer :\n\n$$\nd_i = \\mbox{-2} \\times log(P(y_i|M_e))\n$$ {#eq-glm7}\n\n\navec $d_i$ le résidu de déviance et $P(y_i|M_e)$ la probabilité d’avoir observé la valeur $y_i$ selon le modèle étudié ($M_e$).\n\nLa somme de tous ces résidus est appelée la déviance totale du modèle.\n\n$$\nD(M_e) = \\sum_{i=1}^n \\mbox{-2} \\times log(P(y_i|M_e))\n$$ {#eq-glm8}\n\nIl s’agit donc d’une quantité représentant à quel point le modèle est erroné vis-à-vis des données. Notez qu’en tant que telle, la déviance n’a pas d’interprétation directe en revanche, elle est utilisée pour calculer des mesures d’ajustement des modèles GLM.\n\n**Les résidus simulés** sont une avancée récente dans le monde des GLM, ils fournissent une définition et une interprétation harmonisée des résidus pour l’ensemble des modèles GLM. Dans la section sur les LM ([section @sec-0722]), nous avons vu comment interpréter les graphiques des résidus pour détecter d’éventuels problèmes dans le modèle. Cependant, cette technique est bien plus compliquée à mettre en œuvre pour les GLM puisque la forme attendue des résidus varie en fonction de la distribution choisie pour modéliser *Y*. La façon la plus efficace de procéder est d’interpréter les graphiques des résidus simulés qui ont la particularité d’être **identiquement distribués, quel que soit le modèle GLM construit**. Ces résidus simulés sont compris entre 0 et 1 et sont calculés de la manière suivante :\n\n* À partir du modèle GLM construit, simuler *S* fois (généralement 1 000) une variable *Y’* avec autant d’observation (*n*) que *Y*. Cette variable simulée est une combinaison de la prédiction du modèle (coefficient et variables indépendantes) et de sa dispersion (variance). Ces simulations représentent des variations vraisemblables de la variable *Y* si le modèle est correctement spécifié. En d’autres termes, si le modèle représente bien le phénomène à l’origine de la variable *Y*, alors les simulations *Y’* issues du modèle devraient être proches de la variable *Y* originale. Pour une explication plus détaillée de ce que signifie simuler des données à partir d’un modèle, référez-vous au *bloc attention* intitulé *Distinction entre simulation et prédiction* dans la [section @sec-08152].\n\n* Pour chaque observation, nous obtenons ainsi *S* valeurs formant une distribution $Ds_i$, soit les valeurs simulées par le modèle pour cette observation.\n\n* Pour chacune de ces distributions, nous calculons la probabilité cumulative d’observer la vraie valeur $Y_i$ d'après la distribution $Ds_i$. Cette valeur est comprise entre 0 (toutes les valeurs simulées sont plus grandes que $Y_i$) et 1 (toutes les valeurs simulées sont inférieures à $Y_i$).\n\nSi le modèle est correctement spécifié, le résultat attendu est que la distribution de ces résidus est uniforme. En effet, il y a autant de chances que les simulations produisent des résultats supérieurs ou inférieurs à $Y_i$ si le modèle représente bien le phénomène [@RandomizedResid;@gelman2006data]. Si la distribution des résidus ne suit pas une loi uniforme, cela signifie que le modèle échoue à reproduire le phénomène à l’origine de *Y*, ce qui doit nous alerter sur sa pertinence.\n\n### Vérification l’ajustement {#sec-0815}\n\nIl existe trois façons de vérifier l’ajustement d’un modèle GLM : \n\n* utiliser des mesures d’ajustement (AIC, pseudo-R^2^, déviance expliquée, etc.);\n* comparer les distributions de la variable originale et celle des prédictions;\n* comparer les prédictions du modèle avec les valeurs originales.\n\nNotez d’emblée que vérifier la qualité d’ajustement d’un modèle (ajustement aux données originales) ne revient pas à vérifier la validité d’un modèle (respect des conditions d’application). Cependant, ces deux éléments sont généralement liés, car un modèle mal ajusté a peu de chances d’être valide et inversement.\n\n#### Mesures d'ajustement {#sec-08151}\n\nLes mesures d’ajustement sont des indicateurs plus ou moins arbitraires dont le principal intérêt est de faciliter la comparaison entre plusieurs modèles similaires. Il est nécessaire de les reporter, car dans certains cas, ils peuvent indiquer que des modèles sont très mal ajustés.\n\n##### Déviance expliquée {#sec-081511}\n\nRappelons que la déviance d’un modèle est une quantité représentant à quel point le modèle est erroné. L’objectif de l’indicateur de la déviance expliquée est d’estimer le pourcentage de la déviance maximale observable dans les données que le modèle est parvenu à expliquer. La déviance maximale observable dans les données est obtenue en utilisant la déviance totale du modèle nul (notée $M_n$, soit un modèle dans lequel aucune variable indépendante n’est ajoutée et ne comportant qu’une constante). Cette déviance est maximale puisqu’aucune variable indépendante n’est présente dans le modèle. Nous calculons ensuite le pourcentage de cette déviance totale qui a été contrôlée par le modèle étudié ($M_e$).\n\n$$\n\\mbox{déviance expliquée} = \\frac{D(M_n) - D(M_e)}{D(M_n)} = 1- \\frac{D(M_e)}{D(M_n)}\n$$ {#eq-glm9}\n\n\nIl s’agit donc d’un simple calcul de pourcentage entre la déviance maximale ($D(M_n)$) et la déviance expliquée par le modèle étudié ($D(M_n )-D(M_e)$). Cet indicateur est compris entre 0 et 1 : plus il est petit, plus la capacité de prédiction du modèle est faible. Attention, cet indicateur ne tient pas compte de la complexité du modèle. Ajouter une variable indépendante supplémentaire ne fait qu’augmenter la déviance expliquée, ce qui ne signifie pas que la complexification du modèle soit justifiée (**voir l'encadré sur le principe de parcimonie**, [section @sec-0732]).\n\n##### Pseudo-R^2^ {#sec-081512}\n\nLe R^2^ est une mesure d’ajustement représentant la part de la variance expliquée dans un modèle linéaire classique. Cette mesure n’est pas directement transposable au cas des GLM puisqu’ils peuvent être appliqués à des variables non continues et anormalement distribuées. Toutefois, il existe des mesures semblables appelées pseudo-R^2^, remplissant un rôle similaire. Notez cependant qu’ils ne peuvent pas être interprétés comme le R^2^ classique (d'une régression linéaire multiple) : **ils ne représentent pas la part de la variance expliquée**. Ils sont compris dans l’intervalle 0 et 1; plus leurs valeurs s’approchent de 1, plus le modèle est ajusté.\n\n```{r}\n#| label: tbl-pseudor2\n#| tbl-cap: Principaux pseudos-$R^2$\n#| echo: false\n#| message: false\n#| warning: false\ndf <- data.frame(\n Nom = c(\"McFadden\", \"McFadden ajusté\", \"Efron\", \"Cox & Snell\", \"Nagelkerke\"),\n formule = c(\"$1-\\\\frac{loglike(M_e)}{loglike(M_n)}$\", \n \"$1-\\\\frac{loglike(M_e)-K}{loglike(M_n)}$\",\n \"$1-\\\\frac{\\\\sum_{i=1}^n(y_i-\\\\hat{y}_i)^2}{\\\\sum_{i=1}^n(y_i-\\\\bar{y}_i)^2}$\",\n \"$1-e^{-\\\\frac{2}{n}({loglike(M_e) - loglike(M_n))}}$\",\n \"$\\\\frac{1-e^{-\\\\frac{2}{n}({loglike(M_e) - loglike(M_n))}}}{1-e^{\\\\frac{2*loglike(M_n)}{n}}}$\"),\n Commentaire = c(\"Le rapport des *loglikelihood*, très proche de la déviance expliquée.\", \"Version ajustée du R^2^ de McFadden tenant compte du nombre de paramètres (*k*) dans le modèle.\", \"Rapport entre la somme des résidus classiques au carré (numérateur) et de la somme des écarts au carré à la moyenne (dénominateur). Notez que pour un GLM gaussien, ce pseudo-R^2^ est identique au R^2^ classique.\", \"Transformation de la déviance afin de la mettre sur une échelle de 0 à 1 (mais ne pouvant atteindre exactement 1).\", \"Ajustement du R^2^ de Cox et Snell pour que l’échelle de valeurs possibles puisse comporter 1 (attention, car les valeurs de ce R^2^ tendent à être toujours plus fortes que les autres).\")\n)\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t col.names = c(\"Nom\" , \"Formule\", \"Commentaire\"),\n col.to.resize = 3,\n col.width = \"8cm\")\n```\n\nEn dehors du pseudo-R^2^ de McFadden ajusté, aucune de ces mesures ne tient compte de la complexité du modèle. Il est cependant important de les reporter, car des valeurs très faibles indiquent vraisemblablement un modèle avec une moindre capacité informative. À l’inverse, des valeurs trop fortes pourraient indiquer un problème de surajustement (**voir encadré sur le principe de parcimonie**, [section @sec-0732]).\n\n##### Critère d'information d'Akaike (AIC) {#sec-081513}\n\nProbablement l’indicateur le plus répandu, sa formule est relativement simple, car il s’agit seulement d’un ajustement de la déviance :\n\n$$\nAIC = D(M_e) + 2K\n$$ {#eq-glm10}\n\n\navec *K* le nombre de paramètres à estimer dans le modèle (coefficients, paramètres de distribution, etc.). \n\nL'AIC n’a pas d’interprétation directe, mais permet de comparer deux modèles imbriqués ([section @sec-0732]). Plus l'AIC est petit, mieux le modèle est ajusté. L’idée derrière cet indicateur est relativement simple. Si la déviance *D* est grande, alors le modèle est mal ajusté. Ajouter des paramètres (des coefficients pour de nouvelles variables *X*, par exemple) ne peut que réduire *D*, mais cette réduction n’est pas forcément suffisamment grande pour justifier la complexification du modèle. L'AIC pondère donc *D* en lui ajoutant 2 fois le nombre de paramètres du modèle. Un modèle plus simple (avec moins de paramètres) parvenant à une même déviance est préférable à un modèle complexe (principe de parcimonie ou du rasoir d’Ockham), ce que permet de « quantifier » l'AIC. Attention, l'AIC **ne peut pas être utilisé pour comparer des modèles non imbriqués**. Notez que d’autres indicateurs similaires comme le WAIC, le BIC et le DIC sont utilisés dans un contexte d’inférence bayésienne. Retenez simplement que ces indicateurs sont conceptuellement proches du AIC et s’interprètent (à peu de choses près) de la même façon.\n\n#### Comparaison des distributions originales et prédites {#sec-08152}\n\nUne façon rapide de vérifier si un modèle est mal ajusté est de comparer la forme de la distribution originale et celle capturée par le modèle. L’idée est la suivante : si le modèle est bien ajusté aux données, il est possible de se servir de celui-ci pour générer de nouvelles données dont la distribution ressemble à celle des données originales. Si une différence importante est observable, alors les résultats du modèle ne sont pas fiables, car le modèle échoue à reproduire le phénomène étudié. Cette lecture graphique ne permet pas de s’assurer que le modèle est valide ou bien ajusté, mais simplement d’écarter rapidement les mauvais candidats. Notez que cette méthode ne s’applique pas lorsque la variable modélisée est binaire, multinomiale ou ordinale.\nLe graphique à réaliser comprend donc la distribution de la variable dépendante *Y* (représentée avec un histogramme ou un graphique de densité) et plusieurs distributions simulées à partir du modèle. Cette approche est plus répandue dans la statistique bayésienne, mais elle reste pertinente dans l’approche fréquentiste. Il est rare de reporter ces figures, mais elles doivent faire partie de votre diagnostic.\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Distinction entre simulation et prédiction**\n:::\n::: bloc_attention-body\nNotez ici que **simuler des données** à partir d’un modèle et **effectuer des prédictions** à partir d’un modèle sont deux opérations différentes. Prédire une valeur à partir d’un modèle revient simplement à appliquer son équation de régression à des données. Si nous réutilisons les mêmes données, la prédiction renvoie toujours le même résultat, il s’agit de la partie systématique (ou déterministe) du modèle. \nPour illustrer cela, admettons que nous avons ajusté un modèle GLM de type gaussien (fonction de lien identitaire) avec trois variables continues $X_1$, $X_2$ et $X_3$ et des coefficients respectifs de 0,5, 1,2 et 1,8 ainsi qu’une constante de 7. Nous pouvons utiliser ces valeurs pour prédire la valeur attendue de $Y$ quand $X_1= 3$, $X_2= 5$ et $X_3 = 5$ : \n\n$\\mbox{Prédiction} = \\mbox{7 + 3}\\times \\mbox{0,5 + 5}\\times \\mbox{1,2 + 5}\\times\\mbox{1,8 = 23,5}$\n\nEn revanche, simuler des données à partir d’un modèle revient à ajouter la dimension stochastique (aléatoire) du modèle. Puisque notre modèle GLM est gaussien, il comporte un paramètre $\\sigma$ (son écart-type); admettons, pour cet exemple, qu’il est de 1,2. Ainsi, avec les données précédentes, il est possible de simuler un ensemble infini de valeurs dont la distribution est la suivante : $Normal(\\mu = \\mbox{23,5, } \\sigma = \\mbox{1,2})$. 95 % du temps, ces valeurs simulées se trouveront dans l’intervalle $\\mbox{[21,1-25,9]}$ ($\\mu - 2\\sigma \\text{; } \\mu + 2\\sigma$), puisque cette distribution est normale. Les valeurs simulées dépendent donc de la distribution choisie pour le modèle et de l’ensemble des paramètres du modèle, pas seulement de l’équation de régression.\n\nSi vous aviez à ne retenir qu’une seule phrase de ce bloc, retenez que la prédiction ne se réfère qu’à la partie systématique du modèle (équation de régression), alors que la simulation incorpore la partie stochastique (aléatoire) de la distribution du modèle. Deux prédictions effectuées sur des données identiques donnent nécessairement des résultats identiques, ce qui n’est pas le cas pour la simulation.\n:::\n:::\n\n#### Comparaison des prédictions du modèle avec les valeurs originales {#sec-08153}\n\nLes prédictions d’un modèle devraient être proches des valeurs réelles observées. Si ce n’est pas le cas, alors le modèle n’est pas fiable et ses paramètres ne sont pas informatifs. Dépendamment de la nature de la variable modélisée (quantitative ou qualitative), plusieurs approches peuvent être utilisées pour quantifier l’écart entre valeurs réelles et valeurs prédites.\n\n##### Pour une variable quantitative {#sec-081531}\n\nLa mesure la plus couramment utilisée pour une variable quantitative est l’erreur moyenne quadratique (*Root Mean Square Error* – RMSE en anglais). \n\n$$\nRMSE = \\sqrt{\\frac{\\sum_{i=1}^n(y_i - \\hat{y_i})^2}{n}}\n$$ {#eq-glm11}\n\n\nIl s’agit de la racine carrée de la moyenne des écarts au carré entre valeurs réelles et prédites. Le RMSE est exprimé dans la même unité que la donnée originale et nous donne une indication sur l’erreur moyenne de la prédiction du modèle. Admettons, par exemple, que nous modélisons les niveaux de bruit environnemental en ville en décibels et que notre modèle de régression ait un RMSE de 3,5. Cela signifierait qu’en moyenne notre modèle se trompe de 3,5 décibels (erreur pouvant être négative ou positive), ce qui serait énorme (3 décibels correspondent à une multiplication par deux de l’intensité sonore) et nous amènerait à reconsidérer la fiabilité du modèle. Notez que l’usage d’une moyenne quadratique plutôt qu’une moyenne arithmétique permet de donner plus d’influence aux larges erreurs et donc de pénaliser davantage des modèles faisant parfois de grosses erreurs de prédiction. Le RMSE est donc très sensible à la présence de valeurs aberrantes.\nÀ la place de la moyenne quadratique, il est possible d’utiliser la simple moyenne arithmétique des valeurs absolues des erreurs (MAE). Cette mesure est cependant moins souvent utilisée :\n\n$$\nMAE = \\frac{\\sum_{i=1}^n|y_i - \\hat{y_i|}}{n}\n$$ {#eq-glm12}\n\n\nCes deux mesures peuvent être utilisées pour comparer la capacité de prédiction de deux modèles appliqués aux mêmes données, même s’ils ne sont pas imbriqués. Elles ne permettent cependant pas de prendre en compte la complexité du modèle. Un modèle plus complexe aura toujours des valeurs de RMSE et de MAE plus faibles.\n\n##### Pour une variable qualitative {#sec-081532}\n\nLorsque l’on modélise une variable qualitative, une erreur revient à prédire la mauvaise catégorie pour une observation. Il est ainsi possible de compter, pour un modèle, le nombre de bonnes et de mauvaises prédictions et d’organiser cette information dans une **matrice de confusion**. Cette dernière prend la forme suivante pour un modèle binaire : \n\n```{r}\n#| label: tbl-confusmat1\n#| tbl-cap: Exemple de matrice de confusion\n#| echo: false\n#| message: false\n#| warning: false\ndf <- data.frame(\n C1 = c(\"A\" , \"B\", \"Total (%)\"),\n C2 = c(\"15\" , \"5\", \"20 (46,6)\"),\n C3 = c(\"3\" , \"20\", \"23 (53,5)\"),\n C4 = c(\"18 (41,9)\" , \"25 (51,1)\", \"43 (81,4)\")\n)\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Valeur prédite / Valeur réelle\" , \"A\", \"B\", \"Total (%)\"),\n align= c(\"l\", \"r\", \"r\", \"r\"))\n```\n\nEn colonne du @tbl-confusmat1, nous avons les catégories observées et en ligne, les catégories prédites. La diagonale représente les prédictions correctes. Dans le cas présent, le modèle a bien catégorisé 35 (15 + 20) observations sur 43, soit une précision totale de 81,4 %; huit sont mal classifiées (18,6 %); cinq avec la modalité A ont été catégorisées comme des B, soit 20 % des A, et seules trois B ont été catégorisées comme des A (13 %).\n\nLa matrice ci-dessus (@tbl-confusmat1) ne comporte que deux catégories possibles puisque la variable *Y* modélisée est binaire. Il est facile d'étendre le concept de matrice de confusion au cas des variables avec plus de deux modalités (multinomiale). Le @tbl-confusmat2 est un exemple de matrice de confusion multinomiale.\n\n```{r}\n#| label: tbl-confusmat2\n#| tbl-cap: Exemple de matrice de confusion multinomiale\n#| echo: false\n#| message: false\n#| warning: false\n#| out-width: \"50%\"\ndf <- data.frame(\n C1 = c(\"A\" , \"B\" , \"C\", \"D\", \"Total (%)\"),\n C2 = c(\"15\" , \"5\", \"2\", \"1\" , \"23 (18,1)\"),\n C3 = c(\"3\", \"20\", \"10\", \"0\", \"33 (25,7)\"),\n C4 = c(\"1\", \"2\", \"25\", \"5\", \"33 (25,7)\"),\n C5 = c(\"5\", \"12\" , \"8\" , \"14\" , \"39 (30,5)\"),\n C6 = c(\"24 (18,7)\", \"39 (30,4)\", \"45 (35,2)\", \"20 (15,6)\", \"128\")\n)\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Valeur prédite / Valeur réelle\" , \"A\", \"B\" , \"C\", \"D\", \"Total (%)\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\"))\n```\n\nTrois mesures pour chaque catégorie peuvent être utilisées pour déterminer la capacité de prédiction du modèle : \n\n* La précision (*precision* en anglais), soit le nombre de fois où une catégorie a été correctement prédite, divisé par le nombre de fois où la catégorie a été prédite.\n\n* Le rappel (*recall* en anglais), soit le nombre de fois où une catégorie a été correctement prédite divisé par le nombre de fois où elle se trouve dans les données originales.\n\n* Le score *F1* est la moyenne harmonique entre la précision et le rappel, soit :\n\n$$\n\\text{F1} = 2 \\times \\frac{\\text{précision} \\times \\text{rappel}}{\\text{précision} + \\text{rappel}}\n$$ {#eq-glm13}\n\nIl est possible de calculer les moyennes pondérées des différents indicateurs (macro-indicateurs) afin de disposer d’une valeur d’ensemble pour le modèle. La pondération est faite en fonction du nombre de cas observé de chaque catégorie; l’idée étant qu’il est moins grave d’avoir des indicateurs plus faibles pour des catégories moins fréquentes. Cependant, il est tout à fait possible que cette pondération ne soit pas souhaitable. C’est par exemple le cas dans de nombreuses études en santé portant sur des maladies rares où l’attention est concentrée sur ces catégories peu fréquentes.\n\nLe **coefficient de Kappa** (variant de 0 à 1) peut aussi être utilisé pour quantifier la fidélité générale de la prédiction du modèle. Il est calculé avec l'@eq-kappEq :\n\n$$\nk = \\frac{Pr(a)-Pr(e)}{1-Pr(e)}\n$$ {#eq-kappEq}\n\n\navec $Pr(a)$ la proportion d'accords entre les catégories observées et les catégories prédites, et $Pr(e)$ la probabilité d'un accord aléatoire entre les catégories observées et les catégories prédites (@eq-kappEq2).\n\n$$\nPr(e) = \\sum^{J}_{j=1} \\frac{Cnt_{prédit}(j)}{n\\times2} \\times \\frac{Cnt_{réel}(j)}{n\\times2}\n$$ {#eq-kappEq2}\n\n\navec *n* le nombre d'observations, $Cnt_{prédit}(j)$ le nombre de fois où le modèle prédit la catégorie *j* et $Cnt_{réel}(j)$ le nombre de fois où la catégorie *j* a été observée.\n\nPour l'interprétation du coefficient de Kappa, référez-vous au @tbl-Kappvals.\n\n```{r}\n#| label: tbl-Kappvals\n#| tbl-cap: Inteprétation des valeurs du coefficient de Kappa\n#| echo: false\n#| message: false\n#| warning: false\nindicators <- data.frame(\n K = c(\"< 0\", \"0 - 0,20\", \"0,21 - 0,40\", \"0,41 - 0,60\", \"0,61 - 0,80\", \"0,81 - 1\"),\n Inter = c(\"Désaccord\", \"Accord très faible\", \"Accord faible\", \"Accord modéré\", \"Accord fort\", \"Accord presque parfait\")\n)\nknitr::kable(indicators, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"K\" , \"Interprétation\"),\n align= c(\"l\", \"l\"))\n```\n\nEnfin, un test statistique basé sur la distribution binomiale peut être utilisé pour vérifier que le modèle atteint un niveau de précision supérieur au seuil de non-information. Ce seuil correspond à la proportion de la modalité la plus présente dans le jeu de données. Dans la matrice de confusion utilisée dans le @tbl-Kappvals, ce seuil est de 30,5 % (catégorie D), ce qui signifie qu’un modèle prédisant tout le temps la catégorie D aurait une précision de 30,5 % pour cette catégorie. Il est donc nécessaire que notre modèle fasse mieux que ce seuil.\n\nDans le cas de la matrice de confusion du @tbl-confusmat2, nous obtenons donc les valeurs affichées dans le @tbl-confusIndic.\n\n```{r}\n#| label: tbl-confusIndic\n#| tbl-cap: Indicateurs de qualité de prédiction\n#| echo: false\n#| message: false\n#| warning: false\nindicators <- data.frame(\n C1 = c(\"A\", \"B\", \"C\", \"D\", \"macro\", \"Kappa\", \"Valeur de p (précision > NIR)\"),\n C2 = c(\"65,2\", \"60,6\", \"75,8\", \"35,9\", \"57,8\", \"0,44\", \"< 0,0001\"),\n C3 = c(\"31,3\", \"25,6\", \"27,8\", \"35,0\", \"30,0\", \"\", \"\"),\n C4 = c(\"42,3\", \"36,0\", \"40,7\" ,\"35,4\" ,\"38,2\" , \"\" , \"\")\n)\nknitr::kable(indicators, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"\", \"précision\", \"rappel\", \"F1\"),\n align= c(\"l\", \"r\", \"r\", \"r\"))\n```\n\nÀ la lecture du @tbl-confusIndic, nous remarquons que : \n\n* La catégorie D est la moins bien prédite des quatre catégories (faible précision et faible rappel).\n\n* La catégorie C a une forte précision, mais un faible rappel, ce qui signifie que de nombreuses observations étant originalement des A, B ou D ont été prédites comme des C. Ce constat est également vrai pour la catégorie B.\n\n* Le coefficient de Kappa indique un accord modéré entre les valeurs originales et la prédiction.\n\n* La probabilité que la précision du modèle ne dépasse pas le seuil de non-information est inférieure à 0,001, indiquant que le modèle à une précision supérieure à ce seuil.\n\n\n### Comparaison de deux modèles GLM {#sec-0816}\n\nTel qu'abordé dans le chapitre sur les régressions linéaires classiques, il est courant de comparer plusieurs modèles imbriqués ([section @sec-0732]). Cette procédure permet de déterminer si l'ajout d'une ou de plusieurs variables contribue à significativement améliorer le modèle. Il est possible d'appliquer la même démarche aux GLM à l'aide du test de rapport de vraisemblance (*likelihood ratio test*). Le principe de base de ce test est de comparer le *likelihood* de deux modèles GLM imbriqués; la valeur de ce test se calcule avec l'équation suivante :\n\n$$\nLR = 2(loglik(M_2) - loglik(M_1))\n$$ {#eq-glm14}\n\n\navec $M_2$ un modèle reprenant toutes les variables du modèle $M_1$, impliquant donc que $loglik(M_2) >= loglik(M_1)$. \n\nAvec ce test, nous supposons que le modèle $M_2$, qui comporte plus de paramètres que le modèle $M_1$, devrait être mieux ajusté aux données. Si c'est bien le cas, la différence entre les *loglikelihood* de deux modèles devrait être supérieure à zéro. La valeur calculée *LR* suit une distribution du khi-deux avec un nombre de degrés de liberté égal au nombre de paramètres supplémentaires dans le modèle $M_2$ comparativement à $M_1$. Avec ces deux informations, il est possible de déterminer la valeur de *p* associée à ce test et de déterminer si $M_2$ est significativement mieux ajusté que $M_1$ aux données. Notez qu'il existe aussi deux autres tests (test de Wald et test de Lagrange) ayant la même fonction. Il s'agit, dans les deux cas, d'approximation du test de rapport des vraisemblances dont la puissance statistique est inférieure au test de rapport de vraisemblance [@NeymanLemma].\n\nDans les prochaines sections, nous décrivons les modèles GLM les plus couramment utilisés. Il en existe de nombreuses variantes que nous ne pouvons pas toutes décrire ici. L'objectif est de comprendre les rouages de ces modèles afin de pouvoir, en cas de besoin, transposer ces connaissances sur des modèles plus spécifiques. Pour faciliter la lecture de ces sections, nous vous proposons une carte d’identité de chacun des modèles présentés. Elles contiennent l’ensemble des informations pertinentes à retenir pour chaque modèle.\n\n\n## Modèles GLM pour des variables qualitatives {#sec-082}\n\nNous abordons en premier les principaux GLM utilisés pour modéliser des variables binaires, multinomiales et ordinales. Prenez bien le temps de saisir le fonctionnement du modèle logistique binomial, car il sert de base pour les trois autres modèles présentés.\n\n### Modèle logistique binomial {#sec-0821}\n\nLe modèle logistique binomial est une généralisation du modèle de Bernoulli que nous avons présenté dans l’introduction de cette section. Le modèle logistique binomiale couvre donc deux cas de figure : \n\n1.\tLa variable observée est binaire (0 ou 1). Dans ce cas, le modèle logistique binomiale devient un simple modèle de Bernoulli.\n\n2.\tLa variable observée est un comptage (nombre de réussites) et nous disposons d’une autre variable avec le nombre de réplications de l’expérience. Par exemple, pour chaque intersection d’un réseau routier, nous pourrions avoir le nombre de décès à vélo (variable *Y* de comptage) et le nombre de collisions vélo / automobile (variable quantifiant le nombre d’expériences, chaque collision étant une expérience).\nSpécifiquement, nous tentons de prédire le paramètre *p* de la distribution binomiale à l’aide de notre équation de régression et de la fonction logistique comme fonction de lien. Notez ici que cette fonction de lien influence directement l'interprétation des paramètres du modèle. Pour rappel, cette fonction est définie comme :\n\n$$\ng(x) = ln(\\frac{x}{1-x})\n$$\n\navec $ln$ étant le logarithme naturel.\n\nAu-delà de sa propriété mathématique assurant que $g(x) \\in \\mathopen[0,1\\mathclose]$, cette fonction offre une interprétation intéressante. La partie $\\frac{x}{1-x}$ est une cote et s'interprète en termes de chances d'observer un évènement. Par exemple, dans le cas des accidents de cyclistes, si la probabilité d'observer un décès suite à une collision est de 0,1, alors la cote de cet évènement est $\\frac{\\frac{1}{10}}{\\frac{9}{10}} = \\frac{1}{9}$ soit un contre neuf. Dans un modèle GLM logistique, les coefficients ajustés pour les variables indépendantes représentent des **logarithmes de rapport de cote**, car ils comparent les chances d'observer l'évènement (y = 1) en fonction des valeurs des variables indépendantes.\n\n```{r}\n#| label: tbl-binomidentity\n#| tbl-cap: Carte d'identité du modèle logistique binomial\n#| echo: false\n#| message: false\n#| warning: false\nmodel_formula <- \"$Y \\\\sim Binomial(p)$ \\\\newline $g(p) = \\\\beta_0 + \\\\beta X$ \\\\newline $g(x) = log(\\\\frac{x}{1-x})$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable binaire (0 ou 1) ou comptage de réussite à une expérience (ex : 3 réussites sur 5 expériences)\", \"Binomiale\", model_formula , \"Logistique\", \"p\", \"$\\\\beta_0$, $\\\\beta$\", \"Non-séparation complète, absence de sur-dispersion ou de sous-dispersion\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\")\n```\n\n#### Interprétation des paramètres {#sec-08211}\n\nLes seuls paramètres à estimer du modèle sont les coefficients $\\beta$ et la constante $\\beta_0$. La fonction de lien logistique transforme la valeur de ces coefficients, en conséquence, **ils ne peuvent plus être interprétés directement**. $\\beta_0$ et $\\beta$ sont exprimés dans une unité particulière: des logarithmes de rapports de cote (*log odd ratio*). Le rapport de cote est relativement facile à interpréter contrairement à son logarithme. Pour l’obtenir, il suffit d’utiliser la fonction exponentielle (l’inverse de la fonction logarithme) pour passer des log rapports de cote à de simples rapports de cote.\nDonc si $exp(\\beta)$ est inférieur à 1, il réduit les chances d’observer l’évènement et inversement si $exp(\\beta)$ est supérieur à 1. \n\nPar exemple, admettons que nous ayons un coefficient $\\beta_1$ de 1,2 pour une variable $X_1$ dans une régression logistique. Il est nécessaire d'utiliser son exponentiel pour l'interpréter de façon intuitive. $exp\\mbox{(1,2)} = \\mbox{3,32}$, ce qui signifie que lorsque $X_1$ augmente d'une unité, les chances d'observer 1 plutôt que 0 comme valeur de *Y* sont multipliées par 3,32. Admettons maintenant que $\\beta_1$ vaille −1,2, nous calculons donc $exp\\mbox{(-1,2) = 0,30}$, ce qui signifie qu'à chaque augmentation d'une unité de $X_1$, les chances d'observer 1 plutôt que 0 comme valeur de *Y* sont multipliées par 0,30. En d'autres termes,les chances d'observer 1 plutôt que 0 sont divisées par 3,33 ($\\mbox{1}/\\mbox{0,30} = \\mbox{3,33}$), soit une diminution de 70 % ($\\mbox{1}-\\mbox{0,3} = \\mbox{0,7}$) des chances d'observer 1 plutôt que 0.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Les rapports de cotes**\n:::\n::: bloc_aller_loin-body\nLe rapport de cote ou rapport des chances est une mesure utilisée pour exprimer l’effet d’un facteur sur une probabilité. Il est très utilisé dans le domaine de la santé, mais aussi des paris. Prenons un exemple concret avec le port du casque à vélo. Si sur 100 accidents impliquant des cyclistes portant un casque, nous observons seulement 3 cas de blessures graves à la tête, contre 15 dans un second groupe de 100 cyclistes ne portant pas de casque, nous pouvons calculer le rapport de cote suivant : \n\n$$\n\\frac{p(1-q)}{q(1-p)} = \\frac{\\mbox{0,15} \\times (\\mbox{1}-\\mbox{0,03})}{\\mbox{0,03} \\times (\\mbox{1}-\\mbox{0,15})} = \\mbox{5,71}\n$$\n\navec *p* la probabilité d'observer le phénomène (ici la blessure grave à la tête) dans le groupe 1 (ici les cyclistes sans casque) et *q* la probabilité d'observer le phénomène dans le groupe 2 (ici les cyclistes avec un casque). Ce rapport de cote indique que les cyclistes sans casques ont 5,71 fois plus de risques de se blesser gravement à la tête lors d’un accident comparativement aux cyclistes portant un casque.\n:::\n:::\n\n#### Conditions d'application {#sec-08212}\n\nLa non-séparation complète signifie qu’aucune des variables *X* n'est, à elle seule, capable de parfaitement distinguer les deux catégories 0 et 1 de la variable *Y*. Dans un tel cas de figure, les algorithmes d’ajustement utilisés pour estimer les paramètres des modèles sont incapables de converger. Notez aussi l’absurdité de créer un modèle pour prédire une variable *Y* si une variable *X* est capable à elle seule de la prédire à coup sûr. Ce problème est appelé un effet de Hauck-Donner. Il est assez facile de le repérer, car la plupart du temps les fonctions de R signalent ce problème (message d'erreur sur la convergence). Sinon, des valeurs extrêmement élevées ou faibles pour certains rapports de cote peuvent aussi indiquer un effet de Hauck-Donner.\n\nLa sur-dispersion est un problème spécifique aux distributions n’ayant pas de paramètre de dispersion (binomiale, de Poisson, exponentielle, etc.), pour lesquelles la variance dépend directement de l'espérance. La sur-dispersion désigne une situation dans laquelle les résidus (ou erreurs) d'un modèle sont plus dispersés que ce que suppose la distribution utilisée. À l’inverse, il est aussi possible (mais rare) d’observer des cas de sous-dispersion (lorsque la dispersion des résidus est plus petite que ce que suppose la distribution choisie). Ce cas de figure se produit généralement lorsque le modèle parvient à réaliser une prédiction trop précise pour être crédible. Si vous rencontrez une forte sous-dispersion, cela signifie souvent que l’une de vos variables indépendantes provoque une séparation complète. La meilleure option, dans ce cas, est de supprimer la variable en question du modèle. La variance attendue d’une distribution binomiale est $nb \\times p \\times(1-p)$, soit le produit entre le nombre de tirages, la probabilité de réussite et la probabilité d'échec. À titre d'exemple, si nous considérons une distribution binomiale avec un seul tirage et 50 % de chances de réussite, sa variance serait : $1 \\times \\mbox{0,5} \\times \\mbox{(1}-\\mbox{0,5}) = \\mbox{0,25}$.\n\nPlusieurs raisons peuvent expliquer la présence de sur-dispersion dans un modèle : \n\n* il manque des variables importantes dans le modèle, conduisant à un mauvais ajustement et donc une sur-dispersion des erreurs;\n\n* les observations ne sont pas indépendantes, impliquant qu’une partie de la variance n’est pas contrôlée et augmente les erreurs;\n\n* la probabilité de succès de chaque expérience varie d’une répétition à l’autre (différentes distributions).\n\nLa conséquence directe de la sur-dispersion est la sous-estimation de la variance des coefficients de régression. En d’autres termes, la sur-dispersion conduit à sous-estimer notre incertitude quant aux coefficients obtenus et réduit les valeurs de *p* calculées pour ces coefficients. Les risques de trouver des résultats significatifs à cause des fluctuations d'échantillonnage augmentent.\n\nPour détecter une sur-dispersion ou une sous-dispersion dans un modèle logistique binomial, il est possible d'observer les résidus de déviance du modèle. Ces derniers sont supposés suivre une distribution du khi-deux avec *n−k* degrés de liberté (avec *n* le nombre d'observations et *k* le nombre de coefficients dans le modèle). Par conséquent, la somme des résidus de déviance d'un modèle logistique binomiale divisée par le nombre de degrés de liberté devrait être proche de 1. Une légère déviation (jusqu'à 0,15 au-dessus ou au-dessous de 1) n'est pas alarmante; au-delà, il est nécessaire d'ajuster le modèle.\n\nNotez que si la variable *Y* modélisée est exactement binaire (chaque expérience est indépendante et n'est composée que d'un seul tirage) et que le modèle utilise donc une distribution de Bernoulli, le test précédent pour détecter une éventuelle sur-dispersion n'est pas valide. @hilbe2009logistic parle de sur-dispersion implicite pour le modèle de Bernoulli et recommande notamment de toujours ajuster les erreurs standards des modèles utilisant des distributions de Bernoulli, binomiale et de Poisson. L'idée ici est d'éviter d'être trop optimiste face à l'incertitude du modèle sur les coefficients et de l'ajuster en conséquence. Pour cela, il est possible d'utiliser des quasi-distributions ou des estimateurs robustes [@zeileis2004econometric]. Notez que si le modèle ne souffre pas de sur ou sous-dispersion, ces ajustements produisent des résultats équivalents aux résultats non ajustés.\n\n#### Exemple appliqué dans R {#sec-08213}\n\n**Présentation des données**\n\nPour illustrer le modèle logistique binomial, nous utilisons ici un jeu de données proposé par l’Union européenne : [l’enquête de déplacement sur la demande pour des systèmes de transports innovants](https://dataverse.harvard.edu/dataset.xhtml?persistentId=doi:10.7910/DVN/P82V9X). Pour cette enquête, un échantillon de 1 000 individus représentatifs de la population a été constitué dans chacun des 26 États membres de l’UE, soit un total de 26 000 observations. Pour chaque individu, plusieurs informations ont été collectées relatives à la catégorie socioprofessionnelle, le mode de transport le plus fréquent, le temps du trajet de son déplacement le plus fréquent et son niveau de sensibilité à la cause environnementale. Nous modélisons ici la probabilité qu’un individu déclare utiliser le plus fréquemment le vélo comme moyen de transport. Les variables explicatives sont résumées au @tbl-binomdata. Il existe bien évidemment un grand nombre de facteurs individuels qui influence la prise de décision sur le mode de transport. Les résultats de ce modèle ne doivent donc pas être pris avec un grand sérieux; il est uniquement construit à des fins pédagogiques, sans cadre conceptuel solide.\n\n```{r}\n#| label: tbl-binomdata\n#| tbl-cap: Variables indépendantes utilisées pour prédire le mode de transport le plus utilisé\n#| echo: false\n#| message: false\n#| warning: false\ntableau <- data.frame(\n C1 = c(\"Pays\", \"Sexe\", \"Age\", \"Education\", \"StatutEmploi\", \"Revenu\", \"Residence\", \"Duree\", \"ConsEnv\"),\n C2 = c(\"Pays de résidence\", \"Sexe biologique\", \"Âge biologique\", \"Niveau d’éducation maximum atteint\", \"Employé ou non\", \"Niveau de revenu autodéclaré\", \"Lieu de résidence\", \"Durée du voyage le plus fréquent autodéclarée (en minutes)\", \"Préoccupation environnementale\"),\n C3 = c(\"Variable multinomiale\", \"Variable binaire\", \"Variable continue\", \"Variable multinomiale\", \"Variable binaire\", \"Variable multinomiale\", \"Variable multinomiale\", \"Variable continue\", \"Variable ordinale\"),\n C4 = c(\"Le nom d’un des 26 pays membres de l’UE\", \"Homme ou femme\", \"L’âge en nombre d’années variant de 16 à 84 ans dans le jeu de données\", \"Premier cycle, secondaire inférieur (classes supérieures de l’école élémentaire), secondaire, troisième cycle\", \"Employé ou non\", \"Très faible revenu, faible revenu, revenu moyen, revenu élevé, revenu très élevé, sans reponse\", \"Zone rurale, petite ou moyenne ville (moins de 250 000 habitants), grande ville (entre 250 000 et 1 million d’habitants) , aire métropolitaine (plus d’un million d’habitants)\", \"Nombre de minutes\", \"Échelle de Likert de 1 à 10\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Nom de la variable\" , \"Signification\" , \"Type de variable\" , \"Mesure\"), \n col.to.resize = c(2,4),\n col.width = \"5cm\",\n align= c(\"l\", \"l\", \"l\", \"l\"))\n```\n\n**Vérification des conditions d'application**\n\nLa première étape de la vérification des conditions d'application est de calculer les valeurs du facteur d'inflation de variance (VIF) pour s'assurer de l'absence de multicolinéarité trop forte entre les variables indépendantes. L'ensemble des valeurs de VIF sont inférieures à 5, indiquant l'absence de multicolinéarité excessive dans le modèle. \n\n```{r}\n#| message: false\n#| warning: false\n#| out-width: \"50%\"\nlibrary(car)\n# Chargement des données\ndfenquete <- read.csv(\"data/glm/enquete_transport_UE.csv\", encoding = 'UTF-8')\ndfenquete$Pays <- relevel(as.factor(dfenquete$Pays), ref = \"Allemagne\")\n# Vérification du VIF\nmodel1 <- glm(y ~\n Pays + Sexe + Age + Education + StatutEmploi + Revenu +\n Residence + Duree + ConsEnv,\n family = binomial(link=\"logit\"),\n data = dfenquete\n)\nvif(model1)\n```\n\nLa seconde étape de vérification est le calcul des distances de Cook et l'identification d'éventuelles valeurs aberrantes (@fig-cookdistGLMbinom).\n\n```{r}\n#| label: fig-cookdistGLMbinom\n#| fig-align: center\n#| fig-cap: Distances de Cook pour le modèle binomial avec toutes les observations\n#| warning: false\n#| message: false\n#| out-width: \"60%\"\n\n# Calcul et représentation des distances de Cook\ncookd <- data.frame(\n dist = cooks.distance(model1),\n oid = 1:nrow(dfenquete)\n)\nggplot(cookd) + \n geom_point(aes(x = oid, y = dist ), color = rgb(0.1,0.1,0.1,0.4), size = 1)+\n geom_hline(yintercept = 0.002, color = \"red\")+\n labs(x = \"observations\", y = \"distance de Cook\") + \n theme(axis.text.x = element_blank(),\n axis.ticks.x = element_blank())\n```\n\nLe calcul de la distance de Cook révèle un ensemble d'observations se démarquant nettement des autres (délimitées dans la @fig-cookdistGLMbinom) par la ligne rouge). Nous les isolons dans un premier temps pour les analyser.\n\n```{r}\n#| message: false\n#| warning: false\n#| out-width: \"80%\"\n# Isoler les observations avec de très fortes valeurs de Cook\n# valeur seuil choisie : 0,002\ncas_etranges <- subset(dfenquete, cookd$dist>=0.002)\ncat(nrow(cas_etranges),'observations se démarquant dans le modèle')\nprint(cas_etranges)\n```\n\nÀ la lecture des valeurs pour ces 19 cas étranges, nous remarquons que la plupart des observations proviennent de Malte et de Chypre. Ces deux petites îles constituent des cas particuliers en Europe et devraient vraisemblablement faire l'objet d'une analyse séparée. Nous décidons donc de les retirer du jeu de données. Deux autres observations étranges sont observables en Slovaquie et au Luxembourg. Dans les deux cas, les répondants ont renseigné des temps de trajet fantaisistes de respectivement 775 et 720 minutes. Nous les retirons donc également de l'analyse.\n\n```{r}\n#| label: fig-cookdistGLMbinom2\n#| fig-align: center\n#| fig-cap: Distances de Cook pour le modèle binomial sans les valeurs aberrantes\n#| warning: false\n#| message: false\n#| out-width: \"60%\"\n\n# Retirer les observations aberrantes\ndfenquete2 <- subset(dfenquete, (dfenquete$Pays %in% c(\"Malte\", \"Chypre\")) == F & \n dfenquete$Duree < 400)\n# Réajuster le modèle\nmodel2 <- glm(y ~\n Pays + Sexe + Age + Education + StatutEmploi + Revenu +\n Residence + Duree + ConsEnv,\n family = binomial(link=\"logit\"),\n data = dfenquete2)\n# Recalculer la distance de Cook\ncookd <- data.frame(\n dist = cooks.distance(model2),\n oid = 1:nrow(dfenquete2)\n)\nggplot(cookd) + \n geom_point(aes(x = oid, y = dist ), color = rgb(0.1,0.1,0.1,0.4), size = 1)+\n labs(x = \"observations\", y = \"distance de Cook\") + \n theme(axis.text.x = element_blank(),\n axis.ticks.x = element_blank())\n```\n\nAprès avoir retiré ces valeurs aberrantes, nous n'observons plus de nouveaux cas singuliers avec les distances de Cook (@fig-cookdistGLMbinom2).\n\nLa prochaine étape de vérification des conditions d'application est l'analyse des résidus simulés. Nous commençons donc par calculer ces résidus et afficher leur histogramme (@fig-residsimbinomHistoUnif).\n\n```{r}\n#| label: fig-residsimbinomHistoUnif\n#| fig-align: center\n#| fig-cap: Distribution des résidus simulés pour le modèle binomial\n#| out-width: \"60%\"\n#| message: false\n#| warning: false\n\nlibrary(DHARMa)\n# Extraire les probabilités prédites par le modèle\nprobs <- predict(model2, type = \"response\")\n# Calculer 1000 simulations a partir du modele ajuste\nsims <- lapply(1:length(probs), function(i){\n p <- probs[[i]]\n vals <- rbinom(n = 1000, size = 1, prob = p)\n})\nmatsim <- do.call(rbind, sims)\n# Utiliser le package DHARMa pour calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = matsim, \n observedResponse = dfenquete2$y,\n fittedPredictedResponse = probs,\n integerResponse = TRUE)\nggplot()+\n geom_histogram(aes(x = residuals(sim_res)),\n bins = 30, fill = \"white\", color = rgb(0.3,0.3,0.3))+\n labs(x = \"résidus simulés\", y = \"fréquence\")\n```\n\nL'histogramme indique clairement que les résidus simulés suivent une distribution uniforme (@fig-residsimbinomHistoUnif). Il est possible d'aller plus loin dans le diagnostic en utilisant la fonction `plot` sur l'objet `sim_res`. La partie de droite de la figure ainsi obtenue (@fig-residsimbinom) est un diagramme de quantiles-quantiles (ou Q-Q plot). Les points du graphique sont supposés suivre une ligne droite matérialisée par la ligne rouge. Une déviation de cette ligne indique un éloignement des résidus de leur distribution attendue. Trois tests sont également réalisés par la fonction :\n\n* Le premier (Test de Kolmogorov-Smirnov, *KS test*) permet de tester si les points dévient significativement de la ligne droite. Dans notre cas, la valeur de *p* n'est pas significative, indiquant que les résidus ne dévient pas de la distribution uniforme.\n\n* Le second test permet de vérifier la présence de sur ou sous-dispersion. Dans notre cas, ce test n'est pas significatif, n'indiquant aucun problème de sur-dispersion ou de sous-dispersion.\n\n* Le dernier test permet de vérifier si des valeurs aberrantes sont présentes dans les résidus. Une valeur non significative indique une absence de valeurs aberrantes.\n\nLe second graphique permet de comparer les résidus et les valeurs prédites. L'idéal est donc d'observer une ligne droite horizontale au milieu du graphique qui indiquerait une absence de relation entre les valeurs prédites et les résidus (ce que nous observons bien ici).\n\n```{r}\n#| eval: false\nplot(sim_res)\n```\n\n```{r}\n#| label: fig-residsimbinom\n#| fig-align: center\n#| fig-cap: Diagnostic des résidus simulés par le package DHARMa\n#| out-width: \"80%\"\n#| echo: false\n#| message: false\n#| warning: false\ninvisible(capture.output({\n out <- \"images/Chap08/fig-residsimbinom.png\"\n\n png(filename = out,\n res = 300, width = 20, height = 10, units = \"cm\")\n \n plot(sim_res)\n \n dev.off()\n}))\nknitr::include_graphics(out, dpi = 300)\n```\n\n\nL'analyse approfondie des résidus nous permet donc de conclure que le modèle respecte les conditions d'application et que nous pouvons passer à la vérification de la qualité d'ajustement du modèle.\n\n**Vérification de la qualité d'ajustement**\n\nPour calculer les différents R^2^ d'un modèle GLM, nous proposons la fonction suivante :\n\n```{r}\n#| message: false\n#| warning: false\n#| out-width: \"100%\"\nrsqs <- function(loglike.full, loglike.null, full.deviance, null.deviance, nb.params, n){\n # Calcul de la déviance expliquée\n explained_dev <- 1-(full.deviance / null.deviance)\n K <- nb.params\n # R2 de McFadden ajusté\n r2_faddenadj <- 1- (loglike.full - K) / loglike.null\n Lm <- loglike.full\n Ln <- loglike.null\n # R2 de Cox and Snell\n Rcs <- 1 - exp((-2/n) * (Lm-Ln))\n # R2 de Nagelkerke\n Rn <- Rcs / (1-exp(2*Ln/n))\n return(\n list(\"deviance expliquee\" = explained_dev,\n \"McFadden ajuste\" = r2_faddenadj,\n \"Cox and Snell\" = Rcs,\n \"Nagelkerke\" = Rn\n )\n )\n}\n```\n\nNous l'utilisons pour l'ensemble des modèles GLM de ce chapitre. Dans le cas du modèle binomial, nous obtenons : \n\n```{r}\n#| message: false\n#| warning: false\n#| out-width: \"100%\"\n# Ajuster un modele null avec seulement une constante\nmodel2.null <- glm(y ~1,\n family = binomial(link=\"logit\"),\n data = dfenquete2)\n# Calculer les R2\nrsqs(loglike.full = as.numeric(logLik(model2)), # loglikelihood du modèle complet\n loglike.null = as.numeric(logLik(model2.null)), # loglikelihood du modèle nul\n full.deviance = deviance(model2), # déviance du modèle complet\n null.deviance = deviance(model2.null), # déviance du modèle nul\n nb.params = model2$rank, # nombre de paramètres dans le modèle\n n = nrow(dfenquete2) # nombre d'observations\n )\n```\n\nLa déviance expliquée par le modèle est de 8,8 %, les pseudos R^2^ de McFadden (ajusté), d'Efron et de Nagelkerke sont respectivement 0,084, 0,069 et 0,124. Toutes ces valeurs sont relativement faibles et indiquent qu'une large partie de la variabilité de *Y* reste inexpliquée.\n\nPour vérifier la qualité de prédiction du modèle, nous devons comparer les catégories prédites et les catégories réelles de notre variable dépendante et construire une matrice de confusion. Cependant, un modèle GLM binomial prédit **la probabilité d’appartenance au groupe 1** (ici les personnes utilisant le vélo pour effectuer leur déplacement le plus fréquent). Pour convertir ces probabilités prédites en catégories prédites, il faut choisir un seuil de probabilité au-delà duquel nous considérons que la valeur attendue est 1 (cycliste) plutôt que 0 (autre). Un exemple naïf serait de prendre le seuil 0,5, ce qui signifierait que si le modèle prédit qu’une observation a au moins 50 % de chance d’être une personne à vélo, alors nous l’attribuons à cette catégorie. Cependant, cette méthode est rarement optimale; il est donc plus judicieux de fixer le seuil de probabilité en trouvant le point d’équilibre entre la sensibilité (proportion de 1 correctement identifiés) et la spécificité (proportion de 0 correctement identifiés). Ce point d’équilibre est identifiable graphiquement en calculant la spécificité et la sensibilité de la prédiction selon toutes les valeurs possibles du seuil.\n\n```{r}\n#| label: fig-equlibresensispeci\n#| fig-cap: Point d'équilibre entre sensibilité et spécificité\n#| fig-align: center\n#| out-width: \"80%\"\n#| #| message: false\n#| warning: false\n\n\nlibrary(ROCR)\n# Obtention des prédictions du modèle\nprob <- predict(model2, type = \"response\")\n# Calcul de la sensibilité et de la spécificité (package ROCR)\npredictions <- prediction(prob, dfenquete2$y)\nsens <- data.frame(x = unlist(ROCR::performance(predictions, \"sens\")@x.values),\n y = unlist(ROCR::performance(predictions, \"sens\")@y.values))\nspec <- data.frame(x = unlist(ROCR::performance(predictions, \"spec\")@x.values),\n y = unlist(ROCR::performance(predictions, \"spec\")@y.values))\n# Trouver numériquement la valeur seuil (minimiser la différence absolue\n# entre sensibilité et spécificité)\nreal <- dfenquete2$y\nfind_cutoff <- function(seuil){\n pred <- ifelse(prob>seuil,1,0)\n sensi <- sum(real==1 & pred==1) / sum(real==1)\n spec <- sum(real==0 & pred==0) / sum(real==0)\n return(abs(sensi-spec))\n}\nprob_seuil <- optimize(find_cutoff, interval = c(0,1), maximum = FALSE)$minimum\ncat(\"Le seuil de probabilité à retenir équilibrant\",\n \"la sensibilité et la spécificité est de\", prob_seuil)\n# Affichage du graphique\nggplot() +\n geom_line(data = sens, mapping = aes(x = x, y = y)) +\n geom_line(data = spec, mapping = aes(x = x, y = y, col=\"red\")) +\n scale_y_continuous(sec.axis = sec_axis(~., name = \"Spécificité\")) +\n labs(x = \"Seuil de probabilité\", y = \"Sensibilité\") +\n geom_vline(xintercept = prob_seuil, color = \"black\", linetype = \"dashed\") + \n annotate(geom = \"text\", x = prob_seuil, y = 0.01, label = round(prob_seuil,3))+\n theme(axis.title.y.right = element_text(colour = \"red\"), legend.position = \"none\")\n```\n\nNous constatons à la @fig-equlibresensispeci que si la valeur du seuil est 0 %, alors la prédiction a une sensibilité parfaite (le modèle prédit toujours 1, donc tous les 1 sont détectés); à l’inverse, si le seuil choisi est 100 %, alors la prédiction à une spécificité parfaite (le modèle prédit toujours 0, donc tous les 0 sont détectés). Dans notre cas, la valeur d’équilibre est d'environ 0,148, donc si le modèle prédit une probabilité au moins égale à 14,8 % qu’un individu utilise le vélo pour son déplacement le plus fréquent, nous devons l’attribuer à la catégorie *cycliste*. Avec ce seuil, nous pouvons convertir les probabilités prédites en classes prédites et construire notre matrice de confusion.\n\n```{r}\n#| message: false\n#| warning: false\n#| out-width: \"60%\"\nlibrary(caret) # pour la matrice de confusion\n# Calcul des catégories prédites\nypred <- ifelse(predict(model2, type = \"response\")>0.148,1,0)\ninfo <- confusionMatrix(as.factor(dfenquete2$y), as.factor(ypred))\n# Affichage des valeurs brutes de la matrice de confusion\nprint(info)\n```\n\nLes résultats proposés par le *package* `caret` sont exhaustifs; nous vous proposons ici une façon de les présenter dans deux tableaux : l'un présente la matrice de confusion (@tbl-confusmatbinom) et l'autre, les indicateurs de qualité de prédiction (@tbl-confusmatbinom2).\n\n```{r}\n#| label: tbl-confusmatbinom\n#| tbl-cap: Matrice de confusion pour le modèle binomial\n#| echo: false\n#| message: false\n#| warning: false\nmat <- info[[2]]\nrs <- rowSums(mat)\nrp <- round(rowSums(mat) / sum(mat) * 100,1)\ncs <- colSums(mat)\ncp <- round(colSums(mat) / sum(mat) * 100,1)\nmat2 <- cbind(mat, rs, rp)\nmat3 <- rbind(mat2, c(cs, sum(mat), NA), c(cp, NA, NA))\nmat4 <- cbind(c(\"0 (prédit)\", \"1 (prédit)\", \"Total\", \"%\"), mat3)\noptions(knitr.kable.NA = \"\")\nknitr::kable(mat4,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n \t col.names = c(\"\" , \"0 (réel)\", \"1 (réel)\", \"Total\", \"%\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\"))\n```\n\nD’après ces indicateurs, nous constatons que le modèle a une capacité de prédiction relativement faible, mais tout de même significativement supérieure au seuil de non-information. La valeur de rappel pour la catégorie 1 (cycliste) est faible, indiquant que le modèle a manqué un nombre important de cyclistes lors de sa prédiction. \n\n```{r}\n#| label: tbl-confusmatbinom2\n#| tbl-cap: Matrice de confusion pour le modèle binomial\n#| echo: false\n#| message: false\n#| warning: false\nprecision <- diag(mat) / rowSums(mat)\nrappel <- diag(mat) / colSums(mat)\nF1 <- 2*((precision*rappel)/(precision + rappel))\n\npval <- round(info[[3]][[6]],4)\nif(pval == 0){\n pval <- \"< 0,0001\"\n}\n\n\nmacro_scores <- c(weighted.mean(precision, colSums(mat)),\n weighted.mean(rappel, colSums(mat)),\n weighted.mean(F1, colSums(mat)))\nfinal_table <- rbind(cbind(precision, rappel, F1), c(NA, NA, NA, NA), macro_scores)\nfinal_table <- rbind(final_table, c(info[[3]][[2]], NA, NA), c(info[[3]][[6]], NA, NA))\nrnames <- c(rownames(mat),\"\" , \"macro\" , \"Kappa\" , \"Valeur de p (précision > NIR)\")\nfinal_table <- cbind(rnames, round(final_table,2))\nfinal_table[6,2] <- pval\noptions(knitr.kable.NA = \"\")\nknitr::kable(final_table,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n \t col.names = c(\"\" , \"Précision\", \"Rappel\", \"F1\"),\n align= c(\"l\", \"r\", \"r\", \"r\"))\n```\n\n**Interprétation des résultats du modèle**\n\nL'interprétation des résultats d'un modèle binomial passe par la lecture des rapports de cotes (exponentiel des coefficients) et de leurs intervalles de confiance. Nous commençons donc par calculer la version robuste des erreurs standards des coefficients.\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(dplyr)\nlibrary(sandwich) # pour calculer les erreurs standards robustes\ncovModel2 <- vcovHC(model2, type = \"HC0\") # méthode HC0, basée sur les résidus\nstdErrRobuste <- sqrt(diag(covModel2)) # extraire la diagonale\n# Extraction des coefficients\ncoeffs <- model2$coefficients\n# Recalcul des scores Z\nzvalRobuste <- coeffs / stdErrRobuste\n# Recalcul des valeurs de P\npvalRobuste <- 2 * pnorm(abs(zvalRobuste), lower.tail = FALSE)\n# Calcul des rapports de cote\noddRatio <- exp(coeffs)\n# Calcul des intervalles de confiance à 95 % des rapports de cote\nlowerBound <- exp(coeffs - 1.96 * stdErrRobuste)\nupperBound <- exp(coeffs + 1.96 * stdErrRobuste)\n# Étoiles pour les valeurs de p\nstarsp <- case_when(pvalRobuste <= 0.001 ~ \"***\",\n pvalRobuste > 0.001 & pvalRobuste <= 0.01 ~ \"**\",\n pvalRobuste > 0.01 & pvalRobuste <= 0.05 ~ \"*\",\n pvalRobuste > 0.05 & pvalRobuste <= 0.1 ~ \".\",\n TRUE ~ \"\"\n )\n# Compilation des résultats dans un tableau\ntableau_binom <- data.frame(\n coefficients = coeffs,\n rap.cote = oddRatio,\n err.std = stdErrRobuste,\n score.z = zvalRobuste,\n p.val = pvalRobuste,\n rap.cote.2.5 = lowerBound,\n rap.cote.97.5 = upperBound,\n sign = starsp\n)\n```\n\nConsidérant que la variable *Pays* a 24 modalités, il est plus judicieux de présenter ses 23 rapports de cotes sous forme d’un graphique. Nous avons choisi l’Allemagne comme catégorie de référence puisqu’elle fait partie des pays avec une importante part modale pour le vélo sans pour autant constituer un cas extrême comme le Danemark.\n\n```{r}\n#| message: false\n#| warning: false\n#| label: fig-paysbinom\n#| fig-align: center\n#| fig-cap: Rapports de cote pour les différents pays de l'UE\n#| out-width: \"80%\"\n\n# Isoler les ligne du tableau récapitualtif pour les pays\npaysdf <- subset(tableau_binom, grepl(\"Pays\", row.names(tableau_binom), fixed = TRUE))\n#paysdf$Pays <- gsub(\"Pays\" , \"\", row.names(paysdf), fixed = TRUE)\npaysdf$Pays <- substr(row.names(paysdf), 5, nchar(row.names(paysdf)))\nggplot(data = paysdf) +\n geom_vline(xintercept = 1, color = \"red\")+ #afficher la valeur de référence\n geom_errorbarh(aes(xmin = rap.cote.2.5, xmax = rap.cote.97.5, \n y = reorder(Pays, rap.cote)), height = 0)+\n geom_point(aes(x = rap.cote, y = reorder(Pays, rap.cote))) +\n geom_text(aes(x = rap.cote.97.5, y = reorder(Pays, rap.cote), \n label = paste(\"RC : \", round(rap.cote,2), sep = \"\")),\n size = 3, nudge_x = 0.25)+\n labs(x = \"Rapports de cote\", y = \"Pays (référence : Allemagne)\")\n```\n\nDans la @fig-paysbinom, la barre horizontale pour chaque pays représente l’intervalle de confiance de son rapport de cotes (le point); plus cette ligne est longue, plus grande est l’incertitude autour de ce paramètre. Lorsque les lignes de deux pays se chevauchent, cela signifie qu’il n’y a pas de différence significative au seuil 0,05 entre les rapports de cotes des deux pays. La ligne rouge tracée à x = 1, représente le rapport de cotes du pays de référence (ici l’Allemagne). Nous constatons ainsi que comparativement à un individu vivant en Allemagne, ceux vivant au Danemark et aux Pays-Bas ont 2,4 fois plus de chances d’utiliser le vélo pour leur déplacement le plus fréquent. Les Pays de l’Ouest (France, Luxembourg, Royaume-Uni, Irlande) et du Sud (Grèce, Italie, Espagne, Portugal) ont en revanche des rapports de cotes plus faibles. En France, les chances qu’un individu utilise le vélo pour son trajet le plus fréquent sont 3,22 (1/0,31) fois plus faibles que si l’individu vivait en Allemagne.\n\nPour le reste des coefficients et des rapports de cotes, nous les rapportons dans le @tbl-coeffbinom.\n\n```{r}\n#| label: tbl-coeffbinom\n#| tbl-cap: Résultats du modèle binomial\n#| echo: false\n#| warning: false\n#| message: false\ntableau_comp <- build_table(model2, confid = TRUE, sign = TRUE, coef_digits = 3, std_digits = 3, z_digits = 3, p_digits = 3, OR_digits = 3, robust_se = \"HC0\")\nok_tableau <- tableau_comp[c(1,29:54), c(1,2,3,4,5,6,9,10)]\nknitr::kable(ok_tableau,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t col.names = c(\"Variable\" , \"Coefficient\", \"Rapport de cote\", \"Err.std\" , \"Val.z\", \"P\" , \"RC 2,5 %\", \"RC 97,5 %\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\nLes chances pour un individu d’utiliser le vélo pour son trajet le plus fréquent sont augmentées de 45 % s’il s’agit d’un homme plutôt qu’une femme. Pour l’âge, nous constatons un effet relativement faible puisque chaque année supplémentaire réduit les chances qu’un individu utilise le vélo comme mode de transport pour son trajet le plus fréquent de 0,9 % $((\\mbox{0,991}-\\mbox{1})\\times\\mbox{100})$. Le fait d’être sans emploi augmente les chances d’utiliser le vélo de 29 % comparativement au fait d’avoir un emploi. Concernant le niveau d’éducation, seul le coefficient pour le groupe des personnes de la catégorie « secondaire inférieure » est significatif, indiquant que les personnes de ce groupe ont 35 % de chances en plus d'utiliser le vélo comme mode de transport pour leur déplacement le plus fréquent comparativement aux personnes de la catégorie « premier cycle ». Pour le revenu, seul le groupe avec de très faibles revenus se distingue significativement du groupe avec un revenu élevé avec un rapport de cotes de 1,27, soit 27 % de chances en plus d'utiliser le vélo.\n\nComparativement à ceux vivant dans une aire métropolitaine, les personnes vivant dans de petites, moyennes et grandes villes ont des chances accrues d’utiliser le vélo comme mode de déplacement pour leur trajet le plus fréquent. En revanche, nous n'observons aucune différence entre la probabilité d’utiliser le vélo dans une métropole et en zone rurale. La @fig-villebinom permet de clairement visualiser cette situation. Rappelons que la référence est la situation : vivre dans une région métropolitaine, représentée par la ligne verticale rouge. Plusieurs pistes d’interprétation peuvent être envisagées pour ce résultat : \n\n* En métropole et dans les zones rurales, les distances domicile-travail tendent à être plus grandes que dans les petites, moyennes et grandes villes.\n\n* En métropole, le système de transport en commun est davantage développé et entre donc en concurrence avec les modes de transport actifs.\n\n```{r}\n#| label: fig-villebinom\n#| fig-align: center\n#| fig-cap: Rapports de cote pour les différents lieux de résidence\n#| out-width: \"85%\"\n#| message: false\n#| warning: false\n\n# Isoler les lignes du tableau récapitulatif pour les lieux de résidence\nresiddf <- subset(tableau_binom, grepl(\"Residence\", row.names(tableau_binom), fixed = TRUE))\nresiddf$resid <- gsub(\"Residence\" , \"\", row.names(residdf), fixed=T)\nggplot(data = residdf) +\n geom_vline(xintercept = 1, color = \"red\")+ #afficher la valeur de référence\n geom_errorbarh(aes(xmin = rap.cote.2.5, xmax = rap.cote.97.5, y = resid), height = 0)+\n geom_point(aes(x = rap.cote, y = resid)) +\n geom_text(aes(x = rap.cote.97.5, y = resid, \n label = paste(\"RC : \", round(rap.cote,2), sep = \"\")),\n size = 3, nudge_x = 0.1)+\n labs(x = \"Rapports de cotes\",\n y = \"Lieu de résidence (référence : aire métropolitaine)\")\n```\n\nIl est aussi intéressant de noter que la durée des trajets ne semble pas influencer la probabilité d’utiliser le vélo. Enfin, une conscience environnementale plus affirmée semble être associée avec une probabilité supérieure d’utiliser le vélo pour son déplacement le plus fréquent, avec une augmentation des chances de 11 % pour chaque point supplémentaire sur l’échelle de Likert.\n\nAfin de simplifier la présentation de certains résultats, il est possible de calculer exactement les prédictions réalisées par le modèle. Un bon exemple ici est le cas de la variable *âge*. À quelle différence pouvons-nous nous attendre entre deux individus identiques ayant seulement une différence d’âge de 15 ans?\n\nPrenons comme individu un homme de 30 ans, vivant dans une grande ville allemande, ayant un niveau d’éducation de niveau secondaire, employé, dans la tranche de revenu moyen, déclarant effectuer un trajet de 45 minutes et ayant rapporté un niveau de conscience environnementale de 5 (sur 10). Nous pouvons prédire la probabilité qu’il utilise le vélo pour son trajet le plus fréquent en utilisant la formule suivante : \n\n\n$$logit(p) = -\\mbox{2,497} + \\mbox{1} \\times \\mbox{0,372} + \\mbox{30} \\times -\\mbox{0,009} + \\mbox{1} \\times \\mbox{0,193} + \\mbox{1} \\times \\mbox{0,042} + \\mbox{1} \\times \\mbox{0,273} + \\mbox{45} \\times -\\mbox{0,001} + \\mbox{5} \\times \\mbox{0,102}$$\n\n$$p = \\frac{exp(-\\mbox{2,497} + \\mbox{1} \\times \\mbox{0,372} + \\mbox{30} \\times -\\mbox{0,009} + \\mbox{1} \\times \\mbox{0,193} + \\mbox{1} \\times \\mbox{0,042} + 1 \\times \\mbox{0,273} + 45 \\times -\\mbox{0,001} + \\mbox{5} \\times \\mbox{0,102})}{(\\mbox{1}+exp(-\\mbox{2,497} + 1 \\times \\mbox{0,372} + \\mbox{30} \\times-\\mbox{0,009} + 1 \\times \\mbox{0,193} + 1 \\times \\mbox{0,042} + \\mbox{1} \\times \\mbox{0,273} + \\mbox{45} \\times -\\mbox{0,001} + 5 \\times \\mbox{0,102}))} = \\mbox{0,194}$$\n\n\nIl y aurait 19,4 % de chances pour que cette personne soit cycliste. Comme cette probabilité dépasse le seuil que nous avons sélectionné, cette personne serait classée comme cycliste. Si nous augmentons son âge de 15 ans, nous obtenons :\n\n$$p = \\frac{exp(-\\mbox{2,497} + \\mbox{1} \\times \\mbox{0,372} + \\mbox{45} \\times \\mbox{-0,009} + \\mbox{1} \\times \\mbox{0,193} + \\mbox{1} \\times \\mbox{0,042} + \\mbox{1} \\times \\mbox{0,273} + \\mbox{45} \\times -\\mbox{0,001} + \\mbox{5} \\times \\mbox{0,102})} {(\\mbox{1}+exp(-\\mbox{2,497} + \\mbox{1} \\times \\mbox{0,372} + \\mbox{45} \\times -\\mbox{0,009} + \\mbox{1} \\times \\mbox{0,193} + \\mbox{1} \\times \\mbox{0,042} + \\mbox{1} \\times \\mbox{0,273} + \\mbox{45} \\times -\\mbox{0,001} + \\mbox{5} \\times \\mbox{0,102}))} = \\mbox{0,174}$$\n\nsoit une réduction de 2 points de pourcentages. Il est également possible de représenter cette évolution sur un graphique pour montrer l’effet sur l’étendue des valeurs possibles. Sur ces graphiques des effets marginaux, il est essentiel de représenter l'incertitude quant à la prédiction. En temps normal, la fonction `predict` calcule directement l'erreur standard de la prédiction et cette dernière peut être utilisée pour calculer l'intervalle de confiance de la prédiction. Cependant, nous voulons ici utiliser nos erreurs standards robustes. Nous devons donc procéder par simulation pour déterminer l'intervalle de confiance à 95 % de nos prédictions. Cette opération nécessite de réaliser plusieurs opérations manuellement dans R.\n\n```{r}\n#| label: fig-agebinom\n#| fig-align: center\n#| fig-cap: Effet de l'âge sur la probabilité d'utiliser le vélo comme moyen de déplacement pour son trajet le plus fréquent\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n\n# Créer un jeu de données fictif pour la prédiction\nmat <- model.matrix(model2$terms, model2$model)\nage2seq <- seq(20, 80)\nmat2 <- matrix(mat[1,], nrow = length(age2seq), ncol = length(mat[1,]), byrow = TRUE)\ncolnames(mat2) <- colnames(mat)\nmat2[,\"Age\"] <- age2seq\nmat2[,\"PaysBelgique\"] <- 0\nmat2[,\"Duree\"] <- 45\nmat2[,\"ConsEnv\"] <- 5\nmat2[,\"StatutEmploisans emploi\"] <- 0\nmat2[,\"Residencegrande ville\"] <- 1\nmat2[,\"Educationsecondaire\"] <- 1\nmat2[,\"Sexehomme\"] <- 1\nmat2[,\"Revenumoyen\"] <- 1\nmat2[,\"Revenufaible\"] <- 0\n# Calculer la prédiction comme un log de rapport de cote (avec les erreurs standards)\n# en multipliant les coefficient par les valeurs des données fictives\ncoeffs <- model2$coefficients\npred <- coeffs %*% t(mat2)\n# Simulation de prédictions (toujours en log de rapport de cote)\n# Étape 1 : simuler 1000 valeurs pour chaque coefficient\nsim_coeffs <- lapply(1:length(coeffs), function(i){\n coef <- coeffs[[i]]\n std.err <- stdErrRobuste[[i]]\n vals <- rnorm(n = 1000, mean = coef, sd = std.err)\n return(vals)\n})\nmat_sim_coeffs <- do.call(rbind, sim_coeffs)\n# Étape 2 : effectuer les prédictions à partir des coefficients simulés\nsim_preds <- lapply(1:ncol(mat_sim_coeffs), function(i){\n temp_coefs <- mat_sim_coeffs[,i]\n temp_pred <- as.vector(temp_coefs %*% t(mat2))\n return(temp_pred)\n})\nmat_sim_preds <- do.call(cbind, sim_preds)\n# Étape 3 : extraire les intervalles de confiance pour les simulations\nintervals <- apply(mat_sim_preds, MARGIN = 1, FUN = function(vec){\n return(quantile(vec, probs = c(0.025, 0.975)))\n})\n# Étape 4 : récupérer tous ces éléments dans un DataFrame\ndf <- data.frame(\n Age = seq(20,80),\n pred = as.vector(pred),\n lower = as.vector(intervals[1,]),\n upper = as.vector(intervals[2,])\n)\n# Étape 5 : appliquer l'inverse de la fonction de lien pour\n# obtenir les prédictions en termes de probabilité\nilink <- family(model2)$linkinv\ndf$prob_pred <- ilink(df$pred)\ndf$prob_lower <- ilink(df$lower)\ndf$prob_upper <- ilink(df$upper)\n# Étape 6 : représenter le tout sur un graphique\nggplot(df) + \n geom_ribbon(aes(x = Age, ymax = prob_upper, ymin = prob_lower), \n fill = rgb(0.1,0.1,0.1,0.4)) + \n geom_path(aes(x = Age, y = prob_pred), color = \"blue\", size = 1) +\n geom_hline(yintercept = 0.15, linetype = \"dashed\", size = 0.7) + \n labs(x = \"Âge\", y = \"Probabilité prédite (intervalle de confiance à 95 %)\")\n```\n\nLa @fig-agebinom permet de bien constater la diminution de la probabilité d’utiliser le vélo pour son trajet le plus fréquent avec l’âge, mais cette réduction est relativement ténue. Dans le cas utilisé en exemple, l’individu ne serait plus classé cycliste qu’après 67 ans.\n\n### Modèle probit binomial {#sec-0822}\n\nLe modèle GLM probit binomial est pour ainsi dire le frère du modèle logistique binomial. La seule différence entre les deux réside dans l'utilisation d'une autre fonction de lien: probit plutôt que logistique. La fonction de lien probit (Φ) correspond à la fonction cumulative de la distribution normale et a également une forme de *S*. Cette version du modèle est plus souvent utilisée par les économistes. Le principal changement réside dans l’interprétation des coefficients $\\beta_0$ et $\\beta$. Du fait de la transformation probit, ces derniers indiquent le changement en termes de scores Z de la probabilité modélisée. Vous conviendrez qu’il ne s’agit pas d’une échelle très intuitive; la plupart du temps, seuls la significativité et le signe (positif ou négatif) des coefficients sont interprétés.\n\n```{r}\n#| label: tbl-probitdentity\n#| tbl-cap: Carte d'identité du modèle probit binomial\n#| echo: false\n#| message: false\n#| warning: false\nmodel_formula <- \"$Y \\\\sim Binomial(p)$ \\\\newline $g(p) = \\\\beta_0 + \\\\beta X$ \\\\newline $g(x) = \\\\Phi^-1(x)$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable binaire (0 ou 1) ou comptage de réussite à une expérience (ex : 3 réussites sur 5 expériences)\", \"Binomiale\", model_formula , \"probit\", \"p\", \"$\\\\beta_0$, $\\\\beta$\", \"Non-séparation complète, absence de sur-dispersion ou de sous-dispersion\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\"\n)\n```\n\n### Modèle logistique des cotes proportionnelles {#sec-0823}\n\nLe modèle logistique des cotes proportionnelles (aussi appelé modèle logistique cumulatif) est utilisé pour modéliser une variable qualitative ordinale. Un exemple classique de ce type de variable est une échelle de satisfaction (très insatisfait, insatisfait, mitigé, satisfait, très satisfait) qui peut être recodée avec des valeurs numériques (0, 1, 2, 3, 4; ces échelons étant notés *j*). Il n’existe pas à proprement parler de distribution pour représenter ces données, mais avec une petite astuce, il est possible de simplement utiliser la distribution binomiale. Cette astuce consiste à poser l’hypothèse de la proportionnalité des cotes, soit que le passage de la catégorie 0 à la catégorie 1 est proportionnel au passage de la catégorie 1 à la catégorie 2 et ainsi de suite. Si cette hypothèse est respectée, alors les coefficients du modèle pourront autant décrire le passage de la catégorie *satisfait* à celle *très satisfait* que le passage de *insatisfait* à *mitigé*. Si cette hypothèse n’est pas respectée, il faudrait des coefficients différents pour représenter les passages d’une catégorie à l’autre (ce qui est le cas pour le modèle multinomial présenté dans la [section @sec-0824]).\n\n```{r}\n#| label: tbl-cumuldentity\n#| tbl-cap: Carte d'identité du modèle logistique des cotes proportionnelles\n#| echo: false\n#| message: false\n#| warning: false\nmodel_formula <- \"$Y \\\\sim Binomial(p)$ \\\\newline $g(p \\\\leq j) = \\\\beta_{0j} + \\\\beta X$ \\\\newline $g(x) = log(\\\\frac{x}{1-x})$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable qualitative ordinale avec *j* catégories\", \"Binomiale\", model_formula , \"logistique\", \"p\", \"$\\\\beta$ et *j*-1 constantes $\\\\beta_{0j}$\", \"Non-séparation complète, absence de sur-dispersion ou de sous-dispersion, Proportionnalité des cotes\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\"\n)\n```\n\nAinsi, dans le modèle logistique binomial vu précédemment, nous modélisons la probabilité d’observer un évènement $P(Y = 1)$. Dans un modèle logistique ordinal, nous modélisons la probabilité cumulative d’observer l’échelon *j* de notre variable ordinale $P(Y \\leq j)$. L’intérêt de cette reformulation est que nous conservons la facilité d’interprétation du modèle logistique binomial classique avec les rapports de cotes, à ceci prêt qu’ils représentent maintenant la probabilité de passer à un échelon supérieur de *Y*. La différence pratique est que notre modèle se retrouve avec autant de constantes qu’il y a de catégories à prédire moins une, chacune de ces constantes contrôlant la probabilité de base de passer de la catégorie *j* à la catégorie *j* + 1.\n\n#### Conditions d'application {#sec-08231}\n\nLes conditions d’application sont les mêmes que pour un modèle binomial, avec bien sûr l’ajout de l’hypothèse sur la proportionnalité des cotes. Selon cette hypothèse, l'effet de chaque variable indépendante est identique sur la probabilité de passer d'un échelon de la variable *Y* au suivant. Afin de tester cette condition, deux approches sont envisageables : \n\n1. Utiliser l’approche de Brant [-@brant1990assessing]. Il s’agit d’un test statistique comparant les résultats du modèle ordinal avec ceux d’une série de modèles logistiques binomiaux (1 pour chaque catégorie possible de *Y*).\n\n2. Ajuster un modèle ordinal sans l’hypothèse de proportionnalité des cotes et effectuer un test de ratio des *likelihood* pour vérifier si le premier est significativement mieux ajusté.\n\nSi certaines variables ne respectent pas cette condition d’application, trois options sont possibles pour y remédier : \n\n1. Supprimer la variable du modèle (à éviter si cette variable est importante dans votre cadre théorique).\n\n2. Autoriser la variable à avoir un effet différent entre chaque palier (possible avec le *package* `VGAM`).\n\n3. Changer de modèle et opter pour un modèle des catégories adjacentes. Il s’agit du cas particulier où toutes les variables sont autorisées à changer à chaque niveau. Ne pas confondre ce dernier modèle et le modèle multinomial ([section @sec-0824]), puisque le modèle des catégories adjacentes continue à prédire la probabilité de passer à une catégorie supérieure.\n\n\n#### Exemple appliqué dans R {#sec-08232}\n\nPour cet exemple, nous analysons un jeu de données proposé par [Inside Airbnb](http://insideairbnb.com/get-the-data.html), une organisation sans but lucratif collectant des données des annonces sur le site d’Airbnb pour alimenter le débat sur l’effet de cette société sur les quartiers. Plus spécifiquement, nous utilisons le jeu de données pour Montréal compilé le 30 juin 2020. Nous modélisons ici le prix par nuit des logements, ce type d’exercice est appelé modélisation hédonique. Il est particulièrement utilisé en économie urbaine pour évaluer les déterminants du marché immobilier et prédire son évolution. Le cas d'Airbnb a déjà été étudié dans plusieurs articles [@teubner2017price; @wang2017price; @zhang2017key]. Il en ressort notamment que le niveau de confiance inspiré par l’hôte, les caractéristiques intrinsèques du logement et sa localisation sont les principales variables indépendantes de son prix. Nous construisons donc notre modèle sur cette base. Notez que nous avons décidé de retirer les logements avec des prix supérieurs à 250 \\$ par nuit qui constituent des cas particuliers et qui devraient faire l'objet d'une analyse à part entière. Nous avons également retiré les observations pour lesquelles certaines données sont manquantes, et obtenons un nombre final de 9 051 observations.\n\nLa distribution originale du prix des logements dans notre jeu de données est présentée à la @fig-histopriceairbnb.\n\n```{r}\n#| label: fig-histopriceairbnb\n#| fig-align: center\n#| fig-cap: Distribution des prix des logements Airbnb\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n\n# Charger le jeu de données\ndata_airbnb <- read.csv(\"data/glm/airbnb_data.csv\")\n# Afficher la distribution du prix\nggplot(data = data_airbnb) + \n geom_histogram(aes(x = price), bins = 30, \n color = \"white\", fill = \"#1d3557\", linewidth = 0.02)+\n labs(x = \"Prix (en dollars)\", y = \"Fréquence\")\n```\n\nNous avons ensuite découpé le prix des logements en trois catégories : inférieur à 50 \\$, de 50 \\$ à 99 \\$ et de 100 \\$ à 249 \\$. Ces catégories forment une variable ordinale de trois échelons que nous modélisons à partir de trois catégories de variables : \n\n* les caractéristiques propres au logement;\n* les caractéristiques environnementales autour du logement;\n* les notes obtenues par le logement sur le site d’Airbnb.\n\n\n```{r}\n#| message: false\n#| warning: false\n# Afficher le nombre de logement par catégories\ntable(data_airbnb$fac_price_cat)\n```\n\nLe @tbl-variablecumul présente l’ensemble des variables utilisées dans le modèle.\n\n```{r}\n#| eval: false\n#| include: false\ndf <- data.frame(\n C1 = c(\"Lit\", \"Jardin\", \"Privée\", \"Parking\", \"Accueil\", \"Végétation\", \"Métro\", \"Commercial\", \"Note\", \"Propriétaire\"),\n C2 = c(\"Nombre de lits dans le logement\", \"Présence d’un jardin ou d’une arrière-cour\", \"Le logement est entièrement à disposition du locataire ou seulement une pièce\", \"Une place de stationnement gratuite est disponible sur la rue\", \"L’hôte accueille personnellement les locataires\", \"Végétation dans les environs du logement\", \"Présence d’une station de métro à proximité du logement\", \"Commerce dans les environs du logement\", \"Évaluation de la qualité du logement par les usagers\", \"Nombre total de logements détenus par l’hôte sur Airbnb\"),\n C3 = c(\"Variable de comptage\", \"Variable binaire\", \"Variable binaire\", \"Variable binaire\", \"Variable binaire\", \"Variable continue\", \"Variable binaire\", \"Variable continue\", \"Variable ordinale\", \"Variable de comptage\"),\n C4 = c(\"Nombre de lits dans le logement\", \"Oui ou non\", \"Privé ou partagé\", \"Oui ou non\", \"Oui ou non\", \"Pourcentage de surface végétale dans un rayon de 500 mètres autour du logement\", \"Présence d’une station de métro dans un rayon de 500 mètres autour du logement\", \"Pourcentage de surface dédiée au commerce (mode d’occupation du sol) dans un rayon d'un kilomètre autour du logement\", \"Note obtenue par le logement sur une échelle allant de 1 (très mauvais) à 5 (parfait)\", \"Nombre total de logements détenus par l’hôte sur Airbnb\")\n)\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\tcaption = \"Variables indépendantes utilisées pour prédire la catégorie de prix de logements Airbnb\",\n col.names = c(\"Nom de la variable\" , \"Description\" , \"Type de variable\" , \"Mesure\"),\n align= c(\"l\", \"l\", \"l\", \"l\"),\n col.to.resize = c(2,4),\n col.width = \"5cm\"\n)\n```\n\n```{r}\n#| label: tbl-variablecumul\n#| tbl-cap: Variables indépendantes utilisées pour prédire la catégorie de prix de logements Airbnb\n#| echo: false\n#| message: false\n#| warning: false\ndf <- data.frame(\n C1 = c(\"beds\", \"Garden_or_backyard\", \"private\", \"Free_street_parking\", \"Host_greets_you\", \"prt_veg_500m\", \"has_metro_500m\", \"commercial_1km\", \"cat_review\", \"host_total_listings_count\"),\n C2 = c(\"Nombre de lits dans le logement\", \"Présence d’un jardin ou d’une arrière-cour\", \"Le logement est entièrement à disposition du locataire ou seulement une pièce\", \"Une place de stationnement gratuite est disponible sur la rue\", \"L’hôte accueille personnellement les locataires\", \"Végétation dans les environs du logement\", \"Présence d’une station de métro à proximité du logement\", \"Commerce dans les environs du logement\", \"Évaluation de la qualité du logement par les usagers\", \"Nombre total de logements détenus par l’hôte sur Airbnb\"),\n C3 = c(\"Variable de comptage\", \"Variable binaire\", \"Variable binaire\", \"Variable binaire\", \"Variable binaire\", \"Variable continue\", \"Variable binaire\", \"Variable continue\", \"Variable ordinale\", \"Variable de comptage\"),\n C4 = c(\"Nombre de lits dans le logement\", \"Oui ou non\", \"Privé ou partagé\", \"Oui ou non\", \"Oui ou non\", \"Pourcentage de surface végétale dans un rayon de 500 mètres autour du logement\", \"Présence d’une station de métro dans un rayon de 500 mètres autour du logement\", \"Pourcentage de surface dédiée au commerce (mode d’occupation du sol) dans un rayon d'un kilomètre autour du logement\", \"Note obtenue par le logement sur une échelle allant de 1 (très mauvais) à 5 (parfait)\", \"Nombre total de logements détenus par l’hôte sur Airbnb\")\n)\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Nom de la variable\" , \"Description\" , \"Type de variable\" , \"Mesure\"), \n col.to.resize = c(2,4),\n col.width = \"5cm\",\n align= c(\"l\", \"l\", \"l\", \"l\")\n)\n```\n\n**Vérification des conditions d'application**\n\nAvant d'ajuster le modèle, il convient de vérifier l'absence de multicolinéarité excessive entre les variables indépendantes.\n\n```{r}\n#| message: false\n#| warning: false\n# Notez que la fonction vif ne s'intéresse qu'aux variables indépendantes.\n# Vous pouvez ainsi utiliser la fonction glm avec la fonction vif \n# pour n'importe quel modèle glm\nvif(glm(price ~ beds +\n Garden_or_backyard + Host_greets_you + Free_street_parking + \n prt_veg_500m + has_metro_500m + commercial_1km +host_total_listings_count +\n private + cat_review, data = data_airbnb))\n```\n\nToutes les valeurs de VIF sont inférieures à 2, indiquant une absence de multicolinéarité excessive. Nous pouvons alors ajuster le modèle et analyser les distances de Cook afin de vérifier la présence ou non d'observations très influentes. Pour ajuster le modèle, nous utilisons le *package* `VGAM` et la fonction `vglm` qui nous donnent accès à la famille `cumulative` pour ajuster des modèles logistiques ordinaux. Notez que le fonctionnement de base de cette famille est de modéliser $P(Y\\leq1),P(Y\\leq2),...,P(Y\\leq J)$ avec *J* le nombre de catégories. Cependant, nous voulons ici modéliser la probabilité de passer à une catégorie supérieure de prix. Pour cela, il est nécessaire de spécifier le paramètre `reverse = TRUE` pour la famille `cumulative` (voir `help(cumulative)` pour plus de détails).\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(VGAM)\nmodele <- vglm(fac_price_cat ~ beds +\n Garden_or_backyard + Free_street_parking + \n prt_veg_500m + has_metro_500m + commercial_1km +\n private + cat_review + host_total_listings_count ,\n family = cumulative(link=\"logitlink\", # fonction de lien \n parallel = TRUE, # cote proportionnelle\n reverse = TRUE),\n data = data_airbnb, model = T)\n```\n\nNotez que, puisque la variable *Y* a trois catégories différentes et que nous modélisons la probabilité de passer à une catégorie supérieure, chaque observation a alors deux (3-1) valeurs de résidus différentes. Par conséquent, nous calculons deux distances de Cook différentes que nous devons analyser conjointement. Malheureusement, la fonction `cook.distance` ne fonctionne pas avec les objets `vglm`, nous devons donc les calculer manuellement.\n\n```{r}\n#| label: fig-CookdCotePropor\n#| fig-align: center\n#| fig-cap: Distances de Cook pour le modèle logistique des cotes proportionnelles\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\nlibrary(ggpubr)\n# Extraction des résidus\nres <- residuals(modele, type = \"pearson\")\n# Extraction de la hat matrix (nécessaire pour calculer la distance de Cook)\nhat <- hatvaluesvlm(modele)\n# Calcul des distances de Cook\ncooks <- lapply(1:ncol(res), function(i){\n r <- res[,i]\n h <- hat[,i]\n cook <- (r/(1 - h))^2 * h/(1 * modele@rank)\n})\n# Structuration dans un DataFrame\nmatcook <- data.frame(do.call(cbind, cooks))\nnames(matcook) <- c(\"dist1\" , \"dist2\")\nmatcook$oid <- 1:nrow(matcook)\n# Afficher les distances de Cook\nplot1 <- ggplot(data = matcook) + \n geom_point(aes(x = oid, y = dist1), size = 0.2, color = rgb(0.1,0.1,0.1,0.4)) + \n labs(x = \"\", y = \"\", subtitle = \"distance de Cook P(Y>=2)\")+\n theme(axis.ticks.x = element_blank(),\n axis.text.x = element_blank())\nplot2 <- ggplot(data = matcook) + \n geom_point(aes(x = oid, y = dist2), size = 0.2, color = rgb(0.1,0.1,0.1,0.4)) + \n labs(x = \"\", y = \"\", subtitle = \"distance de Cook P(Y>=3)\")+\n theme(axis.ticks.x = element_blank(),\n axis.text.x = element_blank())\n\nggarrange(plot1, plot2, ncol = 2, nrow = 1)\n```\n\nLes distances de Cook (@fig-CookdCotePropor) nous permettent d'identifier quelques observations potentiellement trop influentes, mais elles semblent être différentes d'un graphique à l'autre. Nous décidons donc de ne pas retirer d'observations à ce stade et de passer à l'analyse des résidus simulés. Pour effectuer des simulations à partir de ce modèle, nous nous basons sur les probabilités d'appartenance prédites par le modèle.\n\n```{r}\n#| message: false\n#| warning: false\n# Extraire les probabilités prédites\npredicted <- predict(modele, type = \"response\")\nround(head(predicted, n = 4),3)\n```\n\nNous constatons ainsi que, pour la première observation, la probabilité prédite d'appartenir au groupe 1 est de 69,4 %, de 27,7 % pour le groupe 2 et de 2,9 % pour le groupe 3. Si nous effectuons 1 000 simulations, nous pouvons nous attendre à ce qu'en moyenne, sur ces 1 000 simulations, 694 indiqueront 1 comme catégorie prédite, 277 indiqueront 2 et seulement 29 indiqueront 3.\n\n```{r}\n#| message: false\n#| warning: false\n# Nous effectuerons 1000 simulations\nnsim <- 1000\n# Lancement des simulations pour chaque observation (lignes dans predicted)\nsimulations <- lapply(1:nrow(predicted), function(i){\n probs <- predicted[i,]\n sims <- sample(c(1,2,3), size = nsim, replace = TRUE, prob = probs)\n return(sims)\n})\n# Combiner les prédictions dans un tableau\nmatsim <- do.call(rbind, simulations)\n# Observons si nos simulations sont proches de ce que nous attendions\ntable(matsim[1,])\n```\n\nÀ partir de ces simulations de prédiction, nous pouvons réaliser un diagnostic des résidus simulés grâce au *package* `DHARMa`.\n\n```{r}\n#| label: fig-diagressimcumul\n#| fig-cap: Diagnostic général des résidus simulés du modèle des cotes proportionnelles\n#| out-width: \"65%\"\n#| fig-align: center\n#| message: false\n#| warning: false\n\nlibrary(DHARMa)\n# Extraction de la prédiction moyenne du modèle\npred_cat <- unique(data_airbnb$fac_price_cat)[max.col(predicted)]\n# Préparer les données avec le package DHARMa\nsim_res <- createDHARMa(simulatedResponse = matsim, \n observedResponse = as.numeric(data_airbnb$fac_price_cat),\n fittedPredictedResponse = as.numeric(pred_cat),\n integerResponse = TRUE)\n# Afficher le graphique de diagnostic général\nplot(sim_res)\n```\n\nLa @fig-diagressimcumul nous indique que les résidus simulés suivent bien une distribution uniforme et qu'aucune valeur aberrante n'est observable. Pour affiner notre diagnostic, nous vérifions également si aucune relation ne semble exister entre chaque variable indépendante et les résidus. \n\n```{r}\n#| eval: false\n# Préparons un plot multiple\npar(mfrow=c(3,4))\nvars <- c(\"nombre de lits\" = \"beds\",\n \"couvert végétal\" = \"prt_veg_500m\", \n \"commercial\" = \"commercial_1km\",\n \"nb logements hôte\" = \"host_total_listings_count\",\n \"jardin\" = \"Garden_or_backyard\",\n \"accueil\" = \"Host_greets_you\",\n \"stationnement gratuit\" = \"Free_street_parking\", \n \"métro\" = \"has_metro_500m\", \n \"logement privé\" = \"private\",\n \"évaluation\" = \"cat_review\")\n\nfor(name in names(vars)){\n v <- vars[[name]]\n plotResiduals(sim_res, data_airbnb[[v]], rank = FALSE, quantreg = FALSE, main = \"\",\n xlab = name, ylab = \"résidus\")\n}\n```\n\n```{r}\n#| label: fig-diagressimcumul2\n#| fig-align: center\n#| fig-cap: Diagnostic des variables indépendantes et des résidus simulés du modèle des cotes proportionnelles\n#| out-width: \"100%\"\n#| echo: false\n#| message: false\n#| warning: false\n\ninvisible(capture.output({\n png(file = \"images/Chap08/diagressimcumul2.png\", res = 300,\n width = 50, height = 35 , units = \"cm\")\n par(mfrow=c(3,4))\n vars <- c(\"nombre de lits\" = \"beds\",\n \"couvert végétal\" = \"prt_veg_500m\", \n \"commercial\" = \"commercial_1km\",\n \"nb logements hôte\" = \"host_total_listings_count\",\n \"jardin\" = \"Garden_or_backyard\",\n \"accueil\" = \"Host_greets_you\",\n \"stationnement gratuit\" = \"Free_street_parking\", \n \"métro\" = \"has_metro_500m\", \n \"logement privé\" = \"private\",\n \"évaluation\" = \"cat_review\")\n \n for(name in names(vars)){\n v <- vars[[name]]\n plotResiduals(sim_res, data_airbnb[[v]], rank = FALSE, quantreg = FALSE, main = \"\",\n xlab = name, ylab = \"résidus\")\n }\n \n dev.off()\n}))\nknitr::include_graphics(\"images/Chap08/diagressimcumul2.png\", dpi = 300)\n\n```\n\nLa fonction `plotResiduals` du *package* `DHARMa` produit des graphiques peu esthétiques, mais pratiques pour effectuer ce type de diagnostic.\n\nLa @fig-diagressimcumul2 indique qu'aucune relation marquée n'existe entre nos variables indépendantes et nos résidus simulés, sauf pour la variable *nombre de lits*. En effet, nous pouvons constater que les résidus ont tendance à être toujours plus faibles quand le nombre de lits augmente. Cet effet est sûrement lié au fait qu'au-delà de cinq lits, le logement en question est vraisemblablement un dortoir. Il pourrait être judicieux de retirer ces observations de l'analyse, considérant qu'elles sont peu nombreuses et constituent un type de logement particulier.\n\n```{r}\n#| message: false\n#| warning: false\ndata_airbnb2 <- subset(data_airbnb, data_airbnb$beds <=5)\nmodele2 <- vglm(fac_price_cat ~ beds + \n Garden_or_backyard + Free_street_parking + \n prt_veg_500m + has_metro_500m + commercial_1km +\n private + cat_review + host_total_listings_count ,\n family = cumulative(link=\"logitlink\", # fonction de lien \n parallel = TRUE, # cote proportionelle\n reverse = TRUE),\n data = data_airbnb2, model = T)\n```\n\nNous pouvons ensuite recalculer les résidus simulés pour observer si cette tendance a été corrigée. La @fig-diagressimcumul3 montre qu'une bonne partie du problème a été corrigée; cependant, il semble tout de même que les résidus soient plus forts pour les logements avec un seul lit.\n\n```{r}\n#| message: false\n#| warning: false\n# Nous effectuerons 1000 simulations\nnsim <- 1000\npredicted <- predict(modele2, type = \"response\")\n# Lancement des simulations pour chaque observation (lignes dans predicted)\nsimulations <- lapply(1:nrow(predicted), function(i){\n probs <- predicted[i,]\n sims <- sample(c(1,2,3), size = nsim, replace = TRUE, prob = probs)\n return(sims)\n})\n# Combiner les prédictions dans un tableau\nmatsim <- do.call(rbind, simulations)\n# Extraction de la prédiction moyenne du modèle\npred_cat <- unique(data_airbnb2$fac_price_cat)[max.col(predicted)]\n# Préparer les donnees avec le package DHARMa\nsim_res <- createDHARMa(simulatedResponse = matsim, \n observedResponse = as.numeric(data_airbnb2$fac_price_cat),\n fittedPredictedResponse = as.numeric(pred_cat),\n integerResponse = TRUE)\n```\n```{r}\n#| eval: false\npar(mfrow=c(3,4))\nvars <- c(\"nombre de lits\" = \"beds\",\n \"couvert végétal\" = \"prt_veg_500m\", \n \"commercial\" = \"commercial_1km\",\n \"nb logements hôte\" = \"host_total_listings_count\",\n \"jardin\" = \"Garden_or_backyard\",\n \"accueil\" = \"Host_greets_you\",\n \"stationnement gratuit\" = \"Free_street_parking\", \n \"métro\" = \"has_metro_500m\", \n \"logement privé\" = \"private\",\n \"évaluation\" = \"cat_review\")\n\nfor(name in names(vars)){\n v <- vars[[name]]\n plotResiduals(sim_res, data_airbnb2[[v]], rank = FALSE, quantreg = FALSE, main = \"\",\n xlab = name, ylab = \"résidus\")\n}\n```\n```{r}\n#| label: fig-diagressimcumul3\n#| echo: false\n#| fig-align: center\n#| fig-cap: Diagnostic des variables indépendantes et des résidus simulés du modèle des cotes proportionnelles (après correction)\n#| out-width: \"100%\"\n#| message: false\n#| warning: false\n\ninvisible(capture.output({\nout <- \"images/Chap08/diagressimcumul3.png\"\n\n png(filename = out,\n res = 300, width = 50, height = 35, units = \"cm\")\n \n par(mfrow=c(3,4))\n vars <- c(\"nombre de lits\" = \"beds\",\n \"couvert végétal\" = \"prt_veg_500m\", \n \"commercial\" = \"commercial_1km\",\n \"nb logements hôte\" = \"host_total_listings_count\",\n \"jardin\" = \"Garden_or_backyard\",\n \"accueil\" = \"Host_greets_you\",\n \"stationnement gratuit\" = \"Free_street_parking\", \n \"métro\" = \"has_metro_500m\", \n \"logement privé\" = \"private\",\n \"évaluation\" = \"cat_review\")\n \n for(name in names(vars)){\n v <- vars[[name]]\n plotResiduals(sim_res, data_airbnb2[[v]], rank = FALSE, quantreg = FALSE, main = \"\",\n xlab = name, ylab = \"résidus\")\n }\n dev.off()\n \n}))\nknitr::include_graphics(out, dpi = 300)\n```\n\nLa prochaine étape du diagnostic est de vérifier l'absence de séparation parfaite provoquée par une de nos variables indépendantes. Le *package* `VGAM` propose pour cela la fonction `hdeff`.\n\n```{r}\n#| message: false\n#| warning: false\ntests <- hdeff(modele2)\nproblem <- table(tests)\nproblem\n```\n\nLa fonction nous informe qu'aucune de nos variables indépendantes ne provoque de séparation parfaite : toutes les valeurs renvoyées par la fonction `hdeff` sont égales à `FALSE.`\n\nIl ne nous reste donc plus qu'à vérifier que l'hypothèse de proportionnalité des cotes est respectée, soit que l'effet de chacune des variables indépendantes est bien le même pour passer de la catégorie 1 à 2 que pour passer de la catégorie 2 à 3. Pour cela, deux approches sont possibles : le test de Brant ou la réalisation d'une séquence de tests de rapport de vraisemblance.\n\nLe *package* `brant` propose une implémentation du test de Brant, mais celle-ci ne peut être appliquée qu'à des modèles construits avec la fonction `polr` du *package* `MASS`. Nous avons donc récupéré le code source de la fonction `brant` du *package* `brant` et apporté quelques modifications pour qu'elle soit utilisable sur un objet `vglm`. Cette nouvelle fonction, appelée `brant.vglm`, est disponible dans le code source de ce livre.\n\n```{r}\n#| message: false\n#| warning: false\ntableau_brant <- round(brant.vglm(modele2), 3)\n```\n\nCe premier tableau nous indique que seule la variable indiquant si le logement est disponible en entier ou partagé contrevient à l'hypothèse de proportionnalité des cotes (la seule valeur *p* significative). Pour confirmer cette observation, nous pouvons réaliser un ensemble de tests de rapport de vraisemblance. Pour chaque variable du modèle, nous créons un second modèle dans lequel cette variable est autorisée à varier pour chaque catégorie et nous comparons les niveaux d'ajustement des modèles. Nous avons implémenté cette procédure dans la fonction `parallel.likelihoodtest.vglm` disponible dans le code source de ce livre.\n\n```{r}\n#| message: false\n#| warning: false\ntableau_likelihood <- parallel.likelihoodtest.vglm(modele2, verbose = FALSE)\nprint(tableau_likelihood)\n```\n\nLes résultats de cette seconde série de tests confirment les précédents, la variable concernant le type de logement doit être autorisée à varier en fonction de la catégorie. Ce second tableau nous indique que la variable concernant la densité de végétation pourrait aussi être amenée à varier en fonction du groupe, mais ce changement a un effet très marginal (différence entre les valeurs d'AIC de seulement 8 points). Nous ajustons donc un nouveau modèle autorisant la variable `private` à changer en fonction de la catégorie prédite.\n\n```{r}\n#| message: false\n#| warning: false\nmodele3 <- vglm(fac_price_cat ~ beds + \n Garden_or_backyard + Host_greets_you + Free_street_parking + \n prt_veg_500m + has_metro_500m + commercial_1km +\n private + cat_review + host_total_listings_count,\n family = cumulative(link=\"logitlink\",\n parallel = FALSE ~ private ,\n reverse = TRUE),\n data = data_airbnb2, model = T)\n```\n\n**Vérification l'ajustement du modèle**\n\nMaintenant que toutes les conditions d'application ont été passées en revue, nous pouvons passer à la vérification de l'ajustement du modèle.\n\n```{r}\n#| message: false\n#| warning: false\nmodelenull <- vglm(fac_price_cat ~ 1,\n family = cumulative(link=\"logitlink\",\n parallel = TRUE,\n reverse = TRUE),\n data = data_airbnb2, model = T)\nrsqs(loglike.full = logLik(modele3),\n loglike.null = logLik(modelenull),\n full.deviance = deviance(modele3),\n null.deviance = deviance(modelenull),\n nb.params = modele3@rank,\n n = nrow(data_airbnb2)\n)\n```\n\nLe modèle final parvient à expliquer 21 % de la déviance originale. Il obtient un R^2^ ajusté de McFadden de 0,21, et des R^2^ de Cox et Snell et de Nagelkerke de respectivement 0,36 et 0,41. Construisons à présent la matrice de confusion de la prédiction du modèle (nous utilisons ici la fonction `nice_confusion_matrix` également disponible dans le code source de ce livre).\n\n```{r}\n#| message: false\n#| warning: false\npreds_probs <- fitted(modele3)\npred_cat <- c(1,2,3)[max.col(preds_probs)]\nlibrary(caret)\nmatrices <- nice_confusion_matrix(data_airbnb2$fac_price_cat, pred_cat)\n# Afficher la matrice de confusion\nprint(matrices$confusion_matrix)\n# Afficher les indicateurs de qualité de prédiction\nprint(matrices$indicators)\n```\n\nLe modèle a une précision totale de 61 % (61 % des observations ont été correctement prédites). La catégorie 1 a de loin la meilleure précision (72 %) et la 3 a la pire (48 %), ce qui indique qu’il manque vraisemblablement des variables indépendantes contribuant à prédire les prix des logements les plus chers. Le coefficient de Kappa (0,37) indique un niveau d’accord entre modéré et faible, mais le modèle parvient à une prédiction significativement supérieure au seuil de non-information. Si l'ajustement du modèle est imparfait, il est suffisamment fiable pour nous donner des renseignements pertinents sur le phénomène étudié.\n\n**Interprétation des résultats**\n\nL'ensemble des coefficients du modèle sont accessibles via la fonction `summary`. À partir des coefficients et de leurs erreurs standards, il est possible de calculer les rapports de cotes ainsi que leurs intervalles de confiance.\n\n```{r}\n#| message: false\n#| warning: false\ntableau <- summary(modele3)@coef3\nrappCote <- exp(tableau[,1])\nrappCote2.5 <- exp(tableau[,1] - 1.96 * tableau[,2])\nrappCote97.5 <- exp(tableau[,1] + 1.96 * tableau[,2])\ntableau <- cbind(tableau, rappCote, rappCote2.5, rappCote97.5)\nprint(round(tableau,3))\n```\n\nPour faciliter la lecture des résultats, nous proposons le @tbl-FinalOrdinale.\n\n```{r}\n#| label: tbl-FinalOrdinale\n#| tbl-cap: Coefficients du modèle logistique des cotes proportionnelles\n#| message: false\n#| warning: false\n#| echo: false\ntableau <- build_table(modele3, confid = TRUE, sign = TRUE, coef_digits = 2, std_digits = 3, z_digits = 2, p_digits = 3, OR_digits = 2)\ntab <- tableau[, c(1,2,3,6,9,10,11)]\nknitr::kable(tab,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t col.names = c(\"Variable\", \"Coefficient\", \"RC\", \"P\", \"RC 2,5 %\", \"RC 97,5 %\", \"sign.\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\"),\n )\n```\n\nSans surprise, chaque lit supplémentaire contribue à augmenter les chances que le logement soit dans une catégorie de prix supérieure (multiplication par deux à chaque lit supplémentaire). En revanche, la présence d’un stationnement gratuit, d'un jardin et l’accueil en personne par l’hôte n’ont pas d’effets significatifs. Comme l'indiquent les articles mentionnés en début de section, les revues positives augmentent la probabilité d'appartenir à une catégorie supérieure de prix. Pour chaque point supplémentaire sur l'échelle de 1 à 5, la probabilité d'appartenir à une catégorie de prix supérieure augmente de 22,2 %. Il est intéressant de noter que le fait de disposer du logement entier plutôt que d'une simple chambre augmente davantage les chances de passer du groupe de prix 1 à 2 (multiplication par 2,45) que du groupe 2 à 3 (multiplication par 1,58). Il semble également que si l’hôte possède plusieurs logements, la probabilité d’avoir une classe de prix supérieure diminue légèrement. Cependant, l’effet est trop petit pour pouvoir se livrer à des interprétations.\n\nLes variables environnementales ont peu d’effet : le pourcentage de surface commerciale dans un rayon d’un kilomètre et la présence d’une station de métro ne sont pas significatifs. En revanche, une augmentation de la surface végétale dans un rayon de 500 mètres tend à réduire la probabilité d’appartenir à une classe supérieure. Notre hypothèse concernant ce résultat est que cette variable représente un effet associé à la localisation des Airbnb, les plus centraux ayant tendance à être plus dispendieux, mais avec un environnement moins vert et inversement. Pour l’illustrer, prédisons les probabilités d’appartenance aux différents niveaux de prix d’un logement avec les caractéristiques suivantes : entièrement privé, 2 lits, un jardin, une place de stationnement gratuite, l’hôte ne dispose que d’un logement sur Airbnb et accueille les arrivants en personne, 10 % de surface commerciale dans un rayon d'un kilomètre, noté 2 comme catégorie de revue, absence de métro dans un rayon de 500 mètres.\n\n```{r}\n#| label: fig-predpricecatveg\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n#| fig-align: center\n#| fig-cap: Prédiction de la probabilité d'appartenance aux trois catégories de prix en fonction de la densité de végétation\n# Créer un jeu de données pour effectuer des prédictions\ndf <- data.frame(\n prt_veg_500m = seq(5,90),\n beds = 2, \n Garden_or_backyard = \"YES\",\n Host_greets_you = \"YES\",\n Free_street_parking = \"YES\",\n has_metro_500m = \"NO\",\n commercial_1km = 10,\n private = \"Entier\",\n cat_review = 2,\n host_total_listings_count = 1\n)\n# Effectuer les prédictions (dans l'échelle log)\npreds <- predict(modele3, newdata = df, type = \"link\", se.fit=T)\n# Définir l'inverse de la fonction de lien\nilink <- function(x){exp(x)/(1+exp(x))}\n# Calculer les probabilités et leurs intervalles de confiance\ndf[[\"P[Y>=2]\"]] <- ilink(preds$fitted.values[,1])\ndf[[\"P[Y>=2] 2,5\"]] <- ilink(preds$fitted.values[,1] - 1.96 * preds$se.fit[,1])\ndf[[\"P[Y>=2] 97,5\"]] <- ilink(preds$fitted.values[,1] + 1.96 * preds$se.fit[,1])\ndf[[\"P[Y>=3]\"]] <- ilink(preds$fitted.values[,2])\ndf[[\"P[Y>=3] 2,5\"]] <- ilink(preds$fitted.values[,2] - 1.96 * preds$se.fit[,2])\ndf[[\"P[Y>=3] 97,5\"]] <- ilink(preds$fitted.values[,2] + 1.96 * preds$se.fit[,2])\ndf[[\"P[Y=1]\"]] = 1-df[[\"P[Y>=2]\"]]\ndf[[\"P[Y=1] 2,5\" ]] = 1-df[[\"P[Y>=2] 2,5\"]]\ndf[[\"P[Y=1] 97,5\"]] = 1-df[[\"P[Y>=2] 97,5\"]]\n# Afficher les résultats\nggplot(data = df) + \n geom_ribbon(aes(x = prt_veg_500m, \n ymin = `P[Y>=2] 2,5`,\n ymax = `P[Y>=2] 97,5`), fill = \"#f94144\", alpha = 0.4)+\n geom_path(aes(x = prt_veg_500m, y = `P[Y>=2]`, color = \"Y2\")) + \n geom_ribbon(aes(x = prt_veg_500m, \n ymin = `P[Y>=3] 2,5`,\n ymax = `P[Y>=3] 97,5`), fill = \"#90be6d\", alpha = 0.4)+\n geom_path(aes(x = prt_veg_500m, y = `P[Y>=3]`, color = \"Y3\" )) + \n geom_ribbon(aes(x = prt_veg_500m, \n ymin = `P[Y=1] 2,5`,\n ymax = `P[Y=1] 97,5`), fill = \"#277da1\" , alpha = 0.4)+\n geom_path(aes(x = prt_veg_500m, y = `P[Y=1]`, color = \"Y1\")) + \n scale_color_manual(name = \"Probabilités prédites\",\n breaks = c(\"Y1\", \"Y2\", \"Y3\"),\n labels = c(\"P[Y=1]\", \"P[Y>=2]\", \"P[Y>=3]\"),\n values = c(\"Y2\" = \"#f94144\", \"Y3\" = \"#90be6d\",\n \"Y1\" = \"#277da1\")) + \n labs(x = \"Densité de végétation (%)\",\n y = \"Probabilité\",\n subtitle = \"Y1 : moins de 50 $; Y2 : 50 à 99 $; Y3 : 100 à 249 $\")\n \n```\n\nNous constatons, à la @fig-predpricecatveg, que les probabilités d’appartenir aux niveaux 2 et 3 diminuent à mesure qu’augmente le pourcentage de végétation. La probabilité d’appartenir à la classe 2 et plus (en rouge) passe de plus de 95 % en cas d’absence de végétation et à environ 75 % avec 80 % de végétation dans un rayon de 500 mètres. Comme vous pouvez le constater, la probabilité $P[Y=1]$ est la symétrie de $P[Y>=2]$ puisque $P[Y=1]+P[Y>=2] = 1$.\n\n### Modèle logistique multinomial {#sec-0824}\n\nLa régression logistique multinomiale est utilisée pour modéliser une variable *Y* qualitative multinomiale, c’est-à-dire une variable dont les modalités ne peuvent pas être ordonnées. Dans le modèle précédent, nous avons vu qu’il était possible de modéliser une variable ordinale avec une distribution binomiale en formulant l’hypothèse de la proportionnalité des cotes. Avec une variable multinomiale, cette hypothèse ne tient plus, car les catégories ne sont plus ordonnées. Il faut donc formuler le modèle différemment.\n\nL’idée derrière un modèle multinomial est de choisir une catégorie de référence, puis de modéliser les probabilités d’appartenir à chaque autre catégorie plutôt qu’à cette catégorie de référence (@tbl-multinomdentity). Si nous avons *K* catégories possibles dans notre variable *Y*, nous obtenons *K*-1 comparaisons. Chaque comparaison est modélisée avec sa propre équation, ce qui génère de nombreux paramètres. Par exemple, admettons que notre variable *Y* a cinq catégories et que nous disposons de six variables *X* prédictives. Nous avons ainsi 4 (5-1) équations de régression avec 7 paramètres (6 coefficients et une constante), soit 28 coefficients à analyser. \n\nConsidérant cette tendance à la multiplication des coefficients, il est fréquent de recourir à une méthode appelée *Analyse de type 3* pour limiter au maximum le nombre de variables indépendantes (VI) dans le modèle. L'idée de cette méthode est de recalculer plusieurs versions du modèle dans lesquelles une variable indépendante est retirée, puis de réaliser un test de rapport de vraisemblance en comparant ce nouveau modèle (complet moins une VI) au modèle complet (toutes les VI) pour vérifier si la variable en question améliore significativement le modèle. Il est alors possible de retirer toutes les variables dont l'apport est négligeable si elles sont également peu intéressantes du point de vue théorique.\n\n```{r}\n#| label: tbl-multinomdentity\n#| tbl-cap: Carte d'identité du modèle logistique multinomial\n#| echo: false\n#| message: false\n#| warning: false\nmodel_formula <- \"$Y \\\\sim Binomial(p)$ \\\\newline $g(p = k\\\\text{ avec }ref = a) = \\\\beta_{0k} + \\\\beta X_{k}$ \\\\newline $g(x) = \\\\frac{log(x)}{1-x}$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable qualitative multinomiale avec *K* catégories\", \"Binomiale\", model_formula , \"Logistique\", \"p\", \"$\\\\beta_{0k}$, $\\\\beta$k pour $k \\\\in [2,...,K]$\", \"Non-séparation complète, absence de sur-dispersion ou de sous-dispersion, Indépendance des alternatives non pertinentes\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\"\n)\n```\n\n#### Conditions d'application {#sec-08241}\n\nLes conditions d’application sont les mêmes que pour un modèle binomial, avec l’ajout de l’hypothèse sur **l’indépendance des alternatives non pertinentes**. Cette dernière suppose que le choix entre deux catégories est indépendant des catégories proposées. Voici un exemple simple pour illustrer cette hypothèse: admettons que nous disposons d’une trentaine de personnes et que nous leur demandons la couleur de leurs yeux. Cette variable ne serait pas affectée par la présence de nouvelles couleurs en dehors de notre échantillon. En revanche, si nous leur demandons de choisir un mode de transport parmi une liste pour se rendre à leur lieu de travail, leur réponse serait nécessairement affectée par la liste des modes de transport disponibles. Les tests développés pour vérifier cette hypothèse sont connus pour leur [faible fiabilité](https://statisticalhorizons.com/iia). Il est plus pertinent de décider théoriquement si cette hypothèse est valide ou non. Dans le cas contraire, il est possible d’utiliser une classe de modèle logistique plus rare: le modèle logistique imbriqué. \n\nNotez également que le grand nombre de paramètres dans ce type de modèle implique de disposer d’un plus grand nombre d’observations afin d'avoir suffisamment d’information dans chaque catégorie pour ajuster tous les paramètres.\n\nPour vérifier la présence de sur-dispersion, il est possible, dans le cas du modèle multinomial, de calculer le rapport entre le khi-deux de Pearson et le nombre de degrés de liberté du modèle. Si ce rapport est supérieur à 1 (des valeurs jusqu'à 1,15 ne sont pas problématiques), alors le modèle souffre de sur-dispersion [@Sasmultinom]. Le khi-deux de Pearson est simplement la somme des résidus de Pearson au carré dans le cas d'un modèle GLM.\n\n$$\n\\chi^2 = \\sum_{i=1}^N\\sum_{c=1}^K{\\frac{(y_{ic} - p_{ic})^2}{p_{ic}}}\n$$ {#eq-glm15}\n\nAvec $y_{ic}$ 1 si l'observation *i* appartient à la catégorie *c*, 0 autrement, $p_{ic}$ la probabilité prédite pour l'observation *i* d'appartenir à la catégorie *c*, *N* le nombre d'observations et *K* le nombre de catégories.\n\nLe ratio est ensuite calculé comme suit: $\\frac{\\chi^2}{(N - p)(K-1)}$, avec *N* le nombre d'observations et *K* le nombre de modalités dans la variable *Y*. Si ce ratio est égal ou supérieur à 1, alors le modèle souffre de sur-dispersion, si le ratio est inférieur à 1, le modèle souffre de sous-dispersion. Un léger écart (> 0,15) n'est pas considéré comme problématique. \n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Le modèle logistique imbriqué**\n:::\n::: bloc_aller_loin-body\nDu fait de sa proximité avec les modèles à effets mixtes que nous abordons au [chapitre @sec-chap09], nous ne détaillons pas ici le modèle logistique imbriqué, mais présentons plutôt son principe général. Il s’agit d’une généralisation du modèle logistique multinomial basé sur l’idée que certaines catégories pourraient être regroupées dans des « nids » (*nest* en anglais). Dans ces groupes, les erreurs peuvent être corrélées, indiquant ainsi que si une catégorie est manquante, une autre catégorie du même groupe sera préférée. Un paramètre $\\lambda$ contrôle spécifiquement cette corrélation et permet de mesurer sa force une fois le modèle ajusté. Il peut être pertinent de comparer un modèle imbriqué à un modèle multinomial pour déterminer lequel des deux est le mieux ajusté aux données.\n:::\n:::\n\n#### Exemple appliqué dans R {#sec-08242}\n\nPour cet exemple, nous reproduisons une partie de l'analyse effectuée dans l'étude de @mcfadden2016examining. Cet article s'intéresse aux écarts entre les croyances des individus et les connaissances scientifiques sur les sujets des OGM et du réchauffement climatique. Les auteurs utilisent pour cela des données issues d'une enquête auprès de 961 individus formant un échantillon représentatif de la population des États-Unis. Les données issues de cette enquête sont téléchargeables sur le [site de l'éditeur](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0166140), ce qui nous permet ici de reproduire l'analyse effectuée par les auteurs. Deux questions sont centrales dans l'enquête : \n\n* Dans quelle mesure êtes-vous en accord ou en désaccord avec la phrase suivante : les plantations génétiquement modifiées sont sans danger pour la consommation ?\n* Dans quelle mesure êtes-vous en accord ou en désaccord avec la phrase suivante : la Terre se réchauffe du fait des activités humaines ?\n\nPour ces deux questions, les répondants devaient sélectionner leur degré d'accord sur une échelle de Likert allant de 1 (fortement en désaccord) à 5 (fortement en accord). Les réponses à ces deux questions ont été utilisées pour former une variable multinomiale à quatre modalités :\n\n* A. Les individus sont en accord avec les deux propositions.\n* B. Les individus sont en désaccord sur les OGM, mais en accord sur le réchauffement climatique.\n* C. Les individus sont en accord sur les OGM, mais en désaccord sur le réchauffement climatique.\n* D. Les individus sont en désaccord avec les deux propositions.\n\nUn modèle logistique multinomial a été utilisé pour déterminer quels facteurs contribuent à la probabilité d'appartenir à ces différentes catégories. Les variables indépendantes présentes dans le modèle sont détaillées dans le @tbl-variablemultinom. Les auteurs avaient notamment conclu que : \n\n* Les effets des connaissances (réelles ou perçues) sur l'appartenance aux différentes catégories n'étaient pas uniformes et pouvaient varier en fonction du sujet.\n\n* L'orientation politique avait une influence significative sur les croyances.\n\n* Les répondants avec de plus hauts résultats au test de cognition CRT avaient plus souvent des opinions divergentes de la communauté scientifique.\n\n```{r}\n#| label: tbl-variablemultinom\n#| tbl-cap: Variables indépendantes utilisées dans le modèle logistique multinomial\n#| echo: false\n#| message: false\n#| warning: false\ndf <- data.frame(\n C1 = c(\"PercepOGM\", \"PercepRechClim\", \"ConnaisOGM\", \"ConnaisRechClim\", \"CRT\", \"Parti\", \"Sexe\", \"Age\", \"Revenu\"),\n C2 = c(\"La recherche scientifique supporte ma vision sur la sécurité des plantes OGM\", \"La recherche scientifique supporte ma vision sur le réchauffement climatique\", \"Niveau de connaissance sur les OGM\", \"Niveau de connaissance sur le réchauffement climatique\", \"Score obtenu au Cognitive Reflection Test, utilisé pour déterminer la propension à faire preuve d’esprit d’analyse plutôt que choisir des réponses intuitives\", \"Orientation politique du répondant\", \"Sexe du répondant\", \"Âge du répondant\", \"Niveau de revenu du répondant\"),\n C3 = c(\"Variable ordinale\", \"Variable ordinale\", \"Variable ordinale\", \"Variable ordinale\", \"Variable ordinale\", \"Variable multinomiale\", \"Variable binaire\", \"Variable continue\", \"Variable ordinale\"),\n C4 = c(\"Échelle de Likert de 1 (fortement en désaccord) à 5 (fortement en accord)\", \"Échelle de Likert de 1 (fortement en désaccord) à 5 (fortement en accord)\", \"Nombre de réponses sur trois questions portant sur les OGM\", \"Nombre de réponses sur trois questions portant sur le réchauffement climatique\", \"Nombre de réponses sur trois questions pièges\", \"Républicain, démocrate et autre\", \"Femme ou homme\", \"Âge du répondant\", \"Échelle de 1 (moins de 20 000 $) à (140 000 $ et plus)\")\n)\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Nom de la variable\" , \"signification\" , \"Type de variable\" , \"Mesure\"), \n align= c(\"l\", \"l\", \"l\", \"l\"),\n col.to.resize = c(2,4),\n col.width = \"5cm\"\n)\n```\n\n**Vérification des conditions d'application**\n\nAvant d'ajuster le modèle, nous commençons par vérifier l'absence de multicolinéarité excessive entre les variables indépendantes. Toutes les valeurs de VIF sont inférieures à 2, indiquant bien une absence de multicolinéarité.\n\n```{r}\n#| label: vifmultinom\n#| message: false\n#| warning: false\ndata_quest <- read.csv(\"data/glm/enquete_PublicOpinion_vs_Science.csv\")\n# Choix des valeurs de références dans les facteurs\ndata_quest$Parti <- relevel(as.factor(data_quest$Parti), ref = \"Democrate\")\ndata_quest$Sexe <- relevel(as.factor(data_quest$Sexe), ref = \"homme\")\nvif(glm(SCIGM ~ PercepOGM + PercepRechClim + ConnaisOGM + ConnaisRechClim +\n CRT + Parti + AGE + Sexe + Revenu, data = data_quest))\n```\n\nLa seconde étape est d'ajuster le modèle et de vérifier l'absence de sur ou sous-dispersion. Pour ajuster le modèle, nous utilisons à nouveau la fonction `vglm` du *package* `VGAM`, avec le paramètre `family = multinomial()`. Le ratio entre la statistique de Pearson et le nombre de degrés de liberté du modèle indique une absence de sur ou sous-dispersion (1,04).\n\n\n```{r}\n#| message: false\n#| warning: false\n# Ajustement du modèle\nmodele <- vglm(Y ~ PercepOGM + PercepRechClim + ConnaisOGM + ConnaisRechClim + \n CRT + Parti + AGE + Sexe + Revenu,\n data = data_quest, \n family = multinomial(refLevel = \"A\"), model = T)\n# Calcul du Khi2 de Pearson\npred <- predict(modele, type= \"response\")\ncat_predict <- colnames(pred)[max.col(pred)]\nfreq_real <- table(data_quest$Y)\nfreq_pred <- table(cat_predict)\n\nkhi2 <- sum(residuals(modele, type = \"pearson\")^2)\n\nN <- nrow(data_quest)\np <- modele@rank\nr <- length(freq_real)\nratio <- khi2 / ((N-p)*(r-1))\nprint(ratio)\n```\n\nLa troisième étape de la vérification des conditions d'application est l'analyse des distances de Cook. À nouveau, puisque le modèle évalue la probabilité d'appartenir à $K-1$ catégorie, nous pouvons calculer $K-1$ résidus par observation et par extension $K-1$ distances de Cook. Aucune observation ne semble se détacher nettement dans la @fig-cookmultinom. Nous décidons donc pour le moment de conserver toutes les observations.\n\n```{r}\n#| label: fig-cookmultinom\n#| fig-align: center\n#| fig-cap: Distances de Cook pour le modèle logistique multinomial\n#| message: false\n#| warning: false\n#| out-width: \"90%\"\n\n# Extraction des résidus\nres <- residuals(modele, type = \"pearson\")\n# Extraction de la hat matrix (nécessaire pour calculer la distance de Cook)\nhat <- hatvaluesvlm(modele)\n# Calcul des distances de Cook\nvals <- c(\"A\" , \"B\" , \"C\" , \"D\")\ncooks <- lapply(1:ncol(res), function(i){\n r <- res[,i]\n h <- hat[,i]\n cook <- (r/(1 - h))^2 * h/(1 * modele@rank)\n df <- data.frame(\n oid = 1:length(cook),\n cook = cook\n )\n plot <- ggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.2, color = rgb(0.1,0.1,0.1,0.4)) + \n labs(x = \"\", y = \"\", subtitle = paste(\"distance de Cook P(\",vals[[1]],\" VS \",vals[[i+1]],\")\", sep = \"\"))+\n theme(axis.ticks.x = element_blank(),\n axis.text.x = element_blank())\n return(plot)\n})\nggarrange(plotlist = cooks, ncol = 2, nrow = 2)\n```\n\nAvant de passer à l'analyse de résidus simulés, il est pertinent de réaliser une analyse de type 3 afin de retirer les variables indépendantes dont l'apport au modèle est négligeable. La fonction `AnalyseType3` (disponible dans le code source de ce livre) permet d'effectuer cette opération automatiquement pour un objet de type `vglm`.\n\n```{r}\n#| message: false\n#| warning: false\ntableau <- AnalyseType3(modele, data_quest, verbose = FALSE)\n```\n\nL'analyse de type 3 nous permet de déterminer que l'âge et le revenu sont deux variables dont la contribution au modèle est marginale. À titre de rappel, l’analyse de type 3 permet de comparer si le modèle complet (avec l’ensemble des variables indépendantes) est statistiquement mieux ajusté que le modèle avec l’ensemble des variables, sauf une. Or, dans notre cas, le modèle complet n’est pas statistiquement mieux ajusté que le modèle complet sans la variable *Age* (*p* = 0,44) et que le modèle complet sans la variable Revenu (*p* = 0,77). Cela signifie donc que ces deux variables n’ont pas un apport significatif au modèle et peuvent par conséquent être ôtées par parcimonie. Nous décidons donc de les retirer afin d'alléger les tableaux de coefficients que nous présentons plus loin. Nous pouvons également en conclure que ces deux variables ne jouent aucun rôle dans la propension à être en désaccord avec la recherche scientifique. Nous réajustons le modèle en conséquence.\n\n```{r}\n#| message: false\n#| warning: false\nmodele2 <- vglm(Y ~ PercepOGM + PercepRechClim + ConnaisOGM + ConnaisRechClim + \n CRT + Parti + Sexe,\n data = data_quest, \n family = multinomial(refLevel = \"A\"), model = T)\n```\n\nNous pouvons à présent passer à l'analyse des résidus simulés. Le problème avec ce modèle est que sa variable *Y* est qualitative alors que la méthode d'analyse des résidus du *package* `DHARMa` ne peut traiter que des variables quantitatives, binaires ou ordinales. Pour rappel, il est possible d'envisager la prédiction d'un modèle logistique multinomial comme la prédiction d'une série de modèles logistiques binomiaux. En représentant nos prédictions de cette façon, nous pouvons à nouveau utiliser le *package* `DHARMa` pour analyser nos résidus. Veuillez noter que cette approche n'est pas optimale et que cette section du livre peut être amenée à changer.\n\nLa @fig-residusmultinom indique que les résidus suivent bien une distribution uniforme et qu'aucune valeur aberrante n'est observable.\n\n```{r}\n#| label: fig-residusmultinom\n#| fig-align: center\n#| fig-cap: Diagnostic général des résidus simulés pour le modèle multinomial\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n# Extraire les prédictions du modèle\ncategories <- c(\"B\" , \"C\" , \"D\")\npredicted <- predict(modele2, type = \"link\")\nnsim <- 1000\nilink <- function(x){exp(x)/(1+exp(x))}\n# Boucler sur chacune des catégories en dehors de la référence\ndata_sims <- lapply(1:ncol(predicted), function(i){\n categorie <- categories[[i]]\n # Extraire les observation de la catégorie i et de la référence\n test <- data_quest$Y %in% c(\"A\", categorie)\n # Calculer les probabilité d'appartenance à i\n values <- predicted[test,i]\n probs <- ilink(values)\n # Extraire les valeurs réelles et les convertir en 0 / 1\n real <- data_quest[test,]$Y\n real <- ifelse(real==\"A\",0,1)\n # Enregistrer ces différents éléments\n all_probs <- cbind(1-probs, probs)\n sub_data <- subset(data_quest, test)\n return(list(\"real\" = real, \"probs\" = all_probs, \"data\" = sub_data))\n})\n# Extraire les probabilités prédites\nall_probs <- do.call(rbind, lapply(data_sims, function(i){i$probs}))\n# Extraire les vrais catégories\nall_real <- unlist(lapply(data_sims, function(i){i$real}))\n# Effectuer les simulations\nsimulations <- lapply(1:nrow(all_probs), function(i){\n probs <- all_probs[i,]\n sims <- sample(c(0,1), size = nsim, replace = TRUE, prob = probs)\n return(sims)\n})\nmatsim <- do.call(rbind, simulations)\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = matsim, \n observedResponse = all_real,\n fittedPredictedResponse = all_probs[,2],\n integerResponse = TRUE)\n# Afficher les résultats\nplot(sim_res)\n```\n\nLa @fig-residusmultinom2 permet d'affiner le diagnostic en s'assurant de l'absence de relation entre les variables indépendantes et les résidus. Il est possible de remarquer des irrégularités pour les variables de perception (premier et second panneaux). Dans les deux cas, la catégorie 1 (fort désaccord) se démarque nettement des autres catégories. Nous proposons donc de les recoder comme des variables binaires : en désaccord / pas en désaccord pour minimiser cet effet.\n\n```{r}\n#| eval: false\n# Recomposer les données pour coller au format\n# étendu de la prediction\netend_data <- do.call(rbind, lapply(data_sims, function(i){i$data}))\npar(mfrow=c(3,3))\nvars <- c(\"PercepOGM\", \"PercepRechClim\", \"ConnaisOGM\", \n \"ConnaisRechClim\", \"CRT\", \"Parti\", \"Sexe\")\nfor(v in vars){\n plotResiduals(sim_res, etend_data[[v]], xlab= v, ylab = \"résidus\")\n}\n```\n\n\n```{r}\n#| label: fig-residusmultinom2\n#| fig-align: center\n#| fig-cap: Diagnostic des variables indépendantes et des résidus simulés pour le modèle multinomial\n#| out-width: \"100%\"\n#| message: false\n#| warning: false\n#| echo: false\ninvisible(capture.output({\n out <- \"images/Chap08/residusmultinom2.png\"\n \n png(filename = out,\n res = 300, width = 50, height = 35, units = \"cm\")\n \n etend_data <- do.call(rbind, lapply(data_sims, function(i){i$data}))\n par(mfrow=c(3,3))\n vars <- c(\"PercepOGM\", \"PercepRechClim\", \"ConnaisOGM\", \n \"ConnaisRechClim\", \"CRT\", \"Parti\", \"Sexe\")\n for(v in vars){\n plotResiduals(sim_res, etend_data[[v]], xlab= v, ylab = \"résidus\")\n }\n \n dev.off()\n}))\nknitr::include_graphics(out, dpi = 300)\n```\n\nNous réajustons donc le modèle et recalculons nos résidus ajustés (masqué ici pour alléger le document). La @fig-residusmultinom3 nous confirme que le problème a été corrigé.\n\n```{r}\n# Convertir les variables ordinales et variables binaires\ndata_quest$PercepOGMDes <- ifelse(data_quest$PercepOGM %in% c(1,2), 1,0)\ndata_quest$PercepRechClimDes <- ifelse(data_quest$PercepRechClim %in% c(1,2), 1,0)\n# Réajuster le modèle\nmodele3 <- vglm(Y ~ PercepOGMDes + PercepRechClimDes + \n ConnaisOGM + ConnaisRechClim + \n CRT + Parti + Sexe,\n data = data_quest, \n family = multinomial(refLevel = \"A\"), model = T)\n```\n\n\n```{r}\n#| label: fig-residusmultinom3\n#| fig-cap: Diagnostic général des résidus simulés pour le modèle multinomial (version 3)\n#| fig-align: center\n#| out-width: \"65%\"\n#| echo: false\n#| message: false\n#| warning: false\n\n# Extraire les prédictions du modèle\ncategories <- c(\"B\" , \"C\" , \"D\")\npredicted <- predict(modele3, type = \"link\")\nnsim <- 1000\n\nilink <- function(x){exp(x)/(1+exp(x))}\n# Boucler sur chacune des catégories en dehors de la référence\ndata_sims <- lapply(1:ncol(predicted), function(i){\n categorie <- categories[[i]]\n # Extraire les observation de la catégorie i et de la référence\n test <- data_quest$Y %in% c(\"A\", categorie)\n # Calculer les probabilité d'appartenance à i\n values <- predicted[test,i]\n probs <- ilink(values)\n # Extraire les valeurs réelles et les convertir en 0 / 1\n real <- data_quest[test,]$Y\n real <- ifelse(real==\"A\",0,1)\n # Enregistrer ces différents éléments\n all_probs <- cbind(1-probs, probs)\n sub_data <- subset(data_quest, test)\n return(list(\"real\" = real, \"probs\" = all_probs, \"data\" = sub_data))\n})\n\n# Extraire les probabilités prédites\nall_probs <- do.call(rbind, lapply(data_sims, function(i){i$probs}))\n\n# Extraire les vrais catégories\nall_real <- do.call(c, lapply(data_sims, function(i){i$real}))\n\n# Effectuer les simulations\nsimulations <- lapply(1:nrow(all_probs), function(i){\n probs <- all_probs[i,]\n sims <- sample(c(0,1), size = nsim, replace = TRUE, prob = probs)\n return(sims)\n})\nmatsim <- do.call(rbind, simulations)\n\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = matsim, \n observedResponse = all_real,\n fittedPredictedResponse = all_probs[,2],\n integerResponse = TRUE)\n\netend_data <- do.call(rbind, lapply(data_sims, function(i){i$data}))\n\ninvisible(capture.output({\n out <- \"images/Chap08/residusmultinom3.png\"\n \n png(filename = out,\n res = 300, width = 50, height = 35, units = \"cm\")\n \n par(mfrow=c(3,3))\n vars <- c(\"PercepOGMDes\", \"PercepRechClimDes\", \"ConnaisOGM\", \n \"ConnaisRechClim\", \"CRT\", \"Parti\", \"Sexe\")\n \n for(v in vars){\n plotResiduals(sim_res, etend_data[[v]], xlab= v, ylab = \"résidus\")\n }\n \n dev.off()\n}))\nknitr::include_graphics(out, dpi = 300)\n```\n\nProfitons du fait que nous utilisons le *package* `VGAM` pour vérifier l'absence d'effet de Hauck-Donner qui indiquerait que des variables indépendantes provoquent des séparations parfaites. \n\n```{r}\n#| message: false\n#| warning: false\ntest <- hdeff(modele3)\ntest[test == TRUE]\n```\n\nLa fonction nous informe que les constantes permettant de comparer le groupe C au groupe A, et le groupe D au groupe A provoquent des séparations parfaites. Cela s'explique notamment par le faible nombre d'observations tombant dans ces catégories. Considérant que comparativement à la catégorie A, être dans les catégories B, C, ou D signifie remettre en cause au moins un consensus scientifique, il peut être raisonnable de fixer la constante pour qu'elle soit la même pour les trois comparaisons. Ainsi, les chances de passer de A à un autre groupe ne dépenderaient pas du groupe en question, mais uniquement des variables indépendantes. Pour cela, nous pouvons forcer le modèle à n'ajuster qu'une seule constante avec la syntaxe suivante :\n\n```{r}\n#| message: false\n#| warning: false\nmodele4 <- vglm(Y ~ PercepOGMDes + PercepRechClimDes + \n ConnaisOGM + ConnaisRechClim + \n CRT + Parti + Sexe,\n data = data_quest, \n family = multinomial(refLevel = \"A\",\n parallel = TRUE ~1), model = T)\ntest <- hdeff(modele4)\nprint(table(test))\n\n# Calcul du khi2 de Pearson\npred <- predict(modele4, type= \"response\")\ncat_predict <- colnames(pred)[max.col(pred)]\nfreq_real <- table(data_quest$Y)\nfreq_pred <- table(cat_predict)\nkhi2 <- sum(residuals(modele4, type = \"pearson\")^2)\nN <- nrow(data_quest)\np <- modele4@rank\nr <- length(freq_real)\nratio <- khi2 / ((N)*(r-1)-p)\nprint(ratio)\n```\n\nNous n'avons donc plus de séparation complète ni de sur ou sous-dispersion et les résidus simulés de la quatrième version du modèle sont toujours acceptables (@fig-residusmultinom4).\n\n```{r}\n#| label: fig-residusmultinom4\n#| fig-cap: Diagnostic général des résidus simulés pour le modèle multinomial (version 4)\n#| fig-align: center\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n#| #| echo: false\n# Extraire les prédictions du modèle\ncategories <- c(\"B\" , \"C\" , \"D\")\npredicted <- predict(modele4, type = \"link\")\nnsim <- 1000\nilink <- function(x){exp(x)/(1+exp(x))}\n\n# Boucler sur chacune des catégories en dehors de la référence\ndata_sims <- lapply(1:ncol(predicted), function(i){\n categorie <- categories[[i]]\n # Extraire les observation de la catégorie i et de la référence\n test <- data_quest$Y %in% c(\"A\", categorie)\n # Calculer les probabilité d'appartenance à i\n values <- predicted[test,i]\n probs <- ilink(values)\n # Extraire les valeurs réelles et les convertir en 0 / 1\n real <- data_quest[test,]$Y\n real <- ifelse(real==\"A\",0,1)\n # Enregistrer ces différents éléments\n all_probs <- cbind(1-probs, probs)\n sub_data <- subset(data_quest, test)\n return(list(\"real\" = real, \"probs\" = all_probs, \"data\" = sub_data))\n})\n\n# Extraire les probabilités prédites\nall_probs <- do.call(rbind, lapply(data_sims, function(i){i$probs}))\n\n# Extraire les vrais catégories\nall_real <- do.call(c, lapply(data_sims, function(i){i$real}))\n\n# Effectuer les simulations\nsimulations <- lapply(1:nrow(all_probs), function(i){\n probs <- all_probs[i,]\n sims <- sample(c(0,1), size = nsim, replace = TRUE, prob = probs)\n return(sims)\n})\nmatsim <- do.call(rbind, simulations)\n\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = matsim, \n observedResponse = all_real,\n fittedPredictedResponse = all_probs[,2],\n integerResponse = TRUE)\nplot(sim_res)\n```\n\n**Vérification l'ajustement du modèle**\n\nPuisque les conditions d'application du modèle sont respectées, nous pouvons à présent vérifier sa qualité d'ajustement.\n\n```{r}\n#| message: false\n#| warning: false\nmodelenull <- vglm(Y ~ 1 ,\n data = data_quest, \n family = multinomial(refLevel = \"A\",\n parallel = TRUE ~ 1 + CRT)\n , model = T)\nrsqs(loglike.full = logLik(modele4),\n loglike.null = logLik(modelenull),\n full.deviance = deviance(modele4),\n null.deviance = deviance(modelenull),\n nb.params = modele4@rank,\n n = nrow(data_quest)\n)\n```\n\nLe modèle parvient à expliquer 17,5 % de la déviance totale. Il obtient un R^2^ ajusté de McFadden de 0,15, et des R^2^ de Cox et Snell et de Nagelkerke de respectivement 0,34 et 0,37. Passons à la construction de la matrice de confusion pour analyser la capacité de prédiction du modèle.\n\n```{r}\n#| message: false\n#| warning: false\npreds <- predict(modele4, type = \"response\")\npred_cats <- colnames(preds)[max.col(preds)]\nreal <- data_quest$Y\nmatrices <- nice_confusion_matrix(real, pred_cats)\n\n# Afficher la matrice de confusion\nprint(matrices$confusion_matrix)\n\n# Afficher les indicateurs de qualité de prédiction\nprint(matrices$indicators)\n```\n\nLa précision globale (macro) du modèle est de 60 % et dépasse significativement le seuil de non-information. L'indicateur de Kappa indique un accord modéré entre la prédiction et les valeurs réelles. Les catégories C et D sont les catégories avec la plus faible précision, indiquant ainsi que le modèle a tendance à manquer les prédictions pour les individus en désaccord avec le consensus scientifique sur le réchauffement climatique. Les indices de rappel sont également très faibles pour les catégories B, C et D, indiquant que très peu d'observations appartenant originalement à ces groupes ont bien été classées dans ces groupes. La capacité de prédiction du modèle est donc relativement faible.\n\n**Interprétation des résultats**\n\nPuisque nous disposons de quatre catégories dans notre variable *Y*, nous obtenons au final trois tableaux de coefficients. Il est possible de visualiser l'ensemble des coefficients du modèle avec la fonction `summary`, nous proposons les tableaux [-@tbl-coeffsmultinom1], [-@tbl-coeffsmultinom2] et [-@tbl-coeffsmultinom3] pour présenter l'ensemble des résultats.\n\n```{r}\n#| message: false\n#| warning: false\n#| echo: false\ntables <- build_table(modele4, confid = TRUE, sign = TRUE, coef_digits = 2, std_digits = 2, z_digits = 2, p_digits = 3, OR_digits = 3)\ntab1 <- tables[[1]][, c(1,2,3,6,9,10,11)]\ntab2 <- tables[[2]][, c(1,2,3,6,9,10,11)]\ntab3 <- tables[[3]][, c(1,2,3,6,9,10,11)]\n```\n\n```{r}\n#| label: tbl-coeffsmultinom1\n#| tbl-cap: Coefficients du modèle multinomial A versus B\n#| message: false\n#| warning: false\n#| echo: false\nknitr::kable(tab1,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n \t\t col.names = c(\"Variable\", \"Coefficient\", \"RC\", \"val.p\", \"RC 2,5 %\", \"RC 97,5 %\", \"sign.\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\nLe @tbl-coeffsmultinom1 compare donc le groupe A (en accord avec la recherche scientifique sur les deux sujets) et le groupe B (en désaccord sur la question des OGM). Les résultats indiquent que le fait de se percevoir en désaccord avec le consensus scientifique sur la question des OGM multiplie par sept les chances d'appartenir au groupe B comparativement au groupe A. Cependant, pour chaque bonne réponse supplémentaire sur les questions testant les connaissances sur les OGM, les chances d'appartenir au groupe B comparativement au groupe A diminuent de 28 %. Ainsi, un individu ayant répondu correctement aux trois questions verrait ses chances réduites de 63 % d'appartenir au groupe B ($exp(-\\text{0,33}\\times\\text{3})$). Il est intéressant de noter que les variables concernant le réchauffement climatique n'ont pas d'effet significatif ici. La variable CRT indique qu'à chaque bonne réponse supplémentaire au test de cognition, les chances d'appartenir au groupe B augmentent de 42 %. Un individu qui aurait répondu aux trois questions du test aurait donc 2,9 fois plus de chances d'appartenir au groupe B qu'au groupe A. Concernant le parti politique, comparativement à une personne se déclarant plus proche du parti démocrate, les personnes proches du parti républicain ou d'un autre parti ont près de deux fois plus de chances d'appartenir au groupe B. Enfin, une femme, comparativement à un homme, a 3,6 fois plus de chance d'appartenir au groupe B.\n\n```{r}\n#| label: tbl-coeffsmultinom2\n#| tbl-cap: Coefficients du modèle multinomial A versus C\n#| message: false\n#| warning: false\n#| echo: false\nknitr::kable(tab2,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t col.names = c(\"variable\", \"Coefficient\", \"RC\", \"val.p\", \"RC 2,5 %\", \"RC 97,5 %\", \"sign.\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\nLe @tbl-coeffsmultinom2 compare les groupes A et C (en désaccord sur le réchauffement climatique). Il est intéressant de noter ici que se percevoir en désaccord avec la recherche scientifique est associé avec une forte augmentation des chances d'appartenir au groupe C. Cependant, un plus grand nombre de bonnes réponses aux questions sur le réchauffement climatique est également associé avec une augmentation des chances (30 % à chaque bonne réponse supplémentaire) d'appartenir au groupe C. Le CRT n'a cette fois-ci pas d'effet. Se déclarer proche du parti républicain, comparativement au parti démocrate, multiplie les chances par 2,5 d'appartenir au groupe C. Comparativement au tableau précédent, le fait d'être une femme diminue les chances de 36 % d'appartenir au groupe C.\n\n```{r}\n#| label: tbl-coeffsmultinom3\n#| tbl-cap: Coefficients du modèle multinomial A versus D\n#| message: false\n#| warning: false\n#| echo: false\nknitr::kable(tab3,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t col.names = c(\"variable\", \"Coefficient\", \"RC\", \"val.p\", \"RC 2,5 %\", \"RC 97,5 %\", \"sign.\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\"),\n )\n```\n\nLe dernier tableau ([-@tbl-coeffsmultinom3]) compare le groupe A au groupe D (en désaccord sur les deux sujets). Les variables les plus importantes sont une fois encore le fait de se sentir en désaccord avec la recherche scientifique et le degré de connaissance sur les OGM. La variable concernant le parti politique est significative au seuil 0,05 et exprime toujours une tendance accrue pour les individus du parti républicain à appartenir au groupe D.\n\nNos propres conclusions corroborent celles de l'article original. Une des conclusions intéressantes est que le rejet du consensus scientifique ne semble pas nécessairement être associé à un déficit d'information ni à une plus faible capacité analytique, mais relèverait davantage d'une polarisation politique. Notez que cette littérature sur les croyances et la confiance dans la recherche est complexe, si le sujet vous intéresse, la discussion de l'article de @mcfadden2016examining est un bon point de départ.\n\n\n### Conclusion sur les modèles pour des variables qualitatives\n\nNous avons vu dans cette section, les trois principales formes de modèles GLM pour modéliser une variable binaire (modèle binomial), une variable ordinale (modèle de cotes proportionnel) et une variable multinomiale (modèle multinomial). Pour ces trois modèles, nous avons vu que la distribution utilisée est toujours la distribution binomiale et la fonction de lien logistique. Les coefficients obtenus s'interprètent comme des rapports de cotes, une fois qu'ils sont transformés avec la fonction exponentielle. \n\n## Modèles GLM pour des variables de comptage {#sec-083}\n\nDans cette section, nous présentons les principaux modèles utilisés pour modéliser des variables de comptage. Il peut s'agir de variables comme le nombre d'accidents à une intersection, le nombre de cafés par quartier, le nombre de cas d'une maladie donnée par entité géographique, etc.\n\n### Modèle de Poisson {#sec-0831}\n\nLe modèle GLM de base pour modéliser une variable de comptage est le modèle de Poisson. Pour rappel, la distribution de Poisson a un seul paramètre: $\\lambda$. Il représente le nombre moyen d'évènements observés sur l’intervalle de temps d'une observation, ainsi que la dispersion de la distribution. En conséquence, $\\lambda$ doit être un nombre strictement positif; autrement dit, nous ne pouvons pas observer un nombre négatif d'évènements. Il est donc nécessaire d’utiliser une fonction de lien pour contraindre l’équation de régression sur l’intervalle $[0 ,+\\infty]$. La fonction la plus utilisée est le logarithme naturel (*log*) dont la réciproque est la fonction exponentielle (*exp*).\n\n```{r}\n#| label: tbl-poissondentity\n#| tbl-cap: Carte d'identité du modèle de Poisson\n#| echo: false\n#| message: false\n#| warning: false\nmodel_formula <- \"$Y \\\\sim Poisson(\\\\lambda)$ \\\\newline $g(\\\\lambda) = \\\\beta_0 + \\\\beta X$ \\\\newline $g(x) =log(x)$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable de comptage\", \"Poisson\", model_formula , \"log\", \"$\\\\lambda$\", \"$\\\\beta_0$, $\\\\beta$\", \"Absence d’excès de zéros, absence de sur-dispersion ou de sous-dispersion\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\"\n)\n```\n\n#### Interprétation des paramètres {#sec-08311}\n\nLes coefficients du modèle expriment l’effet du changement d’une unité des variables *X* sur $\\lambda$ (le nombre de cas) dans l’échelle logarithmique (*log-scale*). Pour rappel, l’échelle logarithmique est multiplicative : si nous convertissons les coefficients dans leur échelle originale avec la fonction exponentielle, leur effet n’est plus additif, mais multiplicatif. Prenons un exemple concret, admettons que nous avons ajusté un modèle de Poisson à une variable de comptage *Y* avec deux variables $X_1$ et $X_2$ et que nous avons obtenus les coefficients suivants :\n\n$\\beta_0 = 1,8 \\text{; } \\beta_1 = 0,5 \\text{; } \\beta_2 = -1,5$\n\nL’interprétation basique (sur l’échelle logarithmique) est la suivante : une augmentation d'une unité de la variable $X_1$ est associée avec une augmentation de 0,5 du logarithme du nombre de cas attendus. Une augmentation d'une unité de la variable $X_2$ est associée avec une réduction de 1,5 unité du logarithme du nombre de cas attendus. Avec la conversion avec la fonction exponentielle, nous obtenons alors : \n\n* $exp\\mbox{(0,5) = 1,649}$, soit une multiplication par 1,649 du nombre de cas attendu (aussi appelé taux d'incident) à chaque augmentation d’une unité de $X_1$;\n\n* $exp\\mbox{(-1,5) = 0,223}$, soit une division par 4,54 (1/0,223) du nombre de cas attendu (aussi appelé taux d'incident) à chaque augmentation d’une unité de $X_2$.\n\nUtilisons maintenant notre équation pour effectuer une prédiction si $X_1 = 1$ et $X_2 = 1$.\n\n$\\lambda = exp(\\mbox{1,8} + (\\mbox{0,5}\\times 1) + (\\mbox{-1,5}\\times1)) = \\mbox{2,225}$\n\nSi nous augmentons $X_1$ d’une unité, nous obtenons alors : \n\n$\\lambda = exp(1,8 + (\\mbox{0,5}\\times 2) + (\\mbox{-1,5}\\times1)) = \\mbox{3,670}$\n\nEn ayant augmenté d’une unité $X_1$, nous avons multiplié notre résultat par 1,649 ($\\mbox{2,225} \\times \\mbox{1,649 = 3,670}$).\n\nNotez que ces effets se multiplient entre eux. Si nous augmentons à la fois $X_1$ et $X_2$ d'une unité chacune, nous obtenons : $\\lambda = exp(1,8 + (\\mbox{0,5} \\times 2) + (\\mbox{-1,5} \\times 2)) = \\mbox{0,818}$, ce qui correspond bien à $\\mbox{2,225} \\times \\mbox{1,649} \\text{ (effet de }X_1\\text{)} \\times \\mbox{0,223} \\text{ (effet de }X_2\\text{)} = \\mbox{0,818}$.\n\nIl existe des fonctions dans R qui calculent ces prédictions à partir des équations des modèles. Il est cependant essentiel de bien saisir ce comportement multiplicatif induit par la fonction de lien *log*.\n\n#### Conditions d'application {#sec-08312}\n\nPuisque la distribution de Poisson n’a qu’un seul paramètre, le modèle GLM de Poisson est exposé au même problème potentiel de sur-dispersion que les modèles binomiaux de la section précédente. Référez-vous à la [section @sec-08212] pour davantage de détails sur le problème posé par la sur-dispersion. Pour détecter une potentielle sur-dispersion dans un modèle de Poisson, il est possible, dans un premier temps, de calculer le ratio entre la déviance du modèle et son nombre de degrés de liberté [@Saspoiss]. Ce ratio doit être proche de 1, s'il est plus grand, le modèle souffre de sur-dispersion.\n\n$$\n\\hat{\\phi} = \\frac{D(modele)}{N-p}\n$$ {#eq-glm16}\n\navec $N$ et $p$ étant respectivement les nombres d'observations et de paramètres. Il est également possible de tester formellement si la sur-dispersion est significative avec un test de dispersion.\n\nLa question de l’excès de zéros a été abordée dans la [section @sec-poissonzero] du [chapitre @sec-chap02]. Il s’agit d’une situation où un plus grand nombre de zéros sont présents dans les données que ce que suppose la distribution de Poisson. Dans ce cas, il convient d'utiliser la distribution de Poisson avec excès de zéros.\n\n#### Exemple appliqué dans R {#sec-08313}\n\nPour cet exemple, nous reproduisons l’analyse effectuée dans l’article de @cloutier2014carrefours. L’enjeu de cette étude était de modéliser le nombre de piétons blessés autour de plus de 500 carrefours dans les quartiers centraux de Montréal. Pour cela, trois types de variables étaient utilisées : des variables décrivant l’intersection, des variables décrivant les activités humaines dans un rayon d'un kilomètre autour de l’intersection et des variables représentant le trafic routier autour de l’intersection. Un effet direct de ce type d’étude est bien évidemment l’établissement de meilleures pratiques d’aménagement réduisant les risques encourus par les piétons lors de leurs déplacements en ville. Le @tbl-variablepoiss présente l'ensemble des variables utilisées dans l'analyse.\n\n```{r}\n#| label: tbl-variablepoiss\n#| tbl-cap: Variables indépendantes utilisées dans le modèle de Poisson\n#| echo: false\n#| message: false\n#| warning: false\ndf <- data.frame(\n C1 = c(\"Feux_auto\", \" Feux_piet\", \" Pass_piet\", \" Terreplein\", \" Apaisement\", \" LogEmploi\", \" Densite_pop\", \" Entropie\", \" DensiteInter\", \" Artere\", \" Long_arterePS\", \" NB_voies5\"),\n C2 = c(\"Présence de feux de circulation\", \" Présence de feux de traversée pour les piétons\", \" Présence d’un passage piéton\", \" Présence d’un terre-plein central\", \" Présence de mesure d’apaisement de la circulation\", \" Logarithme du nombre d’emplois dans un rayon d’un kilomètre\", \" Densité de population dans un rayon d’un kilomètre\", \" Diversité des occupations du sol dans un rayon d’un kilomètre (indice d'entropie)\", \" Densité d’intersections dans un rayon d’un kilomètre (connexité)\", \" Présence d’une artère à l’intersection\", \" Longueur d’artère dans un rayon d’un kilomètre\", \" Présence d’une cinq voies à l’intersection\"),\n C3 = c(\"Variable binaire\", \" Variable binaire\", \" Variable binaire\", \" Variable binaire\", \" Variable binaire\", \" Variable continue\", \" Variable continue\", \" Variable continue\", \" Variable continue\", \" Variable binaire\", \" Variable continue\", \" Variable binaire\"),\n C4 = c(\"0 = absence; 1 = présence\", \" 0 = absence; 1 = présence\", \" 0 = absence; 1 = présence\", \" 0 = absence; 1 = présence\", \" 0 = absence; 1 = présence\", \" Logarithme du nombre d’emplois. Utilisation du logarithme, car la variable est fortement asymétrique\", \" Habitants par hectare\", \" Mesure de 0 à 1; 0 = spécialisation parfaite; 1 = diversité parfaite \", \" Nombre d’intersection par km2 \", \" 0 = absence; 1 = présence\", \" Exprimée en mètres\", \" 0 = absence; 1 = présence\")\n)\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Nom de la variable\" , \"Signification\" , \"Type de variable\" , \"Mesure\"), \n align= c(\"l\", \"l\", \"l\", \"l\"),\n col.to.resize = c(2,4),\n col.width = \"5cm\"\n)\n```\n\nLa distribution originale de la variable est décrite à la @fig-distripoissmod. Les barres grises représentent la distribution du nombre d'accidents et les barres rouges une distribution de Poisson ajustée sans variable indépendante (modèle nul). Ce premier graphique peut laisser penser qu’un modèle de Poisson n'est pas nécessairement le plus adapté considérant le grand nombre d’intersections pour lesquelles nous n’avons aucun accident. Cependant, rappelons que la variable *Y* n'a pas besoin de suivre une distribution de Poisson. Dans un modèle GLM, l'hypothèse que nous formulons est que la variable dépendante (*Y*) **conditionnée par les variables indépendantes (*X*)** suit une certaine distribution (ici Poisson).\n\n```{r}\n#| label: fig-distripoissmod\n#| fig-cap: Distribution originale du nombre d'accidents par intersection\n#| fig-align: center\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n# Chargement des données\ndata_accidents <- read.csv(\"data/glm/accident_pietons.csv\", sep = \";\")\n# Ajustement d'une distribution de Poisson sans variable indépendante\nlibrary(fitdistrplus)\nmodel_poisson <- fitdist(data_accidents$Nbr_acci, distr = \"pois\")\n# Création d'un graphique pour comparer les deux distributions\ndfpoisson <- data.frame(x=c(0:19),\n y = dpois(0:19, model_poisson$estimate)\n)\ncounts <- data.frame(table(data_accidents$Nbr_acci))\nnames(counts) <- c(\"nb_accident\",'frequence')\ncounts$nb_accident <- as.numeric(as.character(counts$nb_accident))\ncounts$prop <- counts$frequence / sum(counts$frequence)\nggplot() + \n geom_bar(aes(x = nb_accident, weight = prop, fill = \"real\"), width = 0.6, data = counts)+\n geom_bar(aes(x = x, weight = y, fill = \"adj\"), width = 0.15, data = dfpoisson)+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n scale_fill_manual(name = \"\",\n breaks = c(\"real\" , \"adj\"),\n labels = c(\"distribution originale\", \"distribution de Poisson\"),\n values = c(\"real\" = rgb(0.4,0.4,0.4), \"adj\" = \"red\"))+\n labs(subtitle = \"\",\n x = \"nombre d'accidents\",\n y = \"\")\n```\n\n**Vérification des conditions d'application**\n\nComme précédemment, notre première étape est de vérifier l'absence de multicolinéarité excessive avec la fonction `vif` du *package* `car`.\n\n```{r}\n#| message: false\n#| warning: false\nvif(glm(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = poisson(link=\"log\"),\n data = data_accidents))\n```\n\nToutes les valeurs de VIF sont inférieures à 5. Notons tout de même que le logarithme de l'emploi et la longueur d'artère dans un rayon d'un kilomètre ont des valeurs de VIF proches de 5. La seconde étape du diagnostic consiste à calculer et à visualiser les distances de Cook.\n\n```{r}\n#| label: fig-poisscookdist\n#| fig-align: center\n#| fig-cap: Distances de Cook pour le modèle de Poisson\n#| out-width: \"60%\"\n#| #| message: false\n#| warning: false\n\n\n# Ajustement d'une première version du modèle\nmodele <- glm(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = poisson(link=\"log\"),\n data = data_accidents)\n\n# Calcul des distances de Cook\ncooksd <- cooks.distance(modele)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, alpha = 0.5)+\n labs(x = \"\",\n y = \"Distance de Cook\")\n```\n\nLa @fig-poisscookdist signale la présence de trois observations avec des valeurs extrêmement fortes de distance de Cook. Nous les isolons dans un premier temps pour les analyser.\n\n```{r}\n#| message: false\n#| warning: false\ncas_etrange <- subset(data_accidents, cooksd>0.1)\nprint(cas_etrange)\n```\n\nLes deux premiers cas sont des intersections avec de nombreux accidents (respectivement 19 et 7) qui risquent de perturber les estimations du modèle. Le troisième cas ne comprend en revanche aucun accident. Puisqu'il ne s'agit que de trois observations et que leurs distances de Cook sont très nettement supérieures aux autres, nous les retirons du modèle.\n\n```{r}\n#| label: fig-poisscookdist2\n#| fig-align: center\n#| out-width: \"60%\"\n#| fig-cap: Distances de Cook pour le modèle de Poisson après avoir retiré les valeurs aberrantes\n#| message: false\n#| warning: false\n\ndata2 <- subset(data_accidents, cooksd<0.1)\n# Ajustement d'une première version du modèle\nmodele <- glm(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = poisson(link=\"log\"),\n data = data2)\n\n# Calcul des distances de Cook\ncooksd <- cooks.distance(modele)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, alpha = 0.5)+\n labs(x = \"\",\n y = \"distance de Cook\")\n```\n\nLa @fig-poisscookdist2 montre que nous n'avons plus d'observations fortement influentes dans le modèle après avoir retiré les trois observations identifiées précédemment. Nous devons à présent vérifier l'absence de sur-dispersion.\n\n```{r}\n#| message: false\n#| warning: false\n# Calcul du rapport entre déviance et nombre de degrés de liberté du modèle\ndeviance(modele)/(nrow(data2) - modele$rank)\n```\n\nLe rapport entre la déviance et le nombre de degrés de liberté du modèle est nettement supérieur à 1, indiquant une sur-dispersion excessive. Nous pouvons confirmer ce résultat avec la fonction `dispersiontest` du *package* `AER`.\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(AER)\n# Test de sur-dispersion\ndispersiontest(modele)\n```\n\nContrairement à la forme classique d’un modèle de Poisson pour laquelle la dispersion attendue est de 1, le test nous indique qu’une dispersion de 1,89 serait mieux ajustée aux données. \n\nIl est également possible d'illuster cet écart à l'aide d'un graphique représentant les valeurs réelles, les valeurs prédites, ainsi que la variance (sous forme de barres d'erreurs) attendue par le modèle (@fig-surdisppoiss). Nous constatons ainsi que les valeurs réelles (en rouge) ont largement tendance à dépasser la variance attendue par le modèle, surtout pour les valeurs les plus faibles de la distribution. \n\n```{r}\n#| label: fig-surdisppoiss\n#| fig-align: center\n#| fig-cap: Représentation de la sur-dispersion des données dans le modèle de Poisson\n#| out-width: \"60%\"\n#| message: false\n#| warning: false\n\n# Extraction des prédictions du modèle\nlambdas <- predict(modele, type = \"response\")\n# Création d'un DataFrame pour contenir la prédiction et les vraies valeurs\ndf1 <- data.frame(\n lambdas = lambdas,\n reals = data2$Nbr_acci\n)\n# Calcul de l'intervalle de confiance à 95 % selon la distribution de Poisson\n# et stockage dans un second DataFrame\nseqa <- seq(0, round(max(lambdas)),1)\ndf2 <- data.frame(\n lambdas = seqa,\n lower = qpois(p = 0.025, lambda = seqa),\n upper = qpois(p = 0.975, lambda = seqa)\n)\n# Affichage des valeurs réelles et prédites (en rouge)\n# et de leur variance selon le modèle (en noir)\nggplot() + \n geom_errorbar(data = df2,\n mapping = aes(x = lambdas, ymin = lower, ymax = upper),\n width = 0.2, color = rgb(0.4,0.4,0.4)) + \n geom_point(data = df1, \n mapping = aes(x = lambdas, y = reals),\n color =\"red\", size = 0.5) + \n labs(x = \"valeurs prédites\",\n y = \"valeurs réelles\")\n```\n\nPour tenir compte de cette particularité des données, nous modifions légèrement le modèle pour utiliser une distribution de quasi-Poisson, intégrant spécifiquement un paramètre de dispersion. Cet ajustement ne modifie pas l'estimation des coefficients du modèle, mais modifie le calcul des erreurs standards et par extension les valeurs de *p* pour les rendre moins sensibles au problème de sur-dispersion. Une autre approche aurait été de calculer une version robuste des erreurs standards avec le *package* `sandwich` comme nous l'avons fait dans la [section @sec-0821] sur le modèle binomial. Après réajustement du modèle, le nouveau paramètre de dispersion estimé est de 1,92.\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Les quasi-distributions**\n:::\n::: bloc_notes-body\nLes distributions binomiale et de Poisson ne disposent chacune que d’un paramètre décrivant à la fois leur dispersion et leur espérance. Elles manquent donc de flexibilité et échouent parfois à représenter fidèlement des données avec une forte variance. Il existe donc d'autres distributions, respectivement les distributions quasi-binomiale et quasi-Poisson comprenant chacune un paramètre supplémentaire pour contrôler la dispersion. Bien que cette solution soit attrayante, il ne faut pas perdre de vue que la sur ou la sous dispersion peuvent être causées par l’absence de certaines variables explicatives, la sur-représentation de zéros, ou encore une séparation parfaite de la variable dépendante causée par une variable indépendante.\n:::\n:::\n\n```{r}\n#| message: false\n#| warning: false\nmodele2 <- glm(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = quasipoisson(link=\"log\"),\n data = data2)\n```\n\nNous pouvons à présent comparer la distribution originale des données et les simulations issues du modèle. Notez que contrairement à la distribution de Poisson simple, il n'existe pas dans R de fonction pour simuler des valeurs issues d'une distribution de quasi-Poisson. Il est cependant possible d'exploiter sa proximité théorique avec la distribution binomiale négative pour définir notre propre fonction de simulation. La @fig-comppoissdistr permet de comparer la distribution originale (en gris) et l'intervalle de confiance à 95 % des simulations (en rouge). Nous remarquons que le modèle semble capturer efficacement la forme générale de la distribution originale. À titre de comparaison, nous pouvons effectuer le même exercice avec la distribution de Poisson classique (le code n'est pas montré pour éviter les répétitions). La @fig-comppoissdistr2 montre qu'un simple modèle de Poisson est très éloigné de la distribution originale de *Y*.\n\n```{r}\n#| label: fig-comppoissdistr\n#| fig-align: center\n#| fig-cap: Comparaison de la distribution originale et des simulations pour le modèle de quasi-Poisson\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n#| \n# Définition d'une fonction pour simuler des données quasi-Poisson\nrqpois <- function(n, lambda, disp) {\n rnbinom(n = n, mu = lambda, size = lambda/(disp-1))\n}\n# Extraction des valeurs prédites par le modèle\npreds <- predict(modele2, type = \"response\")\n# Génération de 1000 simulations pour chaque prédiction\ndisp <- summary(modele2)$dispersion\nnsim <- 1000\ncols <- lapply(1:length(preds), function(i){\n lambda <- preds[[i]]\n sims <- round(rqpois(n = nsim, lambda = lambda, disp = disp))\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Préparation des données pour le graphique (valeurs réelles)\ncounts <- data.frame(table(data2$Nbr_acci))\nnames(counts) <- c(\"nb_accident\",'frequence')\ncounts$nb_accident <- as.numeric(as.character(counts$nb_accident))\ncounts$prop <- counts$frequence / sum(counts$frequence)\n# Préparation des données pour le graphique (valeurs simulées)\ndf1 <- data.frame(count = 0:25)\ncount_sims <- lapply(1:nsim, function(i){\n sim <- mat_sims[,i]\n cnt <- data.frame(table(sim))\n df2 <- merge(df1, cnt, by.x = \"count\", by.y = \"sim\", all.x = TRUE, all.y = FALSE)\n df2$Freq <- ifelse(is.na(df2$Freq),0, df2$Freq)\n return(df2$Freq)\n})\ncount_sims <- do.call(cbind, count_sims)\ndf_sims <- data.frame(\n val = 0:25,\n med = apply(count_sims, MARGIN = 1, median),\n lower = apply(count_sims, MARGIN = 1, quantile, probs = 0.025),\n upper = apply(count_sims, MARGIN = 1, quantile, probs = 0.975)\n)\n\nggplot() + \n geom_bar(aes(x = nb_accident, weight = frequence), width = 0.6, data = counts)+\n geom_errorbar(aes(x = val, ymin = lower, ymax = upper),\n data = df_sims, color = \"red\", width = 0.6)+\n geom_point(aes(x = val, y = med), color = \"red\", size = 1.3, data = df_sims)+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n xlim(-1,12)+\n labs(subtitle = \"\",\n x = \"nombre d'accidents\",\n y = \"nombre d'occurrences\")\n```\n\n```{r}\n#| label: fig-comppoissdistr2\n#| fig-align: center\n#| fig-cap: Comparaison de la distribution originale et des simulations pour le modèle de Poisson\n#| out-width: \"65%\"\n#| echo: false\n#| message: false\n#| warning: false\n\n# Extraction des valeurs prédites par le modèle\npreds <- predict(modele2, type = \"response\")\n# Génération de 1000 simulations pour chaque prédiction\ndisp <- 1.918757 # trouvable dans le summary(modele2)\nnsim <- 1000\ncols <- lapply(1:length(preds), function(i){\n lambda <- preds[[i]]\n sims <- round(rpois(n=nsim, lambda = lambda))\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Préparation des données pour le graphique (valeurs réelles)\ncounts <- data.frame(table(data2$Nbr_acci))\nnames(counts) <- c(\"nb_accident\",'frequence')\ncounts$nb_accident <- as.numeric(as.character(counts$nb_accident))\ncounts$prop <- counts$frequence / sum(counts$frequence)\n# Préparation des données pour le graphique (valeurs simulées)\ndf1 <- data.frame(count = 0:25)\ncount_sims <- lapply(1:nsim, function(i){\n sim <- mat_sims[,i]\n cnt <- data.frame(table(sim))\n df2 <- merge(df1, cnt, by.x = \"count\", by.y = \"sim\", all.x = TRUE, all.y = FALSE)\n df2$Freq <- ifelse(is.na(df2$Freq),0, df2$Freq)\n return(df2$Freq)\n})\ncount_sims <- do.call(cbind, count_sims)\ndf_sims <- data.frame(\n val = 0:25,\n med = apply(count_sims, MARGIN = 1, median),\n lower = apply(count_sims, MARGIN = 1, quantile, probs = 0.025),\n upper = apply(count_sims, MARGIN = 1, quantile, probs = 0.975)\n)\nggplot() + \n geom_bar(aes(x = nb_accident, weight = frequence), width = 0.6, data = counts)+\n geom_errorbar(aes(x = val, ymin = lower, ymax = upper),\n data = df_sims, color = \"blue\", width = 0.6)+\n geom_point(aes(x = val, y = med), color = \"blue\", size = 1.3, data = df_sims)+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n xlim(-1,12)+\n labs(subtitle = \"\",\n x = \"nombre d'accidents\",\n y = \"nombre d'occurrences\")\n```\n\nLa prochaine étape du diagnostic est l'analyse des résidus simulés. La @fig-simrespoiss indique que les résidus du modèle suivent bien une distribution uniforme et qu'aucune valeur aberrante n'est observable.\n\n```{r}\n#| label: fig-simrespoiss\n#| fig-align: center\n#| fig-cap: Analyse globale des résidus simulés pour le modèle de quasi-Poisson\n#| out-width: \"65%\"\n#| warning: false\n#| message: false\n\n# Génération de 1000 simulations pour chaque prédiction\ndisp <- 1.918757 # trouvable dans le summary(modele2)\nnsim <- 1000\ncols <- lapply(1:length(preds), function(i){\n lambda <- preds[[i]]\n sims <- rqpois(n = nsim, lambda = lambda, disp = disp)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = data2$Nbr_acci,\n fittedPredictedResponse = modele2$fitted.values,\n integerResponse = TRUE)\nplot(sim_res)\n```\n\nPour affiner notre diagnostic, nous pouvons également comparer les résidus simulés et chaque variable indépendante. La @fig-simrespoiss2 n'indique aucune relation problématique entre nos variables indépendantes et les résidus.\n\n```{r}\n#| eval: false\npar(mfrow=c(3,4))\nvars <- c(\"Feux_auto\", \"Feux_piet\", \"Pass_piet\", \"Terreplein\", \"Apaisement\",\n \"LogEmploi\", \"Densite_pop\", \"Entropie\", \"DensiteInter\",\n \"Long_arterePS\", \"Artere\", \"NB_voies5\")\nfor(v in vars){\n plotResiduals(sim_res, data2[[v]], xlab = v, main = \"\", ylab = \"résidus\")\n}\n```\n\n```{r}\n#| label: fig-simrespoiss2\n#| fig-align: center\n#| fig-cap: Comparaison des résidus simulés et de chaque variable indépendante\n#| out-width: \"100%\"\n#| message: false\n#| warning: false\n#| echo: false\ninvisible(capture.output({\n out <- \"images/Chap08/simrespoiss2.png\"\n png(file = out, res = 300, width = 50, height = 30, units = \"cm\")\n par(mfrow=c(3,4))\n vars <- c(\"Feux_auto\", \"Feux_piet\", \"Pass_piet\", \"Terreplein\", \"Apaisement\",\n \"LogEmploi\", \"Densite_pop\", \"Entropie\", \"DensiteInter\",\n \"Long_arterePS\", \"Artere\", \"NB_voies5\")\n for(v in vars){\n plotResiduals(sim_res, data2[[v]], xlab = v, main = \"\", ylab = \"résidus\")\n }\n dev.off()\n}))\nknitr::include_graphics(out, dpi = 300)\n```\n\n\nMaintenant que l'ensemble des diagnostics a été effectué, nous pouvons passer à la vérification de la qualité d'ajustement.\n\n**Vérification de la qualité d'ajustement**\n\nPour le calcul des pseudo-R^2^, notez qu'il n'existe pas à proprement parler de *loglikelihood* pour les quasi-distributions. Pour contourner ce problème, il est possible d'utiliser le *loglikelihood* d'un simple modèle de Poisson (puisque les coefficients ne changent pas), mais il est important de garder à l'esprit que ces pseudo-R^2^ seront d'autant plus faibles que la sur-dispersion originale était forte.\n\n```{r}\n#| message: false\n#| warning: false\nmodelnull <- glm(Nbr_acci ~ 1,\n family = poisson(link=\"log\"),\n data = data2)\nrsqs(loglike.full = logLik(modele),\n loglike.null = logLik(modelnull),\n full.deviance = deviance(modele),\n null.deviance = deviance(modelnull),\n nb.params = modele$rank,\n n = nrow(data2))\n```\n\nLe modèle parvient ainsi à expliquer 48 % de la déviance totale. Il obtient un R^2^ ajusté de McFadden de 0,33 et un R^2^ de Cox et Snell de 0,78.\n\n```{r}\n#| message: false\n#| warning: false\n# Calcul du RMSE\nsqrt(mean((predict(modele2, type = \"response\") - data2$Nbr_acci)**2))\n# Nombre moyen d'accidents\nmean(data2$Nbr_acci)\n```\n\nL’erreur quadratique moyenne du modèle est de 1,84, ce que signifie qu’en moyenne le modèle se trompe d’environ deux accidents pour chaque intersection. Cette valeur est relativement élevée si nous la comparons avec le nombre moyen d’accidents, soit 1,5. Cela s’explique certainement par le grand nombre de zéros dans la variable *Y* qui tendent à tirer les prédictions vers le bas.\n\n**Interprétation des résultats**\n\nL'ensemble des coefficients du modèle sont accessibles via la fonction `summary`. Puisque la fonction de lien du modèle est la fonction `log`, il est pertinent de convertir les coefficients avec la fonction `exp` afin de pouvoir les interpréter sur l'échelle originale (`nombre d'accidents`) plutôt que l'échelle logarithmique (`log(nombre d'accidents)`). N'oubliez pas que ces effets sont multiplicatifs une fois transformés avec la fonction `exp`. Nous pouvons également utiliser les erreurs standards pour calculer des intervalles de confiance à 95 % des exponentiels des coefficients. Le @tbl-coeffpoiss présente l'ensemble des informations pertinentes pour l'interprétation des résultats.\n\n```{r}\n#| message: false\n#| warning: false\n# Calcul des coefficients en exponentiel et des intervalles de confiance\ntableau <- summary(modele2)$coefficients\ncoeffs <- tableau[,1]\nerr.std <- tableau[,2]\nexpcoeff <- exp(coeffs)\nexp2.5 <- exp(coeffs - 1.96*err.std)\nexp975 <- exp(coeffs - 1.96*err.std)\npvals <- tableau[,4]\ntableauComplet <- cbind(coeffs, err.std, expcoeff, exp2.5, exp975, pvals)\n# print(tableauComplet)\n```\n\n```{r}\n#| label: tbl-coeffpoiss\n#| tbl-cap: Résultats du modèle de quasi-Poisson\n#| message: false\n#| warning: false\n#| echo: false\ntableau <- build_table(modele2, confid = TRUE, sign = TRUE, coef_digits = 2, std_digits = 2)\nknitr::kable(tableau[, c(1,2,3,6,9,10,11)], \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t col.names = c(\"Variable\" , \"Coeff.\", \"exp(Coeff.)\", \"Val.p\", \"IC 2,5 % exp(Coeff.)\", \"IC 97,5 % exp(Coeff.)\", \"Sign.\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n )\n```\n\nParmi les variables décrivant les aménagements de l’intersection, nous constatons que les présences d’un feu de circulation et d’un feu de traversée pour les piétons multiplient le nombre attendu d’accidents à une intersection par 3,0 et 1,39. Par contre, les présences d’un passage piéton, d’un terre-plein ou de mesures d’apaisement n’ont pas d’effets significatifs (valeurs de *p* > 0,05).\nConcernant les variables décrivant l’environnement à proximité des intersections, nous observons que la concentration d’emplois et la densité de population contribuent toutes les deux à augmenter le nombre d’accidents à une intersection, bien que leurs effets soient limités. Enfin, la présence d’une rue à cinq voies à l’intersection augmente le nombre d’accidents attendu à l’intersection de 89 %. Nous ne détaillons pas plus les résultats, car nous utilisons le même jeu de données dans les prochaines sections.\n\n### Modèle binomial négatif {#sec-0832}\n\nDans le cas où une variable de comptage est marquée par une sur ou sous-dispersion, la distribution de Poisson n’est pas en mesure de capturer efficacement sa variance. Pour contourner ce problème, il est possible d’utiliser la distribution binomiale négative plutôt que la distribution de Poisson (ou quasi-Poisson). Cette distribution peut être décrite comme une généralisation de la distribution de Poisson : elle inclut un second paramètre $\\theta$ contrôlant la dispersion. L’intérêt premier de ce changement de distribution est que l’interprétation des paramètres est la même pour les deux modèles, tout en contrôlant directement l'effet d'une potentielle sur ou sous-dispersion.\n\n```{r}\n#| label: tbl-nbdentity\n#| tbl-cap: Carte d'identité du modèle binomial négatif\n#| echo: false\n#| message: false\n#| warning: false\nmodel_formula <- \"$Y \\\\sim NB(\\\\mu,\\\\theta)$ \\\\newline $g(\\\\mu) = \\\\beta_0 + \\\\beta X$ \\\\newline $g(x) =log(x)$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable de comptage\", \"Négative binomiale\", model_formula , \"log\", \"$\\\\mu$\", \"$\\\\beta_0$, $\\\\beta$ et $\\\\theta$\", \"Absence d’excès de zéros, respect du lien variance-moyenne\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\"\n)\n```\n\n#### Conditions d'application {#sec-08321}\n\nLes conditions d'application d'un modèle binomial négatif sont presque les mêmes que celles d'un modèle de Poisson. La seule différence est que la condition d'absence de sur ou sous-dispersion est remplacée par une condition de respect du lien espérance-variance. En effet, dans un modèle binomial négatif, le paramètre de dispersion $\\theta$ est combiné avec $\\mu$ (l'espérance) pour exprimer la dispersion de la distribution. Dans le *package* `mgcv` que nous utilisons dans l'exemple, le lien entre $\\mu$, $\\theta$ et la variance est le suivant : \n\n$$\nvariance = \\mu + \\mu^{\\frac{2}{\\theta}}\n$$ {#eq-glm17}\n\nIl s'agit donc d'un **modèle hétéroscédastique** : sa variance n'est pas fixe, mais varie en fonction de sa propre espérance. Si celle-ci augmente, la variance augmente (comme pour un modèle de Poisson), et l'intensité de cette augmentation est contrôlée par le paramètre $\\theta$. Si cette condition n'est pas respectée, l'analyse des résidus simulés révélera un problème de dispersion.\n\n#### Exemple appliqué dans R {#sec-08322}\n\nDans l’exemple précédent avec le modèle de Poisson, nous avons observé une certaine sur-dispersion que nous avons contournée en utilisant un modèle de quasi-Poisson. Dans l’article original, les auteurs ont opté pour un modèle binomial négatif, ce que nous reproduisons ici. Les variables utilisées sont les mêmes que pour le modèle de Poisson. Nous utilisons le *package* `mgcv` et sa fonction `gam` pour ajuster le modèle.\n\n**Vérification des conditions d'application**\n\nNous avons vu précédemment que nos variables indépendantes ne sont pas marquées par une multicolinéarité forte. Il n'est pas nécessaire de recalculer les valeurs de VIF puisque nous utilisons les mêmes données. La première étape du diagnostic est donc de calculer les distances de Cook.\n\n```{r}\n#| label: fig-cookdistnb\n#| fig-cap: Distances de Cook pour le modèle binomial négatif\n#| fig-align: center\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n\nlibrary(mgcv)\n# Chargement des données\ndata_accidents <- read.csv(\"data/glm/accident_pietons.csv\", sep = \";\")\n# Ajustement d'une première version du modèle\nmodelnb <- gam(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + \n Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = nb(link=\"log\"),\n data = data_accidents)\n# Calcul et affichage des distances de Cook\ncooksd <- cooks.distance(modelnb)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, color = rgb(0.4,0.4,0.4)) +\n labs(x = \"\", y = \"distance de Cook\")+\n theme(axis.ticks.x = element_blank(),\n axis.text.x = element_blank())\n```\n\nNous observons, dans la @fig-cookdistnb, que quatre observations se distinguent très nettement des autres. \n\n```{r}\n#| message: false\n#| warning: false\ncas_etrange <- subset(data_accidents, cooksd > 0.03)\nprint(cas_etrange)\n```\n\nIl s'agit à nouveau de quatre observations avec un grand nombre d'accidents. Nous décidons de les retirer du jeu de données pour ne pas fausser les résultats concernant l'ensemble des autres intersections. Dans une analyse plus détaillée, il serait judicieux de chercher à comprendre pourquoi ces quatre observations sont particulièrement accidentogènes.\n\n```{r}\n#| label: fig-cookdistnb2\n#| fig-cap: Distances de Cook pour le modèle binomial négatif (après avoir retiré quatre observations fortement influentes\n#| fig-align: center\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n\ndata2 <- subset(data_accidents, cooksd < 0.03)\n# Ajustement d'une première version du modèle\nmodelnb <- gam(Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet + \n Terreplein + Apaisement +\n LogEmploi + Densite_pop + Entropie + DensiteInter +\n Long_arterePS + Artere + NB_voies5,\n family = nb(link=\"log\"),\n data = data2)\n# Calcul et affichage des distances de Cook\ncooksd <- cooks.distance(modelnb)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, color = rgb(0.4,0.4,0.4)) +\n labs(x = \"\", y = \"distance de Cook\")+\n theme(axis.ticks.x = element_blank(),\n axis.text.x = element_blank())\n```\n\nAprès avoir retiré ces quatre observations, les distances de Cook ne révèlent plus d'observations fortement influentes dans le modèle (@fig-cookdistnb2). La prochaine étape du diagnostic est donc d'analyser les résidus simulés.\n\n```{r}\n#| label: fig-diagresnb\n#| fig-cap: Diagnostic général des résidus simulés pour le modèle binomial négatif\n#| fig-align: center\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n\n# Extraction de la valeur de theta\ntheta <- modelnb$family$getTheta(T)\nnsim <- 1000\n# Extraction des valeurs prédites par le modèle\nmus <- predict(modelnb, type = \"response\")\n# Calcul des simulations\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- rnbinom(n = nsim, mu = mu, size = theta)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calcul des résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = data2$Nbr_acci,\n fittedPredictedResponse = mus,\n integerResponse = TRUE)\n# Affichage du diagnostic\nplot(sim_res)\n```\n\nLa @fig-diagresnb présentant le diagnostic des résidus simulés, montre que ces derniers suivent bien une distribution uniforme et aucun problème de dispersion ni de valeurs aberrantes. La @fig-compnbdistr2 permet de comparer la distribution originale de la variable *Y* et les simulations issues du modèle (intervalles de confiance représentés en bleu). Nous constatons que le modèle parvient bien à reproduire la distribution originale, et ce, même pour les valeurs les plus extrèmes de la distribution.\n\n```{r}\n#| label: fig-compnbdistr2\n#| fig-align: center\n#| fig-cap: Comparaison de la distribution originale et des simulations pour le modèle binomial négatif\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n\n# Extraction des valeurs prédites par le modèle\nmus <- predict(modelnb, type = \"response\")\n# Génération de 1000 simulations pour chaque prédiction\ntheta <- modelnb$family$getTheta(T)\nnsim <- 1000\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- round(rnbinom(n = nsim, mu = mu, size = theta))\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Préparation des données pour le graphique (valeurs réelles)\ncounts <- data.frame(table(data2$Nbr_acci))\nnames(counts) <- c(\"nb_accident\",'frequence')\ncounts$nb_accident <- as.numeric(as.character(counts$nb_accident))\ncounts$prop <- counts$frequence / sum(counts$frequence)\n# Préparation des données pour le graphique (valeurs simulées)\ndf1 <- data.frame(count = 0:25)\ncount_sims <- lapply(1:nsim, function(i){\n sim <- mat_sims[,i]\n cnt <- data.frame(table(sim))\n df2 <- merge(df1, cnt, by.x = \"count\", by.y = \"sim\", all.x = TRUE, all.y = FALSE)\n df2$Freq <- ifelse(is.na(df2$Freq),0, df2$Freq)\n return(df2$Freq)\n})\ncount_sims <- do.call(cbind, count_sims)\ndf_sims <- data.frame(\n val = 0:25,\n med = apply(count_sims, MARGIN = 1, median),\n lower = apply(count_sims, MARGIN = 1, quantile, probs = 0.025),\n upper = apply(count_sims, MARGIN = 1, quantile, probs = 0.975)\n)\n# Affichage du graphique\nggplot() + \n geom_bar(aes(x = nb_accident, weight = frequence), width = 0.6, data = counts)+\n geom_errorbar(aes(x = val, ymin = lower, ymax = upper),\n data = df_sims, color = \"blue\", width = 0.6)+\n geom_point(aes(x = val, y = med), color = \"blue\", size = 1.3, data = df_sims)+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n xlim(-1,12)+\n labs(subtitle = \"\",\n x = \"nombre d'accidents\",\n y = \"nombre d'occurrences\")\n```\n\nÀ titre de comparaison, nous pouvons à nouveau réaliser le graphique permettant de visualiser si la variance attendue par le modèle est proche de celle effectivement observée dans les données. Nous avons constaté avec ce graphique, lorsque nous ajustions un modèle de Poisson, que la variance des données était trop grande comparativement à celle attendue par le modèle (@fig-surdisppoiss).\n\n```{r}\n#| label: fig-surdispnb\n#| fig-align: center\n#| fig-cap: Représentation de la sur-dispersion des données dans le modèle de Poisson\n#| out-width: \"65%\"\n#| warning: false\n#| message: false\n# Extraction des prédictions du modèle\nmus <- predict(modelnb, type = \"response\")\n# Création d'un DataFrame pour contenir la prédiction et les vraies valeurs\ndf1 <- data.frame(\n mus = mus,\n reals = data2$Nbr_acci\n)\n# Calcul de l'intervalle de confiance à 95 % selon la distribution de Poisson\n# et stockage dans un second DataFrame\nseqa <- seq(0, round(max(mus)),1)\ndf2 <- data.frame(\n mus = seqa,\n lower = qnbinom(p = 0.025, mu = seqa, size = theta),\n upper = qnbinom(p = 0.975, mu = seqa, size = theta)\n)\n# Affichage des valeurs réelles et prédites (en rouge)\n# et de leur variance selon le modèle (en noir)\nggplot() + \n geom_errorbar(data = df2,\n mapping = aes(x = mus, ymin = lower, ymax = upper),\n width = 0.2, color = rgb(0.4,0.4,0.4)) + \n geom_point(data = df1, \n mapping = aes(x = mus, y = reals),\n color =\"red\", size = 0.5) + \n labs(x = \"valeurs prédites\",\n y = \"valeurs réelles\")\n```\n\nNous pouvons ainsi constater à la @fig-surdispnb que le modèle binomial négatif autorise une variance bien plus large que le modèle de Poisson et est ainsi mieux ajusté aux données.\n\n**Vérification de la qualité d'ajustement**\n\n```{r}\n#| message: false\n#| warning: false\n# Calcul des pseudo R2\nrsqs(loglike.full = logLik(modelnb),\n loglike.null = logLik(modelnull),\n full.deviance = deviance(modelnb),\n null.deviance = modelnb$null.deviance,\n nb.params = modelnb$rank,\n n = nrow(data2))\n# Calcul du RMSE\nsqrt(mean((predict(modelnb, type = \"response\") - data2$Nbr_acci)**2))\n```\n\nLe modèle parvient à expliquer 45 % de la déviance. Il obtient un R^2^ ajusté de McFadden de 0,14 et un R^2^ de Nagelkerke de 0,42. L’erreur moyenne quadratique de la prédiction est de 1,82, ce qui est identique au modèle de Poisson ajusté précédemment.\n\n**Interprétation des résultats**\n\nIl est possible d'accéder à l'ensemble des coefficients du modèle via la fonction `summary`. À nouveau, les coefficients doivent être convertis avec la fonction exponentielle (du fait de la fonction de lien *log*) et interprétés comme des effets multiplicatifs. Le @tbl-coeffsnb présente les coefficients estimés par le modèle. Les résultats sont très similaires à ceux du modèle de quasi-Poisson original. Nous notons cependant que la variable représentant la présence d'un feu pour piéton n'est plus significative au seuil de 0,05.\n\n```{r}\n#| label: tbl-coeffsnb\n#| tbl-cap: Résultats du modèle binomial négatif\n#| message: false\n#| warning: false\n#| echo: false\ntableau <- build_table(modelnb, confid = TRUE, sign = TRUE, coef_digits = 2, std_digits = 2)\nknitr::kable(tableau[, c(1,2,3,6,9,10,11)], \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n \t col.names = c(\"Variable\" , \"Coeff.\", \"exp(Coeff.)\", \"Val.p\", \"IC 2,5 % exp(Coeff.)\", \"IC 97,5 % exp(Coeff.)\", \"Sign.\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\"),\n )\n```\n\n### Modèle de Poisson avec excès fixe de zéros {#sec-0833}\n\nDans le cas où la variable *Y* comprendrait significativement plus de zéros que ce que suppose une distribution de Poisson, il est possible d’utiliser la distribution de Poisson avec excès de zéros. Pour rappel, cette distribution ajoute un paramètre *p* contrôlant pour la proportion de zéros dans la distribution. Du point de vue conceptuel, cela revient à formuler l’hypothèse suivante : dans les données que nous avons observées, deux processus distincts sont à l’œuvre. Le premier est issu d’une distribution de Poisson et l'autre produit des zéros qui s’ajoutent aux données. Les zéros produits par la distribution de Poisson sont appelés les **vrais zéros**, alors que ceux produits par le second phénomène sont appelés les **faux zéros**.\n\n```{r}\n#| label: tbl-poisszidentity\n#| tbl-cap: Carte d'identité du modèle de Poisson avec excès fixe de zéros\n#| echo: false\n#| message: false\n#| warning: false\nmodel_formula <- \"$Y \\\\sim ZIP(\\\\mu,\\\\theta)$ \\\\newline $g(\\\\lambda) = \\\\beta_0 + \\\\beta X$ \\\\newline $g(x) =log(x)$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable de comptage\", \"Poisson avec excès de zéros\", model_formula , \"log\", \"$\\\\lambda$\", \"$\\\\beta_0$, $\\\\beta$ et *p*\", \"Absence de sur-dispersion\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\" \n)\n```\n\nDans cette formulation, *p* est fixé. Nous n’avons donc aucune information sur ce qui produit les zéros supplémentaires, mais seulement leur proportion totale dans le jeu de données.\n\n#### Interprétation des paramètres {#sec-08331}\n\nL’interprétation des paramètres est identique à celle d’un modèle de Poisson. Le paramètre *p* représente la proportion de faux zéros dans la variable *Y* une fois que les variables indépendantes sont contrôlées.\n\n#### Exemple appliqué dans R {#sec-08332}\n\nLa variable de comptage des accidents des piétons que nous avons utilisée dans les deux exemples précédents semble être une bonne candidate pour une distribution de Poisson avec excès de zéros. En effet, nous avons pu constater une sur-dispersion dans le modèle de Poisson original, ainsi qu’un nombre important d’intersections sans accident. Tentons donc d’améliorer notre modèle en ajustant un excès fixe de zéros. Nous utilisons la fonction `gamlss` du *package* `gamlss`.\n\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(gamlss)\nmodelzi <- gamlss(formula = Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet +\n Terreplein + Apaisement + LogEmploi + Densite_pop + \n Entropie + DensiteInter + Long_arterePS + Artere + NB_voies5,\n sigma.formula = ~1,\n family = ZIP(mu.link = \"log\", sigma.link=\"logit\"),\n data = data_accidents)\n\nmodelnull <- glm(formula = Nbr_acci ~ 1,\n family = poisson(link=\"log\"),\n data = data_accidents)\n\n# Constante pour p\ncoeff_p <- modelzi$sigma.coefficients\ncat(\"Coefficient pour p =\", round(coeff_p,4))\n# Calcul de la déviance expliquée\n1 - deviance(modelzi) / deviance(modelnull)\n# Calcul de la probabilité de base p d'être un faux 0\n# en appliquant l'inverse de la fonction logistique\nexp(-coeff_p) / (1+exp(-coeff_p))\n```\n\nNous constatons immédiatement que le modèle avec excès fixe de zéros est peu ajusté aux données. Cette version du modèle ne parvient à capter que 8 % de la déviance, ce qui s’explique facilement, car nous n’avons donné aucune variable au modèle pour distinguer les vrais et les faux zéros. Pour cela, nous devons passer au prochain modèle : Poisson avec excès ajusté de zéros. Notons tout de même que d'après ce modèle, 81 % des observations seraient des faux zéros.\n\n### Modèle de Poisson avec excès ajusté de zéros {#sec-0834}\n\nNous avons vu dans le modèle précédent que l’excès de zéro était conceptualisé comme la combinaison de deux phénomènes, l’un issu d’une distribution de Poisson que nous souhaitons modéliser, et l'autre générant des zéros supplémentaires. Il est possible d’aller plus loin que de simplement contrôler la proportion de zéros supplémentaires en modélisant explicitement ce second processus en ajoutant une deuxième équation au modèle. Cette deuxième équation a pour enjeu de modéliser *p* (la proportion de 0) à l’aide de variables indépendantes, ces dernières pouvant se retrouver dans les deux parties du modèle. L’idée étant que, pour chaque observation, le modèle évalue sa probabilité d’être un faux zéro (partie binomiale), et le nombre attendu d'accidents.\n\n```{r}\n#| label: tbl-poisszadentity\n#| tbl-cap: Carte d'identité du modèle de Poisson avec excès ajusté de zéros\n#| echo: false\n#| message: false\n#| warning: false\nmodel_formula <- \"$Y \\\\sim ZIP(\\\\mu,\\\\theta)$ \\\\newline $g(\\\\mu) = \\\\beta_0 + \\\\beta X$ \\\\newline $s(p) = \\\\alpha_0 + \\\\alpha_X$ \\\\newline $g(x) =log(x)$ \\\\newline $s(x) = log(\\\\frac{x}{1-x})$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable de comptage\", \"Poisson avec excès de zéros\", model_formula , \"log et logistique\", \"$\\\\mu$ et *p*\", \"$\\\\beta_0$, $\\\\beta$, $\\\\alpha_0$ et $\\\\alpha$\", \"Absence de sur-dispersion\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\"\n)\n```\n\n#### Interprétation des paramètres {#sec-08341}\n\nL’interprétation des paramètres $\\beta_0$ et $\\beta$ est identique à celle d’un modèle de Poisson. Les paramètres $\\alpha_0$ et $\\alpha$ sont identiques à ceux d’un modèle binomial. Plus spécifiquement, ces derniers paramètres modélisent la probabilité d’observer des valeurs supérieures à zéro.\n\n#### Exemple appliqué {#sec-08342}\n\nNous avons vu, dans l’exemple précédent, que l’utilisation du modèle avec excès fixe de zéros pour les données d’accident des piétons aux intersections ne donnait pas de résultats satisfaisants. Nous tentons ici d’améliorer le modèle en ajoutant les variables indépendantes significatives du modèle Poisson dans la seconde équation de régression destinée à détecter les faux zéros.\n\n**Vérification des conditions d'application**\n\nPour un modèle de Poisson avec excès de zéros, il n'est pas possible de calculer les distances de Cook. Nous devons donc directement passer à l'analyse des résidus simulés.\n\n```{r}\n#| message: false\n#| warning: false\n# Ajuster une première version du modèle\nmodelza <- gamlss(formula = Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet +\n Terreplein + Apaisement + LogEmploi + Densite_pop + \n Entropie + DensiteInter + Long_arterePS + Artere + NB_voies5,\n sigma.formula = ~1 + Feux_auto + Feux_piet + Densite_pop + NB_voies5,\n family = ZIP(mu.link = \"log\", sigma.link=\"logit\"),\n data = data_accidents)\n\n# Extraire la prédiction des valeurs lambda\nlambdas <- predict(modelza, type = \"response\", what = \"mu\")\n# Extraire la prédiction des valeurs p\nps <- predict(modelza, type = \"response\", what = \"sigma\")\n# Calculer la combinaison de ces deux éléments\npreds <- lambdas * ps\n# Effectuer les 1000 simulations\nnsim <- 1000\ncols <- lapply(1:length(lambdas), function(i){\n lambda <- lambdas[[i]]\n p <- ps[[i]]\n sims <- rZIP(n = nsim, mu = lambda, sigma = p)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = data_accidents$Nbr_acci,\n fittedPredictedResponse = preds,\n integerResponse = TRUE)\n```\n```{r}\n#| message: false\n#| warning: false\n#| eval: false\nplot(sim_res)\n```\n\n```{r}\n#| label: fig-diagzip\n#| fig-align: center\n#| fig-cap: Diagnostic général des résidus simulés du modèle de Poisson avec excès de zéros ajusté\",\n#| out-width: \"65%\"\n#| echo: false\n#| message: false\n#| warning: false\ninvisible(capture.output({\n out <- \"images/Chap08/diagzip.png\"\n png(file = out, res = 300, width = 50, height = 30, units = \"cm\")\n plot(sim_res)\n dev.off()\n}))\nknitr::include_graphics(out, dpi = 300)\n```\n\n\nLa @fig-diagzip indique deux problèmes importants dans le modèle : la présence de valeurs aberrantes ainsi qu'un potentiel problème de dispersion. Nous commençons donc par identifier ces valeurs aberrantes.\n\n```{r}\n#| warning: false\n#| message: false\n# Identification des outliers\nisOutlier <- outliers(sim_res, return = \"logical\", lowerQuantile = 0.001,\n upperQuantile = 0.999)\ncas_etrange <- subset(data_accidents, isOutlier)\nprint(cas_etrange)\n```\n\nNous retirons des données les quelques observations pouvant avoir une trop forte influence sur le modèle. Après réajustement, la @fig-diagzip2 nous informe que nous n'avons plus de valeurs aberrantes restantes ni de fort problème de dispersion. En revanche, le premier quantile des résidus tant à être plus faible que ce que nous aurions pu nous attendre d'une distribution uniforme. Ce constat laisse penser que le modèle a du mal à bien identifier les faux zéros. Ce résultat n'est pas étonnant, car aucune variable n'avait été identifiée à cette fin dans l'article original [@cloutier2014carrefours] qui utilisait un modèle binomial négatif.\n\n```{r}\n#| label: fig-diagzip2\n#| fig-cap: Diagnostic général des résidus simulés du modèle de Poisson avec excès de zéros ajusté (sans valeurs aberrantes)\n#| fig-align: center\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\ndata2 <- subset(data_accidents, isOutlier == FALSE)\n# Ajuster une première version du modèle\nmodelza <- gamlss(formula = Nbr_acci ~ Feux_auto + Feux_piet + Pass_piet +\n Terreplein + Apaisement + LogEmploi + Densite_pop + \n Entropie + DensiteInter + Long_arterePS + Artere + NB_voies5,\n sigma.formula = ~1 + Feux_auto + Feux_piet + Densite_pop + NB_voies5,\n family = ZIP(mu.link = \"log\", sigma.link=\"logit\"),\n data = data2)\n# Extraire la prédiction des valeurs lambda\nlambdas <- predict(modelza, type = \"response\", what = \"mu\")\n# Extraire la prédiction des valeurs p\nps <- predict(modelza, type = \"response\", what = \"sigma\")\n# Calculer la combinaison de ces deux éléments\npreds <- lambdas * ps\n# Effectuer les 1000 simulations\nnsim <- 1000\ncols <- lapply(1:length(lambdas), function(i){\n lambda <- lambdas[[i]]\n p <- ps[[i]]\n sims <- rZIP(n = nsim, mu = lambda, sigma = p)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = data2$Nbr_acci,\n fittedPredictedResponse = preds,\n integerResponse = TRUE)\nplot(sim_res)\n```\n\nNous pouvons une fois encore comparer des simulations issues du modèle et de la distribution originale de la variable *Y*. La @fig-compzipdistr montre clairement que les simulations du modèle (en bleu) sont très éloignées dans la distribution originale (en gris), ce qui remet directement en question la pertinence de ce modèle.\n\n```{r}\n#| label: fig-compzipdistr\n#| fig-align: center\n#| fig-cap: Comparaison de la distribution originale et des simulations pour le modèle de Poisson avec excès de zéros ajusté\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n\n#| # Extraire la prédiction des valeurs lambda\nlambdas <- predict(modelza, type = \"response\", what = \"mu\")\n# Extraire la prédiction des valeurs p\nps <- predict(modelza, type = \"response\", what = \"sigma\")\n# Génération de 1000 simulations pour chaque prédiction\nnsim <- 1000\ncols <- lapply(1:length(lambdas), function(i){\n lambda <- lambdas[[i]]\n p <- ps[[1]]\n sims <- round(rZIP(nsim, mu=lambda, sigma = p))\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Préparation des données pour le graphique (valeurs réelles)\ncounts <- data.frame(table(data2$Nbr_acci))\nnames(counts) <- c(\"nb_accident\",'frequence')\ncounts$nb_accident <- as.numeric(as.character(counts$nb_accident))\ncounts$prop <- counts$frequence / sum(counts$frequence)\n# Préparation des données pour le graphique (valeurs simulées)\ndf1 <- data.frame(count = 0:25)\ncount_sims <- lapply(1:nsim, function(i){\n sim <- mat_sims[,i]\n cnt <- data.frame(table(sim))\n df2 <- merge(df1, cnt, by.x = \"count\", by.y = \"sim\", all.x = TRUE, all.y = FALSE)\n df2$Freq <- ifelse(is.na(df2$Freq),0, df2$Freq)\n return(df2$Freq)\n})\ncount_sims <- do.call(cbind, count_sims)\ndf_sims <- data.frame(\n val = 0:25,\n med = apply(count_sims, MARGIN = 1, median),\n lower = apply(count_sims, MARGIN = 1, quantile, probs = 0.025),\n upper = apply(count_sims, MARGIN = 1, quantile, probs = 0.975)\n)\n# Affichage du graphique\nggplot() + \n geom_bar(aes(x = nb_accident, weight = frequence), width = 0.6, data = counts)+\n geom_errorbar(aes(x = val, ymin = lower, ymax = upper),\n data = df_sims, color = \"blue\", width = 0.6)+\n geom_point(aes(x = val, y = med), color = \"blue\", size = 1.3, data = df_sims)+\n scale_x_continuous(limits = c(-0.5,7), breaks = c(0:7))+\n xlim(-1,12)+\n labs(subtitle = \"\",\n x = \"nombre d'accidents\",\n y = \"nombre d'occurrences\")\n```\n\n**Vérification la qualité d'ajustement**\n\n```{r}\n#| message: false\n#| warning: false\nmodelenull <- glm(Nbr_acci ~ 1,\n family = poisson(link=\"log\"),\n data = data2)\n# Calcul des R2\nrsqs(loglike.full = logLik(modelza),\n loglike.null = logLik(modelenull),\n full.deviance = deviance(modelza),\n null.deviance = deviance(modelenull),\n nb.params = modelza$sigma.df + modelza$mu.df,\n n = nrow(data2)\n )\n# Calcul du RMSE\nsqrt(mean((preds - data2$Nbr_acci)**2))\n```\n\nLe modèle avec excès de zéro ajusté ne parvient à expliquer que 11 % de la déviance totale. Il obtient toutefois des valeurs de R^2^ assez hautes (McFadden ajusté : 0,36, Nagerlkerke : 0,82). Son RMSE est très élevé (2,6), comparativement à celui que nous avons obtenu avec le modèle binomial négatif (1,9). Considérant ces éléments, ce modèle est nettement moins informatif que le modèle binomial négatif et ne devrait pas être retenu. Nous montrons tout de même ici comment interpréter ces résultats.\n\n**Interprétation des résultats**\n\nL'ensemble des coefficients du modèle sont accessibles avec la fonction `summary`. Les coefficients dédiés à la partie Poisson (appelée **Mu** dans le résumé) doivent être analysés et interprétés de la même manière que s'ils provenaient d'un modèle de Poisson. Les coefficients appartenant à la partie logistique (appelé **Sigma** dans le résumé) doivent être analysés et interprétés de la même manière que s'ils provenaient d'un modèle logistique.\n\n```{r}\n#| message: false\n#| warning: false\n# Extraction des résultats\nbase_table <- summary(modelza)\n# Multiplication par 1000 des coefficients de population\n# (effet pour 1000 habitants)\nbase_table[8,1] <- 1000 * base_table[8,1]\nbase_table[8,2] <- 1000 * base_table[8,2]\nbase_table[17,1] <- 1000 * base_table[17,1]\nbase_table[17,2] <- 1000 * base_table[17,2]\n# Multiplication par 1000 des coefficients de longueur artère\n# (effet pour 1 km)\nbase_table[11,1] <- 1000 * base_table[11,1]\nbase_table[11,2] <- 1000 * base_table[11,2]\n# Calcul des exponentiels des variables indépendantes\n# et des intervalles de confiance\nexpcoeff <- exp(base_table[,1])\nexpcoeff2.5 <- exp(base_table[,1] - 1.96 * base_table[,2])\nexpcoeff97.5 <- exp(base_table[,1] + 1.96 * base_table[,2])\nbase_table <- cbind(base_table, expcoeff, expcoeff2.5, expcoeff97.5)\n# Calculer une colonne indiquant le niveau de significativité\nsign <- case_when(\n base_table[,4] < 0.001 ~ \"***\",\n base_table[,4] >= 0.001 & base_table[,4]<0.01 ~ \"**\",\n base_table[,4] >= 0.01 & base_table[,4]<0.05 ~ \"*\",\n base_table[,4] >= 0.05 & base_table[,4]<0.1 ~ \".\",\n TRUE ~ \"\"\n)\n# Arrondir à trois décimales\nbase_table <- round(base_table,3)\n# Enlever les colonnes de valeurs de t et d'erreur standard\nbase_table <- base_table[, c(1,4,5,6,7)]\nbase_table <- cbind(base_table, sign)\n# Remplacer les 0 dans la colonne pval\nbase_table[,2] <- ifelse(base_table[,2]==\"0\" , \"<0.001\",base_table[,2])\n# Séparer le tout en deux tableaux\npart_poiss <- base_table[1:13,]\npart_logit <- base_table[14:18,]\n# Mettre les bons noms de colonnes\ncolnames(part_poiss) <- c(\"Coeff.\" , \"Val.p\" , \"Exp(Coeff.)\",\n \"IC 2,5 % exp(Coeff.)\" , \"IC 97,5 % exp(Coeff.)\", \"Sign.\")\ncolnames(part_logit) <- c(\"Coeff.\" , \"Val.p\" , \"RC\" , \"IC 2,5 % RC\" , \"IC 97,5 % RC\", \"Sign.\")\n```\n\nNous rapportons les résultats de ce modèle de Poisson avec excès de zéro ajusté dans les tableaux [-@tbl-zapoisstab1] et [-@tbl-zapoisstab2].\n\n```{r}\n#| label: tbl-zapoisstab1\n#| tbl-cap: Résultats de la partie Poisson du modèle de Poisson avec excès de zéros ajusté\n#| message: false\n#| warning: false\n#| echo: false\npart_poiss <- cbind(rownames(part_poiss), part_poiss)\nrownames(part_poiss) <- NULL\nknitr::kable(part_poiss, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c('Variable',\"Coeff.\" , \"Val.p\" , \"Exp(Coeff.)\" , \"IC 2,5 % exp(Coeff.)\" , \"IC 97,5 % exp(Coeff.)\", \"Sign.\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n)\n```\n\n```{r}\n#| label: tbl-zapoisstab2\n#| tbl-cap: Résultats de la partie logistique du modèle de Poisson avec excès de zéros ajusté\n#| message: false\n#| warning: false\n#| echo: false\npart_logit <- cbind(rownames(part_logit), part_logit)\nrownames(part_logit) <- NULL\nknitr::kable(part_logit, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c('Variable',\"Coeff.\" , \"Val.p\" , \"RC\" , \"IC 2,5 % RC\" , \"IC 97,5 % RC\", \"Sign.\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n)\n```\n\nNous observons ainsi que la présence d’un feu de circulation divise par 5 les chances de rentrer dans la catégorie d'intersection où des accidents peuvent se produire. De même, la densité de population réduit les chances de passer dans cette catégorie de 11 %.\n\nConcernant les coefficients pour la partie Poisson du modèle, nous observons que les présences d’un feu de circulation et d’un feu pour piéton contribuent à multiplier respectivement par 2 et 1,5 le nombre attendu d’accidents à une intersection. De même, la présence d’un axe de circulation à cinq voies augmente de 57 % le nombre d’accidents. Enfin, la densité de population est aussi associée à une augmentation du nombre d’accidents : pour 1 000 habitants supplémentaires autour de l'intersection, nous augmentons le nombre d'accidents attendu de 9 %.\n\n### Conclusion sur les modèles destinés à des variables de comptage {#sec-0835}\n\nDans cette section, nous avons vu que modéliser une variable de comptage ne doit pas toujours être réalisé avec une simple distribution de Poisson. Il est nécessaire de tenir compte de la sur ou sous-dispersion potentielle ainsi que de l’excès de zéros. Nous n’avons cependant pas couvert tous les cas. Il est en effet possible d’ajuster des modèles avec une distribution binomiale négative avec excès de zéros (avec le *package* `gamlss`), ainsi que des modèles de **Hurdle**. Ces derniers ont une approche différente de celle proposée par les distributions ajustées pour tenir compte de l’excès de zéro que nous détaillons dans l’encadré « pour aller plus loin » ci-dessous. Le processus de sélection du modèle peut être résumé avec la @fig-poisswork. Notez que même en suivant cette procédure, rien ne garantit que votre modèle final reflète bien les données que vous étudiez. L’analyse approfondie des résidus et des prédictions du modèle est la seule façon de déterminer si oui ou non le modèle est fiable.\n\n\n![Processus de sélection d'un modèle pour une variable de comptage](images/Chap08/poisson_workflow.png){#fig-poisswork width=\"80%\" fig-align=\"center\"}\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Modèle de Hurdle *versus* modèle avec excès de zéro**\n:::\n::: bloc_aller_loin-body\nLes modèles de Hurdle sont une autre catégorie de modèles GLM. Ils peuvent être décrits avec la formulation suivante : \n\n$$\n\\left\\{\\begin{array}{c}\nY \\sim \\text {Binomial}(p) \\text { si } y = 0 \\\\\n\\text { logit }(p)=\\beta_{a} X_{a} \\\\\nY \\sim \\text { TrPoisson}(\\lambda) \\text { si } y>0 \\\\\n\\log (\\lambda)=\\beta_{b} X_{b}\n\\end{array}\\right.\n$$ {#eq-glmHurdle}\n\nNous constatons qu’un modèle de Hurdle utilise deux distributions, la première est une distribution binomiale dont l’objectif est de prédire si les observations sont à 0 ou au-dessus de 0. La seconde est une distribution strictement positive (supérieure à 0), il peut s’agir d’une distribution tronquée de Poisson, tronquée binomiale négative, Gamma, log-normale ou autre, dépendamment du phénomène modélisé. Puisque le modèle fait appel à deux distributions, deux équations de régression sont utilisées, l’une pour prédire *p* (la probabilité d’observer une valeur au-dessus de 0) et l'autre l’espérance (moyenne) de la seconde distribution. \n\nEn d’autres termes, un modèle de Hurdle modélise les données à zéro et les données au-delà de 0 comme deux processus différents (chacun avec sa propre distribution). Cette approche se distingue des modèles avec excès de zéros qui utilisent une seule distribution pour décrire l’ensemble des données. D’après un modèle avec excès de zéro, il existe de vrais et de faux zéros que l’on tente de distinguer. Dans un modèle de Hurdle, l’idée est que les zéros constituent une limite. Nous modélisons la probabilité de dépasser cette limite et ensuite la magnitude du dépassement de cette limite.\n\nPrenons un exemple pour rendre la distinction plus concrète. Admettons que nous utilisons un capteur capable de mesurer la concentration de particules fines dans l’air. D’après les spécifications du fabricant, le capteur est capable de mesurer des taux de concentration à partir de 0,001 µg/m^3^. Dans une ville avec des niveaux de concentration très faibles, il est très fréquent que le capteur enregistre des valeurs à zéro. Considérant ce phénomène, il serait judicieux de modéliser le processus avec un modèle de Hurdle Gamma puisque les 0 représentent une limite qui n’a pas été franchie : le seuil de détection du capteur. Nous traitons donc différemment les secteurs au-dessous et au-dessus de ce seuil. Si nous reprenons notre exemple sur les accidents des piétons à des intersections, il est plus judicieux, dans ce cas, de modéliser le phénomène avec un modèle avec excès de zéro puisque nous pouvons observer zéro accident à une intersection dangereuse (vrai zéro) et zéro accident à une intersection sur laquelle aucun piéton ne traverse jamais (faux zéro).\n:::\n:::\n\n## Modèles GLM pour des variables continues {#sec-084}\n\nComme nous l'avons vu dans la [section @sec-024], il existe un grand nombre de distributions permettant de décrire une grande diversité de variables continues. Il serait fastidieux de toutes les présenter, nous revenons donc seulement sur les plus fréquentes.\n\n### Modèle GLM gaussien {#sec-0841}\n\nComme nous l'avons vu en introduction, le modèle GLM gaussien est le plus simple puisqu'il correspond à la transposition de la régression linéaire classique (des moindres carrés) dans la forme des modèles généralisés.\n\n```{r}\n#| label: tbl-gaussiandentity\n#| tbl-cap: Carte d'identité du modèle gaussien\n#| echo: false\n#| message: false\n#| warning: false\nmodel_formula <- \"$Y \\\\sim Normal(\\\\mu,\\\\sigma)$ \\\\newline $g(\\\\mu) = \\\\beta_0 + \\\\beta X$ \\\\newline $g(x) = x$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable continue dans l'intervalle $]-\\\\infty ; + \\\\infty[$\", \"Normale\", model_formula , \"Identitaire\", \"$\\\\mu$\", \"$\\\\beta_0$, $\\\\beta$ et $\\\\sigma$\", \"Homoscédasticité\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\"\n)\n```\n\n#### Conditions d'application {#sec-08411}\n\nLes conditions d'application sont les mêmes que celles d'une régression linéaire classique. La condition de l'homoscédasticité (homogénéité de la variance) est due au fait que la variance du modèle est contrôlée par un seul paramètre fixe $var(y) = \\sigma$ (l'écart-type de la distribution normale). À titre de comparaison, rappelons que dans un modèle de Poisson, la variance est égale à la moyenne ($var(y) = E(y)$) alors que dans un modèle binomial négatif, la variance est fonction de la moyenne et d'un paramètre $\\theta$ ($var(y) = E(y) + E(y)^{\\frac{2}{\\theta}}$). Pour ces deux exemples, la variance augmente au fur et à mesure que la moyenne augmente.\n\n#### Interprétation des paramètres {#sec-08412}\n\nL'interprétation des paramètres est la même que pour une régression linéaire classique : \n\n* $\\beta_0$ : la constante, soit la moyenne attendue de la variable *Y* lorsque les valeurs de toutes les variables *X* sont 0.\n\n* $\\beta$ : les coefficients de régression qui quantifient l'effet d’une augmentation d’une unité des variables *X* sur la moyenne de la variable *Y*.\n\n* $\\sigma$ : l’écart-type de *Y* après avoir contrôlé les variables *X*. Il peut s’interpréter comme l’incertitude restante après modélisation de la moyenne de *Y*. Concrètement, si vous utilisez votre équation de régression pour prédire une nouvelle valeur de *Y* : $\\hat{Y}$, l’intervalle de confiance à 95 % de cette prédiction est ($\\hat{Y} - 3\\sigma\\text{ ; }\\hat{Y} + 3\\sigma$). Vous noterez donc que plus $\\sigma$ est grand, plus grande est l'incertitude de la prédiction.\n\n#### Exemple appliqué dans R {#sec-08413}\n\nPour cet exemple, nous reprenons le modèle LM que nous avons présenté dans la [section @sec-077]. À titre de rappel, l'objectif est de modéliser la densité végétale dans les secteurs de recensement de Montréal. Pour cela, nous utilisons des variables relatives aux populations vulnérables physiologiquement ou socioéconomiquement, tout en contrôlant l'effet de la forme urbaine. Parmi ces dernières, l'âge médian des bâtiments est ajouté au modèle avec une polynomiale d'ordre deux, et la densité d'habitants est transformée avec la fonction logarithmique.\n\n**Vérification des conditions d'application**\n\nLa première étape de la vérification des conditions d'application est bien sûr de s'assurer de l'absence de multicolinéarité excessive. \n\n```{r}\n#| message: false\n#| warning: false\n# Chargement des données\nload(\"data/lm/DataVegetation.RData\")\n# Calcul du VIF\nlibrary(car)\nvif(glm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal))\n```\n\nPuisque l'ensemble des valeurs de VIF sont inférieures à deux, nos données ne sont pas marquées par une multicolinéarité problématique. La seconde étape du diagnostic consiste à calculer et à afficher les distances de Cook.\n\n```{r}\n#| label: fig-gausscook\n#| fig-align: center\n#| fig-cap: Distances de Cook pour le modèle gaussien\n#| out-width: \"65%\"\n#| echo: false\n#| message: false\n#| warning: false\n\n# Ajustement du modèle\nmodele <- glm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)\n# Calcul des distances de Cook\ncooksd <- cooks.distance(modele)\n# Affichage des valeurs\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\n\nggplot(data = df) + \n geom_point(aes(x = oid, y = cook), color = rgb(0.4,0.4,0.4,0.7), size = 1) + \n labs(x = \"\", y = \"distance de Cook\")\n```\n\nLa @fig-gausscook indique clairement que quatre observations sont très influentes dans le modèle. \n\n```{r}\n#| message: false\n#| warning: false\n# Sélection des cas étranges\ncas_etranges <- subset(DataFinal, cooksd > 0.03)\nprint(cas_etranges)\n```\n\nIl s'agit de quatre îlots dans Montréal avec des logements très anciens : plus de 200 ans, alors que la moyenne est de 52 ans pour le reste de la zone d'étude. Le fait que nous ayons dans le modèle une polynomiale d'ordre 2 pour cette variable intensifie l'influence de ces valeurs extrêmes. Par conséquent, nous décidons de simplement les supprimer. Nous verrons plus tard qu'une alternative envisageable est de changer la distribution du modèle pour une distribution de Student (plus robuste aux valeurs extrêmes).\n\n```{r}\n#| message: false\n#| warning: false\n#| echo: false\n#| label: fig-gausscook2\n#| fig-align: center\n#| fig-cap: Distances de Cook pour le modèle gaussien après suppression des observations influentes\n#| out-width: \"65%\"\n\n# Retirer les cas étranges\nDataFinal2 <- subset(DataFinal, cooksd < 0.03)\n# Ajustement du modèle\nmodele <- glm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal2, \n family = gaussian())\n# Calcul des distances de Cook\ncooksd <- cooks.distance(modele)\n# Affichage des valeurs de Cook\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\n\nggplot(data = df) + \n geom_point(aes(x = oid, y = cook), color = rgb(0.4,0.4,0.4,0.7), size = 1) + \n labs(x = \"\", y = \"distance de Cook\")\n```\n\nUne fois ces observations retirées, les nouvelles distances de Cook ne révèlent plus d'observations fortement influentes (@fig-gausscook2). Nous pouvons passer à l'analyse des résidus simulés. La @fig-gaussresid démontre que la distribution des résidus est significativement différente d'une distribution uniforme, que des valeurs aberrantes sont encore présentes et qu'il existe un lien entre résidus et prédiction dans le modèle.\n\n```{r}\n#| message: false\n#| warning: false\n#| label: fig-gaussresid\n#| fig-align: center\n#| fig-cap: Diagnostic général des résidus simulés pour le modèle gaussien\n#| out-width: \"65%\"\n# Extraction des prédictions du modèle\nmus <- predict(modele, type = 'response')\nmodsigma <- sigma(modele)\n# Extraction de l'écart type du modèle\n# Génération de 1000 simulations pour chaque prédiction\nnsim <- 1000\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- rnorm(nsim, mean=mu, sd = modsigma)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = DataFinal2$VegPct,\n fittedPredictedResponse = mus,\n integerResponse = FALSE)\nplot(sim_res)\n```\n\nPour mieux cerner ce problème, nous pouvons, dans un premier temps, comparer la distribution originale des données et les simulations issues du modèle. La @fig-gausssim montre clairement que la distribution normale est mal ajustée aux données. Ces dernières sont légèrement asymétriques et ne peuvent pas être inférieures à zéro, ce que la distribution normale ne parvient pas à reproduire.\n\n```{r}\n#| message: false\n#| warning: false\n#| label: fig-gausssim\n#| fig-align: center\n#| fig-cap: Comparaison de la distribution originale de la variable et des simulations issues du modèle\n#| out-width: \"65%\"\ndf <- reshape2::melt(mat_sims[,1:30])\nggplot() + \n geom_histogram(data = DataFinal2, mapping = aes(x = VegPct, y = ..density..),\n color = \"black\", fill = \"white\", bins = 50)+\n geom_density(data = df, aes(x = value, group = Var2), \n color = rgb(0.4,0.4,0.4,0.4), fill = rgb(0,0,0,0))+\n labs(x = \"Pourcentage de végétation dans l'îlot (%)\",\n y = \"Densité\")\n```\n\nIl est également possible de vérifier si la condition d'homogénéité de la variance s'applique bien aux données.\n\n```{r}\n#| label: fig-gausssim2\n#| fig-align: center\n#| fig-cap: Comparaison de la distribution originale de la variable et des simulations issues du modèle\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n\n# Extraction des prédictions du modèle\nmus <- predict(modele, type = \"response\")\nsigma_model <- sigma(modele)\n# Création d'un DataFrame pour contenir les prédictions et les vraies valeurs\ndf1 <- data.frame(\n mus = mus,\n reals = DataFinal2$VegPct\n)\n# Calcul de l'intervalle de confiance à 95 % selon la distribution normale\n# et stockage dans un second DataFrame\nseqa <- seq(0,100,10)\ndf2 <- data.frame(\n mus = seqa,\n lower = qnorm(p = 0.025, mean = seqa, sd = sigma_model),\n upper = qnorm(p = 0.975, mean = seqa, sd = sigma_model)\n)\n\n# Affichage des valeurs réelles et prédites (en rouge)\n# et de leur variance selon le modèle (en noir)\nggplot() + \n geom_point(data = df1, \n mapping = aes(x = mus, y = reals),\n color =\"red\", size = 0.5) + \n geom_errorbar(data = df2,\n mapping = aes(x = mus, ymin = lower, ymax = upper),\n width = 0.2, color = rgb(0.4,0.4,0.4)) + \n labs(x = \"valeurs prédites\",\n y = \"valeurs réelles\")\n```\n\nÀ nouveau, nous constatons à la @fig-gausssim2 que le modèle s'attend à trouver des valeurs négatives pour la concentration de végétation, ce qui n'est pas possible dans notre cas. En revanche, il semble que la variance soit bien homogène puisque la dispersion des observations semble suivre à peu près la dispersion attendue par le modèle (en noir).\n\nMalgré ces différents constats indiquant clairement qu'un modèle gaussien est un choix sous-optimal pour ces données, nous poursuivons l'analyse de ce modèle.\n\n**Vérification de la qualité d'ajustement**\n\n```{r}\n#| warning: false\n#| message: false\n# Ajustement d'un modèle nul\nmodelenull <- glm(VegPct ~ 1,\n data = DataFinal2, \n family = gaussian())\n# Calcul des pseudo R2\nrsqs(loglike.full = logLik(modele),\n loglike.null = logLik(modelenull),\n full.deviance = deviance(modele),\n null.deviance = deviance(modelenull), \n nb.params = modele$rank,\n n = nrow(DataFinal2)\n )\n```\n\nLe modèle parvient à expliquer 47 % de la déviance totale, mais obtient un R^2^ ajusté de McFadden de seulement 0,07.\n\n```{r}\n#| warning: false\n#| message: false\n# Calcul du RMSE\nsqrt(mean((predict(modele, type = \"response\") - DataFinal2$VegPct)**2))\n```\n\nL'erreur quadratique moyenne et de 13,5 points de pourcentage, ce qui indique que le modèle a une assez faible capacité prédictive.\n\n**Interprétation des résultats**\n\nL'ensemble des coefficients du modèle sont accessibles via la fonction `summary`; le @tbl-tableaugauss présente les résultats pour les coefficients du modèle.\n\n```{r}\n#| label: tbl-tableaugauss\n#| tbl-cap: Résultats du modèle gaussien\n#| warning: false\n#| message: false\n#| echo: false\n# Afficher le tableau\ntab <- build_table(modele, coef_digits = 3, p_digits = 3)\nknitr::kable(tab, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c('Variable',\"Coeff.\" , \"Err.std\" , \"Val.z\", \"val.p\" , \"IC coeff 2,5 %\", \"IC coeff 97,5 %\", \"Sign.\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n)\n```\n\nLes résultats de la régression linéaire multiple ont déjà été interprétés dans la [section @sec-0771], nous ne commenterons pas ici les résultats du modèle GLM gaussien qui sont identiques.\n\n\n### Modèle GLM avec une distribution de Student {#sec-0842}\n\nPour rappel, la distribution de Student ressemble à une distribution normale ([section @sec-024311]). Elle est symétrique autour de sa moyenne et a également une forme de cloche. Cependant, elle dispose de queues lourdes, ce qui signifie qu’elle permet de représenter des phénomènes présentant davantage de valeurs extrêmes qu’une distribution normale. Pour contrôler le poids des queues, la distribution de Student intègre un troisième paramètre : $\\nu$ (nu). Lorsque $\\nu$ tends vers l’infini, la distribution de Student tend vers une distribution normale (@fig-studentdistrib).\n\n```{r}\n#| label: fig-studentdistrib\n#| fig-cap: Effet du paramètre nu sur une distribution de Student\n#| fig-align: center\n#| out-width: \"65%\"\n#| echo: false\n#| message: false\n#| warning: false\n\nlibrary(LaplacesDemon)\nlibrary(ggplot2)\ncolors <- c(\"#03071e\" , \"#6a040f\" , \"#f48c06\", \"#0096c7\")\nlabels_col <- c(\"nu=2\" , \"nu=5\" , \"nu=30\" , \"normal\")\nggplot() + \n stat_function(aes(color = colors[[1]]), linewidth = 1,\n fun = dst, args = list(\"mu\"=0,\n \"sigma\"=10,\n \"nu\"=2)) +\n stat_function(aes(color = colors[[2]]), linewidth = 1,\n fun = dst, args = list(\"mu\"=0,\n \"sigma\"=10,\n \"nu\"=5)) +\n stat_function(aes(color = colors[[3]]), linewidth = 1,\n fun = dst, args = list(\"mu\"=0,\n \"sigma\"=10,\n \"nu\"=30)) +\n stat_function(aes(color = colors[[4]]), linewidth = 1,\n fun = dnorm, args = list(\"mean\"=0,\n \"sd\"=10)) +\n scale_color_identity(name = \"Paramètres\",\n breaks = colors,\n labels = labels_col,\n guide = \"legend\") + \n theme(axis.title.y = element_blank(),\n axis.ticks.y = element_blank(),\n axis.text.y = element_blank(),\n panel.background = element_blank(),\n panel.grid = element_blank()) +\n xlim(-50,50) + \n ylim(0,0.05)\n```\n\nComme vous pouvez le constater dans la carte d'identité au @tbl-studentdentity, le modèle GLM de Student est très proche du modèle GLM gaussien. Nous modélisons explicitement la moyenne de la distribution et son paramètre de dispersion (variance) est laissé fixe. Ce GLM est même souvent utilisé comme une version « robuste » du modèle gaussien du fait de sa capacité à intégrer explicitement l’effet des observations extrêmes. En effet, dans un modèle gaussien, les observations extrêmes (aussi appelées observations aberrantes) vont davantage influencer les paramètres du modèle que pour un modèle utilisant une distribution de Student.\n\n```{r}\n#| label: tbl-studentdentity\n#| tbl-cap: Carte d'identité du modèle de Student\n#| echo: false\n#| message: false\n#| warning: false\n#| out-width: \"50%\"\nmodel_formula <- \"$Y \\\\sim Student(\\\\mu,\\\\sigma,\\\\nu)$ \\\\newline $g(\\\\mu) = \\\\beta_0 + \\\\beta X$ \\\\newline $g(x) = x$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable continue dans l'intervalle $]-\\\\infty ; + \\\\infty[$\", \"Student\", model_formula , \"Identitaire\", \"$\\\\mu$\", \"$\\\\beta_0$, $\\\\beta$, $\\\\sigma$ et $\\\\nu$\", \"Homoscédasticité\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\"\n)\n```\n\n#### Conditions d'application {#sec-08421}\n\nLes conditions d’application sont les mêmes que pour un modèle GLM gaussien, à ceci prêt que le modèle utilisant la distribution de Student est moins sensible aux observations extrêmes.\n\n#### Interprétation des paramètres {#sec-08422}\n\nL’interprétation des paramètres est la même que pour un modèle gaussien puisque nous modélisons la moyenne de la distribution et que la fonction de lien est la fonction identitaire. Le seul paramètre supplémentaire est $\\nu$, qui n’a en soit aucune interprétation pratique. Notez simplement que si $\\nu$ est supérieur à 30, un simple modèle GLM gaussien serait sûrement suffisant.\n\n#### Exemple appliqué dans R {#sec-08423}\n\nNous proposons ici de simplement réajuster le modèle gaussien présenté dans la section précédente en utilisant une distribution de Student. Nous utilisons pour cela la fonction `gam` du *package* `mgcv` avec le paramètre `family = scat` pour utiliser une distribution de Student. Les valeurs de VIF ont déjà été calculées dans l'exemple précédent, nous pouvons donc passer directement au calcul des distances de Cook.\n\n```{r}\n#| label: fig-stucookdist\n#| fig-align: center\n#| fig-cap: Distances de Cook pour un modèle GLM avec une distribution de Student\n#| out-width: \"50%\"\n#| message: false\n#| warning: false\n\n# Chargement des données\nload(\"data/lm/DataVegetation.RData\")\n# Ajustement du modèle\nmodele <- gam(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal,\n family = scat)\n\n# Calcul des distances de Cook\ncooksd <- cooks.distance(modele)\n# Affichage des valeurs\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df) + \n geom_point(aes(x = oid, y = cook), color = rgb(0.4,0.4,0.4,0.7), size = 1) + \n labs(x = \"\", y = \"distance de Cook\")\n```\n\nNous retrouvons les quatre observations avec des distances de Cook très fortes que nous avons identifiées dans le modèle gaussien. Nous décidons donc de les enlever pour les mêmes raisons que précédemment.\n\n```{r}\n#| label: fig-stucookdist2\n#| fig-align: center\n#| fig-cap: Distances de Cook pour un modèle GLM avec une distribution de Student après suppression des valeurs fortement influentes\n#| out-width: \"50%\"\n#| warning: false\n#| message: false\n# Chargement des données\nDataFinal2 <- subset(DataFinal, cooksd<0.1)\n# Ajustement du modèle\nmodele <- gam(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal2,\n family = scat)\n\n# Calcul des distances de Cook\ncooksd <- cooks.distance(modele)\n# Affichage des valeurs\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\nggplot(data = df) + \n geom_point(aes(x = oid, y = cook), color = rgb(0.4,0.4,0.4,0.7), size = 1) + \n labs(x = \"\", y = \"distance de Cook\")\n```\n\n\nNous pouvons à présent vérifier si les résidus simulés se comportent tel qu'attendu.\n\n```{r}\n#| message: false\n#| warning: false\n#| label: fig-studentresid\n#| fig-align: center\n#| fig-cap: Diagnostic général des résidus simulés pour le GLM avec distribution de Student\n#| out-width: \"65%\"\n# Extraction des prédictions du modèle\nmus <- predict(modele, type = 'response')\n# Affichage des paramètres nu et sigma\nmodele$family$family\nsigma_model <- 11.281\nnu_model <- 6.333\nlibrary(LaplacesDemon) # pour simuler des données d'une distribution de Student\n# Génération de 1000 simulations pour chaque prédiction\nnsim <- 1000\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- rst(nsim, mu=mu, sigma = sigma_model, nu = nu_model)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calculer les résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = DataFinal2$VegPct,\n fittedPredictedResponse = mus,\n integerResponse = FALSE)\nplot(sim_res)\n```\n\nIl semble que nous obtenons des résultats similaires à ceux du modèle gaussien: les résidus divergent significativement d'une distribution uniforme (@fig-studentresid). Le graphique quantile-quantile n'est parfois pas très adapté pour discerner une déviation de la distribution uniforme, nous pouvons dans ce cas afficher un histogramme des résidus pour en avoir le coeur net (@fig-studentresid2).\n\n```{r}\n#| message: false\n#| warning: false\n#| label: fig-studentresid2\n#| fig-align: center\n#| fig-cap: Distribution des résidus simulés du modèle GLM avec distribution de Student\n#| out-width: \"60%\"\nggplot()+\n geom_histogram(aes(x = residuals(sim_res)), bins = 50, color = \"white\") + \n labs(x = \"effectifs\", y = \"résidus simulés\")\n```\n\nPour cet exercice, il est intéressant de comparer les formes des simulations issues du modèle gaussien et du modèle de Student pour bien distinguer la différence entre les deux.\n\n```{r}\n#| message: false\n#| warning: false\n#| label: fig-studentresid3\n#| fig-align: center\n#| fig-cap: Simulations issues des modèles gaussien et de Student, comparées aux données originales\n#| echo: false\n#| out-width: \"60%\"\n# Formattage des simulations Students\ndf1 <- reshape2::melt(mat_sims[,1:20])\n# Simulation pour un modèle gaussien\nmodeleGau <- glm(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal2)\nsigma2 <- sigma(modeleGau)\nmus <- predict(modeleGau, type = 'response')\nnsim <- 1000\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- rnorm(nsim, mean=mu, sd = sigma2)\n return(sims)\n})\nmat_sims2 <- do.call(rbind, cols)\ndf2 <- reshape2::melt(mat_sims2[,1:20])\nP1 <- ggplot()+\n geom_histogram(data = DataFinal2, mapping = aes(x = VegPct, y = ..density..), color = \"white\", bins = 50) + \n geom_density(data = df1, aes(x = value, group = Var2), color = rgb(0.9,0.22,0.27,0.4)) + \n labs(x = \"Densité de végétation\",\n y = \"\",\n subtitle = \"Simulations du modèle Student\")+\n xlim(-10,110) + \n ylim(0,0.023) +\n theme(axis.text.y = element_blank(),\n axis.ticks.y = element_blank())\nP2 <- ggplot()+\n geom_histogram(data = DataFinal2, mapping = aes(x = VegPct, y = ..density..), color = \"white\", bins = 50) + \n geom_density(data = df2, aes(x = value, group = Var2), color = rgb(0.11,0.21,0.34,0.4)) + \n labs(x = \"Densité de végétation\",\n y = \"\",\n subtitle = \"Simulations du modèle gaussien\")+\n xlim(-10,110) + \n ylim(0,0.023) +\n theme(axis.text.y = element_blank(),\n axis.ticks.y = element_blank())\n \nggarrange(P1, P2, ncol = 2, nrow = 1)\n```\n\nNous constatons ainsi que la différence entre les deux modèles est ici très mince, voire inexistante. Le seul élément que nous pouvons noter est que le modèle de Student à une courbe (une queue de distribution) moins aplatie vers la droite. Cela lui permettrait de mieux tenir compte de cas extrêmes avec de fortes densités de végétation (ce qui concerne donc très peu d'observations puisque cette variable a un maximum de 100).\n\nPour déterminer si le modèle de Student est plus pertinent à retenir que le modèle gaussien, nous pouvons ajuster un second modèle de Student pour lequel nous forçons artificiellement $\\nu$ à être très élevé. Pour rappel, quand $\\nu$ tend vers l'infini, la distribution de Student tend vers une distribution normale. Nous forçons ici $\\nu$ à être supérieur à 100 pour créer un second modèle de Student se comportant quasiment comme un modèle gaussien et calculons les AIC des deux modèles.\n\n```{r}\n#| message: false\n#| warning: false\n# Calcul d'un modèle de Student identique à un modèle gaussien\nmodele2 <- gam(VegPct ~ log(HABHA)+poly(AgeMedian,2)+\n Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal2,\n family = scat(min.df = 100))\n# Calcul des deux AIC\nAIC(modele)\nAIC(modele2)\n```\n\nLe second AIC (modèle gaussien) est plus élevé, indiquant que le modèle est moins bien ajusté aux données. Dans le cas présent, il est plus pertinent de retenir le modèle de Student même si les écarts entre ces deux modèles sont minimes. Ce résultat n'est pas surprenant puisque la variable *Y* (pourcentage de végétation dans les îlots de l'île de Montréal) est relativement compacte et comporte peu / pas de valeurs pouvant être qualifiées de valeurs extrêmes.\n\nNous ne détaillons pas ici l'interprétation des coefficients du modèle (présentés au @tbl-glmstudentres) puisqu'ils s'interprètent de la même façon qu'un modèle GLM et qu'un modèle de régression linéaire multiple.\n\n```{r}\n#| label: tbl-glmstudentres\n#| tbl-cap: Résultats du modèle Student\n#| warning: false\n#| message: false\n#| echo: false\n# Afficher le tableau\ntab <- build_table(modele, coef_digits = 3, p_digits = 3)\nknitr::kable(tab, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c('Variable',\"Coeff.\" , \"Err.std\" , \"Val.z\", \"val.p\" , \"IC coeff 2,5 %\", \"IC coeff 97,5 %\", \"Sign.\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n)\n```\n\n### Modèle GLM avec distribution Gamma {#sec-0843}\n\nPour rappel, la distribution Gamma est strictement positive ($[0;+\\infty[$), asymétrique, et a une variance proportionnelle à sa moyenne (hétéroscedastique). Dans la section sur les distributions, nous avons vu que la distribution Gamma ([section @sec-024315]) est formulée avec deux paramètres : sa forme ($\\alpha$ ou *shape*) et son échelle ($b$ ou *scale*). Ces deux paramètres n’ont pas une interprétation intuitive, mais il est possible avec un peu de jonglage mathématique d’arriver à une reparamétrisation intéressante. Cela est détaillé dans l'encadré ci-dessous; notez toutefois qu'il n'est pas nécessaire de maîtriser le contenu de cet encadré pour lire la suite de cette section sur les modèles GLM avec une distribution Gamma.\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Reparamétrisation d'une distribution Gamma pour un GLM**\n:::\n::: bloc_aller_loin-body\nSi nous disposons d’une variable *Y*, suivant une distribution Gamma telle que $Y \\sim Gamma(\\alpha,b)$ avec $\\alpha$ le paramètre de forme et $b$ le paramètre d’échelle, alors, l'espérance et la variance de *Y* peuvent être définies comme suit : \n\n$$\n\\begin{aligned}\n&E(Y) = \\alpha \\times b \\\\\n&Var(Y) = \\alpha \\times b^2\\\\\n\\end{aligned}\n$$ {#eq-glm18}\n\nEn d’autres termes, l’espérance (l’équivalent de la moyenne pour une distribution normale) de notre variable *Y* est égale au produit des paramètres de forme et d’échelle.\n\nAvec ces propriétés, il est possible de redéfinir la fonction de densité de la distribution Gamma et d’arriver à une nouvelle formulation : $Y \\sim Gamma(\\mu,\\alpha)$. $\\mu$ est donc l'espérance de *Y* (interprétable comme sa moyenne, soit sa valeur attendue) et $\\alpha$ permet de capturer la dispersion de la distribution Gamma. Par extension des relations présentées ci-dessus, il est possible de reformuler la variance en fonction de $\\mu$ et de $\\alpha$.\n\n$$\n\\begin{aligned}\n&Var(Y) = \\alpha \\times b^2\\\\\n&\\mu = \\alpha \\times b \\text{ soit }b = \\frac{\\mu}{a}\\\\\n&Var(Y) = \\alpha \\times (\\frac{\\mu}{\\alpha})^2 \\text{ soit } Var(Y) = \\frac{\\mu^2}{\\alpha}\\\\\n\\end{aligned}\n$$ {#eq-glm19}\n\nNous observons donc que la variance dans un modèle Gamma augmente de façon quadratique avec la moyenne, mais est tempérée par le paramètre de forme. Nous en concluons qu'un paramètre de forme plus grand produit une distribution moins étalée.\n\nDans ce contexte, $\\mu$ doit être strictement positif : la valeur attendue moyenne d'une distribution Gamma doit être positive par définition puisqu'une distribution Gamma ne peut pas produire de valeurs négatives. Il est donc logique d’utiliser la fonction logarithmique comme fonction de lien, puisque sa contrepartie (la fonction exponentielle) ne produit que des résultats positifs.\n:::\n:::\n\nPour résumer, nous nous retrouvons donc avec un modèle qui prédit, sur une échelle logarithmique, l'espérance (~moyenne) d’une distribution Gamma. Notez qu’il existe d’autres façons de spécifier un modèle GLM avec une distribution Gamma, mais celle-ci est la plus intuitive.\n\n```{r}\n#| label: tbl-gammadentity\n#| tbl-cap: Carte d'identité du modèle Gamma\n#| echo: false\n#| message: false\n#| warning: false\nmodel_formula <- \"$Y \\\\sim Gamma(\\\\mu,\\\\alpha)$ \\\\newline $g(\\\\mu) = \\\\beta_0 + \\\\beta X$ \\\\newline $g(x) = log(x)$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable continue dans l'intervalle $]0 ; + \\\\infty[$\", \"Gamma\", model_formula , \"log\", \"$\\\\mu$\", \"$\\\\beta_0$, $\\\\beta$, et $\\\\alpha$\", \"$Variance = \\\\frac{\\\\mu^2}{\\\\alpha}$\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\"\n)\n```\n\n#### Interprétation des paramètres {#sec-08431}\n\nPuisque le modèle utilise la fonction de lien *log*, alors les coefficients $\\beta$ expriment l’augmentation de l’espérance (la valeur attendue de *Y*, ce qui est proche de l'idée de moyenne) de la variable Y sur une échelle logarithmique (comme dans un modèle de Poisson). Il est possible de convertir les coefficients dans l’échelle originale de la variable *Y* en utilisant la fonction exponentielle (l’inverse de la fonction *log*), mais ces coefficients représentent alors des effets multiplicatifs et non des effets additifs.\nPrenons un exemple, admettons que le coefficient $\\beta_1$, associé à la variable $X_1$ soit de 1,5. Cela signifie qu’une augmentation d’une unité de $X_1$, augmente le log de l'espérance de *Y* de 1,5 unité. L’exponentielle du coefficient est 4,48, ce qui signifie qu’une augmentation d’une unité entraîne une multiplication par 4,48 de la valeur attendue de *Y* (l’espérance de *Y*). Le paramètre de forme ($\\alpha$) n’a pas d’interprétation pratique, bien qu’il soit utilisé dans les différents tests des conditions d’application du modèle et dans le calcul de sa déviance.\n\n#### Conditions d'application {#sec-08432}\n\nDans un modèle GLM gaussien, la variance est capturée par un paramètre $\\sigma$ et est constante, produisant la condition d'homoscédasticité des résidus. Dans un modèle Gamma, la variance varie en fonction de l'espérance et du paramètre de forme selon la relation : $Var(Y) = \\frac{E(Y)^2}{\\alpha}$. Les résidus sont donc par nature hétéroscédastiques dans un modèle Gamma et doivent suivre cette relation.\n\n#### Exemple appliqué dans R {#sec-08433}\n\nPour cet exemple, nous nous intéressons à la durée de déplacement en milieu urbain. Ce type d’analyse permet notamment de mieux comprendre les habitudes de déplacement de la population et d’orienter les politiques de transport. Plusieurs travaux concluent que les durées de déplacement en milieu urbain varient en fonction du motif du déplacement, du mode de transport utilisé, des caractéristiques socio-économiques de l’individu et des caractéristiques du trajet lui-même [@anastasopoulos2012analysis; @frank2008urban]. Nous modélisons ici la durée en minute d’un ensemble de déplacements effectués par des Montréalais en 2017 et enregistrés avec l’application MTL Trajet proposée par la Ville de Montréal. Ces données sont disponibles sur le site web des [données ouvertes de Montréal](http://donnees.ville.montreal.qc.ca/dataset/mtl-trajet) et sont anonymisées. Nous ne disposons donc d’aucune information individuelle. Compte tenu du très grand nombre d’observations (plus de 185 000), nous avons dû effectuer quelques opérations de tri et nous avons ainsi supprimé:\n\n* les trajets utilisant de multiples modes de transport (sauf en combinaison avec la marche, par exemple, un trajet effectué à pied et en transport en commun a été recatégorisé comme un trajet en transport en commun uniquement). Les déplacements multimodaux se distinguent largement des déplacements unimodaux dans la littérature scientifique;\n\n* les trajets de nuit (seuls les trajets démarrant dans l'intervalle de 7 h à 21 h ont été conservés);\n\n* les trajets dont le point de départ est un arrondissement / municipalité pour lequel moins de 150 trajets ont été enregistrés (trop peu d’observations);\n\n* les trajets de plus de deux heures (cas rares, considérés comme des données aberrantes);\n\n* les trajets dont le point de départ est à moins de 100 mètres du point d’arrivée (formant des boucles plutôt que des déplacements).\n\nNous arrivons ainsi à un total de 24 969 observations. Pour modéliser ces durées de déplacement, nous utilisons les variables indépendantes présentées dans le @tbl-variablegamma.\n\n```{r}\n#| label: tbl-variablegamma\n#| tbl-cap: Variables indépendantes utilisées dans le modèle Gamma\n#| echo: false\n#| message: false\n#| warning: false\n#| out-width: \"50%\"\ndf <- data.frame(\n C1 = c(\"Mode\", \"Motif\", \"HeureDep\", \"ArrondDep\", \"LogDist\", \"MemeArrond\", \"Semaine\"),\n C2 = c(\"Mode de déplacement\", \"Motif du déplacement\", \"Heure de départ\", \"Arrondissement de départ\", \"Logarithme de la distance à vol d’oiseau en km\", \"L’arrivée du trajet se situe-t-elle dans le même arrondissement que celui du départ?\", \"Le trajet a-t-il été effectué en semaine ou en fin de semaine?\"),\n C3 = c(\"Variable catégorielle\", \"Variable catégorielle\", \"Variable catégorielle\", \"Variable catégorielle\", \"Variable continue\", \"Variable binaire\", \"Variable binaire\"),\n C4 = c(\"Transport collectif; piéton; vélo et véhicule individuel\", \"Travail; loisir; magasinage et éducation\", \"De 7 h à 21 h\", \"Nom de l’arrondissement dont part le trajet\", \"Logarithme de la distance à vol d’oiseau en km entre le point de départ et d’arrivée\", \"Oui ou non\", \"Semaine ou fin de semaine\")\n)\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Nom de la variable\" , \"Signification\" , \"Type de variable\" , \"Mesure\"), \n align= c(\"l\", \"l\", \"l\", \"l\"),\n col.to.resize = c(2,4),\n col.width = \"5cm\"\n)\n```\n\nLes temps de trajet forment une variable strictement positive et très vraisemblablement asymétrique. En effet, nous nous attendons à observer une certaine concentration de valeurs autour d'une moyenne, et davantage de trajets avec de courtes durées que de trajets avec de longues durées. Pour nous en assurer, réalisons un histogramme de la distribution de notre variable *Y* et comparons-la avec des distributions normale et Gamma.\n\n```{r}\n#| label: fig-gammadatadistrib\n#| fig-cap: Distribution des temps de trajet diurne à Montréal\n#| fig-align: center\n#| out-width: \"50%\"\n#| message: false\n#| warning: false\n\n# Chargement des données\ndataset <- read.csv(\"data/glm/DureeTrajets.csv\", stringsAsFactors = FALSE)\narrondMTL <- c(\"Mercier-Hochelaga-Maisonneuve\", \"Villeray-Saint-Michel-Parc-Extension\", \n \"Ville-Marie\", \"Verdun\", \"Saint-Leonard\", \"Saint-Laurent\", \n \"Rosemont-La Petite-Patrie\", \"Riviere-des-Prairies-Pointe-aux-Trembles\", \n \"Pierrefonds-Roxboro\", \"Outremont\", \"Montreal-Nord\", \"Le Sud-Ouest\", \n \"Le Plateau-Mont-Royal\", \"Lachine\" , \"Ahuntsic-Cartierville\",\n \"Anjou\" ,\"Cote-des-Neiges-Notre-Dame-de-Grace\", \"LaSalle\" \n)\ndataset <- subset(dataset, dataset$ArrondDep %in% arrondMTL)\n# Définissons 7 h du matin comme la référence pour la variable Heure de départ\ndataset$HeureDep <- relevel(\n factor(dataset$HeureDep, levels = as.character(7:21)),\n ref = \"7\")\n# Comparaison de la distribution originale avec une distribution \n# normale et une distribution Gamma\nlibrary(fitdistrplus)\nmodel_gamma <- fitdist(dataset$Duree, distr = \"gamma\")\nggplot(data = dataset) + \n geom_histogram(aes(x = Duree, y = ..density..), bins = 40, color = \"white\")+\n stat_function(fun = dgamma, color = \"red\", linewidth = 0.8, \n args = as.list(model_gamma$estimate))+\n stat_function(fun = dnorm, color = \"blue\", linewidth = 0.8, \n args = list(mean = mean(dataset$Duree), \n sd = sd(dataset$Duree)))+\n labs(x = \"Temps de déplacement (minutes)\",\n y = \"\",\n subtitle = \"modèles Gamma et gaussien\")\n```\n\nLa @fig-gammadatadistrib permet de constater l'asymétrie de la distribution des temps de trajet et qu'un modèle Gamma (ligne rouge) a plus de chance d'être adapté aux données qu'un modèle gaussien (ligne bleue).\n\n**Vérification des conditions d'application**\n\nComme pour les modèles précédents, nous commençons par la vérification de l'absence de multicolinéarité.\n\n```{r}\n#| message: false\n#| warning: false\n#| out-width: \"50%\"\n## Calcul du VIF\nvif(glm(Duree ~ Mode + Motif + HeureDep + LogDist +\n ArrondDep + MemeArrond + Jour,\n data = dataset,\n family = Gamma(link=\"log\")))\n```\n\nL'ensemble des valeurs de VIF sont inférieures à trois, indiquant donc l'absence de multicolinéarité excessive. Nous pouvons donc ajuster une première version du modèle (ici avec le *package* `VGAM` et la fonction `vglm`) et calculer les distances de Cook.\n\n```{r}\n#| label: fig-cookdistgamma\n#| fig-align: center\n#| fig-cap: Distances de Cook pour le modèle Gamma\n#| out-width: \"50%\"\n#| message: false\n#| warning: false\n\n# Calcul du modèle avec VGAM\nmodele <- vglm(Duree ~ Mode + Motif + HeureDep + LogDist +\n ArrondDep+ MemeArrond + Semaine,\n data = dataset,\n family = gamma2(lmu = \"loglink\"))\n# Calcul des distances de Cook\nhats <- hatvaluesvlm(modele)[,1]\nres <- residuals(modele, type = \"pearson\")[,1]\ndisp <- modele@coefficients[[2]]**-1\nnbparams <- modele@rank\ncooksd <- (res/(1 - hats))^2 * hats/(disp * nbparams)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\n# Représentation des distances de Cook\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, color = rgb(0.4,0.4,0.4,0.4)) + \n geom_hline(yintercept = 0.003, color = \"red\") +\n labs(x = \"\", y = \"distance de Cook\")\n```\n\nPuisque nous disposons d'un (très) grand nombre d'observations, nous pouvons nous permettre de retirer les quelques observations fortement influentes (distance de Cook > 0,003 dans notre cas) qui apparaissent dans la @fig-cookdistgamma. Nous retirons ainsi 28 observations et réajustons le modèle.\n\n```{r}\n#| message: false\n#| warning: false\n# Retirer les valeurs influentes\ndataset2 <- subset(dataset, cooksd<0.003)\n# Calcul du modèle avec VGAM\nmodele <- vglm(Duree ~ Mode + Motif + HeureDep + LogDist +\n ArrondDep+ MemeArrond + Semaine,\n data = dataset2,\n family = gamma2(lmu = \"loglink\"))\n```\n\nNous constatons ainsi que dans la nouvelle version du modèle (@fig-cookdistgamma2), aucune valeur particulièrement influente ne semble être présente.\n\n```{r}\n#| label: fig-cookdistgamma2\n#| fig-cap: Distances de Cook pour le modèle Gamma (sans les observations fortement influentes)\n#| fig-align: center\n#| out-width: \"50%\"\n#| message: false\n#| warning: false\n\n# Calcul des distances de Cook\nhats <- hatvaluesvlm(modele)[,1]\nres <- residuals(modele, type = \"pearson\")[,1]\ndisp <- modele@coefficients[[2]]**-1\nnbparams <- modele@rank\ncooksd <- (res/(1 - hats))^2 * hats/(disp * nbparams)\ndf <- data.frame(\n cook = cooksd,\n oid = 1:length(cooksd)\n)\n# Représentation des distances de Cook\nggplot(data = df)+\n geom_point(aes(x = oid, y = cook), size = 0.5, color = rgb(0.4,0.4,0.4,0.4)) +\n labs(x = \"\", y = \"distance de Cook\")\n```\n\n\n```{r}\n#| label: fig-simdistribgamma\n#| fig-cap: Comparaison de la distribution originale et de simulations issues du modèle Gamma\n#| fig-align: center\n#| out-width: \"60%\"\n#| message: false\n#| warning: false\n#| echo: true\n# Extraction des prédictions du modèle (mu)\nmus <- modele@fitted.values\n# Extraction du paramètre de forme\nshape <- exp(modele@coefficients[[2]])\n# Calcul des simulations\nnsim <- 1000\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- rgamma(n = nsim, shape = shape, scale = mu/shape)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Représentation graphique de 20 simulations\ndf2 <- reshape2::melt(mat_sims[,0:20])\nggplot() + \n geom_histogram(aes(x = Duree, y = ..density..),\n data = dataset, bins = 100, color = \"black\", fill = \"white\") + \n geom_density(aes(x = value, y = ..density.., group = Var2), data = df2, \n fill = rgb(0,0,0,0), color = rgb(0.9,0.22,0.27,0.4), size = 1)+\n xlim(0,200)+\n labs(x = \"durée (minutes)\", y = \"densité\")\n```\n\nAvant de calculer les résidus simulés, nous comparons la distribution originale des données et des simulations issues du modèle. La @fig-simdistribgamma permet de constater que le modèle semble bien capturer l’essentiel de la forme de la variable *Y* originale. Nous notons un léger décalage entre la pointe des deux distributions, laissant penser que les valeurs prédites par le modèle tendent à être légèrement plus grandes que les valeurs réelles. Pour mieux appréhender ce constat, nous passons à l'analyse des résidus simulés.\n\n```{r}\n#| label: fig-gammaresids\n#| fig-align: center\n#| fig-cap: Distribution des résidus simulés du modèle Gamma\n#| message: false\n#| warning: false\n#| out-width: \"60%\"\n#| echo: true\n# DHarma tests\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = dataset2$Duree,\n fittedPredictedResponse = modele@fitted.values[,1],\n integerResponse = FALSE)\nggplot() + \n geom_histogram(aes(x = residuals(sim_res)), bins = 100, color = \"white\") + \n labs(x = \"résidus simulés\",\n y = \"effectifs\")\n```\n\nNul besoin d'un test statistique pour constater que ces résidus (@fig-gammaresids) ne suivent pas une distribution uniforme. Nous observons une nette surreprésentation de résidus à 1 et une nette sous-représentation de résidus à 0. Il y a donc de nombreuses observations dans notre modèle pour lesquelles les simulations sont systématiquement trop fortes et il n'y en a pas assez pour lesquelles les simulations seraient systématiquement trop faibles.\n\n```{r}\n#| label: fig-gammaresids2\n#| fig-align: center\n#| fig-cap: Diagnostic général des résidus simulés du modèle Gamma\n#| out-width: \"65%\"\n#| echo: true\n#| message: false\n#| warning: false\nplot(sim_res)\n```\n\nLa @fig-gammaresids2 indique que le modèle souffre à la fois d'un problème de dispersion (la relation espérance-variance n'est donc pas respectée) et est affecté par des valeurs aberrantes. Considérant que nous avons encore un très grand nombre d'observations, nous faisons le choix de retirer celles pour lesquelles la méthode des résidus simulés estime qu'elles sont des valeurs aberrantes dans au moins 1 % des simulations, soit environ 620 observations.\n\n```{r}\n#| label: fig-gammaresids3\n#| fig-align: center\n#| fig-cap: Diagnostic général des résidus simulés du modèle Gamma (après suppression d'environ 620 valeurs aberrantes)\n#| message: false\n#| warning: false\n#| out-width: \"65%\"\n#| echo: true\n# Sélection des valeurs aberrantes au seuil 0.01\nsim_outliers <- outliers(sim_res, \n lowerQuantile = 0.01,\n upperQuantile = 0.99, \n return = \"logical\")\ntable(sim_outliers)\n# Retirer ces observations des données\ndataset3 <- subset(dataset2, sim_outliers == FALSE)\n# Réajuster le modèle\nmodele <- vglm(Duree ~ Mode + Motif + HeureDep + \n LogDist + ArrondDep + MemeArrond + Semaine,\n data = dataset3,\n model = TRUE,\n family = gamma2)\nmodele2 <- vglm(Duree ~ Mode + Motif + HeureDep + ArrondDep + MemeArrond + Semaine,\n data = dataset3,\n model = TRUE,\n family = gamma2)\n# Extraction des prédictions du modèle (mu)\nmus <- modele@fitted.values\n# Extration du paramètre de forme\nshape <- exp(modele@coefficients[[2]])\n# Calcul des simulations\nnsim <- 1000\ncols <- lapply(1:length(mus), function(i){\n mu <- mus[[i]]\n sims <- rgamma(n = nsim, shape = shape, scale = mu/shape)\n return(sims)\n})\nmat_sims <- do.call(rbind, cols)\n# Calcul des résidus simulés\nsim_res <- createDHARMa(simulatedResponse = mat_sims, \n observedResponse = dataset3$Duree,\n fittedPredictedResponse = modele@fitted.values[,1],\n integerResponse = FALSE)\nplot(sim_res)\n```\n\nLa @fig-gammaresids3 indique que les résidus simulés ne suivent toujours pas une distribution uniforme et qu'il existe une relation prononcée (panneau de droite) entre les résidus et les valeurs prédites. Cette dernière laisse penser que des variables indépendantes importantes ont été omises dans le modèle, ce qui n’est pas surprenant compte tenu du fait que nous ne disposons d’aucune donnée socioéconomique sur les individus ayant réalisé les trajets. Nos données sont également potentiellement affectées par la présence de dépendance spatiale.\n\nNous pouvons comparer graphiquement la variance observée dans les données et la variance attendue par le modèle. La @fig-dispgamma montre clairement que la variance des données tend à être plus grande qu'attendu quand les temps de trajet sont courts, mais diminue trop vite quand les temps de trajet augmentent. D'autres distributions pourraient être envisagées pour ajuster notre modèle : Lognormal, Weibull, etc.\n\n```{r}\n#| label: fig-dispgamma\n#| fig-align: center\n#| fig-cap: Comparaison de la variance attendue par le modèle et la variance observée dans les données pour le modèle Gamma\n#| out-width: \"50%\"\n#| warning: false\n#| message: false\n# Extraction des prédictions du modèle\nmus <- predict(modele, type = \"response\")[,1]\n# Création d'un DataFrame pour contenir la prédiction et les vraies valeurs\ndf1 <- data.frame(\n mus = mus,\n reals = dataset3$Duree\n)\n# Calcul de l'intervalle de confiance à 95 % selon la distribution Gamma\n# et stockage dans un second DataFrame\nseqa <- seq(10,120,10)\nshape <- exp(modele@coefficients[[2]])\ndf2 <- data.frame(\n mus = seqa,\n lower = qgamma(p = 0.025, shape = shape, scale = seqa/shape),\n upper = qgamma(p = 0.975, shape = shape, scale = seqa/shape)\n)\n# Affichage des valeurs réelles et prédites (en rouge)\n# et de leur variance selon le modèle (en noir)\nggplot() + \n geom_point(data = df1, \n mapping = aes(x = mus, y = reals),\n color =rgb(0.9,0.22,0.27,0.4), size = 0.5) + \n geom_errorbar(data = df2,\n mapping = aes(x = mus, ymin = lower, ymax = upper),\n width = 0.2, color = rgb(0.4,0.4,0.4)) + \n labs(x = \"valeurs prédites\",\n y = \"valeurs réelles\")\n```\n\nÀ ce stade, nous disposons de suffisamment d’éléments pour douter des résultats du modèle. Nous poursuivons tout de même notre analyse afin d'illustrer l'estimation de la qualité d'ajustement d'un tel modèle et son interprétation.\n\n**Analyse de la qualité d'ajustement**\n\n```{r}\n#| warning: false\n#| message: false\n# Ajustement d'un modèle nul\nmodele.null <- vglm(Duree ~1,\n data = dataset3,\n model = TRUE,\n family = gamma2)\n# Calcul des pseudos R2\nrsqs(loglike.full = logLik(modele),\n loglike.null = logLik(modele.null),\n full.deviance = logLik(modele) * -2,\n null.deviance = logLik(modele.null) * -2,\n nb.params = modele2@rank,\n n = nrow(dataset3)\n )\n# Calcul du RMSE\npreds <- predict(modele, type = \"response\")[,1]\nsqrt(mean((preds - dataset3$Duree)**2))\n```\n\nLe modèle n’explique que 5 % de la déviance et obtient des valeurs de R^2^ ajusté de McFadden, de Cox et Snell et de Nagelkerke de respectivement 0,05, 0,33 et 0,33. La moyenne de l’erreur quadratique est de seulement 13,4 indiquant que le modèle se trompe en moyenne de seulement 13,4 minutes. La capacité de prédiction du modèle est donc limitée sans être catastrophique.\n\n**Interprétation des résultats**\n\nPour rappel, la fonction de lien dans notre modèle est la fonction `log`. Chaque coefficient représente donc l'effet de l'augmentation d'une unité des variables indépendantes sur le logarithme de l'espérance de notre variable dépendante. Si nous transformons nos coefficients avec la fonction exponentielle (`exp`), nous obtenons, pour chaque augmentation d'une unité des variables indépendantes, la multiplication de l'espérance de notre variable dépendante.\n\nPuisque nos trajets peuvent provenir de nombreux arrondissements, nous proposons de représenter l'exponentiel de leurs coefficients avec un graphique. Nous pouvons d'ailleurs comparer les exponentiels des coefficients et les effets marginaux pour simplifier l'interprétation.\n\n```{r}\n#| label: fig-arrondgamma\n#| fig-cap: Effet de l'arrondissement de départ sur les temps de trajet à Montréal\",\n#| fig-align: center\n#| out-width: \"100%\"\n#| warning: false\n#| message: false\n\n# Extraction des coefficient du modèle\ncoeffs <- modele@coefficients\n# Calcul des interval de confiance des coefficients\nconf <- confint(modele)\n# Passage en exponentiel\ndf <- exp(cbind(coeffs, conf))\n# Extraction des coefficients pour les arrondissements\ndfArrond <- data.frame(df[grepl(\"ArrondDep\", row.names(df), fixed = TRUE),])\nnames(dfArrond) <- c(\"coeff\", \"lower\" , \"upper\")\ndfArrond$Arrondissement <- gsub(\"ArrondDep\" , \"\", rownames(dfArrond), fixed = TRUE)\n# Graphique des exponentiels des coefficients\nP1 <- ggplot(data = dfArrond) + \n geom_vline(xintercept = 1, color = \"red\")+\n geom_errorbarh(aes(y = reorder(Arrondissement, coeff), xmin = upper, xmax = lower),\n height = 0)+\n geom_point(aes(y = reorder(Arrondissement, coeff), x = coeff)) + \n geom_text(aes(x = upper, y = reorder(Arrondissement, coeff),\n label = paste(\"coeff. : \", round(coeff,2), sep = \"\")),\n size = 3, nudge_x = 0.07)+\n labs(x = \"Coefficient multiplicateur (ref : Ahuntsic-Cartierville)\",\n y = \"\",\n subtitle = \"Exponentiels des coefficients du modèle\")+\n xlim(c(0.75,1.46))\n# Création d'un DataFrame fictif pour les effets marginaux\ndfpred <- expand.grid(\n LogDist = mean(dataset3$LogDist),\n Motif = 'education',\n HeureDep = '7',\n MemeArrond = 'Different',\n ArrondDep = unique(dataset3$ArrondDep),\n Mode = 'pieton','velo','transport collectif',\n Semaine = 'lundi au vendredi'\n)\n# Utiliser le modèle pour effectuer des prédictions (échelle log)\nlin_pred <- predict(modele, dfpred, se = TRUE)\nmu_lin_pred <- lin_pred$fitted.values[,1]\nse_lin_pred <- lin_pred$se.fit[,1]\ndfpred2 <- data.frame(\n pred = exp(mu_lin_pred),\n lower = exp(mu_lin_pred- 1.96*se_lin_pred),\n upper = exp(mu_lin_pred+ 1.96*se_lin_pred)\n)\ndfpred2 <- cbind(dfpred2, dfpred)\n# Réaliser le graphique des effets marginaux\nP2 <- ggplot(data = dfpred2) + \n geom_col(aes(x = pred, y = ArrondDep)) + \n geom_errorbarh(aes(xmin = lower, xmax = upper, y = ArrondDep)) + \n labs(x = \"Temps de déplacement prédit\", y = \"\",\n subtitle = \"Prédiction du modèle\")\nggarrange(P1, P2, ncol = 1, nrow = 2)\n \n```\n\nLa @fig-arrondgamma permet de constater que les arrondissements Ville-Marie et Plateau-Mont-Royal se distinguent avec des trajets plus courts (environ 20 % plus courts en moyenne que les trajets partant d'Ahuntsic-Cartierville). À l'inverse, Lachine est de loin l'arrondissement avec les trajets les plus longs (25 % plus longs en moyenne que les trajets partant d'Ahuntsic-Cartierville).\n\nNous appliquons la même méthode de visualisation à la variable *Heure de départ* des trajets.\n\n```{r}\n#| label: fig-heuresgamma\n#| fig-cap: Effet de l'heure de départ sur les temps de trajet à Montréal\"\n#| fig-align: center\n#| out-width: \"85%\"\n#| warning: false\n#| message: false\n# Extraction des valeurs pour les heures de départ\ndfHeures <- data.frame(df[grepl(\"HeureDep\", row.names(df), fixed = TRUE),])\nnames(dfHeures) <- c(\"coeff\", \"lower\" , \"upper\")\ndfHeures$Heure <- gsub(\"HeureDep\" , \"\", rownames(dfHeures), fixed = TRUE)\n# Rajouter des 0 et des h pour de jolies légendes\ndfHeures$Heure <- paste(dfHeures$Heure,\"h\", sep=\" \")\n\n# Afficher le graphique\nggplot(data = dfHeures) + \n geom_hline(yintercept = 1, color = \"red\")+\n geom_errorbar(aes(x = Heure, ymin = upper, ymax = lower), width = 0)+\n geom_point(aes(x = Heure, y = coeff)) + \n geom_text(aes(y = upper, x = Heure, label = round(coeff,2)), size = 3, nudge_y = 0.07)+\n labs(x = \"Coefficient multiplicateur (ref : 7 h)\",\n y = \"\")\n```\n\nNous pouvons ainsi observer, à la @fig-heuresgamma, que les trajets effectués à 10 h, 11 h et 12 h sont les plus longs de la journée, entre 30 et 40 % plus longs que ceux effectués à 7 h et 8 h qui constituent les trajets les plus courts.\n\nLe reste des coefficients (ainsi que le paramètre de forme) sont affichés dans le @tbl-coeffsgamma. Comparativement à un trajet effectué à pied, un trajet en transport en commun dure en moyenne 52 % plus longtemps (1,53 fois plus long), alors que les déplacements en véhicule individuel et en vélo sont respectivement 28 % et 23 % moins longs. Aucune différence n’est observable entre les déplacements effectués en semaine ou pendant la fin de semaine.\n\n```{r}\n#| label: tbl-coeffsgamma\n#| tbl-cap: Résultats pour le modèle GLM Gamma\n#| warning: false\n#| message: false\n#| echo: false\ntableau <- build_table(modele, coef_digits = 3, OR_digits = 3)\ntableau_ok <- tableau[c(1:11,28,48:nrow(tableau)),]\ntableau_ok <- tableau_ok[, c(1,2,3,6,7,8,9)]\nknitr::kable(tableau_ok, \n col.names = c('Variable',\"Coeff.\" , \"Exp(Coeff.)\" , \"Val.p\" , \"IC 2,5 % exp(Coeff.)\" , \"IC 97,5 % exp(Coeff.)\", \"Sign.\"),\n align= c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\")\n)\n```\n\nLes déplacements ayant comme motif le magasinage et le travail ont tendance à être en moyenne plus courts de 11 % et 6 % respectivement, comparativement aux déplacements effectués pour l’éducation ou le loisir (différence non significative entre loisir et éducation). Sans surprise, la distance entre le point de départ et d’arrivée du trajet (`LogDist`) affecte sa durée de façon positive. Considérant qu’il est difficile d’interpréter des log de kilomètre (dû à une transformation de la variable originale), nous représentons l’effet de cette variable avec la prédiction du modèle à la figure. Nous utilisons pour cela le cas suivant: déplacement à pied à 7 h en semaine, ayant pour motif éducation, dont le point de départ se situe dans l’arrondissement Ahuntsic et donc le point d’arrivée est dans un autre arrondissement. Seule la distance du trajet varie de 1 à 40 km. À titre de comparaison, nous représentons aussi, pour les mêmes conditions, le cas d’une personne à vélo (en vert) et d’une personne utilisant le transport en commun (en bleu). Les lignes en pointillés représentent les intervalles de confiance à 95 % des prédictions (@fig-distancegamma).\n\n\n```{r}\n#| label: fig-distancegamma\n#| fig-cap: Effet de la distance à vol d'oiseau sur les temps de trajet à Montréal\n#| fig-align: center\n#| out-width: \"85%\"\n#| warning: false\n#| message: false\n# Création d'un DataFrame fictif pour la prédiction\ndfpred <- expand.grid(\n Dist = seq(1,40, 0.5),\n Motif = 'education',\n HeureDep = '7',\n MemeArrond = 'Different',\n ArrondDep = 'Ahuntsic-Cartierville',\n Mode = c('pieton','velo','transport collectif'),\n Semaine = 'lundi au vendredi'\n)\n# Mise en log de la variable de distance\ndfpred$LogDist <- log(dfpred$Dist)\n# Calcul des prédictions et de leur erreur standard (échelle log)\nlin_pred <- predict(modele, dfpred, se = TRUE)\n# Calcul des intervalles de confiance et mise en exponentielle des prédictions\ndfpred$pred <- exp(lin_pred$fitted.values[,1])\ndfpred$lower <- exp(lin_pred$fitted.values[,1] -1.96*lin_pred$se.fit[,1])\ndfpred$upper <- exp(lin_pred$fitted.values[,1] +1.96*lin_pred$se.fit[,1])\n# Ajoutons les accents pour le graphiques\ndfpred$Mode <- as.character(dfpred$Mode)\ndfpred$Mode2 <- case_when(dfpred$Mode == \"pieton\" ~ \"piéton\",\n dfpred$Mode == \"velo\" ~ \"vélo\",\n TRUE ~ dfpred$Mode)\n# Affichage des résultats\nggplot(data = dfpred) + \n geom_path(aes(x = Dist, y = lower, color = Mode2), linetype = \"dashed\")+\n geom_path(aes(x = Dist, y = upper, color = Mode2), linetype = \"dashed\")+\n geom_path(aes(x = Dist, y = pred, color = Mode2), size = 1) + \n labs(y = \"temps de trajet prédit (minutes)\",\n x = \"distance à vol d'oiseau (km)\")\n```\n\n### Modèle GLM avec une distribution bêta {#sec-0844}\n\nPour rappel, la distribution bêta est une distribution définie sur l’intervalle $[0,1]$, elle est donc particulièrement utile pour décrire des proportions, des pourcentages ou des probabilités. Dans la [section @sec-024316] sur les distributions, nous avons présenté la paramétrisation classique de la distribution avec les paramètres $a$ et $b$ étant tous les deux des paramètres de forme. Ces deux paramètres n’ont pas d’interprétation pratique, mais il est possible (comme pour la distribution Gamma) de reparamétrer la distribution bêta avec un paramètre de centralité (espérance) et de dispersion.\n\nNotez également que si la distribution bêta autorise la présence de 0 et de 1, le modèle GLM utilisant cette distribution doit les exclure des valeurs possibles s'il utilise la fonction de lien logistique. En effet, cette fonction à la forme suivante :\n\n$$\nlogit(x) = log(\\frac{x}{1-x})\\\\\n$$ {#eq-logitbeta}\n\nNous pouvons constater que si $x = 1$, alors le dénominateur de la fraction est 0, or il est impossible de diviser par 0. Si $x = 0$, alors nous obtenons $log(0)$ ce qui est également impossible au plan mathématique.\n\nDans le cas de figure où des 0 et/ou des 1 sont présents dans les données, quatre options sont possibles pour contourner le problème :\n\n1. Si les observations à 0 ou 1 sont très peu nombreuses, il est envisageable de les retirer des données.\n2. Si la variable mesurée le permet, il est possible de remplacer les 0 et les 1 par des valeurs très proches (0,0001 et 0,9999 par exemple) sans dénaturer excessivement les données initiales.\n3. Plutôt que d'utiliser une valeur arbitraire, @smithson2006better recommandent de recalculer la variable $Y \\in [0;1]$ avec la formule @eq-correctbeta;\n4. Employer un modèle Hurdle à trois équations, la première prédisant la probabilité d'observer $Y > 0$, la seconde, la probabilité d'observer $Y = 1$ et la dernière prédisant les valeurs de *Y* pour $0>Y>1$.\n\n$$\nY' = \\frac{Y(N-1)+s}{N}\n$$ {#eq-correctbeta}\n\nAvec *N* le nombre d'observations, *Y'* la variable *Y* transformée et *s* une constante. Plus cette dernière est élevée, plus la variable *Y'* a des valeurs éloignées de 0 et 1. la valeur de 0,5 est recommandée par les auteurs.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Reparamétrisation de la distribution bêta**\n:::\n::: bloc_aller_loin-body\nPour une distribution bêta telle que définie par $Y \\sim Beta(a,b)$, l'espérance de cette distribution et sa variance sont données par : \n\n$$\n\\begin{aligned}\n&E(Y) = \\frac{a}{a+b} \\\\\n&Var(Y) = \\frac{a \\times b}{(a+b)^2(a+b+1)}\\\\\n\\end{aligned}\n$$ {#eq-glm20}\n\nPour reparamétrer cette distribution, nous définissons un nouveau paramètre $\\phi$ (phi) tel que:\n\n$$\n\\begin{aligned}\n&a = \\phi * E(Y) \\\\\n&b = \\phi - a \\\\\n&Var(Y) = \\frac{E(Y) \\times (1-E(Y))}{1+\\phi}\n\\end{aligned}\n$$ {#eq-glm21}\n\nDe cette manière, il est possible d'exprimer la distribution bêta en fonction de son espérance (sa valeur attendue, ce qui s'interprète approximativement comme une moyenne) et d'un paramètre $\\phi$ intervenant dans le calcul de sa variance. Vous noterez d'ailleurs que la variance de cette distribution dépend de sa moyenne, impliquant à nouveau une hétéroscédasticité intrinsèque.\n:::\n:::\n\nPour résumer, nous nous retrouvons donc avec un modèle qui prédit l'espérance d’une distribution bêta avec une fonction de lien logistique. La variance de cette distribution est fonction de cette moyenne et d'un second paramètre $\\phi$. Ces informations sont résumées dans la fiche d'identité du modèle (@tbl-betaentity).\n\n```{r}\n#| label: tbl-betaentity\n#| tbl-cap: Carte d'identité du modèle bêta\n#| echo: false\n#| message: false\n#| warning: false\nmodel_formula <- \"$Y \\\\sim Beta(\\\\mu,\\\\phi)$ \\\\newline $g(\\\\mu) = \\\\beta_0 + \\\\beta X$ \\\\newline $g(x) = log(\\\\frac{x}{1-x})$\"\ntableau <- data.frame(\n C1 = c(\"Type de variable dépendante\" , \"Distribution utilisée\", \"Formulation\", \"Fonction de lien\", \"Paramètre modélisé\", \"Paramètres à estimer\", \"Conditions d'application\"),\n C2 = c(\"Variable continue dans l'intervalle $]0,1[$\", \"Student\", model_formula , \"log\", \"$\\\\mu$\", \"$\\\\beta_0$, $\\\\beta$, et $\\\\phi$\", \"$Variance = \\\\frac{\\\\mu \\\\times (1-\\\\mu)}{1+\\\\phi}$\")\n)\nknitr::kable(tableau, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = NULL, \n col.to.resize = c(2),\n col.width = \"8cm\"\n)\n```\n\n#### Conditions d'application {#sec-08441}\n\nComme pour un modèle Gamma, la seule condition d'application spécifique à un modèle avec distribution bêta est que la variance des résidus suit la forme attendue par la distribution bêta.\n\n#### Interprétation des coefficients {#sec-08442}\n\nPuisque le modèle utilise la fonction de lien logistique, les exponentiels des coefficients $\\beta$ du modèle peuvent être interprétés comme des rapports de cotes (voir la [section @sec-0821] sur le modèle GLM binomial). Admettons ainsi que nous avons obtenu pour une variable indépendante $X_1$ le coefficient $\\beta_1$ de 0,12. Puisque le coefficient est positif, cela signifie qu’une augmentation de $X_1$ conduit à une augmentation de l'espérance de *Y*. L’exponentiel de 0,12 est 1,13, ce qui signifie qu’une augmentation d’une unité de $X_1$ multiplie par 1,13 (augmente de 13 %) les chances d'une augmentation de *Y*. **Pour ce type de modèle, il est particulièrement important de calculer ses prédictions afin d'en faciliter l'interprétation**.\n\n#### Exemple appliqué dans R {#sec-08443}\n\nAfin de présenter le modèle GLM avec une distribution bêta, nous utilisons un jeu de données que nous avons construit pour l’île de Montréal. Nous nous intéressons à la question des îlots de chaleur urbains au niveau des aires de diffusion (AD – entités spatiales du recensement canadien comprenant entre 400 et 700 habitants). Pour cela, nous avons calculé dans chaque AD le pourcentage de sa surface classifiée comme îlot de chaleur dans la carte des îlots de [chaleur/fraicheur](https://www.donneesquebec.ca/recherche/fr/dataset/ilots-de-chaleur-fraicheur-urbains-et-temperature-de-surface) réalisée par l’INSPQ et le CERFO.\n\nLa question que nous nous posons est la suivante : les populations vulnérables socioéconomiquement et/ou physiologiquement sont-elles systématiquement plus exposées à la nuisance que représentent les îlots de chaleur? Cette question se rattache donc au champ de la recherche sur l'équité environnementale. Plusieurs études se sont d'ailleurs déjà penchées sur la question des îlots de chaleur abordée sous l'angle de l'équité environnementale [@harlan2007shade; @sanchez2019cooling; @huang2011everyone]. Nous modélisons donc pour chaque AD (n = 3 158) de l’île de Montréal la proportion de sa surface couverte par des îlots de chaleur. Nos variables indépendantes sont divisées en deux catégories : variables environnementales et variables socio-économiques. Les premières sont des variables de contrôle, il s’agit de la densité de végétation dans l’AD (ajoutée avec une polynomiale d'ordre deux) et de l'arrondissement dans lequel elle se situe. Ces deux paramètres affectent directement les chances d’observer des îlots de chaleur, mais nous souhaitons isoler leurs effets (toutes choses étant égales par ailleurs) de ceux des variables socio-économiques. Ces dernières ont pour objectif de cibler les populations vulnérables sur le plan physiologique (personnes âgées et enfants de moins de 14 ans) ou socio-économique (minorités visibles et faible revenu). L'ensemble de ces variables sont présentées dans le @tbl-variablebeta. Notez que, puisque le modèle avec distribution bêta ne peut pas prendre en compte des valeurs exactes de 1 ou 0, nous les avons remplacées respectivement par 0,99 et 0,01. Cette légère modification n'altère que marginalement les données, surtout si nous considérons qu'elles sont agrégées au niveau des AD et proviennent originalement d'imagerie satellitaire.\n\n```{r}\n#| label: tbl-variablebeta\n#| tbl-cap: Variables indépendantes utilisées dans le modèle bêta\n#| echo: false\n#| message: false\n#| warning: false\ndf <- data.frame(\n C1 = c(\"A65PlusPct\" , \"A014Pct\" , \"PopFRPct\" , \"PopMVPct\" , \"VegPct\" , \"Arrond\"),\n C2 = c(\"Population de 65 ans et plus\", \"Population de 14 ans et moins\", \"Population à faible revenu\", \"Minorités visibles\", \"Végétation\", \"Arrondissements\"),\n C3 = c(\"Variable continue\", \"Variable continue\", \"Variable continue\", \"Variable continue\", \"Variable continue\", \"Variable continue\"),\n C4 = c(\"Pourcentage de la population ayant 65 ans et plus\", \"Pourcentage de la population ayant 14 ans et moins\", \"Pourcentage de la population à faible revenu\", \"Pourcentage de la population faisant partie des minorités visibles\", \"Pourcentage de la surface de l’AD couverte par de la végétation\", \"Arrondissement de l'Île de Montréal\"))\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Nom de la variable\" , \"Signification\" , \"Type de variable\" , \"Mesure\"),\n align= c(\"l\", \"l\", \"l\", \"l\"),\n col.to.resize = c(2,4),\n col.width = \"5cm\"\n)\n```\n\n**Vérification des conditions d'application**\n\nSans surprise, nous commençons par charger nos données et nous nous assurons de l'absence de multicolinéarité excessive entre nos variables indépendantes.\n\n```{r}\n#| message: false\n#| warning: false\n## Chargement des données\ndataset <- read.csv(\"data/glm/data_chaleur.csv\", fileEncoding = \"utf8\")\n## Calcul des valeurs de vif\nvif(glm(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n poly(prt_veg, degree = 2) + Arrond,\n data = dataset))\n```\n\nLa seule variable semblant poser un problème de multicolinéarité est la variable `Arrond`. Cependant, du fait de sa nature multinomiale, elle regroupe en réalité 32 coefficients (voir la colonne `Df`). Il faut donc utiliser la règle habituelle de 5 sur le carré de la troisième colonne (`GVIF^(1/(2*Df))`) du tableau [@fox1992generalized], soit `1,032820^2 = 1,066717`, ce qui est bien inférieur à la limite de 5. Nous n'avons donc pas de problème de multicolinéarité excessive. Nous pouvons passer au calcul des distances de Cook. Pour ajuster notre modèle, nous utilisons le *package* `mgcv` et la fonction `gam` avec le paramètre `family = betar(link = \"logit\")`.\n\n```{r}\n#| label: fig-cookdistbeta\n#| fig-align: center\n#| fig-cap: Distances de Cook pour le modèle GLM bêta\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n# Ajustement d'une première version du modèle\nmodele <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n poly(prt_veg, degree=2) + Arrond,\n data = dataset, family = betar(link = \"logit\"))\n# Calcul des distances de Cook\ndf <- data.frame(\n cooksd = cooks.distance(modele),\n oid = 1:nrow(dataset)\n)\n# Affichage des distances de Cook\nggplot(data = df)+\n geom_point(aes(x = oid, y = cooksd),\n color = rgb(0.4,0.4,0.4,0.4), size = 0.5)+\n labs(x = \"\", y = \"Distance de Cook\")\n```\n\nNous pouvons observer à la @fig-cookdistbeta que seulement deux observations se distinguent très nettement des autres. Nous les isolons donc dans un premier temps.\n\n```{r}\n#| message: false\n#| warning: false\ncas_etranges <- subset(dataset, df$cooksd >= 0.01)\nprint(cas_etranges[,23:ncol(cas_etranges)])\n```\n\nCes deux observations n'ont pas de points communs marqués, et ne semblent pas avoir de valeurs particulièrement fortes sur les différentes variables indépendantes ou la variable dépendante. Nous décidons donc de les supprimer et de recalculer les distances de Cook.\n\n```{r}\n#| label: fig-cookdistbeta2\n#| fig-align: center\n#| fig-cap: Distances de Cook pour le modèle GLM bêta (suppression de deux observations influentes)\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n# Suppression des deux observations très influentes\ndataset2 <- subset(dataset, df$cooksd < 0.01)\nmodele2 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n I(prt_veg**2) + prt_veg + Arrond,\n data = dataset2, family = betar(link = \"logit\"), methode = \"REML\")\n# Calcul des distances de Cook\ndf2 <- data.frame(\n cooksd = cooks.distance(modele2),\n oid = 1:nrow(dataset2)\n)\n# Affichage des distances de Cook\nggplot(data = df2)+\n geom_point(aes(x = oid, y = cooksd),\n color = rgb(0.4,0.4,0.4,0.4), size = 0.5)+\n labs(x = \"\", y = \"Distance de Cook\")\n```\n\nAprès réajustement, nous constatons à nouveau qu'une observation est **extrêmement** éloignée des autres (@fig-cookdistbeta2). Nous la retirons également, car cette différence est si forte qu'elle risque de polluer le modèle.\n\n```{r}\n#| label: fig-cookdistbeta3\n#| fig-cap: Distances de Cook pour le modèle GLM bêta (suppression de trois observations influentes)\n#| fig-align: center\n#| out-width: \"65%\"\n#| message: false\n#| warning: false\n# Suppression de l'observation très étonnante\ndataset3 <- subset(dataset2, df2$cooksdformuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/09-GLMM.qmd.json b/.quarto/idx/09-GLMM.qmd.json new file mode 100644 index 0000000..da2d272 --- /dev/null +++ b/.quarto/idx/09-GLMM.qmd.json @@ -0,0 +1 @@ +{"title":"Régressions à effets mixtes (GLMM)","markdown":{"headingText":"Régressions à effets mixtes (GLMM)","headingAttr":{"id":"sec-chap09","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans les deux chapitres précédents, nous avons consécutivement présenté la méthode de la régression linéaire multiple (LM) ainsi qu'une de ses extensions, soit les modèles linéaires généralisés (GLM). Dans ce chapitre, nous poursuivons sur cette voie avec une nouvelle extension : les modèles généralisés à effet mixtes (GLMM). À la fin de cette section, vous serez en mesure de :\n\n* comprendre la distinction entre un modèle GLM et un modèle GLMM;\n* distinguer un effet fixe d'un effet aléatoire;\n*\tformuler des modèles GLMM avec des constantes et/ou des pentes aléatoires;\n*\teffectuer les diagnostics d’un GLMM.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes.\n - `ellipse` pour représenter des ellipses sur certains graphiques.\n \n* Pour ajuster des modèles GLMM :\n - `lme4`, offrant une interface simple pour ajuster des GLMM.\n\n* Pour analyser des modèles GLM :\n - `car`, essentiellement pour la fonction `vif`.\n - `DHARMa` pour le diagnostic des résidus simulés.\n - `merTools` pour explorer les résultats d'un GLMM.\n - `lmerTest` pour obtenir des tests de significativité pour les coefficients d'un GLMM.\n - `MuMin` pour calculer les R^2^ conditionnel et marginal.\n - `performance` pour calculer l'ICC et d'autres mesures d'ajustement.\n:::\n:::\n\n## Introduction {#sec-091}\n\n### Indépendance des observations et effets de groupes {#sec-0911}\n\nNous avons vu dans les précédents chapitres que l'indépendance des observations est une condition d'application commune à l'ensemble des modèles de régression. Cette condition implique ainsi que chaque unité d'observation de notre jeu de données est indépendante des autres; en d'autres termes, qu'elle ne soit associée à aucune autre observation par un lien de dépendance. Prenons un exemple concret pour illustrer cette notion. Admettons que nous nous intéressons à la performance scolaire d'élèves du secondaire à Montréal. Pour cela, nous collectons la moyenne des résultats aux examens du ministère de tous les élèves des différentes commissions scolaires de l'île de Montréal. Chaque élève appartient à une classe spécifique, et chaque classe se situe dans une école spécifique. Les classes constituent des environnements particuliers, la performance des élèves y est influencée par un ensemble de facteurs comme la personne qui enseigne et les relations entre les élèves d'une même classe. Deux élèves provenant d'une même classe sont donc lié(e)s par une forme de structure propre à leur classe et ne peuvent pas être considéré(e)s comme indépendant(e)s. De même, l'école constitue un environnement particulier pouvant influencer la performance des élèves du fait de moyens financiers plus importants, de la mise en place de programmes spéciaux, de la qualité des infrastructures (bâtiment, gymnase, cour d'école) ou d'une localisation minimisant certaines nuisances à l'apprentissage comme le bruit. À nouveau, deux élèves provenant d'une même école partagent une forme de structure qui, cette fois-ci, est propre à leur école. Si nous collectons des données pour l'ensemble du Canada, nous pourrions étendre ce raisonnement aux villes dans lesquelles les écoles se situent et aux provinces.\n\nDans cet exemple, la dépendance entre les données est provoquée par un effet de groupe : il est possible de rassembler les observations dans des ensembles (classes et écoles) influençant vraisemblablement la variable étudiée (performance scolaire). Les effets des classes et des écoles ne sont cependant pas intrinsèques aux élèves. En effet, il est possible de changer un ou une élève de classe ou d'école, mais pas de changer son âge ou sa situation familiale. Il est ainsi possible de distinguer la population des élèves, la population des classes, et la population des écoles (@fig-glmmecoles). Ces effets de groupes sont plus la règle que l'exception dans l'analyse de données en sciences sociales, ce qui met à mal l'hypothèse d'indépendance des observations. Notez que les effets de groupes ne sont pas les seules formes de structures remettant en cause l'indépendance des observations. Il existe également des structures temporelles (deux observations proches dans le temps ont plus de chances de se ressembler) et spatiales (deux observations proches dans l'espace ont plus de chances de se ressembler); cependant, les cas de la dépendance temporelle et spatiale ne sont pas couverts dans ce livre, car ils sont complexes et méritent un ouvrage dédié.\n\n\n![Structure hiérarchique entre élèves, classes et écoles](images/Chap09/Hierarchie_Ecoles.png){#fig-glmmecoles width=\"50%\" fig-align=\"center\"}\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**La notion de pseudo-réplication**\n:::\n::: bloc_aller_loin-body\nLes effets de dépendance causés par des structures de groupe, temporelles ou spatiales, sont regroupés sous le terme de pseudo-réplication. Il est intéressant de se pencher sur la signification de ce mot pour comprendre le problème intrinsèque causé par la dépendance entre les observations et son influence sur l'inférence.\n\nReprenons l'exemple des élèves et de la performance scolaire et admettons que nous souhaitons estimer la moyenne générale de l'ensemble des élèves sur l'île de Montréal, mais que nous ne disposons pas du jeu de données complet. Nous devons donc collecter un échantillon suffisamment grand pour estimer la moyenne pour l'ensemble de cette population. Raisonnons en termes de quantité d'informations. Si nous ne disposons d'aucune observation (nous n'avons pas encore interrogé d'élèves), cette quantité est de 0. Si nous interrogeons un premier ou une première élève, nous obtenons une donnée supplémentaire, et donc un point d'information supplémentaire (+1). Admettons maintenant que nous collectons 30 observations dans une école, 10 dans une seconde et 5 dans une troisième. A priori, nous pourrions dire que nous avons ajouté 45 points d'information à notre total de connaissance. Ce serait le cas si les observations étaient indépendantes les unes des autres. Dans un tel contexte, chaque observation ajoute la même quantité d'information. Cependant, puisque les personnes étudiant dans la même école ont plus de chance de se ressembler, interroger les élèves d'une même école apporte moins d'information. Notez que plus la ressemblance entre les élèves d'une même école est forte, plus la quantité d'information est réduite. Nous sommes donc loin de disposer d'une quantité d'information égale à 45. Chaque réplication de l'expérience (demander à un ou une élève sa moyenne annuelle) n'apporte pas autant d'information qu'attendu si les observations étaient indépendantes, c'est pourquoi on parle de **pseudo-réplication**.\n\nLa pseudo-réplication influence directement l'inférence statistique puisque le calcul des différents tests statistiques assume que chaque observation apporte autant d'information que les autres. En cas de présence de pseudo-réplication, la quantité d'information présente dans l'échantillon est plus petite qu'attendu. Il est possible de voir cela comme une forme de surestimation de la taille de l'échantillon. En cas de pseudo-réplication, nous disposons en réalité de moins de données que ce que l'on attendrait d'un échantillon de cette taille, si les observations étaient indépendantes. La conséquence est la sous-estimation de la variabilité réelle des données et l'augmentation des risques de trouver des effets significatifs dans l'échantillon alors qu'ils ne le sont pas pour l'ensemble de la population.\n:::\n:::\n\n\n### Terminologie : effets fixes et effets aléatoires {#sec-0912}\n\nPuisque les effets des classes et des écoles ne sont pas propres aux élèves, il convient de les introduire différemment dans les modèles de régression. Nous appelons un effet fixe, un effet qui est propre aux observations que nous étudions et un effet aléatoire, un effet provoqué par une structure externe (effet de groupe, effet temporel et/ou effet spatial). Un modèle combinant à la fois des effets fixes et des effets aléatoires est appelé un **modèle à effets mixtes**, ou GLMM pour *Generalized Linear Mixed Model*. Tous les modèles que nous avons ajustés dans les sections précédentes ne comprenaient que des effets fixes alors qu'à plusieurs reprises, des effets aléatoires induits par l'existence de structure de groupe auraient pu (dû) être utilisés. Prenons pour exemple le modèle logistique binomial visant à prédire la probabilité d'utiliser le vélo comme mode de transport pour son trajet le plus fréquent. La variable multinomiale *Pays*, représentant le pays dans lequel les personnes interrogées résident, a été introduite comme un effet fixe. Cependant, l'effet du pays ne constitue pas une caractéristique propre aux individus; il s'agit plutôt d'un agrégat complexe mêlant culture, météorologie, politiques publiques et formes urbaines. À l'inverse, le sexe ou l'âge sont bien des caractéristiques intrinsèques des individus et peuvent être considérés comme des effets fixes.\n\nNotez que l'utilisation du terme *effet aléatoire* peut porter à confusion, car il est utilisé différemment en fonction du champ d'études. Parmi les différentes définitions relevées par @gelman2005analysis d'un effet aléatoire, citons les suivantes : \n\n* Les effets fixes sont identiques pour tous les individus, alors que les effets aléatoires varient (définition 1).\n\n* Les effets sont fixes s'ils sont intéressants en eux-mêmes, et les effets sont aléatoires si nous nous intéressons à la population dont ils sont issus (définition 2).\n\n* Lorsqu'un échantillon couvre une grande part de la population, la variable correspondante est un effet fixe. Si l'échantillon couvre une faible part de la population, l'effet est aléatoire (définition 3).\n\n* Si l'effet est censé provenir d'une variable aléatoire, alors il s'agit d'un effet aléatoire (définition 4).\n\n* Les effets fixes sont estimés par la méthode des moindres carrés ou par le maximum de vraisemblance, alors que les effets aléatoires sont estimés avec régularisation (*shrinkage*) (définition 5).\n\nIl est ainsi possible de se retrouver dans des cas où un effet serait classé comme fixe selon une définition et aléatoire selon une autre. La deuxième définition suppose même qu'un effet peut être aléatoire ou fixe selon l'objectif de l'étude. La dernière définition a l'avantage d'être mathématique, mais ne permet pas de décider si un effet doit être traité comme aléatoire ou fixe. Nous ne proposons pas ici de clore le débat, mais plutôt de donner quelques pistes de réflexion pour décider si un effet doit être modélisé comme fixe ou aléatoire:\n\n* Est-ce que l'effet en question est propre aux individus étudiés ou est externe aux individus? S'il est propre aux individus, il s'agit plus certainement d'un effet fixe. À titre d'exemple, il n'est pas possible de changer l'âge d'une personne, mais il est certainement possible de changer de ville de résidence.\n\n* Existe-t-il un nombre bien arrêté de catégories possibles pour l'effet en question? Si oui, il s'agit plus certainement d'un effet fixe. Il y a un nombre bien arrêté de catégories pour la variable sexe, mais pour la variable pays, de nombreuses autres valeurs peuvent être ajoutées. Il est également possible de se demander s'il semble cohérent d'effectuer un échantillonnage sur les catégories en question. Dans le cas des pays, nous pourrions mener une étude à l'échelle des pays et collecter des données sur un échantillon de l'ensemble des pays. Il existe donc une population de pays, ce que nous ne pouvons pas affirmer pour la variable sexe.\n\n* L'effet en question est direct ou indirect? Dans le second cas, l'effet en question est un agglomérat complexe découlant de plusieurs processus n'ayant pas été mesurés directement, ce qui correspond davantage à un effet aléatoire. Ainsi, l'effet du pays de résidence des individus sur leur probabilité d'utiliser le vélo est bien une agglomération complexe d'effets (culture, météorologie, orientation des politiques publiques, formes urbaines, etc.) n'ayant pas tous été mesurés. À l'inverse, l'âge d'un individu a bien un effet direct sur sa probabilité d'utiliser le vélo.\n\n* L'effet est-il le même pour tous les individus, ou doit-il varier selon le groupe dans lequel l'individu se situe? Si un effet doit varier en fonction d'un groupe, il s'apparente davantage à un effet aléatoire. Pour reprendre l'exemple de l'âge, nous pourrions décider que cette caractéristique des individus n'a peut-être pas le même effet en fonction du pays dans lequel vit l'individu et l'ajouter au modèle comme un effet aléatoire.\n\nVous comprendrez donc qu'une partie non négligeable du choix entre effet fixe ou effet aléatoire réside dans le cadre théorique à l'origine du modèle. Maintenant que cette distinction conceptuelle a été détaillée, nous pouvons passer à la présentation statistique des modèles GLMM.\n\n## Principes de base des GLMM {#sec-092}\n\nUn GLMM est donc un modèle GLM introduisant à la fois des effets fixes et des effets aléatoires. Si nous ne considérons que les effets de groupes, un GLMM peut avoir trois formes : constantes aléatoires, pentes aléatoires et constantes et pentes aléatoires. Nous présentons ici ces trois formes en reprenant l'exemple ci-dessus avec des élèves intégré(e)s dans des classes et pour lesquel(le)s le niveau de performance à l'examen ministériel de mathématique nous intéresse.\n\n### GLMM avec constantes aléatoires {#sec-0921}\n\nIl s'agit de la forme la plus simple d'un GLMM. Plus spécifiquement, elle autorise le modèle à avoir une constante différente pour chaque catégorie d'une variable multinomiale. En d'autres termes, si nous reprenons l'exemple des élèves dans leurs classes, nous tentons d'ajouter dans le modèle l'idée que chaque classe a une moyenne différente en termes de performance à l'examen de mathématique. Il est assez facile de visualiser ce que cela signifie à l'aide d'un graphique. Admettons que nous modélisons la note obtenue par des élèves du secondaire à l'examen ministériel de mathématique à partir d'une autre variable continue représentant le temps de travail moyen par semaine en dehors des heures de classe et d'une variable catégorielle représentant dans quelle classe se trouve chaque élève. Notez qu'il ne s'agit pas ici de vraies données, mais de simples simulations utilisées à titre d'illustration. Si nous ne tenons pas compte des classes, nous pouvons ajuster une régression linéaire simple entre nos deux variables continues comme le propose la @fig-randominter1.\n\n```{r}\n#| label: fig-randominter1\n#| echo: false\n#| fig-align: center\n#| fig-cap: Influence du temps de travail sur la performance scolaire d'élèves\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nsource(\"code_complementaire/JG_helper.R\")\nset.seed(11)\nlibrary(ggplot2)\n\ntofr <- function(float){\n return(gsub(\".\" , \",\", as.character(float), fixed = TRUE, useBytes = TRUE))\n}\n# Générer des effets aléatoires\ngroups <- c(\"A\" , \"B\" , \"C\" , \"D\" , \"E\" , \"F\" , \"G\" , \"H\")\nsig2 <- matrix(c(12, 0.1,\n 0.1, 0.5), \n nrow = 2, ncol = 2)\nmu2 <- c(inter = 0, coeff = 0)\ndf2 <- data.frame(data.frame(MASS::mvrnorm(n = length(groups), mu = mu2, Sigma = sig2)))\ndf2$name <- groups\ncolors <- hcl.colors(length(groups), palette = \"Dynamic\")\nnames(colors) <- groups\n# Générer des données\nn <- 300\ndf <- data.frame(\n X = rnorm(n,8,2),\n group = sample(df2$name, size = n, replace = TRUE)\n)\ndf3 <- merge(df, df2, by.x = \"group\", by.y = \"name\")\ndf3$Y <- 65 + df3$X*(1.5+df3$coeff) + df3$inter + rnorm(n = n, mean = 0, sd = 8)\ndf3$Y2 <- ifelse(df3$Y>=100, 100, df3$Y)\n# Afficher le tout!\nggplot(data = df3)+\n geom_point(aes(x = X, y = Y2, color = group), size = 1) + \n geom_smooth(aes(x = X, y = Y2), method='lm', formula= y~x, se = FALSE, color = \"black\", size = 1.2)+\n scale_color_manual(values = colors)+\n labs(y = \"Note à l'examen (%)\", x = \"Temps de travail (heures)\", color = \"Classe\")\n```\n\nNous constatons que notre modèle semble bien identifier la relation positive entre le temps de travail et le niveau de performance, mais la droite de régression est très éloignée de chaque point; nous avons ainsi énormément d'erreurs de prédiction, et donc des résidus importants. Jusqu'ici, nous avons vu que nous pouvons ajouter un prédicteur et intégrer l'effet des classes comme un effet fixe (@fig-randominter2).\n\n```{r}\n#| label: fig-randominter2\n#| echo: false\n#| fig-align: center\n#| fig-cap: Influence du temps de travail sur la performance scolaire d'élèves en tenant compte de l'effet de leur classe (effet fixe)\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nmodel <- lm(Y2 ~ X + group, data = df3)\nb1 <- model$coefficients[[2]]\ndiffs <- c(0, model$coefficients[c(3:length(model$coefficients))])\ndiffs <- diffs + model$coefficients[[1]]\ndf4 <- data.frame(\n inter = diffs,\n slope = b1,\n group = names(colors)\n)\nggplot(data = df3)+\n geom_point(aes(x = X, y = Y2, color = group), alpha = 0.8, size = 1)+\n geom_abline(data = df4, mapping = aes(intercept = inter, slope = slope, color = group), size = 1.2)+ \n scale_color_manual(values =colors)+\n labs(y = \"Note à l'examen (%)\", x = \"Temps de travail (heures)\", color = \"Classe\")\n```\n\nCet ajustement constitue une nette amélioration du modèle. Prenons un instant pour reformuler clairement notre modèle à effets fixes : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\sum^k_{j=1}{\\beta_j x_{2j}}\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm1}\n\navec $x_1$ le temps de travail et $x_2$ la classe ayant *k-1* modalités (puisqu'une modalité est la référence). Nous ajustons ainsi un coefficient pour chaque classe, ce qui a pour effet de tirer vers le haut ou vers le bas la prédiction du modèle en fonction de la classe. Cet effet est pour l'instant fixe, mais nous avons déterminé dans les sections précédentes qu'il serait conceptuellement plus approprié de le traiter comme un effet aléatoire.\n\nPassons à présent à la reformulation de ce modèle en transformant l'effet fixe de la classe en effet aléatoire.\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\upsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon}) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm2}\n\nRemarquez que l'effet fixe de la classe $\\sum^k_{j=1}{\\beta_j x_{2j}}$ a été remplacé par $\\upsilon$ qui est un terme aléatoire propre aux classes et qui suit une distribution normale centrée sur 0 ($\\upsilon \\sim Normal(0, \\sigma_{\\upsilon})$). En d’autres termes, cela signifie que l'effet des classes sur la performance des élèves suit une distribution normale et que si nous moyennons l'effet de toutes les classes, cet effet serait de 0. Nous ne modélisons donc plus l'effet moyen de chaque classe comme dans le modèle à effets fixes, mais la variabilité de l'effet des classes, soit $\\sigma_{\\upsilon}$. Notre modèle a donc deux variances, une au niveau des élèves ($\\sigma_e$) et une au niveau des classes ($\\sigma_{\\upsilon}$). Cette particularité explique souvent pourquoi ce type de modèle est appelé un modèle hiérarchique ou un modèle de partition de la variance. Cette information est particulièrement intéressante, car elle permet de calculer la part de la variance présente au niveau des élèves et celle au niveau des classes.\n\nSelon cette formulation, les constantes propres à chaque classe sont issues d'une distribution normale (nous reviendrons d'ailleurs sur ce choix plus tard), mais elles n'apparaissent pas directement dans le modèle. Ces paramètres ne sont plus estimés directement dans le modèle, mais a posteriori à partir des prédictions du modèle, et sont appelés *Best Linear Unbiased Predictor* (*BLUP*). Ces dernières précisions devraient d'ailleurs mieux vous aider à comprendre l'origine des définitions 1, 2 et 4 que nous avons mentionnées précédemment.\n\n```{r}\n#| label: fig-randominter3\n#| echo: false\n#| fig-align: center\n#| fig-cap: Influence du temps de travail sur la performance scolaire d'élèves en tenant compte de l'effet de leur classe (effet aléatoire)\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nlibrary(lme4)\nmodel2 <- lmer(Y2 ~ X + (1|group), data = df3)\ncoeffs <- coef(model2)$group\ndf5 <- data.frame(\n inter = coeffs[,1],\n slope = coeffs[,2],\n group = rownames(coeffs)\n)\nggplot(data = df3)+\n geom_point(aes(x = X, y = Y2, color = group), alpha = 0.8, size = 1)+\n geom_abline(data = df5, mapping = aes(intercept = inter, slope = slope, color = group), size = 1.2)+ \n scale_color_manual(values = colors)+\n labs(y = \"Note à l'examen sur 100\", x = \"Temps de travail (heures)\", color = \"Classe\")\n```\n\nEn comparant les figures [-@fig-randominter2] et [-@fig-randominter3], la différence ne saute pas aux yeux; vous pourriez alors légitimement vous demander pourquoi tous ces efforts et cette complexité théorique pour une différence d'ajustement minime? Trois arguments permettent de justifier l'utilisation de constantes aléatoires plutôt que d'effets fixes dans notre cas.\n\n#### Resserrement (*shrinkage*) et mutualisation (*partial pooling*) {#sec-09221}\n\nLe premier intérêt d'utiliser un effet aléatoire réside dans sa méthode d'estimation qui diffère largement d'un effet fixe. Il est assez facile de se représenter intuitivement la différence entre les deux. Dans le cas de nos élèves et de nos classes, lorsque l'effet des classes est estimé avec un effet fixe, l'effet de chaque classe est déterminé de façon totalement indépendante des autres classes. En d'autres termes, il n'est possible d'en apprendre plus sur une classe qu'en collectant des données dans cette classe (*separate pooling*). Si l'effet des classes est estimé comme un effet aléatoire, alors l'information entre les classes est mutualisée (*partial pooling*). L'idée étant que l'information que nous apprenons sur des élèves dans une classe est au moins en partie valide dans les autres classes. Cette méthode d'estimation est particulièrement intéressante si nous ne disposons que de peu d'observations dans certaines classes, puisque nous pouvons apprendre au moins une partie de l'effet de cette classe à partir des données des autres classes. Cela n'est pas possible dans le cas d'un effet fixe où l'on traite chaque classe en silo. @mcelreath2020statistical écrit à ce sujet qu'un effet fixe « n'a pas de mémoire » et qu'il oublie tout ce qu'il a appris sur les classes lorsqu'il passe à une nouvelle classe. La conséquence de cette mutualisation de l'information est un resserrement (*shrinkage*) des effets des classes autour de leur moyenne. Cela signifie que les tailles des effets de chaque classe sont plus petites dans le cas d'un effet aléatoire que d'un effet fixe. Utiliser des effets aléatoires conduit donc à une estimation plus conservatrice de l'effet des classes. Nous pouvons le visualiser en comparant les effets de classes dans le modèle à effets mixtes et le modèle à effets fixes. La @fig-randominter5 montre clairement que les effets aléatoires tendent à se rapprocher (resserrement) de leur moyenne (ligne noire), et donc à identifier des effets moins extrêmes pour chaque classe. Cette explication est directement en lien avec la définition 5 d'un effet aléatoire vu précédemment.\n\n```{r}\n#| label: fig-randominter5\n#| echo: false\n#| fig-align: center\n#| fig-cap: Comparaison des effets des classes pour le modèle à effets fixes versus le modèle à effets aléatoires\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\nlibrary(MuMIn)\nr2s <- r.squaredGLMM(model2)\ndf6 <- data.frame(\n fixed = df4$inter,\n random = df5$inter,\n group = df4$group\n)\nggplot() + \n geom_point(data = df4, mapping = aes(x = inter, y = group, color = \"fixed\")) +\n geom_point(data = df5, mapping = aes(x = inter, y = group, color = \"random\")) + \n geom_vline(xintercept = mean(df4$inter)) + \n labs(x = \"Effet de la classe\", y = \"Classe\", color = \"Type d'effet\") + \n scale_color_manual(values = c(\"fixed\" = \"red\", random = \"blue\"), labels = c(\"fixe\", \"aléatoire\"))\nsigma_u <- as.data.frame(VarCorr(model2))$sdcor[[1]]\nsigma_e <- as.data.frame(VarCorr(model2))$sdcor[[2]]\n```\n\n#### Prédiction pour de nouveaux groupes {#sec-09222}\n\nUne autre retombée directe de la mutualisation de l'information est la capacité du modèle à envisager les effets plausibles pour de nouvelles classes. En effet, puisque nous avons approximé l'effet des classes sous forme d'une distribution normale dont nous connaissons la moyenne (0) et l'écart-type ($\\sigma_{\\upsilon}$), nous pouvons **simuler** des données pour de nouvelles classes, ce que ne permet pas un effet fixe. Ce constat est d'ailleurs directement lié à la définition 3 des effets aléatoires vue précédemment. Dans notre cas, $\\sigma_{\\upsilon}$ = `r tofr(round(sigma_u,3))`, ce qui nous permet d'affirmer que dans 95 % des classes, l'effet de la classe sur la performance scolaire doit se trouver entre -1,96 $\\times$ `r tofr(round(sigma_u,3))` et +1,96 $\\times$ `r tofr(round(sigma_u,3))`, soit l'intervalle [`r tofr(round(-1.96*sigma_u,3))`, `r tofr(round(1.96*sigma_u,3))`].\n\n#### Partition de la variance {#sec-09223}\n\nUn autre avantage net de l'effet aléatoire est l'estimation du paramètre $\\sigma_{\\upsilon}$, soit la variance au niveau des écoles. Ce dernier permet de calculer un indicateur très intéressant, soit le **coefficient de corrélation intraclasse (ICC)** :\n\n$$\nICC = \\frac{\\sigma_{\\upsilon}}{\\sigma_{\\upsilon} + \\sigma_{e}}\n$$ {#eq-glmm3}\n\nIl s'agit donc du pourcentage de la variance présente au niveau des classes, qui peut être interprétée comme le niveau de corrélation (de ressemblance) entre les élèves d'une même classe.\n\nDans notre cas, l'écart-type est de `r tofr(round(sigma_u,3))` au niveau des classes et de `r tofr(round(sigma_e,3))` au niveau des élèves. Nous pouvons donc calculer l'ICC au niveau des classes avec la formule précédente : `r tofr(round(sigma_u,3))` / (`r tofr(round(sigma_u,3))` + `r tofr(round(sigma_e,3))`) = `r tofr(round(sigma_u /(sigma_u + sigma_e),3))`. Cela signifie que le niveau de corrélation entre deux élèves d'une même classe est de `r tofr(round(sigma_u /(sigma_u + sigma_e),3))` ou encore que `r tofr(round(sigma_u /(sigma_u + sigma_e),3)*100)` % de la variance de *Y* se situe au niveau des classes, ce qui est conséquent. Une telle information ne peut être extraite d'un modèle avec uniquement des effets fixes. Notez ici que l'ICC peut être calculé pour chaque niveau d'un modèle à effet mixte. Dans notre exemple, nous n'avons qu'un seul niveau au-dessus des élèves, soit les classes, mais nous pourrions étendre cette logique à des écoles, par exemple. Notez également que cette formule de l'ICC n'est valide que pour un modèle pour lequel la distribution de la variable *Y* est normale. Des développements apparaissent pour proposer d'autres formulations adaptées à d'autres distributions, mais il est également possible d'estimer l'ICC à partir des simulations issues du modèle [@NakagawaICC; @aly2014reliability; @stryhn2006interpretation; @wu2012comparison]. L'idée générale reste d'expliquer la partition de la variance dans le modèle.\n\nEn plus de l'ICC, il est également possible de calculer les **R^2^ marginal et conditionnel** du modèle. Le premier représente la variance expliquée par le modèle si seulement les effets fixes sont pris en compte, et le second si les effets fixes et aléatoires sont pris en compte. Distinguer les deux sources d'information permet de mieux cerner l'importance du rôle des écoles dans la performance des élèves. Dans notre cas, nous obtenons un R^2^ marginal de `r tofr(round(r2s[[1]],3))` et un R^2^ conditionnel de `r tofr(round(r2s[[2]],3))`, ce qui nous confirme à nouveau que le rôle joué par la classe dans le niveau de performance est loin d'être négligeable.\n\n### GLMM avec pentes aléatoires {#sec-0923}\n\nDans cette seconde version du GLMM, nous n'envisageons plus de faire varier une constante en fonction des classes, mais un coefficient en fonction des classes. Admettons que nous voulons tester ici si l’effet du temps de travail ($x_1$) sur la performance scolaire (*Y*) n'est pas constant partout. En d'autres termes, nous supposons que, dans certaines classes, le temps de travail hebdomadaire en dehors de l’école est plus ou moins efficace que d’autres classes. L'idée sous-jacente est que nous n'observons pas de différence en termes de moyenne entre deux classes, mais en termes d'effet pour notre variable $x_1$. À nouveau, nous pouvons nous contenter d'un effet fixe pour intégrer cette idée dans notre modèle. Pour cela, nous avons simplement à ajouter une interaction entre notre variable quantitative *temps de travail* et notre variable qualitative *classe*. Nous obtenons le résultat décrit par la @fig-randomslope. Notez ici que la constante est bien la même pour chaque classe (les lignes s'intersectent à 0 sur l'axe des x), et que seule la pente change.\n\n```{r}\n#| label: fig-randomslope\n#| fig-align: center\n#| fig-cap: Influence du temps de travail sur la performance scolaire d'élèves en interaction avec la classe (effet fixe)\n#| out-width: \"70%\"\n#| echo: false\n#| message: false\n#| warning: false\nmodel <- lm(Y2 ~ X + X:group, data = df3)\ninter <- model$coefficients[[1]]\nb1 <- model$coefficients[[2]]\ndiffs <- c(0, model$coefficients[c(3:length(model$coefficients))])\ndiffs <- b1 + diffs\ndf4 <- data.frame(\n inter = inter,\n slope = diffs,\n group = names(colors)\n)\nggplot(data = df3)+\n geom_point(aes(x = X, y = Y2, color = group), alpha = 0.8, size = 1)+\n geom_abline(data = df4, mapping = aes(intercept = inter, slope = slope, color = group), size = 1.2)+ \n scale_color_manual(values =colors)+\n labs(y = \"Note à l'examen sur 100\", x = \"Temps de travail (heures)\", color = \"Classe\") + \n xlim(0, max(df3$X)+1)\n```\n\nLa formulation de ce modèle à effets fixes seulement est la suivante : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\sum^k_{j=1}{\\beta_j x_{2j} x_1}\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm4}\n\n\nNous constatons donc que nous avons un effet principal $\\beta_1$ décrivant le lien entre le temps de travail et la note obtenue à l'examen pour l'ensemble des élèves, ainsi qu'un bonus ou un malus sur cet effet $\\beta_j$ s'appliquant en fonction de la classe. Nous pouvons reformuler ce modèle pour inclure cet effet spécifique par classe comme un effet aléatoire :\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\upsilon x_1 \\\\\n&\\upsilon \\sim Normal(0,\\sigma_{\\upsilon})\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm5}\n\nNous formulons ici un modèle dans lequel la classe modifie l'effet de la variable *temps d'étude* sur la variable *note à l'examen*. L'effet moyen de $x_1$ (propre aux individus) est capté par le coefficient $\\beta_1$, les bonus ou malus ajoutés à cet effet par la classe sont issus d'une distribution normale centrée sur 0 avec un écart-type, soit $\\sigma_{\\upsilon}$. À nouveau, l'idée est que si nous moyennons l'effet de toutes les classes, nous obtenons 0. Aussi, le fait de modéliser cet effet comme un effet aléatoire nous permet de partitionner la variance, de mutualiser l'information entre les classes et de resserrer l'estimation des effets des classes.\n\nLes résultats pour ce second modèle sont présentés à la @fig-randomslope2, et une comparaison entre les estimations des effets fixes et des effets aléatoires est présentée à la @fig-randomslope3. Nous pouvons ainsi constater à nouveau l'effet de resserrement provoqué par l'effet aléatoire.\n\n\n```{r}\n#| label: fig-randomslope2\n#| echo: false\n#| fig-align: center\n#| fig-cap: Influence du temps de travail sur la réussite scolaire d'élèves en interaction avec la classe (effet aléatoire)\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nmodel2 <- lmer(Y2 ~ X + (-1+X|group), data = df3)\ncoeffs <- coef(model2)$group\ndf5 <- data.frame(\n inter = coeffs[,1],\n slope = coeffs[,2],\n group = rownames(coeffs)\n)\nggplot(data = df3)+\n geom_point(aes(x = X, y = Y2, color = group), alpha = 0.8, size = 1)+\n geom_abline(data = df5, mapping = aes(intercept = inter, slope = slope, color = group), size = 1.2)+ \n scale_color_manual(values =colors)+\n labs(y = \"Note à l'examen sur 100\", x = \"Temps de travail (heure)\", color = \"Classe\") + \n xlim(0, max(df3$X)+1)\n```\n\n```{r}\n#| label: fig-randomslope3\n#| echo: false\n#| fig-align: center\n#| fig-cap: Influence du temps de travail sur la réussite scolaire d'élèves en interaction avec la classe (effet aléatoire)\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\ndf6 <- data.frame(\n fixed = df4$slope,\n random = df5$slope,\n group = df4$group\n)\nggplot() + \n geom_point(data = df4, mapping = aes(x = slope, y = group, color = \"fixed\")) +\n geom_point(data = df5, mapping = aes(x = slope, y = group, color = \"random\")) + \n geom_vline(xintercept = mean(df4$slope)) + \n labs(x = \"Effet du temps de travail\", y = \"classe\", color = \"type d'effet\") + \n scale_color_manual(values = c(\"fixed\" = \"red\", random = \"blue\"), labels = c(\"fixe\", \"aléatoire\"))\nrs2 <- r.squaredGLMM(model2)\n```\n\nLorsque nous intégrons des pentes aléatoires dans un modèle, nous faisons face au problème suivant : la variance associée aux pentes aléatoires n'est pas fixe, mais proportionnelle à la variable *X* autorisée à varier. Si nous comparons la @fig-randominter3 (constantes aléatoires) et la @fig-randomslope2 (pentes aléatoires), nous constatons bien que la dispersion des prédictions du modèle (représentées par les lignes) augmente dans le cas de pentes aléatoires et reste identique dans le cas des constantes aléatoires. La conséquence pratique est qu'il existe un nombre infini de valeurs possibles pour l'ICC. Dans ce contexte, il est préférable de laisser de côté cet indicateur et de ne reporter que les R^2^ marginal et conditionnel. Dans notre cas, nous obtenons les valeurs `r tofr(round(rs2[[1]],3))` et `r tofr(round(rs2[[2]],3))`, ce qui confirme une fois encore que le rôle joué par la classe est loin d'être négligeable.\n\n### GLMM avec constantes et pentes aléatoires {#sec-0924}\n\nVous l'aurez certainement deviné en lisant le titre de cette section : il est tout à fait possible de combiner à la fois des constantes et des pentes aléatoires dans un modèle. Cela augmente bien sûr la complexité du modèle et introduit quelques subtilités comme la notion de distribution normale multivariée, mais chaque chose en son temps.\n\nSi nous reprenons notre exemple avec nos élèves et nos classes, combiner à la fois des constantes et des pentes aléatoires revient à formuler l'hypothèse que chaque classe a un effet sur la moyenne de la performance de ses élèves, mais également un effet sur l'efficacité du temps de travail. Il est possible de créer un modèle avec uniquement des effets fixes tenant compte de ces deux aspects en ajoutant dans le modèle la variable multinomiale *classe* ainsi que son interaction avec la variable *temps de travail*. La formulation de ce modèle à effets fixes est la suivante :\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\sum^k_{j=1}{\\beta_{2j} x_{2j} + \\beta_{3j} x_{2j} x_1}\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm6}\n\nNous pouvons représenter les résultats de ce modèle avec la @fig-fullrandom1.\n\n```{r}\n#| label: fig-fullrandom1\n#| echo: false\n#| fig-align: center\n#| fig-cap: Influence du temps de travail sur la performance scolaire d'élèves en tenant compte de l'effet de leur classe et de l'effet de la classe sur l'efficacité du temps de travail (effet fixe)\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\nmodel <- lm(Y2 ~ X*group, data = df3)\nb1 <- model$coefficients[[2]]\ninter <- model$coefficients[[1]]\ninters <- c(0, model$coefficients[3:(2+length(colors)-1)])\ncoeffs <- c(0, model$coefficients[(2+length(colors)):length(model$coefficients)])\ndf4 <- data.frame(\n inter = inters + inter,\n slope = b1 + coeffs,\n group = names(colors)\n)\nggplot(data = df3)+\n geom_point(aes(x = X, y = Y2, color = group), alpha = 0.8, size = 1)+\n geom_abline(data = df4, mapping = aes(intercept = inter, slope = slope, color = group), size = 1.2)+ \n scale_color_manual(values =colors)+\n labs(y = \"Note à l'examen (%)\", x = \"Temps de travail (heures)\", color = \"Classe\")\n```\n\nNous reformulons à présent ce modèle pour intégrer l'effet moyen de chaque classe (constante) et l'effet des classes sur l'efficacité du temps de travail (pente) comme deux effets aléatoires : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\upsilon_1 + (\\beta_1 + \\upsilon_2) x_1\\\\\n&\\left(\\begin{array}{l}\n\\upsilon_{1} \\\\\n\\upsilon_{2}\n\\end{array}\\right) \\sim \\mathcal{N}\\left(\\left(\\begin{array}{l}\n0 \\\\\n0\n\\end{array}\\right),\\left(\\begin{array}{cc}\n\\sigma_{\\upsilon_1} & \\sigma_{\\upsilon_1\\upsilon_2} \\\\\n \\sigma_{\\upsilon_1\\upsilon_2} & \\sigma_{\\upsilon_1}\n\\end{array}\\right)\\right) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm7}\n\nPas de panique! Cette écriture peut être interprétée de la façon suivante :\n\nLe modèle a deux effets aléatoires, l'un faisant varier la constante en fonction de la classe ($\\upsilon_1$) et l'autre l'effet de la classe sur l'efficacité du temps de travail ($\\upsilon_2$). Ces deux effets sont issus d'une distribution normale bivariée (une dimension par effet aléatoire). Cette distribution normale bivariée a donc deux moyennes et ces deux moyennes sont à 0 (les effets s'annulent si nous considérons toutes les classes ensemble). Elle dispose également d'une variance par effet aléatoire ($\\sigma_{\\upsilon_1}$ et $\\sigma_{\\upsilon_2}$) et d'une covariance entre les deux effets aléatoires ($\\sigma_{\\upsilon_1\\upsilon_2}$). Cette covariance permet de tenir compte du fait que, potentiellement, les classes avec une constante plus élevée pourraient systématiquement avoir une efficacité du temps de travail plus faible ou plus élevée. Cette formulation implique donc d'ajuster trois paramètres de variance : $\\sigma_{\\upsilon_1}$, $\\sigma_{\\upsilon_2}$ et $\\sigma_{\\upsilon_1\\upsilon_2}$. Il peut arriver que nous n'ayons pas assez de données pour estimer ces trois paramètres, ou que nous décidions, pour des raisons théoriques, qu'aucune corrélation ne soit attendue entre $\\sigma_{\\upsilon_1}$ et $\\sigma_{\\upsilon_2}$. Dans ce cas, il est possible de fixer $\\sigma_{\\upsilon_1\\upsilon_2}$ à 0, ce qui revient à indiquer au modèle que $\\upsilon_1$ et $\\upsilon_2$ proviennent de deux distributions normales distinctes, nous pouvons donc écrire :\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\upsilon_1 + (\\beta_1 + \\upsilon_2) x_1\\\\\n&\\left(\\begin{array}{l}\n\\upsilon_{1} \\\\\n\\upsilon_{2}\n\\end{array}\\right) \\sim \\mathcal{N}\\left(\\left(\\begin{array}{l}\n0 \\\\\n0\n\\end{array}\\right),\\left(\\begin{array}{cc}\n\\sigma_{\\upsilon_1} & 0 \\\\\n 0 & \\sigma_{\\upsilon_1}\n\\end{array}\\right)\\right) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm8}\n\nCe qui est identique à : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\upsilon_1 + (\\beta_1 + \\upsilon_2) x_1\\\\\n&\\upsilon_{1} \\sim Normal(0,\\sigma_{\\upsilon_1}) \\\\\n&\\upsilon_{2} \\sim Normal(0,\\sigma_{\\upsilon_2}) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glmm9}\n\nNous avons déjà abordé la notion de covariance dans la [section @sec-042]. Pour rappel, la covariance dépend de l'unité de base des deux variables sur laquelle elle est calculée. Ici, il s'agit d'un coefficient et d'une constante. Il est donc préférable de la standardiser pour obtenir la corrélation entre les deux effets : \n\n$$\ncorr(\\upsilon_1;\\upsilon_2) = \\frac{\\sigma_{\\upsilon_1\\upsilon_2}}{\\sqrt{\\sigma_{\\upsilon_1}}\\sqrt{\\sigma_{\\upsilon_2}}}\n$$ {#eq-glmm10}\n\nSi cette corrélation est positive, cela signifie que les classes ayant tendance à avoir un effet positif sur la performance scolaire ont également tendance à influencer positivement l'efficacité du temps de travail. À l'inverse, une corrélation négative signifie que l'efficacité du temps de travail a tendance à être plus faible dans les classes où la performance scolaire moyenne est élevée. Si la corrélation n'est pas significative, c'est que les deux effets sont indépendants l'un de l'autre.\n\nPour cet exemple, nous conservons la première formulation afin de montrer comment interpréter $\\sigma_{\\upsilon_1\\upsilon_2}$, mais nous ne disposons probablement pas de suffisamment de classes différentes pour estimer correctement ces trois paramètres. Les résultats de ce modèle sont représentés à la @fig-fullrandom2.\n\n```{r}\n#| label: fig-fullrandom2\n#| echo: false\n#| fig-align: center\n#| fig-cap: Influence du temps de travail sur la performance scolaire d'élèves en tenant compte de l'effet de leur classe et de l'effet de la classe sur l'efficacité du temps de travail (effet aléatoire)\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\ndf3$x <- scale(df3$X, center = TRUE, scale = TRUE)\nmodel2 <- lmer(Y2 ~ X + (X|group), data = df3,\n control = lmerControl(optimizer = \"bobyqa\"))\ncoeffs <- coef(model2)$group\ndf5 <- data.frame(\n inter = coeffs[,1],\n slope = coeffs[,2],\n group = rownames(coeffs)\n)\nggplot(data = df3)+\n geom_point(aes(x = X, y = Y2, color = group), alpha = 0.8, size = 1)+\n geom_abline(data = df5, mapping = aes(intercept = inter, slope = slope, color = group), size = 1.2)+ \n scale_color_manual(values =colors)+\n labs(y = \"Note à l'examen (%)\", x = \"Temps de travail (heures)\", color = \"Classe\")\ncovmod <- VarCorr(model2)$group[1,2]\nsigma1 <- VarCorr(model2)$group[1,1]\nsigma2 <- VarCorr(model2)$group[2,2]\n```\n\nNous pouvons ainsi constater que pour ce troisième modèle, l'effet de resserrement est bien plus prononcé que pour les modèles précédents (@fig-fullrandom3). Si nous nous fions au modèle à effets fixes (@fig-fullrandom1)), alors l'effet de l'école sur l'efficacité du temps de travail est très important. En revanche, le modèle à effet aléatoire identifie que la différence de moyenne entre les écoles est importante, mais la différence en termes d'efficacité du temps de travail est beaucoup plus anecdotique.\n\n```{r}\n#| label: fig-fullrandom3\n#| echo: false\n#| fig-align: center\n#| fig-cap: Comparaison des effets fixes et aléatoires pour le modèle intégrant l'effet des classes et l'interaction entre les classes et le temps de travail\n#| message: false\n#| warning: false\n#| out-width: \"90%\"\n\nlibrary(ggpubr)\nplot1 <- ggplot() + \n geom_point(data = df4, mapping = aes(x = inter, y = group, color = \"fixed\")) +\n geom_point(data = df5, mapping = aes(x = inter, y = group, color = \"random\")) + \n geom_vline(xintercept = mean(df4$inter)) + \n labs(x = \"constante\", y = \"classe\", color = \"type d'effet\") + \n scale_color_manual(values = c(\"fixed\" = \"red\", random = \"blue\"), labels = c(\"fixe\", \"aléatoire\"))\nplot2 <- ggplot() + \n geom_point(data = df4, mapping = aes(x = slope, y = group, color = \"fixed\")) +\n geom_point(data = df5, mapping = aes(x = slope, y = group, color = \"random\")) + \n geom_vline(xintercept = mean(df4$slope)) + \n labs(x = \"pente\", y = \"classe\", color = \"type d'effet\") + \n scale_color_manual(values = c(\"fixed\" = \"red\", random = \"blue\"), labels = c(\"fixe\", \"aléatoire\"))\nggarrange(plot1, plot2, ncol = 2, nrow = 1, common.legend = TRUE)\nrs2 <- r.squaredGLMM(model2)\n```\n\nNotre modèle estime les valeurs de $\\sigma_{\\upsilon_1}$ à `r tofr(round(sigma1, 3))`, de $\\sigma_{\\upsilon_2}$ à `r tofr(round(sigma2, 3))` et de $\\sigma_{\\upsilon_1\\upsilon_2}$ à `r tofr(round(covmod, 3))`. La corrélation entre les deux effets est donc de `r tofr(round(covmod/(sqrt(sigma1)*sqrt(sigma2)), 3))`, ce qui est relativement faible (pour l'anecdote, notez que la valeur originale de corrélation entre ces deux effets était de 0,1 lorsque nous avons simulé ces données, notre modèle a donc bien été capable de retrouver le paramètre original). À nouveau, puisque nous avons des pentes aléatoires dans ce modèle, nous ne pouvons pas calculer l'ICC; nous pouvons cependant rapporter les R^2^ marginal et conditionnel. Leurs valeurs respectives sont `r tofr(round(r2s[[1]],3))` et `r tofr(round(r2s[[2]],3))`, ce qui nous confirme une nouvelle fois que l'ajout d'effets aléatoires contribue à expliquer une partie importante de la variance de la performance scolaire.\n\nPour terminer cette section, comparons brièvement les trois modèles (constantes aléatoires, pentes aléatoires, constantes et pentes aléatoires) pour déterminer lequel est le mieux ajusté à nos données. Nous ajoutons également un quatrième modèle dans lequel les deux effets aléatoires sont présents, mais non corrélés ($\\sigma_{\\upsilon_1\\upsilon_2}=0$). Le @tbl-fullrandom4 nous permet de constater que l'ajout des constantes aléatoires joue un rôle essentiel dans le premier modèle : le R^2^ conditionnel est plus que deux fois supérieur au R^2^ marginal. Cependant, l'ajout des pentes aléatoires dans les trois autres modèles apporte finalement très peu d'information, nous laissant penser que l'effet de la classe sur le temps de travail est faible, voire inexistant.\n\n\n```{r}\n#| label: tbl-fullrandom4\n#| tbl-cap: Comparaison des trois modèles à effets aléatoires\n#| echo: false\n#| message: false\n#| warning: false\n#| out-width: \"90%\"\n\nmodel1 <- lmer(Y2 ~ X + (1|group), data = df3)\nmodel2 <- lmer(Y2 ~ X + (-1+X|group), data = df3)\nmodel3 <- lmer(Y2 ~ X + (X|group), data = df3,\n control = lmerControl(optimizer = \"bobyqa\"))\nmodel4 <- lmer(Y2 ~ X + (X||group), data = df3,\n control = lmerControl(optimizer = \"bobyqa\"))\nmodels <- list(model1, model2, model3, model4)\ntableau <- data.frame(\n name = c(\"Constantes aléatoires\", \"Pentes aléatoires\", \"Pentes et constantes aléatoires corrélées\", \"Pentes et constantes aléatoires non corrélées\"),\n aic = round(sapply(models, function(i){AIC(i)}),1),\n r2m = round(sapply(models, function(i){r.squaredGLMM(i)[[1]]}),2),\n r2c = round(sapply(models, function(i){r.squaredGLMM(i)[[2]]}),2)\n)\nknitr::kable(tableau,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"modèle\" , \"AIC\" , \"R2 marginal\" , \"R2 conditionnel\"),\n align= c(\"l\" , \"r\", \"r\", \"r\"))\n```\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Modèles à effets mixtes avec des structures croisées**\n:::\n::: bloc_aller_loin-body\nJusqu'à présent, nous avons abordé des modèles GLMM comprenant des structures imbriquées (*nested* en anglais), c'est-à-dire qu'une observation d'un niveau 1 est incluse dans un et un seul groupe du niveau 2. Comme structure imbriquée à trois niveaux, nous avons vu comme exemple des élèves intégrés dans des classes elles-mêmes intégrées dans des écoles (@fig-glmmecoles) : un ou une élève appartient à une et une seule classe qui est elle-même localisée dans une et une seule école (élève / classe / école).\n\nNotez qu'il est aussi possible d'avoir des structures des données croisées (*crossed*).\n\nAdmettons à présent que nous ne nous intéressons pas à la classe dans laquelle se situe l'élève, mais plutôt à la personne qui enseigne. Admettons également que ces personnes peuvent donner des cours dans plusieurs écoles. Nous nous retrouvons dans un cas de figure où une personne qui enseigne peut se situer dans plusieurs écoles, ce qui diffère du cas précédent où chaque classe appartient à une seule école. Dans ce second cas, on parle d'une **structure croisée** plutôt qu'imbriquée.\n\nSi les personnes enseignent dans toutes les écoles, il est possible de dire que le design d'étude est croisé complet ou croisé partiel si elles n'enseignent que dans certaines écoles. La @fig-crossednested résume ces trois situations.\n\n\n\n![Différentes structures de données hiérarchiques (imbriquée versus croisée)](images/Chap09/glmm_croise-nested.png){#fig-crossednested width=\"50%\" fig-align=\"center\"}\n\nIl est important de bien saisir la structure de son jeu de données, car l'estimation d'un modèle avec effets imbriqués ou croisés peut donner des résultats parfois significativement différents. De plus, un modèle imbriqué est généralement moins difficile à ajuster qu'un modèle croisé. En effet, dans un modèle imbriqué, deux personnes étudiant dans deux écoles différentes sont jugées indépendantes. Dans un modèle croisé, deux élèves provenant de deux écoles différentes peuvent tout de même partager une dépendance du fait qu'ils ou elles ont pu avoir le même professeur ou la même professeure. La structure de dépendance (et donc de la matrice de covariance des effets aléatoires) est ainsi plus complexe pour un modèle croisé.\n:::\n:::\n\n\n## Conditions d'application des GLMM {#sec-093}\n\nPuisque les GLMM sont une extension des GLM, ils partagent l'essentiel des conditions d'application de ces derniers. Pour simplifier, si vous ajustez un modèle GLMM avec une distribution Gamma, vous devez réaliser les mêmes tests que ceux pour un simple GLM avec une distribution Gamma.\n\nUne question importante se pose souvent lorsque nous ajustons des modèles GLMM : **combien de groupes faut-il au minimum aux différents niveaux?** En effet, pour estimer les différentes variances, nous devons disposer de suffisamment de groupes différents. Dans le cas d'un modèle avec uniquement une constante aléatoire, il est fréquent de lire que nous devons disposer au minimum de cinq groupes différents [@gelman2006data], en dessous de ce minimum, traiter l'effet comme aléatoire plutôt que fixe apporte très peu d'information. De plus, l'estimation des variances pour chaque niveau est très imprécise, donnant potentiellement des valeurs inexactes pour l'ICC et polluant l'interprétation. Avec cinq groupes ou moins, il est certainement plus judicieux d'ajuster seulement un effet fixe. Dans un modèle avec plusieurs effets aléatoires et plusieurs variances / covariances à estimer, ce nombre doit être augmenté proportionnellement, à moins que les effets aléatoires ne soient estimés indépendamment les uns des autres. Notez ici que, si l'enjeu du modèle était d'estimer avec une grande précision les paramètres de variances, il faudrait compter au minimum une centaine de groupes. Il n'est pas nécessaire d'avoir le même nombre d'observations par groupe, car les modèles GLMM partagent l'information entre les groupes. Cependant, dans les groupes avec peu d'observations (inférieur à 15), l'estimation de leur effet propre (BLUP) est très incertaine.\n\nPuisque les GLMM font intervenir la distribution normale aux niveaux supérieurs du modèle, il est nécessaire de vérifier si les hypothèses qu'elle implique sont respectées. Il s'agit essentiellement de deux hypothèses : les effets aléatoires suivent bien une distribution normale (univariée ou multivariée), et la variance au sein des groupes est bien homogène.\n\n### Vérification de la distribution des effets aléatoires {#sec-0931}\n\nReprenons la formulation d'un modèle simple avec seulement deux niveaux et seulement une constante aléatoire:\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\upsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon}) \\\\\n&g(x) = x\n\\end{aligned}\n$$\n\nCe modèle formule l'hypothèse que les constantes aléatoires $\\upsilon$ proviennent d'une distribution normale avec une moyenne de 0 et un écart-type $\\sigma_{\\upsilon}$. La première étape du diagnostic est donc de vérifier si les constantes aléatoires suivent bien une distribution normale, ce que nous pouvons faire habituellement avec un diagramme quantile-quantile. Si nous reprenons notre exemple avec nos données de performance scolaire des sections précédentes, nous obtenons la @fig-diagglmm1. Puisque les points tombent bien approximativement sur la ligne rouge, nous pouvons conclure que cette condition d'application est bien respectée. Notez qu'il est également possible d'utiliser ici un des tests vus dans le [chapitre @sec-chap02] pour tester formellement la distribution des constantes aléatoires, mais nous disposons rarement de suffisamment de valeurs différentes pour qu'un tel test soit pertinent.\n\n```{r}\n#| label: fig-diagglmm1\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution normale univariée des constantes aléatoires\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\nmodel2 <- lmer(Y2 ~ X + (1|group), data = df3)\nqplot(sample = ranef(model2)$group[,1])+\n geom_qq_line(line.p = c(0.25, 0.75),\n color = \"red\", size=0.8, linetype = \"dashed\")+\n labs(title = \"Diagramme quantile-quantile\",\n x = \"Valeurs théoriques\",\n y = \"Constantes aléatoires\")\n```\n\nCette vérification est bien sûr à appliquer à chacun des niveaux (en dehors du niveau de base) du modèle étudié.\n\nSi nous nous intéressons maintenant au modèle avec constantes et pentes aléatoires, nous avons deux cas de figure:\n\n* Notre modèle inclut une covariance entre les constantes et les pentes; elles proviennent donc d'une distribution normale bivariée.\n\n* Notre modèle considère les pentes et les constantes comme indépendantes; elles proviennent donc de deux distributions normales distinctes.\n\nLe second cas est de loin le plus simple puisqu'il nous suffit de réaliser un graphique de type quantile-quantile pour les deux effets aléatoires séparément. Dans le premier cas, il nous faut adapter notre stratégie pour vérifier si les deux effets aléatoires suivent conjointement une distribution normale multivariée. Pour cela, nous devons, dans un premier temps, observer séparément la distribution des pentes et des constantes, puisque chaque variable provenant d'une distribution normale multivariée suit elle-même une distribution normale univariée [@burdenski2000evaluating]. Nous pouvons, dans un second temps, construire un graphique nous permettant de juger si nos pentes et nos constantes suivent bien la distribution normale bivariée attendue par le modèle. Pour l'illustrer, nous reprenons le modèle sur la performance scolaire intégrant des pentes et des constantes aléatoires avec une covariance estimée entre les deux.\n\nLa @fig-diagglmm2 représente donc les deux graphiques quantile-quantile univariés. Les deux semblent indiquer que nos effets aléatoires suivent bien chacun une distribution normale. La @fig-diagglmm3 montre la distribution normale bivariée attendue par le modèle avec des ellipses représentant différents percentiles de cette distribution. Les valeurs des effets aléatoires sont représentées par des points noirs. Seulement 5 % des points noirs devraient se trouver dans la première ellipse et 95 % des points devraient se trouver dans la quatrième ellipse. En revanche, seulement 20 % des points devraient se trouver dans le dernier anneau et seulement 5 % des points en dehors de cet anneau. Il faut donc évaluer si les points sont plus ou moins centrés que ce que nous attendons. Pour simplifier la lecture, il est possible de rajouter des points grisés en arrière-plan représentant des réalisations possibles de cette distribution normale bivariée. Les vrais points noirs devraient avoir une dispersion similaire à celle des points grisés. Dans notre cas, ils semblent suivre un patron cohérent avec notre distribution normale bivariée. Dans le cas contraire, cela signifierait que le modèle doit être révisé.\n\n```{r}\n#| label: fig-diagglmm2\n#| echo: false\n#| fig-align: center\n#| fig-cap: Multiples distributions normales univariées des constantes et pentes aléatoires\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\nmodel2 <- lmer(Y2 ~ X + (X|group), data = df3,\n control = lmerControl(optimizer = \"bobyqa\"))\nre_effects <- ranef(model2)$group\nq1 <- qplot(sample = re_effects[,1])+\n geom_qq_line(line.p = c(0.25, 0.75),\n color = \"red\", size=0.8, linetype = \"dashed\")+\n labs(x = \"Valeurs théoriques\",\n y = \"Constantes aléatoires\")\nq2 <- qplot(sample = re_effects[,2])+\n geom_qq_line(line.p = c(0.25, 0.75),\n color = \"red\", size=0.8, linetype = \"dashed\")+\n labs(x = \"Valeurs théoriques\",\n y = \"Pentes aléatoires\")\nggarrange(q1, q2)\n```\n\n\n```{r}\n#| label: fig-diagglmm3\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution normale bivariée des constantes et des pentes aléatoires\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\ncor_mat <- VarCorr(model2)[[1]]\nre_effects <- data.frame(ranef(model2)$group)\nnames(re_effects) <- c(\"constante\" , \"pente\")\nlibrary(ellipse)\nlevels <- c(0.05,0.25,0.75,0.95)\nels <- lapply(levels, function(i){\n el <- data.frame(ellipse(cor_mat, center = c(0,0), level = i))\n names(el) <- c(\"x\" , \"y\")\n return(el)\n})\nref_points <- data.frame(data.frame(MASS::mvrnorm(n = 1000, mu = c(0,0), Sigma = cor_mat)))\nnames(ref_points) <- c(\"x\" , \"y\")\nggplot() + \n geom_point(aes(x = x, y = y), data = ref_points, alpha = 0.3, size = 0.4) + \n geom_path(data = els[[1]], aes(x = x, y = y, color = \"a\")) + \n geom_path(data = els[[2]], aes(x = x, y = y, color = \"b\")) + \n geom_path(data = els[[3]], aes(x = x, y = y, color = \"c\")) +\n geom_path(data = els[[4]], aes(x = x, y = y, color = \"d\")) + \n geom_point(data = re_effects, aes(x = constante, y = pente))+\n scale_color_manual(values = c(\"a\" = \"#90e0ef\",\n \"b\" = \"#00b4d8\",\n \"c\" = \"#0077b6\",\n \"d\" = \"#03045e\"),\n labels = c(\"5 %\" , \"25 %\" , \"75 %\" , \"95 %\")) + \n labs(color = \"quantiles\")\n```\n\n### Homogénéité des variances au sein des groupes {#sec-0932}\n\nDans le [chapitre @sec-chap08] sur les GLM, nous avons vu que chaque distribution a sa propre définition de la variance. Pour rappel, un modèle gaussien assume une variance constante, un modèle de Poisson assume une variance égale à son espérance, alors qu'un modèle Gamma assume une variance proportionnelle au carré de son espérance divisée par un paramètre de forme, etc. Nous devions donc, pour chaque GLM, vérifier graphiquement si la variance présente dans les données originales était proche de la variance attendue par le modèle. Dans un modèle GLMM, le même exercice doit être fait pour chaque groupe aux différents niveaux du modèle. \n\nDans notre exemple sur la performance scolaire, notre variable *Y* a été modélisée avec une distribution normale. Le modèle assume donc une uniformité de sa variance (homoscédasticité). La @fig-glmmvariance nous montre ainsi que, quelle que soit la classe, la dispersion des points (notes des élèves) semble bien respecter la variance attendue par le modèle (représentée par les lignes noires).\n\n\n```{r}\n#| label: fig-glmmvariance\n#| echo: false\n#| fig-align: center\n#| fig-cap: Homogénéité de la variance pour les différents groupes d'un modèle GLMM gaussien\n#| message: false\n#| warning: false\n#| out-width: \"95%\"\n\nlibrary(lme4)\nmodel2 <- lmer(Y2 ~ X + (1|group), data = df3)\n# Extraction des prédictions du modèle\nmus <- predict(model2, type = \"response\")\nsigma_model <- sigma(model2)\n# Création d'un DataFrame pour contenir les prédictions et les vraies valeurs\ndf1 <- data.frame(\n mus = mus,\n reals = df3$Y2,\n group = df3$group\n)\ndf1$group <- as.factor(df1$group)\n# Calcul de l'intervalle de confiance à 95 % selon la distribution normale\n# et stockage dans un second DataFrame\nseqa <- seq(70,95,5)\ndf2 <- data.frame(\n mus = seqa,\n lower = qnorm(p = 0.025, mean = seqa, sd = sigma_model),\n upper = qnorm(p = 0.975, mean = seqa, sd = sigma_model)\n)\n# Affichage des valeurs réelles et prédites (en rouge)\n# et de leur variance selon le modèle (en noir)\nggplot() + \n geom_point(data = df1, \n mapping = aes(x = mus, y = reals),\n color =\"red\", size = 0.5) + \n geom_errorbar(data = df2,\n mapping = aes(x = mus, ymin = lower, ymax = upper),\n width = 0.2, color = rgb(0.4,0.4,0.4)) + \n labs(x = \"valeurs prédites\",\n y = \"valeurs réelles\") + \n facet_wrap(vars(group), ncol = 3)\n```\n\n## Inférence dans les modèles GLMM {#sec-094}\n\nUne des questions importantes à se poser lorsque nous construisons un modèle est toujours : est-ce que les différents effets présents dans le modèle ont un effet significativement différent de zéro sur la variable dépendante? Cette étape d'inférence est plus compliquée pour les modèles GLMM que dans les modèles GLM à cause de la présence d'effets aléatoires. Ces derniers brouillent le comptage du nombre de paramètres et, par extension, du nombre de degrés de liberté des modèles. Pour un effet aléatoire, il est possible de déterminer que le nombre de degrés de liberté est de 1 puisque nous ajustons un seul paramètre supplémentaire (la variance de cet effet aléatoire). Selon un autre point de vue, il serait possible d'affirmer que le nombre de degrés de liberté est de $k - 1$ (avec *k* le nombre de groupes dans cet effet aléatoire), ce que nous utilisons habituellement pour un effet fixe. La vraie valeur du nombre de degrés de liberté se situe quelque part entre ces deux extrêmes. L'enjeu du nombre de degrés de liberté est crucial, car il influence directement l'estimation des valeurs de *p* pour l'ensemble des coefficients du modèle. Avec un nombre de degrés de liberté plus petit, les valeurs de *p* sont plus faibles et les effets plus significatifs. Le sujet est d'ailleurs l'objet d'une telle controverse que les auteurs de certains *packages* comme `lme4` (un des *packages* les plus utilisés pour ajuster des GLMM) ont fait le choix de ne renvoyer aucune valeur de *p* dans les résultats des modèles. L'article de @bolker2009generalized propose une explication détaillée et relativement accessible du problème (en plus d'une excellente introduction aux GLMM) : en se basant sur leurs recommandations, il est possible de séparer le problème de l'inférence dans les GLMM en trois sous problèmes : \n\n* Quel est le degré de significativité des effets fixes?\n* Quel est le degré de significativité de l'effet aléatoire dans le modèle?\n* Quels sont les degrés de significativité de chaque constante / pente aléatoire?\n\n\n### Inférence pour les effets fixes {#sec-0941}\n\nTrois approches peuvent être envisagées pour déterminer si un effet fixe est significatif ou non. Elles font appel à trois approches théoriques différentes (test classique, comparaison de modèles et *bootstrapping*) et peuvent donc donner des résultats différents. À titre exploratoire, il peut être intéressant de toutes les tester, mais certaines peuvent être préférées en fonction de votre champ de recherche.\n\n#### Test classique {#sec-09411}\n\nNous avons vu, pour les modèles LM et GLM, que les valeurs de *p* sont calculées à partir de scores obtenus en divisant les coefficients par leurs erreurs standards. Une approche similaire peut être utilisée pour les modèles GLMM. Cependant, la question du nombre de degrés de liberté à utiliser reste un problème. L'approche la plus flexible est certainement l'approximation par la méthode Satterthwaite proposant une estimation de ce nombre de degrés de liberté et, par extension, des valeurs de *p*.\n\n#### Rapports de vraisemblance {#sec-09412}\n\nSi le modèle comprend suffisamment d'observations (par suffisamment, comprenez au moins une centaine d'observations par paramètre), il est également possible d'utiliser une série de tests de rapports de vraisemblance pour vérifier si l'apport de chaque variable indépendante contribue à améliorer significativement le modèle. Cette approche correspond à une analyse de type 3, comme nous l'avons mentionné dans la [section @sec-0824] pour le modèle logistique multinomial.\n\n#### Bootstrapping {#sec-09413}\n\nL'approche par *bootstrapping* (*parametric-bootstrap* ou *semi-parametric-bootstrap*) permet de calculer, pour les différents paramètres d'un modèle, un intervalle de confiance. L'idée étant de réajuster un grand nombre de fois le modèle sur des sous-échantillons de données pour saisir la variabilité des différents paramètres du modèle. Si les intervalles de confiance ainsi construits ne comprennent pas de zéro, il est possible de dire que cet effet est significatif. À nouveau, cette méthode n'est valide que si le jeu de données comporte suffisamment d'observations. L'intérêt de cette approche est qu'elle ne postule pas d'hypothèse sur la distribution des paramètres qui ont la fâcheuse tendance à ne pas suivre une distribution normale dans le cas des GLMM. Elle est d'ailleurs considérée comme la plus robuste, bien que coûteuse en termes de temps de calcul.\n\n### Inférence pour les effets aléatoires, effet global {#sec-0942}\n\nPour déterminer si un effet aléatoire est significatif dans un modèle, il est recommandé d'utiliser un test de rapport de vraisemblance entre un modèle sans l'effet aléatoire et un modèle avec l'effet aléatoire. L'analyse des différences entre les valeurs de déviance, l'AIC et le BIC peut également aider à déterminer si l'ajout de l'effet aléatoire est justifié. Il est également possible de considérer les valeurs de l'ICC et du R^2^ conditionnel. Notez ici que si vous avez une très bonne raison théorique d'ajouter l'effet aléatoire dans votre modèle et suffisamment d'observations / groupes pour l'ajuster, il peut être pertinent de laisser l'effet aléatoire dans le modèle même si tous les indicateurs mentionnés précédemment indiquent qu'il contribue faiblement au modèle. Le retirer risquerait en effet de donner l'impression que les autres paramètres du modèle sont plus significatifs qu'ils ne le sont en réalité.\n\nNotez que l'approche par *bootstrapping* décrite pour les effets fixes peut aussi être utilisée ici pour obtenir un intervalle de confiance pour l'ICC, le R^2^ conditionnel et les différents paramètres de variance et covariance. \n\n### Inférence pour les effets aléatoires, des constantes et des pentes {#sec-0943}\n\nPour rappel, dans l'approche fréquentiste présentée ici, les valeurs des constantes et des pentes aléatoires ne sont pas à proprement parler des paramètres du modèle : elles sont estimées a posteriori (BLUP). Pour déterminer si ces constantes et des pentes sont significativement différentes de zéro et significativement différentes les unes des autres, il est possible de calculer les intervalles de confiance de chacune d'entre elles par *bootstrap*, par profilage ou par simulation à partir du modèle. Si la constante du groupe *j* a zéro dans son intervalle de confiance, nous pouvons alors déclarer que le groupe *j* en question ne semble pas varier du reste de la population en termes de moyenne. Si la pente *l* du groupe *j* a zéro dans son intervalle de confiance, nous pouvons alors déclarer que le groupe *j* en question ne semble pas varier du reste de la population pour l'effet *l*. Notez que la méthode par simulation est bien plus rapide que les deux autres, mais que l'approche par *bootstrapping* reste la plus fiable.\n\n## Conclusion sur les GLMM {#sec-095}\n\nLes GLMM sont donc une extension des GLM offrant une grande flexibilité de modélisation (variabilité des pentes et des constantes en fonction de groupes) et nous permettant d'analyser la partition de la variance entre plusieurs niveaux de nos données. Cependant, cette flexibilité implique des modèles plus complexes avec un travail de diagnostic et d'interprétation plus long et potentiellement plus ardu.\n\n\n## Mise en œuvre des GLMM dans R {#sec-096}\n\nPour cet exemple de GLMM, nous proposons d'analyser à nouveau les données présentées dans la [section @sec-06211] sur le modèle logistique binomial. Pour rappel, nous modélisions la probabilité qu'un individu utilise le vélo comme mode de transport pour son trajet le plus fréquent en utilisant une enquête réalisée auprès d'environ 26 000 Européens. Initialement, nous avons intégré les pays comme un effet fixe. Or, nous savons à présent qu'il serait plus judicieux de les traiter comme un effet aléatoire. Nous comparons deux modèles, un pour lequel seulement la constante varie par pays et un second dans lequel la pente pour l'âge varie également par pays. L'hypothèse étant que l'effet de l'âge sur l'utilisation du vélo pourrait être réduit dans certains pays où la culture du vélo est plus présente. Cette hypothèse implique également la présence potentielle d'une corrélation inverse entre la constante et la pente de chaque pays : dans un pays où la probabilité de base d'utiliser le vélo est plus élevée, l'effet de l'âge est probablement réduit.\n\nPour ajuster ces modèles, nous utilisons le *package* `lme4`, permettant d'ajuster des modèles GLMM avec des distributions gaussienne, Gamma, de Poisson et binomial. Lorsque d'autres distributions sont nécessaires, il est possible de se tourner vers le *package* `gamlss`. Notez cependant que les effets aléatoires de `gamlss` sont estimés avec une méthode appelée PQL très flexible, mais qui peut produire des résultats erronés dans certains cas [@bolker2009generalized].\n\nAfin de limiter les répétitions, nous ne recalculons pas ici le VIF et nous excluons d'emblée les observations aberrantes (provenant de Malte ou de Chypre ou avec des temps de trajets supérieurs à 400 minutes).\n\n### Ajustement du modèle avec uniquement une constante aléatoire {#sec-0961}\n\nNous commençons donc par ajuster un premier modèle avec une constante aléatoire en fonction du pays. Dans la plupart des *packages* intégrant des effets aléatoires, la syntaxe suivante est utilisée pour stipuler une constante aléatoire : `+ (1|Pays)`. Concrètement, nous tentons d'ajuster le modèle décrit par l'@eq-glmmbinom1.\n\n$$\n\\begin{aligned}\n&Y \\sim Binomial(p)\\\\\n&g(p) = \\beta_0 + \\beta_1 x_1 + \\upsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon}) \\\\\n&g(x) = log(\\frac{x}{1-x})\n\\end{aligned}\n$$ {#eq-glmmbinom1}\n\nIl s'agit simplement d'un modèle logistique binomial dans lequel nous avons ajouté une constante aléatoire : $\\upsilon$. Dans notre cas, elle varie avec la variable `Pays`. La syntaxe dans R pour produire ce modèle est la suivante.\n\n```{r}\n#| message: false\n#| warning: false\n# Chargement des données\ndfenquete <- read.csv(\"data/glm/enquete_transport_UE.csv\", encoding = \"UTF-8\")\ndfenquete$Pays <- relevel(as.factor(dfenquete$Pays), ref = \"Allemagne\")\n# Retirer les observations aberrantes\ndfenquete2 <- subset(dfenquete, (dfenquete$Pays %in% c(\"Malte\", \"Chypre\")) == F & \n dfenquete$Duree < 400)\n# Ajustement du modèle\nlibrary(lme4)\n# Nécessité ici de centrer et réduire ces variables pour permettre au modèle de converger\ndfenquete2$Age2 <- scale(dfenquete2$Age, center = TRUE, scale = TRUE)\ndfenquete2$Duree2 <- scale(dfenquete2$Duree, center = TRUE, scale = TRUE)\nmodele1 <- glmer(y ~Sexe + Age2 + Education + StatutEmploi + Revenu +\n Residence + Duree2 + ConsEnv + (1|Pays),\n family = binomial(link=\"logit\"),\n control = glmerControl(optimizer = \"bobyqa\"),\n data = dfenquete2)\n```\n\nNous nous concentrons ici sur l'interprétation des résultats du modèle et nous réalisons l'ensemble des diagnostics dans une section dédiée en fin de chapitre. Notez cependant que le diagnostic **devrait précéder l'interprétation** comme nous l'avons vu dans le chapitre sur les modèles GLM.\n\nVous constaterez que nous avons centré-réduit les variables `Age` et `Duree`. Il est souvent nécessaire de réaliser cette étape en amont pour s'assurer que le modèle converge sans trop de difficulté. Dans notre cas, si ces deux variables sont laissées dans leur échelle d'origine, la fonction `glmer` ne parvient pas à ajuster le modèle. Notez que cette transformation nous permet d'obtenir les coefficients standardisés, s'exprimant alors en écarts-types. La fonction `summary` nous donne accès à un premier ensemble d'informations.\n\n```{r}\n#| message: false\n#| warning: false\nsummary(modele1)\n```\n\nLa première partie de ce résumé nous rappelle la formule utilisée pour le modèle et nous indique différents indicateurs de qualité d'ajustement comme l'AIC, le BIC et la déviance. Nous avons ensuite une partie dédiée aux effets aléatoires (`Random Effects`) et une partie dédiée aux effets fixes (`Fixed effects`). Cette dernière s'interprète de la même manière que pour un modèle à effets fixes, n'oubliez cependant pas d'utiliser la fonction exponentielle pour obtenir les rapports de cotes (fonction de lien logistique).\n\n#### Rôle joué par l'effet aléatoire {#sec-09611}\n\nComme vous pouvez le constater, la section `Random Effects` ne comprend qu'un seul paramètre : la variance de l'effet pays. Nous pouvons ainsi écrire que l'effet du pays suit une distribution normale avec une moyenne de 0 et une variance $\\sigma^2$ de `r tofr(round(VarCorr(modele1)[[1]][[1]],3))`. Pour aller plus loin dans cette analyse, nous pouvons calculer le coefficient de corrélation intraclasse (ICC). Cependant, puisque notre modèle est binomial et non gaussien, nous ne disposons pas d'un paramètre de variance au niveau des individus, il est donc possible, à la place, d'utiliser la variance théorique du modèle : $\\frac{\\pi^2}{3}$. Nous calculons ainsi notre ICC :\n\n```{r}\n#| message: false\n#| warning: false\n# Extraction de la variance des Pays\nvar_pays <- VarCorr(modele1)[[1]][[1]]\n# Calcul de l'ICC\nvar_pays / (((pi**2)/3) + var_pays)\n```\n\nNous pouvons parvenir au même résultat en utilisant la fonction `icc` du *package* `performance`.\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(performance)\n# Calcul de l'ICC\nicc(modele1)\n```\n\nNotez que cette fonction distingue un ICC ajusté et un ICC conditionnel. Le premier correspond à l'ICC que nous avons présenté jusqu'ici et que nous avons calculé à la main. L'ICC conditionnel inclut dans son estimation la variance présente dans les effets fixes. Un fort écart entre ces deux ICC indique que les effets fixes sont capables de capturer une très forte variance dans les données, ce qui pourrait remettre en cause la pertinence de l'effet aléatoire. Dans notre cas, la différence entre les deux est très faible.\n\nEn plus du ICC, nous pouvons calculer les R^2^ marginal et conditionnel. Pour cela, nous utilisons la fonction `r.squaredGLMM` du *package* `MuMIn`.\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(MuMIn)\nr.squaredGLMM(modele1)\n```\n\nCette fonction nous renvoie à la fois les R^2^ obtenus en utilisant la variance théorique du modèle ($\\frac{\\pi^2}{3}$ dans notre cas) et la variance estimée par la méthode delta. La seconde est plus conservative, mais les deux résultats indiquent que les effets aléatoires expliquent une part importante de la variance comparativement aux effets fixes. Notez également que la fonction `r2` du *package* `performance` peut calculer ces deux R^2^, mais seulement en utilisant la variance théorique.\n\n#### Significativité de l'effet aléatoire {#sec-09612}\n\nNous souhaitons déterminer ici si notre effet aléatoire contribue à significativement améliorer le modèle. Pour cela, nous effectuons un test de rapport de vraisemblance entre le modèle sans l'effet aléatoire (un simple GLM ici) et le modèle complet. Nous utilisons pour cela la fonction `anova` : \n\n```{r}\n#| message: false\n#| warning: false\n# Ajustement d'un modèle sans l'effet aléatoire\nmodel_simple <- glm(y ~Sexe + Age2 + Education + StatutEmploi + Revenu +\n Residence + Duree2 + ConsEnv,\n family = binomial(link=\"logit\"),\n data = dfenquete2)\n# Comparaison des deux modèles\nanova(modele1, model_simple)\n```\n\nLe test indique clairement que le modèle complet est mieux ajusté : les valeurs de l'AIC, du BIC et de la déviance sont toutes grandement réduites et le test est largement significatif.\n\nPour aller plus loin, nous pouvons utiliser une approche par *bootstrap* pour calculer un intervalle de confiance pour la variance de l'effet aléatoire, l'ICC et le R^2^ conditionnel. Nous utilisons pour cela la fonction `bootMer`. Si vous essayez de lancer cette syntaxe, vous constaterez qu'elle prend énormément de temps, ce qui s'explique par le grand nombre de fois où le modèle doit être réajusté. Nous vous recommandons donc de bien enregistrer vos résultats après l'exécution de la fonction avec la fonction `save.` Notez que pour réduire significativement le temps de calcul, il est possible d'utiliser simultanément plusieurs cœurs de votre processeur, ce que nous faisons ici avec le *package* `snow`.\n\n```{r}\n#| message: false\n#| warning: false\n#| eval: false\n#| echo: true\n# Définition d'une fonction pour extraire les valeurs qui nous intéressent\nextractor <- function(mod){\n vari <- VarCorr(mod)[[1]][[1]]\n ICC <- vari / (vari + (pi**2/3))\n r2cond <- performance::r2(mod)[[1]]\n return(c(\"vari\"=vari,\"icc\"=ICC,\"r2cond\"=r2cond))\n}\n# Préparation d'un environnement multitraitement pour accélérer le calcul\nlibrary(snow)\n# Préparation de huit coeurs (attention si votre machine en a moins!)\ncl <- makeCluster(8)\nclusterEvalQ(cl, library(\"lme4\"))\nvaleurs <- bootMer(modele1, FUN = extractor, nsim = 1000,\n use.u = FALSE, type = \"parametric\", ncpus = 8,\n parallel=\"snow\",\n cl = cl)\n# Sauvegarde des résultats\nsave(valeurs, file = 'data/glmm/boot_binom.rda')\n```\n\nNous pouvons à présent analyser l'incertitude de ces différents paramètres. Pour cela, nous devons commencer par observer graphiquement leurs distributions obtenues par *bootstrap* avec la @fig-bottdistrib.\n\n```{r}\n#| label: fig-bottdistrib\n#| fig-cap: Distributions obtenues par bootstrap de la variance de l'effet aléatoire, de l'ICC et du R carré conditionnel\n#| out-width: \"80%\"\n#| fig-align: center\n#| message: false\n#| warning: false\n#| echo: true\n# Chargement de nos valeurs préalablement enregistrées\nload('data/glmm/boot_binom.rda')\n# Construction de trois graphiques de distribution\ndf <- data.frame(valeurs$t)\nnames(df) <- c(\"variance\" , \"icc\" , \"R2cond\")\nbreaks1 <- as.vector(quantile(df$variance, probs = c(0.001,0.15,0.5,0.85, 0.999)))\nlabs1 <- round(breaks1,2)\np1 <- ggplot(df) + \n geom_histogram(aes(x = variance), bins = 50, fill = \"#e63946\", color = \"black\")+\n geom_vline(xintercept = median(df$variance),\n color = \"black\", linetype = \"dashed\", size = 1)+\n scale_x_continuous(breaks = breaks1, labels = labs1)+\n theme(axis.ticks.y = element_blank(),\n axis.text.y = element_blank(), axis.title.y = element_blank())\nbreaks2 <- as.vector(quantile(df$icc, probs = c(0.001,0.15,0.5,0.85, 0.999)))\nlabs2 <- round(breaks2,2)\np2 <- ggplot(df) + \n geom_histogram(aes(x = icc), bins = 50, fill = \"#a8dadc\", color = \"black\")+\n geom_vline(xintercept = median(df$icc),\n color = \"black\", linetype = \"dashed\", size = 1)+\n scale_x_continuous(breaks = breaks2, labels = labs2)+\n theme(axis.ticks.y = element_blank(),\n axis.text.y = element_blank(), axis.title.y = element_blank())\nbreaks3 <- as.vector(quantile(df$R2cond, probs = c(0.001,0.15,0.5,0.85, 0.999)))\nlabs3 <- round(breaks3,3)\np3 <- ggplot(df) + \n geom_histogram(aes(x = R2cond), bins = 50, fill = \"#1d3557\", color = \"black\")+\n geom_vline(xintercept = median(df$R2cond),\n color = \"black\", linetype = \"dashed\", size = 1)+\n scale_x_continuous(breaks = breaks3, labels = labs3)+\n theme(axis.ticks.y = element_blank(),\n axis.text.y = element_blank(), axis.title.y = element_blank())\nggarrange(p1, p2, p3, nrow = 2, ncol = 2)\n```\n\nLes trois distributions sont toutes suffisamment éloignées de zéro pour que nous puissions en conclure que ces différentes valeurs sont toutes différentes de zéro. Notez également que les distributions sont relativement symétriques, indiquant que nous disposons de probablement suffisamment d'information dans nos données pour inclure notre effet aléatoire. Des distributions fortement asymétriques indiqueraient, au contraire, une forte difficulté du modèle à estimer le paramètre de variance à partir des données. Dans un article, il n'est pas nécessaire de reporter ces graphiques, mais plus simplement les intervalles de confiance à 95 % et les médianes.\n\n```{r}\n# Intervalle de confiance pour la variance\nquantile(df$variance, probs = c(0.0275,0.5,0.975))\n# Intervalle de confiance pour l'ICC\nquantile(df$icc, probs = c(0.0275,0.5,0.975))\n# Intervalle de confiance pour le R2 conditionnel\nquantile(df$R2cond, probs = c(0.0275,0.5,0.975))\n```\n \n\n#### Significativité des différentes constantes {#sec-09613}\n\nPuisque nous avons conclu que l'effet aléatoire contribue significativement au modèle, nous pouvons à présent vérifier si les constantes ajustées pour chaque pays varient significativement les unes des autres. Pour rappel, les pentes et les constantes aléatoires ne sont pas directement estimées par le modèle, mais a posteriori. Il en résulte qu'il n'y a pas de moyen direct de mesurer l'incertitude de ces paramètres, et donc de construire des intervalles de confiance. Une première option pour contourner ce problème est d'effectuer des simulations à partir de la distribution postérieure du modèle. Notez que cette approche s'inspire largement de l'approche statistique bayésienne. Nous utilisons ici le *package* `merTools` pour effectuer 1000 simulations et obtenir une erreur standard pour chaque constante aléatoire de chaque pays.\n\n```{r}\n#| label: fig-randomconstantes1\n#| fig-cap: Constantes aléatoires estimées par Pays (IC par simulations)\n#| fig-align: center\n#| out-width: \"70%\"\n#| message: false\n#| warning: false\n#| echo: true\n# Simulations et extraction des effets aléatoires\nlibrary(merTools)\nlibrary(dplyr)\nsimsRE <- REsim(modele1, n.sims = 1000, oddsRatio = FALSE)\n# Calcul des intervalles de confiance\nsimsRE$lower <- simsRE$mean - 1.96 * simsRE$sd\nsimsRE$upper <- simsRE$mean + 1.96 * simsRE$sd\n# Variable binaire pour la significativité\nsimsRE$sign <- case_when(\n simsRE$lower<0 & simsRE$upper<0 ~ \"inf\",\n simsRE$lower>0 & simsRE$upper>0 ~ \"sup\",\n TRUE ~ \"not\"\n)\n# Représentation des intervalles de confiance\nggplot(simsRE) + \n geom_errorbarh(aes(xmin = lower, xmax = upper,\n y = reorder(groupID, mean)), size = 0.5, height = 0.5) + \n geom_point(aes(x = mean, y = reorder(groupID, mean),\n color = sign)) + \n scale_color_manual(values = c(\"inf\" = \"#0077b6\", \"sup\" = \"#e63946\", \"not\"=\"#000000\"), \n labels = c(\"sign. < 0\", \"sign. > 0\", \"non sign.\")) +\n labs(x = \"Constante aléatoire\", y = \"Pays\")\n```\n\nLa @fig-randomconstantes1 permet de repérer en un coup d'oeil les pays pour lesquels la probabilité d'utiliser le vélo comme moyen de transport pour le trajet le plus fréquent est la plus élevée ou la plus faible. Notez cependant que les valeurs représentées sont pour l'instant des logarithmes de rapport de cotes. Nous devons donc les convertir en rapports de cotes avec la fonction exponentielle pour faciliter leur interprétation.\n\n```{r}\n# Conversion en rapports de cote (et arrondissement à trois décimales)\nmat <- round(exp(simsRE[c(\"mean\" , \"lower\" , \"upper\")]),3)\nrownames(mat) <- simsRE$groupID\nnames(mat) <- c(\"RC\" , \"RC.025\" , \"RC.975\")\nprint(mat)\n```\n\nNous observons ainsi qu'une personne vivant en Finlande voit ses chances multipliées par 2,25 d'utiliser le vélo comme mode de transport pour son trajet le plus fréquent comparativement à la moyenne des pays européens. À l'inverse, une personne résidant en France a 47 % de chances de moins d'utiliser le vélo.\n\nNotez cependant que cette approche basée sur des simulations peut poser des problèmes, car elle ne renvoie qu'une erreur standard pour mesurer l'incertitude de nos constantes. Dans les cas où nous ne disposons pas de beaucoup d'observations par groupe, la distribution a posteriori des constantes peut être asymétrique, rendant l'estimation des intervalles de confiance par les erreurs standards inutiles. Il est possible de détecter ce cas de figure quand les médianes et les moyennes renvoyées par la fonction `simsRE` diffèrent nettement. Une alternative plus robuste est à nouveau d'estimer la variabilité des effets aléatoires par *bootstrap*. Cette méthode requiert bien plus de temps de calcul que la précédente, nous vous recommandons donc de commencer par la méthode par simulations pour disposer d'un premier aperçu des résultats et d'utiliser ensuite la méthode *bootstrap* quand votre modèle est dans sa forme finale.\n\n```{r}\n#| eval: false\n#| echo: true\n# Création de la fonction d'extraction\nextractor2 <- function(mod){\n elements <- ranef(mod)$Pays\n vec <- elements[,1]\n names(vec) <- rownames(elements)\n return(vec)\n}\n# Préparation de l'opération en multitraitement\ncl <- makeCluster(8)\nclusterEvalQ(cl, library(\"lme4\"))\n# Calcul des effets aléatoires en bootstrap\nvaleurs <- bootMer(modele1, FUN = extractor2, nsim = 1000,\n use.u = T, type = \"parametric\", ncpus = 8,\n parallel=\"snow\",\n cl = cl)\n# Sauvegarder des résultats!\nsave(valeurs, file = 'data/glmm/boot_binom2.rda')\n```\n\nPuisque nous disposons des distributions *bootstrapées* des différents effets aléatoires, nous pouvons directement les représenter dans un graphique (@fig-randomconstantes2). Les résultats sont très similaires à ceux de la @fig-randomconstantes1, ce qui s'explique par le grand nombre d'observations et de groupes. Avec moins d'observations, il est recommandé de privilégier l'approche par *bootstrap*.\n\n```{r}\n#| label: fig-randomconstantes2\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n#| echo: true\n#| fig-cap: Constantes aléatoires estimées par Pays (IC par bootstrap)\n#| fig-align: center\n# Chargement de nos valeurs bootstrapées\nload('data/glmm/boot_binom2.rda')\n# Conversion des bootstraps en intervalle de confiance\nq025 <- function(x){return(quantile(x, probs = 0.025))}\nq975 <- function(x){return(quantile(x, probs = 0.975))}\ndf <- reshape2::melt(valeurs$t)\ndf_med <- df %>% group_by(Var2) %>% summarise(\n med = median(value),\n lower = q025(value),\n upper = q975(value))\n# Ajout d'une variable pour la couleur si significatif\ndf_med$sign <- case_when(\n df_med$lower<0 & df_med$upper<0 ~ \"inf\",\n df_med$lower>0 & df_med$upper>0 ~ \"sup\",\n TRUE ~ \"not\"\n)\n# Affichage des résultats\nggplot(df_med) + \n geom_errorbar(aes(xmin = lower, xmax = upper, y = reorder(Var2, med)), width = 0.5) +\n geom_point(aes(x = med, y = reorder(Var2, med), color = sign)) + \n scale_color_manual(values = c(\"inf\" = \"#0077b6\", \"sup\" = \"#e63946\", \"not\"=\"#000000\"), \n labels = c(\"sign. < 0\", \"sign. > 0\", \"non sign.\")) +\n labs(x = \"Constante aléatoire\", y = \"Pays\")\n```\n\n### Ajustement du modèle avec constantes et pentes aléatoires {#sec-0962}\n\nDans le modèle précédent, nous avons ajusté, pour chaque pays, une constante aléatoire afin de vérifier si la probabilité d'utiliser le vélo comme mode de transport principal changeait d'un pays d'Europe à l'autre. Nous souhaitons à présent tester l'hypothèse que l'effet de l'âge sur la probabilité d'utiliser le vélo varie d'un pays à l'autre. Pour cela, nous ajustons des constantes aléatoires par pays. Nous comparons trois modèles, triés ici selon leur niveau de complexité (nombre de paramètres) : \n\n* le modèle avec uniquement des constantes aléatoires;\n* le modèle avec des constantes et des pentes aléatoires indépendantes;\n* le modèle avec des constantes et des pentes aléatoires corrélées.\n\nDans le *package* `lme4`, les syntaxes pour ajuster ces trois modèles sont les suivantes : \n\n* constantes aléatoires : `+(1|Pays)`;\n* constantes et pentes aléatoires indépendantes : `+(1 + Age||Pays)`;\n* constantes et pentes aléatoires corrélées : `+(1 + Age|Pays)`.\n\nNotez qu'il est aussi possible d'ajuster un modèle avec uniquement des pentes aléatoires avec la syntaxe : `+(-1 + Age|Pays)`. Le paramètre `-1` sert à retirer explicitement la constante aléatoire du modèle. Ajustons donc nos deux modèles avec pentes et constantes aléatoires.\n\n```{r}\n#| warning: false\n#| message: false\n# Constantes et pentes aléatoires indépendantes\nmodele2 <- glmer(y ~ Sexe + Age2 + Education + StatutEmploi + Revenu +\n Residence + Duree2 + ConsEnv + (1 + Age2||Pays),\n family = binomial(link=\"logit\"),\n control = glmerControl(optimizer = \"bobyqa\"),\n data = dfenquete2)\n# Constantes et pentes aléatoires corrélées\nmodele3 <- glmer(y ~ Sexe + Age2 + Education + StatutEmploi + Revenu +\n Residence + Duree2 + ConsEnv + (1 + Age2|Pays),\n family = binomial(link=\"logit\"),\n control = glmerControl(optimizer = \"bobyqa\"),\n data = dfenquete2)\n```\n\n#### Significativité de l'effet aléatoire {#sec-09621}\n\nPuisque les trois modèles sont imbriqués, la première étape est de vérifier si les ajouts successifs au modèle de base sont significatifs, ce que nous pouvons tester avec un rapport de vraisemblance.\n\n```{r}\n#| warning: false\n#| message: false\nanova(modele1, modele2, modele3)\n```\n\nNous constatons ainsi que l'ajout des pentes aléatoires permet d'améliorer significativement le modèle, mais que l'ajout de la corrélation entre les pentes et les constantes aléatoires a un apport très marginal. Nous décidons tout de même de le garder dans un premier temps, car ce paramètre a un intérêt théorique. Affichons le résumé du modèle 3.\n\n\n```{r}\n#| warning: false\n#| message: false\nsummary(modele3)\n```\n\n```{r}\n#| warning: false\n#| message: false\n#| echo: false\nvar1 <- VarCorr(modele3)[[1]][[1]]\nvar2 <- VarCorr(modele3)[[1]][[4]]\nvar3 <- VarCorr(modele3)[[1]][[2]]\n```\n\nÀ nouveau, nous nous intéressons ici principalement à la section `Random Effect`, puisque les effets fixes s'interprètent exactement comme dans les modèles présentés dans le [chapitre @sec-chap06]. Les constantes ont une variance de `r tofr(round(var1,3))` et les pentes de `r tofr(round(var2,3))`. La corrélation entre les deux effets est de `r tofr(round(var3 / (sqrt(var1)*sqrt(var2)),2))`. Cette corrélation est négative et relativement faible, ce qui signifie que les pays dans lesquels la constante est forte tendent à avoir un coefficient plus petit pour l'âge, et donc une réduction accrue de la probabilité d'utiliser le vélo avec l'âge. Nous devons cependant encore nous assurer qu'elle est significativement différente de 0. Pour cela, nous devons calculer l'intervalle de confiance des trois paramètres de variance du modèle. Nous utilisons à nouveau une approche par *bootstrap* et nous enregistrons les résultats.\n\n```{r}\n#| warning: false\n#| message: false\n#| eval: false\n#| echo: true\n# Fonction d'extraction des trois paramètres de variance\nextractor3 <- function(mod){\n vari1 <- VarCorr(mod)[[1]][[1]]\n vari2 <- VarCorr(mod)[[1]][[4]]\n covari <- VarCorr(mod)[[1]][[2]]\n return(c(\"vari1\"=vari1,\"vari2\"=vari2,\"covari\"=covari))\n}\n# Lancement du bootstrap\nvaleurs <- bootMer(modele3, FUN = extractor3, nsim = 1000,\n use.u = FALSE, type = \"parametric\", ncpus = 8,\n parallel=\"snow\",\n cl = cl,\n .progress=\"txt\", PBarg=list(style=3))\n# Enregistrement des résultats\nsave(valeurs, file = 'data/glmm/boot_binom3.rda')\n```\n\nÀ partir des valeurs *bootstrapées*, nous pouvons représenter les distributions de ces trois paramètres (variance des constantes, variance des pentes et corrélation entre les deux).\n\n```{r}\n#| label: fig-glmmvarboot\n#| warning: false\n#| message: false\n#| eval: true\n#| echo: true\n#| fig-cap: Incertitude autour des paramètres de variance obtenue par bootstrap\n#| fig-align: center\n#| out-width: \"95%\"\n# Chargement des résultats\nload('data/glmm/boot_binom3.rda')\n# Conversion des valeurs de covariance en corrélation\ndf <- data.frame(\n corr_values = valeurs$t[,3] / (sqrt(valeurs$t[,1]) * sqrt(valeurs$t[,2])),\n vari_const = valeurs$t[,1],\n vari_pente = valeurs$t[,2]\n )\n# Histogramme pour la variance des constantes\nbreaks1 <- quantile(df$vari_const, probs=c(0.025,0.5,0.975,0.999))\nlabel1 <- round(breaks1,3)\np1 <- ggplot(df) + \n geom_histogram(aes(x = vari_const), color = \"black\", fill = \"white\", bins = 30) + \n geom_vline(xintercept = median(df$vari_const), color = \"red\", linetype = 1, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$vari_const, probs = 0.025), \n color = \"blue\", linetype = 0.5, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$vari_const, probs = 0.975), \n color = \"blue\", linetype = 0.5, linetype = \"dashed\") + \n labs(x = \"Variance des constantes\", y = \"\")+ \n scale_x_continuous(breaks = breaks1, labels = label1)\n# Histogramme pour la variance des pentes\nbreaks2 <- quantile(df$vari_pente, probs=c(0.025,0.5,0.975,0.999))\nlabel2 <- round(breaks2,3)\np2 <- ggplot(df) + \n geom_histogram(aes(x = vari_pente), color = \"black\", fill = \"white\", bins = 30) + \n geom_vline(xintercept = median(df$vari_pente), color = \"red\", linetype = 1, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$vari_pente, probs = 0.025), \n color = \"blue\", size = 0.5, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$vari_pente, probs = 0.975), \n color = \"blue\", size = 0.5, linetype = \"dashed\") + \n labs(x = \"Variance des pentes\", y = \"\")+\n scale_x_continuous(breaks = breaks2, labels = label2)\n# Histogramme pour la corrélation\nbreaks3 <- c(-1,-0.5,0,0.5,1, median(df$corr_values))\nlabel3 <- round(breaks3,3)\np3 <- ggplot(df) + \n geom_histogram(aes(x = corr_values), color = \"black\", fill = \"white\", bins = 30) + \n geom_vline(xintercept = median(df$corr_values), color = \"red\", size = 1, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$corr_values, probs = 0.025), \n color = \"blue\", size = 0.5, linetype = \"dashed\") + \n geom_vline(xintercept = quantile(df$corr_values, probs = 0.975), \n color = \"blue\", size = 0.5, linetype = \"dashed\") + \n labs(x = \"Corrélation pentes/constantes\", y = \"\") + \n scale_x_continuous(breaks = breaks3, labels = label3)\nggarrange(p1, p2, p3, ncol = 2, nrow = 2)\n```\n\nNous constatons ainsi, à la @fig-glmmvarboot, que la variance des constantes aléatoires est significativement différente de zéro (cette valeur n'est pas dans l'intervalle de confiance à 95 % représenté par les lignes verticales bleues) et une médiane de `r tofr(round(median(df$vari_const),3))` (ligne verticale rouge). Pour les pentes, zéro est également à la limite de l'intervalle de confiance, et la distribution asymétrique et étalée nous indique que ce paramètre est fortement incertain dans le modèle. Enfin, la corrélation entre les pentes et les constantes est de loin le paramètre le plus incertain et son intervalle de confiance est franchement à cheval sur zéro, ce qui devrait nous amener à privilégier un modèle sans ce paramètre.\n\nPour terminer, nous pouvons calculer les R^2^ marginal et conditionnel du modèle afin de mieux cerner le rôle joué par les effets fixes et les effets aléatoires.\n\n```{r}\n#| warning: false\n#| message: false\nr.squaredGLMM(modele3)\n```\n\nLes valeurs des R^2^ marginal et conditionnel du modèle sont similaires à celles que nous avons obtenus avec seulement des constantes aléatoires dans la section précédente, signalant l'apport relativement faible des pentes aléatoires.\n\n#### Analyse des effets aléatoires {#sec-09622}\n\nPour analyser facilement les constantes et les pentes aléatoires de chaque pays, nous pouvons représenter graphiquement leurs intervalles de confiance construits à partir des simulations tirées de la distribution a posteriori du modèle.\n\n```{r}\n#| label: fig-randomconstantes2b\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n#| echo: true\n#| fig-cap: Constantes aléatoires estimées par pays (intervalles de confiance obtenus par simulations)\n#| fig-align: center\n# Simulations et extraction des effets aléatoires\nlibrary(merTools)\nsimsRE <- REsim(modele3, n.sims = 1000, oddsRatio = FALSE)\n# Calcul des intervalles de confiance\nsimsRE$lower <- simsRE$mean - 1.96 * simsRE$sd\nsimsRE$upper <- simsRE$mean + 1.96 * simsRE$sd\n# Variable binaire pour la significativité\nsimsRE$sign <- case_when(\n simsRE$lower<0 & simsRE$upper<0 ~ \"inf\",\n simsRE$lower>0 & simsRE$upper>0 ~ \"sup\",\n TRUE ~ \"not\"\n)\ndf1 <- subset(simsRE, grepl(\"Intercept\", simsRE$term, fixed = TRUE))\ndf2 <- subset(simsRE, grepl(\"Age2\", simsRE$term, fixed = TRUE))\n# Représentation des intervalles de confiance\np1 <- ggplot(df1) + \n geom_errorbarh(aes(xmin = lower, xmax = upper,\n y = reorder(groupID, mean)), size = 0.5, height = 0.5) + \n geom_point(aes(x = mean, y = reorder(groupID, mean),\n color = sign)) + \n scale_color_manual(values = c(\"inf\" = \"#0077b6\", \"sup\" = \"#e63946\", \"not\"=\"#000000\"), \n labels = c(\"sign. < 0\", \"non sign.\", \"sign. > 0\")) +\n labs(x = \"Constante aléatoire\", y = \"Pays\")\np2 <- ggplot(df2) + \n geom_errorbarh(aes(xmin = lower, xmax = upper,\n y = reorder(groupID, mean)), size = 0.5, height = 0.5) + \n geom_point(aes(x = mean, y = reorder(groupID, mean),\n color = sign)) + \n scale_color_manual(values = c(\"inf\" = \"#0077b6\", \"sup\" = \"#e63946\", \"not\"=\"#000000\"), \n labels = c(\"sign. < 0\", \"non sign.\", \"sign. > 0\")) +\n labs(x = \"Pente aléatoire (âge)\", y = \"Pays\")\nggarrange(p1, p2, common.legend = TRUE, nrow = 1, ncol = 2)\n```\n\nLa @fig-randomconstantes2b nous permet ainsi de constater que l'effet des pays sur les pentes est presque toujours non significatif, sauf pour le Danemark. Son effet négatif (`r tofr(round(ranef(modele3)$Pays[rownames(ranef(modele3)$Pays)==\"Danemark\",2],3))`) indique un renforcement de l'effet général, lui-même négatif (`r tofr(round(fixef(modele3)[[3]],3))`). Une interprétation possible est qu'au Danemark, l'utilisation du vélo est proportionnellement plus courante par les jeunes que dans le reste des pays de l'Europe.\n\nPour l'interprétation finale, il est nécessaire d'afficher les valeurs exactes de ces différents paramètres et, dans notre cas, de les convertir en rapports de cotes avec la fonction exponentielle. Pour les pentes aléatoires, il peut être plus facile d'interpréter la somme de l'effet fixe et de l'effet aléatoire.\n\n```{r}\n# Extraction des effets aléatoires obtenus par simulation\nmat <- simsRE[c(\"mean\" , \"lower\" , \"upper\")]\nmat$Pays <- simsRE$groupID\nmat$effet <- simsRE$term\n# Séparation des pentes et des constantes\ndf1 <- subset(mat, grepl(\"Intercept\", mat$effet, fixed = TRUE))\ndf2 <- subset(mat, grepl(\"Age2\", mat$effet, fixed = TRUE))\n# Conversion en rapports de cotes pour les pentes (+ effet fixe)\ndf2$RC <- round(exp(df2$mean + fixef(modele3)[[3]]),3)\ndf2$RC025 <- round(exp(df2$lower + fixef(modele3)[[3]]),3)\ndf2$RC975 <- round(exp(df2$upper + fixef(modele3)[[3]]),3)\nprint(head(df2[c(\"Pays\" , \"RC\" , \"RC025\" , \"RC975\")],10))\n```\n\nNous constatons ainsi qu'au Danemark, les chances pour un individu d'utiliser le vélo sont réduites de 20 % à chaque augmentation de l'âge d'un écart-type, contre seulement 1,5 % en Autriche (non significatif pour ce dernier). Notons ici que l'écart-type de la variable `Age` est de 11 ans. Nous pouvons à présent analyser les constantes.\n\n```{r}\n# Conversion en rapports de cotes pour les constantes\ndf1$RC <- round(exp(df1$mean),3)\ndf1$RC025 <- round(exp(df1$lower),3)\ndf1$RC975 <- round(exp(df1$upper),3)\nprint(head(df1[c(\"Pays\" , \"RC\" , \"RC025\" , \"RC975\")],10))\n```\n\nEn revanche, les chances pour un individu d'utiliser le vélo comme mode de transport pour son trajet le plus fréquent sont 4 fois supérieures à la moyenne européenne, contre seulement 1,3 fois en Autriche. Notez à nouveau que les intervalles de confiance pour ces pentes et ces constantes pourraient être estimés plus fiablement par *bootstrap*.\n\n#### Diagnostic des effets aléatoires {#sec-09623}\n\nPour rappel, dans un modèle GLMM, les effets aléatoires sont modélisés comme provenant de distributions normales. Nous devons donc vérifier qu'ils respectent cette condition d'application. La @fig-diagbinomglmm1 (graphique quantile-quantile) nous permet de constater que les constantes suivent bien une distribution normale, ce qui ne semble pas vraiment être le cas pour les pentes. Considérant que leurs effets sont petits, il serait plus pertinent ici de les retirer du modèle.\n\n```{r}\n#| label: fig-diagbinomglmm1\n#| echo: false\n#| fig-align: center\n#| fig-cap: Distribution normale univariée des constantes et des pentes aléatoires\n#| message: false\n#| warning: false\n#| out-width: \"90%\"\ndf <- data.frame(ranef(modele3)$Pays)\nnames(df) <- c('constante',\"pente\")\np1 <- qplot(sample = df$constante)+\n geom_qq_line(line.p = c(0.25, 0.75),\n color = \"red\", size=0.8, linetype = \"dashed\")+\n labs(title = \"Diagramme quantile-quantile\",\n x = \"Valeurs théoriques\",\n y = \"Constantes aléatoires\")\np2 <- qplot(sample = df$pente)+\n geom_qq_line(line.p = c(0.25, 0.75),\n color = \"red\", size=0.8, linetype = \"dashed\")+\n labs(title = \"Diagramme quantile-quantile\",\n x = \"Valeurs théoriques\",\n y = \"Pentes aléatoires\")\nggarrange(p1, p2, common.legend = TRUE, nrow = 1, ncol = 2)\n```\n\nConsidérant que ce modèle inclut une corrélation entre les constantes et les pentes aléatoires, il est également nécessaire de vérifier si elles suivent conjointement une distribution normale bivariée. La @fig-diagbinomglmm2 semble indiquer que c'est le cas.\n\n```{r}\n#| label: fig-diagbinomglmm2\n#| echo: true\n#| fig-align: center\n#| fig-cap: Distribution normale bivariée des constantes et des pentes aléatoires\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\ncor_mat <- VarCorr(modele3)[[1]]\nre_effects <- data.frame(ranef(modele3)$Pays)\nnames(re_effects) <- c(\"constante\" , \"pente\")\nlibrary(ellipse)\nlevels <- c(0.05,0.25,0.75,0.95)\nels <- lapply(levels, function(i){\n el <- data.frame(ellipse(cor_mat, center = c(0,0), level = i))\n names(el) <- c(\"x\" , \"y\")\n return(el)\n})\nref_points <- data.frame(data.frame(MASS::mvrnorm(n = 1000, mu = c(0,0), Sigma = cor_mat)))\nnames(ref_points) <- c(\"x\" , \"y\")\nggplot() + \n geom_point(aes(x = x, y = y), data = ref_points, alpha = 0.3, size = 0.4) + \n geom_path(data = els[[1]], aes(x = x, y = y, color = \"a\")) + \n geom_path(data = els[[2]], aes(x = x, y = y, color = \"b\")) + \n geom_path(data = els[[3]], aes(x = x, y = y, color = \"c\")) +\n geom_path(data = els[[4]], aes(x = x, y = y, color = \"d\")) + \n geom_point(data = re_effects, aes(x = constante, y = pente))+\n scale_color_manual(values = c(\"a\"=\"#90e0ef\",\n \"b\"=\"#00b4d8\",\n \"c\"=\"#0077b6\",\n \"d\"=\"#03045e\"),\n labels = c(\"5 %\" , \"25 %\" , \"75 %\" , \"95 %\"))+\n labs(x = \"Constantes\", y = \"Pentes\", color = \"quantiles\")\n```\n\n#### Inférence pour les effets fixes {#sec-09624}\n\nNous avons mentionné, dans les sections précédentes, que le calcul de valeurs de *p* pour les effets fixes fait l'objet de controverses pour les modèles GLMM. La méthode offrant le meilleur compromis entre rapidité de calcul et fiabilité est la méthode Satterthwaite implémentée dans le *package* `lmerTest`. Pour l'utiliser, il suffit de charger le *package* `lmerTest` après `lme4`, ce qui modifie la fonction `summary` pour qu'elle utilise directement cette approche.\n\n```{r}\n#| label: iagbinomglmm3\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\nlibrary(lmerTest)\nround(summary(modele3)$coefficients,3)\n```\n\nLes deux autres options envisageables sont : effectuer une analyse de type 3 ou calculer les intervalles de confiance par *bootstrap*. Cependant, elles requièrent beaucoup plus de temps de calcul. Par conséquent, elles ne sont pas présentées ici.\n\n## Quiz de révision du chapitre {#sec-097}\n\n```{r}\n#| label: quizGLMM\n#| echo: false\n#| warning: false\n#| results: asis\nsource(\"code_complementaire/QuizzFunctions.R\")\nquizz_glmm <- quizz(\"quiz/Chapitre09-glmm.yml\", \"quizz_glmm\")\nrender_quizz(quizz_glmm)\n```\n\n\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"09-GLMM.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/10-Multiniveau.qmd.json b/.quarto/idx/10-Multiniveau.qmd.json new file mode 100644 index 0000000..d823661 --- /dev/null +++ b/.quarto/idx/10-Multiniveau.qmd.json @@ -0,0 +1 @@ +{"title":"Régressions multiniveaux","markdown":{"headingText":"Régressions multiniveaux ","headingAttr":{"id":"sec-chap10","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans le précédent chapitre, nous avons abordé les modèles à effets mixtes qui permettent d'introduire à la fois des effets fixes et aléatoires (GLMM). Dans ce chapitre, nous poursuivons sur cette voie avec une nouvelle extension des modèles GLM : les modèles multiniveaux. Ces modèles sont simplement une extension des modèles à effets mixtes et permettent de modéliser un phénomène avec une structure hiérarchique des données, tel que décrit dans le chapitre précédent.\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Rappel de la structure hiérarchique des données**\n:::\n::: bloc_notes-body\n**Exemple à deux niveaux :** il s’agit de modéliser un phénomène $y_{ij}$, soit une variable dépendante *Y* pour un individu *i* (niveau 1) niché dans un groupe *j* (niveau 2). Par exemple, modéliser l’indice de masse corporelle (IMC) de 5000 individus résidant dans 100 quartiers différents.\n\n**Exemple à trois niveaux :** il s’agit de modéliser un phénomène $y_{ijk}$, soit une variable dépendante *Y* pour un individu *i* (niveau 1), niché dans un groupe *j* (niveau 2) appartenant à un groupe *k* (niveau 3). Par exemple, modéliser les notes à un examen de mathématiques d’élèves (niveau 1) nichés dans des classes (niveau 2) nichées dans des écoles (niveau 3).\n:::\n:::\n\n\nNous avons largement décrit précédemment trois principaux types de modèles d’effets mixtes (GLMM) :\n\n* Les GLMM avec constantes aléatoires qui permettent d'avoir une constante différente pour chacun des groupes (niveau 2).\n\n* Les GLMM avec pentes aléatoires qui permettent de faire varier une variable indépendante au niveau 1 (coefficient) en fonction des groupes au niveau 2.\n\n* Les GLMM avec constantes et pentes aléatoires.\n\nLes modèles multiniveaux se différencient des modèles à effets mixtes puisqu'ils permettent d'introduire des variables indépendantes mesurées aux niveaux supérieurs (2 et 3).\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n - `lme4` pour en œuvre des modèles multiniveaux avec une variable dépendante continue.\n - `performance` pour obtenir le coefficient intraclasse (ICC).\n - `MuMIn` pour obtenir les pseudos R^2^.\n:::\n:::\n\n\n## Modèles multiniveaux : deux intérêts majeurs {#sec-101}\n\nLes modèles multiniveaux ont deux principaux avantages : analyser la répartition de la variance entre les différents niveaux et introduire des variables explicatives aux différents niveaux du modèle.\n\n### Répartition de la variance entre les différents niveaux {#sec-1011}\n\nLes modèles multiniveaux permettent d’estimer comment se répartit la variance entre les différents niveaux du jeu de données. Dans les deux exemples de l'encadré précédent, ils permettraient de répondre aux questions suivantes :\n\n* Quel niveau explique le plus l’IMC, le niveau individuel (niveau 1) ou le niveau contextuel (niveau 2)?\n\n* Comment se répartit la variance des notes à l’examen de mathématiques entre les trois niveaux? A-t-on plus de variance pour les individus (niveau 1) ou au sein des classes (niveau 2) ou entre les différentes écoles (niveau 3)?\n\n### Estimation des coefficients aux différents niveaux {#sec-1012}\nLes modèles multiniveaux permettent d’estimer simultanément les coefficients de plusieurs variables indépendantes introduites à chacun des niveaux du modèle. Autrement dit, de voir comment les variables indépendantes introduites aux différents niveaux influencent la variable dépendante (*Y*) mesurée au niveau 1. Si nous reprenons l'exemple à trois niveaux (élèves/classes/écoles), plusieurs facteurs peuvent influencer la réussite ou la performance scolaire des élèves aux différents niveaux :\n\n* **Variables indépendantes au niveau 1** (élève) : âge, sexe, statut socioéconomique, langue maternelle autre que la langue d'enseignement...\n\n* **Variables indépendantes au niveau 2** (classe) : nombre d’élèves par classe, programme spécialisé ou pas...\n\n* **Variables indépendantes au niveau 3** (école) : indice de défavorisation de l’école, école publique ou privée, qualité des infrastructures de l'école (bâtiment, gymnase, cour d'école)...\n\nDans la même veine, afin d'illustrer l'apport des modèles multiniveaux dans le champ de la géographie de la santé, Philibert et Apparicio [-@philibert2007statistiques, p. 129] signalent que « pour un modèle à deux niveaux, il s’agit de modéliser $y_{ij}$, par exemple l’IMC d’un individu *i* (niveau 1) résidant dans un quartier *j* (niveau 2). Il est alors possible de mettre des variables explicatives tant au niveau 1 (âge, sexe, revenu, niveau d’éducation, etc.) qu’au niveau 2 (niveau de défavorisation sociale du quartier, offre de services et d’équipements sportifs et récréatifs, caractéristiques de l’environnement urbain, etc.). Dans cet exemple, nous pouvons voir comment la modélisation multiniveau permet d’estimer simultanément les effets environnementaux et individuels de manière à distinguer la contribution de chacun des niveaux (ex. : l’effet du revenu des individus et celui de la défavorisation du quartier) dans l’explication des variations géographiques observées ».\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Évaluer les effets de milieu avec des analyses multiniveaux**\n:::\n::: bloc_aller_loin-body\nEn santé des populations et en études urbaines, les modèles multiniveaux sont largement mobilisés pour évaluer les effets de milieu (*neighbourhoods effects* ou *area effects* en anglais).\n\nAtkinson et Kintrea [-@atkinson2001disentangling, p. 2278] définissent les « effets de milieu comme le changement net dans les potentialités de l’existence (*life chances*) attribuable au fait de vivre dans un quartier (ou une zone) plutôt qu'un autre » [traduction libre]. Les effets de milieu peuvent être positifs ou négatifs et concerner aussi bien les enfants que les adultes.\n\nLes analyses multiniveaux sont particulièrement adaptées à l'évaluation des effets de milieu. En effet, plusieurs phénomènes — état de santé, comportement ou choix individuels — peuvent être influencés à la fois par des caractéristiques individuelles (âge, sexe, niveau de revenu, niveau d'éducation, etc.) et par des caractéristiques contextuelles (caractéristiques du quartier).\n\nAvec un modèle multiniveau, une fois contrôlées les caractéristiques individuelles (variables indépendantes mesurées au niveau 1), il est alors possible d'évaluer l'effet des caractéristiques du quartier (variables indépendantes mesurées au niveau 2) sur un phénomène $y_{ij}$ mesuré pour un individu *i* résidant dans un quartier *j*.\n:::\n:::\n\n## Différents types de modèles multiniveaux {#sec-102}\n\n### Description du jeu de données utilisé {#sec-1021} \n\nDans le cadre de cette section, nous présentons uniquement les modèles à deux niveaux, soit celui pour modéliser un phénomène $y_{ij}$. Pour ce faire, nous utilisons des données tirées d'une étude de Pham et al. [-@apparicio2017disentangling]. Dans cet article, les auteurs souhaitent évaluer les effets des caractéristiques de la forme urbaine et des caractéristiques socioéconomiques sur la couverture des arbres de rue, et ce, à partir d'un modèle multiniveau. Ils disposent ainsi d'une structure hiérarchique de données avec deux niveaux : les tronçons de rue (niveau 1, n = 10 814) inclus dans un et un seul secteur de recensement (niveau 2, n = 312). La variable dépendante ($y_{ij}$) est le pourcentage de la superficie du tronçon de rue qui est couverte par des arbres, calculé à partir d'images satellites à haute résolution (Quickbird, 60 cm, septembre 2008). L'ensemble des variables utilisées pour les modèles sont reportées au @tbl-Multi.\n\nSept variables indépendantes relatives à la forme urbaine sont mesurées pour les tronçons de rue, soit la largeur et la longueur de la rue, l'âge médian des bâtiments (introduit également au carré pour vérifier l'existence d'un effet curvilinéaire; voir la [section @sec-07511]), les pourcentages de bâtiments résidentiels, de duplex et de triplex, le nombre de bâtiments et finalement la distance moyenne entre le bâtiment et la rue. Les variables indépendantes pour les 312 secteurs de recensement (niveau 2) sont extraites du recensement canadien de 2006 (@tbl-Multi).\n\n```{r}\n#| label: tbl-Multi\n#| tbl-cap: Statistiques descriptives pour les variables des modèles multiniveaux\n#| echo: false\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nload(\"data/multiniveau/dataArbres.RData\")\n\nvars <- c(\"PCTArb\" , \"Width\" , \"Length\" , \"AgeMed\" , \"ResiPCT\" , \"DuTriPct\" , \"NoLog\" , \"Setback\",\n \"ValLog\" , \"UDipPCT\" , \"PCTFRAVI\" , \"PCTIMGRE\",\n \"AvecEnf\" , \"FranPCT\")\n\nintitule <- c(\"Arbres sur le tronçon de rue (%)\" , \"Largeur des rues\" , \"Longueur de rues\" , \"Âge médian des bâtiments\",\n \"Bâtiments résidentiels (%)\" , \"Duplex ou triplex (%)\", \"Nombre de bâtiments\", \"Distance entre le bâtiment et la rue\",\n \n \"Valeur moyenne des logements (milliers de dollars)\" , \"Diplômés universitaires (%)\" , \"Personnes à faible revenu (%)\" , \"Immigrants récents (%)\",\n \"Ménages avec enfants (%)\" , \"Langue maternelle française (%)\")\ntype1 <- c(\"VD\" , \"VI\" , \"VI\" , \"VI\" , \"VI\" , \"VI\" , \"VI\" , \"VI\" , \"VI\" , \"VI\" , \"VI\" , \"VI\" , \"VI\" , \"VI\")\ntype2 <- c(\"1\" , \"1\" , \"1\" , \"1\" , \"1\" , \"1\" , \"1\" , \"1\" , \"2\" , \"2\" , \"2\" , \"2\" , \"2\" , \"2\")\n\nmoy <- round(sapply(Multiniveau[vars], mean),1)\net <- round(sapply(Multiniveau[vars], sd),1)\n\nstats <- data.frame(cbind(moy, et))\nstats <- cbind(vars, intitule, type1, type2, stats)\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(stats,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n digits = 1,\n row.names = FALSE,\n col.names = c(\"Nom\" , \"Intitulé\" , \"Type\", \"Niveau\", \"Moy.\", \"Écart type\"),\n align= c(\"l\" , \"l\" , \"c\", \"c\", \"r\", \"r\")\n )\n```\n\n### Démarche classique pour les modèles multiniveaux {#sec-1022} \n\nLa démarche habituelle en analyse multiniveau est de réaliser plusieurs modèles, allant du plus simple au plus complexe. Cette stratégie permet habituellement de bien cerner la répartition de la variance entre les différents niveaux et l'apport des variables explicatives introduites aux différents niveaux. De la sorte, cinq types de modèles peuvent être construits :\n\n1. Le modèle vide (appelé aussi modèle inconditionnel) qui comprend des constantes aléatoires au niveau 2, mais aucune variable explicative.\n\n2. Le modèle avec uniquement les variables indépendantes au niveau 1 et des constantes aléatoires au niveau 2.\n\n3. Le modèle complet avec les variables indépendantes aux deux niveaux et des constantes aléatoires.\n\n4. Le modèle complet avec les variables indépendantes aux deux niveaux, incluant une interaction entre une variable indépendante mesurée au niveau 1 et une autre mesurée au niveau 2.\n\n5. Le modèle avec les variables indépendantes aux deux niveaux et des constantes et pentes aléatoires.\n\n\nDans les sous-sections suivantes, nous détaillons les quatre premiers modèles en prenant soin de montrer les similitudes qu'ils partagent avec les modèles à effets mixtes vus précédemment. Notez d'emblée que les trois premiers modèles sont les plus fréquemment utilisés.\n\n#### Modèle vide {#sec-10221} \n\nComme son nom l'indique, le modèle vide ne comprend aucune variable explicative. Il consiste simplement à faire varier la constante du niveau 1 avec des effets aléatoires au niveau 2, ce qui explique qu'il est souvent comparé à une ANOVA avec des effets aléatoires. En d'autres termes, ce modèle correspond à un GLMM avec constantes aléatoires dans lequel aucune variable indépendante n'est incluse au niveau 1. D'ailleurs, si vous comparez l'@eq-multiniveauModeleVide avec l'@eq-glmm2 au chapitre précédent, vous constaterez que seul le paramètre $\\beta_1 x_1$ a été ôté et qu'il comprend aussi deux variances : l'une fixe au niveau 1 ($\\sigma_e$) et l'autre aléatoire (stochastique) au niveau 2 ($\\sigma_{\\upsilon}$).\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\beta_0 + \\upsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon}) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-multiniveauModeleVide}\n\n**Quel est alors l'intérêt de réaliser un modèle si simple?** À partir des deux variances, il est possible de calculer le **coefficient de corrélation intraclasse** (*intraclass-correlation* (ICC) en anglais) qui est le rapport entre la variance aléatoire et la somme des variances des deux niveaux, soit fixe et aléatoire (@eq-multiniveauIcc). Ce coefficient varie ainsi de 0 à 1 et indique la proportion de la variance de la variable dépendante qui est imputable au niveau 2. Tous(tes) les auteur(e)s s'entendent sur le fait qu'il est impératif de commencer une analyse de multiniveau en calculant ce modèle vide qui nous informe de la répartition de la variance entre les deux niveaux [@raudenbush2002hierarchical;@gelman2006data;@tabachnick2007;@bressoux2010]. Nous pourrons ensuite analyser l'évolution de ce coefficient dans les modèles subséquents.\n\n$$\n\\rho = \\frac{\\sigma_{\\upsilon}}{\\sigma_{\\upsilon} + \\sigma_{e}}\n$$ {#eq-multiniveauIcc}\n\nLes résultats du modèle vide (inconditionnel) à partir des données de Pham et al. [-@apparicio2017disentangling] sont présentés au @tbl-ModeleVide. La variance du niveau 1 est de 92,93 contre 19,82 au niveau 2. Le coefficient de corrélation intraclasse vaut alors : $\\mbox{19,82} / \\mbox{(19,82} + \\mbox{92,93}) = \\mbox{0,1758}$. Cela signifie que 18 % de la variance de la variable dépendante sont imputables au niveau 2 (des secteurs de recensement) et 82 % au niveau 1 (des tronçons). Nous verrons comment évolue ce coefficient dans les modèles subséquents.\n\n```{r}\n#| label: tbl-ModeleVide\n#| tbl-cap: Résultats du modèle vide (modèle 1)\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(\"lme4\")\nlibrary(\"MuMIn\")\nlibrary(\"performance\")\nload(\"data/multiniveau/dataArbres.RData\")\nModele1 <- lmer(PCTArb ~ 1 + (1| SRNOM), data = Multiniveau)\nReslModele1 <- summary(Modele1)\nRandomEffects <- as.data.frame(VarCorr(Modele1))\nVarModel1Niv1 <- round(RandomEffects[1,4],3)\nVarModel1Niv2 <- round(RandomEffects[2,4],3)\nICCModele1 <- round(VarModel1Niv1/(VarModel1Niv1+VarModel1Niv2),3)\n\nTemp <- summary(Modele1)\ncoefs <- round(summary(Modele1)$coefficients,3)\nTableauModele1 <- as.data.frame(coefs)\ncols <- rownames(TableauModele1)\ncols[1] <- \" Constante\"\nTableauModele1 <- cbind(cols, TableauModele1)\nTableauModele1 <- rbind(c(NA, NA, NA, NA), TableauModele1)\nTableauModele1[1,1] <- \"Effets fixes (niveau 1)\"\n\nnlignes <- nrow(TableauModele1)\nTableauModele1[nlignes+1,1] <- \"Répartition de la variance\"\nTableauModele1[nlignes+2,1] <- \"Variance (niveau 1)\"\nTableauModele1[nlignes+3,1] <- \"Variance (niveau 2)\"\nTableauModele1[nlignes+4,1] <- \"Coefficient de corrélation intraclasse\"\nTableauModele1[nlignes+2,2] <- VarModel1Niv1\nTableauModele1[nlignes+3,2] <- VarModel1Niv2\nTableauModele1[nlignes+4,2] <- ICCModele1\n\nTableauModele1[nlignes+5,1] <- \"Qualité d'ajustement du modèle\"\nTableauModele1[nlignes+6,1] <- \"AIC\"\nTableauModele1[nlignes+7,1] <- \"R^2^ marginal\"\nTableauModele1[nlignes+8,1] <- \"R^2^ conditionnel\"\nTableauModele1[nlignes+6,2] <- round(AIC(Modele1),3)\nTableauModele1[nlignes+7,2] <- round(r.squaredGLMM(Modele1)[1],3)\nTableauModele1[nlignes+8,2] <- round(r.squaredGLMM(Modele1)[2],3)\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(TableauModele1[, c(1,2,3,4)],\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n digits = 3,\n row.names = FALSE,\n col.names = c(\"Paramètre\" , \"Coefficient\" , \"Erreur type\", \"Valeur de T\"),\n align= c(\"l\" , \"r\" , \"r\", \"r\")\n )\n```\n\n#### Modèle avec les variables indépendantes du niveau 1 {#sec-10222}\n\nDans ce second modèle, nous introduisons uniquement les variables explicatives au niveau 1. Par conséquent, ce modèle est tout simplement un modèle à effets mixtes (GLMM) avec des constantes aléatoires largement décrit à la [section @sec-0921]). Si vous comparez l'équation du modèle vide (@eq-multiniveauModeleVide) avec l'équation de ce modèle (@eq-multiniveauModele2), vous constaterez que le paramètre $\\beta_1 x_1$ a été ajouté. Il correspond au coefficient pour la variable indépendante $X_1$ mesurée au niveau 1 (effet fixe). Nous pourrions alors ajouter d'autres paramètres pour les autres variables indépendantes du modèle, soit $\\beta_1 x_1 + \\beta_2 x_2+ \\ldots + \\beta_k x_k$ ($k$ étant le nombre de variables explicatives mesurées au niveau 1, effets fixes).\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\beta_0 + \\beta_1 x_1 + \\upsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon})) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-multiniveauModele2}\n\nLes résultats du second modèle sont présentés au @tbl-Modele2. \n\n**La répartition de la variance entre les deux niveaux**. La variance du niveau 1 est désormais de 15,263 contre 80,317 au niveau 2, ce qui permet d'obtenir un coefficient de corrélation intraclasse de 0,1597. Cela signifie que de 16 % de la variance de la variable dépendante sont imputables au niveau 2 (des secteurs de recensement), une fois contrôlées les caractéristiques des tronçons.\n\n**La qualité d'ajustement du modèle**. Dans le chapitre précédent sur les GLMM, nous avons largement décrit plusieurs mesures de la qualité d'ajustement du modèle, notamment l'AIC et les R^2^ marginal et conditionnel. À titre de rappel, voici comment interpréter ces mesures :\n\n* Plus la valeur de l'AIC est faible, mieux le modèle est ajusté. En comparant les valeurs d'AIC du modèle vide et du modèle avec les variables explicatives du niveau 1 (80 305 *versus* 78 785), nous constatons, sans surprise, que ce dernier modèle est plus performant.\n\n* Le R^2^ marginal indique la proportion de la variance expliquée uniquement si les effets fixes sont pris en compte (ici, 0,129). Quant au R^2^ conditionnel, il indique la proportion de la variance expliquée à la fois par les effets fixes et aléatoires (ici, 0,268). L'écart important entre les deux R^2^ signale que les secteurs de recensement (effets aléatoires, niveau 2) jouent un rôle important dans le modèle.\n\n**Quelles informations peut-on tirer des coefficients de régression?**\nLes variables indépendantes relatives à la forme urbaine les plus importantes sont : le pourcentage de bâtiments résidentiels (`ResiPCT`), la largeur de la rue (`Width`) et le nombre de bâtiments (`NoLog`). Aussi, la distance entre le bâtiment et la rue (`Setback`) est associée positivement avec la variable dépendante. En effet, à chaque ajout d'un mètre de la distance moyenne entre les bâtiments et le tronçon de rue, la couverture des arbres sur le tronçon augmente de 0,202 point de pourcentage, toutes choses étant égales par ailleurs.\n\n```{r}\n#| label: tbl-Modele2\n#| tbl-cap: Résultats du modèle avec les variables indépendantes au niveau 1 (modèle 2)\n#| echo: false\n#| message: false\n#| warning: false\n# MODÈLE 2\nModele2 <- lmer(PCTArb ~\n # Variables indépendantes au niveau 1\n Width+Length+AgeMed+AgeMed2+ResiPCT+DuTriPct+NoLog+Setback+\n (1| SRNOM), data = Multiniveau)\n\nRandomEffects <- as.data.frame(VarCorr(Modele2))\nVarModel2Niv1 <- round(RandomEffects[1,4],3)\nVarModel2Niv2 <- round(RandomEffects[2,4],3)\nICCModele2 <- round(VarModel2Niv1/(VarModel2Niv1+VarModel2Niv2),3)\n\nTemp <- summary(Modele2)\ncoefs <- round(summary(Modele2)$coefficients,3)\nTableauModele2 <- as.data.frame(coefs)\ncols <- rownames(TableauModele2)\ncols[1] <- \" Constante\"\nTableauModele2 <- cbind(cols, TableauModele2)\nTableauModele2 <- rbind(c(NA, NA, NA, NA), TableauModele2)\nTableauModele2[1,1] <- \"Effets fixes (niveau 1)\"\n\nnlignes <- nrow(TableauModele2)\nTableauModele2[nlignes+1,1] <- \"Répartition de la variance\"\nTableauModele2[nlignes+2,1] <- \"Variance (niveau 1)\"\nTableauModele2[nlignes+3,1] <- \"Variance (niveau 2)\"\nTableauModele2[nlignes+4,1] <- \"Coefficient de corrélation intraclasse\"\nTableauModele2[nlignes+2,2] <- VarModel2Niv1\nTableauModele2[nlignes+3,2] <- VarModel2Niv2\nTableauModele2[nlignes+4,2] <- ICCModele2\n\nTableauModele2[nlignes+5,1] <- \"Qualité d'ajustement du modèle\"\nTableauModele2[nlignes+6,1] <- \"AIC\"\nTableauModele2[nlignes+7,1] <- \"R^2^ marginal\"\nTableauModele2[nlignes+8,1] <- \"R^2^ conditionnel\"\n\nTableauModele2[nlignes+6,2] <- round(AIC(Modele2),3)\nTableauModele2[nlignes+7,2] <- round(r.squaredGLMM(Modele2)[1],3)\nTableauModele2[nlignes+8,2] <- round(r.squaredGLMM(Modele2)[2],3)\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(TableauModele2[, c(1,2,3,4)],\n\t\t digits = 3,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n row.names = FALSE,\n col.names = c(\"Paramètre\" , \"Coefficient\" , \"Erreur type\", \"Valeur de T\"),\n align= c(\"l\" , \"r\" , \"r\", \"r\")\n )\n```\n\nRemarquez la valeur de la constante : −1028,618. À titre de rappel, la constante est la valeur que prend la variable dépendante quand toutes les variables indépendantes sont égales à 0. Or, il est impossible qu'elles soient toutes égales à zéro. \n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Centrage des variables quantitatives mesurées au niveau 1**\n:::\n::: bloc_astuce-body\nEn analyse multiniveau, il est très courant et souvent recommandé de centrer les variables explicatives quantitatives au niveau 1. Deux options sont alors possibles :\n\n1. Pour une variable indépendante donnée, les observations sont centrées sur leur moyenne générale, c'est-à-dire la moyenne de l'ensemble des observations du jeu de données, soit $X_{ij} - \\bar{X}$. Dans ce cas, la constante est donc la valeur que prend la variable $Y$ quand toutes les variables indépendantes sont égales à leur moyenne respective.\n2. Chaque observation est centrée sur la moyenne de son groupe respectif, soit $X_{ij} - \\bar{X}_{.j}$.\n\nComme signalé par Bressoux [-@bressoux2010, p. 328], « dans le premier cas, la variance des pentes sera estimée pour l'individu moyen dans la distribution générale, tandis que dans le second elle est estimée pour l'individu moyen de chaque groupe ».\n\nAutrement dit, comparativement à un modèle sans centrage, les valeurs des coefficients pour les variables indépendantes sont les mêmes dans le premier cas (seule la valeur de la constante va changer) tandis qu'elles sont différentes dans le second cas.\n\nAttention, il ne faut pas appliquer de centrage sur une variable qualitative, qu'elle soit dichotomique, nominale ou ordinale.\n\n**Pourquoi la pratique du centrage en analyse multiniveau est si courante?**\n\nDans la plupart des livres sur les régressions multiniveaux, le centrage est recommandé, notamment dans l'ouvrage classique de Raudenbush et Bryk [-@raudenbush2002hierarchical]. Rappelons que ces modèles sont largement utilisés en éducation avec une structure hiérarchique classique élève/école/classe. Nous nous intéressons alors à l'individu moyen (l'élève), ce qui explique que le centrage est habituellement appliqué. Par exemple, ne pas centrer l'âge des élèves fait que la constante qui est obtenue est peu interprétable : difficile d'évaluer la note moyenne à un examen quand la variable *âge de l'élève* a la valeur de 0, tout comme les autres variables explicatives quantitatives relatives à l'élève.\n\n\n**Centrage et réduction de l'ensemble des variables du modèle**\n\nIl est à noter que certains auteurs centrent et réduisent l'ensemble des variables du modèle. À titre de rappel, le centrage consiste à soustraire à chaque valeur la moyenne de la variable; la réduction, à la diviser par l'écart-type de la variable ([section @sec-02552]). Pour chaque variable, la moyenne est alors égale à 0 et l'écart-type à 1. Les coefficients s'interprètent alors en termes d'augmentation d'une unité d'écart-type tant pour la VI que la VD. Ils correspondent alors à des coefficients de régression standardisés (abordés dans la [section @sec-0742]). Ce processus de centrage et de réduction des variables peut être motivé par des problèmes de convergence du modèle (lorsque l'algorithme d'optimisation n'arrive pas à trouver une solution pour produire les coefficients).\n:::\n:::\n\nPar conséquent, nous vous proposons de centrer les variables du niveau 1 de notre jeu de données. Si vous comparez les tableaux [-@tbl-Modele2] et [-@tbl-Modele2b], vous constaterez que les valeurs relatives aux coefficients, aux mesures de la répartition de la variance et à la qualité d'ajustement du modèle sont les mêmes. Seule la valeur de la constante change : elle passe de −1028,618 à 7,228. Elle s'interprète désormais de la façon suivante : si toutes les variables explicatives sont égales à leurs moyennes respectives, alors le pourcentage de la superficie du tronçon couverte par des arbres est égal à 7,228 %.\n\n```{r}\n#| label: tbl-Modele2b\n#| tbl-cap: Résultats du modèle avec les variables indépendantes centrées au niveau 1 (modèle 2)\n#| echo: false\n#| message: false\n#| warning: false\n\nVINiv1 <- c(\"Width\" , \"Length\" , \"AgeMed\" , \"AgeMed2\" , \"ResiPCT\" , \"DuTriPct\" , \"NoLog\" , \"Setback\")\nfor (e in VINiv1){\n e.c <- paste(e, \".c\", sep = \"\")\n Multiniveau[[e.c]] <- Multiniveau[[e]] - mean(Multiniveau[[e]])\n}\n\n# MODÈLE 2\nModele2 <- lmer(PCTArb ~\n # Variables indépendantes au niveau 1\n Width.c+Length.c+AgeMed.c+AgeMed2.c+ResiPCT.c+DuTriPct.c+NoLog.c+Setback.c+\n (1| SRNOM), data = Multiniveau)\n\nRandomEffects <- as.data.frame(VarCorr(Modele2))\nVarModel2Niv1 <- round(RandomEffects[1,4],3)\nVarModel2Niv2 <- round(RandomEffects[2,4],3)\nICCModele2 <- round(VarModel2Niv1/(VarModel2Niv1+VarModel2Niv2),3)\n\ncoefs <- round(summary(Modele2)$coefficients,3)\nTableauModele2 <- as.data.frame(coefs)\ncols <- rownames(TableauModele2)\ncols[1] <- \" Constante\"\nTableauModele2 <- cbind(cols, TableauModele2)\nTableauModele2 <- rbind(c(NA, NA, NA, NA), TableauModele2)\nTableauModele2[1,1] <- \"Effets fixes (niveau 1)\"\n\nnlignes <- nrow(TableauModele2)\nTableauModele2[nlignes+1,1] <- \"Répartition de la variance\"\nTableauModele2[nlignes+2,1] <- \"Variance (niveau 1)\"\nTableauModele2[nlignes+3,1] <- \"Variance (niveau 2)\"\nTableauModele2[nlignes+4,1] <- \"Coefficient de corrélation intraclasse\"\nTableauModele2[nlignes+2,2] <- VarModel2Niv1\nTableauModele2[nlignes+3,2] <- VarModel2Niv2\nTableauModele2[nlignes+4,2] <- ICCModele2\n\nTableauModele2[nlignes+5,1] <- \"Qualité d'ajustement du modèle\"\nTableauModele2[nlignes+6,1] <- \"AIC\"\nTableauModele2[nlignes+7,1] <- \"R^2^ marginal\"\nTableauModele2[nlignes+8,1] <- \"R^2^ conditionnel\"\n\nTableauModele2[nlignes+6,2] <- round(AIC(Modele2),3)\nTableauModele2[nlignes+7,2] <- round(r.squaredGLMM(Modele2)[1],3)\nTableauModele2[nlignes+8,2] <- round(r.squaredGLMM(Modele2)[2],3)\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(TableauModele2[, c(1,2,3,4)],\n\t\t digits = 3,\n row.names = FALSE,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Paramètre\" , \"Coefficient\" , \"Erreur type\", \"Valeur de T\"),\n align= c(\"l\" , \"r\" , \"r\", \"r\")\n )\n```\n\n#### Modèle complet avec les variables indépendantes aux niveaux 1 et 2 {#sec-10223}\n\nLe troisième type de modèle consiste à introduire à la fois les variables explicatives mesurées au niveau 1 et au niveau 2 (@eq-multiniveauModele3). Il est communément appelé le modèle complet. Les variables explicatives du niveau 2 sont aussi considérées comme des effets fixes.\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\underbrace{\\beta_0 + \\beta_1 x_1}_{\\mbox{effets fixes (niveau 1)}}+ \\underbrace{\\beta_2 z_2}_{\\mbox{effets fixes (niveau 2)}}+\\epsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon}) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-multiniveauModele3}\n\nLes résultats du troisième modèle sont présentés au @tbl-Modele3. Ce modèle permet d'évaluer les effets des caractéristiques socioéconomiques (mesurés au niveau des secteurs de recensement) sur la couverture des arbres des îlots, une fois contrôlées les caractéristiques de la forme urbaine des tronçons. Rappelons que dans ce modèle, les constantes sont aléatoires et les variables indépendantes au niveau 1 sont centrées.\n\n**Quelles informations peut-on tirer des coefficients de régression du niveau 2?**\nD’emblée, deux caractéristiques n'ont pas d'effet significatif sur la variable dépendante, soit les pourcentages de diplômés universitaires et de ménages avec enfants. Par contre, toutes choses étant égales par ailleurs, la valeur moyenne des logements et le pourcentage d'immigrants récents sont associés à une augmentation de la couverture végétale. À l'inverse, le pourcentage de personnes à faible revenu est associé à une diminution de la couverture végétale.\n\n```{r}\n#| label: tbl-Modele3\n#| tbl-cap: Résultats du modèle avec les variables indépendantes aux niveaux 1 et 2 (modèle 3)\n#| echo: false\n#| message: false\n#| warning: false\n# MODÈLE 3\nvarsNiv2 <- c(\"ValLog\" , \"UDipPCT\" , \"PCTFRAVI\" , \"PCTIMGRE\" , \"AvecEnf\" , \"FranPCT\")\nModele3 <- lmer(PCTArb ~\n # Variables indépendantes au niveau 1\n Width.c+Length.c+AgeMed.c+AgeMed2.c+ResiPCT.c+DuTriPct.c+NoLog.c+Setback.c+\n # Variables indépendantes au niveau 2\n ValLog+UDipPCT+PCTFRAVI+PCTIMGRE+AvecEnf+FranPCT+ (1| SRNOM), data = Multiniveau)\n\nRandomEffects <- as.data.frame(VarCorr(Modele3))\nVarModel3Niv1 <- round(RandomEffects[1,4],3)\nVarModel3Niv2 <- round(RandomEffects[2,4],3)\nICCModele3 <- round(VarModel3Niv1/(VarModel3Niv1+VarModel3Niv2),3)\n\ncoefs <- round(summary(Modele3)$coefficients,3)\nnvar1 <- length(VINiv1)+1\nnvar2 <- length(varsNiv2)\nnvar12 <- nvar1+nvar2\n\ncoefNiv1 <- coefs[1:nvar1,]\ncoefNiv2 <- coefs[(nvar1+1):nvar12,]\ncoefs <- rbind(coefNiv1, c(NA, NA, NA), coefNiv2)\n\nTableauModele3 <- as.data.frame(coefs)\ncols <- rownames(TableauModele3)\ncols[1] <- \" Constante\"\nTableauModele3 <- cbind(cols, TableauModele3)\nTableauModele3 <- rbind(c(NA, NA, NA, NA), TableauModele3)\nTableauModele3[1,1] <- \"Effets fixes (niveau 1 : tronçons)\"\nTableauModele3[(nvar1+2),1] <- \"Effets fixes (niveau 2 : secteurs de recensement)\"\n\nnlignes <- nrow(TableauModele3)\nTableauModele3[nlignes+1,1] <- \"Répartition de la variance\"\nTableauModele3[nlignes+2,1] <- \"Variance (niveau 1)\"\nTableauModele3[nlignes+3,1] <- \"Variance (niveau 2)\"\nTableauModele3[nlignes+4,1] <- \"Coefficient de corrélation intraclasse\"\nTableauModele3[nlignes+2,2] <- VarModel3Niv1\nTableauModele3[nlignes+3,2] <- VarModel3Niv2\nTableauModele3[nlignes+4,2] <- ICCModele3\n\nTableauModele3[nlignes+5,1] <- \"Qualité d'ajustement du modèle\"\nTableauModele3[nlignes+6,1] <- \"AIC\"\nTableauModele3[nlignes+7,1] <- \"R^2^ marginal\"\nTableauModele3[nlignes+8,1] <- \"R^2^ conditionnel\"\n\nTableauModele3[nlignes+6,2] <- round(AIC(Modele3),3)\nTableauModele3[nlignes+7,2] <- round(r.squaredGLMM(Modele3)[1],3)\nTableauModele3[nlignes+8,2] <- round(r.squaredGLMM(Modele3)[2],3)\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(TableauModele3[, c(1,2,3,4)],\n\t\t digits = 3,\n row.names = FALSE,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Paramètre\" , \"Coefficient\" , \"Erreur type\", \"Valeur de T\"),\n align= c(\"l\" , \"r\" , \"r\", \"r\")\n )\n```\n\n#### Modèle avec une interaction entre deux niveaux {#sec-10224}\n\nDans la [section @sec-0754], nous avons vu comment introduire des variables d'interaction dans une régression linéaire multiple, soit entre deux variables continues ([section @sec-07541]), soit entre une variable continue et une variable dichotomique ([section @sec-07542]), soit entre deux variables dichotomiques ([section @sec-07543]). En analyse multiniveau, il peut être pertinent d'introduire une interaction entre une variable mesurée au niveau 1 et une autre mesurée au niveau 2 (@eq-multiniveauModele4).\n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma_e)\\\\\n&g(\\mu) = \\underbrace{\\beta_0 + \\beta_1 x_1}_{\\mbox{effets fixes (niv. 1)}}+ \\underbrace{\\beta_2 z_2}_{\\mbox{effets fixes (niv. 2)}}+ \\underbrace{\\beta_3 (x_1 \\times z_2)}_{\\mbox{interaction (niv. 1 et 2)}}+ \\epsilon \\\\\n&\\upsilon \\sim Normal(0, \\sigma_{\\upsilon})) \\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-multiniveauModele4}\n\nDans le @tbl-Modele4, nous introduisons une variable d'interaction entre la *distance entre le bâtiment et la rue* (`Setback.c`) et le *pourcentage de personnes à faible revenu* (`PCTFRAVI`). On constate alors que `PCTFRAVI` est associé négativement avec la variable dépendante ($\\beta =$ −0,079, *t* = −2,684). Toutefois, lorsqu'elle est mise en interaction avec la variable `Setback.c`, cette variable est significative et positive ($\\beta =$ 0,008, *t* = 4,591).\n\n```{r}\n#| label: tbl-Modele4\n#| tbl-cap: Résultats du modèle avec une variable d'interaction entre les deux niveaux 1 et 2 (modèle 4)\n#| echo: false\n#| message: false\n#| warning: false\n\nMultiniveau$PCTFRAVI_Setback <- Multiniveau$PCTFRAVI * Multiniveau$Setback.c\n\n# MODÈLE 4\nvarsNiv2 <- c(\"ValLog\" , \"UDipPCT\" , \"PCTFRAVI\" , \"PCTIMGRE\" , \"AvecEnf\" , \"FranPCT\")\nModele4 <- lmer(PCTArb ~\n # Variables indépendantes au niveau 1\n Width.c+Length.c+AgeMed.c+AgeMed2.c+ResiPCT.c+DuTriPct.c+NoLog.c+Setback.c+\n # Variables indépendantes au niveau 2\n ValLog+UDipPCT+PCTFRAVI+PCTIMGRE+AvecEnf+FranPCT+ # Variable d'interaction\n PCTFRAVI_Setback+\n(1| SRNOM), data = Multiniveau)\n\nRandomEffects <- as.data.frame(VarCorr(Modele4))\nVarModel4Niv1 <- round(RandomEffects[1,4],3)\nVarModel4Niv2 <- round(RandomEffects[2,4],3)\nICCModele4 <- round(VarModel4Niv1/(VarModel4Niv1+VarModel4Niv2),3)\n\ncoefs <- round(summary(Modele4)$coefficients,3)\nnvar1 <- length(VINiv1)+1\nnvar2 <- length(varsNiv2)\nnvar12 <- nvar1+nvar2\n\ncoefNiv1 <- coefs[1:nvar1,]\ncoefNiv2 <- coefs[(nvar1+1):nvar12,]\ncoefs <- rbind(coefNiv1, c(NA, NA, NA), coefNiv2,\n c(NA, NA, NA), coefs[(nvar12+1),])\n\nTableauModele4 <- as.data.frame(coefs)\ncols <- rownames(TableauModele4)\ncols[1] <- \" Constante\"\nTableauModele4 <- cbind(cols, TableauModele4)\nTableauModele4 <- rbind(c(NA, NA, NA, NA), TableauModele4)\nTableauModele4[1,1] <- \"Effets fixes (niveau 1 : tronçons)\"\nTableauModele4[(nvar1+2),1] <- \"Effets fixes (niveau 2 : secteurs de recensement)\"\n\nnlignes <- nrow(TableauModele4)\nTableauModele4[nlignes-1,1] <- \"Variable d'interaction (niv. 1 et 2)\"\nTableauModele4[nlignes,1] <- \"Setback X PCTFRAVI\"\nTableauModele4[nlignes+1,1] <- \"Répartition de la variance\"\nTableauModele4[nlignes+2,1] <- \"Variance (niveau 1)\"\nTableauModele4[nlignes+3,1] <- \"Variance (niveau 2)\"\nTableauModele4[nlignes+4,1] <- \"Coefficient de corrélation intraclasse\"\nTableauModele4[nlignes+2,2] <- VarModel4Niv1\nTableauModele4[nlignes+3,2] <- VarModel4Niv2\nTableauModele4[nlignes+4,2] <- ICCModele4\n\nTableauModele4[nlignes+5,1] <- \"Qualité d'ajustement du modèle\"\nTableauModele4[nlignes+6,1] <- \"AIC\"\nTableauModele4[nlignes+7,1] <- \"R^2^ marginal\"\nTableauModele4[nlignes+8,1] <- \"R^2^ conditionnel\"\n\nTableauModele4[nlignes+6,2] <- round(AIC(Modele4),3)\nTableauModele4[nlignes+7,2] <- round(r.squaredGLMM(Modele4)[1],3)\nTableauModele4[nlignes+8,2] <- round(r.squaredGLMM(Modele4)[2],3)\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(TableauModele4[, c(1,2,3,4)],\n\t\t digits = 3,\n row.names = FALSE,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Paramètre\" , \"Coefficient\" , \"Erreur type\", \"Valeur de T\"),\n align= c(\"l\" , \"r\" , \"r\", \"r\")\n )\n```\n\n## Conditions d'application des régressions multiniveaux {#sec-103}\n\nPuisque les modèles multiniveaux sont une extension des modèles à effets mixtes (GLMM), nous retrouvons globalement les mêmes conditions d'application (voir la [section @sec-093]), dont les principales sont :\n\n1. l'absence de multicolinéarité excessive,\n2. la normalité des résidus,\n3. l'absence d'observations trop influentes dans le modèle.\n\n**Combien de groupes au niveau 2?** Dans la [section @sec-093], nous avons vu que dans un modèle GLMM, plusieurs auteur(e)s, notamment Gelman et Hill \n [-@gelman2006data], préconisent un minimum de cinq groupes dans un modèle à effets mixtes. Toutefois, dans un modèle complet d'une régression multiniveau, nous introduisons aussi des variables indépendantes au niveau 2. Par conséquent, le nombre de groupes doit être augmenté significativement, et ce, idéalement proportionnellement au nombre des variables indépendantes ajoutées au niveau 2. En ce sens, Bressoux [-@bressoux2010, p.325] conseille d'avoir au moins 10 groupes pour chaque variable indépendante mesurée au niveau 2. Toujours selon Bressoux [-@bressoux2010, p.325], certains auteurs recommandent même 20 groupes par variable indépendante au niveau 2. En conséquence, bien qu'aucune règle de pouce soit clairement admise, il est clair qu'un modèle complet multiniveau nécessite un nombre de groupes conséquent.\n\n## Mise en œuvre dans R {#sec-104}\n\nPour mettre en œuvre des modèles multiniveaux avec une variable dépendante continue, nous utilisons la fonction `lmer` du *package* `lme4`. Pour d'autres distributions, nous pouvons utiliser la fonction `glmer` implémentant différentes familles de modèles GLM, notamment binomiale (modèle multiniveau logistique), gaussien, Gamma, inverse gaussien, Poisson, Quasi-poisson, etc. Comme pour les modèles GLMM, lorsque d’autres distributions sont nécessaires, il est possible d'utiliser le *package* `gamlss`.\n\n### Le modèle vide {#sec-1041}\nDans le code R ci-dessous, la syntaxe `lmer(PCTArb ~ 1 + (1| SRNOM), data = Multiniveau)` permet de construire le modèle vide avec la variable indépendante `PCTArb` et `SRNOM` comme variable définissant les groupes au niveau 2, soit les 312 secteurs de recensement. À titre de rappel, le modèle vide ne comprend aucune variable indépendante.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nlibrary(\"lme4\")\nlibrary(\"MuMIn\")\n# chargement du jeu de données\nload(\"data/multiniveau/dataArbres.RData\")\n\n# MODÈLE 1 : modèle vide (sans prédicteurs)\n#------------------------------------------------------\n# Écrire Y ~ 1 signifie que le modèle est vide\n# 1| SRNOM : signifie que l'on fait varier la constante avec la variable SRNOM\nModele1 <- lmer(PCTArb ~ 1 + (1| SRNOM), data = Multiniveau)\n\n# Nombre de groupes\ncat(\"nombre de groupes =\", length(unique(Multiniveau$SRNOM)))\n```\n\nLa fonction `summary(Modele1)` permet d'afficher les résultats du modèle. Dans la section intitulée `Random effects`, la variance pour le niveau 2 (`SRNOM (Intercept)`) est de 19,82 contre 92,93 pour le niveau 1 (`Residual`). Le coefficient de corrélation intraclasse (ICC) est donc égal à $\\mbox{19,82 / (19,82+92,93)} \\times \\mbox{100 = 17,58}$%.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Résultats du modèle\nsummary(Modele1)\n```\n\nNotez qu'il est possible d'obtenir directement la valeur de l'ICC avec la fonction `icc(Modele1)` du *package* `performance` et les statistiques d'ajustement du modèle avec les fonctions `logLik`, `AIC` et `BIC`.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Calcul de l'ICC (coefficient intraclasse)\nperformance::icc(Modele1)\nICC1 <- performance::icc(Modele1)\ncat(\"Part de la variance de la variable dépendante imputable au niveau 2 : \", \n round(ICC1$ICC_adjusted*100,2), \"%\", sep = \"\")\n\n# Qualité d'ajustement du modèle\ncat(\"Statistiques d'ajustement du modèle :\",\n \"\\n-2 Log V = \", -2*logLik(Modele1),\n \"\\nAIC =\", AIC(Modele1), \n \"\\nBIC =\", BIC(Modele1))\n```\n\n### Modèle avec les variables indépendantes du niveau 1 {#sec-1042}\n\nLe second modèle consiste à introduire les variables indépendantes mesurées pour les tronçons de rue (niveau 1). Notez comment sont centrées préalablement les variables explicatives.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n\n# Centrage des variables indépendantes\nVINiv1 <- c(\"Width\" , \"Length\" , \"AgeMed\" , \"AgeMed2\" , \"ResiPCT\" , \"DuTriPct\" , \"NoLog\" , \"Setback\")\nfor (e in VINiv1){\n e.c <- paste(e, \".c\", sep = \"\")\n Multiniveau[[e.c]] <- Multiniveau[[e]] - mean(Multiniveau[[e]])\n}\n\n# MODÈLE 2 : modèle avec les prédicteurs au niveau 1 (rues) \n# ------------------------------------------------------\nModele2 <- lmer(PCTArb ~\n # Variables indépendantes au niveau 1\n Width.c+Length.c+AgeMed.c+AgeMed2.c+ResiPCT.c+DuTriPct.c+NoLog.c+Setback.c+\n (1| SRNOM), data = Multiniveau)\n\n# Résultats du modèle\nsummary(Modele2)\n\n# Calcul de l'ICC (coefficient intraclasse)\nperformance::icc(Modele2)\nICC2 <- performance::icc(Modele2)\ncat(\"Part de la variance de la variable dépendante \",\n \"\\nimputable au niveau 2 : \", round(ICC2$ICC_adjusted*100,2), \"%\", sep = \"\")\n\n# Calcul des R2 conditionnel et marginal avec les fonctions\n# r.squaredGLMM ou r2_nakagawa du package performance\nr.squaredGLMM(Modele2)\nr2_nakagawa(Modele2)\n\n# Qualité d'ajustement du modèle\ncat(\"Statistiques d'ajustement du modèle\",\n \"\\n-2 Log L = \", -2*logLik(Modele2),\n \"\\nAIC =\", AIC(Modele2), \n \"\\nBIC =\", BIC(Modele2))\n```\n\n\n### Modèle avec les variables indépendantes aux niveaux 1 et 2 {#sec-1043}\n\nLe troisième modèle comprend à la fois les variables indépendantes mesurées aux deux niveaux (tronçons et secteurs de recensement).\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n\n# MODÈLE 3 : modèle complet avec les prédicteurs aux niveaux 1 et 2\n# ------------------------------------------------------\nModele3 <- lmer(PCTArb ~\n # Variables indépendantes au niveau 1\n Width.c+Length.c+AgeMed.c+AgeMed2.c+ResiPCT.c+DuTriPct.c+NoLog.c+Setback.c+\n # Variables indépendantes au niveau 2\n ValLog+UDipPCT+PCTFRAVI+PCTIMGRE+AvecEnf+FranPCT+\n (1| SRNOM), data = Multiniveau)\n\n# Résultats du modèle\nsummary(Modele3)\n\n# Qualité d'ajustement du modèle\ncat(\"Statistiques d'ajustement du modèle\",\n \"\\n-2 Log L = \", -2*logLik(Modele3),\n \"\\nAIC =\", AIC(Modele3), \"\\nBIC =\", BIC(Modele3))\n\n# Calcul de l'ICC (coefficient intraclasse)\nperformance::icc(Modele3)\nICC3 <- performance::icc(Modele3)\ncat(\"Part de la variance de la variable dépendante \",\n \"\\nimputable au niveau 2 : \", round(ICC3$ICC_adjusted*100,2), \"%\", sep = \"\")\n\n# Calcul des R2 conditionnel et marginal avec les fonctions\n# r.squaredGLMM ou r2_nakagawa du package performance\nr.squaredGLMM(Modele3)\nr2_nakagawa(Modele3)\n```\n\n### Modèle complet avec une interaction {#sec-10414}\n\nLe quatrième modèle consiste à ajouter au modèle complet une interaction entre deux variables des deux niveaux.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n# Variance d'interaction\nMultiniveau$PCTFRAVI_Setback <- Multiniveau$PCTFRAVI * Multiniveau$Setback.c\n\n# MODÈLE 4 : interaction aux deux niveaux\n# ------------------------------------------------------\nModele4 <- lmer(PCTArb ~\n # Variables indépendantes au niveau 1\n Width.c+Length.c+AgeMed.c+AgeMed2.c+ResiPCT.c+DuTriPct.c+NoLog.c+Setback.c+\n # Variables indépendantes au niveau 2\n ValLog+UDipPCT+PCTFRAVI+PCTIMGRE+AvecEnf+FranPCT+\n # Variable d'interaction\n PCTFRAVI_Setback+\n(1| SRNOM), data = Multiniveau)\n\n# Résultats du modèle\nsummary(Modele4)\n\n# Qualité d'ajustement du modèle\ncat(\"Statistiques d'ajustement du modèle\",\n \"\\n-2 Log L = \", -2*logLik(Modele4),\n \"\\nAIC =\", AIC(Modele3), \"\\nBIC =\", BIC(Modele4))\n\n# Calcul de l'ICC (coefficient intraclasse)\nperformance::icc(Modele4)\nICC4 <- performance::icc(Modele4)\ncat(\"Part de la variance de la variable dépendante \",\n \"\\nimputable au niveau 2 : \", round(ICC4$ICC_adjusted*100,2), \"%\", sep = \"\")\n\n# Calcul des R2 conditionnel et marginal avec les fonctions\n# r.squaredGLMM ou r2_nakagawa du package performance\nr.squaredGLMM(Modele4)\nr2_nakagawa(Modele4)\n```\n\n### Comparaison des quatre modèles {#sec-1045}\n\nPour comparer les modèles, nous utilisons habituellement les statistiques d'ajustement du modèle vues plus haut, soit le maximum de vraisemblance (*−2 Log-likelihood*), l'AIC, l'ICC et les R^2^ marginal et conditionnel.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nc_logLik <- c(logLik(Modele1),logLik(Modele2),logLik(Modele3),logLik(Modele4))\nICC <- c(performance::icc(Modele1)$ICC_adjusted,\n performance::icc(Modele2)$ICC_adjusted,\n performance::icc(Modele3)$ICC_adjusted,\n performance::icc(Modele4)$ICC_adjusted)\n\nR2m <- c(r.squaredGLMM(Modele1)[1],\n r.squaredGLMM(Modele2)[1],\n r.squaredGLMM(Modele3)[1],\n r.squaredGLMM(Modele4)[1])\n\nR2c <- c(r.squaredGLMM(Modele1)[2],\n r.squaredGLMM(Modele2)[2],\n r.squaredGLMM(Modele3)[2],\n r.squaredGLMM(Modele4)[2])\n\nprint(data.frame(\n Modele = c(\"Modèle 1 (vide)\", \n \"Modèle 2 (VI : niv. 1)\", \n \"Modèle 3 (VI : niv. 1 et 2)\",\n \"Modèle 4 (interaction niv. 1 et 2\"),\n dl = AIC(Modele1, Modele2, Modele3, Modele4)$df,\n Moins2LogLik = round(-2*c_logLik,0),\n AIC = round(AIC(Modele1, Modele2, Modele3, Modele4)$AIC,0),\n ICC = round(ICC,4),\n R2marg = round(R2m,3),\n R2cond = round(R2c,3)\n))\n```\n\nVous constaterez ci-dessus que les valeurs d'AIC et de -2 log de vraisemblance diminuent des modèles 1 à 4, signalant une amélioration progressive des modèles. Cela se traduit aussi par une augmentation du R^2^ conditionnel incluant à la fois les effets fixes et aléatoires. Sans surprise, la valeur du coefficient de corrélation intraclasse diminue du modèle vide au modèle complet : plus nous ajoutons de variables dépendantes, plus la capacité explicative du niveau 2 diminue.\n\nIl est également judicieux de vérifier si un modèle est significativement différent du modèle précédent avec la fonction `anova` qui compare les différences de leurs déviances. En guise d'exemple, la différence de déviance de 59 ($\\mbox{78 625}-\\mbox{78 684}=\\mbox{59}$) entre les modèles 3 et 2 (modèle complet *versus* modèle GLMM) avec six degrés de liberté – puisque le modèle 3 inclut six variables indépendantes de plus que le précédent ($\\mbox{17}-\\mbox{11}=\\mbox{6}$) – est significative (*p* < 0,001). Cela indique que le modèle 3 est plus performant que le précédent.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\nanova(Modele1, Modele2, Modele3, Modele4)\n```\n\n## Quiz de révision du chapitre {#sec-105}\n\n```{r}\n#| label: quizChapitre10\n#| echo: false\n#| warning: false\n#| results: asis\nsource(\"code_complementaire/QuizzFunctions.R\")\nChapitre10_Multiniveau <- quizz(\"quiz/Chapitre10_Multiniveau.yml\", \"Chapitre10_Multiniveau\")\nrender_quizz(Chapitre10_Multiniveau)\n```\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"10-Multiniveau.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/11-GAM.qmd.json b/.quarto/idx/11-GAM.qmd.json new file mode 100644 index 0000000..96af707 --- /dev/null +++ b/.quarto/idx/11-GAM.qmd.json @@ -0,0 +1 @@ +{"title":"Modèles généralisés additifs","markdown":{"headingText":"Modèles généralisés additifs ","headingAttr":{"id":"sec-chap11","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans les précédents chapitres, nous avons eu l'occasion d'explorer toute une panoplie de modèles : régressions linéaires, modèles généralisés, modèles généralisés à effets mixtes et modèles multiniveaux. Dans ce chapitre, nous abordons une nouvelle extension dans le monde des régressions : les modèles généralisés additifs (*Generalized additive model* en anglais — GAM). Cette extension a pour but de permettre de modéliser des relations non linéaires entre les variables indépendantes et la variable dépendante.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2` le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes.\n - `metR` pour placer des étiquettes sur des isolignes.\n \n* Pour jouer avec des *splines* :\n - `splines2` pour construire les fonctions de base de nombreuses *splines*.\n - `segmented` pour ajuster des modèles avec des coefficients variant par segment.\n \n* Pour ajuster des modèles GAM :\n - `mgcv`, le *package* de référence pour ajuster des GAM dans R!\n - `gamlss`, un second *package* très flexible pour ajuster des GAM.\n - `gamlss.add`, une extension de `gamlss` ajoutant des distributions supplémentaires.\n\n* Pour analyser des modèles GAM :\n - `itsadug` pour notamment extraire certains résultats d'un GAM.\n - `mixedup` pour notamment extraire les effets aléatoires d'un GAM.\n - `DHARMa` pour le diagnostic des résidus simulés.\n:::\n:::\n\n\n## Introduction {#sec-111}\n\nPuisque les modèles GAM sont une extension des modèles GLM, ils peuvent s'appliquer à des modèles pour des variables indépendantes qualitatives, de comptage ou continues. Nous l'appliquons ici, à titre d'illustration, à une variable indépendante continue. Pour rappel, la formule décrivant un modèle linéaire généralisé (GLM) utilisant une distribution normale et une fonction de lien identitaire est la suivante : \n\n$$\n\\begin{aligned}\n&Y \\sim Normal(\\mu,\\sigma)\\\\\n&g(\\mu) = \\beta_0 + \\beta X\\\\\n&g(x) = x\n\\end{aligned}\n$$ {#eq-glm1B}\n\nLes coefficients $\\beta$ permettent de quantifier l'effet des variables indépendantes (*X*) sur la moyenne (l'espérance) ($\\mu$) de la variable dépendante (*Y*). Un coefficient $\\beta_k$ négatif indique que, si la variable $X_k$ augmente, alors la variable *Y* tend à diminuer et inversement, si le coefficient est positif. L'inconvénient de cette formulation est que le modèle est capable de capter uniquement des relations linéaires entre ces variables. Or, il existe de nombreuses situations dans lesquelles une variable indépendante a un lien non linéaire avec une variable dépendante; voici quelques exemples : \n\n* Si nous mesurons le niveau de bruit émis par une source sonore (variable dépendante) à plusieurs endroits et que nous tentons de prédire l'intensité sonore en fonction de la distance à la source (variable indépendante), nous pouvons nous attendre à observer une relation non linéaire entre les deux. En effet, le son étant une énergie se dispersant selon une sphère dans l'espace, son intensité est inversement proportionnelle au carré de la distance avec la source sonore.\n\n* La concentration de la pollution atmosphérique en ville suit généralement des patrons temporels et spatiaux influencés directement par la météorologie et les activités humaines. Autrement dit, il serait absurde d'introduire l'espace de façon linéaire (avec un gradient nord-sud ou est-ouest), ou le moment de la journée de façon linéaire (comme si la pollution augmentait du matin au soir ou inversement). En guise d'exemple, la @fig-gam1, tirée de @2020_3, illustre bien ces variations temporelles pour deux polluants (le dioxyde d'azote et l'ozone).\n\n\n![Patron journalier du dioxyde d'azote et de l'ozone à Paris](images/Chap11/no2_03_patterns.png){#fig-gam1 width=\"75%\" fig-align=\"center\"}\n\n### Non-linéarité fonctionnelle {#sec-1111}\n\nIl existe de nombreuses façons d'introduire des relations non linéaires dans un modèle. La première et la plus simple à mettre en œuvre est de transformer la variable indépendante à l'aide d'une fonction inverse, exponentielle, logarithmique ou autre.\n\nPrenons un premier exemple avec une variable *Y* que nous tentons de prédire avec une variable *X*, présenté à la @fig-gam2. Si nous ajustons une droite de régression à ces données (en bleu), nous constatons que l'augmentation de *X* est associée à une augmentation de *Y*. Cependant, la droite de régression est très éloignée des données et ne capte qu'une petite partie de la relation. Une lecture attentive permet de constater que l'effet de *X* sur *Y* augmente de plus en plus rapidement à mesure que *X* augmente. Cette forme est caractéristique d'une relation exponentielle. Nous pouvons donc transformer la variable *X* avec la fonction exponentielle afin d'obtenir un meilleur ajustement (en rouge).\n\n```{r}\n#| label: fig-gam2\n#| fig-cap: Relation non linéaire exponentielle\n#| echo: false\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"50%\"\nlibrary(ggplot2)\nlibrary(ggpubr)\nlibrary(boot)\n\ntofr <- function(float){\n return(gsub(\".\" , \",\", as.character(float), fixed = TRUE, useBytes = TRUE))\n}\n\ndf <- data.frame(\n x1 = rnorm(1000,0,1),\n x2 = rnorm(1000,10,5),\n x3 = rnorm(1000,0,3),\n x4 = abs(rnorm(1000,0,5))\n)\n\ndf$y1 <- exp(df$x1) + rnorm(1000,0,2)\ndf$y2 <- -log(df$x2 + rnorm(1000,0,1))\ndf$y3 <- inv.logit(df$x3) + rnorm(1000,0,0.3)\ndf$y4 <- sqrt(df$x4) + rnorm(1000,0,0.2)\n\n\nggplot(df)+\n geom_point(aes(x = x1, y = y1), size = 0.5) + \n labs(x = \"x\", y = \"y\") + \n geom_smooth(aes(x = x1, y = y1), method = \"lm\",\n se = FALSE, color = \"blue\", formula = y ~ x)+ \n geom_smooth(aes(x = x1, y = y1), method = \"lm\",\n se = FALSE, color = \"red\", formula = y ~ exp(x))\n\n```\n\n\nLa @fig-gam3 illustre trois autres situations avec les fonctions logarithmique, logistique inverse et racine carrée. Cette approche peut donner des résultats intéressants si vous disposez d'une bonne justification théorique sur la forme attendue de la relation entre *X* et *Y*. \n\n```{r}\n#| label: fig-gam3\n#| fig-cap: Autres relations non linéaires\n#| echo: false\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\n\nP1 <- ggplot(df)+\n geom_point(aes(x = x2, y = y2), size = 0.5) + \n labs(x = \"x\", y = \"y\", subtitle = \"fonction logarithmique\") + \n geom_smooth(aes(x = x2, y = y2), method = \"lm\",\n se = FALSE, color = \"blue\", formula = y ~ x)+ \n geom_smooth(aes(x = x2, y = y2), method = \"lm\",\n se = FALSE, color = \"red\", formula = y ~ log(x)) + \n ylim(-3,2.5) + xlim(0,20)\n\nP2 <- ggplot(df)+\n geom_point(aes(x = x3, y = y3), size = 0.5) + \n labs(x = \"x\", y = \"y\", subtitle = \"fonction logistique inverse\") + \n geom_smooth(aes(x = x3, y = y3), method = \"lm\",\n se = FALSE, color = \"blue\", formula = y ~ x)+ \n geom_smooth(aes(x = x3, y = y3), method = \"lm\",\n se = FALSE, color = \"red\", formula = y ~ inv.logit(x))\n\nP3 <- ggplot(df)+\n geom_point(aes(x = x4, y = y4), size = 0.5) + \n labs(x = \"x\", y = \"y\", subtitle = \"fonction racine carrée\") + \n geom_smooth(aes(x = x4, y = y4), method = \"lm\",\n se = FALSE, color = \"blue\", formula = y ~ x)+ \n geom_smooth(aes(x = x4, y = y4), method = \"lm\",\n se = FALSE, color = \"red\", formula = y ~ sqrt(x))\n\nggarrange(P1, P2, P3, ncol = 2, nrow = 2)\n\n```\n\nIl existe également des cas de figure dans lesquels aucune fonction ne donne de résultats pertinents, comme illustré à la @fig-gam4. Nous constatons facilement qu'aucune des fonctions proposées n'est capable de bien capter la relation entre les deux variables. Puisque cette relation est complexe, il convient alors d'utiliser une autre stratégie pour la modéliser. \n\n```{r}\n#| label: fig-gam4\n#| echo: false\n#| fig-align: center\n#| fig-cap: Relation non linéaire plus complexe\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nlibrary(mgcv)\ndataset <- gamSim(eg = 1, n = 400, dist = \"normal\", scale = 1, verbose = FALSE)\n\nggplot(dataset) + \n geom_point(aes(y = y, x = x2), size = 1) + \n geom_smooth(aes(x = x2, y = y, color = \"lineaire\"), method = \"lm\",\n se = FALSE, formula = y ~ x, size = 1.3) + \n geom_smooth(aes(x = x2, y = y, color = \"logarithme\"), method = \"lm\",\n se = FALSE, formula = y ~ log(x), size = 1.3) +\n geom_smooth(aes(x = x2, y = y, color = \"racine carrée\"), method = \"lm\",\n se = FALSE, formula = y ~ sqrt(x), size = 1.3) + \n scale_color_manual(values = c(\"lineaire\" = \"#0077b6\",\n \"logarithme\" = \"#e63946\",\n \"racine carrée\" = \"#2a9d8f\"))+\n labs(colour = 'forme fonctionelle')\n\n```\n\n\n### Non-linéarité avec des polynomiales {#sec-1112}\n\nNous avons vu, dans le chapitre sur la régression simple ([section @sec-07511]), qu'il est possible d'utiliser des polynomiales pour ajuster des relations non linéaires. Pour rappel, il s'agit simplement d'ajouter à un modèle la variable *X* à différents exposants ($X+X^2+\\dots+X^k$). Chaque exposant supplémentaire (chaque ordre supplémentaire) permet au modèle d'ajuster une relation plus complexe. Rien de tel qu'un graphique pour illustrer le tout (@fig-gam5).\n\n```{r}\n#| label: fig-gam5\n#| echo: false\n#| fig-align: center\n#| fig-cap: Visualisation de plusieurs polynomiales\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\np1 <- ggplot(dataset) + \n geom_point(aes(y = y, x = x2), size = 1) + \n geom_smooth(aes(x = x2, y = y), color = \"blue\" , method = \"lm\",\n se = FALSE, formula = y ~ x + I(x**2), size = 1.3) + \n labs(subtitle = \"polynomiale de degré 2\", x = \"x\", y = \"y\")\n \np2 <- ggplot(dataset) + \n geom_point(aes(y = y, x = x2), size = 1) + \n geom_smooth(aes(x = x2, y = y), color = \"blue\" , method = \"lm\",\n se = FALSE, formula = y ~ x + I(x**2) + I(x**3), size = 1.3) + \n labs(subtitle = \"polynomiale de degré 3\", x = \"x\", y = \"y\")\n\np3 <- ggplot(dataset) + \n geom_point(aes(y = y, x = x2), size = 1) + \n geom_smooth(aes(x = x2, y = y), color = \"blue\" , method = \"lm\",\n se = FALSE, formula = y ~ x + I(x**2) + I(x**3) + I(x**4), size = 1.3) + \n labs(subtitle = \"polynomiale de degré 4\", x = \"x\", y = \"y\")\n\np4 <- ggplot(dataset) + \n geom_point(aes(y = y, x = x2), size = 1) + \n geom_smooth(aes(x = x2, y = y), color = \"blue\" , method = \"lm\",\n se = FALSE, formula = y ~ x + I(x**2) + I(x**3) + I(x**4)+ I(x**5), size = 1.3) + \n labs(subtitle = \"polynomiale de degré 5\", x = \"x\", y = \"y\")\n\nggarrange(p1, p2, p3, p4, ncol = 2, nrow = 2)\n```\n\nL'enjeu est de sélectionner le bon nombre de degrés de la polynomiale pour le modèle. Chaque degré supplémentaire constitue une nouvelle variable dans le modèle, et donc un paramètre supplémentaire. Un trop faible nombre de degrés produit des courbes trop simplistes, alors qu'un nombre trop élevé conduit à un surajustement (*overfitting* en anglais) du modèle. La @fig-gam6 illustre ces deux situations.\n\n```{r}\n#| label: fig-gam6\n#| echo: false\n#| fig-align: center\n#| fig-cap: Sur et sous-ajustement d'une polynomiale\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\nggplot(dataset) + \n geom_point(aes(y = y, x = x2), size = 1) + \n geom_smooth(aes(x = x2, y = y), color = \"blue\" , method = \"lm\",\n se = FALSE, formula = y ~ x + I(x**2), size = 1.3) +\n geom_smooth(aes(x = x2, y = y), color = \"red\" , method = \"lm\",\n se = FALSE, formula = y ~ x + poly(x, degree = 12), size = 1.3) + \n labs(subtitle = \"polynomiales de degrés 2 (bleu) et 12 (rouge)\", x = \"x\", y = \"y\")\n```\n\nUn des problèmes inhérents à l'approche des polynomiales est la difficulté d'interprétation. En effet, les coefficients ne sont pas directement interprétables et seule une figure représentant les prédictions du modèle permet d'avoir une idée de l'effet de la variable *X* sur la variable *Y*.\n\n### Non-linéarité par segments {#sec-1113}\n\nUn compromis intéressant offrant une interprétation simple et une relation potentiellement complexe consiste à découper la variable *X* en segments, puis d'ajuster un coefficient pour chacun de ces segments. Nous obtenons ainsi une ligne brisée et des coefficients faciles à interpréter (@fig-gam7). Nous ne présentons pas d'exemple d'application dans R, mais sachez que le *package* `segmented` permet d'ajuster ce type de modèle. \n\n```{r}\n#| label: fig-gam7\n#| echo: false\n#| fig-align: center\n#| fig-cap: Régression par segment\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\nlibrary(segmented)\n\nmodel <- lm(y ~ x2, data = dataset)\no <- segmented(model, seg.Z = ~x2, psi = list(x2 = c(0.25,0.5)),\n control = seg.control(display = FALSE)\n)\ndataset$fit <- broken.line(o)$fit\n\nggplot(dataset) + \n geom_point(aes(y = y, x = x2), size = 1) + \n geom_line(aes(x = x2, y = fit), color = \"blue\", linewidth = 1)\n```\n\nL'enjeu est alors de déterminer le nombre de points et la localisation de points de rupture. L'inconvénient majeur de cette approche est qu'en réalité, peu de phénomènes sont marqués par des ruptures très nettes.\n\nÀ la @fig-gam7, nous avons divisé la variable *X* en trois segments ($k_1$, $k_2$ et $k_3$), définis respectivement avec les intervalles suivants : [0,00-0,22], [0,22-0,41] et [0,41-1,00]. Concrètement, cela revient à diviser la variable *X* en trois nouvelles variables $X_{k1}$, $X_{k2}$, et $X_{k3}$. La valeur de $X_{ik}$ est égale à $x_i$ si $x_i$ se trouve dans l'intervalle propre à *k*, et à 0 autrement. Ici, nous obtenons trois coefficients : \n\n* le premier est positif, une augmentation de *X* sur le premier segment est associée à une augmentation de *Y*;\n\n* le second est négatif, une augmentation de *X* sur le second segment est associée à une diminution de *Y*;\n\n* le troisième est aussi négatif, une augmentation de *X* sur le troisième segment est associée à une diminution de *Y*, mais moins forte que pour le second segment.\n\n\n### Non-linéarité avec des *splines* {#sec-1114}\n\nLa dernière approche, et certainement la plus flexible, est d'utiliser ce que l'on appelle une *spline* pour capter des relations non linéaires. Une *spline* est une fonction créant des variables supplémentaires à partir d'une variable *X* et d'une fonction de base. Ces variables supplémentaires, appelées bases (*basis* en anglais), sont ajoutées au modèle; la sommation de leurs valeurs multipliées par leurs coefficients permet de capter les relations non linéaires entre une variable dépendante et une variable indépendante. Le nombre de bases et leur localisation (plus souvent appelé nœuds) permettent de contrôler la complexité de la fonction non linéaire.\n\nPrenons un premier exemple simple avec une fonction de base triangulaire (*tent basis* en anglais). Nous créons ici une *spline* avec sept nœuds répartis équitablement sur l'intervalle de valeurs de la variable *X*. Les sept bases qui en résultent sont présentées à la @fig-gam8. Dans cette figure, chaque sommet d'un triangle correspond à un nœud et chaque triangle correspond à une base.\n\n\n```{r}\n#| label: fig-gam8\n#| echo: false\n#| fig-align: center\n#| fig-cap: Bases de la spline triangulaire\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nlibrary(splines)\n\nbasis <- bs(dataset$x2, df = 7, degre = 1)\ndf <- data.frame(basis * 3)\ndf$X <- dataset$x2\ndf <- reshape2::melt(df, id.vars = \"X\")\n\nggplot() + \n geom_point(aes(y = y, x = x2), size = 1, data = dataset) + \n geom_line(aes(x = X, y = value, color = variable), linewidth = 1, data = df) + theme(legend.position = \"none\") \n```\n\n\nEn ajoutant ces bases dans notre modèle de régression, nous pouvons ajuster un coefficient pour chacune et le représenter en multipliant ces bases par les coefficients obtenus avec une simple régression linéaire (@fig-gam9).\n\n```{r}\n#| label: fig-gam9\n#| echo: false\n#| fig-align: center\n#| fig-cap: Spline triangulaire multipliée par ces coefficients\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\nbasis <- bs(dataset$x2, df = 7, degre = 1)\nmodel <- lm(y ~ basis, data = dataset)\ncoefs <- coefficients(model)[2:length(coefficients(model))]\n\nprodbase <- sweep(basis, MARGIN = 2, coefs, `*`)\n\ndf <- data.frame(prodbase)\ndf$X <- dataset$x2\ndf <- reshape2::melt(df, id.vars = \"X\")\n\nggplot() + \n geom_point(aes(y = y, x = x2), size = 1, data = dataset) + \n geom_line(aes(x = X, y = value, color = variable), linewidth = 1, data = df) + theme(legend.position = \"none\") \n```\n\nNous remarquons ainsi que les bases correspondant à des valeurs plus fortes de *Y* ont reçu des coefficients plus élevés. Pour reconstituer la fonction non linéaire, il suffit d'additionner ces bases multipliées par leurs coefficients, soit la ligne bleue à la @fig-gam10.\n\n```{r}\n#| label: fig-gam10\n#| echo: false\n#| fig-align: center\n#| fig-cap: Spline triangulaire\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\n\nbasis <- bs(dataset$x2, df = 7, degre = 1)\nmodel <- lm(y ~ basis, data = dataset)\ncoefs <- coefficients(model)[2:length(coefficients(model))]\n\nprodbase <- sweep(basis, MARGIN = 2, coefs, `*`)\ntotal <- rowSums(prodbase) + coefficients(model)[1]\n\ndf <- data.frame(prodbase)\ndf$X <- dataset$x2\ndf <- reshape2::melt(df, id.vars = \"X\")\ndf$total <- total\n\nggplot() + \n geom_point(aes(y = y, x = x2), size = 1, data = dataset) + \n geom_line(aes(x = X, y = value, group = variable), color = \"grey\", linetype = \"dashed\", linewidth = 1, data = df) +\n geom_line(aes(x = X, y = total), color = \"blue\", linewidth = 1, data = df)+\n theme(legend.position = \"none\") \n```\n\nLa fonction de base triangulaire est intéressante pour présenter la logique qui sous-tend les *splines*, mais elle est rarement utilisée en pratique. On lui préfère généralement d'autres formes donnant des résultats plus lisses comme les *B-spline* quadratiques, *B-spline* cubiques, *M-spline*, *Duchon spline*, etc.\n\n```{r}\n#| label: fig-gam11\n#| echo: false\n#| fig-align: center\n#| fig-cap: Comparaison de différentes bases\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nlibrary(mgcv)\nlibrary(splines2)\n\n# Squared spline\nbasis <- bSpline(dataset$x2, df = 7, degre = 2)\nmodel <- lm(y ~ basis, data = dataset)\ncoefs <- coefficients(model)[2:length(coefficients(model))]\n\nprodbase <- sweep(basis, MARGIN = 2, coefs, `*`)\ntotal <- rowSums(prodbase) + coefficients(model)[1]\n\ndf <- data.frame(prodbase)\ndf$X <- dataset$x2\ndf <- reshape2::melt(df, id.vars = \"X\")\ndf$total <- total\n\nP1 <- ggplot() + \n geom_point(aes(y = y, x = x2), size = 1, data = dataset) + \n geom_line(aes(x = X, y = value, group = variable), color = \"grey\", linetype = \"dashed\", linewidth = 1, data = df) +\n geom_line(aes(x = X, y = total), color = \"blue\", linewidth = 1, data = df)+\n theme(legend.position = \"none\") + \n labs(subtitle = \"B-spline quadratique\")+ \n ylim(0,20)\n\n\n# Spline cubique\nbasis <- bSpline(dataset$x2, df = 7, degre = 3)\nmodel <- lm(y ~ basis, data = dataset)\ncoefs <- coefficients(model)[2:length(coefficients(model))]\n\nprodbase <- sweep(basis, MARGIN = 2, coefs, `*`)\ntotal <- rowSums(prodbase) + coefficients(model)[1]\n\ndf <- data.frame(prodbase)\ndf$X <- dataset$x2\ndf <- reshape2::melt(df, id.vars = \"X\")\ndf$total <- total\n\nP2 <- ggplot() + \n geom_point(aes(y = y, x = x2), linewidth = 1, data = dataset) + \n geom_line(aes(x = X, y = value, group = variable), color = \"grey\", linetype = \"dashed\", linewidth = 1, data = df) +\n geom_line(aes(x = X, y = total), color = \"blue\", linewidth = 1, data = df)+\n theme(legend.position = \"none\") + \n labs(subtitle = \"B-spline cubique\")+ \n ylim(0,20)\n\n# M-spline\nbasis <- mSpline(dataset$x2, df = 7, degre = 2)\nmodel <- lm(y ~ basis, data = dataset)\ncoefs <- coefficients(model)[2:length(coefficients(model))]\n\nprodbase <- sweep(basis, MARGIN = 2, coefs, `*`)\ntotal <- rowSums(prodbase) + coefficients(model)[1]\n\ndf <- data.frame(prodbase)\ndf$X <- dataset$x2\ndf <- reshape2::melt(df, id.vars = \"X\")\ndf$total <- total\n\nP3 <- ggplot() + \n geom_point(aes(y = y, x = x2), size = 1, data = dataset) + \n geom_line(aes(x = X, y = value, group = variable), color = \"grey\", linetype = \"dashed\", linewidth = 1, data = df) +\n geom_line(aes(x = X, y = total), color = \"blue\", linewidth = 1, data = df)+\n theme(legend.position = \"none\") + \n labs(subtitle = \"M-spline\")+ \n ylim(0,20)\n\n\n# Duchon spline\nsmoother <- smoothCon(s(x2, bs=\"ds\", k = 7), data = dataset, absorb.cons = T)\nbasis <- smoother[[1]]$X\nmodel <- lm(y ~ basis, data = dataset)\ncoefs <- coefficients(model)[2:length(coefficients(model))]\n\nprodbase <- sweep(basis, MARGIN = 2, coefs, `*`)\ntotal <- rowSums(prodbase) + coefficients(model)[1]\n\ndf <- data.frame(prodbase)\ndf$X <- dataset$x2\ndf <- reshape2::melt(df, id.vars = \"X\")\ndf$total <- total\n\nP4 <- ggplot() + \n geom_point(aes(y = y, x = x2), size = 1, data = dataset) + \n geom_line(aes(x = X, y = value, group = variable), color = \"grey\", linetype = \"dashed\", linewidth = 1, data = df) +\n geom_line(aes(x = X, y = total), color = \"blue\", linewidth = 1, data = df)+\n theme(legend.position = \"none\") + \n labs(subtitle = \"Duchon-spline\") + \n ylim(0,20)\n\nggarrange(P1, P2, P3, P4, ncol = 2, nrow = 2)\n```\n\nLes approches que nous venons de décrire sont regroupées sous l'appellation de modèles additifs. Dans les prochaines sous-sections, nous nous concentrons davantage sur les *splines* du fait de leur plus grande flexibilité.\n\n## *Spline* de régression et *spline* de lissage {#sec-112}\n\nDans les exemples précédents, nous avons vu que la construction d'une *spline* nécessite d'effectuer deux choix importants : le nombre de nœuds et leur localisation. Un trop grand nombre de nœuds conduit à un surajustement du modèle alors qu'un trop faible nombre de nœuds conduit à un sous-ajustement. Lorsque ces choix sont effectués par l'utilisateur et que les bases sont ajoutées manuellement dans le modèle tel que décrit précédemment, nous parlons alors de **_splines_ de régression** (*Regression Spline* en anglais).\n\nUne approche a été proposée pour faciliter le choix du nombre de nœuds, il s'agit de **_splines_ de lissage** (*smoothing spline* en anglais). L'idée derrière cette approche est d'introduire dans le modèle une pénalisation associée avec le nombre de nœuds (ou degré de liberté) de la *spline*, dans un souci de parcimonie : chaque nœud supplémentaire doit suffisamment contribuer au modèle pour être conservé. Il n'est pas nécessaire ici de rentrer dans le détail mathématique de cette pénalisation qui est un peu complexe. Retenez simplement qu'elle dépend d'un paramètre appelé $\\lambda$ :\n\n* plus $\\lambda$ tend vers 0, plus la pénalisation est faible et plus la *spline* de lissage devient une simple *spline* de régression; \n\n* à l'inverse, plus elle est forte, plus la pénalité est importante, au point que la *spline* peut se résumer à une simple ligne droite. \n\nCela est illustré à la @fig-gam12 comprenant trois *splines* avec 20 nœuds et des valeurs $\\lambda$ différentes contrôlant la force de la pénalité. \n\nBien évidemment, nous constatons qu'avec la *spline* de régression (non pénalisée), 20 nœuds conduisent à un fort surajustement du modèle. En revanche, les *splines* de lissage (pénalisées) permettent de corriger ce problème de surajustement. Toutefois, une valeur trop importante de $\\lambda$ conduit à un sous-ajustement du modèle (ici $\\lambda = 3$ et $\\lambda = 100$, lignes verte et bleue).\n\n\n```{r}\n#| label: fig-gam12\n#| echo: false\n#| fig-align: center\n#| fig-cap: Pénalisation des splines\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\n# Modèle 1 : régression spline sans pénalite\nmod1 <- gam(y~ s(x2, k = 20, fx = T), data = dataset)\n\n# Modèle 2 : régression spline avec pénalite = 3\nmod2 <- gam(y~ s(x2, k = 20, sp = 0.5), data = dataset)\n\n# Modèle 3 : régression spline avec pénalite = 10\nmod3 <- gam(y~ s(x2, k = 20, sp = 3), data = dataset)\n\n# Modèle 4 : régression spline avec pénalite = 100\nmod4 <- gam(y~ s(x2, k = 20, sp = 100), data = dataset)\n\ndf <- data.frame(\n y = dataset$y,\n x = dataset$x2,\n pred1 = predict(mod1),\n pred2 = predict(mod2),\n pred3 = predict(mod3),\n pred4 = predict(mod4)\n)\n\nggplot(df) + \n geom_point(aes(x = x, y = y), size = 1) +\n geom_line(aes(x = x, y = pred1, color = \"spline de régression\"), linewidth = 1.1) +\n geom_line(aes(x = x, y = pred2, color = \"lambda = 0.5\"), linewidth = 1.1) +\n geom_line(aes(x = x, y = pred3, color = \"lambda = 3\"), linewidth = 1.1)+\n geom_line(aes(x = x, y = pred4, color = \"lambda = 100\"), linewidth = 1.1) + \n labs(colour = 'pénalisation')\n\n```\n\n\nAvec les *splines* de lissage, l'enjeu est de sélectionner une valeur optimale de $\\lambda$. Le plus souvent, les *packages* R **estiment eux-mêmes** ce paramètre à partir des données utilisées dans le modèle. Toutefois, gardez en mémoire que vous pouvez modifier ce paramètre. Mentionnons également que les *splines* de lissage peuvent être reparamétrées dans un modèle pour être intégrées comme des effets aléatoires. Dans ce cas-ci, $\\lambda$ est remplacé par un simple paramètre de variance directement estimé dans le modèle [@wood2004stable].\n\n\n## Interprétation d'une *spline* {#sec-113}\n\nL'interprétation d'une *spline* se fait à l'aide de graphiques. En effet, puisqu'elle est composée d'un ensemble de coefficients appliqués à des bases, il est difficile d'interpréter directement ces derniers. Nous préférons alors représenter la fonction obtenue à l'aide d'un graphique, illustrant son **effet marginal**. Ce graphique est construit en trois étapes : \n\n1. Créer un jeu de données fictif dans lequel l'ensemble des variables indépendantes sont fixées à leurs moyennes respectives, sauf la variable pour laquelle nous souhaitons représenter la *spline*. Pour cette dernière, un ensemble de valeurs allant de son minimum à son maximum est utilisé;\n\n2. Utiliser le modèle pour prédire les valeurs attendues de la variable dépendante pour chacune des observations fictives ainsi créées;\n\n3. Afficher les prédictions obtenues dans un graphique.\n\nNotez ici qu'un graphique des effets marginaux se base sur les prédictions du modèle. Si un modèle est mal ajusté, les prédictions ne seront pas fiables et il sera inutile d'interpréter la *spline* obtenue.\n\nIl est aussi possible, dans le cas des *splines* de lissage, d'interpréter les *estimated degrees of freedom* (EDF) qui constituent une approximation du nombre de nœuds de la *spline*. S'ils ne nous renseignent pas sur la forme de la *spline*, ils nous indiquent son niveau de complexité. Une *spline* avec un EDF de 1 est en réalité un simple terme linéaire. Plus l'EDF augmente, plus la *spline* est complexe. \n\n\n## Multicolinéarité non linéaire {#sec-114}\n\nLorsque des *splines* sont ajoutées dans un modèle, il est nécessaire de vérifier si ces dernières ne posent pas un problème de multicolinéarité. Cependant, le VIF ne peut plus être utilisé du fait de la non-linéarité des relations modélisées. Il est alors nécessaire d'utiliser une autre mesure : la concurvité (*concurvity*) permettant de mesurer sur une échelle allant de 0 à 1 à quel point deux *splines* ont en réalité capturé le même effet et se substituent l'une à l'autre. Une valeur de 0 indique une absence totale de concurvité alors qu'une valeur de 1 indique que deux *splines* sont rigoureusement identiques (modèle non identifiable). \n\n## *Splines* avancées {#sec-115}\n\nJusqu'ici, nous avons seulement présenté le cas le plus simple pour lequel une *spline* est construite à partir d'une seule variable dépendante continue, mais les **splines** peuvent être utilisées dans de nombreux autres contextes et ont une incroyable flexibilité. Nous détaillons ici trois exemples fréquents : les *splines* cycliques, les *splines* variant par groupe et les *splines* multivariées. Pour une description complète des effets non linéaires possibles avec `mgcv`, n'hésitez pas à consulter sa [documentation](https://stat.ethz.ch/R-manual/R-patched/library/mgcv/html/smooth.terms.html).\n\n```{r}\n#| label: tbl-exemplesplines\n#| tbl-cap: Exemples de splines avancées\n#| echo: false\n#| message: false\n#| warning: false\n\ndf <- data.frame(\n Type = c(\"spline cyclique\", \"spline variant par groupe\", \"spline bivariée\", \n \"spline d'interaction complète\", \"spline d'interaction partielle\"),\n Code = c(\"`s(x, bs = 'cc')`\" , \"`s(x, by = x2)`\" , \"`s(x1,x2)`\" , \"`te(x1,x2)`\",\n \"`s(x1) + s(x2) + ti(x1,x2)`\"),\n Description = c(\"Une spline cyclique doit être utilisée si le 0 de la variable X correspond également à sa valeur maximum. Un bon exemple est le temps dans une journée, car 24 h est équivalent à 0 h\", \"Une spline variant par groupe permet d'ajuster une spline à une variable X1 différente pour chaque groupe identifié par une variable qualitative X2\", \"Une spline bivariée est utilisée pour modéliser l'interaction non linéaire de deux variables X1 et X2 s'exprimant dans la même unité (typiquement des coordonnées géographiques cartésiennes)\", \"Une spline d'interaction permet de modéliser l'interaction non linéaire de deux variables continues pouvant s'exprimer dans des unités différentes, elle combine les effets spécifiques de chacune des deux variables et leur interaction\", \"Une spline d'interaction partielle permet de distinguer les effets non linéaires individuels de deux variables de leur interaction non linéaire\"))\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(df, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Type\" , \"Code\" , \"Description\"),\n col.to.resize = 3,\n col.width = c(\"10cm\")\n )\n\n```\n\n\n### *Splines* cycliques {#sec-1151}\n\nUne *spline* cyclique est une extension d'une *spline* classique dont les bases aux extrémités sont spécifiées de telle sorte que la valeur au départ de la *spline* soit la même que celle à la fin de la *spline*. Cela permet à la *spline* de former une boucle, ce qui est particulièrement intéressant pour des variables dont le 0 et la valeur maximale correspondent en réalité à la même valeur. L'exemple le plus parlant est certainement le cas d'une variable représentant la mesure d'un angle en degrés. Les valeurs de 0 et 360 sont identiques et les valeurs 350 et 10 sont toutes les deux à une distance de 10 degrés de 0. Un autre exemple possible serait de considérer l'heure comme une variable continue; dans ce cas, 24 h et 0 h signifient la même chose.\n\nPrenons un exemple concret. Nous souhaitons modéliser la concentration de dioxyde d'azote (NO~2~) à Paris, mesurée par un ensemble de stations fixes. Nous pourrions nous attendre à ce que le NO~2~ suive chaque jour un certain patron. Concrètement, à proximité d'axes routiers majeurs, nous nous attendons à observer des pics suivant les flux pendulaires. À la @fig-gam13, nous retrouvons bien les deux pics attendus correspondant aux heures de pointe du matin et du soir. Aussi, comme indiqué par la ligne rouge, la valeur prédite par la *spline* est la même à 24 h et à 0 h.\n\n\n```{r}\n#| label: fig-gam13\n#| echo: false\n#| fig-align: center\n#| fig-cap: Spline cyclique pour modéliser la concentration de dioxyde d'azote\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\ndataset <- read.csv('data/gam/NO2_airparif.csv', sep=';')\ndataset <- dataset[2:nrow(dataset),]\ndf <- reshape2::melt(dataset, id.vars = c(\"heure\" , \"date\"))\ndf$no2 <- ifelse(df$value == \"n/d\", NA, as.numeric(df$value))\n\nmodel <- gam(no2 ~ s(heure, bs = \"cp\"), data = df, family = tw)\npreds <- data.frame(\n heure = 1:24\n)\nmodout <- predict(model, newdata = preds, type = \"link\", se.fit = TRUE)\npreds$yhat <- exp(modout$fit)\npreds$lower <- exp(modout$fit - 1.96*modout$se.fit)\npreds$upper <- exp(modout$fit + 1.96*modout$se.fit)\n\nsubpts <- df[sample(1:nrow(df), size = 1000, replace = FALSE),]\nsubpts$heure2 <- subpts$heure + runif(nrow(subpts), min = -0.5, max = +0.5)\n\ncent_line <- preds$yhat[[1]]\n\nggplot() + \n geom_point(mapping = aes(x = heure2, y = no2), size = 0.5, data = subpts, alpha = 0.5) +\n geom_ribbon(mapping = aes(x = heure, ymax = upper, ymin = lower), fill = \"grey\", alpha = 0.4, data = preds) +\n geom_line(mapping = aes(x = heure, y = yhat), color = \"blue\", linewidth = 1.1, data = preds) + \n geom_hline(yintercept = cent_line, color = \"red\", linetype = \"dashed\") +\n labs(x = \"moment de la journée\", y = \"concentration de NO2\") + \n scale_x_continuous(breaks = seq(4,20,4), labels = paste(seq(4,20,4),'h', sep='')) + \n xlim(1,24)\n\n```\n\n\n\n### Splines par groupe {#sec-1152}\n\nTel qu'abordé dans les chapitres précédents, il arrive régulièrement que les observations appartiennent à différents groupes. Dans ce cas de figure, nous pouvons être amenés à vérifier si la relation décrite par une *spline* est identique pour chacun des groupes d'observations. Il s'agit alors d'ajuster une *spline* différente par groupe. Dans l'exemple précédent, chaque valeur de NO~2~ a été mesurée par une station fixe de mesure spécifique. Compte tenu du fait que l'environnement autour de chaque station est particulier, nous pourrions s'attendre à ce que les valeurs de NO~2~ ne présentent pas exactement les mêmes patrons journaliers pour chaque station.\n\nÀ la @fig-gam14, il est possible de constater que le NO~2~ suit globalement le même patron temporel pour l'ensemble des stations à l'exception de trois d'entres-elles. Il s'agit en réalité de stations situées dans des secteurs ruraux de la région parisienne, et donc moins impactées par le trafic routier.\n\n\n```{r}\n#| label: fig-gam14\n#| echo: false\n#| fig-align: center\n#| fig-cap: Spline cyclique variant par groupe\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\nmodel <- gam(no2 ~ s(heure, bs = \"cp\", by = variable), data = df, family = gaussian)\npreds <- expand.grid(\n heure = 1:24,\n variable = unique(df$variable)\n)\n\nmodout <- predict(model, newdata = preds, type = \"link\", se.fit = TRUE)\npreds$yhat <- modout$fit\npreds$lower <- modout$fit - 1.96*modout$se.fit\npreds$upper <-modout$fit + 1.96*modout$se.fit\n\nsubpts <- df[sample(1:nrow(df), size = 1000, replace = FALSE),]\nsubpts$heure2 <- subpts$heure + runif(nrow(subpts), min = -0.5, max = +0.5)\n\ncent_line <- preds$yhat[[1]]\n\nggplot() + \n geom_point(mapping = aes(x = heure2, y = no2), size = 0.5, data = subpts, alpha = 0.5) +\n geom_ribbon(mapping = aes(x = heure, ymax = upper, ymin = lower, group = variable), fill = \"grey\", alpha = 0.4, data = preds) +\n geom_line(mapping = aes(x = heure, y = yhat, color = variable), size =0.7, data = preds) + \n labs(x = \"moment de la journée\", y = \"concentration de NO2\", color = \"station de mesure\") + \n scale_x_continuous(breaks = seq(4,20,4), labels = paste(seq(4,20,4),'h', sep='')) + \n xlim(1,24) + \n theme(legend.position = 'NONE')\n\n```\n\n\n### *Splines* multivariées et *splines* d'interaction {#sec-1153}\n\nJusqu'ici, nous n'avons considéré que des *splines* ne s'appliquant qu'à une seule variable indépendante; cependant, il est possible de construire des *splines* multivariées s'ajustant simultanément sur plusieurs variables indépendantes. L'objectif est alors de modéliser les potentielles interactions non linéaires entre les variables indépendantes combinées dans une même *spline*. Prenons un exemple concret, dans la section sur les modèles GLM, nous avons modélisé la couverture des aires de diffusion (AD) à Montréal par des îlots de chaleur. Parmi les variables indépendantes, nous avons notamment utilisé la distance au centre-ville ainsi que la part de la surface végétalisée des AD. Nous pourrions formuler l'hypothèse que ces deux variables influencent conjointement et de façon non linéaire la proportion de la surface d'îlot de chaleur dans chaque AD. Pour représenter une *spline* sur plusieurs dimensions, nous utilisons alors une carte de chaleur dont la couleur représente la valeur de la variable dépendante prédite en fonction des deux variables indépendantes.\n\nIl est important de distinguer la *spline* d'**interaction** et la *spline* **multivariée**. La première est utilisée lorsque les variables indépendantes introduites dans la *spline* ne sont pas exprimées sur la même échelle et n'évoluent pas conjointement. L'exemple donné ci-dessus avec les variables de végétation et de distance au centre-ville est un exemple de *spline* d'interaction, la première variable étant exprimée en pourcentage et l'autre en mètres. De plus, ces deux variables ne sont pas conjointes, mais bien distinctes l'une de l'autre. Un cas typique où une *spline* multivariée serait à privilégier est le cas de l'ajout des coordonnées spatiales dans le modèle. L'emplacement des AD est mesuré par deux variables (coordonnées spatiales *x* et *y*) toutes les deux exprimées en mètres évoluant conjointement, au sens où les coordonnées *x* n'interagissent pas avec les coordonnées *y*, mais forment à elles deux un espace propre. Au-delà de la problématique de l'échelle des données, il est important de retenir que les *splines* d'interaction tendent à être davantage pénalisées que les splines *multivariées*.\n\nLa *spline* d'interaction représentée à la @fig-gam15 indique que les AD avec la plus grande proportion de leur surface couverte par des îlots de chaleur sont situées à moins de 25 kilomètres du centre-ville, au-delà de cette distance, cette proportion chute en bas de 0,1, soit 10 % de la surface de l'AD. En revanche, à proximité du centre-ville (moins d'un kilomètre), même les AD disposant d'un fort pourcentage de surface végétalisée sont tout de même marquées par un fort pourcentage de surface couverte par des îlots de chaleur.\n\nLes *splines* bivariées sont fréquemment utilisées pour capturer un potentiel patron spatial dans les données. En effet, si nous disposons des coordonnées spatiales de chaque observation (*x, y*), il est possible d'ajuster une *spline* bivariée sur ces coordonnées, contrôlant ainsi l'effet de l'espace. \n\n```{r}\n#| label: fig-gam15\n#| echo: false\n#| fig-align: center\n#| fig-cap: Spline d'interaction bivariée\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\n\ndataset <- read.csv(\"data/glm/data_chaleur.csv\")\ndataset$prt_hot01 <- dataset$prt_hot/100\nmodel <- gam(prt_hot01 ~ te(prt_veg, dist_cntr), data = dataset, family = betar)\nvis.gam(model, plot.type = 'contour', type = 'response', main = '', xlab = 'Pourcentage de la surface végétalisée', ylab = 'Distance au centre-ville', too.far = 0.1, n.grid = 150)\n```\n\nIl n'y a pas de limite théorique au nombre de variables qui peuvent être ajoutées dans une *spline* d'interaction ou multivariée. Notez cependant que plus le nombre de dimensions augmente, plus la fonction à estimer est complexe et plus le volume de données nécessaire est grand et doit couvrir densément l'ensemble de l'espace d'échantillonnage multidimensionnel.\n\n## Mise en œuvre dans R {#sec-116}\n\nIl est possible d'ajuster des *splines* de régression dans n'importe quel *package* permettant d'ajuster des coefficients pour un modèle de régression. Il suffit de construire les bases des *splines* en amont à l'aide du *package* `splines2` et de les ajouter directement dans l'équation de régression. \nEn revanche, il est nécessaire d'utiliser des *packages* spécialisés pour ajuster des *splines* de lissage. Parmi ceux-ci, `mgcv` est probablement le plus populaire du fait de sa (très) grande flexibilité, suivi des *packages* `gamlss`, `gam` et `VGAM.` Nous comparons ici les deux approches, puis nous tentons d'améliorer le modèle que nous avons ajusté pour prédire le pourcentage de surface couverte par des îlots de chaleur dans les aires de diffusion de Montréal, dans une perspective d'équité environnementale. Pour rappel, la variable dépendante est exprimée en pourcentage et nous utilisons une distribution bêta pour la modéliser.\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(mgcv)\n# Chargement des données\ndataset <- read.csv(\"data/gam/data_chaleur.csv\", fileEncoding = \"utf8\")\n# Ajustement du modèle de base\nrefmodel <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n poly(prt_veg, degree = 2) + Arrond,\n data = dataset, family = betar(link = \"logit\"))\n```\n\nDans notre première analyse de ces données, nous avons ajusté une polynomiale d'ordre 2 pour représenter un potentiel effet non linéaire de la végétation sur les îlots de chaleur. Nous remplaçons à présent ce terme par une *spline* de régression en sélectionnant quatre nœuds.\n\n```{r}\n#| message: false\n#| warning: false\nlibrary(splines2)\n# Création des bases de la spline\nbasis <- bSpline(x = dataset$prt_veg, df =4, intercept = FALSE)\n# Ajouter les bases au DataFrame\nbasisdf <- as.data.frame(basis)\nnames(basisdf) <- paste('spline',1:ncol(basisdf), sep='')\ndataset <- cbind(dataset, basisdf)\n# Ajuster le modèle\nmodel0 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n spline1 + spline2 + spline3 + spline4 + Arrond,\n data = dataset, family = betar(link = \"logit\"))\n\n```\n\nNous pouvons à présent ajuster une *spline* de lissage et laisser `mgcv` déterminer son niveau de complexité.\n\n```{r}\n#| message: false\n#| warning: false\n# Ajustement du modèle avec une spline simple\nmodel1 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n s(prt_veg) + Arrond,\n data = dataset, family = betar(link = \"logit\"))\n```\n\nNotez ici que la syntaxe à employer est très simple, il suffit de spécifier `s(prt_veg)` pour indiquer à la fonction `gam` que vous souhaitez ajuster une *spline* pour la variable `prt_veg`. Nous pouvons à présent comparer l'ajustement des deux modèles en utilisant la mesure de l'AIC.\n\n```{r}\n#| message: false\n#| warning: false\n# Comparaison des AIC\nAIC(refmodel, model0, model1)\n```\n\nNous constatons que la valeur de l'AIC du second modèle est plus réduite, indiquant un meilleur ajustement du modèle avec une *spline* de régression. Notons cependant que la différence avec la *spline* de lissage est anecdotique (deux points de l'AIC) et que nous connaissions a priori le bon nombre de nœuds à utiliser. Pour des relations plus complexes, les *splines* de lissage ont tendance à nettement mieux performer. Voyons à présent comment représenter ces trois termes non linéaires.\n\n```{r}\n#| message: false\n#| warning: false\n#| label: fig-gam16\n#| fig-align: center\n#| fig-cap: Comparaison d'une spline et d'une polynomiale\n#| out-width: \"75%\"\n\n# Création d'un DataFrame de prédiction dans lequel seule\n# la variable prt_veg varie.\ndfpred <- data.frame(\n prt_veg = seq(min(dataset$prt_veg), max(dataset$prt_veg), 0.5),\n A65Pct = mean(dataset$A65Pct),\n A014Pct = mean(dataset$A014Pct),\n PopFRPct = mean(dataset$PopFRPct),\n PopMVPct = mean(dataset$PopMVPct),\n Arrond = \"Verdun\"\n)\n\n# Recréation des bases de la spline de régression\n# pour les nouvelles observations\nnvl_bases <- data.frame(predict(basis, newx = dfpred$prt_veg))\nnames(nvl_bases) <- paste('spline',1:ncol(basisdf), sep='')\ndfpred <- cbind(dfpred, nvl_bases)\n\n# Définition de la fonction inv.logit, soit l'inverse de la fonction \n# de lien du modèle pour retrouver les prédictions dans l'échelle \n# originales des données\ninv.logit <- function(x){exp(x)/(1+exp(x))}\n\n# Utilisation des deux modèles pour effectuer les prédictions\npredref <- predict(refmodel, newdata = dfpred, type = 'link', se.fit = TRUE)\npredmod0 <- predict(model0, newdata = dfpred, type = 'link', se.fit = TRUE)\npredmod1 <- predict(model1, newdata = dfpred, type = 'link', se.fit = TRUE)\n\n# Calcul de la valeur prédite et construction des intervalles de confiance\ndfpred$polypred <- inv.logit(predref$fit)\ndfpred$poly025 <- inv.logit(predref$fit - 1.96 * predref$se.fit)\ndfpred$poly975 <- inv.logit(predref$fit + 1.96 * predref$se.fit)\n\ndfpred$regsplinepred <- inv.logit(predmod0$fit)\ndfpred$regspline025 <- inv.logit(predmod0$fit - 1.96 * predmod0$se.fit)\ndfpred$regspline975 <- inv.logit(predmod0$fit + 1.96 * predmod0$se.fit)\n\ndfpred$splinepred <- inv.logit(predmod1$fit)\ndfpred$spline025 <- inv.logit(predmod1$fit - 1.96 * predmod1$se.fit)\ndfpred$spline975 <- inv.logit(predmod1$fit + 1.96 * predmod1$se.fit)\n\n# Créer un graphique pour afficher les résultats\nggplot(dfpred) + \n geom_ribbon(aes(x = prt_veg, ymin = poly025, ymax = poly975),\n alpha = 0.4, color = \"grey\") +\n geom_ribbon(aes(x = prt_veg, ymin = spline025, ymax = spline975),\n alpha = 0.4, color = \"grey\") +\n geom_ribbon(aes(x = prt_veg, ymin = regspline025, ymax = regspline975),\n alpha = 0.4, color = \"grey\") +\n geom_line(aes(y = polypred, x = prt_veg, color = \"polynomiale\"),\n linewidth = 1) + \n geom_line(aes(y = regsplinepred, x = prt_veg, color = \"spline de régression\"),\n linewidth = 1)+\n geom_line(aes(y = splinepred, x = prt_veg, color = \"spline de lissage\"),\n linewidth = 1)\n```\n\nNous constatons que les trois termes renvoient des prédictions très similaires et qu'une légère différence n'est observable que pour les secteurs avec les plus hauts niveaux de végétation (supérieurs à 75 %).\n\nJusqu'ici, nous utilisons l'arrondissement dans lequel est comprise chaque aire de diffusion comme une variable nominale afin de capturer la dimension spatiale du jeu de données. Puisque nous avons abordé la notion de *splines* bivariées, il serait certainement plus efficace d'en construire une à partir des coordonnées géographiques (*x*,*y*) des centroïdes des aires de diffusion. En effet, il est plus probable que la distribution des îlots de chaleur suive un patron spatial continu sur le territoire plutôt que les délimitations arbitraires des arrondissements.\n\n```{r}\n#| message: false\n#| warning: false\n# Ajustement du modèle avec une spline bivariée pour l'espace\nmodel2 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n s(prt_veg) + s(X,Y),\n data = dataset, family = betar(link = \"logit\"))\n```\n\nNotez ici que l'expression `s(X,Y)` permet de créer une *spline* bivariée à partir des coordonnées (*x, y*), soit deux colonnes présentes dans le jeu de données. Ces coordonnées sont exprimées toutes deux en mètres et n'interagissent pas ensemble au sens strict, nous devons donc ajuster une *spline* bivariée. Si vous avez besoin d'ajuster une *spline* d'interaction (notamment quand les variables sont dans des unités différentes), il est nécessaire d'utiliser une autre syntaxe `te(X,Y)` ou `t2(X,Y)` faisant appel à une structure mathématique légèrement différente, soit des *tensor product smooths*.\n\nPuisque notre modèle intègre deux *splines*, nous devons nous assurer que nous n'avons pas de problème de concurvité, ce que nous pouvons faire avec la fonction `concurvity` du *package* `mgcv`. \n\n```{r}\n#| message: false\n#| warning: false\nvalues <- concurvity(model2, full = FALSE)\n\n# Worst, estimation pessimiste de la concurvité\nround(values$worst,3)\n\n# Observed, estimation optimiste de la concurvité\nround(values$observed,3)\n\n# Estimate, estimation entre deux de la concurvité\nround(values$estimate,3)\n```\n\nNous pouvons ainsi constater des niveaux de concurvité tout à fait acceptables dans notre modèle. Des valeurs supérieures à 0,8 devraient être considérées comme alarmantes, surtout si elles sont reportées pour `observed` et `estimate`.\n\nVoyons désormais, le résumé d'un modèle GAM tel que présenté dans R.\n\n```{r}\n#| message: false\n#| warning: false\nsummary(model2)\n```\n\nLa première partie du résumé comprend les résultats pour les effets fixes et linéaires du modèle. Ils s'interprètent comme pour ceux d'un GLM classique. La seconde partie présente les résultats pour les termes non linéaires. La valeur de *p* permet de déterminer si la *spline* a ou non un effet différent de 0. Une valeur non significative indique que la *spline* ne contribue pas au modèle. Les colonnes *edf* et *Ref.df* indiquent la complexité de la *spline* et peuvent être considérées comme une approximation du nombre de nœuds. Dans notre cas, la *spline* spatiale (`s(X,Y)`) est environ 5 fois plus complexe que la *spline* ajustée pour la végétation (`s(prt_veg)`). Cela n'est pas surprenant puisque la dimension spatiale (*spline* bivariée) du phénomène est certainement plus complexe que l’effet de la végétation. Notez ici que des valeurs *edf* et *Ref.df* proches de 1 signaleraient que l'effet d’un prédicteur est essentiellement linéaire et qu'il n'est pas nécessaire de recourir à une *spline* pour cette variable.\n\nLa dernière partie du résumé comprend deux indicateurs de qualité d'ajustement, soit le R^2^ ajusté et la part de la déviance expliquée.\n\n```{r}\n#| message: false\n#| warning: false\nAIC(refmodel, model1, model2)\n```\n\nNous pouvons constater que le fait d'introduire la *spline* spatiale dans le modèle contribue à réduire encore la valeur de l'AIC, et donc à améliorer le modèle. À ce stade, nous pourrions tenter de forcer la *spline* à être plus complexe en augmentant le nombre de nœuds.\n\n```{r}\n#| message: false\n#| warning: false\n# Augmentation de la complexité de la spline spatiale\nmodel3 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n s(prt_veg) + s(X,Y,k = 40),\n data = dataset, family = betar(link = \"logit\"))\n\nAIC(refmodel, model1, model2, model3)\n```\n\nCela a pour effet d'améliorer de nouveau le modèle. Pour vérifier si l'augmentation du nombre nœuds est judicieuse, il est possible de représenter le résultat des deux *splines* précédentes. Pour ce faire, nous proposons de calculer les valeurs prédites de la *spline* pour chaque localisation dans notre terrain d'étude, en le découpant préalablement en pixels de 100 de côté. Pour cette prédiction, nous maintenons toutes les autres variables à leur moyenne respective afin d'évaluer uniquement l'effet de la *spline* spatiale.\n\n```{r}\n#| label: fig-gam17\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Comparaison de deux splines spatiales\n#| out-width: \"100%\"\nlibrary(viridis)\nlibrary(metR) # pour placer des étiquettes sur les isolignes\n\n# Création d'un DataFrame fictif pour les prédictions\ndfpred <- expand.grid(\n prt_veg =mean(dataset$prt_veg),\n A65Pct = mean(dataset$A65Pct),\n A014Pct = mean(dataset$A014Pct),\n PopFRPct = mean(dataset$PopFRPct),\n PopMVPct = mean(dataset$PopMVPct),\n X = seq(min(dataset$X), max(dataset$X),100),\n Y = seq(min(dataset$Y), max(dataset$Y),100)\n)\n\ndfpred$predicted1 <- predict(model2, newdata = dfpred, type = 'response')\ndfpred$predicted2 <- predict(model3, newdata = dfpred, type = 'response')\n\n# Centrage des prédictions\ndfpred$predicted1 <- dfpred$predicted1 - mean(dfpred$predicted1)\ndfpred$predicted2 <- dfpred$predicted2 - mean(dfpred$predicted2)\n\n# Représentation des splines\nplot1 <- ggplot(dfpred) + \n geom_raster(aes(x = X, y = Y, fill = predicted1)) + \n geom_point(aes(x = X, y = Y),\n size = 0.2, alpha = 0.4,\n color = \"black\", data = dataset)+\n geom_contour(aes(x = X, y = Y, z = predicted1), binwidth = 0.1, \n color = \"white\", linetype = 'dashed') + \n geom_text_contour(aes(x = X, y = Y, z = predicted1), \n color = \"white\", binwidth = 0.1)+\n scale_fill_viridis() +\n coord_cartesian() + \n theme(axis.title= element_blank(),\n axis.text = element_blank(),\n axis.ticks = element_blank()\n ) + \n labs(subtitle = \"spline de base\", fill = \"prédictions\")\n\nplot2 <- ggplot(dfpred) + \n geom_raster(aes(x = X, y = Y, fill = predicted2)) + \n geom_point(aes(x = X, y = Y),\n size = 0.2, alpha = 0.4,\n color = \"black\", data = dataset)+\n geom_contour(aes(x = X, y = Y, z = predicted2),\n binwidth = 0.1, color = \"white\", linetype = 'dashed') + \n geom_text_contour(aes(x = X, y = Y, z = predicted2), color = \"white\", binwidth = 0.1)+\n scale_fill_viridis() +\n coord_cartesian()+ \n theme(axis.title= element_blank(),\n axis.text = element_blank(),\n axis.ticks = element_blank()\n ) + \n labs(subtitle = \"spline plus complexe\", fill = \"prédictions\")\n\nggarrange(plot1, plot2, nrow = 1, ncol = 2, common.legend = TRUE, legend = 'bottom')\n```\n\nOr, il s'avère que les deux *splines* spatiales sont très similaires (@fig-gam17). Par conséquent, il est vraisemblablement plus pertinent de conserver la plus simple des deux. Notez que le Mont-Royal, compris dans le cercle central avec une isoligne à 0, est caractérisé par des valeurs plus faibles d'îlots de chaleur, alors que les quartiers centraux situés un peu plus au nord sont au contraire marqués par des pourcentages d'îlots de chaleur supérieurs de 20 points de pourcentage en moyenne.\n\n## GAMM {#sec-117}\n\nBien entendu, il est possible de combiner les modèles généralisés additifs (GAM) avec les modèles à effet mixtes (GLMM) abordés dans les sections précédentes. Ces modèles généralisés additifs à effets mixtes (GAMM) peuvent facilement être mis en œuvre avec `mgcv`.\n\n#### GAMM et interceptes aléatoires {#sec-1171}\n\nPour définir des constantes aléatoires, il suffit d'utiliser la notation `s(var, bs = 're')` avec `var` une variable nominale. Reprenons l'exemple précédent, mais avec cette fois-ci les arrondissements comme un intercepte aléatoire.\n\n```{r}\n#| message: false\n#| warning: false\ndataset$Arrond <- as.factor(dataset$Arrond)\nmodel4 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n s(prt_veg) + s(Arrond, bs = \"re\"),\n data = dataset, family = betar(link = \"logit\"))\n```\n\nL'enjeu est ensuite d'extraire la variance propre à cet effet aléatoire ainsi que les valeurs des interceptes pour chaque arrondissement.\n\n```{r}\n#| message: false\n#| warning: false\ngam.vcomp(model4)\n```\n\nNous constatons donc que l'écart-type de l'effet aléatoire des arrondissements est de 0,39, ce qui signifie que les effets de chaque arrondissement seront compris à 95 % entre -1,17 et 1,17 (`1.17 = 3*0.39`) sur l'échelle du prédicteur linéaire. En effet, rappelons que les effets aléatoires sont modélisés comme des distributions normales et que 95 % de la densité d'une distribution normale se situe entre -3 et +3 écarts-types. Pour extraire les interceptes spécifiques de chaque arrondissement, nous pouvons utiliser la fonction `get_random` du *package* `itsadug.`\n\n```{r}\n#| label: fig-randomconstGAM\n#| fig-cap: Constantes aléatoires pour les arrondissements\n#| message: false\n#| warning: false\nlibrary(itsadug)\nvalues <- get_random(model4)[[1]]\ndf <- data.frame(\n ri = as.numeric(values),\n arrond = names(values)\n)\n\nggplot(df) + \n geom_point(aes(x = ri, y = reorder(arrond, ri))) + \n geom_vline(xintercept = 0, color = \"red\") + \n labs(y = \"Arrondissement\", x = \"intercepte aléatoire\")\n```\n\nNous constatons ainsi, à la @fig-randomconstGAM, que pour une partie des arrondissements, la densité d'îlot de chaleur est systématiquement supérieure à la moyenne régionale représentée ici par la ligne rouge (0 = effet moyen pour tous les arrondissements). Il convient alors d’améliorer ce graphique en ajoutant le niveau d'incertitude associé à chaque intercepte. Pour ce faire, nous utilisons la fonction `extract_random_effects` du *package* `mixedup.` Notez que ce *package* n'est actuellement pas disponible sur CRAN et doit être téléchargé sur **github** avec la commande suivante :\n\n```{r}\n#| message: false\n#| warning: false\n#| eval: false\nremotes::install_github('m-clark/mixedup')\n```\n\nAvec la version 4.0.1 de R, nous avons rencontré des difficultés pour installer `mixedup`. Nous avons donc simplement récupéré le code source de la fonction et l'avons enregistré dans un fichier de code séparé que nous appelons ici.\n\n```{r}\n#| message: false\n#| warning: false\nsource(\"code_complementaire/gam_functions.R\")\n```\n\nNous pouvons ensuite procéder à l'extraction des effets aléatoires et les représenter à nouveau (@fig-randomconstGAM2).\n\n```{r}\n#| label: fig-randomconstGAM2\n#| message: false\n#| warning: false\n#| fig-cap: Constantes aléatoires pour les arrondissements avec intervalle de confiance\ndf_re <- extract_random_effects.gam(model4, re = \"Arrond\")\n\nggplot(df_re) + \n geom_errorbarh(aes(xmin = lower_2.5, xmax = upper_97.5, y = reorder(group, value))) +\n geom_point(aes(x = value, y = reorder(group, value))) + \n geom_vline(xintercept = 0, color = \"red\") + \n labs(y = \"Arrondissement\", x = \"Intercepte aléatoire\")\n```\n\nCela permet de distinguer quels écarts sont significativement différents de 0 au seuil de 95 %. À titre de rappel, pour être significatif à ce seuil, un intervalle représenté par une ligne noire horizontale ne doit pas intersecter la ligne rouge verticale. Puisque nous utilisons ici la distribution bêta et une fonction de lien logistique, nous devons utiliser des prédictions pour simplifier l'interprétation des coefficients. Nous fixons ici toutes les variables à leur moyenne respective, sauf l'arrondissement, et calculons les prédictions dans l'échelle originale (0 à 1).\n\n```{r}\n#| label: fig-randomconstGAM3\n#| message: false\n#| warning: false\n#| fig-cap: Prédictions pour les différents arrondissements pour une AD fictive moyenne\ndfpred <- data.frame(\n A65Pct = mean(dataset$A65Pct),\n A014Pct = mean(dataset$A014Pct),\n PopFRPct = mean(dataset$PopFRPct),\n PopMVPct = mean(dataset$PopMVPct),\n prt_veg = mean(dataset$prt_veg),\n Arrond = as.character(unique(dataset$Arrond))\n)\n\n# Calculer les prédictions pour le prédicteur linéaire\ndfpred$preds <- predict(model4, newdata = dfpred, type = \"link\")\n\n# Calculer l'intervalle de confiance en utilisant les valeurs\n# extraites avec extract_random_effects\ndfpred <- dfpred[order(dfpred$Arrond),]\ndf_re <- df_re[order(df_re$group),]\n\ndfpred$lower <- dfpred$preds - 1.96*df_re$se\ndfpred$upper <- dfpred$preds + 1.96*df_re$se\n\n# Il nous reste juste à reconvertir le tout dans l'unité d'origine\n# en utilisant l'inverse de la fonction logistique\ninv.logit <- function(x){exp(x)/(1+exp(x))}\n\ndfpred$lower <- inv.logit(dfpred$lower)\ndfpred$upper <- inv.logit(dfpred$upper)\ndfpred$preds <- inv.logit(dfpred$preds)\n\nggplot(dfpred) + \n geom_errorbarh(aes(xmin = lower, xmax = upper, y = reorder(Arrond, preds))) +\n geom_point(aes(x = preds, y = reorder(Arrond, preds))) + \n geom_vline(xintercept = mean(dfpred$preds), color = \"red\") + \n labs(y = \"Arrondissement\", x = \"intercepte aléatoire\")\n\n```\n\nNous constatons ainsi, à la @fig-randomconstGAM3, que pour une hypothétique aire de diffusion moyenne, la différence de densité d'îlot de chaleur peut être de 0,32 (32 % de la surface de l'AD) entre les arrondissements Verdun et Dollard-des-Ormeaux.\n\n#### GAMM et coefficients aléatoires {#sec-1172}\n\nEn plus des interceptes aléatoires, il est aussi possible de définir des coefficients aléatoires. Reprenons notre exemple et tentons de faire varier l'effet de la variable `PopFRPct` en fonction de l'arrondissement.\n\n```{r}\n#| message: false\n#| warning: false\nmodel5 <- gam(hot ~\n A65Pct + A014Pct + PopFRPct + PopMVPct +\n s(prt_veg) + s(Arrond, bs = \"re\") + \n s(PopFRPct, Arrond, bs = \"re\"),\n data = dataset, family = betar(link = \"logit\"))\n```\n\nNotez ici une distinction importante! Le modèle n'assume aucune corrélation entre les coefficients aléatoires pour la variable `PopFRPct` et pour les constantes aléatoires. Il est présumé que ces deux effets proviennent de deux distributions normales distinctes. En d'autres termes, le modèle ne dispose pas des paramètres nécessaires pour vérifier si les arrondissements avec les constantes les plus fortes (avec des densités supérieures d'îlot de chaleur) sont aussi des arrondissements dans lesquels l'effet de la variable `PopFRPct` est plus prononcé (et vice-versa). Pour plus d'informations sur cette distinction, référez-vous à la [section @sec-0924].\n\n```{r}\n#| message: false\n#| warning: false\nAIC(model4, model5)\n```\n\nCe dernier modèle présente une valeur de l'AIC plus faible et serait donc ainsi mieux ajusté que notre modèle avec seulement un intercepte aléatoire. Nous pouvons donc extraire les coefficients aléatoires et les représenter à la @fig-randomconstcoefGAM.\n\n```{r}\n#| label: fig-randomconstcoefGAM\n#| message: false\n#| warning: false\n#| fig-cap: Pentes et constantes aléatoires pour les arrondissements\ndf_re <- extract_random_effects.gam(model5)\ndf_re <- subset(df_re, df_re$effect == 'PopFRPct')\n\nggplot(df_re) + \n geom_errorbarh(aes(xmin = lower_2.5, xmax = upper_97.5, y = reorder(group, value))) +\n geom_point(aes(x = value, y = reorder(group, value))) + \n geom_vline(xintercept = 0, color = \"red\") + \n labs(y = \"Arrondissement\", x = \"coefficient aléatoire\")\n```\n\nNous constatons notamment que seuls trois arrondissements ont des coefficients aléatoires significativement différents de 0. Ainsi, pour les arrondissements Anjou et Plateau-Mont-Royal, les coefficients aléatoires sont respectivement de `r tofr(df_re[df_re$group == \"Anjou\",]$value[[1]])` et `r tofr(df_re[df_re$group == \"Le Plateau-Mont-Royal\",]$value[[1]])`, et viennent donc se retrancher à la valeur moyenne régionale de `r tofr(round(model5$coefficients[[4]],4))` qui atteint alors presque 0. Du point de vue de l'interprétation, nous pouvons en conclure que le groupe des personnes à faible revenu ne subit pas de surexposition aux îlots de chaleur à l'échelle des AD dans ces arrondissements.\n\nEn revanche, dans l'arrondissement Mercier-Hochelaga-Maisonneuve, la situation est à l'inverse plus systématiquement en défaveur des populations à faible revenu, avec une taille d'effet près de deux fois supérieure à la moyenne régionale. En effet, l'effet moyen régional (coefficient fixe) est de `r tofr(round(model5$coefficients[[4]],4))`, auquel vient s'ajouter l'effet spécifique (coefficient aléatoire) de Mercier-Hochelaga-Maisonneuve, soit `r tofr(df_re[df_re$group == \"Mercier-Hochelaga-Maisonneuve\",]$value[[1]])`, pour un effet total de `r tofr(df_re[df_re$group == \"Mercier-Hochelaga-Maisonneuve\",]$value[[1]] + round(model5$coefficients[[4]],4))`\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Des effets aléatoires plus complexes dans les GAMM**\n:::\n::: bloc_aller_loin-body\nIl est possible de spécifier des GAMM avec des effets aléatoires plus complexes autorisant, par exemple, des corrélations entre les différents effets / niveaux. Il faut pour cela utiliser la fonction `gamm` de `mgcv` ou la fonction `gamm4` du *package* `gamm4.` La première offre plus de flexibilité, mais la seconde est plus facile à utiliser et doit être privilégiée quand un modèle comporte un très grand nombre de groupes dans un effet aléatoire, ou lorsque la distribution du modèle n'est pas gaussienne. La fonction `gamm` permet d'ajuster des modèles non gaussiens, mais elle utilise une approche appelée PQL (*Penalized Quasi-Likelihood* en anglais) connue pour être moins stable et moins précise.\n\nCependant, dans l'exemple de cette section, nous utilisons un modèle GAMM avec une distribution bêta, ce qui n'est actuellement pas supporté par les fonctions `gamm` et `gamm4`. Pour un modèle GAMM plus complexe utilisant une distribution bêta, il est nécessaire d'utiliser le *package* `gamlss`, mais ce dernier utilise aussi une approche de type PQL. Nous montrons tout de même ici comment ajouter un modèle qui inclut une corrélation entre les deux effets aléatoires de l'exemple précédent. Notez ici que le terme `re` apparaissant dans la formule permet de spécifier un effet aléatoire en utilisant la syntaxe du *package* `nlme.` Plus spécifiquement, `gamlss` fait un pont avec `nlme` et utilise son algorithme d'ajustement au sein de ces propres routines. De même, le terme `pb` permet de spécifier une *spline* de lissage dans le même esprit que `mgcv.` Il est également possible d'utiliser le terme `ga` faisant le lien avec `mgcv` et de profiter de sa flexibilité dans `gamlss`.\n\n```{r}\n#| message: false\n#| warning: false\n#| results: hide\nlibrary(gamlss)\nlibrary(gamlss.add)\n\nmodel6 <- gamlss(hot ~\n pb(prt_veg) + \n re(fixed = ~ A65Pct + A014Pct + PopFRPct + PopMVPct, \n random = ~(1 + PopFRPct)|Arrond),\n data = dataset, family = BE(mu.link = \"logit\"))\n```\n\nNous pouvons ensuite accéder à la partie du modèle qui nous intéresse, soit celle concernant les effets aléatoires.\n\n```{r}\n#| message: false\n#| warning: false\nrandomPart <- model6$mu.coefSmo[[2]]\nprint(randomPart)\n```\n\n\nÀ lecture de la partie du résumé consacrée aux résultats pour les effets aléatoires, nous constatons que la corrélation entre les interceptes aléatoires et les coefficients aléatoires est de -0,65. Cela signifie que pour les arrondissements avec des interceptes élevés (plus grande proportion d'îlots de chaleur), l'effet de la variable `PopFRPct` tend à être plus faible. Autrement dit, dans les arrondissements avec beaucoup d'îlots de chaleur, les personnes à faible revenu ont tendance à être moins exposées, tel qu'illustré à la @fig-corrrandom).\n\n```{r}\n#| label: fig-corrrandom\n#| fig-cap: Relation entre les effets aléatoires des arrondissements et la variable population à faible revenu\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\ndf <- ranef(randomPart)\ndf$arrond <- rownames(df)\nnames(df) <- c('Intercept', 'PopFRPct', 'Arrondissement')\n\nggplot(df) + \n geom_hline(yintercept = 0, color = \"red\") +\n geom_vline(xintercept = 0, color = \"red\") +\n geom_point(aes(x = Intercept, y = PopFRPct))\n```\n:::\n:::\n\n## Quiz de révision du chapitre {#sec-118}\n\n```{r}\n#| label: quizGAM\n#| echo: false\n#| warning: false\n#| results: asis\nsource(\"code_complementaire/QuizzFunctions.R\")\nquizz_gam <- quizz(\"quiz/Chapitre11-GAM.yml\", \"quizz_gam\")\nrender_quizz(quizz_gam)\n```\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"11-GAM.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/12-AnalysesFactorielles.qmd.json b/.quarto/idx/12-AnalysesFactorielles.qmd.json new file mode 100644 index 0000000..5644f4e --- /dev/null +++ b/.quarto/idx/12-AnalysesFactorielles.qmd.json @@ -0,0 +1 @@ +{"title":"Méthodes factorielles","markdown":{"headingText":"Méthodes factorielles","headingAttr":{"id":"sec-chap12","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans le cadre de ce chapitre, nous présentons les trois méthodes factorielles les plus utilisées en sciences sociales : l'analyse en composantes principales (ACP, [section @sec-122]), l'analyse factorielle des correspondances (AFC, [section @sec-123]) et l'analyse factorielle des correspondances multiples (ACM, [section @sec-124]). Ces méthodes, qui permettent d'explorer et de synthétiser l'information de différents tableaux de données, relèvent de la statistique exploratoire multidimensionnelle.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2`, le seul, l'unique!\n - `ggpubr` pour combiner des graphiques.\n* Pour les analyses factorielles :\n - `FactoMineR` pour réaliser une ACP, une AFC et une ACM.\n - `factoextra` pour réaliser des graphiques à partir des résultats d'une analyse factorielle.\n - `explor` pour les résultats d'une ACP, d'une AFC ou d'une ACM avec une interface Web interactive.\n* Autres *packages* :\n - `geocmeans` pour un jeu de données utilisé pour calculer une ACP.\n - `ggplot2`, `ggpubr`, `stringr` et `corrplot` pour réaliser des graphiques personnalisés sur les résultats d'une analyse factorielle.\n - `tmap` et `RColorBrewer` pour cartographier les coordonnées factorielles.\n - `Hmisc` pour l'obtention d'une matrice de corrélation.\n:::\n:::\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Réduction de données et identification de variables latentes**\n:::\n::: bloc_objectif-body\nLes méthodes factorielles sont souvent dénommées des **méthodes de réduction de données**, en raison de leur objectif principal : résumer l'information d'un tableau en quelques nouvelles variables synthétiques (@fig-AnalysesFactoriellesFig). Ainsi, elles permettent de réduire l'information d'un tableau volumineux — comprenant par exemple 1000 observations et 100 variables — en *p* nouvelles variables (par exemple cinq avec toujours 1000 observations) résumant *X* % de l'information contenue dans le tableau initial. Lebart et al. [-@lebart1995statistique, p.13] proposent une formulation plus mathématique : ils signalent qu'avec les méthodes factorielles, « on cherche à réduire les dimensions du tableau de données en représentant les associations entre individus et entre variables dans des espaces de faibles dimensions ».\n\n![Principe de base des analyses factorielles](images/Chap12/AnalysesFactorielles.png){#fig-AnalysesFactoriellesFig width=\"40%\" fig-align=\"center\"}\n\n\nCes nouvelles variables synthétiques peuvent être considérées comme des **variables latentes** puisqu’elles ne sont pas directement observées; elles sont plutôt produites par la méthode factorielle utilisée afin de résumer les relations/associations entre plusieurs variables mesurées initialement.\n:::\n:::\n\n## Aperçu des méthodes factorielles {#sec-121}\n\n### Méthodes factorielles et types de données {#sec-1211}\n\nEn analyse factorielle, la nature même des données du tableau à traiter détermine la méthode à employer : l’analyse en composantes principales (ACP) est adaptée aux tableaux avec des variables continues (idéalement normalement distribuées), l’analyse factorielle des correspondances (AFC) s’applique à des tableaux de contingence tandis que l’analyse des correspondances multiples (ACM) permet de résumer des tableaux avec des données qualitatives (issues d'un sondage par exemple) (@tbl-typesanalysesfactorielles). Sachez toutefois qu'il existe d'autres méthodes factorielles qui ne sont pas abordées dans ce chapitre, notamment : l'analyse factorielle de données mixtes (AFDM) permettant d'explorer des tableaux avec à la fois des variables continues et des variables qualitatives et l'analyse factorielle multiple hiérarchique (AFMH) permettant de traiter des tableaux avec une structure hiérarchique. Pour s'initier à ces deux autres méthodes factorielles plus récentes, consultez notamment l'excellent ouvrage de Jérôme Pagès [-@pages2013analyse].\n\n```{r}\n#| label: tbl-typesanalysesfactorielles\n#| tbl-cap: Trois principales méthodes factorielles\n#| echo: false\n#| message: false\n#| warning: false\n\ntypesaf <- data.frame(Metho = c(\"Analyse en composantes principales\",\n \"Analyse factorielle des correspondances\", \n \"Analyse factorielle des correspondances multiples\"), \n Abr = c(\"ACP\", \"AFC\", \"ACM\"),\n type = c(\"Variables continues\", \"Tableau de contingence\", \"Variables qualitatives\"),\n dist = c(\"Distance euclidienne\", \"Distance du khi-deux\", \"Distance du khi-deux\")\n )\noptions(knitr.kable.NA = \"\")\nknitr::kable(typesaf,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Méthode factorielle\" , \"Abr.\" , \"Type de données\", \"Type de distance\"),\n align= c(\"l\", \"l\", \"l\", \"l\"),\n )\n```\n\n### Bref historique des méthodes factorielles {#sec-1212}\n\nIl existe une longue tradition de l'utilisation des méthodes factorielles dans le monde universitaire francophone puisque plusieurs d'entre elles ont été proposées par des statisticiens et des statisticiennes francophones à partir des années 1960. L’analyse en composantes principales (ACP) a été proposée dès les années 1930 par le statisticien américain Harold Hotelling [-@hotelling1933analysis]. En revanche, l’analyse des correspondances (AFC) et son extension, l’analyse des correspondances multiples (ACM), ont été proposées par le statisticien français Jean-Paul Benzécri [-@benzecri1973analyse], tandis que l’analyse factorielle de données mixtes (AFDM) a été proposée par Brigitte Escofier et Jérôme Pagès [@escofier1979traitement; @pages2002analyse].\n\nAinsi, plusieurs ouvrages de statistique sur les méthodes factorielles, désormais classiques, ont été publiés en français [@benzecri1973analyse; @escofier1998analyses; @lebart1995statistique; @pages2013analyse]. Ils méritent grandement d'être consultés, notamment pour mieux comprendre les formulations mathématiques (matricielles et géométriques) de ces méthodes. À cela s'ajoutent plusieurs ouvrages visant à « vulgariser ces méthodes » en sciences sociales; c'est notamment le cas de l'excellent ouvrage de Léna Sanders [-@sanders1989analyse] en géographie.\n\n\n## Analyses en composantes principales (ACP) {#sec-122}\n\nD'emblée, notez qu'il existe deux types d'analyse en composantes principales (ACP) (*Principal Component Analysis, PCA* en anglais) : \n\n- **l'ACP non normée** dans laquelle les variables quantitatives du tableau sont uniquement centrées (moyenne = 0).\n\n- **l'ACP normée** dans laquelle les variables quantitatives du tableau sont préalablement centrées réduites (moyenne = 0 et variance = 1; [section @sec-02552]).\n\nPuisque les variables d'un tableau sont souvent exprimées dans des unités de mesure différentes ou avec des ordres de grandeur différents (intervalles et écarts-types bien différents), l'utilisation de l'ACP normée est bien plus courante. Elle est d'ailleurs l'option par défaut dans les fonctions R permettant de calculer une ACP. Par conséquent, nous détaillons dans cette section uniquement l'ACP normée.\n\nAutrement dit, le recours à une ACP non normée est plus rare et s'applique uniquement à la situation suivante : toutes les variables du tableau sont mesurées dans la même unité (par exemple, en pourcentage); il pourrait être ainsi judicieux de conserver leurs variances respectives.\n\n### Recherche d'une simplification {#sec-1221}\n\nL’ACP permet d'explorer et de résumer un tableau constitué uniquement de variables quantitatives (@fig-AnalysesFactoriellesTabACPFig), et ce, de trois façons : 1) en montrant les ressemblances entre les individus (observations), 2) en révélant les liaisons entre les variables quantitatives et 3) en résumant l’ensemble des variables du tableau par des variables synthétiques nommées composantes principales.\n\n\n![Tableau pour une ACP](images/Chap12/AnalysesFactoriellesTabACP.png){#fig-AnalysesFactoriellesTabACPFig width=\"60%\" fig-align=\"center\"}\n\n**Ressemblance entre les individus**. Concrètement, deux individus se ressemblent si leurs valeurs respectives pour les *p* variables du tableau sont similaires. Cette proximité/ressemblance est évaluée à partir de la distance euclidienne (@eq-ACPdistEuc). La notion de distance fait l'objet d'une section à part entière ([section @sec-1321]) que vous pouvez consulter dès à présent si elle ne vous est pas familière.\n\n$$\nd^2(a,b) = \\sum_{j=1}^p(x_{aj}-x_{bj})^2\n$$ {#eq-ACPdistEuc}\n\n\nPrenons un exemple fictif avec trois individus (*i*, *j* et *k*) ayant des valeurs pour trois variables préalablement centrées réduites (V1 à V3) (@tbl-distanceACPindi). La proximité entre les paires de points est évaluée comme suit : \n\n$$d^2(i,j)=(-\\mbox{1,15}-\\mbox{0,49})^2+(-\\mbox{1,15}-\\mbox{0,58})^2+(\\mbox{0,83}+\\mbox{1,11})^2=\\mbox{9,44}$$\n$$d^2(i,k)=(-\\mbox{1,15}+\\mbox{0,66})^2+(-\\mbox{1,15}-\\mbox{0,58})^2+(\\mbox{0,83}-\\mbox{0,28})^2=\\mbox{5,98}$$\n\n$$d^2(j,k)= (\\mbox{0,49}+\\mbox{0,66})^2+(\\mbox{0,58}-\\mbox{0,58})^2+(-\\mbox{1,11}-\\mbox{0,28})^2=\\mbox{1,97}$$\n\nNous pouvons en conclure que *i* est plus proche de *k* que de *j*, mais aussi que la paire de points les plus proches est (*i*,*k*). En d'autres termes, les deux observations *i* et *k* sont les plus similaires du jeu de données selon la distance euclidienne.\n\n```{r}\n#| label: tbl-distanceACPindi\n#| tbl-cap: Données fictives\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(kableExtra)\ndf1 <- data.frame(Ind=c(\"i\", \"j\", \"k\"),\n V1=c(100,150,155),\n V2=c(20,22,22),\n V3=c(25,18,23))\n\ndf1$V1 <- round(scale(df1$V1),2)\ndf1$V2 <- round(scale(df1$V2),2)\ndf1$V3 <- round(scale(df1$V3),2)\n\noptions(knitr.kable.NA = \"\")\nmy_table <- knitr::kable(df1,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n row.names = FALSE,\n col.names = c(\"Individu\" , \"V1\" , \"V2\", \"V3\"),\n align = c(\"c\", \"c\", \"c\", \"c\")\n )\nadd_header_above(my_table, c(\" \" = 1, \"Variables centrées réduites\" = 3))\n```\n\n\n**Liaisons entre les variables**. Dans une ACP normée, les liaisons entre les variables deux à deux sont évaluées avec le coefficient de corrélation ([section @sec-0431]), soit la moyenne du produit des deux variables centrées réduites (@eq-ACPcor). Notez que dans une ACP non normée, plus rarement utilisée, les liaisons sont évaluées avec la covariance puisque les variables sont uniquement centrées (@eq-ACPcov).\n\n\n$$\nr_{xy} = \\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})(y_{i}-\\bar{y})}{n\\sqrt{\\sum_{i=1}^n(x_i - \\bar{x})^2(y_i - \\bar{y})^2}}=\\sum_{i=1}^n\\frac{Zx_iZy_i}{n}\n$$ {#eq-ACPcor}\n\n\n$$\ncov(x,y) = \\frac{\\sum_{i=1}^n (x_{i}-\\bar{x})(y_{i}-\\bar{y})}{n}\n$$ {#eq-ACPcov}\n\n\n**Composantes principales**. Au [chapitre @sec-chap04], nous avons abordé deux méthodes pour identifier des relations linéaires entre des variables continues normalement distribuées : \n\n* la corrélation de Pearson ([section @sec-043]), qu'il est possible d'illustrer graphiquement à partir d'un nuage de points;\n\n* la régression linéaire simple ([section @sec-044]), permettant de résumer la relation linéaire entre deux variables avec une droite de régression de type $Y=a+bX$. \n\nBrièvement, plus deux variables sont corrélées (positivement ou négativement), plus le nuage de points qu'elles forment est allongé et plus les points sont proches de la droite de régression (@fig-liaisons2Vars, partie **a**). À l'inverse, plus la liaison entre les deux variables normalement distribuées est faible, plus le nuage prend la forme d'un cercle et plus les points du nuage sont éloignés de la droite de régression (@fig-liaisons2Vars, partie **b**). Puisqu'en ACP normée, les variables sont centrées réduites, le centre de gravité du nuage de points est (*x* = 0, *y* = 0) et il est toujours traversé par la droite de régression. Finalement, nous avons vu que la méthode des moindres carrés ordinaires (MCO) permet de déterminer cette droite en minimisant les distances entre les valeurs observées et celles projetées orthogonalement sur cette droite (valeurs prédites). Dans le cas de deux variables uniquement, l'axe factoriel principal/la composante principale est donc la droite qui résume le mieux la liaison entre les deux variables (en rouge). L'axe 2 représente la seconde plus importante composante (axe, dimension) et il est orthogonal (perpendiculaire) au premier axe (en bleu).\n\n\n![Corrélation, allongement du nuage de points et axes factoriels](images/Chap12/bivariePlanFacto.png){#fig-liaisons2Vars width=\"100%\" fig-align=\"center\"}\n\n\n\n```{r}\n#| echo: false\n# library(\"MASS\")\n# library(\"ggplot2\")\n# library(\"ggpubr\")\n# library(\"FactoMineR\")\n# N <- 500 # nombre d'observations\n# moy_x <- 50 # moyenne de x\n# moy_y <- 40 # moyenne de y\n# sd_x <- 10 # écart-type de x\n# sd_y <- 8 # écart-type de y\n# rxy <- c(.90,-.85,0.01) # corrélation entre X et Y\n# # Matrice de covariance\n# cov1 <- matrix(c(sd_x^2, rxy[1]*sd_x*sd_y, rxy[1]*sd_x*sd_y, sd_y^2), nrow = 2)\n# cov2 <- matrix(c(sd_x^2, rxy[2]*sd_x*sd_y, rxy[2]*sd_x*sd_y, sd_y^2), nrow = 2) \n# cov3 <- matrix(c(sd_x^2, rxy[3]*sd_x*sd_y, rxy[3]*sd_x*sd_y, sd_y^2), nrow = 2) \n# data1 <- as.data.frame(mvrnorm(N, c(moy_x, moy_y), cov1))\n# data2 <- as.data.frame(mvrnorm(N, c(moy_x, moy_y), cov2))\n# data3 <- as.data.frame(mvrnorm(N, c(moy_x, moy_y), cov3))\n# data1$V1 <- scale(data1$V1)\n# data1$V2 <- scale(data1$V2)\n# data2$V1 <- scale(data2$V1)\n# data2$V2 <- scale(data2$V2)\n# data3$V1 <- scale(data3$V1)\n# data3$V2 <- scale(data3$V2)\n# cor1 <- round(cor(data1)[1,2],3)\n# cor2 <- round(cor(data2)[1,2],3)\n# cor3 <- round(cor(data3)[1,2],3)\n# \n# lm1 <- lm(V1 ~ V2, data = data1)\n# coef1 <- round(lm1$coefficients,3)[2]\n# y1 <-lm1$coefficients[1]+(lm1$coefficients[2]*3)\n# y2 <-lm1$coefficients[1]+(lm1$coefficients[2]*-3)\n# plot1 <- ggplot(data1, aes(x = V1, y = V2))+\n# xlim(-3,3)+\n# ylim(-3,3)+\n# geom_point(size = 1, color = \"steelblue\")+\n# ggtitle(\"a. Forte relation linéaire positive\", subtitle = paste0(\"Corrélation = \", tofr(cor1)))+\n# geom_hline(yintercept=0, linewidth = .2, color = \"black\")+\n# geom_vline(xintercept = 0, linewidth = .2, color = \"black\")+\n# xlab(\"Variable 1\")+ylab(\"Variable 2\")+\n# stat_ellipse( size = 1, color = \"black\")+\n# annotate(geom = \"text\", x = 3, y = 3, label = \"Axe 1\", color = \"red\", hjust = 1, size = 5)+\n# annotate(geom = \"text\", x = -2.5, y = 3, label = \"Axe 2\", color = \"steelblue\", hjust = 0, size = 5)+\n# geom_segment(aes(x = 3, y = y1, xend = -3, yend = y2), size = 1, color = \"red\")+\n# geom_segment(aes(x = -y1, y = 3, xend = -y2, yend = -3), size = 1, color = \"steelblue\")+\n# coord_fixed()\n# plot1\n# \n# lm3 <- lm(V1 ~ V2, data = data3)\n# coef3 <- round(lm3$coefficients,3)[2]\n# y1 <-lm3$coefficients[1]+(lm3$coefficients[2]*3)\n# y2 <-lm3$coefficients[1]+(lm3$coefficients[2]*-3)\n# plot3 <- ggplot(data3, aes(x = V1, y = V2))+\n# xlim(-3,3)+\n# ylim(-3,3)+\n# geom_point(size = 1, color = \"steelblue\")+\n# ggtitle(\"b. Absence de relation linéaire\", subtitle = paste0(\"Corrélation = \", tofr(cor3)))+\n# xlab(\"Variable 1\")+ylab(\"Variable 2\")+\n# geom_hline(yintercept=0, linewidth = .2, color = \"black\")+\n# geom_vline(xintercept = 0, linewidth = .2, color = \"black\")+\n# stat_ellipse( size = 1, color = \"black\")+\n# annotate(geom = \"text\", x = 3, y = -.2, label = \"Axe 1\", color = \"red\", hjust = 1, size = 5)+\n# annotate(geom = \"text\", x = .2, y = 2.8, label = \"Axe 2\", color = \"blue\", hjust = 0, size = 5)+\n# geom_segment(aes(x = 3, y = y1, xend = -3, yend = y2), size = 1, color = \"red\")+\n# geom_segment(aes(x = -y1, y = 3, xend = -y2, yend = -3), size = 1, color = \"blue\")+\n# coord_fixed()\n# plot3\n \n```\n\nImaginez maintenant trois variables pour lesquelles vous désirez identifier un axe, une droite qui résume le mieux les liaisons entre elles. Visuellement, vous passez d'un nuage de points en deux dimensions (2D) à un nuage en dimensions (3D). Si les corrélations entre les trois variables sont très faibles, alors le nuage prend la forme d'un ballon de soccer (football en Europe). Par contre, plus ces liaisons sont fortes, plus la forme est allongée comme un ballon de rugby et plus les points sont proches de l'axe traversant le ballon.\n\nAjouter une autre variable revient alors à ajouter une quatrième dimension qu'il est impossible de visualiser, même pour les plus fervents adaptes de science-fiction. Pourtant, le problème reste le même : identifier, dans un plan en *p* dimensions (variables), les axes factoriels – les composantes principales – qui concourent le plus à résumer les liaisons entre les variables continues préalablement centrées réduites, et ce, en utilisant la méthode des moindres carrés ordinaires.\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Composantes principales et axes factoriels**\n:::\n::: bloc_attention-body\nLes termes **composantes principales** et **axes factoriels** sont des synonymes employés pour référer aux nouvelles variables synthétiques produites par l'ACP et résumant l'information du tableau initial.\n:::\n:::\n\n### Aides à l'interprétation {#sec-1222}\n\nPour illustrer les aides à l'interprétation de l'ACP, nous utilisons un jeu de données spatiales tiré d'un article sur l'agglomération lyonnaise en France [@2021_4]. Ce jeu de données comprend dix variables, dont quatre environnementales (EN) et six socioéconomiques (SE), pour les îlots regroupés pour l'information statistique (IRIS) de l'agglomération lyonnaise (@tbl-dataacp et @fig-datacartoacp). Sur ces dix variables, nous calculons une **ACP normée**.\n\n```{r}\n#| label: tbl-dataacp\n#| tbl-cap: Statistiques descriptives pour le jeu de données utilisé pour l'ACP\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(geocmeans)\nlibrary(sf)\n\ndata(LyonIris)\nData <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\",\n \"Pct0_14\" , \"Pct_65\" , \"Pct_Img\",\n \"TxChom1564\" , \"Pct_brevet\" , \"NivVieMed\")])\n\nintitule <- c(\"Bruit routier (Lden dB(A))\",\n \"Dioxyde d'azote (ug/m^3^)\",\n \"Particules fines (PM$_{2,5}$)\",\n \"Canopée (%)\",\n \"Moins de 15 ans (%)\",\n \"65 ans et plus (%)\",\n \"Immigrants (%)\",\n \"Taux de chômage\",\n \"Personnes à faible scolarité (%)\",\n \"Médiane du niveau de vie (Euros)\" )\n\nstats <- data.frame(variable = names(Data),\n nom = intitule,\n type = c(\"EN\" , \"EN\" , \"EN\" , \"EN\" , \"SE\" , \"SE\" , \"SE\" , \"SE\" , \"SE\" , \"SE\"),\n moy = round(sapply(Data, mean), 2),\n et = round(sapply(Data, sd), 2), \n minimum = round(sapply(Data, min), 2), \n maximum = round(sapply(Data, max), 2)\n )\noptions(knitr.kable.NA = \"\")\nknitr::kable(stats,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t digits = 1,\n col.names = c(\"Nom\" , \"Intitulé\" , \"Type\" , \"Moy.\", \"E.-T.\", \"Min.\", \"Max.\"),\n align= c(\"l\" , \"l\", \"c\" , \"r\", \"r\", \"r\", \"r\"),\n )\n```\n\n\n![Cartographie des dix variables utilisées pour l'ACP](images/Chap12/Figure3Data.png){#fig-datacartoacp width=\"100%\" fig-align=\"center\"}\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Trois étapes pour bien analyser une ACP et comprendre la signification des axes factoriels**\n:::\n::: bloc_objectif-body\n1. Interprétation des résultats des valeurs propres pour identifier le nombre d'axes (de composantes principales) à retenir. L'enjeu est de garder un nombre d'axes limité qui résume le mieux le tableau initial (réduction des données).\n\n2. Analyse des résultats pour les variables (coordonnées factorielles, cosinus carrés et contributions sur les axes retenus).\n\n3. Analyse des résultats pour les individus (coordonnées factorielles, cosinus carrés et contributions sur les axes retenus).\n\nLes deux dernières étapes permettent de comprendre la signification des axes retenus et de les qualifier. Cette étape d'interprétation est essentielle en sciences sociales. En effet, nous avons vu dans l'introduction du chapitre que les méthodes factorielles permettent de résumer l'information d'un tableau en quelques nouvelles variables synthétiques, souvent considérées comme des variables latentes dans le jeu de données. Il convient alors de bien comprendre ces variables synthétiques (latentes), si nous souhaitons les utiliser dans une autre analyse subséquente (par exemple, les introduire dans une régression).\n:::\n:::\n\n#### Résultats de l'ACP pour les valeurs propres {#sec-12221}\n\nÀ titre de rappel, une ACP normée est réalisée sur des variables préalablement centrées réduites (@eq-scorezacpnormee), ce qui signifie que pour chaque variable :\n\n- Nous soustrayons à chaque valeur la moyenne de la variable correspondante (centrage); la moyenne est donc égale à 0.\n- Nous divisons cette différence par l’écart-type de la variable correspondante (réduction); la variance est égale à 1.\n\t\n$$\nz= \\frac{x_i-\\mu}{\\sigma}\n$$ {#eq-scorezacpnormee}\n\n\t\nPar conséquent, la variance totale (ou inertie totale) d’un tableau sur lequel est calculée une ACP normée est égale au nombre de variables qu'il comprend. Puisque nous l'appliquons ici à dix variables, la variance totale du tableau à réduire – c'est-à-dire à résumer en *K* nouvelles variables synthétiques, composantes principales, axes factoriels – est donc égale à 10. Trois mesures reportées au @tbl-dataacpValeurPropres permettent d'analyser les valeurs propres : \n\n- $\\mbox{VP}_k$, la valeur propre (*eigenvalue* en anglais) de l'axe *k*, c'est-à-dire la quantité de variance du tableau initial résumé par l'axe.\n\n- $\\mbox{VP}_k / \\mbox{P}$ avec *P* étant le nombre de variables que comprend le tableau initial. Cette mesure représente ainsi le pourcentage de la variance totale du tableau résumé par l’axe *k*; autrement dit, la quantité d’informations du tableau initial résumée par l’axe, la composante principale *k*. Cela nous permet ainsi d’évaluer le pouvoir explicatif de l’axe.\n\n- Le pourcentage cumulé pour les axes.\n\n```{r}\n#| label: tbl-dataacpValeurPropres\n#| tbl-cap: Résultats de l'ACP pour les valeurs propres\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(FactoMineR)\n\n# Calcul de l'ACP\nres.acp <- PCA(Data, ncp=5, scale.unit = TRUE, graph = FALSE)\n\n# Construction d'un DataFrame pour les valeurs propres\ndfACPvp <- data.frame(res.acp$eig)\nnames(dfACPvp) <- c(\"VP\" , \"VP_pct\" , \"VP_cumupct\")\ndfACPvp$Composante <- factor(1:nrow(dfACPvp), levels = rev(1:nrow(dfACPvp)))\ndfACPvp <- dfACPvp[, c(4,1:3)]\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(dfACPvp,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t digits = 3,\n col.names = c(\"Composante\" , \"Valeur propre\" , \"Pourcentage\", \"Pourc. cumulé\"),\n align= c(\"r\", \"r\", \"r\", \"r\")\n )\n```\n\nAvant d'analyser en détail le @tbl-dataacpValeurPropres, notez que la somme des valeurs propres de toutes les composantes de l'ACP est toujours égale au nombre de variables du tableau initial. Aussi, la quantité de variance expliquée (les valeurs propres) décroît de la composante 1 à la composante *K*.\n\n**Combien d'axes d'une ACP faut-il retenir?** Pour répondre à cette question, deux approches sont possibles :\n\n- **Approche statistique** (avec le critère de Kaiser [-@kaiser1960application]). Nous retenons uniquement les composantes qui présentent une valeur propre supérieure à 1. Rappelez-vous qu'en ACP normée, les variables sont préalablement centrées réduites, et donc que leur variance respective est égale à 1. Par conséquent, une composante ayant une valeur propre inférieure à 1 a un pouvoir explicatif inférieur à celui d'une variable. À la lecture du tableau, nous retenons les trois premières composantes si nous appliquons ce critère.\n\n- **Approche empirique** basée sur la lecture des pourcentages et des pourcentages cumulés. Nous pouvons retenir uniquement les deux premières composantes. En effet, ces deux premiers facteurs résument près des deux tiers de la variance totale du tableau (63,02 %). Cela démontre bien que l'ACP, comme les autres méthodes factorielles, est bien une méthode de réduction de données puisque nous résumons dix variables avec deux nouvelles variables synthétiques (axes, composantes principales). Pour faciliter le choix du nombre d'axes, il est fortement conseillé de construire des histogrammes à partir des valeurs propres, des pourcentages et des pourcentages cumulés (@fig-acpgraphvp). Or, à la lecture de ces graphiques, nous constatons que la variance expliquée chute drastiquement après les deux premières composantes. Par conséquent, nous pouvons retenir uniquement les deux premiers axes.\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Lecture du diagramme des valeurs propres** \n:::\n::: bloc_astuce-body\nPlus les variables incluses dans l'ACP sont corrélées entre elles, plus l'ACP est intéressante : plus les valeurs propres des premiers axes sont fortes et plus il y a des sauts importants dans le diagramme des valeurs propres. À l'inverse, lorsque les variables incluses dans l'ACP sont peu corrélées entre elles, il n'y a pas de sauts importants dans l'histogramme, autrement dit les valeurs propres sont uniformément décroissantes.\n:::\n:::\n\n```{r}\n#| label: fig-acpgraphvp\n#| echo: false\n#| fig-align: center\n#| fig-cap: Graphiques personnalisés pour les valeurs propres pour l'ACP\n#| out-width: \"75%\"\nlibrary(ggplot2)\nlibrary(ggpubr)\nlibrary(stringr)\n\ntofr <- function(float){\n return(gsub(\".\" , \",\", as.character(float), fixed = TRUE, useBytes = TRUE))\n}\n\ndfACPvp <- data.frame(res.acp$eig)\nnames(dfACPvp) <- c(\"VP\" , \"VP_pct\" , \"VP_cumupct\")\ndfACPvp$Composante <- factor(1:nrow(dfACPvp), levels = rev(1:nrow(dfACPvp)))\n\ncouleursAxes <- c(\"steelblue\" , \"skyblue2\")\nvpsup1 <- tofr(round(sum(subset(dfACPvp, VP >= 1)$VP),2))\nvpsup1cumul <- tofr(round(sum(subset(dfACPvp, VP >= 1)$VP_pct),2))\n\nplotVP1 <- ggplot(dfACPvp, aes(x = VP, y = Composante, fill = VP<1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 1, linetype = \"dashed\", color = \"azure4\", linewidth = 1)+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n labs(x = \"Valeur propre\", y = \"Composante principale\")\n\nplotVP2 <- ggplot(dfACPvp, aes(x = VP_pct, y = Composante, fill = VP<1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n theme(legend.position = \"none\")+\n labs(x = \"Variance expliquée (%)\", y = \"\")\n\nplotVP3 <- ggplot(dfACPvp, aes(x = VP_cumupct, y = Composante, fill = VP<1, group=1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n geom_line(colour = \"brown\", linetype = \"solid\", linewidth = .8) +\n geom_point(size=3, shape=21, color = \"brown\", fill = \"brown\")+\n theme(legend.position = \"none\")+\n labs(x = \"Variance expliquée (% cumulé)\", y = \"\")\n\n annotate_figure(ggarrange(plotVP1, plotVP2, plotVP3, ncol = 2, nrow = 2),\n text_grob(\"Graphiques pour les valeurs propres\", color = \"black\", face = \"bold\", size = 12),\n bottom = text_grob(\n paste0(\"Somme des valeurs propres supérieures à 1 : \", vpsup1,\n \".\\nPourcentage cumulé des valeurs propres supérieures à 1 : \", vpsup1cumul, \" %.\"),\n color = \"black\", hjust = 1, x = 1, size = 10))\n```\n\n#### Résultats de l'ACP pour les variables {#sec-12222}\n\nPour qualifier les axes, quatre mesures sont disponibles pour les variables :\n\n- **Les coordonnées factorielles des variables** sont simplement les coefficients de corrélation de Pearson des variables sur l’axe *k* et varient ainsi de -1 à 1 (relire au besoin la [section @sec-043]). Pour qualifier un axe, il convient alors de repérer les variables les plus corrélées positivement et négativement sur l’axe, autrement dit, de repérer les variables situées aux extrémités l'axe. \n\n- **Les cosinus carrés des variables** (Cos^2^) (appelés aussi les qualités de représentation des variables sur un axe) permettent de repérer le ou les axes qui concourent le plus à donner un sens à la variable. Ils sont en fait les coordonnées des variables mises au carré. La somme des cosinus carrés d’une variable sur tous les axes de l’ACP est donc égale à 1 (sommation en ligne).\n\n- **La qualité de représentation d'une variable sur les _n_ premiers axes** est simplement la somme des cosinus carrés d'une variable sur les axes retenus. Par exemple, pour la variable `Lden`, la qualité de représentation de la variable sur le premier axe est égale : $\\mbox{0,42}^2=\\mbox{0,17}$. Pour cette même variable, la qualité de la `Lden` sur les trois premiers axes est égale à : $\\mbox{0,17}+\\mbox{0,32}+\\mbox{0,26}=\\mbox{0,75}$.\n\n- **Les contributions des variables** permettent de repérer celles qui participent le plus à la formation d’un axe. Elles s'obtiennent en divisant les cosinus carrés par la valeur propre de l’axe multiplié par 100. La somme des contributions des variables pour un axe donné est donc égale à 100 (sommation en colonne). Par exemple, pour la variable `Lden`, la contribution sur le premier axe est égale : $\\mbox{0,174} / \\mbox{3,543} \\times \\mbox{100}= \\mbox{4,920 }%$.\n\nLes résultats de l'ACP pour les variables sont présentés au @tbl-dataacpCoordVars.\n\n```{r}\n#| label: tbl-dataacpCoordVars\n#| tbl-cap: Résultats de l'ACP pour les variables\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(kableExtra)\nnComp <- 3\n# Variance expliquée par les axes retenus\nvppct <- round(dfACPvp[1:nComp,\"VP_pct\"],1)\n# Dataframe des résultats pour les variables\nCoordsVar <- res.acp$var$coord[, 1:nComp]\nCos2Var <- res.acp$var$cos2[, 1:nComp]\nCtrVar <- res.acp$var$contrib[, 1:nComp]\ndfACPVars <- data.frame(Variable = row.names(res.acp$var$coord[, 1:nComp]),\n Coord = CoordsVar,\n Cos2 = Cos2Var,\n Qualite = rowSums(Cos2Var),\n Ctr = CtrVar)\nrow.names(dfACPVars) <- NULL\nnames(dfACPVars) <- str_replace(names(dfACPVars), \".Dim.\", \"Comp\")\n\noptions(knitr.kable.NA = \"\")\nmy_table <- knitr::kable(dfACPVars,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t\t row.names = FALSE,\n\t\t\t\t digits = 2,\n col.names = c(\"Variable\" , \"1\" , \"2\" , \"3\" , \"1\" , \"2\" , \"3\" , \"Qualité\" , \"1\" , \"2\" , \"3\"),\n align= c(\"l\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\"),\n )\nadd_header_above(my_table, c(\" \" = 1, \"Coordonnées\" = 3, \"Cosinus carrés\" = 4, \"Contributions\" = 3))\n```\n\n**Analyse de la première composante principale (valeur propre de 3,54, 35,43 %)**\n\n- À la lecture des contributions, il est clair que quatre variables contribuent grandement à la formation de l'axe 1 : `NivVieMed` (22,06 %), \n`Pct_Img` (21,56 %), `TxChom1564` (16,89 %) et `Pct_brevet` (14,94 %). Il convient alors d'analyser en détail leurs coordonnées factorielles et leurs cosinus carrés.\n\n- À la lecture des coordonnées factorielles, nous constatons que trois variables socioéconomiques sont fortement corrélées positivement avec l’axe 1, soit le *pourcentage d’immigrants* (0,87), le *taux de chômage* (0,77) et le *pourcentage de personnes avec une faible scolarité* (0,73). À l’autre extrémité, la *médiane du niveau de vie* (en euros) est négativement corrélée avec l’axe 1. Comment interpréter ce résultat? Premièrement, cela signifie que plus la valeur de l’axe 1 est positive et élevée, plus celles des trois variables (`Pct_Img`,`TxChom1564` et `Pct_brevet`) sont aussi élevées (corrélations positives) et plus la valeur de `NivVieMed` est faible (corrélation négative). Inversement, plus la valeur de l’axe 1 est négative et faible, les valeurs de `Pct_Img`, `TxChom1564` et `Pct_brevet` sont faibles et plus celle de `NivVieMed` est forte. Deuxièmement, cela signifie que les trois variables (`Pct_Img`,`TxChom1564` et `Pct_brevet`) sont fortement corrélées positivement entre elles puisqu’elles se situent sur la même extrémité de l’axe et qu’elles sont toutes trois négativement corrélées avec la variable `NivVieMed`. Cela peut être rapidement confirmé avec la matrice de corrélation entre les dix variables (@tbl-dataacpMatriceCorr). \n\n- À la lecture des cosinus carrés de l'axe 1, nous constatons que plus des trois quarts de la dispersion/de l'information des variables `NivVieMed` (0,78) et `Pct_Img` (0,76) est concentrée sur l'axe 1.\n\n\n```{r}\n#| label: tbl-dataacpMatriceCorr\n#| tbl-cap: Matrice de corrélation de Pearson entre les variables utilisées pour l'ACP\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(Hmisc)\n\nDataZ <- scale(Data)\nMatriceCorr <- as.data.frame(rcorr(Data %>% as.matrix())$r)\nMatriceCorr$Variable <- c(\"A. Lden\", \"B. NO2\", \"C. PM25\", \"D. VegHautPrt\", \"E. Pct0_14\", \n \"F. Pct_65\", \"G. Pct_Img\", \"H. TxChom1564\", \"I. Pct_brevet\", \"J. NivVieMed\")\nMatriceCorr <- MatriceCorr[, c(11,1:10)]\nnames(MatriceCorr) <- c(\"Variable\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"I\", \"J\")\nfor (e in 2:11){\n MatriceCorr[[e]] <- ifelse(MatriceCorr[[e]] == 1.00, NA, MatriceCorr[[e]])\n}\noptions(knitr.kable.NA = \"\")\nknitr::kable(MatriceCorr,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t digits = 2,\n align= c(\"l\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\")\n )\n```\n\n**Analyse de la deuxième composante principale (valeur propre de 2,76, 27,60 %)**\n\n- À la lecture des contributions, trois variables environnementales contribuent à la formation de l'axe 2 : principalement, celles sur la pollution de l'air (`NO2` = 31,07 % et `PM25` = 30,36 %) et secondairement, celle sur le bruit routier (`Lden` = 11,64 %).\n\n- À la lecture des coordonnées factorielles, ces trois variables sont fortement corrélées positivement avec l'axe 2 : `NO2` (0,93), `PM25` (0,92) et `Lden` (0,57). À l'autre extrémité de l'axe, la variable `Pct0_14` est négativement, mais pas fortement, corrélée (-0,53). La lecture de la matrice de corrélation au @tbl-dataacpMatriceCorr confirme que ces trois variables environnementales sont fortement corrélées positivement entre elles (par exemple, un coefficient de corrélation de Pearson de 0,90 entre `NO2` et `PM25`).\n\n- À la lecture des cosinus carrés de l'axe 2, nous constatons que près de 90 % de la dispersion/de l'information des variables `NO2` (0,86) et `PM25` (0,84) est concentrée sur l'axe 2.\n\n\n**Analyse de la troisième composante principale (valeur propre de 1,042, 10,42 %)**\n\n- Le *pourcentage de personnes âgées* (`Pct_65`) contribue principalement à la formation de l'axe 3 avec lequel il est corrélé positivement (contribution de 49,26 % et coordonnée factorielle de 0,72). S'en suit la variable `Lden`, qui joue un rôle beaucoup moins important (contribution de 24,80 % et coordonnée factorielle de 0,51).\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Lien entre la valeur propre d'un axe et le nombre de variables contribuant à sa formation**\n:::\n::: bloc_astuce-body\nVous auvez compris que plus la valeur propre d'un axe est forte, plus il y a potentiellement de variables qui concourent à sa formation. Cela explique que pour la troisième composante, qui a une faible valeur propre (1,042), seule une variable contribue significativement à sa formation. \n:::\n:::\n\n**Analyse de la qualité de représentation des variables sur les premiers axes de l'ACP**\n\nÀ titre de rappel, la qualité est simplement la somme des cosinus carrés d’une variable sur les axes retenus. Si nous retenons trois axes, les six variables qui sont le mieux résumées – et qui ont donc le plus d'influence sur les résultats de l'ACP – sont  : `NO2` (0,92), `PM25` (0,87), `NivVieMed` (0,79), `Pct_Img` (0,78), `Pct_brevet` (0,77) et `Lden` (0,75).\n\n**Qualification, dénomination d'axes factoriels**\n\nL'analyse des coordonnées, des contributions et des cosinus carrés doit vous permettre de formuler un intitulé pour chacun des axes retenus. Nous vous proposons les intitulés suivants : \n\n- *Niveau de défavorisation socioéconomique* (axe 1). Plus la valeur de l'axe est élevée, plus le niveau de défavorisation de l'entité spatiale (IRIS) est élevé.\n\n- *Qualité environnementale* (axe 2). Plus la valeur de l'axe est forte, plus les niveaux de pollution atmosphérique (dioxyde d'azote et particules fines) et de bruit (Lden) sont élevés.\n\n**Recours à des graphiques pour analyser les résultats de l'ACP pour des variables**\n\nPlus le nombre de variables utilisées pour calculer l'ACP est important, plus l'analyse des coordonnées factorielles, des cosinus carrés et des contributions reportés dans un tableau devient fastidieuse. Puisque l’ACP a été calculée sur dix variables, l’analyse des valeurs du @tbl-dataacpCoordVars a été assez facile et rapide. Imaginez maintenant que nous réalisons une ACP sur une centaine de variables, la taille du tableau des résultats pour les variables sera considérable... Par conséquent, il est recommandé de construire plusieurs graphiques qui facilitent l’analyse des résultats pour les variables. \n\nPar exemple, à la @fig-acpgraphvarscoords, nous avons construit des graphiques avec les coordonnées factorielles sur les trois premiers axes de l’ACP. En un coup d’œil, il est facile de repérer les variables les plus corrélées positivement ou négativement avec chacun d’entre eux.\nAussi, il est fréquent de construire un nuage de points avec les coordonnées des variables sur les deux premiers axes factoriels, soit un graphique communément appelé **nuage de points des variables sur le premier plan factoriel** sur lequel est représenté le cercle des corrélations (@fig-acp1erplanfactVars). Bien entendu, cet exercice peut être fait avec d’autres axes factoriels (les axes 3 et 4 par exemple).\n\n```{r}\n#| label: fig-acpgraphvarscoords\n#| echo: false\n#| fig-align: center\n#| fig-cap: Coordonnées factorielles des variables\n#| out-width: \"80%\"\n# Variance expliquée par les axes retenus\nvppct <- round(dfACPvp[1:nComp,\"VP_pct\"],1)\n# Dataframe des résultats pour les variables\nCoordsVar <- res.acp$var$coord[, 1:nComp]\nCos2Var <- res.acp$var$cos2[, 1:nComp]\nCtrVar <- res.acp$var$contrib[, 1:nComp]\ndfACPVars <- data.frame(Variable = row.names(res.acp$var$coord[, 1:nComp]),\n Coord = CoordsVar,\n Cos2 = Cos2Var,\n Qualite = rowSums(Cos2Var),\n Ctr = CtrVar)\nrow.names(dfACPVars) <- NULL\nnames(dfACPVars) <- str_replace(names(dfACPVars), \".Dim.\", \"Comp\")\n\n# Histogrammes pour les coordonnées\ncouleursCoords <- c(\"lightsalmon\" , \"steelblue\")\nplotCoordF1 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp1),\n x = CoordComp1, fill = CoordComp1<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords, labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 1 (\", tofr(vppct[1]),\"%)\"), y = \"Variable\")+\n theme(legend.position = \"none\")\n\nplotCoordF2 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp2),\n x = CoordComp2, fill = CoordComp2<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords, labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 2 (\", tofr(vppct[2]),\"%)\"), y = \"Variable\")+\n theme(legend.position = \"none\")\n\nplotCoordF3 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp3),\n x = CoordComp3, fill = CoordComp3<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\", values = couleursCoords, labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 3 (\", tofr(vppct[3]),\"%)\"), y = \"Variable\")\n\nannotate_figure(ggarrange(plotCoordF1, plotCoordF2, plotCoordF3, nrow = nComp),\n text_grob(\"Coordonnées des variables sur les axes factoriels\",\n color = \"black\", face = \"bold\", size = 12))\n```\n\n```{r}\n#| label: fig-acp1erplanfactVars\n#| echo: false\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'ACP pour les variables\n#| message: false\n#| out-width: \"75%\"\n#| quietly: true\n\nlibrary(factoextra)\nlibrary(ggplot2)\nlibrary(ggpubr)\n\nfviz_pca_var(res.acp,\n geom = c(\"point\", \"text\" , \"arrow\"),\n col.var=\"black\",\n col.circle = \"red\",\n title = \"Premier plan factoriel pour les variables\")+\n theme_minimal()\n```\n\n#### Résultats de l'ACP pour les individus {#sec-12223}\n\nComme pour les variables, nous retrouvons les mêmes mesures pour les individus : les coordonnées factorielles, les cosinus carrés et les contributions. Les coordonnées factorielles des individus sont les projections orthogonales des observations sur l'axe. Puisqu'en ACP normée, les variables utilisées pour l'ACP sont centrées réduites, la moyenne des coordonnées factorielles des individus pour un axe est toujours égale à zéro. En revanche, contrairement aux coordonnées factorielles pour les variables, les coordonnées pour les individus ne varient pas de -1 à 1! Les cosinus carrés quantifient à quel point chaque axe représente chaque individu. Enfin, les contributions quantifient l'apport de chaque individu à la formation d'un axe.\n\nSi le jeu de données comprend peu d'observations, il est toujours possible de créer un **nuage de points des individus sur le premier plan factoriel** sur lequel vous pouvez ajouter les étiquettes permettant d'identifier les observations (@fig-acp1erplanfactIndiv). Ce graphique est rapidement illisible lorsque le nombre d'observations est important. Il peut rester utile si certaines des observations du jeu de données doivent faire l'objet d'une analyse spécifique.\n\n```{r}\n#| label: fig-acp1erplanfactIndiv\n#| echo: false\n#| fig-align: center\n#| fig-cap: Premier plan factoriel pour les individus\n#| message: false\n#| out-width: \"75%\"\nlibrary(factoextra)\nlibrary(ggplot2)\nlibrary(ggpubr)\n\nfviz_pca_ind(res.acp,\n geom = c(\"point\", \"text\"),\n col.var=\"black\",\n col.circle = \"red\",\n title = \"\")+\n theme_minimal()\n```\n\nLorsque les observations sont des unités spatiales, il est très intéressant de cartographier les coordonnées factorielles des individus (@fig-acp1erplanfactIndiv). À la lecture de la carte choroplèthe de gauche (axe 1), nous pouvons constater que le niveau de défavorisation socioéconomique est élevé dans l'est (IRIS en vert), et inversement, très faible à l'ouest de l'agglomération (IRIS en rouge). À la lecture de la carte de droite (axe 2), sans surprise, la partie centrale de l'agglomération est caractérisée par des niveaux de pollution atmosphérique et de bruit routier bien plus élevés qu'en périphérie.\n\n```{r}\n#| label: fig-acpcartoindiv\n#| echo: false\n#| warning: false\n#| message: false\n#| fig-align: center\n#| fig-cap: Cartographie des coordonnées factorielles des individus\n#| out-width: \"80%\"\nlibrary(tmap)\nlibrary(RColorBrewer)\n\nCoordsInd <- res.acp$ind$coord[, 1:nComp]\nCos2Ind <- res.acp$ind$cos2[, 1:nComp]\nCtrInd <- res.acp$ind$contrib[, 1:nComp]\ndfACPInd <- data.frame(Coord = CoordsInd, Cos2 = Cos2Ind, Ctr = CtrInd)\nnames(dfACPInd) <- str_replace(names(dfACPInd), \".Dim.\", \"Comp\")\nCartoACP <- cbind(LyonIris, dfACPInd)\n\nCarte1 <- tm_shape(CartoACP) +\n tm_polygons(col = \"CoordComp1\", style = \"cont\",\n midpoint = 0, title = \"Coordonnées\")+\n tm_layout(main.title = \"Axe 1 : Défavorisation socioéco.\",\n main.title.size = 1, attr.outside = TRUE, frame = FALSE)\n\nCarte2 <- tm_shape(CartoACP) +\n tm_polygons(col = \"CoordComp2\", style = \"cont\",\n midpoint = 0, title = \"Coordonnées\")+\n tm_layout(main.title = \"Axe 2 : Qualité environnementale\",\n main.title.size = 1, attr.outside = TRUE, frame = FALSE)\n\ntmap_arrange(Carte1, Carte2)\n```\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Autres éléments intéressants de l'ACP**\n:::\n::: bloc_aller_loin-body\n**Ajout de variables ou d'individus supplémentaires** \n\nPremièrement, il est possible d'ajouter des variables continues ou des individus supplémentaires qui n'ont pas été pris en compte dans le calcul de l'ACP (@fig-acpvarindcorrsuppl). Concernant les variables continues supplémentaires, il s'agit simplement de calculer leurs corrélations avec les axes retenus de l'ACP. Concernant les individus, il s'agit de les projeter sur les axes factoriels. Pour plus d'informations sur le sujet, consultez les excellents ouvrages de Ludovic Lebart, Alain Morineau et Marie Piron [-@lebart1995statistique, p.42-45] ou encore de Jérôme Pagès [-@pages2013analyse, p.22-24].\n\n\n![Variables et individus supplémentaires pour l'ACP](images/Chap12/AcpIndVarSuppl.png){#fig-acpvarindcorrsuppl width=\"28%\" fig-align=\"center\"}\n\n\n**Pondération des individus et des variables**\n\nDeuxièmement, il est possible de pondérer à la fois les individus et, plus rarement, les variables lors du calcul de l'ACP.\n\n**Analyse en composantes principales non paramétrique**\n\nTroisièmement, il est possible de calculer une ACP sur des variables préalablement transformées en rang ([section @sec-02552]). Cela peut être justifié lorsque les variables sont très anormalement distribuées en raison de valeurs extrêmes. Les coordonnées factorielles pour les variables sont alors le coefficient de Spearman ([section @sec-0433]) et non de Pearson. Aussi, les variables sont centrées non pas sur leurs moyennes respectives, mais sur leurs médianes. Pour plus d'informations sur cette approche, consultez de nouveau Lebart et al. [-@lebart1995statistique, p.51-52].\n\n**Analyse en composantes principales robuste**\n\nFinalement, d'autres méthodes plus avancées qu'une ACP non paramétrique peuvent être utilisées afin d'obtenir des composantes principales qui ne sont pas influencées par des valeurs extrêmes : les ACP robustes [@rivest1988analyse; @hubert2005robpca] qui peuvent être mises en œuvre, entre autres avec le *package* `roscpca`.\n:::\n:::\n\n\n### Mise en œuvre dans R {#sec-1223}\n\nPlusieurs *packages* permettent de calculer une ACP dans R, notamment `psych` avec la fonction `principal`, `ade4` avec la fonction `dudi.pca` et `FactoMineR`[@FactoMineR] avec la fonction `PCA`. Ce dernier est certainement le plus abouti. De plus, il permet également de calculer une analyse des correspondances (AFC), une analyse des correspondances multiples (ACM) et une analyse factorielle de données mixtes (AFDM). Nous utilisons donc `FactoMineR` pour mettre en œuvre les trois types de méthodes factorielles abordées dans ce chapitre (ACP, AFC et ACM). Pour l'ACP, nous exploitons un jeu de données issu du *package* `geocmeans` qu'il faut préalablement charger à l'aide des lignes de code suivantes.\n\n```{r}\n#| echo: true\nlibrary(geocmeans)\ndata(LyonIris)\nData <- st_drop_geometry(LyonIris[c(\"CODE_IRIS\" , \"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\",\n \"Pct0_14\" , \"Pct_65\" , \"Pct_Img\",\n \"TxChom1564\" , \"Pct_brevet\" , \"NivVieMed\")])\n```\n\n#### Calcul et exploration d'une ACP avec `FactoMineR` {#sec-12231}\n\nPour calculer l'ACP, il suffit d'utiliser la fonction `PCA` de `FactoMineR`, puis la fonction `summary(MonACP)` qui renvoie les résultats de l'ACP pour : \n\n- Les valeurs propres (section `Eigenvalues`) pour les composantes principales (`Dim.1` à `Dim.n`) avec leur variance expliquée brute (`Variance`) en pourcentage (`% of var.`) et en pourcentage cumulé (`Cumulative % of var.`).\n\n- Les dix premières observations (section `Individuals`) avec les coordonnées factorielles (`Dim.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`). Pour accéder aux résultats pour toutes les observations, utilisez les fonctions `res.acp$ind` ou encore `res.acp$ind$coord` (uniquement les coordonnées factorielles), `res.acp$ind$contrib` (uniquement les contributions) et `res.acp$ind$cos2` (uniquement les cosinus carrés).\n\n- Les variables (section `Variables`) avec les coordonnées factorielles (`Dim.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`).\n\n```{r}\n#| echo: true\nlibrary(FactoMineR)\n# Version classique avec FactoMineR\n# Construction d'une ACP sur les colonnes 2 à 11 du DataFrame Data\nres.acp <- PCA(Data[,2:11], scale.unit = TRUE, graph = FALSE)\n# Affichage des résultats de la fonction PCA\nprint(res.acp)\n# Résumé des résultats (valeurs propres, individus, variables)\nsummary(res.acp)\n```\n\nAvec les fonctions de base `barplot` et `plot`, il est possible de construire rapidement des graphiques pour explorer les résultats de l'ACP pour les valeurs propres, les variables et les individus.\n\n```{r}\n#| echo: true\n# Graphiques pour les valeurs propres\nbarplot(res.acp$eig[,1], main=\"Valeurs propres\", names.arg=1:nrow(res.acp$eig))\nbarplot(res.acp$eig[,2], main=\"Variance expliquée (%)\", names.arg=1:nrow(res.acp$eig))\nbarplot(res.acp$eig[,3], main=\"Variance expliquée cumulée (%)\",\n names.arg=1:nrow(res.acp$eig))\n# Nuage du points du premier plan factoriel pour les variables et les individus\nplot(res.acp, graph.type = \"classic\", choix = \"var\", axes = 1:2, \n title = \"Premier plan factoriel (variables)\")\nplot(res.acp, graph.type = \"classic\", choix = \"ind\", axes = 1:2, \n title = \"Premier plan factoriel (individus)\")\n```\n\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Pondérations pour les individus et les variables**\n:::\n::: bloc_aller_loin-body\nNous avons vu, dans un encadré ci-dessus, qu'il est possible d'ajouter des variables et des individus supplémentaires dans une ACP, ce que permet la fonction `PCA` de `FactoMineR` avec les paramètres `ind.sup` et `quanti.sup`. Aussi, pour ajouter des pondérations aux individus ou aux variables, utilisez les paramètres `row.w` et `col.w`. Pour plus d'informations sur ces paramètres, consulter l'aide de la fonction en tapant `?PCA` dans la console de RStudio.\n:::\n:::\n\n#### Exploration graphique des résultats de l'ACP avec `factoextra` {#sec-12232}\n\nVisuellement, vous avez pu constater que les graphiques ci-dessus (pour les valeurs propres et pour le premier plan factoriel pour les variables et les individus), réalisés avec les fonctions de base `barplot` et `plot`, sont peu attrayants. Avec le *package* `factoextra`, quelques lignes de code suffissent pour construire des graphiques bien plus esthétiques. \n\nPremièrement, la syntaxe ci-dessous renvoie deux graphiques pour analyser les résultats des valeurs propres (@fig-factoextra1).\n\n```{r}\n#| label: fig-factoextra1\n#| echo: true\n#| fig-align: center\n#| fig-cap: Graphiques pour les valeurs propres de l'ACP avec factoextra\n#| message: false\n#| out-width: \"75%\"\nlibrary(factoextra)\nlibrary(ggplot2)\nlibrary(ggpubr)\n\n# Graphiques pour les variables propres avec factoextra\nG1 <- fviz_screeplot(res.acp, choice =\"eigenvalue\", addlabels = TRUE,\n x = \"Composantes\",\n y = \"Valeur propre\",\n title = \"\")\nG2 <- fviz_screeplot(res.acp, choice =\"variance\", addlabels = TRUE,\n x = \"Composantes\",\n y = \"Pourcentage de la variance expliquée\",\n title = \"\")\nggarrange(G1, G2)\n```\n\nDeuxièmement, la syntaxe ci-dessous renvoie trois graphiques pour analyser les contributions de chaque variable aux deux premiers axes de l'ACP (figures [-@fig-factoextra2] et [-@fig-factoextra3]) et la qualité de représentation des variables sur les trois premiers axes (@fig-factoextra4), c'est-à-dire la somme des cosinus carrés sur les trois axes retenus.\n\n```{r}\n#| eval: false\n#| include: true\n# Contributions des variables aux deux premières composantes avec factoextra\nfviz_contrib(res.acp, choice = \"var\", axes = 1, top = 10,\n title = \"Contributions des variables à la première composante\")\nfviz_contrib(res.acp, choice = \"var\", axes = 2, top = 10,\n title = \"Contributions des variables à la première composante\")\nfviz_cos2(res.acp, choice = \"var\", axes = 1:3)+\n labs(x = \"\", y = \"Somme des cosinus carrés sur les 3 axes retenus\",\n title = \"Qualité de représentation des variables sur les axes retenus de l'ACP\")\n```\n\n\n```{r}\n#| label: fig-factoextra2\n#| echo: false\n#| fig-align: center\n#| fig-cap: Contributions des variables à la première composante avec factoextra\n#| out-width: \"85%\"\n# Contributions des variables aux deux premières composantes\nfviz_contrib(res.acp, choice = \"var\", axes = 1, top = 10,\n title = \"Contributions des variables à la première composante\")\n```\n\n```{r}\n#| label: fig-factoextra3\n#| echo: false\n#| fig-align: center\n#| fig-cap: Contributions des variables à la deuxième composante avec factoextra\n#| out-width: \"85%\"\n# Contributions des variables aux deux premières composantes\nfviz_contrib(res.acp, choice = \"var\", axes = 2, top = 10,\n title = \"Contributions des variables à la deuxième composante\")\n```\n\n```{r}\n#| label: fig-factoextra4\n#| echo: false\n#| fig-align: center\n#| fig-cap: Qualité des variables sur les trois premières composantes avec factoextra\n#| out-width: \"85%\"\nfviz_cos2(res.acp, choice = \"var\", axes = 1:3)+\n labs(x = \"\", y = \"Somme des cosinus carrés sur les 3 axes retenus\",\n title = \"Qualité de représentation des variables sur les axes retenus de l'ACP\")\n```\n\n\nTroisièmement, le code ci-dessous renvoie un nuage de points pour le premier plan factoriel de l'ACP (axes 1 et 2) pour les variables (@fig-factoextra5) et les individus (@fig-factoextra6).\n\n```{r}\n#| eval: false\n#| include: true\n# Premier plan factoriel pour les variables avec factoextra\nfviz_pca_var(res.acp, col.var=\"contrib\",\n title = \"Premier plan factoriel pour les variables\")+\n scale_color_gradient2(low=\"#313695\", mid=\"#ffffbf\", high=\"#a50026\",\n midpoint=mean(res.acp$var$contrib[,1]))\n# Premier plan factoriel pour les individus avec factoextra\nfviz_pca_ind(res.acp, label = \"none\", title = \"ACP. Individus\")\nfviz_pca_ind(res.acp, col.ind=\"cos2\", title = \"ACP. Individus\") +\n scale_color_gradient2(low=\"blue\", mid=\"white\", high=\"red\", midpoint=0.50)\n```\n\n```{r}\n#| label: fig-factoextra5\n#| echo: false\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'ACP pour les variables avec factoextra\n#| out-width: \"100%\"\nfviz_pca_var(res.acp, col.var=\"contrib\",\n title = \"\")+\n scale_color_gradient2(low=\"#313695\", mid=\"#ffffbf\", high=\"#a50026\",\n midpoint=mean(res.acp$var$contrib[,1]))\n```\n\n```{r}\n#| label: fig-factoextra6\n#| echo: false\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'ACP pour les individus avec factoextra\n#| out-width: \"75%\"\nfviz_pca_ind(res.acp, col.ind=\"cos2\", title = \"\") +\n scale_color_gradient2(low=\"blue\", mid=\"white\", high=\"red\", midpoint=0.50)+coord_fixed()\n```\n\n#### Personnalisation des graphiques avec les résultats de l'ACP {#sec-12233}\n\nAvec un peu plus de lignes de code et l'utilisation d'autres *packages* (`ggplot2`, `ggpubr`, `stringr`, `corrplot`), vous pouvez aussi construire des graphiques personnalisés.\n\nPremièrement, la syntaxe ci-dessous permet de réaliser trois graphiques pour analyser les valeurs propres (@fig-acpmesgraphs1). Notez que, d'un coup d'œil, nous pouvons identifier les composantes principales avec une valeur propre égale ou supérieure à 1. \n\n```{r}\n#| eval: false\n#| include: true\nlibrary(ggplot2)\nlibrary(ggpubr)\nlibrary(stringr)\nlibrary(corrplot)\n\n# Calcul de l'ACP\nres.acp <- PCA(Data[,2:11], ncp=5, scale.unit = TRUE, graph = FALSE)\nprint(res.acp)\n\n# Construction d'un DataFrame pour les valeurs propres\ndfACPvp <- data.frame(res.acp$eig)\nnames(dfACPvp) <- c(\"VP\" , \"VP_pct\" , \"VP_cumupct\")\ndfACPvp$Composante <- factor(1:nrow(dfACPvp), levels = rev(1:nrow(dfACPvp)))\ncouleursAxes <- c(\"steelblue\" , \"skyblue2\")\nvpsup1 <- round(sum(subset(dfACPvp, VP >= 1)$VP),2)\nvpsup1cumul <- round(sum(subset(dfACPvp, VP >= 1)$VP_pct),2)\n\nplotVP1 <- ggplot(dfACPvp, aes(x = VP, y = Composante, fill = VP<1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 1, linetype = \"dashed\", color = \"azure4\", linewidth = 1)+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n labs(x = \"Valeur propre\", y = \"Composante principale\")\nplotVP2 <- ggplot(dfACPvp, aes(x = VP_pct, y = Composante, fill = VP<1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n theme(legend.position = \"none\")+\n labs(x = \"Pourcentage de la variance expliquée\", y = \"\")\nplotVP3 <- ggplot(dfACPvp, aes(x = VP_cumupct, y = Composante, fill = VP<1, group=1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n geom_line(colour = \"brown\", linetype = \"solid\", size=.8) +\n geom_point(size=3, shape=21, color = \"brown\", fill = \"brown\")+\n theme(legend.position = \"none\")+\n labs(x = \"Pourcentage cumulé de la variance expliquée\", y = \"\")\n\ntext1 <- paste0(\"Somme des valeurs propres supérieures à 1 : \",\n vpsup1,\n \".\\nPourcentage cumulé des valeurs propres supérieures à 1 : \",\n vpsup1cumul, \"%.\")\nannotate_figure(ggarrange(plotVP1, plotVP2, plotVP3, ncol = 2, nrow = 2),\n text_grob(\"Analyse des valeurs propres\", \n color = \"black\", face = \"bold\", size = 12),\n bottom = text_grob(text1,\n color = \"black\", hjust = 1, x = 1, size = 10))\n```\n\n```{r}\n#| label: fig-acpmesgraphs1\n#| echo: false\n#| fig-align: center\n#| fig-cap: Graphiques personnalisés pour les valeurs propres\n#| out-width: \"75%\"\nlibrary(ggplot2)\nlibrary(ggpubr)\nlibrary(stringr)\n\n# Calcul de l'ACP\nres.acp <- PCA(Data[,2:11], ncp=5, scale.unit = TRUE, graph = FALSE)\n\n# Construction d'un DataFrame pour les valeurs propres\ndfACPvp <- data.frame(res.acp$eig)\nnames(dfACPvp) <- c(\"VP\" , \"VP_pct\" , \"VP_cumupct\")\ndfACPvp$Composante <- factor(1:nrow(dfACPvp), levels = rev(1:nrow(dfACPvp)))\n\ncouleursAxes <- c(\"steelblue\" , \"skyblue2\")\nvpsup1 <- round(sum(subset(dfACPvp, VP >= 1)$VP),2)\nvpsup1cumul <- round(sum(subset(dfACPvp, VP >= 1)$VP_pct),2)\nplotVP1 <- ggplot(dfACPvp, aes(x = VP, y = Composante, fill = VP<1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 1, linetype = \"dashed\", color = \"azure4\", linewidth = 1)+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n labs(x = \"Valeur propre\", y = \"Composante principale\")\nplotVP2 <- ggplot(dfACPvp, aes(x = VP_pct, y = Composante, fill = VP<1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n theme(legend.position = \"none\")+\n labs(x = \"Variance expliquée (%)\", y = \"\")\nplotVP3 <- ggplot(dfACPvp, aes(x = VP_cumupct, y = Composante, fill = VP<1, group=1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n scale_fill_manual(name = \"Valeur\\npropre\" , values = couleursAxes, labels = c(\">= 1\" , \"< 1\"))+\n geom_line(colour = \"brown\", linetype = \"solid\", linewidth = .8) +\n geom_point(size=3, shape=21, color = \"brown\", fill = \"brown\")+\n theme(legend.position = \"none\")+\n labs(x = \"Variance expliquée (% cumulé)\", y = \"\")\n annotate_figure(ggarrange(plotVP1, plotVP2, plotVP3, ncol = 2, nrow = 2),\n text_grob(\"Analyse des valeurs propres\", color = \"black\", face = \"bold\", size = 12),\n bottom = text_grob(\n paste0(\"Somme des valeurs propres supérieures à 1 : \", vpsup1,\n \".\\nPourcentage cumulé des valeurs propres supérieures à 1 : \", vpsup1cumul, \"%.\"),\n color = \"black\", hjust = 1, x = 1, size = 10))\n```\n\nDeuxièmement, la syntaxe ci-dessous permet de : \n\n- Construire un *DataFrame* avec les résultats des variables.\n\n- Construire des histogrammes avec les coordonnées des variables sur les axes factoriels (@fig-acpmesgraphs2). Notez que les coordonnées négatives sont indiquées avec des barres bleues et celles positives, avec des barres de couleur saumon.\n\n- Un graphique avec les contributions des variables sur les axes retenus (@fig-acpmesgraphs3).\n\n- Un graphique avec les cosinus carrés des variables sur les axes retenus (@fig-acpmesgraphs4). \n\n- Un histogramme avec la qualité des variables sur les axes retenus (@fig-acpmesgraphs5), soit la sommation de leurs cosinus carrés sur les axes retenus.\n\n```{r}\n#| eval: false\n#| include: true\n# Analyse des résultats de L'ACP pour les variables\nlibrary(corrplot)\nlibrary(stringr)\nlibrary(ggplot2)\nlibrary(ggpubr)\n\n# Indiquer le nombre d'axes à conserver suite à l'analyse des valeurs propres\nnComp <- 3\n# Variance expliquée par les axes retenus\nvppct <- round(dfACPvp[1:nComp,\"VP_pct\"],1)\n# Dataframe des résultats pour les variables\nCoordsVar <- res.acp$var$coord[, 1:nComp]\nCos2Var <- res.acp$var$cos2[, 1:nComp]\nCtrVar <- res.acp$var$contrib[, 1:nComp]\ndfACPVars <- data.frame(Variable = row.names(res.acp$var$coord[, 1:nComp]),\n Coord = CoordsVar,\n Cos2 = Cos2Var,\n Qualite = rowSums(Cos2Var),\n Ctr = CtrVar)\nrow.names(dfACPVars) <- NULL\nnames(dfACPVars) <- str_replace(names(dfACPVars), \".Dim.\", \"Comp\")\ndfACPVars\n\n# Histogrammes pour les coordonnées\ncouleursCoords <- c(\"lightsalmon\" , \"steelblue\")\nplotCoordF1 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp1),\n x = CoordComp1, fill = CoordComp1<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords,\n labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 1 (\", vppct[1],\"%)\"), y = \"Variable\")+\n theme(legend.position = \"none\")\nplotCoordF2 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp2),\n x = CoordComp2, fill = CoordComp2<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords,\n labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 2 (\", vppct[2],\"%)\"), y = \"Variable\")+\n theme(legend.position = \"none\")\nplotCoordF3 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp3),\n x = CoordComp3, fill = CoordComp3<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\", values = couleursCoords,\n labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 3 (\", vppct[3],\"%)\"), y = \"Variable\")\n\nannotate_figure(ggarrange(plotCoordF1, plotCoordF2, plotCoordF3, nrow = nComp),\n text_grob(\"Coordonnées des variables sur les axes factoriels\",\n color = \"black\", face = \"bold\", size = 12))\n\n# Contributions des variables à la formation des axes\ncorrplot(CtrVar, is.corr = FALSE, method =\"square\",\n addCoef.col = 1, cl.pos = FALSE)\n\n# La qualité des variables sur les composantes retenues : cosinus carrés\ncorrplot(Cos2Var, is.corr = FALSE, method =\"square\",\n addCoef.col = 1, cl.pos = FALSE)\n\nggplot(dfACPVars)+\n geom_bar(aes(y = reorder(Variable, Qualite), x=Qualite),\n stat = \"identity\", width = .6, alpha = .8, fill = \"steelblue\")+\n labs(x = \"\", y = \"Somme des cosinus carrés sur les axes retenus\",\n title = \"Qualité de représentation des variables sur les axes retenus de l'ACP\",\n subtitle = paste0(\"Variance expliquée par les \", nComp, \n \" composantes : \", sum(vppct), \"%\"))\n```\n\n\n```{r}\n#| label: fig-acpmesgraphs2\n#| echo: false\n#| fig-align: center\n#| fig-cap: Histogrammes personnalisés avec les coordonnées factorielles pour les variables\n#| out-width: \"75%\"\n# Indiquer le nombre d'axes à conserver suite à l'analyse des valeurs propres\nnComp <- 3\n# Variance expliquée par les axes retenus\nvppct <- round(dfACPvp[1:nComp,\"VP_pct\"],1)\n# Dataframe des résultats pour les variables\nCoordsVar <- res.acp$var$coord[, 1:nComp]\nCos2Var <- res.acp$var$cos2[, 1:nComp]\nCtrVar <- res.acp$var$contrib[, 1:nComp]\ndfACPVars <- data.frame(Variable = row.names(res.acp$var$coord[, 1:nComp]),\n Coord = CoordsVar,\n Cos2 = Cos2Var,\n Qualite = rowSums(Cos2Var),\n Ctr = CtrVar)\nrow.names(dfACPVars) <- NULL\nnames(dfACPVars) <- str_replace(names(dfACPVars), \".Dim.\", \"Comp\")\n\n# Histogrammes pour les coordonnées\ncouleursCoords <- c(\"lightsalmon\" , \"steelblue\")\nplotCoordF1 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp1),\n x = CoordComp1, fill = CoordComp1<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords, labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 1 (\", vppct[1],\"%)\"), y = \"Variable\")+\n theme(legend.position = \"none\")\nplotCoordF2 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp2),\n x = CoordComp2, fill = CoordComp2<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords, labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 2 (\", vppct[2],\"%)\"), y = \"Variable\")+\n theme(legend.position = \"none\")\nplotCoordF3 <- ggplot(dfACPVars,\n aes(y = reorder(Variable, CoordComp3),\n x = CoordComp3, fill = CoordComp3<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\", values = couleursCoords, labels = c(\"Positive\" , \"Négative\"))+\n labs(x = paste0(\"Axe 3 (\", vppct[3],\"%)\"), y = \"Variable\")\n\nannotate_figure(ggarrange(plotCoordF1, plotCoordF2, plotCoordF3, nrow = nComp),\n text_grob(\"Coordonnées des variables sur les axes factoriels\",\n color = \"black\", face = \"bold\", size = 12))\n```\n\n![Graphiques personnalisés avec les contributions des variables](images/Chap12/corrplotacpmesgraph3.png){#fig-acpmesgraphs3 width=\"30%\" fig-align=\"center\"}\n\n![Graphiques personnalisés avec les cosinus carrés des variables](images/Chap12/corrplotacpmesgraph4.png){#fig-acpmesgraphs4 width=\"30%\" fig-align=\"center\"}\n\n```{r}\n#| label: fig-acpmesgraphs5\n#| echo: false\n#| fig-align: center\n#| fig-cap: Graphique personnalisé avec la qualité des variables sur les axes retenus de l'ACP\n#| out-width: \"75%\"\nggplot(dfACPVars)+\n geom_bar(aes(y = reorder(Variable, Qualite), x=Qualite),\n stat = \"identity\", width = .6, alpha = .8, fill = \"steelblue\")+\n labs(x = \"\", y = \"Somme des cosinus carrés sur les axes retenus\",\n title = \"Qualité de représentation des variables sur les axes\",\n subtitle = paste0(\"Variance expliquée par les \", nComp, \n \" composantes : \", sum(vppct), \"%\"))\n```\n\nTroisièmement, lorsque les observations sont des unités spatiales, il convient de cartographier les coordonnées factorielles des individus. Dans le jeu de données utilisé, les observations sont des polygones délimitant les îlots regroupés pour l'information statistique (IRIS) pour l'agglomération de Lyon (France). Nous utilisons les *packages* `tmap` et `RColorBrewer` pour réaliser des cartes choroplèthes avec les coordonnées des deux premières composantes (@fig-acpmesgraphs6).\n\n\n```{r}\n#| label: fig-acpmesgraphs6\n#| echo: true\n#| fig-align: center\n#| fig-cap: Cartographie des coordonnées factorielles des individus\n#| out-width: \"75%\"\nlibrary(\"tmap\")\nlibrary(\"RColorBrewer\")\n# Analyse des résultats de l'ACP pour les individus\n# Dataframe des résultats pour les individus\nCoordsInd <- res.acp$ind$coord[, 1:nComp]\nCos2Ind <- res.acp$ind$cos2[, 1:nComp]\nCtrInd <- res.acp$ind$contrib[, 1:nComp]\ndfACPInd <- data.frame(Coord = CoordsInd, Cos2 = Cos2Ind, Ctr = CtrInd)\nnames(dfACPInd) <- str_replace(names(dfACPInd), \".Dim.\", \"Comp\")\n# Fusion du tableau original avec les résultats de l'ACP pour les individus\nCartoACP <- cbind(LyonIris, dfACPInd)\n# Cartographie des coordonnées factorielles pour les individus pour les\n# deux premières composantes\nCarte1 <- tm_shape(CartoACP) +\n tm_polygons(col = \"CoordComp1\", style = \"cont\",\n midpoint = 0, title = \"Coordonnées\")+\n tm_layout(main.title = paste0(\"Axe 1 (\", vppct[1],\"%)\"),\n attr.outside = TRUE, frame = FALSE, main.title.size = 1)\nCarte2 <- tm_shape(CartoACP) +\n tm_polygons(col = \"CoordComp2\", style = \"cont\",\n midpoint = 0, title = \"Coordonnées\")+\n tm_layout(main.title = paste0(\"Axe 2 (\", vppct[2],\"%)\"),\n attr.outside = TRUE, frame = FALSE, main.title.size = 1)\ntmap_arrange(Carte1, Carte2)\n```\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Exploration interactive des résultats d'une ACP avec le _package_ `explor`**. \n:::\n::: bloc_aller_loin-body\nVous avez compris qu'il ne suffit pas de calculer une ACP, il faut retenir les *n* premiers axes de l'ACP qui nous semblent les plus pertinents, puis les interpréter à la lecture des coordonnées factorielles, des cosinus carrés et des contributions des variables et des individus sur les axes. Il faut donc bien explorer les résultats à l’aide de tableaux et de graphiques! Cela explique que nous avons mobilisé de nombreux graphiques dans les deux sections précédentes ([-@sec-12232] et [-@sec-12233]). \nL’exploration des données d’une ACP peut aussi être réalisée avec des graphiques interactifs. Or, un superbe *package* dénommé [`explor`](https://juba.github.io/explor/), reposant sur [`Shiny`](https://shiny.rstudio.com/), permet d’explorer de manière interactive les résultats de plusieurs méthodes factorielles calculés avec `FactorMinerR`. Pour cela, il vous suffit de lancer les deux lignes de code suivantes :\n\n`library(explor)`\n\n`explor(res.acp)`\n\nFinalement, `explor` permet également d'explorer les résultats d'une analyse des correspondances (AFC) et d'une analyse des correspondances multiples (ACM).\n:::\n:::\n\n## Analyse factorielle des correspondances (AFC) {#sec-123}\n\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**AFC et tableau de contingence**\n:::\n::: bloc_notes-body\nPour bien comprendre l'AFC, il est essentiel de bien maîtriser les notions de tableau de contingence (marges du tableau, fréquences observées et théoriques, pourcentages en ligne et en colonne, contributions au khi-deux) et de distance du khi-deux. Si ce n'est pas le cas, il est conseillé de (re)lire le [chapitre @sec-chap05]. \n:::\n:::\n\nDans le [chapitre @sec-chap05], nous avons vu comment construire un tableau de contingence (@fig-AnalysesFactoriellesTabAFCFig) à partir de deux variables qualitatives comprenant plusieurs modalités, puis comment vérifier s’il y a dépendance entre les deux variables qualitatives avec le test du khi-deux. Or, s’il y a bien dépendance, il est peut-être judicieux de résumer l’information que contient le tableau de contingence en quelques nouvelles variables synthétiques, objectif auquel répond l’analyse factorielle des correspondances (AFC).\n\n\n![Tableau de contingence pour une AFC](images/Chap12/AnalysesFactoriellesTabAFC.png){#fig-AnalysesFactoriellesTabAFCFig width=\"70%\" fig-align=\"center\"}\n\nÀ titre de rappel ([section @sec-1212]), l’AFC a été développée par le statisticien français Jean-Paul Benzécri [-@benzecri1973analyse]. Cela explique qu’elle est souvent enseignée et utilisée en sciences sociales dans les universités francophones, mais plus rarement dans les universités anglophones. Pourtant, les applications de l’AFC sont nombreuses dans différentes disciplines des sciences sociales comme illustrées avec les exemples suivants :\n\n-\tEn géographie, les modalités de la première variable du tableau de contingence sont souvent des entités spatiales (régions, municipalités, quartiers, etc.) croisées avec les modalités d'une autre variable qualitative (catégories socioprofessionnelles, modes de transport, tranches de revenu des ménages ou des individus, etc.).\n\n- En économie régionale, nous pourrions vouloir explorer un tableau de contingence croisant des entités spatiales (par exemple, MRC au Québec, départements en France) et les effectifs d'emplois pour différents secteurs d’activité.\n\n- En sciences politiques, le recours à l’AFC peut être intéressant pour explorer les résultats d’une élection. Les deux variables qualitatives pourraient être les *circonscriptions électorales* et les *partis politiques*. Le croisement des lignes et des colonnes du tableau de contingence représenterait le nombre de votes obtenus par un parti politique *j* dans la circonscription électorale *i*. Appliquer une AFC sur un tel tableau de contingence permettrait de révéler les ressemblances entre les différents partis politiques et celles entre les circonscriptions électorales. \n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Appliquer une ACP sur un tableau de contingence : un bien mauvais calcul...**\n:::\n::: bloc_attention-body\n\nIl pourrait être tentant de transformer le tableau de contingence initial (@tbl-encadreAFCACP1) en un tableau avec les pourcentages en ligne (@tbl-encadreAFCACP2) afin de lui appliquer une analyse en composantes principales. Une telle démarche a deux inconvénients majeurs : chacune des modalités de la première variable qualitative (*I*) aurait alors le même poids; chacune des modalités de la deuxième variable (*J*) aurait aussi le même poids. Or, à la lecture des marges en ligne et en colonne au @tbl-encadreAFCACP1), il est clair que les modalités `j1` et `i1` comprennent bien plus d'individus que les autres modalités respectives.\n\nSi nous reprenons le dernier exemple applicatif, cela signifierait que le même poids est accordé à chaque parti puisque les variables sont centrées réduites en ACP (moyenne = 0 et variance = 1). Autrement dit, les grands partis traditionnels seraient ainsi sur le pied d’égalité que les autres partis. Aussi, chaque circonscription électorale aurait le même poids bien que certaines comprennent bien plus d’électeurs et d’électrices que d’autres.\n\n```{r}\n#| label: tbl-encadreAFCACP1\n#| tbl-cap: Exemple de tableau de contingence pour l'AFC\n#| echo: false\n#| message: false\n#| warning: false\ndataAFCex <- data.frame(Véhicule = c(357060, 427530, 147500, 128520),\n VehPass = c(22010,26400 , 6545, 6405),\n TranspC = c(276625,295860, 34545, 42925),\n Apied = c(65000,69410, 4415, 6565),\n Velo = c(29415,30645 , 1040, 2670))\n\ndataafex1 <- dataAFCex\ndataafex1[nrow(dataafex1)+1,] <- colSums(dataafex1)\ndataafex1$MargeJ <- rowSums(dataafex1)\nrownames(dataafex1) <- c(\"i1\", \"i2\", \"i3\", \"i4\" , \"Marge (colonne)\")\ncolnames(dataafex1) <- c(\"j1\", \"j2\", \"j3\", \"j4\", \"j5\" , \"MargeJ\")\noptions(knitr.kable.NA = \"\")\nknitr::kable(dataafex1,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t caption = \"Exemple de tableau de contingence pour l'AFC\",\n row.names = TRUE,\n col.names = c(\"j1\", \"j2\", \"j3\", \"j4\", \"j5\", \"Marge (ligne)\"),\n align= c(\"r\", \"r\", \"r\", \"r\", \"r\", \"r\"),\n position = 'HOLD_position'\n )\n```\n\n```{r}\n#| label: tbl-encadreAFCACP2\n#| tbl-cap: Exemple d'un tableau de contingence transformé (pourcentage en ligne) pour l'ACP\n#| echo: false\n#| message: false\n#| warning: false\ndataafex2 <- dataAFCex\nrownames(dataafex2) <- c(\"i1\", \"i2\", \"i3\", \"i4\")\ncolnames(dataafex2) <- c(\"V1\", \"V2\", \"V3\", \"V4\", \"V5\")\ndataafex2$MargeJ <- rowSums(dataafex2)\ndataafex2$V1 <- round(dataafex2$V1 / dataafex2$MargeJ *100, 1)\ndataafex2$V2 <- round(dataafex2$V2 / dataafex2$MargeJ *100, 1)\ndataafex2$V3 <- round(dataafex2$V3 / dataafex2$MargeJ *100, 1)\ndataafex2$V4 <- round(dataafex2$V4 / dataafex2$MargeJ *100, 1)\ndataafex2$V5 <- round(dataafex2$V5 / dataafex2$MargeJ *100, 1)\ndataafex2$MargeJ <- NULL\noptions(knitr.kable.NA = \"\")\nknitr::kable(dataafex2,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n row.names = TRUE,\n align= c(\"r\", \"r\", \"r\", \"r\", \"r\"),\n position = 'HOLD_position'\n )\n```\n:::\n:::\n\n\n### Recherche d'une simplification basée sur la distance du khi-deux {#sec-1231}\n\nSur le plan mathématique et des objectifs visés, l'AFC est similaire à l'ACP puisqu'elle permet d'explorer un tableau de trois façons : 1) en montrant les ressemblances entre un ensemble d'individus (*I*), 2) en révélant les liaisons entre les variables (*J*) et 3) en résumant le tout avec des variables synthétiques. Toutefois, avec l'AFC, les ensembles *I* et *J* sont les modalités de deux variables qualitatives (dont le croisement forme un tableau de contingence) et elle est basée sur la distance du khi-deux (et non sur la distance euclidienne comme en ACP).\n\nAinsi, avec la distance du khi-deux, la proximité (ressemblance) entre deux lignes (*i* et *l*) et deux colonnes (*j* et *k*) est mesurée comme suit :\n\n$$\nd_{\\chi_{il}^2} = \\sum_j \\frac{1}{f_{.j}}(\\frac{f_{ij}}{f_{i.}}-\\frac{f_{lj}}{f_{l.}})^2\n$$ {#eq-khideuxlignes}\n\n$$\nd_{\\chi_{jk}^2} = \\sum_i \\frac{1}{f_{i.}}(\\frac{f_{ij}}{f_{.j}}-\\frac{f_{ik}}{f_{.k}})^2\n$$ {#eq-khideuxcolonnes}\n\nPrenons un exemple fictif pour calculer ces deux distances. Le @tbl-afcdataex1 comprend trois modalités en ligne (*I*) et trois autres en colonne (*J*). Le total des effectifs de ce tableau de contingence est égal à 1 665.\n\nÀ partir des données brutes, il est facile de construire deux tableaux : le profil des lignes et le profil des colonnes (@tbl-afcProfilsLignesCols, c'est-à-dire les proportions en ligne et en colonne.\n\n```{r}\n#| label: tbl-afcdataex1\n#| tbl-cap: Données brutes du tableau de contingence\n#| echo: false\n#| message: false\n#| warning: false\n# Fréquences brutes\ndfAFC1 <- data.frame(j1 = c(360, 420, 145),\n j2 = c(65, 70, 5),\n j3 = c(275,290, 35))\n# Fréquences relatives\nnt <- sum(dfAFC1)\nni <- nrow(dfAFC1)\nnj <- ncol(dfAFC1)\ndfAFC1fij <- dfAFC1 / nt\n\n# Tableau des profils des lignes\nprofilligne <- data.frame(round(dfAFC1 / rowSums(dfAFC1),3))\nprofilligne$Total <- 1\nnames(profilligne) <- c(\"j1\" , \"j2\" , \"j3\" , \"Total\")\nrownames(profilligne) <- c(\"i1\", \"i2\", \"i3\")\n\n# Tableau des profils des colonnes\nprofilcol <- dfAFC1\nprofilcol$j1 <- round(profilcol$j1 / sum(profilcol$j1),3)\nprofilcol$j2 <- round(profilcol$j2 / sum(profilcol$j2),3)\nprofilcol$j3 <- round(profilcol$j3 / sum(profilcol$j3),3)\nprofilcol[ni+1,] <- 1\nrownames(profilcol) <- c(\"j1\", \"j2\", \"j3\", \"Total\")\n\n# Calcul des marges\ndfAFC1$fi <- rowSums(dfAFC1)\ndfAFC1[ni+1,] <- colSums(dfAFC1)\ndfAFC1fij$fi <- rowSums(dfAFC1fij)\ndfAFC1fij[ni+1,] <- colSums(dfAFC1fij)\nrownames(dfAFC1) <- c(\"i1\", \"i2\", \"i3\", \"Total (colonne)\")\noptions(knitr.kable.NA = \"\")\nknitr::kable(dfAFC1,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t row.names = TRUE,\n col.names = c(\"j1\" , \"j2\" , \"j3\" , \"Total (ligne)\"),\n align= c(\"c\" , \"c\" , \"c\" , \"c\"),\n )\n```\n\n\n```{r}\n#| label: tbl-afcProfilsLignesCols\n#| tbl-cap: Profils des lignes et des colonnes\n#| echo: false\n#| message: false\n#| warning: false\nprofilcol$Total <- NA\nprofils <- rbind(profilligne, profilcol)\nrownames(profils) <- NULL\nprofils$ind <- c(\"i1\" , \"i2\" , \"i3\" , \"i1\" , \"i2\" , \"i3\" , \"Total\")\nprofils <- profils[, c(5,1:4)]\n\noptions(knitr.kable.NA = \"\")\nmontableau <- knitr::kable(profils,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t row.names = FALSE,\n digits = 3,\n col.names = c(\"\" , \"j1\" , \"j2\" , \"j3\" , \"Total\"),\n align= c(\"c\" , \"c\" , \"c\" , \"c\" , \"c\"),\n )\ngroup_rows(montableau,\n index = c(\"Profil des lignes\" = 3,\n \"Profils des colonnes\" = 4)\n )\n```\n\nEn divisant les valeurs du @tbl-afcdataex1 par le grand total (1 665), nous obtenons tous les termes utilisés dans les équations [-@eq-khideuxlignes] et [-@eq-khideuxcolonnes] au @tbl-afcdataex2 :\n\n- Les fréquences relatives dénommées $f_{ij}$. \n- La marge $fi.$ est égale à la somme des fréquences relatives en ligne.\n- La marge $f.j$ est égale à la somme des fréquences relatives en colonne.\n- La somme de toutes les fréquences relatives est donc égale à 1, soit $\\sum{f_{i.}}$ ou $\\sum{f_{.j}}$.\n\n\n```{r}\n#| label: tbl-afcdataex2\n#| tbl-cap: Données relatives du tableau de contingence (fij)\n#| echo: false\n#| message: false\n#| warning: false\nrownames(dfAFC1fij) <- c(\"i1\", \"i2\", \"i3\", \"Total (f.j)\")\noptions(knitr.kable.NA = \"\")\nknitr::kable(dfAFC1fij,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t digits = 3,\n row.names = TRUE,\n col.names = c(\"j1\" , \"j2\" , \"j3\" , \"Total (fi.)\"),\n align= c(\"r\" , \"r\" , \"r\" , \"r\"),\n )\n```\n\nIl est possible de calculer les distances entre les différentes modalités de *I* en appliquant l'@eq-khideuxlignes; par exemple, la distance entre les observations `i1` et `i2` est égale à :\n\n$$d_{(i1,i2)}=\\frac{\\mbox{1}}{\\mbox{0,556}}(\\mbox{0,216}-\\mbox{0,252})^2+\\frac{\\mbox{1}}{\\mbox{0,084}}(\\mbox{0,039}-\\mbox{0,042})^2+\n\\frac{\\mbox{1}}{\\mbox{0,360}}(\\mbox{0,165}-\\mbox{0,174})^2=\\mbox{0,003}$$\n\nAvec l'@eq-khideuxcolonnes, la distance entre les modalités `j1` et `j2` de *J* est égale à :\n\n$$d_{(j1,j2)}=\\frac{\\mbox{1}}{\\mbox{0,420}}(\\mbox{0,216}-\\mbox{0,039})^2+ \\frac{\\mbox{1}}{\\mbox{0,468}}(\\mbox{0,252}-\\mbox{0,042})^2 + \\frac{\\mbox{1}}{\\mbox{0,111}}(\\mbox{0,087}-\\mbox{0,003})^2=\\mbox{0,233}$$\n\n\nÀ la lecture du @tbl-MatriceDistKhi, les modalités les plus semblables sont \n`i1` et `i2` (0,003) pour *I* et `j1` et `j3` (0,058) pour *J*.\n\n```{r}\n#| label: tbl-MatriceDistKhi\n#| tbl-cap: Distances du khi-deux entre les modalités I et les modalités J\n#| echo: false\n#| message: false\n#| warning: false\nMatriceI <- matrix(1:9, nrow = 3, ncol = 3)\nMatriceJ <- matrix(1:9, nrow = 3, ncol = 3)\ndfij <- dfAFC1fij\n\n# Matrice de distances des lignes I\nfor (i in 1:ni){\n for (l in 1:ni){\n dil <- (1/dfij[4,1])*(dfij[i,1]-dfij[l,1])^2 +\n (1/dfij[4,2])*(dfij[i,2]-dfij[l,2])^2 + \n (1/dfij[4,3])*(dfij[i,3]-dfij[l,3])^2\n MatriceI[i,l] <- round(dil,3)\n }\n}\n# Matrice de distances des colonnes J\nfor (i in 1:ni){\n for (l in 1:ni){\n dil <- (1/dfij[1,4])*(dfij[1,i]-dfij[1,l])^2 +\n (1/dfij[2,4])*(dfij[2,i]-dfij[2,l])^2 + \n (1/dfij[3,4])*(dfij[3,i]-dfij[3,l])^2\n MatriceJ[i,l] <- round(dil,3)\n }\n}\nMatrices <- data.frame(Ind. =c(\"i1\" , \"i2\" , \"i3\"),\n MatriceI,\n Col.=c(\"j1\" , \"j2\" , \"j3\"),\n MatriceJ)\ncolnames(Matrices) <- c(\"Ind.\" , \"i1\" , \"i2\" , \"i3\", \"Col.\" , \"j1\" , \"j2\" , \"j3\")\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(Matrices,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t digits = 5,\n align= c(\"c\" , \"c\" , \"c\" , \"c\" , \"c\" , \"c\" , \"c\" , \"c\")\n )\n```\n\nFinalement, l'approche pour déterminer les axes factoriels de l'AFC est similaire à celle de l'ACP : les axes factoriels sont les droites orthogonales qui minimisent les distances aux points du profil des lignes, excepté que la métrique pour mesurer ces distances est celle du khi-deux (et non celle la distance euclidienne comme pour l'ACP). Pour plus détails sur le calcul de ces axes (notamment les formulations matricielles), consultez notamment Benzécri [-@benzecri1973analyse], Escofier et Pagès [-@escofier1998analyses] et Lebart et al. [-@lebart1995statistique].\n\n\n### Aides à l'interprétation {#sec-1232}\n\nPour illustrer les aides à l’interprétation de l’AFC, nous utilisons un jeu de données spatiales extrait du [profil du recensement de 2016 de Statistique Canada](https://www12.statcan.gc.ca/census-recensement/2016/dp-pd/prof/index.cfm?Lang=F){target='_blank'} pour les secteurs de recensement de l'île de Montréal. La liste des modalités des variables qu'il comprend est reportée au @tbl-dataAfc. L'AFC est calculée sur un tableau de contingence croisant les secteurs de recensement (lignes) et les modalités d'une variable relative au mode de transport utilisé pour les déplacements domicile-travail (colonnes). Ces modalités sont cartographiées à la @fig-cartovarAFC).\n\n```{r}\n#| label: tbl-dataAfc\n#| tbl-cap: Jeu de données utilisé pour l'analyse factorielle des correspondances\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(sf)\nlibrary(kableExtra)\nload(\"data/analysesfactorielles/DonneesAFC.Rdata\")\n\nDimensions <- c(\"Mode de transport\", \"Durée du trajet\")\nMesVarLongs <- c(\"Véhicule motorisé (conducteur·trice)\",\n \"Véhicule motorisé (passager·ère)\",\n \"Transport en commun\",\n \"À pied\",\n \"Bicyclette\",\n \"Autre moyen\",\n \"Moins de 15 minutes\",\n \"15 à 29 minutes\",\n \"30 à 44 minutes\",\n \"45 à 59 minutes\",\n \"60 minutes et plus\")\nstats <- data.frame(variable = names(dfDonneesAFC),\n nom = MesVarLongs,\n somme = sapply(dfDonneesAFC, sum)\n )\n\noptions(knitr.kable.NA = \"\")\nmontableau <- knitr::kable(stats,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t digits = 1,\n col.names = c(\"Nom\" , \"Intitulé\" , \"Somme\"),\n align= c(\"l\" , \"l\", \"r\"),\n )\ngroup_rows(montableau,\n index = c(\"Modalités de la variable utilisée dans l'AFC (mode de transport)\" = 6,\n \"Modalités de la variable supplémentaire (durée du trajet)\" = 5)\n )\n```\n\n```{r}\n#| label: fig-cartovarAFC\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Cartographie des modalités de la variable mode de transport utilisée pour l'AFC\n#| out-width: \"100%\"\nlibrary(tmap)\nlibrary(viridis)\nCarte1 <- tm_shape(sfDonneesAFC) + tm_fill(\"VehCond\", style = \"cont\", pal = viridis(10, direction = -1, option = \"G\"), title = \"Véhicule (conducteur·trice)\")\nCarte2 <- tm_shape(sfDonneesAFC) + tm_fill(\"VehPass\", style = \"cont\", pal = viridis(10, direction = -1, option = \"G\"), title = \"Véhicule (passager·ère)\")\nCarte3 <- tm_shape(sfDonneesAFC) + tm_fill(\"TranspC\", style = \"cont\", pal = viridis(10, direction = -1, option = \"G\"), title = \"Transport en commun\")\nCarte4 <- tm_shape(sfDonneesAFC) + tm_fill(\"Apied\", style = \"cont\", pal = viridis(10, direction = -1, option = \"G\"), title = \"À pied\")\nCarte5 <- tm_shape(sfDonneesAFC) + tm_fill(\"Velo\", style = \"cont\", pal = viridis(10, direction = -1, option = \"G\"), title = \"Bicyclette\")\nCarte6 <- tm_shape(sfDonneesAFC) + tm_fill(\"AutreMoyen\", style = \"cont\", pal = viridis(10, direction = -1, option = \"G\"), title = \"Autre moyen\")\ntmap_arrange(Carte1, Carte2, Carte3, Carte4, Carte5, Carte6, ncol = 2, nrow = 3)\n```\n\n#### Résultats de l'AFC pour les valeurs propres {#sec-12321}\n\nAvant de calculer l'AFC, il convient de vérifier s'il y a bien une dépendance entre les modalités des deux variables qualitatives. En effet, si les deux variables sont indépendantes, il n'est pas nécessaire de résumer le tableau de contingence avec une AFC. Pour ce faire, nous utilisons le test du khi-deux largement décrit à la [section @sec-052]. Les résultats de ce test signalent qu’il existe des associations entre les modalités des deux variables ($\\chi$ = 203 971, *p* < 0,001, @tbl-dataafckhi2). Nous pouvons donc appliquer une AFC sur ce tableau de contingence.\n\n```{r}\n#| label: tbl-dataafckhi2\n#| tbl-cap: Résultats du test du khi-deux sur le tableau de contingence\n#| echo: false\n#| message: false\n#| warning: false\nload(\"data/analysesfactorielles/DonneesAFC.Rdata\")\nchideux <- chisq.test(dfDonneesAFC[,1:6])\nni <- nrow(dfDonneesAFC)\nnj <- ncol(dfDonneesAFC[,1:6])\nnij <- sum(dfDonneesAFC[,1:6])\n# cat(\"\\n Modalités I (secteurs de recensement) :\", nrow(dfDonneesAFC),\n# \"\\n Modalités J (variable mode de transport) :\", ncol(dfDonneesAFC[,1:5]),\n# \"\\n Somme nij :\", nij,\n# \"\\n chi-deux :\", chideux$statistic,\n# \"\\n valeur de p :\", round(chideux$p.value,3),\n# \"\\nphi2 (khi-deux / nij) : \", round(chideux$statistic / nij, 5))\n\ndfkhi <- data.frame(Mesure= c(\"Modalités *I* (secteurs de recensement)\",\n \"Modalités *J* (variable mode de transport)\",\n \"Somme des données brutes ($n_{ij}$)\",\n \"Khi-deux ($\\\\chi^2$)\",\n \"Degrés de liberté, soit $(c-1)\\\\times(l-1)$\",\n \"Valeur de *p*\",\n \"Coefficient Phi au carré ($\\\\phi^2=\\\\chi^2 / n_{ij})$\"),\n Valeur = c(ni,\n nj,\n nij,\n round(chideux$statistic,2),\n (ni-1)*(nj-1),\n round(chideux$p.value,3),\n round(chideux$statistic / nij, 2))\n )\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(dfkhi,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n align= c(\"l\", \"r\")\n )\n```\n\nNous avons vu qu'en ACP normée ([section @sec-12221]), la somme des valeurs propres est égale au nombre de variables puisqu'elles sont centrées réduites. Par contre, en AFC, cette somme est égale à l'inertie totale du tableau de contingence, c'est-à-dire à la valeur du khi-deux divisée par le nombre total des effectifs bruts (soit le coefficient phi au carré, $\\phi^2$) ([section @sec-052]). Le @tbl-dataafcValeurPropres permet de vérifier que la somme des valeurs propres est bien égale au coefficient phi au carré : \n\n$$\\mbox{0,156}+\\mbox{0,046}+\\mbox{0,031}+\\mbox{0,004}+\\mbox{0,004} = \\mbox{0,24}$$\n\n$$\\phi^2 = \\chi^2 / n_{ij}=\\mbox{203 971}/ \\mbox{849 795} = \\mbox{0,24}$$\n```{r}\n#| label: tbl-dataafcValeurPropres\n#| tbl-cap: Résultats de l'AFC pour les valeurs propres\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(FactoMineR)\n# Calcul de l'AFC\nres.afc <- CA(dfDonneesAFC[,1:6], graph = FALSE)\n# Construction d'un DataFrame pour les valeurs propres\ndfAFCvp <- data.frame(res.afc$eig)\nnames(dfAFCvp) <- c(\"VP\" , \"VP_pct\" , \"dfAFCvp\")\ndfAFCvp$Composante <- factor(1:nrow(dfAFCvp), levels = rev(1:nrow(dfAFCvp)))\ndfAFCvp <- dfAFCvp[, c(4,1:3)]\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(dfAFCvp,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t digits = 3,\n col.names = c(\"Axe factoriel\" , \"Valeur propre\" , \"Pourcentage\", \"Pourc. cumulé\"),\n align= c(\"r\", \"r\" , \"r\", \"r\")\n )\n```\n\n**Combien d'axes d'une AFC faut-il retenir?**\n\n- **Approche statistique**. Mike Bendixen [-@bendixen1995compositional], cité dans l'excellent site [STHDA](http://www.sthda.com/){target='_blank'}, propose deux critères pour sélectionner les premiers axes d'une AFC : $c_1= 1 / (l-1) \\times 100$ et $c_2= 1 / (c-1) \\times 100$ avec *l* et *c* étant respectivement les nombres de modalités en ligne et en colonne. Autrement dit, lorsque les données sont distribuées aléatoirement, la valeur propre en pourcentage devrait être égale à $c_1$ et celle de l'axe factoriel moyen à $c_2$. Par conséquent, nous pourrions retenir uniquement les axes dont les valeurs propres en pourcentage excèdent : $c_1 = \\mbox{1}/(\\mbox{521}-\\mbox{1})\\times \\mbox{100}=\\mbox{0,19 }%$ et $c_2=\\mbox{1}/(\\mbox{6}-\\mbox{1})\\times \\mbox{100}=\\mbox{20 }%$. En appliquant ces deux critères, seul le premier axe factoriel qui résume 65,6 % mérite d'être retenu.\n\n- **Approche empirique** basée sur la lecture des pourcentages et des pourcentages cumulés. Nous retenons uniquement les deux premières composantes qui résument 85 % de la variance totale. Pour faciliter le choix du nombre d'axes avec cette approche empirique, il est fortement conseillé de construire un histogramme à partir des valeurs propres, soit brutes, soit en pourcentage, soit en pourcentage cumulé (@fig-afcGraphVP).\n\n```{r}\n#| label: fig-afcGraphVP\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Histogramme des valeurs propres de l'AFC\n#| out-width: \"80%\"\nlibrary(factoextra)\nc2 <- 1/(ncol(dfDonneesAFC[,1:6])-1)*100\ntexte <- tofr(round(c2, 2))\ntexte <- paste0(\"Critère pour le profil moyen : \", as.character(texte), \" %\")\nfviz_screeplot(res.afc, choice = \"variance\", addlabels = TRUE, ylim = c(0, 70),\n ylab = \"Variance expliquée (%)\",\n xlab = \"Axes factoriels\",\n main=\"\")+\n geom_hline(yintercept = c2, linetype = 1, color = \"red\", linewidth = 1)+\n annotate(geom = \"text\", x = 5.5, y = c2+3, label=texte, color = \"red\", hjust = 1, linewidth = 4)\n```\n\n#### Résultats de l'AFC pour les variables et les individus {#sec-12322}\nComme pour l'ACP, nous retrouvons les trois mêmes mesures pour les variables et les individus : 1) les coordonnées factorielles, 2) les contributions et 3) les cosinus carrés. \n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Compréhension des axes factoriels de l'AFC : une étape essentielle, incontournable...**\n:::\n::: bloc_objectif-body\nComme en ACP, l'analyse des trois mesures (coordonnées, contributions et cosinus carrés) pour les variables et les individus doit vous permettre de comprendre la signification des axes factoriels retenus de l'AFC. Cette étape d'interprétation est essentielle afin de qualifier les variables latentes (axes factoriels, variables synthétiques) produites par l'AFC.\n:::\n:::\n\n\n- **Les coordonnées factorielles** sont simplement les projections des points-lignes et des points-colonnes sur les axes de l'AFC. Tant pour les lignes que pour les colonnes, ces coordonnées bénéficient de deux propriétés intéressantes. Premièrement, pour chaque axe factoriel *k*, la somme du produit des marges des variables ($f.j$, colonnes) ou des individus ($fi.$, lignes) avec leurs coordonnées respectives ($C^k_j$ et $C^k_i$) est égale à 0 (@eq-CoordPropr1). Deuxièmement, pour chaque axe factoriel *k*, la somme des produits entre les marges (en ligne et en colonne) et les coordonnées au carré (en ligne et en colonne) est égale à la valeur propre de l'axe (@eq-CoordPropr2).\n\n$$\n\\sum{f.j (C^k_j)}= 0 \\text{ et} \\sum{fi. (C^k_i)}= 0\n$$ {#eq-CoordPropr1}\n\n$$\n\\sum{fi. (C^k_i)^2}= \\mu_k \\text{ et} \\sum{f.j (C^k_j)^2}= \\mu_k\n$$ {#eq-CoordPropr2}\n\nEn guise d'exemple, le @tbl-dataafcCoordVars2 permet de vérifier les deux propriétés des coordonnées pour les variables. Les sommes de ${f.j (C^k_j)}$ pour les axes 1 et 2 sont bien égales à 0; et les sommes de ${f.j (C^k_j)^2}$ pour les axes 1 et 2 sont bien égales aux valeurs propres de ces deux axes, soit 0,156 et 0,046 (comparez ces valeurs avec celles reportées au @tbl-dataafcValeurPropres plus haut).\n\n```{r}\n#| label: tbl-dataafcCoordVars2\n#| tbl-cap: Vérification des deux propriétés des coordonnées factorielles pour les variables\n#| echo: false\n#| message: false\n#| warning: false\nfj <- colSums(dfDonneesAFC[,1:6]) / sum(dfDonneesAFC[,1:6])\nnAxes <- 2\nCoordsVar <- res.afc$col$coord[, 1:nAxes]\ndfAFCVars2 <- data.frame(Modalite = row.names(CoordsVar),\n Coord = res.afc$col$coord[, 1:nAxes])\ndfAFCVars2$fj <- fj\ndfAFCVars2 <- dfAFCVars2[, c(1,4,2,3)]\nnames(dfAFCVars2) <- c(\"Modalite\", \"fj\", \"CoordAxe1\", \"CoordAxe2\")\nni <- nrow(dfAFCVars2)\ndfAFCVars2$fiCoord1 <- dfAFCVars2$CoordAxe1*dfAFCVars2$fj\ndfAFCVars2$fiCoord2 <- dfAFCVars2$CoordAxe2*dfAFCVars2$fj\ndfAFCVars2$fiCoord1b <- dfAFCVars2$CoordAxe1^2*dfAFCVars2$fj\ndfAFCVars2$fiCoord2b <- dfAFCVars2$CoordAxe2^2*dfAFCVars2$fj\ndfAFCVars2[ni+1,] <- NA\ndfAFCVars2[ni+1,1] <- \"Somme\"\nfor (i in c(2,5:ncol(dfAFCVars2))){\n dfAFCVars2[ni+1,i] <- round(sum(dfAFCVars2[[i]], na.rm = TRUE),4)\n}\n\noptions(knitr.kable.NA = \"\")\nmontableau <- knitr::kable(dfAFCVars2,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t\t digits = 3,\n\t\t\t\t row.names = FALSE,\n col.names = c(\"Modalité\" , \"f.j\" , \"1\" , \"2\" , \"1\" , \"2\" , \"1\" , \"2\"),\n align= c(\"l\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\"),\n )\nadd_header_above(montableau, c(\" \" = 2, \"Coord.\" = 2, \"f.j x Coord.\" = 2, \"f.j x Coord2\" = 2))\n```\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Particularité de l'AFC**\n:::\n::: bloc_attention-body\nContrairement à l'ACP, les coordonnées factorielles pour les variables en AFC ne sont pas les coefficients de corrélation de Pearson des variables sur les axes!\n:::\n:::\n\n- **Les contributions** des colonnes ou des lignes en AFC permettent de repérer celles qui contribuent le plus à la formation des axes factoriels (de manière analogue à l'ACP). Pour un axe donné, leur sommation est égale à 100 %. Elles s'obtiennent en multipliant la coordonnée au carré avec la marge et en divisant le tout par la valeur propre de l'axe (équations [-@eq-CtrAFCVar] et [-@eq-CtrAFCInd]).\n\n$$\n\\mbox{Ctr}_j^k =\\frac{f.j(C^k_j)^2}{\\mu_{k}}\\times 100\n$$ {#eq-CtrAFCVar}\n\n$$\n\\mbox{Ctr}_i^k =\\frac{fi.(C^k_i)^2}{\\mu_{k}}\\times 100\n$$ {#eq-CtrAFCInd}\n\n- **Les cosinus carrés** (Cos^2^) (appelés aussi les qualités de représentation sur un axe) permettent de repérer le ou les axes qui concourent le plus à donner un sens aux colonnes (variables) et aux lignes (individus), de manière analogue à l'ACP. Pour une variable ou un individu, la sommation des Cos^2^ pour tous les axes de l'AFC est aussi égale à 1.\n\n**Interprétation des résultats pour les colonnes (variables)**\n\nMaintenant, analysons ces trois statistiques pour les variables pour les deux premiers axes de l'AFC (@tbl-dataafcCoordVars et @fig-afc1erplanfactVars).\n\nPour l'axe 1, résumant 65 % de la variance, trois modalités concourent à sa formation : `VehCond` (34,69 %), `Apied` (34,25 %) et `Velo` (20,13 %). À la lecture des coordonnées factorielles sur cet axe, les modes de transport relatifs aux véhicules motorisés (`VehCond` = -0,33 et `VehPass` = -0,25) s'opposent clairement aux modes actifs (`Apied` = 0,81 et `Velo` = 0,94), constat qu'il est possible de confirmer visuellement avec la @fig-afc1erplanfactVars. La modalité `VehCond` a d'ailleurs la plus forte valeur de Cos^2^ sur cet axe (0,92), ce qui signale, sans l'ombre d'un doute, que l'axe 1 est celui qui donne le plus de sens à cette modalité. \n\nPuisque l'axe 2 résume une partie beaucoup plus limitée de la variance du tableau (19,25 %), il n'est pas étonnant qu'un nombre plus limité de modalités concourent à sa formation : seules les contributions de la modalité `Apied` (51,68 %) et secondairement de `TranspC` (38,81 %) sont importantes. Leurs coordonnées factorielles s'opposent d'ailleurs sur cet axe (respectivement 0,81 et 0,21).\n\n\n```{r}\n#| label: tbl-dataafcCoordVars\n#| tbl-cap: Résultats de l'AFC pour les variables\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(kableExtra)\nlibrary(stringr)\nnAxes <- 2\ndfAFCVars <- data.frame(Modalite = row.names(CoordsVar),\n Coord = res.afc$col$coord[, 1:nAxes],\n Cos2 = res.afc$col$cos2[, 1:nAxes],\n Ctr = res.afc$col$contrib[, 1:nAxes])\nrow.names(dfAFCVars) <- NULL\nnames(dfAFCVars) <- str_replace(names(dfAFCVars), \".Dim.\", \"Axe\")\n\noptions(knitr.kable.NA = \"\")\nmontableau <- knitr::kable(dfAFCVars,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t\t digits = 2,\n col.names = c(\"Modalité\" , \"1\" , \"2\" , \"1\" , \"2\" , \"1\" , \"2\"),\n align= c(\"l\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\"),\n )\nadd_header_above(montableau, c(\" \" = 1, \"Coordonnées\" = 2, \"Cosinus carrés\" = 2, \"Contributions (%)\" = 2))\n```\n\n```{r}\n#| label: fig-afc1erplanfactVars\n#| echo: false\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'AFC pour les variables\n#| message: false\n#| out-width: \"75%\"\nVP1pct <- tofr(round(res.afc$eig[1,2],2))\nVP2pct <- tofr(round(res.afc$eig[2,2],2))\nfviz_ca_col(res.afc,\n repel = TRUE,\n geom= c(\"text\" , \"point\"),\n col.col = \"steelblue\",\n gradient.cols = c(\"#00AFBB\", \"#E7B800\", \"#FC4E07\"),\n title = \"\",\n xlab=paste0(\"Axe 1 (\", VP1pct, \" %)\"),\n ylab=paste0(\"Axe 2 (\", VP2pct, \" %)\"))\n``` \n \n \n**Interprétation des résultats pour les individus**\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Premier plan factoriel pour les variables et les individus**\n:::\n::: bloc_notes-body\nLorsque le jeu de données comprend à la fois peu de modalités en ligne et en colonne, il est judicieux de les représenter simultanément sur le premier plan factoriel (axes 1 et 2). Pour ce faire, vous pouvez utiliser la fonction `fviz_ca_biplot` du *package* `factoextra`.\n:::\n:::\n\nÉtant donné que notre jeu de données comprend 521 secteurs de recensement, nous proposons ici de cartographier les coordonnées factorielles des individus pour les deux premiers axes de l'AFC (@fig-afc1erplanfactInds2). Pour l'axe 1, les secteurs de recensement à l'est et l'ouest de l'île de Montréal présentent les coordonnées les plus fortement négatives (en rouge); dans ces zones, l'usage des véhicules motorisés pour des déplacements domicile-travail est certainement surreprésenté, comparativement aux modes actifs. À l'inverse, dans les secteurs de recensement du centre de l'île présentant de fortes valeurs positives (en rouge), le recours aux modes de transports actifs (marche et vélo) est bien plus important, toutes proportions gardées. Quant à la cartographie des coordonnées pour l'axe 2, elle permet surtout de repérer quelques secteurs de recensement autour du centre-ville (très fortes valeurs positives en vert foncé) où les déplacements domicile-travail à pied sont plus fréquents, toutes proportions gardées.\n\nEn résumé, suite à l'analyse des coordonnées factorielles des variables et des individus, nous pouvons conclure que le premier axe est certainement le plus intéressant puisqu’il permet d'opposer l’usage des modes de transports motorisés versus les modes de transports actifs pour les déplacements domicile-travail sur l'île de Montréal. Cette nouvelle variable synthétique (variable latente) pourrait ainsi être introduite dans des analyses subséquentes (par exemple, dans un modèle de régression). Cela démontre qu’au même titre que l’ACP, l’AFC est une méthode de réduction de données puisque nous sommes passés d’un tableau comprenant 512 secteurs de recensement et six modalités à un tableau comprenant une seule variable synthétique (axe 1).\n\n```{r}\n#| label: fig-afc1erplanfactInds2\n#| echo: false\n#| fig-align: center\n#| fig-cap: Cartographie de coordonnées factorielles des individus pour l'AFC\n#| message: false\nlibrary(tmap)\nlibrary(stringr)\ndfAFCInd <- data.frame(Coord = res.afc$row$coord, \n Cos2 = res.afc$row$cos2, \n Ctr = res.afc$row$contrib)\nnames(dfAFCInd) <- str_replace(names(dfAFCInd), \".Dim.\", \"Comp\")\nCartoAFC <- cbind(sfDonneesAFC, dfAFCInd)\nVP1pct <- tofr(round(res.afc$eig[1,2],2))\nVP2pct <- tofr(round(res.afc$eig[2,2],2))\nCarte1 <- tm_shape(CartoAFC) +\n tm_fill(col = \"CoordComp1\", style = \"cont\", midpoint = 0, title = \"Coordonnées\")+\n tm_layout(title = paste0(\"Axe 1 (\", VP1pct,\"%)\"), attr.outside = TRUE, frame = FALSE)\nCarte2 <- tm_shape(CartoAFC) +\n tm_fill(col = \"CoordComp2\", style = \"cont\", midpoint = 0, title = \"Coordonnées\")+\n tm_layout(title = paste0(\"Axe 2 (\", VP2pct,\"%)\"), attr.outside = TRUE, frame = FALSE)\ntmap_arrange(Carte1, Carte2, nrow = 1)\n``` \n\n\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Ajout de modalités supplémentaires dans une analyse des correspondances (AFC)**\n:::\n::: bloc_aller_loin-body\nComme pour l'ACP, il est possible d'ajouter des variables et des individus supplémentaires une fois l'AFC calculée. En guise d'illustration, nous avons ajouté à l'AFC précédemment analysée des modalités relatives à la durée des temps de déplacements :\tmoins de 15 minutes, 15 à 29, 30 à 44, 45 à 59, 60 minutes et plus. Sans surprise, sur le premier plan factoriel à la @fig-afc1erplanfactInds2, cette dernière modalité, représentant les trajets les plus longs, est la plus proche des modalités relatives à l'usage des véhicules motorisés (`VehCond` et `VehPass`).\n\n```{r}\n#| label: fig-afcAjoutModalites\n#| echo: false\n#| fig-align: center\n#| fig-cap: Ajout de modalités supplémentaires sur le premier plan factoriel de l'AFC\n#| message: false\n#| out-width: \"75%\"\nres.afc2 <- CA(dfDonneesAFC, col.sup = 7:11, graph = FALSE)\nVP1pct <- tofr(round(res.afc2$eig[1,2],2))\nVP2pct <- tofr(round(res.afc2$eig[2,2],2))\nfviz_ca_col(res.afc2,\n repel = TRUE,\n geom= c(\"text\" , \"point\"),\n col.col = \"steelblue\",\n title = \"\",\n xlab=paste0(\"Axe 1 (\", VP1pct, \" %)\"),\n ylab=paste0(\"Axe 2 (\", VP2pct, \" %)\"))\n``` \n:::\n:::\n\n### Mise en œuvre dans R {#sec-1233}\n\n#### Calcul d’une AFC avec `FactoMineR` {#sec-12331}\n\nPlusieurs *packages* permettent de calculer une AFC dans R, notamment `ca` (fonction `ca`), `MASS` (fonction `corresp`), `ade4` (fonction `dudi.coa`) et `FactoMineR` (fonction `CA`). De nouveau, nous utilisons `FactoMineR` couplé au *package* `factoextra` pour réaliser rapidement des graphiques avec les résultats pour les variables et les coordonnées.\n\nPour calculer l'AFC, il suffit d'utiliser la fonction `CA` de `FactoMineR`, puis la fonction `summary(res.afc)`, qui renvoie les résultats de l'AFC pour : \n\n- Les valeurs propres (section `Eigenvalues`) pour les axes factoriels (`Dim.1` à `Dim.n`) avec leur variance expliquée brute (`Variance`), en pourcentage (`% of var.`) et en pourcentage cumulé (`Cumulative % of var.`).\n\n- Les dix premières observations (section `Rows`) avec les coordonnées factorielles (`Dim.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`). Pour accéder aux résultats pour toutes les observations, utilisez les fonctions `res.afc$row` ou encore `res.afc$row$coord` (uniquement les coordonnées factorielles), `res.afc$row$contrib` (uniquement les contributions) et `res.afc$row$cos2` (uniquement les cosinus carrés).\n\n- Les colonnes (section `Columns`) avec les coordonnées factorielles (D`im.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`).\n\n```{r}\n#| label: calculAFC\n#| echo: true\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n# Chargement des packages\nlibrary(FactoMineR)\nlibrary(factoextra)\n# Chargement des données\nload(\"data/analysesfactorielles/DonneesAFC.Rdata\")\n# Avant de calculer l'AFC, il convient de vérifier si les deux variables\n# qualitatives sont dépendantes avec le test du khi-deux\nkhideux <- chisq.test(dfDonneesAFC[,1:6])\nprint(khideux)\nif(khideux$p.value <=0.05){\n cat(\"La valeur de p < 0,05. Les variables sont dépendantes. Calculez l'AFC.\")\n}else {\n cat(\"La valeur de p > 0,05. Les variables sont indépendantes. Inutile de calculer l'AFC\")\n}\n\n# Calcul de l'analyse des correspondances sur les six premières variables\nres.afc <- CA(dfDonneesAFC[,1:6], graph = FALSE)\n# Affichage des résultats de la fonction CA\nprint(res.afc)\n# Visualisation des marges en colonne\nround(res.afc$call$marge.col,4)\n# Visualisation des marges en ligne. Étant donné que nous avons 521 individus, \n# la ligne ci-dessous est en commentaire\n# round(res.afc$call$marge.row,4)\n\n# Sommaire des résultats de l'AFC\n# Remarquez que la première ligne de ce sommaire est le résultat du khi-deux\nsummary(res.afc)\n\n```\n\n#### Exploration graphique des résultats de l'AFC avec `factoextra` {#sec-12332}\n\nComme pour l'ACP, `factoextra` dispose de plusieurs fonctions très intéressantes pour construire rapidement des graphiques avec les résultats de l'AFC. Premièrement, la syntaxe ci-dessous (avec la fonction `fviz_screeplot`) renvoie deux graphiques pour analyser les résultats des valeurs propres de l'AFC (@fig-factoextraAFC1).\n\n```{r}\n#| label: fig-factoextraAFC1\n#| echo: true\n#| fig-align: center\n#| fig-cap: Graphiques pour les valeurs propres de l'AFC avec factoextra\n#| message: false\n#| out-width: \"65%\"\nlibrary(factoextra)\nlibrary(ggplot2)\nlibrary(ggpubr)\n\n# Nombre de modalités en ligne et en colonne\nModalitesLig <- nrow(dfDonneesAFC)\nModalitesCol <- ncol(dfDonneesAFC[,1:6])\n# Critère statistique du profil moyen\ncritere2 <- round(1/(ModalitesCol-1)*100,2)\ntexte <- paste0(\"Critère pour le profil moyen : \", as.character(critere2), \" %\")\n# Graphique avec les valeurs propres\nG1 <- fviz_screeplot(res.afc, choice = \"eigenvalue\",\n ylab = \"Valeurs propres\",\n xlab = \"Axes factoriels\",\n main=\"Valeurs propres\")\nG2 <- fviz_screeplot(res.afc, choice = \"variance\", addlabels = TRUE, ylim = c(0, 70),\n ylab = \"Variance expliquée (%)\",\n xlab = \"Axes factoriels\",\n main=\"Valeurs propres (%)\")+\n geom_hline(yintercept=c2, linetype=1, color = \"red\", linewidth = 1)+\n annotate(geom = \"text\", x = ModalitesCol-.5,\n y = critere2+3, label=texte, \n color = \"red\", hjust=1, linewidth = 4)\nggarrange(G1, G2)\n```\n\nAvec les fonctions `fviz_contrib` et `fviz_cos2`, il est très facile de réaliser des histogrammes pour les contributions et les cosinus carrés pour les variables (colonnes) ou les individus (lignes), et ce, avec le paramètre `choice = c(\"row\", \"col\")` (@fig-acp1erplanfactVars2a).\n\n```{r}\n#| label: fig-acp1erplanfactVars2a\n#| echo: true\n#| fig-align: center\n#| fig-cap: Contributions des variables avec factoextra\n#| message: false\n#| out-width: \"65%\"\nlibrary(factoextra)\nlibrary(ggplot2)\nlibrary(ggpubr)\nVP1pct <- round(res.afc$eig[1,2],2)\nVP2pct <- round(res.afc$eig[2,2],2)\nG1 <- fviz_contrib (res.afc, choice = \"col\", axes = 1, title = \"Axe 1\")\nG2 <- fviz_contrib (res.afc, choice = \"col\", axes = 2, title = \"Axe 2\")\nggarrange(G1, G2, ncol = 2, nrow = 1)\n```\n\nQuant aux fonctions `fviz_ca_col` et `fviz_ca_row`, elles permettent rapidement de construire le premier plan factoriel pour les colonnes (variables) et les lignes (individus) (@fig-afc1erplanfactVars2b). Aussi, la fonction `fviz_ca_biplot` permet de construire un plan factoriel, mais avec les lignes et les colonnes simultanément.\n \n```{r}\n#| label: fig-afc1erplanfactVars2b\n#| echo: true\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'AFC pour les variables et les individus avec factoextra\n#| message: false\n#| out-width: \"65%\"\nG3 <- fviz_ca_col(res.afc,\n repel = TRUE,\n geom = c(\"text\" , \"point\"),\n col.col = \"steelblue\",\n title = \"Mode de transport\",\n xlab = paste0(\"Axe 1 (\", VP1pct, \" %)\"),\n ylab = paste0(\"Axe 2 (\", VP2pct, \" %)\"))\nG4 <- fviz_ca_row(res.afc,\n repel = TRUE,\n geom = c(\"point\"),\n col.row = \"steelblue\",\n title = \"Secteurs de recensement\",\n xlab = paste0(\"Axe 1 (\", VP1pct, \" %)\"),\n ylab = paste0(\"Axe 2 (\", VP2pct, \" %)\"))\nggarrange(G3, G4, ncol = 2, nrow = 1)\n```\n\n\nLa syntaxe ci-dessous permet d'ajouter des modalités supplémentaires dans l'AFC et de constuire le graphique du premier plan factoriel (@fig-afcAjoutModalites2).\n\n```{r}\n#| label: fig-afcAjoutModalites2\n#| echo: true\n#| fig-align: center\n#| fig-cap: Ajout de modalités supplémentaires sur le premier plan factoriel l'AFC avec factoextra\n#| message: false\n#| out-width: \"65%\"\n# Les colonnes 7 à 11 sont mises comme des variables supplémentaires dans l'AFC\nres.afc2 <- CA(dfDonneesAFC, col.sup = 7:11, graph = FALSE)\nVP1pct <- round(res.afc2$eig[1,2],2)\nVP2pct <- round(res.afc2$eig[2,2],2)\nfviz_ca_col(res.afc2,\n repel = TRUE,\n geom= c(\"text\" , \"point\"),\n col.col = \"steelblue\",\n title = \"\",\n xlab=paste0(\"Axe 1 (\", VP1pct, \" %)\"),\n ylab=paste0(\"Axe 2 (\", VP2pct, \" %)\"))\n``` \n\nFinalement, la syntaxe ci-dessous permet de cartographier les coordonnées factorielles des individus de l’AFC avec le *package* `tmap` (@fig-afc1erplanfactInds2B).\n \n\n```{r}\n#| label: fig-afc1erplanfactInds2B\n#| echo: true\n#| fig-align: center\n#| fig-cap: Cartographie de coordonnées factorielles des individus pour l'AFC\n#| message: false\n#| out-width: \"85%\"\nlibrary(tmap)\nlibrary(stringr)\ndfAFCInd <- data.frame(Coord = res.afc$row$coord, \n Cos2 = res.afc$row$cos2, \n Ctr = res.afc$row$contrib)\nnames(dfAFCInd) <- str_replace(names(dfAFCInd), \".Dim.\", \"Comp\")\nCartoAFC <- cbind(sfDonneesAFC, dfAFCInd)\nVP1pct <- tofr(round(res.afc$eig[1,2],2))\nVP2pct <- tofr(round(res.afc$eig[2,2],2))\nCarte1 <- tm_shape(CartoAFC) +\n tm_fill(col = \"CoordComp1\", style = \"cont\", midpoint = 0, title = \"Coordonnées\")+\n tm_layout(title = paste0(\"Axe 1 (\", VP1pct,\"%)\"), attr.outside = TRUE, frame = FALSE)\nCarte2 <- tm_shape(CartoAFC) +\n tm_fill(col = \"CoordComp2\", style = \"cont\", midpoint = 0, title = \"Coordonnées\")+\n tm_layout(title = paste0(\"Axe 2 (\", VP2pct,\"%)\"), attr.outside = TRUE, frame = FALSE)\ntmap_arrange(Carte1, Carte2, nrow = 1)\n``` \n\n\n## Analyse de correspondances multiples (ACM) {#sec-124}\n\nL'analyse des correspondances multiples (ACM) est particulièrement adaptée à l'exploration de données issues d'une enquête par sondage, puisqu'elle permet de résumer/synthétiser l'information d'un tableau comprenant uniquement des variables qualitatives (@fig-AnalysesFactoriellesTabACM). \n\n\n![Lieu de pèlerinage de R](images/Chap12/AnalysesFactoriellesTabACM.png){#fig-AnalysesFactoriellesTabACM width=\"60%\" fig-align=\"center\"}\n\nPar exemple, une enquête sur la mobilité d'une population donnée pourrait comprendre plusieurs variables qualitatives, dont celles reportées au @tbl-ACM1.\n\n```{r}\n#| label: tbl-ACM1\n#| tbl-cap: Exemple de variables qualitatives issues d'une enquête\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(kableExtra)\ntabacm <- data.frame(Modalite = c(\"Homme\" , \"Femme\", \n \"Moins de 20 ans\", \"20 à 39 ans\", \"40 à 59 ans\", \"60 ans et plus\",\n \"Automobile\", \"Transport en commun\", \"Marche\", \"Vélo\"),\n Code = c(1,2,1,2,3,4,1,2,3,4))\noptions(knitr.kable.NA = \"\")\nmontableau <- knitr::kable(tabacm, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Modalités des variables\" , \"Codage\"), align= c(\"l\", \"c\") )\n\ngroup_rows(montableau,\n index = c(\"Sexe\" = 2,\n \"Groupe d'âge\" = 4,\n \"Mode de transport\"= 4))\n```\n\nPour analyser de telles données, il suffit de transformer le tableau condensé (de données brutes) en un tableau disjonctif complet dans lequel chaque modalité des variables qualitatives devient une variable binaire prenant les valeurs de 0 ou 1 (tableaux [-@tbl-ACM2] et [-@tbl-ACM3]). Notez que la somme de chaque ligne est alors égale au nombre de variables qualitatives.\n\n```{r}\n#| label: tbl-ACM2\n#| tbl-cap: Tableau condensé (données brutes)\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(kableExtra)\ntabs <- data.frame(V1 = c(1,1,2,1,2,1),\n V2 = c(1,2,3,2,4,4),\n V3 = c(2,3,1,1,2,4))\n# Sexe\ntabs$Homme <- ifelse(tabs$V1 == 1, 1, 0)\ntabs$Femme <- ifelse(tabs$V1 == 2, 1, 0)\n# Age\ntabs$A20m <- ifelse(tabs$V2 == 1, 1, 0)\ntabs$A2039 <- ifelse(tabs$V2 == 2, 1, 0)\ntabs$A4059 <- ifelse(tabs$V2 == 3, 1, 0)\ntabs$A60p <- ifelse(tabs$V2 == 4, 1, 0)\n# Mode de transport\ntabs$Auto <- ifelse(tabs$V3 == 1, 1, 0)\ntabs$TC <- ifelse(tabs$V3 == 2, 1, 0)\ntabs$Apied <- ifelse(tabs$V3 == 3, 1, 0)\ntabs$Velo <- ifelse(tabs$V3 == 4, 1, 0)\nrownames(tabs) <- paste0(\"Ind. \", c(1:nrow(tabs)))\ntabCond <- tabs[,1:3]\noptions(knitr.kable.NA = \"\")\nknitr::kable(tabCond, \n row.names = TRUE,\n col.names = c(\"Sexe\" , \"Groupe d'âge\", \"Mode de transport\"), \n align= c(\"c\" , \"c\" , \"c\"),\n )\n```\n\n```{r}\n#| label: tbl-ACM3\n#| tbl-cap: Tableau disjonctif complet\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(kableExtra)\ntabDisjComplet <- tabs[,4:13]\ntabDisjComplet$Ind <- row.names(tabDisjComplet)\ntabDisjComplet <- tabDisjComplet[, c(11,1:10)]\n\noptions(knitr.kable.NA = \"\")\nmontableau <-knitr::kable(tabDisjComplet,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n \trow.names = FALSE,\n col.names = c(\"Individu\", \"Homme\" , \"Femme\", \n \"Moins de 20 ans\", \"20 à 39 ans\", \"40 à 59 ans\", \"60 ans et plus\",\n \"Auto.\", \"T.C.\", \"Marche\", \"Vélo\"), \n align= c(\"c\" , \"c\" , \"c\" , \"c\",\n \"c\" , \"c\" , \"c\" , \"c\")\n\t\t\t\t\t\t )\nadd_header_above(montableau, c(\" \" = 1,\"Sexe\" = 2, \"Groupe d'âge\" = 4, \"Mode de transport\" = 4))\n```\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**ACM versus AFC**\n:::\n::: bloc_astuce-body\nNous avons vu que l'AFC permet d'analyser un tableau de contingence avec deux variables qualitatives. En ACM, les colonnes sont les différentes modalités des variables qualitatives et les lignes sont les observations (par exemple, les individus ayant répondu à une enquête). En résumé, l'analyse des correspondances multiples (ACM) est simplement **une analyse des correspondances (AFC) appliquée sur un tableau disjonctif complet**. \n\nL'ACM permet ainsi de révéler les ressemblances entre les différentes modalités des variables qualitatives et les ressemblances entre les différents individus. Par conséquent, elle produit également des variables synthétiques (axes factoriels) résumant l'information contenue dans le tableau initial. L'évaluation de ces ressemblances et la détermination des axes factoriels sont aussi basées sur la **distance du khi-deux**.\n:::\n:::\n\n\n### Aides à l'interprétation {#sec-1241}\n\nPuisque l'ACM est une extension de l'AFC, nous retrouvons les mêmes aides à l'interprétation : les valeurs propres pour les axes, les coordonnées factorielles, les contributions et les cosinus carrés pour les variables et les individus. \n\nPour présenter l'ACM, nous utilisons des données ouvertes de la Ville de Montréal et, plus particulièrement, celles d'un [sondage auprès de la population de l’île de Montréal sur l'agriculture urbaine](https://www.donneesquebec.ca/recherche/dataset/vmtl-agriculture-urbaine-sondage){target='_blank'}. Pour ce faire, nous avons conservé uniquement les personnes pratiquant l'agriculture urbaine (n = 352). Les variables qualitatives extraites pour l'ACM sont reportées au @tbl-dataACM) avec la description des questions, leurs modalités respectives avec les effectifs bruts et en pourcentage. Au final, l'ACM est calculée de la manière suivante :\n\n- Neuf variables qualitatives relatives à la pratique de l'agriculture urbaine sont retenues (`q3`, `q4`, `q5`, `q8`, `q9`, `q10`, `q11`, `q12` et `q13`).\n\n- Quatre variables relatives au profil socioéconomique des personnes répondantes sont introduites comme variables supplémentaires (`q15`, `q16`, `q17` et `q21`).\n\n- Chaque ligne est pondérée avec la variable `pond`.\n\nL'objectif de cette ACM est double : \n\n1. Montrer les ressemblances entre les différentes modalités relatives à la pratique de l'agriculture urbaine. L'analyse des axes factoriels devrait nous permettre d'identifier différents profils des personnes pratiquant l'agriculture urbaine.\n\n2. Projeter les modalités des variables socioéconomiques afin de vérifier si elles sont ou non associées aux axes factoriels, c'est-à-dire aux différents profils révélés par les axes.\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Bloc attention**\n:::\n::: bloc_attention-body\nL'analyse du sondage sur l'agriculture urbaine réalisée ici est purement exploratoire : elle vise uniquement à démontrer que l'ACM est un outil particulièrement intéressant pour analyser les données d'un sondage. Par contre, cette analyse n'a aucune prétention scientifique puisque nous ne sommes pas des spécialistes de l'agriculture urbaine. Dans ce champ de recherche très fertile qu'est l'agriculture urbaine (surement pas la meilleure blague du livre...), vous pourrez consulter plusieurs études montréalaises [@mcclintock2018urban; @audate2021motivations; @bhatt2016cultivating].\n:::\n:::\n\n```{r}\n#| label: tbl-dataACM\n#| tbl-cap: Variables qualitatives extraites du sondage sur l'agriculture urbaine de la Ville de Montréal\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(kableExtra)\nload(\"data/analysesfactorielles/DonneesACM.Rdata\")\ndfACM <- dfenquete[, c(\"q3\", \"q4\", \"q5\", \"q8\", \"q9\", \"q10\", \"q11\", \"q12\", \"q13\",\n \"q15\", \"q16\", \"q17\", \"q21\")]\nquestions <- c(\n\"Q3. Depuis combien de temps cultivez-vous des fruits, des fines herbes ou des légumes?\",\n\"Q4. Selon vous, quelle proportion des fruits, des fines herbes et des légumes que vous consommez durant l'été provient de votre propre production?\",\n\"Q5. Utilisez-vous du compost provenant de vos déchets verts ou de vos déchets alimentaires pour faire pousser des fruits, des fines herbes ou des légumes?\",\n\"Q8. Récupérez-vous l'eau de pluie pour irriguer vos cultures de fruits, de fines herbes ou des légumes ou encore votre jardin?\",\n\"Q9. Combien de sortes de fruits, de fines herbes ou des légumes cultivez-vous?\",\n\"Q10. Cultivez-vous suffisamment de fruits, de fines herbes ou des légumes pour partager avec d'autres personnes?\",\n\"Q11. Échangez-vous vos semis ou vos récoltes de fruits, de fines herbes ou des légumes avec d'autres personnes?\",\n\"Q12. Selon vous, l'agriculture urbaine contribue-t-elle à améliorer les rapports entre les gens?\",\n\"Q13. Saviez-vous que la Ville de Montréal encourage et soutient l'agriculture urbaine sur l'île de Montréal?\",\n\"Q15. À quel groupe d'âge appartenez-vous?\",\n\"Q16. Quelle est votre occupation principale?\",\n\"Q17. Quel est le plus haut niveau de scolarité que vous avez complété?\",\n\"Q21. Êtes-vous propriétaire ou locataire de votre résidence ?\"\n)\n\nmodalites <- c()\nnmodalites <- c()\nnimodalites <- c()\ni <- 0\nfor (e in names(dfACM)){\n # Nombre de modalités par questions\n i <- i + 1\n nmodalites[i] <- length(unique(dfACM[[e]]))\n nimodalites <- append(nimodalites, table(dfACM[[e]]))\n modalites <- append(modalites, levels(dfACM[[e]]))\n}\n\nDesTabACM <- data.frame(Modalite = modalites, N = nimodalites, Pct = round(nimodalites/nrow(dfACM)*100,1))\n\noptions(knitr.kable.NA = \"\")\nmontableau <-knitr::kable(DesTabACM,\n row.names = FALSE,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"Modalité\", \"N\" , \"%\"),\n align= c(\"l\" , \"r\" , \"r\"))\n\ngroup_rows(montableau,\n index = c(\n \"Q3. Depuis combien de temps cultivez-vous des fruits, des fines herbes ou des légumes?\" = nmodalites[1],\n \"Q4. Selon vous, quelle proportion des fruits, des fines herbes et des légumes que vous consommez durant l'été provient de votre propre production?\" = nmodalites[2],\n \"Q5. Utilisez-vous du compost provenant de vos déchets verts ou alimentaires pour faire pousser des fruits, des fines herbes ou des légumes?\" = nmodalites[3],\n \"Q8. Récupérez-vous l'eau de pluie pour irriguer vos cultures de fruits, de fines herbes ou des légumes ou encore votre jardin?\" = nmodalites[4],\n \"Q9. Combien de sortes de fruits, de fines herbes ou de légumes cultivez-vous?\" = nmodalites[5],\n \"Q10. Cultivez-vous suffisamment de fruits, de fines herbes ou de légumes pour partager avec d'autres personnes?\" = nmodalites[6],\n \"Q11. Échangez-vous vos semis ou vos récoltes de fruits, de fines herbes ou de légumes avec d'autres personnes?\" = nmodalites[7],\n \"Q12. Selon vous, l'agriculture urbaine contribue-t-elle à améliorer les rapports entre les gens?\" = nmodalites[8],\n \"Q13. Saviez-vous que la Ville de Montréal encourage et soutient l'agriculture urbaine sur l'île de Montréal?\" = nmodalites[9],\n \"Q15. À quel groupe d'âge appartenez-vous?\" = nmodalites[10],\n \"Q16. Quelle est votre occupation principale?\" = nmodalites[11],\n \"Q17. Quel est le plus haut niveau de scolarité que vous avez complété?\" = nmodalites[12],\n \"Q21. Êtes-vous propriétaire ou locataire de votre résidence ?\" = nmodalites[13]\n))\n```\n \n \n#### Résultats de l'ACM pour les valeurs propres {#sec-12411}\n\nLes résultats pour les valeurs propres sont reportés au @tbl-ACMValeursPropresTab et à la @fig-ACMValeursPropresFig.\nEn ACM, l'inertie totale du tableau des variables qualitatives est égale au nombre moyen de modalités par variable moins un, soit $\\frac{K}{J}-1$ avec *K* et *J* étant respectivement les nombres de modalités et de variables. Aussi, le nombre d'axes produits par l'ACM est égal à $K - J$. Pour notre tableau, l'inertie est donc égale à $\\mbox{25} / \\mbox{9} = \\mbox{1,77}$ avec $\\mbox{25}-\\mbox{9} = \\mbox{16}$ axes. Le nombre d'axes à retenir est souvent plus difficile à déterminer puisque, tel que signalé judicieusement par Jérôme Pagès [-@pages2002analyse, p.53] : « en pratique, comparée à l'ACP, l'ACM conduit, dans l'ensemble à : des pourcentages d'inertie plus petits; une décroissance de ces pourcentages plus douce ».\n\nL'histogramme des valeurs propres (@fig-ACMValeursPropresFig) révèle plusieurs sauts importants dans les valeurs propres qui pourraient justifier le choix du nombre d'axes factoriels, soit aux axes 1, 2, 3 et 6. Pour l'exercice, nous retenons les trois premiers axes qui résument 30 % de l'inertie du tableau initial.\n\n```{r}\n#| label: tbl-ACMValeursPropresTab\n#| tbl-cap: Résultats de l'ACM pour les valeurs propres\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(FactoMineR)\n# Calcul de l'AFC\nres.acm <- MCA(dfACM, ncp = 5, quali.sup=10:13, graph = FALSE, row.w = dfenquete$pond)\n\n# Construction d'un DataFrame pour les valeurs propres\ndfACMvp <- data.frame(res.acm$eig)\nnames(dfACMvp) <- c(\"VP\" , \"VP_pct\" , \"VP_pctCumul\")\ndfACMvp$Axe <- factor(1:nrow(dfACMvp), levels = rev(1:nrow(dfACMvp)))\ndfACMvp <- dfACMvp[, c(4,1:3)]\n\noptions(knitr.kable.NA = \"\")\nknitr::kable(dfACMvp,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t digits = 3,\n col.names = c(\"Axe factoriel\" , \"Valeur propre\" , \"Pourcentage\", \"Pourc. cumulé\"),\n align= c(\"r\", \"r\" , \"r\", \"r\")\n )\n```\n\n```{r}\n#| label: fig-ACMValeursPropresFig\n#| echo: false\n#| fig-align: center\n#| fig-cap: Graphiques pour les valeurs propres pour l'ACM\nlibrary(ggplot2)\nlibrary(ggpubr)\ng1 <- ggplot(dfACMvp, aes(x = VP, y = Axe))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"skyblue2\")+\n labs(x = \"Valeur propre\", y = \"Axe factoriel\")\ng2 <- ggplot(dfACMvp, aes(x = VP_pct, y = Axe))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"skyblue2\")+\n theme(legend.position = \"none\")+\n labs(x = \"Variance expliquée (%)\", y = \"\")\ng3 <- ggplot(dfACMvp, aes(x = VP_pctCumul, y = Axe, group=1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"skyblue2\")+\n geom_line(colour = \"brown\", linetype = \"solid\", size=.8) +\n geom_point(size=3, shape=21, color = \"brown\", fill = \"brown\")+\n theme(legend.position = \"none\")+\n labs(x = \"Variance expliquée (% cumulé)\", y = \"Axe factoriel\")\nggarrange(g2, g3, nrow = 2)\n```\n\n#### Résultats de l'ACM pour les modalités des variables {#sec-12412}\n\nÀ titre de rappel, comme pour l’ACP et l'AFC, nous retrouvons les trois mêmes mesures pour les variables et les individus (coordonnées factorielles, contributions et cosinus carrés). Plus les variables qualitatives du jeu de données comprennent de modalités, plus la taille du tableau des résultats des modalités est importante et plus il est fastidieux de l'analyser. Il est donc recommandé de construire des histogrammes avec les coordonnées factorielles et les contributions des modalités, mais aussi un nuage de points avec les coordonnées des modalités des variables qualitatives sur le premier, voire le deuxième plan factoriel.\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Compréhension des axes factoriels de l'ACM : une étape essentielle, incontournable...**\n:::\n::: bloc_objectif-body\nComme en ACP et en AFC, l'analyse des trois mesures (coordonnées, contributions et cosinus carrés) pour les variables et les individus doit vous permettre de comprendre la signification des axes factoriels retenus de l'ACM. Prenez le temps de bien réaliser cette étape d'interprétation souvent plus fastidieuse qu'en ACP et ACM, en raison du nombre élevé de modalités. Cette étape est en effet essentielle afin de qualifier les variables latentes (axes factoriels, variables synthétiques) produites par l'ACM.\n:::\n:::\n\nLes résultats pour les variables sont reportés 1) au @tbl-ACMValeursCoordTab, 2) aux figures [-@fig-ACMValeursCoordFig1], [-@fig-ACMValeursCoordFig2] et [-@fig-ACMValeursCoordFig3] pour les coordonnées et les contributions et à la [-@fig-ACMValeursPlanFacto1] pour le premier plan factoriel.\n\n\n**Interprétation des résultats de l'axe 1 pour les variables**\n\nSept modalités concourent le plus à la formation de l'axe 1 résumant 13,9 % de la variance : `Q9. 10 à 14 sortes` (10,35 %), `Q10. Oui`\t(9,99 %), `Q9. Moins de 5 sortes` (9,71 %), `Q5. Oui`\t(9,19 %), `Q11. Oui` (8,20 %), `Q4. Moins de 10%`\t(7,87 %) et `Q10. Non` (7,10 %). Aussi, les modalités suivantes sont aux deux extrémités de cet axe :\n\n* **Coordonnées négatives** : `Q12. Non` (-0,84), `Q3. Moins de 1 an` (-0,73), `Q9. Moins de 5 sortes` (-0,67), `Q4. Moins de 10%` (-0,56), `Q10. Non` (-0,521). Cela signifie que lorsque les coordonnées des individus sont fortement négatives sur cet axe, les personnes pratiquant l'agriculture urbaine : \n + *ne pensent pas que l'agriculture urbaine contribue à améliorer les rapports entre les gens* (`Q12`);\n + *cultivent des fruits, des fines herbes ou de légumes depuis moins d'un an* (`Q3`);\n + *cultivent moins de cinq sortes de fruits, de fines herbes ou de légumes* (`Q9`);\n + *moins de 10 % de la proportion des fruits, des fines herbes et des légumes consommés durant l’été provient de leur propre production *(`Q4`);\n + *ne cultivent pas suffisamment pour partager avec d'autres personnes* (`Q10`).\n \n* **Coordonnées positives** : `Q9. 15 sortes ou plus` (1,36), `Q9. 10 à 14 sortes` (1,28), `Q5. Oui` (0,95) et `Q11. Oui` (0,85). Cela signifie que lorsque les coordonnées des individus sont fortement positives sur cet axe, les personnes pratiquant l'agriculture urbaine :\n + *cultivent plus de dix sortes de fruits, de fines herbes ou de légumes* (`Q9`);\n + *utilisent du compost provenant de leurs déchets verts ou de leurs déchets alimentaires pour faire pousser des fruits, des fines herbes ou de légumes* (`Q5`);\n + *échangent leurs semis ou leurs récoltes de fruits, de fines herbes ou des légumes avec d’autres personnes* (`Q11`).\n\nEn résumé, l'axe 1 oppose clairement les **néophytes en agriculture** versus les **personnes expérimentées** cultivant des fruits et de légumes variés avec leur propre compost et échangeant leurs semis ou leurs récoltes.\n\n\n```{r}\n#| label: tbl-ACMValeursCoordTab\n#| tbl-cap: Résultats de l'ACM pour les modalités des variables\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(kableExtra)\nlibrary(stringr)\nnAxes <- 3\ndfmodalites <- data.frame(Modalite =rownames(res.acm$var$coord),\n Coord = round(res.acm$var$coord[, 1:nAxes],2),\n ctr = round(res.acm$var$contrib[, 1:nAxes],2),\n Cos2 = round(res.acm$var$cos2[, 1:nAxes],2))\nrownames(dfmodalites) <- 1:nrow(dfmodalites)\nnames(dfmodalites) <- str_replace(names(dfmodalites), \".Dim.\", \"F\")\n\noptions(knitr.kable.NA = \"\")\nmontableau <- knitr::kable(dfmodalites,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t\t row.names = FALSE,\n digits = 2,\n col.names = c(\"Modalité\" , \"1\" , \"2\" , \"3\" , \"1\" , \"2\" , \"3\" , \"1\" , \"2\" , \"3\"),\n align= c(\"l\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\")\n )\nadd_header_above(montableau, c(\" \" = 1, \"Coordonnées\" = 3, \"Cosinus carrés\" = 3, \"Contributions (%)\" = 3))\n```\n\n```{r}\n#| label: fig-ACMValeursCoordFig1\n#| echo: false\n#| fig-align: center\n#| fig-cap: Graphiques pour les résultats des modalités de l'axe 1 de l'ACM\n#| out-width: \"90%\"\n# Histogrammes pour les coordonnées des modalités\ncouleursCoords <- c(\"lightsalmon\" , \"steelblue\")\nplotCoordF1 <- ggplot(dfmodalites,\n aes(y = reorder(Modalite, CoordF1),\n x = CoordF1, fill = CoordF1<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords,\n labels = c(\"Positive\" , \"Négative\"))+\n labs(x = \"Coordonnées sur l'axe 1\", y = \"Modalité\")+\n theme(legend.position = \"none\", axis.text.y = element_text(size = 7))\n\nplotCoordF2 <- ggplot(dfmodalites,\n aes(y = reorder(Modalite, CoordF2),\n x = CoordF2, fill = CoordF2<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords,\n labels = c(\"Positive\" , \"Négative\"))+\n labs(x = \"Coordonnées sur l'axe 2\", y = \"Modalité\")+\n theme(legend.position = \"none\", axis.text.y = element_text(size = 7))\n\nplotCoordF3 <- ggplot(dfmodalites,\n aes(y = reorder(Modalite, CoordF3),\n x = CoordF3, fill = CoordF3<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\", values = couleursCoords,\n labels = c(\"Positive\" , \"Négative\"))+\n labs(x = \"Coordonnées sur l'axe 3\", y = \"Modalité\")+\n theme(legend.position = \"none\", axis.text.y = element_text(size = 7))\n\n\nplotCtrF1 <- ggplot(dfmodalites, aes(y = reorder(Modalite, ctrF1), x = ctrF1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"steelblue\")+\n labs(x = \"Contributions sur l'axe 1\", y = \"Modalité\")+\n theme(legend.position = \"none\", axis.text.y = element_text(size = 7))\n\nplotCtrF2 <- ggplot(dfmodalites, aes(y = reorder(Modalite, ctrF2), x = ctrF2))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"steelblue\")+\n labs(x = \"Contributions sur l'axe 2\", y = \"Modalité\")+\n theme(legend.position = \"none\",\n axis.text.y = element_text(size = 7))\n\nplotCtrF3 <- ggplot(dfmodalites, aes(y = reorder(Modalite, ctrF3), x = ctrF3))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"steelblue\")+\n labs(x = \"Contributions sur l'axe 3\", y = \"Modalité\")+\n theme(legend.position = \"none\", axis.text.y = element_text(size = 7))\n\nggarrange(plotCoordF1, plotCtrF1, ncol = 1, nrow = 2)\n```\n\n\n**Interprétation des résultats de l'axe 2 pour les variables**\n\nQuatre modalités concourent le plus à la formation de l'axe 2 résumant 8,8 % de la variance : `Q3. De 1 à 4 ans` (15,30 %), `Q9. 15 sortes ou plus`\t(14,42 %), `Q11. Oui`\t(12,45 %) et `Q9. 10 à 14 sortes`\t(9,42 %). Les modalités suivantes sont présentes aux deux extrémités de l'axe 2 :\n\n- **Coordonnées négatives** : `Q9. 10 à 14 sortes` (-0,97), `Q11. Oui` (-0,83), `Q3. De 1 à 4 ans` (-0,79), `Q4. 10 à 25%` (-0,76). Cela signifie que lorsque les coordonnées des individus sont fortement négatives sur cet axe, les personnes pratiquant l'agriculture urbaine : \n + *cultivent de 10 à 14 sortes de fruits, de fines herbes ou de légumes* (`Q9`); \n + *échangent leurs semis ou leurs récoltes de fruits, de fines herbes ou de légumes avec d’autres personnes* (`Q11`);\n + *cultivent des fruits, des fines herbes ou des légumes depuis 1 à 4 ans* (`Q3`);\n + *de 10 à 25 % de la proportion des fruits, des fines herbes et des légumes consommés durant l’été provient de leur propre production *(`Q4`).\n\n- **Coordonnées positives** : seule la modalité `Q9. 15 sortes ou plus` (2,15) présente une forte coordonnée positive.\n\n**En résumé, l'axe 2** permet surtout d'identifier des personnes pratiquant l'agriculture urbaine depuis quelques années (de 1 à 4 ans), mais cultivant déjà de nombreuses sortes de fruits et légumes et partageant aussi leurs semis ou récoltes.\n\n\n```{r}\n#| label: fig-ACMValeursCoordFig2\n#| echo: false\n#| fig-align: center\n#| fig-cap: Graphiques pour les résultats des modalités de l'axe 2 de l'ACM\n#| out-width: \"90%\"\n# Histogrammes pour les coordonnées des modalités\nggarrange(plotCoordF2, plotCtrF2, ncol = 1, nrow = 2)\n```\n\n```{r}\n#| label: fig-ACMValeursPlanFacto1\n#| fig-cap: Premier plan factoriel de l'ACM pour les modalités\n#| fig-align: center\n#| echo: false\n#| out-width: \"75%\"\nres.acm2 <- MCA(dfACM[1:9], ncp = 3, graph = FALSE, row.w = dfenquete$pond)\nfviz_mca_var(res.acm2, repel = TRUE,\n choice = \"var.cat\",\n axes = c(1, 2),\n # col.var = \"black\",\n title = \"\", xlab = \"Axe 1\", ylab = \"Axe 2\",\n ggtheme = theme_minimal ())\n```\n\n**Interprétation des résultats de l'axe 3 pour les variables**\n\nTrois modalités concourent le plus à la formation de l'axe 3 résumant 7,6 % de la variance : `Q8. Oui` (23,31), `Q3. De 5 à 9 ans` (19,43) et `Q9. 5 à 9 sortes` (17,31). Les modalités suivantes sont présentes aux deux extrémités de l'axe 3 :\n\n- **Coordonnées négatives** : `Q3. De 5 à 9 ans` (-1,11), `Q9. 5 à 9 sortes` (-0,79). \n- **Coordonnées positives** : seule la modalité `Q8. Oui` présente une coordonnée fortement positive (1,21).\n\nPar conséquent, cet axe semble plus complexe à analyser et surtout moins intéressant que les deux premiers.\n\n\n```{r}\n#| label: fig-ACMValeursCoordFig3\n#| fig-cap: Graphiques pour les résultats des modalités de l'axe 3 de l'ACM\n#| echo: false\n#| fig-align: center\n#| out-width: \"100%\"\n# Histogrammes pour les coordonnées des modalités\nggarrange(plotCoordF3, plotCtrF3, ncol = 1, nrow = 2)\n```\n\n\n**Analyse des variables supplémentaires dans l'ACM**\n\nIl est ensuite possible de projeter les modalités supplémentaires sur les axes de l'ACM retenus (@tbl-ACMValeursCoordSuppl et @fig-ACMValeursPlanFactoSupp1). Les faibles valeurs des coordonnées factorielles des modalités supplémentaires sur les deux axes semblent indiquer que le profil socioéconomique des personnes pratiquant l'agriculture urbaine ne semble pas (ou peu) relié aux profils identifiés par les axes factoriels.\n\n```{r}\n#| label: tbl-ACMValeursCoordSuppl\n#| tbl-cap: Résultats de l'ACM pour les modalités des variables supplémentaires\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(kableExtra)\nlibrary(stringr)\nnAxes <- 2\ndfmodalsuppl <- data.frame(Modalite =rownames(res.acm$quali.sup$coord),\n Coord = round(res.acm$quali.sup$coord[, 1:nAxes],2),\n cos2 = round(res.acm$quali.sup$cos2[, 1:nAxes],2))\nrownames(dfmodalsuppl) <- 1:nrow(dfmodalsuppl)\nnames(dfmodalsuppl) <- str_replace(names(dfmodalsuppl), \".Dim.\", \"F\")\n\noptions(knitr.kable.NA = \"\")\nmontableau <- knitr::kable(dfmodalsuppl,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t\t\t row.names = FALSE,\n\t\t\t\t\t digits = 2,\n col.names = c(\"Modalité\" , \"1\" , \"2\" , \"1\" , \"2\"),\n align= c(\"l\" , \"r\" , \"r\" , \"r\" , \"r\")\n )\nadd_header_above(montableau, c(\" \" = 1, \"Coordonnées\" = 2, \"Cosinus carrés\" = 2))\n```\n\n```{r}\n#| label: fig-ACMValeursPlanFactoSupp1\n#| echo: false\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'ACM avec toutes les modalités incluant celles supplémentaires\n#| message: false\n#| warning: false\nfviz_mca_var(res.acm, repel = TRUE,\n choice = \"var.cat\",\n axes = c(1, 2),\n col.var = \"gray23\",\n col.quali.sup = \"darkred\",\n labelsize = 3,\n title = \"\", xlab = \"Axe 1\", ylab = \"Axe 2\", \n ggtheme = theme_minimal ())\n```\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Visualisation de variables qualitatives ordinales sur un plan factoriel**\n:::\n::: bloc_astuce-body\nLorsque les variables qualitatives sont ordinales et non nominales, il peut être intéressant de relier les différentes modalités avec une ligne. Cela permet de comprendre en un coup d'œil la trajectoire que suivent les modalités sur les deux axes factoriels. En guise d'exemple, nous réalisons cet exercice pour les variables `Q3` et `Q9` (@fig-ACMordinaleTrajectoire).\n\n```{r}\n#| label: fig-ACMordinaleTrajectoire\n#| fig-cap: Trajectoires des variables ordinales sur le premier plan factoriel de l'ACM\n#| echo: false\n#| fig-align: center\n#| out-width: \"70%\"\nlibrary(ggpubr)\nQ3 <- dfmodalites[1:4, 1:3]\nQ9 <- dfmodalites[13:16, 1:3]\nG1 <- ggplot(Q3, aes(x = CoordF1, y = CoordF2, label=Modalite))+\n xlim(-1, .75)+ylim(-1, 1)+\n labs(title = \"Q3. Depuis combien de temps cultivez-vous \\ndes fruits, des fines herbes ou des légumes?\",\n x = \"Axe 1\", y = \"Axe 2\")+\n geom_label(nudge_x=0, nudge_y = 0.07) +\n geom_line( color = \"black\", linewidth = .2)+\n geom_point(shape=21, color = \"black\", fill = \"steelblue\", size=4)\nG2 <- ggplot(Q9, aes(x = CoordF1, y = CoordF2, label=Modalite))+\n xlim(-1, 1.75)+ylim(-1, 2.3)+\n labs(title = \"Q9. Combien de sortes de fruits, de fines \\nherbes ou des légumes cultivez-vous?\",\n x = \"Axe 1\", y = \"Axe 2\")+\n geom_label(nudge_x=0, nudge_y = 0.07) +\n geom_line( color = \"black\", linewidth = .2)+\n geom_point(shape=21, color = \"black\", fill = \"steelblue\", size=4)\nggarrange(G1, G2, nrow = 2)\n```\n:::\n:::\n\n#### Résultats de l'ACM pour les individus {#sec-12413}\n\nComme toute méthode factorielle, les coordonnées factorielles, les cosinus carrés et les contributions sont aussi disponibles pour les individus en ACM. Nous proposons ici simplement de réaliser le premier plan factoriel pour les individus en attribuant un dégradé de couleurs avec les cosinus carrés (@fig-ACMPlanFacto12Ind1). Il est aussi possible d'attribuer des couleurs aux différentes modalités d'une variable. Par exemple, sur le premier plan factoriel, nous avons utilisé la variable `Q12. Selon vous, l’agriculture urbaine contribue-t-elle à améliorer les rapports entre les gens?`. Cela permet de repérer visuellement que les personnes ayant répondu négativement à cette question ont surtout des coordonnées négatives sur l'axe 1.\n\n```{r}\n#| label: fig-ACMPlanFacto12Ind1\n#| echo: false\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'ACM pour les individus\n#| message: false\n#| warning: false\n#| out-width: \"100%\"\nfviz_mca_ind(res.acm, col.ind = \"cos2\",\n gradient.cols = c(\"#00AFBB\", \"#E7B800\", \"#FC4E07\"),\n repel = TRUE,\n xlab = \"Axe 1\", ylab = \"Axe 2\", title = \"\",\n ggtheme = theme_minimal())\n```\n\n```{r}\n#| label: fig-ACMPlanFacto12Ind2\n#| echo: false\n#| message: false\n#| warning: false\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'ACM pour les individus avec coloration d'une variable\n#| out-width: \"100%\"\nfviz_mca_ind (res.acm,\n label = \"none\",\n habillage = \"q12\", # colorer par groupes\n xlab = \"Axe 1\", ylab = \"Axe 2\", title = \"\",\n palette = c (\"darkred\", \"steelblue\", \"gray23\"),\n ggtheme = theme_minimal ())\n```\n\n### Mise en œuvre dans R {#sec-1242}\n\n#### Calcul d’une ACM avec `FactoMineR` {#sec-12421}\n\nPlusieurs *packages* permettent de calculer une ACM dans R, notamment `ExPosition` (fonction `epMCA`), `ade4` (fonction `dudi.mca`) et `FactoMineR` (fonction `MCA`). De nouveau, nous utilisons `FactoMineR` couplé au *package* `factoextra` pour réaliser rapidement des graphiques.\n\nPour calculer l'ACM, il suffit d'utiliser la fonction `MCA` de `FactoMineR`, puis la fonction `summary(res.acm)` qui renvoie les résultats de l'ACM pour : \n\n- Les valeurs propres (section `Eigenvalues`) pour les axes factoriels (`Dim.1` à `Dim.n`) avec leur variance expliquée brute (`Variance`), en pourcentage (`% of var.`) et en pourcentage cumulé (`Cumulative % of var.`).\n\n- Les dix premières observations (section `Individuals`) avec les coordonnées factorielles (`Dim.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`). Pour accéder aux résultats pour toutes les observations, utilisez les fonctions `res.acm$ind` ou encore `res.acm$ind$coord` (uniquement les coordonnées factorielles), `res.acm$ind$contrib` (uniquement les contributions) et `res.acm$ind$cos2` (uniquement les cosinus carrés).\n\n- Les dix premières modalités des variables (section `Categories`) avec les coordonnées factorielles (D`im.1` à `Dim.n`), les contributions (`ctr`) et les cosinus carrés (`cos2`).\n\nLa syntaxe ci-dessous permet, dans un premier temps, de calculer l'ACM, puis de créer un *DataFrame* pour les résultats des valeurs propres.\n\n```{r}\n#| label: ACMCodePartie1VPa\n#| echo: true\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nlibrary(FactoMineR)\n# Calcul de l'AFC\nres.acm <- MCA(dfACM, # Nom du DataFrame\n ncp = 3, # Nombre d'axes retenus\n quali.sup=10:13, # Variables supplémentaires\n graph = FALSE, \n row.w = dfenquete$pond) # Variables pour la pondération des lignes\n# Affichage des résultats\nprint(res.acm)\nsummary(res.acm)\n# Construction d'un DataFrame pour les valeurs propres\ndfACMvp <- data.frame(res.acm$eig)\nnames(dfACMvp) <- c(\"VP\" , \"VP_pct\" , \"VP_pctCumul\")\ndfACMvp$Axe <- factor(1:nrow(dfACMvp), levels = rev(1:nrow(dfACMvp)))\ndfACMvp <- dfACMvp[, c(4,1:3)]\n```\n\n#### Exploration graphique des résultats de l'ACM pour les valeurs propres {#sec-124212}\n\nPour créer un histogramme des valeurs propres de l'ACM, vous pouvez utiliser la fonction `fviz_screeplot` de `factoextra`.\n\n```{r}\n#| label: fig-ACMCodePartie1VPb\n#| echo: true\n#| fig-align: center\n#| fig-cap: Graphique pour les valeurs propres de l'ACM avec factoextra\n#| message: false\n#| out-width: \"75%\"\n\nlibrary(factoextra)\nlibrary(ggplot2)\n\nfviz_screeplot(res.acm, addlabels = TRUE,\n x = \"Composantes\", y = \"Valeur propre\", title = \"\")\n```\n\nAvec un peu plus de lignes de code, il est relativement facile d'exploiter le *DataFrame* des valeurs propres créé précédemment (`dfACMvp`) pour construire des graphiques plus personnalisés.\n\n```{r}\n#| label: fig-ACMCodePartie1VPc\n#| echo: true\n#| fig-align: center\n#| fig-cap: Graphiques pour les valeurs propres de l'ACM avec factoextra\n#| message: false\n#| out-width: \"75%\"\nlibrary(factoextra)\nlibrary(ggplot2)\n\ncouleursAxes <- c(\"steelblue\" , \"skyblue2\")\ng1 <- ggplot(dfACMvp, aes(x = VP, y = Axe))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"skyblue2\")+\n labs(x = \"Valeur propre\", y = \"Axe factoriel\")\ng2 <- ggplot(dfACMvp, aes(x = VP_pct, y = Axe))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"skyblue2\")+\n theme(legend.position = \"none\")+\n labs(x = \"Variance expliquée (%)\", y = \"Axe factoriel\")\ng3 <- ggplot(dfACMvp, aes(x = VP_pctCumul, y = Axe, group=1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"skyblue2\")+\n geom_line(colour = \"brown\", linetype = \"solid\", size=.8) +\n geom_point(size=3, shape=21, color = \"brown\", fill = \"brown\")+\n theme(legend.position = \"none\")+\n labs(x = \"Variance expliquée (% cumulé)\", y = \"Axe factoriel\")\nggarrange(g2, g3, nrow = 2)\n```\n\nLa syntaxe ci-dessous permet de construire un tableau avec les coordonnées factorielles, les cosinus carrés et les contributions pour les modalités des variables qualitatives.\n\n\n```{r}\n#| label: ACMCodePartie2a\n#| echo: true\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nlibrary(stringr)\nnAxes <- 3\ndfmodalites <- data.frame(Modalite =rownames(res.acm$var$coord),\n Coord = round(res.acm$var$coord[, 1:nAxes],3),\n Cos2 = round(res.acm$var$cos2[, 1:nAxes],3),\n ctr = round(res.acm$var$contrib[, 1:nAxes],3))\nrownames(dfmodalites) <- 1:nrow(dfmodalites)\nnames(dfmodalites) <- str_replace(names(dfmodalites), \".Dim.\", \"F\")\n```\n\n\n#### Exploration graphique des résultats de l'ACM pour les modalités {#sec-124213}\n\nAvant d'explorer graphiquement les résultats pour les modalités, il est judicieux de construire un *DataFrame* avec les coordonnées factorielles, les contributions et les cosinus carrés des modalités (voir la syntaxe ci-dessous).\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nlibrary(kableExtra)\nlibrary(stringr)\nnAxes <- 3\ndfmodalites <- data.frame(Modalite =rownames(res.acm$var$coord),\n Coord = round(res.acm$var$coord[, 1:nAxes],2),\n ctr = round(res.acm$var$contrib[, 1:nAxes],2),\n Cos2 = round(res.acm$var$cos2[, 1:nAxes],2))\nrownames(dfmodalites) <- 1:nrow(dfmodalites)\nnames(dfmodalites) <- str_replace(names(dfmodalites), \".Dim.\", \"F\")\n```\n\nPlusieurs fonctions très faciles à utiliser de `factoextra` permettent de construire rapidement des graphiques : `fviz_mca_var` pour un nuage de points d'un plan factoriel, `fviz_cos2` et `fviz_contrib` (en utilisant le paramètre `choice=var.cat`) pour des histogrammes avec les cosinus carrés et les contributions des modalités.\n\nIl est aussi possible de créer vos propres graphiques avec `ggplot2` en utilisant le *DataFrame* créé précédemment avec les modalités. Par exemple, la syntaxe ci-dessous renvoie deux histogrammes pour l'axe 1 : l'un avec les coordonnées, l'autre avec les contributions. Dans la syntaxe, repérez le terme `CoordF1`. Dupliquez la syntaxe et changez ce terme pour `CoordF2` et `CoordF3` pour réaliser les graphiques des axes 2 et 3.\n\n```{r}\n#| label: fig-ACMMiseEnOeuvreVars1\n#| echo: true\n#| fig-align: center\n#| fig-cap: Exemple de graphiques pour les résultats des modalités\n#| out-width: \"100%\"\n# Histogrammes pour les coordonnées des modalités\ncouleursCoords <- c(\"lightsalmon\" , \"steelblue\")\nplotCoordF1 <- ggplot(dfmodalites,\n aes(y = reorder(Modalite, CoordF1),\n x = CoordF1, fill = CoordF1<0))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\")+\n geom_vline(xintercept = 0, color = \"black\", linewidth = 1)+\n scale_fill_manual(name = \"Coordonnée\" , values = couleursCoords,\n labels = c(\"Positive\" , \"Négative\"))+\n labs(x = \"Coordonnées sur l'axe 1\", y = \"Modalité\")+\n theme(legend.position = \"none\", axis.text.y = element_text(size = 7))\n\nplotCtrF1 <- ggplot(dfmodalites, aes(y = reorder(Modalite, ctrF1), x = ctrF1))+\n geom_bar(stat = \"identity\", width = .6, alpha = .8, color = \"black\", fill = \"steelblue\")+\n labs(x = \"Contributions sur l'axe 1\", y = \"Modalité\")+\n theme(legend.position = \"none\", axis.text.y = element_text(size = 7))\n\nggarrange(plotCoordF1, plotCtrF1, ncol = 1, nrow = 2)\n```\n\nLa syntaxe suivante permet de construire le premier plan factoriel pour les modalités avec la fonction `fviz_mca_var` de `factoextra` (@fig-ACMMiseEnOeuvreVars2).\n\n```{r}\n#| label: fig-ACMMiseEnOeuvreVars2\n#| echo: true\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'ACM pour les modalités\n#| out-width: \"75%\"\nres.acm2 <- MCA(dfACM[1:9], ncp = 3, graph = FALSE, row.w = dfenquete$pond)\nfviz_mca_var(res.acm2, repel = TRUE,\n choice = \"var.cat\",\n axes = c(1, 2),\n # col.var = \"black\",\n title = \"\", xlab = \"Axe 1\", ylab = \"Axe 2\",\n ggtheme = theme_minimal ())\n```\n\nLa syntaxe suivante permet de construire le premier plan factoriel pour les modalités supplémentaires avec la fonction `fviz_mca_var` de `factoextra` (@fig-ACMMiseEnOeuvreVars3).\n\n```{r}\n#| label: fig-ACMMiseEnOeuvreVars3\n#| echo: true\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'ACM pour les modalités supplémentaires\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nfviz_mca_var(res.acm, repel = TRUE,\n choice = \"var.cat\",\n axes = c(1, 2),\n col.var = \"gray23\",\n col.quali.sup = \"darkred\",\n labelsize = 3,\n title = \"\", xlab = \"Axe 1\", ylab = \"Axe 2\", \n ggtheme = theme_minimal ())\n```\n\nFinalement, la syntaxe ci-dessous renvoie un graphique avec la trajectoire de la variable `Q3` (@fig-ACMMiseEnOeuvreVars4).\n\n```{r}\n#| label: fig-ACMMiseEnOeuvreVars4\n#| echo: true\n#| fig-align: center\n#| fig-cap: Trajectoires des variables ordinales sur le premier plan factoriel de l'ACM\n#| out-width: \"70%\"\nlibrary(ggpubr)\nQ3 <- dfmodalites[1:4, 1:3]\nggplot(Q3, aes(x = CoordF1, y = CoordF2, label=Modalite))+\n xlim(-1, .75)+ylim(-1, 1)+\n labs(title = \"Q3. Depuis combien de temps cultivez-vous \\n\n des fruits, des fines herbes ou des légumes?\",\n x = \"Axe 1\", y = \"Axe 2\")+\n geom_label(nudge_x=0, nudge_y = 0.07) +\n geom_line( color = \"black\", linewidth = .2)+\n geom_point(shape=21, color = \"black\", fill = \"steelblue\", size=4)\n```\n\n#### Exploration graphique des résultats de l'ACM pour les individus {#sec-124214}\n\nD'autres fonctions de `factoextra` produisent rapidement des graphiques pour les individus :\n\n- `fviz_cos2` et `fviz_contrib` (en utilisant le paramètre `choice=ind`) pour construire des histogrammes pour les cosinus carrés et les contributions des individus.\n- `fviz_mca_ind` pour un nuage de points d'un plan factoriel (axes 1 et 2 habituellement).\n\nLa syntaxe ci-dessous produit le premier axe factoriel pour les individus (@fig-ACMPlanFactoInd1Facto).\n\n```{r}\n#| label: fig-ACMPlanFactoInd1Facto\n#| echo: true\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'ACM pour les individus avec factoextra\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nfviz_mca_ind(res.acm, col.ind = \"cos2\",\n gradient.cols = c(\"#00AFBB\", \"#E7B800\", \"#FC4E07\"),\n repel = TRUE,\n xlab = \"Axe 1\", ylab = \"Axe 2\", title = \"\",\n ggtheme = theme_minimal())\n```\n\nLa syntaxe ci-dessous produit aussi le premier plan factoriel pour les individus, mais en attribuant une couleur différente aux modalités de la variable `q12` (@fig-ACMPlanFactoInd2Facto).\n\n```{r}\n#| label: fig-ACMPlanFactoInd2Facto\n#| echo: true\n#| fig-align: center\n#| fig-cap: Premier plan factoriel de l'ACM pour les individus avec coloration d'une variable avec factoextra\n#| message: false\n#| warning: false\n#| out-width: \"70%\"\nfviz_mca_ind (res.acm,\n label = \"none\",\n habillage = \"q12\", # colorer par groupes\n xlab = \"Axe 1\", ylab = \"Axe 2\", title = \"\",\n palette = c (\"darkred\", \"steelblue\", \"gray23\"),\n ggtheme = theme_minimal ())\n```\n\n## Quiz de révision du chapitre {#sec-125}\n\n```{r}\n#| label: quizChapitre12\n#| echo: false\n#| warning: false\n#| results: asis\nsource(\"code_complementaire/QuizzFunctions.R\")\nChapitre12_AnalysesFacto <- quizz(\"quiz/Chapitre12_AnalysesFacto.yml\", \"Chapitre12_AnalysesFacto\")\nrender_quizz(Chapitre12_AnalysesFacto)\n```\n\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"12-AnalysesFactorielles.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/13-MethodeClassification.qmd.json b/.quarto/idx/13-MethodeClassification.qmd.json new file mode 100644 index 0000000..7d888e1 --- /dev/null +++ b/.quarto/idx/13-MethodeClassification.qmd.json @@ -0,0 +1 @@ +{"title":"Méthodes de classification non supervisée","markdown":{"headingText":"Méthodes de classification non supervisée","headingAttr":{"id":"sec-chap13","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\nDans le cadre de ce chapitre, nous présentons les méthodes les plus utilisées en sciences sociales pour explorer la présence de groupes homogènes au sein d'un jeu de données, soit les méthodes de classification non supervisée. Le qualificatif *non supervisé* signifie que ces classes/groupes ne sont pas connus a priori et doivent être identifiés à partir des données. Autrement dit, nous cherchons à regrouper les observations partageant des caractéristiques similaires sur la base de plusieurs variables. Ces méthodes descriptives et exploratoires multivariées peuvent être vues comme une façon de réduire le nombre d'observations d'un jeu de données à un ensemble d'observations synthétiques, représentant le mieux possible la population à l’étude.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n**Liste des *packages* utilisés dans ce chapitre**\n:::\n::: bloc_package-body\n\n* Pour créer des graphiques :\n - `ggplot2` le seul, l'unique!\n - `ggpubr` pour combiner des graphiques et réaliser des diagrammes.\n* Outils généraux pour faciliter les classifications :\n - `clusterCrit` pour calculer des indicateurs de qualité de classification.\n - `NbClust` pour trouver le bon nombre de groupe dans une classification.\n - `cluster` pour appliquer la méthode GAP.\n - `proxy` pour calculer plusieurs types de distances.\n - `Gmedian` pour calculer le k-médianes.\n - `geocmeans` pour explorer les résultats de classifications floues.\n:::\n:::\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Pourquoi recourir à des méthodes de classification non supervisée en sciences sociales?**\n:::\n::: bloc_objectif-body\nLes méthodes de classification sont très utilisées en sciences sociales. Elles visent à identifier des groupes cohérents au sein d'un ensemble d'observations sur la base de plusieurs variables (@fig-ClassifNonNSuperv). Ces groupes peuvent ensuite être analysés et nous renseigner sur les caractéristiques communes partagées par les individus qui les composent. \n\n![Principe de base des méthodes de classification non supervisée](images/Chap13/ClassifNonNSuperv.png){#fig-ClassifNonNSuperv width=\"40%\" fig-align=\"center\"}\n\nUn exemple classique est l'identification de profils d'individus ayant répondu à un sondage, en fonction de plusieurs caractéristiques (par exemple, l'âge, le sexe, la situation de famille, le revenu, etc.). En identifiant ces groupes homogènes, il est ensuite possible d'explorer les associations entre ces profils et d'autres variables.\n\nUn second exemple serait de regrouper les secteurs d'une ville selon leurs caractéristiques environnementales (végétation, niveau de bruit, pollution atmosphérique, etc.) et socioéconomiques (revenu médian des ménages, pourcentage d’immigrants, pourcentage de personnes à faible scolarité, taux de chômage, etc.).\n:::\n:::\n\n\n## Méthodes de classification : un aperçu {#sec-131}\n\nIl existe une multitude de méthodes de classification généralement regroupées dans plusieurs familles imbriquées à partir de deux distinctions importantes.\n\nLa première distinction vise à séparer les méthodes **supervisées** des **non supervisées**. Pour les premières, les catégories/groupes/classes des observations sont connues à l'avance. L'enjeu n'est pas de trouver les catégories puisqu’elles sont connues, mais **de déterminer des règles ou un modèle permettant d'attribuer des observations à ces catégories**. Parmi les méthodes de classification supervisée, les plus connues sont les forêts d’arbres décisionnels, les réseaux de neurones artificiels ou encore l’analyse factorielle discriminante. Nous n'abordons pas ces méthodes dans ce chapitre dédié uniquement aux méthodes de classification non supervisée. Pour ces dernières, les catégories ne sont pas connues à l'avance et l'enjeu est de **faire ressortir les structures des groupes propres aux données**. Ainsi, les méthodes de classification non supervisée « relèvent de la statistique exploratoire multidimensionnelle et permettent de classifier automatiquement les observations sans connaissance a priori sur la nature des classes présentes dans le jeu de données; les plus connues sont sans conteste les algorithmes de classification ascendante hiérarchique (CAH) et du *k-means* (k-moyennes) » [@2021_4, p.1]. Notez également qu'à la frontière entre ces deux familles, se situent les méthodes de classification semi-supervisée. Il s'agit de cas spécifiques où des informations partielles sont connues sur les groupes à détecter : seulement le groupe final de certaines observations est connu, certaines observations sont supposées appartenir à un même groupe même s'il est indéfini en lui-même [@bair2013semi].\n\nLa seconde distinction vise à séparer les méthodes **strictes** des **floues**. Les premières ont pour objectif d'assigner chaque observation à une et une seule catégorie, alors que les secondes décrivent le degré d’appartenance de chaque observation à chaque catégorie. Autrement dit, « dans une classification stricte, chaque observation appartient à une seule classe. Mathématiquement parlant, l’appartenance à une classe donnée est binaire (0 ou 1) tandis que dans une classification floue, chaque observation a une probabilité d’appartenance variant de 0 à 1 à chacune des classes » [@2021_4, p.1]. Bien entendu, pour chaque observation, la somme des degrés d’appartenance à chacune des classes est égale à 1 (@fig-floueVSstrict). En termes de données, cela signifie que pour les méthodes strictes, le groupe d'appartenance d'une observation est contenu dans une seule variable nominale (une colonne d'un *DataFrame*). Pour les méthodes floues, il est nécessaire de disposer d’autant de variables continues (plusieurs colonnes numériques d'un *DataFrame*), soit une par groupe, dans lesquelles sont enregistrées le degré d'appartenance de chaque observation à chacun des groupes. Parmi les méthodes de classification supervisée floue, notez que nous avons déjà abordé la régression logistique multinomiale dans le chapitre sur les GLM ([section @sec-0824]).\n\n![Classifications stricte et floue](images/Chap13/floueVSstricte.png){#fig-floueVSstrict width=\"35%\" fig-align=\"center\"}\n\nEn résumé, le croisement de ces deux distinctions permet ainsi de différencier les méthodes **supervisées strictes**, **supervisées floues**, **non supervisées strictes** et **non supervisées floues** (@fig-methoClassif), auxquelles s'ajoutent les méthodes semi-supervisées discutées brièvement.\n\n![Synthèse des principales méthodes de classification (Gelb et Apparicio 2021)](images/Chap13/syntheseClassif.png){#fig-methoClassif width=\"60%\" fig-align=\"center\"}\n\nDans ce chapitre, nous décrivons les trois méthodes de classification non supervisée les plus utilisées et faciles à mettre en œuvre : la classification ascendante hiérarchique, les nuées dynamiques strictes (*k-means* et *k-medians*) et nuées dynamiques floues (*c-means* et *c-medians*). \n\n## Notions essentielles en classification {#sec-132}\n\nAvant de décrire différentes méthodes de classification non supervisées, il convient de définir deux notions centrales, soit la **distance** et l'**inertie**.\n\n### Distance {#sec-1321}\n\nLa distance en analyse de données est définie comme une fonction (*d*) permettant de déterminer à quel point deux observations sont semblables ou différentes l'une de l'autre. Elle doit respecter les conditions suivantes :\n\n* **la non-négativité** : la distance minimale entre deux objets est égale à 0; $d(x,y) \\geq 0$.\n\n* **le principe d'identité des indiscernables** : la distance entre deux objets $x$ et $y$ est égale à 0, si $x = y$; $d(x,y)=0\\text{ si et seulement si }x=y$.\n\n* **la symétrie** : la distance entre $x$ et $y$ est la même qu'entre $y$ et $x$; $d(x,y) = d(y,x)$.\n\n* **le triangle d'inégalité** : passer d'un point $x$ à un point $z$ est toujours plus court ou égal que de passer par $y$ entre $x$ et $z$; $d(x,z)\\leq d(x,y)+d(y,z)$.\n\nIl existe un grand nombre de types de distance qui peuvent être utilisés pour déterminer le degré de similarité entre les observations. Nous présentons ici les six types les plus fréquemment utilisés en sciences sociales, mais retenez qu’il en existe bien d'autres.\n\n#### Distance euclidienne {#sec-13211}\n\nIl s'agit vraisemblablement de la distance la plus couramment utilisée, soit la longueur de la ligne droite la plus courte entre les deux objets considérés. Pour la représenter, admettons que nous nous intéressons à trois classes d'étudiants et d'étudiantes A, B et C pour lesquelles nous avons calculé la moyenne de leurs notes dans les cours de méthodes quantitatives et qualitatives. Ces deux variables sont mesurées dans la même unité et varient de 0 à 100. Le nuage de points à la @fig-dist0 illustre cette situation avec des données fictives.\n\n```{r}\n#| label: fig-dist0\n#| fig-cap: Situation de base pour le calcul de distance\n#| fig-align: center\n#| out-width: \"60%\"\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(ggplot2)\nlibrary(dplyr)\ndf <- data.frame(\n \"classe\" = c(\"A\" , \"B\" , \"C\"),\n \"quantitative\" = c(85,80,83),\n \"qualitative\" = c(80,79,77)\n)\n\nggplot(df) + \n geom_point(aes(x = quantitative, y = qualitative, color = classe), size = 3) + \n scale_color_manual(values = c(\"A\" = \"#E73D3D\", \"B\" = \"#3CE73C\", \"C\" = \"#3C3CE7\")) + \n labs(x = \"Moyenne des notes en méthodes quantitatives\",\n y = \"Moyenne des notes en méthodes qualitatives\")\n\n```\n\nLes distances euclidiennes entre les classes B et C et les classes C et A sont représentées par les lignes noires à la @fig-dist1. Nous pouvons constater que la distance entre les classes C et B est plus petite que celle entre les classes A et C, ce qui signale que les deux premières se ressemblent davantage.\n\n\n```{r}\n#| label: fig-dist1\n#| fig-align: center\n#| fig-cap: Représentation de la distance euclidienne\n#| out-width: \"60%\"\n#| message: false\n#| warning: false\n#| echo: false\n\ndf2 <- data.frame(\n xstart = c(80,83),\n xend = c(83,85),\n ystart = c(79,77),\n yend = c(77,80)\n)\n\nggplot(df) + \n geom_segment(data = df2, mapping = aes(x = xstart, y = ystart, \n xend = xend, yend = yend))+\n geom_point(aes(x = quantitative, y = qualitative, color = classe), size = 3) + \n scale_color_manual(values = c(\"A\" = \"#E73D3D\", \"B\" = \"#3CE73C\", \"C\" = \"#3C3CE7\")) + \n labs(x = \"Moyenne des notes en méthodes quantitatives\",\n y = \"Moyenne des notes en méthode qualitatives\")\n\n```\n\n\nLa formule de la distance euclidienne (@eq-euclideandist) est simplement la racine carrée de la somme des écarts au carré pour chacune des variables décrivant les observations *a* et *b*.\n\n$$ \nd(a,b) = \\sqrt{\\sum{}^v_{i=1}(a_i-b_i)^2}\n$$ {#eq-euclideandist}\n\navec *v* le nombre de variables décrivant les observations *a* et *b*.\n\nNous pouvons facilement calculer la distance euclidienne pour notre jeu de données : \n\n* $d(A,B)=\\sqrt{(\\mbox{85}-\\mbox{80})^2+(\\mbox{80}-\\mbox{77})^2} = \\mbox{5,83}$\n* $d(B, c)=\\sqrt{(\\mbox{80}-\\mbox{83})^2+(\\mbox{79}-\\mbox{77})^2} = \\mbox{3,60}$\n\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Distance et unité de mesure **\n:::\n::: bloc_attention-body\nIl est très important de garder à l'esprit que la distance entre deux observations dépend directement des unités de mesure utilisées. Cela est très souvent problématique, car il est rare que toutes les variables utilisées pour décrire des observations soient mesurées dans la même unité. Ainsi, une variable dont les valeurs numériques sont plus grandes risque de déséquilibrer les calculs de distance. À titre d'exemple, une variable mesurée en mètres plutôt qu'en kilomètres produit des distances euclidiennes 1000 fois plus grandes.\n\nIl est donc nécessaire de standardiser les variables utilisées avant de calculer des distances. Cette opération permet de transformer les variables originales vers une échelle commune. Plusieurs types de transformations peuvent être utilisés tels que décrits à la [section @sec-02552] :\n\n* **Le centrage et la réduction** qui consistent à soustraire de chaque valeur sa moyenne, puis à la diviser par son écart-type. La nouvelle variable obtenue s'exprime alors en écart-type (appelé aussi score-z). La formule de la transformation est $f(x) = \\frac{x - \\bar{x}}{\\sigma_x}$, avec $\\bar{x}$ la moyenne de $x$ et $\\sigma_x$ l'écart-type de $x$.\n\n* **La transformation sur une mise à l'échelle de 0 à 1** qui permet de modifier l'étendue d'une variable afin que sa valeur maximale soit de 1 et sa valeur minimale soit de 0. La formule de cette transformation est $f(x) = \\frac{x-min(x)}{max(x)-min(x)}$.\n\n* **La transformation en rang** qui consiste à remplacer les valeurs d'une variable par leur rang. La valeur la plus faible est remplacée par 1, et la plus forte par *n* (nombre d'observations). Notez que cette transformation modifie la distribution de la variable originale contrairement aux deux transformations précédentes. Cette propriété peut être désirable si les écarts absolus entre les valeurs ont peu d'importance, si la variable n'a pas été mesurée avec précision ou encore si des valeurs extrêmes sont présentes.\n\n* **La transformation en percentile** qui consiste à remplacer les valeurs d'une variable par leur percentile correspondant. Elle peut être vue comme une standardisation de la transformation en rang, car elle ne dépend pas du nombre d'observations.\n\nLa @fig-impactTransform montre l'effet de ces transformations sur l'histogramme d'une variable.\n\n```{r}\n#| label: fig-impactTransform\n#| echo: false\n#| fig-align: center\n#| fig-cap: Effets de différentes transformations sur la distribution d'une variable\n#| message: false\n#| warning: false\n#| out-width: \"80%\"\n\nx <- rgamma(10000, 0.95,0.1)\ndfx <- data.frame(\n x = x,\n xstd = (x - mean(x)) / sd(x),\n x_01 = (x-min(x)) / (max(x) - min(x)),\n x_rang = rank(x, ties.method = \"min\"),\n x_prt = trunc(rank(x, ties.method = \"average\"))/length(x)\n)\n\nx2 <- reshape2::melt(dfx)\n\nx2$variable <- case_when(x2$variable == \"x\" ~ \"1-originale\",\n x2$variable == \"xstd\" ~ \"2-centrée-réduite\",\n x2$variable == \"x_01\" ~ \"3-mise à l'échelle 0-1\",\n x2$variable == \"x_rang\" ~ \"4-rang\",\n x2$variable == \"x_prt\" ~ \"5-percentile\",\n )\n\nggplot(x2) + \n geom_histogram(aes(x = value), bins = 50, color = \"white\") + \n facet_wrap(vars(variable), ncol = 2, scales = \"free\")\n\n```\n:::\n:::\n\n#### Distance de Manhattan {#sec-13212}\n\nCette seconde distance est également couramment utilisée. Elle doit son nom au réseau de rue de l'île de Manhattan qui suit un plan quadrillé. La distance de Manhattan correspond à la somme des écarts absolus entre les valeurs des différentes variables décrivant les observations (@eq-manhattandist). La @fig-dist2 illustre que la distance Manhattan (lignes noires) représente les deux côtés opposés de l'hypoténuse d’un triangle rectangle; l'hypoténuse représentant quant à elle la distance euclidienne.\n\n$$\nd(a,b) = \\sum{}^v_{i=1}(|a_i-b_i|)\n$$ {#eq-manhattandist}\n\n\n```{r}\n#| label: fig-dist2\n#| echo: false\n#| fig-align: center\n#| fig-cap: Représentation de la distance de Manhattan\n#| message: false\n#| warning: false\n#| out-width: \"60%\"\n\ndf2 <- data.frame(\n xstart = c(85,83,80,80),\n xend = c(83,83,80,83),\n ystart = c(80,80,79,77),\n yend = c(80,77,77,77)\n)\n\nggplot(df) + \n geom_segment(data = df2, mapping = aes(x = xstart, y = ystart, \n xend = xend, yend = yend))+\n geom_point(aes(x = quantitative, y = qualitative, color = classe), size = 3) + \n scale_color_manual(values = c(\"A\" = \"#E73D3D\", \"B\" = \"#3CE73C\", \"C\" = \"#3C3CE7\")) + \n labs(x = \"Moyenne des notes en méthodes quantitatives\",\n y = \"Moyenne des notes en méthode qualitatives\")\n\n```\n\nLa distance de Manhattan doit être privilégiée à la distance euclidienne lorsque les données considérées ont un très grand nombre de dimensions (variables). En effet, lorsque le nombre de variables est important (supérieur à 30), la distance euclidienne tend à être grande pour toutes les paires d’observations et à moins bien discriminer les observations proches et lointaines les unes des autres. Du fait de sa nature additive, la distance de Manhattan est moins sujette à ce problème [@aggarwal2001surprising].\n\nCalculons la distance de Manhattan pour nos deux paires d'observations :\n\n* $d(A,B)=|85-80|+|80-77| = 8$\n* $d(B, c)=|80-83|+|79-77| = 5$\n\n#### Distance du khi-deux {#sec-13213}\n\nLa distance du khi-deux est basée sur le test du khi-deux ([chapitre @sec-chap05]) et est généralement utilisée pour calculer la distance entre deux histogrammes, deux images ou deux ensembles de mots. Plus précisément, elle permet de mesure la distance entre deux observations A et B, pour lesquelles nous disposons d'un ensemble de variables étant toutes des variables de comptage.\n\nPrenons un exemple concret en générant trois histogrammes A, B et C sur l'intervalle [0,50] à partir des distributions normale, log-normale et Gamma, puis comptons le nombre de valeurs de chaque unité (1, 2, 3, 4, etc.). Ces histogrammes sont représentés à la @fig-dist3.\n\n```{r}\n#| label: fig-dist3\n#| echo: false\n#| fig-align: center\n#| fig-cap: Trois histogrammes pour illustrer le calcul de la distance du khi-deux\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nset.seed(123)\nx1 <- rnorm(500, mean = 25, sd = 5)\nx2 <- rlnorm(500, meanlog = 2.75, sdlog = 0.25)\nx3 <- rgamma(500, 2,0.2)\n\ndf <- data.frame(\n normal = x1,\n lognormal = x2,\n gamma = x3\n)\n\ndf2 <- reshape2::melt(df)\ndf2$distribution <- case_when(\n df2$variable == \"normal\" ~ \"Normale\",\n df2$variable == \"lognormal\" ~ \"Log-normale\",\n df2$variable == \"gamma\" ~ \"Gamma\",\n)\ndf2$distribution <- as.factor(df2$distribution)\n\nggplot(df2) + \n geom_histogram(aes(x = value), breaks = 0:50) +\n facet_wrap(vars(distribution), ncol = 2) + \n labs(x = \"\", y = \"\")\n```\n\nNous pouvons calculer les distances du khi-deux entre les paires d'histogrammes (@tbl-tabdist3). Nous constatons ainsi que les histogrammes B et C sont les plus semblables.\n\n```{r}\n#| label: tbl-tabdist3\n#| tbl-cap: Distance du khi-deux entre trois histogrammes\n#| echo: false\n#| message: false\n#| warning: false\n\nchi2dist <- function(x,y){\n vec1 <- (x-y)**2\n vec2 <- x+y\n sum(vec1[vec2!=0] / vec2[vec2!=0])/2\n}\n\nA <- hist(df$normal, breaks = 0:50, plot = FALSE)$counts\nB <- hist(df$lognormal, breaks = 0:50, plot = FALSE)$counts\nC <- hist(df$gamma, breaks = 0:50, plot = FALSE)$counts\n\ntableau <- data.frame(\n pair = c(\"A-B\", \"A-C\", \"B-C\"),\n distances = c(chi2dist(A,B), chi2dist(A,C), chi2dist(B,C))\n)\n\nknitr::kable(tableau,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t col.names = c(\"Histogrammes\" , \"Distance du khi-deux\"),\n align=c(\"l\", \"r\")\n )\n```\n\nLa formule de cette distance est la suivante : \n\n$$ \nd_{\\chi^2}(a,b) = \\frac{1}{2}\\sum^n_{i=1}\\frac{(a_i-b_i)^2}{(a_i+b_i)}\n$$ {#eq-chi2dist}\n\navec $a_i$ et $b_i$ les comptages pour les histogrammes. Notez que si $a_i$ et $b_i$ valent tous les deux 0, il faut retirer ces valeurs avant le calcul, car cela provoquerait une division par 0.\n\nÀ première vue, cette distance peut paraître moins utile que les deux précédentes. Pourtant, de nombreuses données sont collectées comme des histogrammes. Un premier exemple serait des images que nous pouvons représenter sous forme de trois histogrammes, un pour chaque canal de couleur (rouge, vert et bleu). Un second exemple serait des données sonores, souvent synthétisées sous forme d'histogrammes des fréquences sonores enregistrées (octaves ou tiers d'octaves). Un dernier exemple pourrait être le nombre d'accidents de la route enregistré à diverses intersections d'une ville chaque heure. Dans ce contexte, un histogramme serait formé par l'intersection avec les heures de la journée comme limites des bandes et le nombre d'accidents comme hauteur des bandes.\n\n#### Distance de Mahalanobis {#sec-13214}\n\nProposée dans les années 1930 par le statisticien indien Prasanta Chandra Mahalanobis [-@chandra1936generalised], cette distance se base sur la matrice de covariance des variables analysées. Plus spécifiquement, elle est utilisée pour calculer la distance entre un point et une distribution normale multivariée. Elle permet notamment de tenir compte du fait que certaines variables sont corrélées et ainsi d'éviter de surestimer les distances entre des observations dans des jeux de données comprenant des variables corrélées entre elles.\n\nLa formule permettant de calculer cette distance est la suivante : \n\n\n$$ \nd(a,b) = \\sqrt{(a-b)^TS^{-1}(a-b)}\n$$ {#eq-mahalanobis}\n\navec *S* étant la matrice de covariance.\n\n#### Distance de Hamming {#sec-13215}\n\nCette distance est utilisée quand les écarts entre les variables de deux observations sont uniquement binaires. Un bon exemple serait un jeu de données ne comprenant que des variables qualitatives pouvant avoir une valeur identique pour deux observations (distance = 0) ou différente (distance = 1). La distance de Hamming est la simple addition de ces écarts.\n\nPrenons un exemple très simple en prenant trois maisons pour lesquelles nous connaissons cinq caractéristiques (@tbl-dist4).\n\n```{r}\n#| label: tbl-dist4\n#| echo: false\n#| tbl-cap: Exemple de données pour la distance de Hamming\n#| message: false\n#| warning: false\n\ntableau <- data.frame(\n couleur = c(\"blanc\", \"blanc\", \"rouge\"),\n jardin = c(\"non\", \"non\", \"oui\"),\n garage = c(\"oui\" , \"non\" , \"oui\"),\n cheminee = c(\"oui\" , \"oui\" , \"non\"),\n cave = c(\"non\", \"non\", \"oui\")\n)\n\nknitr::kable(tableau,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t col.names = c(\"couleur\", \"jardin\", \"garage\", \"cheminée\", \"sous-sol\"),\n align = c(\"l\", \"l\", \"l\", \"l\", \"l\")\n )\n```\n\nNous pouvons utiliser la distance de Hamming pour estimer le niveau de dissimilarité entre ces différentes maisons et l'organiser dans une matrice de distances. À la lecture du @tbl-dist5), les maisons 2 et 3 sont les plus dissimilaires (distance de Hamming = 5), et les maisons 1 et 2 les plus similaires (distance de Hamming = 1).\n\n```{r}\n#| label: tbl-dist5\n#| tbl-cap: Distance de Hamming entre les maisons\n#| echo: false\n#| message: false\n#| warning: false\n\nhouse_dists <- apply(tableau,1, function(x){\n dists <- apply(tableau, 1, function(y){\n sum(x != y)\n })\n return(dists) \n})\n\nrow.names(house_dists) <- c(\"maison 1\" , \"maison 2\" , \"maison 3\")\n\nknitr::kable(house_dists,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t row.names = TRUE,\n col.names = c(\"maison 1\" , \"maison 2\" , \"maison 3\"),\n align = c(\"l\", \"c\", \"c\", \"c\")\n )\n\n```\n\n#### Distance de Gower {#sec-13216}\n\nLa distance de Gower [-@gower1971general] peut être utilisée pour mesurer la distance entre deux observations lorsque les données sont à la fois qualitatives et quantitatives. Cette distance est comprise dans un intervalle de 0 à 1, 0 signifiant que les deux observations sont identiques et 1, que les observations sont radicalement différentes.\n\nElle se calcule de la façon suivante : \n\n$$\n\\begin{aligned}\n&d(a,b) = 1-\\frac{1}{p}\\sum^p_{j=1}s_{12j}\\\\\n&\\left\\{\\begin{array}{c}\ns_{xyj} = 1 \\text{ si } x_j = y_j \\text{, 0 autrement pour une variable qualitative} \\\\\ns_{xyj} = 1 - \\frac{|x_j-y_j|}{max(j)-min(j)} \\text{ pour une variable quantitative}\n\\end{array}\\right.\n\\end{aligned}\n$$ {#eq-gower}\n\n\navec *p* le nombre de variables, *x* et *y* deux observations et *j* une variable.\n\nAutrement dit, si la valeur d'une variable qualitative diffère entre deux observations, la distance entre ces deux observations augmente de $1/p$. Pour une variable quantitative, la distance augmente selon la différence absolue entre les valeurs de la variable divisée par l'étendue totale de la variable, le tout à nouveau divisé par *p*.\n\nSi cette mesure semble intéressante puisqu'elle permet de combiner des variables quantitatives et qualitatives, elle souffre de deux limites importantes :\n\n* Elle ne prend pas en compte le fait que certaines modalités des variables qualitatives sont moins fréquentes ni que certaines combinaisons sont également moins fréquentes.\n\n* Les variables qualitatives tendent à affecter bien plus la distance que les variables quantitatives. En effet, pour obtenir un écart de 1 sur une variable quantitative, il faut que les deux valeurs soient respectivement le maximum et le minimum de cette variable.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**D'autres distances pour des données mixtes**\n:::\n::: bloc_aller_loin-body\nIl existe bien d'autres distances qui peuvent être utilisées dans le cas de données mixtes. Le *package* `kmed` en implémente cinq (auxquelles s'ajoute la distance de Gower) dans sa fonction `distmix` : les distances de Wishart, de Podani, d'Huang, d'Harikumar et d'Ahmad. Ces différentes distances ont toutes leurs avantages et leurs défauts respectifs; pour plus d'information, référez-vous à la documentation de la fonction `distmix`.\n:::\n:::\n\n#### Distance du Phi^2^ {#sec-13217}\n\nLa distance du $\\Phi^2$ (Phi^2^) est une variante de la distance du $\\chi^2$. Il s'agit donc d'une distance à utiliser lorsque les données à analyser sont uniquement qualitatives. Elle calcule la distance entre deux observations en additionnant les différences entre les valeurs de chaque variable (1 si différentes, 0 si identiques, pour chaque variable), divisées respectivement par la fréquence totale d'occurrences de chaque modalité dans le jeu de données. En d'autres termes, cette distance tient compte du fait que certaines valeurs pour des variables qualitatives peuvent être observées plus fréquemment que d'autres et qu'une distance plus grande devrait être obtenue entre deux observations si l'une des deux présente des modalités rares comparativement au reste du jeu de données.\n\nElle peut être calculée de la façon suivante : \n\n$$\nd_{\\Phi^2}(i,j) = \\frac{1}{Q}\\sum_k\\frac{(\\delta_{ik} - \\delta_{jk})^2}{f_k}\n$$ {#eq-phidist}\n\navec *i* et *j* deux observations, *k* une modalité d'une variable qualitative, *Q* le nombre total de modalités des variables qualitatives, $\\delta_{ik} = 1$ si l'observation i a la modalité *k*, 0 sinon et $f_k$ la fréquence de la modalité *k* dans le jeu de données.\n\nLa distance du $\\Phi^2$ est très utile pour analyser les résultats de questionnaires.\n\n### Inertie {#sec-1322}\n\nUne notion importante à saisir dans le cadre des méthodes de classification non supervisée est celui celle l'**inertie** d'un jeu de données. Elle est proche de la notion de variance qui a été présentée dans le chapitre sur la statistique univariée ([section @sec-0253]).\n\nL'inertie est une quantité permettant de décrire la dispersion des observations d'un jeu de données. Cette mesure dépend à la fois des données (nombres d'observations et de variables, échelle des variables) et de la mesure de distance retenue entre deux observations. Plus spécifiquement, l'inertie correspond à la somme des distances entre chaque observation et le centre du jeu de données. \n\n$$\ninertie= \\sum{}^n_{i=1} d(c,x_i)\n$$ {#eq-inertia}\n\navec *c* le centre du jeu de données, *n* le nombre d'observations, *x* une observation et *d* la fonction calculant la distance entre deux observations.\n\nL'enjeu est de définir *c* dans un contexte où la distance euclidienne est utilisée. Il s'agit simplement d'une observation fictive dont les coordonnées sont les moyennes des différentes variables du jeu de données. Dans le cas d'autres distances, il peut s'agir de l'observation minimisant la distance à toutes les autres observations.\n\nPour bien visualiser la notion d'inertie, prenons une fois encore le jeu de données `IRIS` comme exemple. Admettons que nous ne nous intéressons qu'à deux variables de ce jeu de données : `sepal.Length` et `sepal.Width`. Nous pouvons représenter l'inertie totale du jeu de données à la @fig-dist6.\n\n\n```{r}\n#| label: fig-dist6\n#| echo: false\n#| fig-align: center\n#| fig-cap: Représentation de l'inertie du jeu de données IRIS\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\ndata(iris)\nggplot(iris) + \n geom_segment(aes(x = Sepal.Length, y = Sepal.Width,\n xend = mean(Sepal.Length),\n yend = mean(Sepal.Width)),\n color = \"blue\") +\n geom_point(aes(x = Sepal.Length, y = Sepal.Width)) +\n geom_point(aes(x = mean(Sepal.Length), y = mean(Sepal.Width)), color = \"red\", size = 3)\n\n```\n\nChaque ligne bleue représente la contribution de chaque point à l'inertie totale du jeu de données. Pour chaque iris, nous connaissons son espèce (Setosa, Versicolor ou Virginica). Nous pouvons donc attribuer chaque point de ce jeu de données à un groupe (une espèce dans notre cas). Il devient alors possible de calculer l'inertie de chacun des sous-groupes de notre jeu de données. Pour cela, nous devons calculer le centre de chaque groupe (généralement les moyennes des variables des observations au sein d'un groupe) et ensuite calculer l'inertie entre chaque observation et le centre de son groupe. Nous représentons cette situation à la @fig-dist7.\n\n```{r}\n#| label: fig-dist7\n#| echo: false\n#| fig-align: center\n#| fig-cap: Représentation de l'inertie par groupe pour le jeu de données IRIS\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nlibrary(gganimate)\n\nspec_means <- iris %>% \n group_by(Species) %>% \n summarise_all(mean)\n\nnames(spec_means)[2:ncol(spec_means)] <- paste(names(spec_means)[2:ncol(spec_means)],\".end\", sep = \"\")\n\niris2 <- merge(iris, spec_means, by = \"Species\")\n\nggplot(iris2) + \n geom_segment(aes(x = Sepal.Length, y = Sepal.Width,\n xend = Sepal.Length.end,\n yend = Sepal.Width.end,\n color = Species)) +\n geom_point(aes(x = Sepal.Length, y = Sepal.Width)) +\n geom_point(data = spec_means,\n mapping = aes(x = Sepal.Length.end, y = Sepal.Width.end, fill = Species),\n size = 3, colour = \"black\", pch = 21)\n\n```\n\nCette inertie propre aux groupes est toujours inférieure ou égale à l'inertie totale du jeu de données. Il s'agit en réalité de l'inertie que la structure de groupe n'est pas en mesure d'expliquer. En utilisant ces concepts, il est possible de calculer la part de l'inertie totale expliquée par les groupes (@eq-explainedinertia) : \n\n$$ \n\\text{inertie expliquée} = 1-\\frac{\\text{inertie totale}}{\\text{inertie restante}}\n$$ {\\#eq-explainedinertia}\n\nCette valeur nous renseigne sur la capacité d'une classification à bien réduire l'inertie totale d'un jeu de données. Elle est comprise entre 0 et 1. Si l'inertie expliquée est à 0, c'est que la classification n'explique absolument aucune part de l'inertie totale. Si l'inertie expliquée est à 1, la classification utilisée explique l'intégralité de l'inertie, ce qui en pratique n'est atteignable que si le nombre de groupes de la classification est égal au nombre d'observations. En d'autres termes, chaque observation est attribuée à un groupe dont elle est la seule représentante. Un telle situation n'a aucun intérêt puisque l'objectif d'une classification est bien de réduire la complexité d'un jeu de données en regroupant les observations.\n\n\n## Classification ascendante hiérarchique {#sec-133}\n\nLa classification ascendante hiérarchique (CAH) est un algorithme de classification non supervisée dont l'objectif est de créer un arbre de classification des observations. Cet arbre est ensuite utilisé pour déterminer le nombre de groupes à former et à quel groupe appartient chaque observation.\n\n### Fonctionnement de l'algorithme {#sec-1331} \n\nLa classification ascendante hiérarchique est un algorithme permettant de regrouper les observations d'un jeu de données de façon itérative. À chaque itération, deux observations similaires sont agrégées en un groupe représenté par le point central entre les deux observations. Le processus est ensuite répété en considérant le nouveau point comme une observation jusqu'à ce que toutes les observations soient fusionnées en un seul groupe.\n\nCes regroupements successifs créent un arbre de classification appelé dendrogramme. La racine de cet arbre est le groupe unique fusionnant toutes les observations, et ses branches correspondent aux différentes agrégations effectuées jusqu'aux observations individuelles. Cet arbre peut être vu comme une hiérarchie de classification. Chaque niveau de l'arbre est un regroupement de plus en plus généraliste au fur et à mesure que nous nous approchons de sa racine.\n\nPour appliquer cette méthode, il est nécessaire de sélectionner une **fonction de distance** pour mesurer la dissimilarité ou la ressemblance entre deux observations. L'algorithme fonctionne avec n'importe quelle fonction de distance, ce qui permet de l'appliquer aussi bien à des données qualitatives que quantitatives. En effet, l'opération de regroupement des observations se base sur une matrice de distance, soit un tableau de taille *n x n* indiquant pour chaque paire d'observations leur degré de dissimilarité. La @fig-tablvsmat illustre cette transformation en appliquant la distance du $\\Phi^2$ à un jeu de données comprenant cinq observations et 5 variables qualitatives.\n\n```{r}\n#| label: fig-tablvsmat\n#| echo: false\n#| fig-align: center\n#| fig-cap: Du tableau de données à la matrice de distance\n#| message: false\n#| warning: false\n#| out-width: \"80%\"\n\nlibrary(gridExtra)\nlibrary(grid)\nsource(\"code_complementaire/classif_helper.R\")\n\n\ndf1 <- data.frame(\n couleur = c(\"blanc\", \"blanc\", \"rouge\", \"bleu\", \"rouge\"),\n jardin = c(\"non\", \"non\", \"non\", \"oui\", \"non\"),\n garage = c(\"oui\" , \"non\" , \"oui\", \"oui\", \"oui\"),\n cheminee = c(\"oui\" , \"oui\" , \"non\", \"non\", \"non\"),\n cave = c(\"non\", \"non\", \"non\", \"oui\", \"non\")\n)\n\ndf2 <- df1\n\nfor(col in names(df2)){\n df2[[col]] <- paste(col, df2[[col]], sep = \"_\")\n}\n\ndist_mat <- round(Phi2dist(df2),2)\ndist_mat <- ifelse(is.na(dist_mat),0, dist_mat)\nrownames(df1) <- paste(\"maison \", 1:nrow(df1), sep = \"\")\nrownames(dist_mat) <- paste(\"maison \", 1:nrow(df1), sep = \"\")\ncolnames(dist_mat) <- paste(\"maison \", 1:nrow(df1), sep = \"\")\n\ntheme_table <- ttheme_default()\ntheme_table$colhead$fg_params$fontface <- 3\ntheme_table$colhead$bg_params$fill <- \"white\"\n\ng1 <- tableGrob(df1)\ng2 <- tableGrob(dist_mat, theme = theme_table)\n\ngrid.arrange(rectGrob(), rectGrob(), nrow = 2, ncol = 1)\ngrid.arrange(g1, g2, nrow = 2, newpage = FALSE)\n```\n\n\nEn plus de la fonction de distance, il est également nécessaire de sélectionner un **critère d'agrégation**, soit la règle permettant de décider à chaque itération quelles observations doivent être regroupées. Les méthodes les plus courantes sont : \n\n* Le critère de Ward [-@ward1963hierarchical] : cette méthode consiste à agréger à chaque itération les deux observations permettant de minimiser la variance (ou l'inertie) intra-groupe, ce qui revient à maximiser l'inertie inter-groupe (autrement dit, à rendre les groupes les plus homogènes possibles et les plus dissemblables entre eux). Ainsi, l'enjeu est de fusionner les deux observations permettant d'avoir les groupes les plus dissimilaires possible après fusion.\n\n* Le lien complet : à chaque itération, les deux groupes d'observations associés sont ceux pour lesquels la distance maximale entre les observations les composant est la plus petite parmi tous les groupes.\n\n* Le lien simple : à chaque itération, les deux groupes d'observations associés sont ceux pour lesquels la distance minimum entre les observations les composant est la plus petite parmi tous les groupes.\n\nLa plus utilisée est de loin la méthode de Ward. La méthode du lien complet produit généralement des résultats similaires. En revanche, la méthode du lien simple peut produire des groupes non sphériques (non centrés sur leur moyenne) plus difficile à interpréter.\n\nPrenons un instant pour visualiser cet algorithme (@fig-animhclust). Cette animation a été réalisée par David Sheehan et est également accessible sur son [blog](https://dashee87.github.io/data%20science/general/Clustering-with-Scikit-with-GIFs/). Elle présente bien le processus d'agglomération de la classification ascendante hiérarchique et la construction progressive du dendrogramme.\n\n![Principe de fonctionnement de la classification ascendante hiérarchique (auteur : David Sheehan)](images/Chap13/CAH.gif){#fig-animhclust width=\"75%\" fig-align=\"center\"}\n\n### Choisir le bon nombre de groupes {#sec-1332}\n\nUne fois que l'algorithme a été appliqué aux données et le dendrogramme obtenu, il faut encore choisir le nombre optimal de groupes pour la classification finale. Chaque embranchement du dendrogramme constitue une classification possible, allant de la plus complexe (chaque observation appartient à un groupe formé d'elle seule) à la plus simple (toutes les observations appartiennent au même groupe). Si le nombre de groupes n'est pas connu à l'avance et qu'aucune forte justification théorique n'existe, il est possible d'utiliser plusieurs techniques pour déterminer un nombre de groupes judicieux à partir des données. Nous en présentons ici trois, mais il convient de ne pas s'en tenir uniquement à ses critères arbitraires. Il est important d'explorer les résultats de la classification obtenue pour plusieurs valeurs de *k* candidates et de tenir compte de la qualité des informations qu'elles fournissent. Au final, il est pertinent de retenir la classification dont les résultats offrent l'interprétation la plus claire avec un nombre de groupes réduit (principe de parcimonie).\n\n#### Méthode du coude {#sec-13321}\n\nCette première approche est la plus simple à mettre en œuvre. Il s'agit simplement de produire plusieurs classifications à partir du dendrogramme avec différentes valeurs de *k* (nombre de groupes) et de calculer à chaque fois la part de l'inertie expliquée. Chaque groupe supplémentaire ne peut qu'améliorer l'inertie expliquée, car pour rappel, si $k=n$, alors nous expliquons 100 % de l'inertie totale. L'objectif est de déterminer à quel moment l'ajout d'un groupe supplémentaire ne contribue que de façon marginale à améliorer l'inertie expliquée. Si nous représentons les valeurs d'inertie expliquée pour les différentes valeurs de *k* dans un graphique, une rupture (un coude) indiquerait le point au-delà duquel les groupes supplémentaires ne captent finalement que du bruit et non plus de l'information.\n\nSi nous reprenons l'exemple du jeu de données `IRIS`, nous pouvons créer ce graphique avec *k* allant de 2 à 8 (@fig-kmeans2). Un premier coude très net est observable pour $k = 3$ et un second plus faible, mais tout de même marqué pour $k = 4$. \n\n```{r}\n#| label: fig-kmeans2\n#| echo: false\n#| fig-align: center\n#| fig-cap: Méthode du coude\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nks <- 2:8\ndata(iris)\nX <- as.matrix(iris[,1:4])\nD <- dist(X)\n\nclust <- hclust(D)\n\n## calcul de l'inertie totale\ncenter <- apply(X, MARGIN = 2, mean)\n\ninert_tot <- sum((t(X) - as.numeric(center))**2)\n\nrows <- t(sapply(ks, function(k){\n classif <- cutree(clust, k)\n \n ## calcul du centre des groupes\n X2 <- as.data.frame(X)\n X2$gp <- as.character(classif)\n centers <- X2 %>% \n group_by(gp) %>%\n summarize_all(mean)\n \n ## calcul de l'inertie intra-classe\n inert_intra <- sapply(unique(X2$gp), function(g){\n elems <- subset(X2,X2$gp == g)\n elems$gp <- NULL\n x <- as.matrix(elems)\n center <- subset(centers, centers$gp == g)\n center$gp <- NULL\n y <- as.numeric(center)\n sum((t(x) - y)**2)\n })\n \n \n exp_inertia <- 1-(sum(inert_intra)/inert_tot)\n return(c(k, exp_inertia))\n}))\n\nrows <- as.data.frame(rows)\nnames(rows) <- c(\"k\" , \"exp_inertia\")\n\nggplot(rows) + \n geom_path(aes(x = k, y = exp_inertia)) + \n geom_point(aes(x = k, y = exp_inertia), color = \"red\") + \n scale_x_continuous(breaks = 2:8)+\n labs(x = \"nombre de groupes\", \n y = \"inertie expliquée\")\n\n```\n\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Inertie expliquée et centre de groupe**\n:::\n::: bloc_notes-body\nPour calculer l'inertie expliquée, il est nécessaire de pouvoir déterminer pour le centre de gravité (ou centroïde) chaque groupe. Lorsque la distance euclidienne est utilisée, il s'agit simplement de calculer pour chaque groupe la valeur moyenne des différentes colonnes des observations. Cependant, lorsque d'autres distances sont utilisées, il peut être plus difficile de déterminer le centre d'un groupe. Avec la distance de Manhattan, il est par exemple recommandé d'utiliser la médiane des colonnes plutôt que la moyenne. Pour la distance de Hamming, la moyenne peut aussi être utilisée, car elle représente pour cette distance la fréquence d'occurrence des différentes modalités des variables qualitatives. Pour d'autres distances plus complexes, il est préférable de définir le centre d'un groupe comme le point de ce groupe minimisant les distances à tous les autres points du groupe. Il s'agit du médoïde du groupe.\n:::\n:::\n\n#### Indicateur de silhouette {#sec-13322}\n\nSi un coude net ne s'observe pas pour la méthode précédente, il est possible d'utiliser l'indicateur de silhouette. Il permet de mesurer pour une classification à quel point une observation est similaire à celles dans son propre groupe (cohésion) comparativement aux observations des autres groupes. Elle se calcule de la façon suivante : \n\n$$\n\\begin{aligned}\ns(i) &= \\frac{b(i)-a(i)}{\\max \\{a(i), b(i)\\}} \\\\\na(i) &= \\frac{1}{|C_i|-1}\\sum_{j \\in C_i,i \\neq j}d(i,j) \\\\\nb(i) &= min_{i \\neq j}\\frac{1}{|C_j|}\\sum_{j \\in C_j}d(i,j)\n\\end{aligned}\n$$ {#eq-silhouetteidx}\n\navec $s(i)$ la valeur de l'indice de silhouette pour l'observation *i*, $a(i)$ la distance moyenne entre l'observation *i* et son groupe $C_i$ et $b(i)$ la distance minimale entre l'observation *i* et le centre de chaque autre groupe $C_j$.\n\n\nLa valeur totale de l'indice est simplement la moyenne des valeurs moyennes des indices de silhouette au sein de chaque groupe. Une valeur plus élevée indique une meilleure classification. Il est nécessaire de déterminer le centre des groupes pour calculer cet indicateur, ce qui peut être un exercice difficile quand une distance autre que la distance euclidienne est utilisée. Référez-vous à la note de la section précédente pour plus d'informations. L'indice de silhouette semble indiquer que seulement trois groupes serait un choix optimal, soit la valeur la plus haute (@fig-kmeans3).\n\n```{r}\n#| label: fig-kmeans3\n#| echo: false\n#| fig-align: center\n#| fig-cap: Méthode de l'indice de silhouette\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nlibrary(clusterCrit)\nks <- 2:8\n\nrows <- t(sapply(ks, function(k){\n classif <- cutree(clust, k)\n sil <- intCriteria(X, classif, crit = \"Silhouette\")$silhouette\n return(c(k, sil))\n}))\n\nrows <- as.data.frame(rows)\nnames(rows) <- c(\"k\" , \"silhouette\")\n\nggplot(rows) + \n geom_path(aes(x = k, y = silhouette)) + \n geom_point(aes(x = k, y = silhouette), color = \"red\") + \n labs(x = \"nombre de groupes\", \n y = \"Indice de Silhouette\")\n```\n\n\n#### Méthode GAP {#sec-13323}\n\nCette méthode, proposée par @tibshirani2001estimating, consiste à comparer l'inertie intra-groupe (inexpliquée) avec l'inertie observée pour un jeu de données généré aléatoirement (distribution uniforme des valeurs entre le minimum et le maximum de chaque variable) pour différentes valeurs successives de *k*. Une fois ces calculs effectués, l'objectif est de trouver la valeur de *k* telle que la valeur de GAP à *k + 1* n'est pas plus grande qu'un écart type pour GAP à *k + 1*.\n\nLa statistique GAP est calculée ainsi : \n\n$$\n\\begin{aligned}\nGAP(k) = \\frac{1}{\\text{nsim}} \\sum^{\\text{nsim}}_{\\text{sim} = 1} log(W_{ksim}) - log(W_k)\n\\end{aligned}\n$$ {#eq-gapidx}\n\navec $W_k$ l'inertie non expliquée (intra-groupe), $W_{ksim}$ l'inertie non expliquée (intra-groupe) obtenue pour un jeu de données simulé et *k* le nombre de groupes.\n\nL'idée est qu'une bonne classification doit produire des résultats plus structurés que ce que nous pourrions attendre du hasard. Chaque groupe supplémentaire permet de réduire l'inertie, mais lorsque l'ajout d'un groupe ne permet pas un gain significatif comparativement au hasard, alors l'ajout de ce groupe ne se justifie pas. À nouveau, il est possible de visualiser la situation avec un simple graphique (@fig-kmeans4). Selon cette méthode, il faudrait sélectionner quatre groupes, car il s'agit de la première valeur de *k* validant le critère de cette méthode. La seconde valeur retenue par cette méthode est 6.\n \n\n```{r}\n#| label: fig-kmeans4\n#| echo: false\n#| fig-align: center\n#| fig-cap: Méthode GAP\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nlibrary(NbClust)\nlibrary(cluster)\n\nhclustfun <- function(x, k){\n D <- dist(x)\n clust <- hclust(D)\n classif <- cutree(clust, k)\n return(list(\n \"cluster\" = classif\n ))\n}\n\nvals <- clusGap(X, hclustfun, K.max = 8)\ntab <- data.frame(vals$Tab)\ntab$k <- 1:nrow(tab)\n\nis_valid <- sapply(2:nrow(tab), function(i){\n tab[i-1,\"gap\"] >= (tab[i,\"gap\"] - tab[i,\"SE.sim\"])\n})\n\nvalids <- subset(tab, is_valid)[1,]\nvalids2 <- subset(tab, is_valid)[2,]\n\nggplot(tab[2:8,]) + \n geom_line(aes(x = k, y = gap)) + \n geom_segment(x = valids$k, xend = valids$k, y = min(tab$gap), yend = valids$gap, \n linetype = \"dashed\") +\n geom_segment(x = valids2$k, xend = valids2$k, y = min(tab$gap), yend = valids2$gap, \n linetype = \"dashed\") +\n geom_point(aes(x = k, y = gap), color = \"red\") + \n scale_x_continuous(breaks = 1:10) + \n labs(x = \"nombre de groupes\", y = \"GAP\")\n\n```\n\n### Limites de la classification ascendante hiérarchique {#sec-1333}\n\nBien que très flexible (choix de la fonction de distance et du critère d'agrégation), la CAH fait face à un enjeu majeur : la vitesse d'exécution et la consommation de mémoire lorsque de grands jeux de données sont utilisés. En effet, il est nécessaire de calculer à chaque étape une matrice de distance entre les groupes. Si un jeu de données comprend 1000 observations, cette matrice comprend donc 1000 x 1000 cases, soit un million de distances. Même en divisant ce nombre par deux (les éléments de la matrice sont symétriques, donc $d(ij) = d(ji)$), ce nombre augmente avec le carré du nombre d'observations. Pour de grands jeux de données, la CAH peut donc échouer à cause des limites de l'ordinateur utilisé. Il existe des versions plus performantes de l'algorithme réduisant cette limite, mais il convient de la garder en mémoire. Quand un très grand jeu de données doit être analysé, les méthodes des nuées dynamiques sont une solution à considérer.\n\n### Mise en œuvre dans R {#sec-1334}\n\nNous proposons ici un exemple issu d'un article portant sur les parcs urbains de Montréal [@apparicio2010accessibilite], dont l'objectif était notamment de classifier ces parcs en fonction de leur superficie et des équipements qu'ils comprennent, et ce, en utilisant la classification ascendante hiérarchique. Nous proposons ici de reproduire l'étape de classification effectuée dans cet article. La base de données comporte 653 parcs pour lesquels la présence de 18 équipements est codée comme un ensemble de variables binaires (0 signifiant absence et 1 présence). Nous disposons également de la taille de ces parcs, recodée en cinq catégories : moins d'un hectare, de 1 à 5 hectares, de 5 à 10 hectares, de 10 à 20 hectares et 20 hectares et plus. Le @tbl-exampleHclust1DF indique le nombre d'équipements recensés dans les parcs.\n\n```{r}\n#| label: tbl-exampleHclust1DF\n#| tbl-cap: Équipements recensés dans les différents parcs de Montréal\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(kableExtra)\ndf <- data.frame(\n equipement = c(\"Aire de jeux\", \"Pataugeoire\", \"Jeux d’eau\",\n \"Baseball\", \"Soccer (football)\", \"Basketball\", \"Tennis\" , \" Football\", \"Volleyball\", \"Athlétisme\",\n \"Patinoire extérieure\", \"Glissade\", \"Piste de ski de fond\", \"Piste de raquette\",\n \"Parc de planches à roulettes\", \"Patins à roues alignées\",\n \"Piscine intérieure\", \"Chemin de randonnée\"),\n N = c(601,161,28,188,169,144,125,36,24,20,241,30,14,9,18,8,92,15)\n)\n\nmy_table <- knitr::kable(df,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t col.names = c(\"Équipements\" , \"N\"), \n\t\t row.names = FALSE,\n align=c(\"l\", \"r\")\n )\n\ngroup_rows(my_table,\n index = c(\"Équipements pour les 0 à 4 ans\" = 3,\n \"Terrains de sport\" = 7,\n \"Équipements d'hiver\" = 4,\n \"Équipements spécialisés\" = 2,\n \"Autres équipements\" = 2)\n )\n```\n\nPuisque notre jeu de données ne comporte que des variables qualitatives, nous utilisons la distance du $\\Phi^2$ pour construire notre matrice de distance entre les parcs. Notons que, dans l'article original, la distance euclidienne au carré avait été utilisée, alors nous n'obtiendrons probablement pas les mêmes résultats, car la distance du $\\Phi^2$ tient compte des fréquences d'occurrence des modalités des variables qualitatives.\n\n#### Calcul de la matrice de distance {#sec-13341}\n\nLa première étape consiste donc à charger notre jeu de données et à calculer la matrice de distance.\n\n```{r}\n#| label: exampleHclust1\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\n# chargement du jeu de données et sélection des colonnes pour l'analyse\nparcs <- read.csv(\"data/classification/Parcs.txt\", header = TRUE, stringsAsFactors = FALSE)\nX <- parcs[c(5:22, 27)]\n```\n\nPour calculer la distance du $\\Phi^2$, nous utilisons la fonction `dist` du *package* `proxy` avec le paramètre `method = \"Phi-squared\"`. Elle requiert que l'ensemble des variables catégorielles soient converties en variables binaires. Pour cela, nous pouvons utiliser la fonction `dummy_cols` du *package* `fastDummies`.\n\n```{r}\n#| label: exampleHclust2\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nlibrary(fastDummies)\nlibrary(proxy)\n\nX <- dummy_cols(X, select_columns = \"HaTypo\", remove_selected_columns = TRUE)\nparc_distances <- dist(as.matrix(X), method = \"Phi-squared\")\n```\n\n#### Application de l'algorithme de classification ascendante hiérarchique {#sec-13342}\n\nUne fois la matrice obtenue, il ne reste plus qu'à appliquer la fonction `hclust` disponible de base dans R pour obtenir le dendrogramme. Comme dans l'article, nous utilisons le critère d'agrégation de Ward pour la création des groupes.\n\n```{r}\n#| label: exampleHclust3\n#| fig-align: center\n#| message: false\n#| warning: false\n\ndendogramme_parcs <- hclust(parc_distances, method = \"ward.D\")\n```\n\nPuisque nous n'utilisons pas la distance euclidienne, nous optons ici pour l'indice de silhouette pour déterminer le nombre adéquat de groupes à former. Nous testons toutes les valeurs comprises entre 2 et 10.\n\n```{r}\n#| label: fig-exampleHclust4\n#| fig-align: center\n#| fig-cap: Valeur de l'indice de silhouette pour différents nombres de groupes\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nlibrary(cluster)\nks <- 2:10\n\n# Calcul des indices de silhouette pour les différentes valeurs de k\nvalues <- sapply(ks, function(k){\n # découpage du dendrogramme\n groupes <- cutree(dendogramme_parcs, k = k)\n # calcul des valeurs de silhouette\n sil <- silhouette(groupes, dist = parc_distances)\n # extraction de l'indice global (moyenne des moyennes)\n idx <- mean(summary(sil)$clus.avg.widths)\n return(idx)\n})\n\n# Création d'un graphique avec les résultats\ndf <- data.frame(k = ks, silhouette = values)\nggplot(df) + \n geom_line(aes(x = k, y = silhouette)) + \n geom_point(aes(x = k, y = silhouette), color = \"red\") + \n labs(x = \"nombre de groupes\", y = \"indice global de silhouette\")\n```\nSi nous écartons d'emblée les résultats pour k = 2 et k = 3 (trop peu de groupes pour l'interprétation), nous constatons que la solution optimale selon ce critère est k = 5. Dans l'article original, la solution k = 6 avait été retenue en examinant le dendrogramme. Comparons les résultats pour k = 5 et k = 6.\n\n```{r}\n#| label: exampleHclust5\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nresk5 <- cutree(dendogramme_parcs, k = 5)\nresk6 <- cutree(dendogramme_parcs, k = 6)\nsil5 <- silhouette(resk5, dist = parc_distances)\nsil6 <- silhouette(resk6, dist = parc_distances)\n\n# résumé pour l'indice de silhouette pour k = 5\nsummary(sil5)\n\n# résumé pour l'indice de silhouette pour k = 6\nsummary(sil6)\n \n```\nNous constatons que le groupe supplémentaire vient séparer le groupe trois comprenant 246 parcs dans la solution avec k = 5. Ce dernier ne comprend plus que 197 parcs pour la solution k = 6 et le nouveau groupe en compte 49. Ce nouveau groupe à un indice de silhouette moyen relativement faible (0,079), et le fait de découper le groupe trois améliore très peu sa propre valeur (passant de -0,12 à -0,10). Nous retenons cependant ici la solution avec k = 6 afin de tenter de reproduire les résultats de l'article.\n\n#### Interprétation des résultats {#sec-13343}\n\nLa dernière étape consiste à identifier les groupes obtenus et leur attribuer un intitulé en fonction de leurs caractéristiques. Dans notre cas, la classification ne comporte que des variables binaires, nous pouvons donc calculer le pourcentage de valeurs à 1 (présence d'un équipement) dans chacun des groupes.\n\n```{r}\n#| label: exampleHclust6\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\n# calcul du nombre de fois où chaque modalité est observée dans un groupe\nX$groupe <- resk6\ndf_groupes <- X %>% \n group_by(groupe) %>% summarise_all(.funs = sum)\n\n# calcul du nombre d'observations par groupe\nnb_gp <- table(resk6)\ngroupe_ratios <- round(100 * as.matrix(df_groupes)[,2:ncol(df_groupes)] / as.vector(nb_gp),1)\ngroupe_ratios <- as.data.frame(t(groupe_ratios))\nnames(groupe_ratios) <- paste0(\"groupe \", 1:ncol(groupe_ratios))\n\n# calcul du nombre moyen d'équipements par catégorie par parc\nequip_class <- list(\n c(\"AIRE_JEUX\", \"JEUX_EAU\", \"PATAUGEOIRE\"),\n c(\"ATHLETISME\", \"BASEBALL_S\", \"BASKETBALL\", \"FOOTBALL\", \"SOCCER\", \"TENNIS\", \"VOLLEY_BALL\"),\n c(\"TOBBOGAN_G\", \"PATINOIRE_E\", \"RAQUETTES\", \"SKI_FOND\"),\n c(\"PATIN_ROUE\", \"ROULI_ROUL\"),\n c(\"PISC_EXT\", \"RANDONNEE\")\n)\n\nclass_compte <- data.frame(sapply(equip_class, function(equip){\n rowSums(X[equip])\n}))\nnames(class_compte) <- c(\"enfants\", \"terrain_sport\", \"hiver\", \"specialise\", \"autre\")\nclass_compte$groupe <- resk6\ndf_class_equip <- class_compte %>% \n group_by(groupe) %>% \n summarise_all(mean)\n\ndf_class_equip <- t(df_class_equip[2:ncol(df_class_equip)])\ncolnames(df_class_equip) <- paste0(\"groupe \", 1:ncol(df_class_equip))\n\n# comptage du nombre moyen total d'équipements\ndf_equip_tot <- data.frame(\n nb = rowSums(X[1:18]),\n groupe = resk6\n)\ndf_equip_tot_mean <- df_equip_tot %>% \n group_by(groupe) %>% \n summarize_all(mean)\n\n# mise dans l'ordre de la première partie du tableau\nall_types <- do.call(c, equip_class)\nidxs <- match(all_types, row.names(groupe_ratios[1:length(all_types),]))\ngroupe_ratios <- rbind(groupe_ratios[idxs,],\n groupe_ratios[(length(all_types)+1):nrow(groupe_ratios),])\n\n# combinaison des deux tableaux\ngroupe_ratios <- rbind(groupe_ratios, df_class_equip, df_equip_tot_mean$nb, as.integer(nb_gp))\n```\n\nIl est ensuite possible d'afficher le tableau obtenu pour l'interpréter. Les résultats sont ici rapportés au @tbl-exampleHclust7.\n\n```{r}\n#| label: tbl-exampleHclust7\n#| tbl-cap: Caractéristiques des groupes obtenus lors de la CAH\n#| echo: false\n#| fig-align: center\n#| message: false\n#| warning: false\n\nlibrary(kableExtra)\nrow.names(groupe_ratios) <- c(\n \"Aire de jeux\", \"Jeux d'eau\", \"Pataugeoire\", \"Athlétisme\", \"Baseball\", \"Basketball\", \"Football américain\", \"Soccer (football)\",\n \"Tennis\", \"Volleyball\", \"Glissade\", \"Patinoire\", \"Piste de ski de fond\", \"Raquettes\", \"Parc de planches à roulettes\",\n \"Patins à roues alignées\", \"Piscine extérieure\", \"Chemin de randonnée\", \"Moins d'un hectare\", \"1 à 5 hectares\", \"5 à 10 hectares\",\n \"10 à 20 hectares\", \"20 hectares et plus\", \"Équipements pour les 0 à 4 ans\", \"Terrains de sport\", \"Équipements d'hiver\", \n \"Équipements spécialisés\", \"Autres équipements\", \"Tous les équipements\", \"\"\n)\nmy_table <- knitr::kable(round(groupe_ratios,1), row.names = TRUE, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t\t\t col.names = paste0(\"groupe \",1:6),\n align = c(\"r\", \"r\", \"r\", \"r\", \"r\", \"r\"))\ngroup_rows(my_table,\n index = c(\n \"Équipements pour les 0 à 4 ans (%)\" = 3,\n \"Terrains de sport (%)\" = 7,\n \"Équipements d'hiver (%)\" = 4,\n \"Équipements spécialisés (%)\" = 2,\n \"Autres équipements (%)\" = 2,\n \"Superficie (%)\" = 5,\n \"Nombre moyen d'équipements selon le type\" = 6,\n \"Nombre d'observations par groupe\"\n )\n )\n\n```\n\n* Le premier groupe correspond à de grands parcs (superficie généralement comprise entre 5 et plus de 20 hectares), il comporte 116 observations. Ces grands parcs sont en moyenne équipés de deux terrains de sport et d'un équipement d'hiver. Il s'agit vraisemblablement des grands parcs identifiés dans l'article original, dans lesquels se retrouvent également les parcs à vocation métropolitaine.\n\n* Le second groupe (212 parcs) correspond à de très petits parcs (moins d'un hectare) comportant uniquement une aire de jeu.\n\n* Le troisième groupe (197 parcs) correspond à de petits parcs (entre 1 et 5 hectares), souvent équipés d'une piscine extérieure (27,4 % des cas), et en moyenne de deux terrains de sports (essentiellement des terrains de tennis et de soccer). Ces parcs comprennent en moyenne plus de 4 équipements et doivent donc correspondre à la classe D dans l'article original (Petit parc (1 à 5 ha) avec en moyenne six équipements, dont une patinoire et une piscine).\n\n* Le quatrième groupe (49 parcs) comprend de petits parcs (entre 1 et 5 hectares) qui ressemblent aux parcs du groupe 2 mais tendent à disposer en plus d'un terrain de sport (baseball ou basketball).\n\n* Le quatrième groupe (84 parcs) correspond à de petits parcs, il est caractérisé par une présence plus marquée de pataugeoires (39 %).\n\n* Le cinquième groupe (35 parcs) est très similaire au second groupe (uniquement une aire de jeux), excepté sont les parcs qui s'y trouvent sont de taille supérieure (de 1 à 5 hectares).\n\nConsidérant les différences minimes entre certains des groupes que nous avons obtenus, il est clair que retenir seulement trois ou cinq groupes serait préférable. Notez également l'importance du choix de la distance, car nous obtenons des résultats sensiblement différents de ceux de l'article original en ayant opté pour la distance du $\\Phi^2$ plutôt que la distance euclidienne au carré.\n\n#### Utilisation de la matrice de distance euclidienne au carré {#sec-13344}\n\nPour obtenir des résultats plus proches de ceux de l'article original, nous pouvons reprendre notre analyse et utiliser cette fois-ci une distance euclidienne au carré.\n\n```{r}\n#| label: fig-exampleHclust8\n#| fig-align: center\n#| fig-cap: Valeur de l'indice de silhouette pour différents nombres de groupes (distance euclidienne au carré)\n#| out-width: \"75%\"\n#| message: false\n#| warning: false\n\nX$groupe <- NULL\n# calcule de la matrice de distance\nparc_distances_euc <- dist(as.matrix(X), method = \"Euclidean\")**2\n\n# Application de la CAH\ndendogramme_parcs_euc <- hclust(parc_distances_euc, method = \"ward.D\")\n\n# calcul de l'indice de silhouette\nks <- 2:10\nvalues <- sapply(ks, function(k){\n # découpage du dendrogramme\n groupes <- cutree(dendogramme_parcs_euc, k = k)\n # calcul des valeurs de silhouette\n sil <- silhouette(groupes, dist = parc_distances_euc)\n # extraction de l'indice global (moyenne des moyennes)\n idx <- mean(summary(sil)$clus.avg.widths)\n return(idx)\n})\n\n# création d'un graphique avec les résultats\n\ndf <- data.frame(\n k = ks,\n silhouette = values\n)\n\nggplot(df) + \n geom_line(aes(x = k, y = silhouette)) + \n geom_point(aes(x = k, y = silhouette), color = \"red\") + \n labs(x = \"nombre de groupes\", y = \"indice global de silhouette\")\n```\n\nNous constatons cette fois-ci, que quatre groupes serait probablement le meilleur choix et qu'au-delà de ce nombre, l'indice global de silhouette ne fait que diminuer. Tentons cependant de reproduire les résultats de l'article avec k = 6.\n\n```{r}\n#| label: exampleHclust9\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\nresk6 <- cutree(dendogramme_parcs_euc, k = 6)\n\n# calcul du nombre de fois ou chaque modalité est observée dans un groupe\nX$groupe <- resk6\ndf_groupes <- X %>% \n group_by(groupe) %>% summarise_all(.funs = sum)\n\n# calcul du nombre d'observations par groupe\nnb_gp <- table(resk6)\n\ngroupe_ratios <- round(100 * as.matrix(df_groupes)[,2:ncol(df_groupes)] / as.vector(nb_gp),1)\ngroupe_ratios <- as.data.frame(t(groupe_ratios))\nnames(groupe_ratios) <- paste0(\"groupe \", 1:ncol(groupe_ratios))\n\n# calcul du nombre moyen d'équipements par catégorie par parc\nequip_class <- list(\n c(\"AIRE_JEUX\", \"JEUX_EAU\", \"PATAUGEOIRE\"),\n c(\"ATHLETISME\", \"BASEBALL_S\", \"BASKETBALL\", \"FOOTBALL\", \"SOCCER\", \"TENNIS\", \"VOLLEY_BALL\"),\n c(\"TOBBOGAN_G\", \"PATINOIRE_E\", \"RAQUETTES\", \"SKI_FOND\"),\n c(\"PATIN_ROUE\", \"ROULI_ROUL\"),\n c(\"PISC_EXT\", \"RANDONNEE\")\n)\n\nclass_compte <- data.frame(sapply(equip_class, function(equip){\n rowSums(X[equip])\n}))\nnames(class_compte) <- c(\"enfants\", \"terrain_sport\", \"hiver\", \"specialise\", \"autre\")\nclass_compte$groupe <- resk6\ndf_class_equip <- class_compte %>% \n group_by(groupe) %>% \n summarise_all(mean)\n\ndf_class_equip <- t(df_class_equip[2:ncol(df_class_equip)])\ncolnames(df_class_equip) <- paste0(\"groupe \", 1:ncol(df_class_equip))\n\n# comptage du nombre moyen d'équipements\ndf_equip_tot <- data.frame(\n nb = rowSums(X[1:18]),\n groupe = resk6\n)\ndf_equip_tot_mean <- df_equip_tot %>% \n group_by(groupe) %>% \n summarize_all(mean)\n\n# mise dans l'ordre de la première partie du tableau\nall_types <- do.call(c, equip_class)\nidxs <- match(all_types, row.names(groupe_ratios[1:length(all_types),]))\ngroupe_ratios <- rbind(groupe_ratios[idxs,],\n groupe_ratios[(length(all_types)+1):nrow(groupe_ratios),])\n\n# combinaison des deux tableaux\ngroupe_ratios <- rbind(groupe_ratios, df_class_equip, df_equip_tot_mean$nb, as.integer(nb_gp))\n\n```\n\nRecréons le tableau final des résultats au @tbl-exampleHclust10. Si vous comparez ce tableau avec celui de l'article original, vous verrez que notre groupe 3 correspond exactement à la classe A et que notre groupe 5 correspond exactement à la classe F. Pour les autres groupes, nous pouvons observer de légères variations, ce qui correspond vraisemblablement à des divergences d'implémentation des algorithmes entre le logiciel utilisé pour l'article (SAS) et R.\n\n```{r}\n#| label: tbl-exampleHclust10\n#| tbl-cap: Caractéristiques des groupes obtenus lors de la CAH (distance euclidienne au carré)\n#| echo: false\n#| fig-align: center\n#| message: false\n#| warning: false\nlibrary(kableExtra)\nrow.names(groupe_ratios) <- c(\n \"Aire de jeux\", \"Jeux d'eau\", \"Pataugeoire\", \"Athlétisme\", \"Baseball\", \"Basketball\", \"Football\", \"Soccer (football)\",\n \"Tennis\", \"Volleyball\", \"Glissade\", \"Patinoire\", \"Piste de ski de fond\", \"Raquettes\", \"Parc de planches à roulettes\",\n \"Patins à roues alignées\", \"Piscine extérieure\", \"Chemin de randonnée\", \"Moins d'un hectare\", \"1 à 5 hectares\", \"5 à 10 hectares\",\n \"10 à 20 hectares\", \"20 hectares et plus\", \"Équipements pour les 0 à 4 ans\", \"Terrains de sport\", \"Équipements d'hiver\", \n \"Équipements spécialisés\", \"Autres équipements\", \"Tous les équipements\", \"\"\n)\nmy_table <- knitr::kable(round(groupe_ratios,1),\n row.names = TRUE, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t\t\t\t col.names = paste0(\"groupe \",1:6),\n align=c(\"r\" , \"r\" , \"r\" , \"r\" , \"r\" , \"r\"))\ngroup_rows(my_table,\n index = c(\n \"Équipements pour les 0 à 4 ans (%)\" = 3,\n \"Terrains de sport (%)\" = 7,\n \"Équipements d'hiver (%)\" = 4,\n \"Équipements spécialisés (%)\" = 2,\n \"Autres équipements (%)\" = 2,\n \"Superficie (%)\" = 5,\n \"Nombre moyen d'équipements selon le type\" = 6,\n \"Nombre d'observations par groupe\"\n )\n )\n```\n\n## Nuées dynamiques {#sec-134}\n\nLes méthodes des nuées dynamiques regroupent plusieurs algorithmes, tous plus ou moins liés avec l'algorithme le plus connu : *k-means*, originalement proposé par James MacQueen [-@macqueen1967]. Nous présentons également ici plusieurs variantes du *k-means*, soit le *k-medians*, le *k-medioids*, le *c-means* et le *c-medians*.\n\n### *K-means* {#sec-1341}\n\n#### Fonctionnement de l'algorithme {#sec-13411}\n\nNous commençons ici par détailler le fonctionnement de cet algorithme afin de mieux le cerner. D'emblée, cet algorithme nécessite que certains éléments soient définis d'avance : \n\n* Une matrice de données *X* comportant *n* lignes (nombre d'observations) et *p* colonnes (nombre de variables). Chaque variable de cette matrice doit être quantitative et continue et de préférence dans une échelle standardisée (par exemple des variables centrées réduites).\n\n* Le nombre de groupes à identifier *k* doit être choisi par l'utilisateur ou l'utilisatrice. \n\n* La distance *d* à utiliser entre les observations.\n\nLe fonctionnement classique du *k-means* est le suivant :\n\n1. Définir *k* centres de groupes de façon aléatoire.\n\n2. Déterminer pour chaque observation le centre de son groupe le plus proche en utilisant la fonction de distance.\n\n3. Pour chacun des groupes ainsi formés, recalculer le centre du groupe en calculant le centroïde (moyennes le plus souvent) des observations appartenant à ce groupe.\n\n4. Répéter l'opération 2 avec les nouveaux centres.\n\n5. Calculer l'inertie expliquée par la nouvelle classification.\n\n6. Comparer cette inertie expliquée avec celle obtenue lors de l'itération précédente.\n\n7. Si la variation entre les deux valeurs est supérieure à une certaine limite, reprendre à l'étape 2, sinon, l'algorithme prend fin.\n\nAinsi, l'algorithme *k-means* part d'une première classification obtenue aléatoirement et la raffine jusqu'au point où l'amélioration de la classification devient négligeable. Du fait de ce point de départ aléatoire, cet algorithme est dit heuristique, car deux exécutions risquent de ne pas donner exactement le même résultat. Par conséquent, en relaçant l'algorithme, vous pourriez obtenir des résultats légèrement différents, avec par exemple des groupes similaires, mais obtenus dans un autre ordre, le groupe 1 étant devenu le groupe 3 et vice-versa. Il est aussi possible d'obtenir des résultats radicalement différents d'une tentative à l'autre, ce qui signifie que les groupes formés sont très instables et ne sont pas représentatifs de la population étudiée.\n\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Réplicabilité des résultats dans R**\n:::\n::: bloc_astuce-body\nLorsqu'une méthode heuristique ou faisant appel au hasard est utilisée dans R, il est nécessaire de s'assurer que les résultats sont reproductibles. Cela permet notamment de relancer le même code et de réobtenir exactement les mêmes résultats : l'idée étant de figer le hasard.\n\nUltimement, un programme informatique est incapable de générer un résultat véritablement aléatoire, car il ne fait que suivre une suite d'opérations prédéterminées. Pour générer des résultats qui ressemblent au hasard, des algorithmes ont été proposés, partant d'une configuration initiale et appliquant une série d'opérations complexes permettant de générer des nombres semblant se distribuer aléatoirement. Si nous connaissons le point de départ de la suite d'opérations et que nous réappliquons ces dernières, alors nous sommes certains d'obtenir le même résultat. Il est possible, dans R, de définir un *état initial de hasard* à l'aide de la fonction `set.seed`. Avec ce point de départ défini, nous sommes certains d'obtenir les mêmes résultats en relançant les mêmes opérations. \n\nPrenons un exemple concret en sélectionnant aléatoire 3 chiffres dans un vecteur allant de 1 à 10.\n\n```{r}\n#| warning: false\n#| message: false\nvec <- 1:10\n\n# prenons un premier échantillon\nsample(vec, size = 3)\n\n# et un second échantillon \nsample(vec, size = 3)\n```\nNous obtenons bien deux échantillons différents. Recommençons en utilisant la fonction `set.seed` pour obtenir cette fois-ci des résultats identiques.\n\n```{r}\n#| warning: false\n#| message: false\nvec <- 1:10\n\n# prenons un premier échantillon\nset.seed(123)\nsample(vec, size = 3)\n\n# et un second échantillon \nset.seed(123)\nsample(vec, size = 3)\n\n# prenons un troisème échantillon\nset.seed(4568997)\nsample(vec, size = 3)\n\n# et un quatrième échantillon \nset.seed(4568997)\nsample(vec, size = 3)\n```\n\nVous constatez que nous utilisons cette fonction plusieurs fois au cours de cette section. Elle nous permet de nous assurer que les résultats obtenus ne changent pas entre le moment où nous écrivons le livre et le moment où nous le formatons. Sinon, le texte pourrait ne plus être en phase avec les images ou les tableaux.\n:::\n:::\n\nPour mieux comprendre le fonctionnement du *k-means*, nous proposons ici une visualisation de ses différentes itérations (@fig-kmeansA). \nNous pouvons constater que, pour ce jeu de données relativement simple, l'algorithme converge très rapidement et que sa solution varie peu au-delà de la troisième itération. \nL'amination de la @fig-kmeansA illustre pourquoi le *k-means* est appelé algorithme de nuées dynamiques.\n\n![Algorithme K-means](images/Chap13/kmeansGif.gif){#fig-kmeansA width=\"80%\" fig-align=\"center\"}\n\n```{r}\n#| label: fig-kmeansA2\n#| eval: false\n#| message: false\n#| warning: false\n#| include: false\nX <- data.frame(\n x = c(rnorm(50,0,0.5), rnorm(50,5,1.5), rnorm(50,7,1), rnorm(50,6,1), rnorm(50,2.75,1.5)),\n y = c(rnorm(50,0,0.5), rnorm(50,2.5,1), rnorm(50,0,0.5), rnorm(50,2,1), rnorm(50,1,0.5))\n)\n\nX$oid <- 1:nrow(X)\n \ncenters <- data.frame(\n x = c(1,7.5,4,7),\n y = c(2,2.5,5,3)\n)\n\ngp <- apply(X,1, function(r){\n dists <- sqrt((r[[1]] - centers$x)**2 + (r[[2]] - centers$y)**2)\n (1:length(dists))[dists == min(dists)]\n})\nX$groupe <- as.factor(gp)\ncenters$groupe <- as.factor(1:nrow(centers))\n\n# CAS 1 : Sortie HTML (un joli Gif)\nif(knitr::is_latex_output() == FALSE){\n library(gganimate)\n X$iter <- 1\n centers$iter <- 1\n \n Xtot <- X\n centerstot <- centers\n \n for (i in 2:4){\n rez <- kmeans(X[, c(1,2)], centers = centers[, c(1,2)], iter.max = 1)\n X$groupe <- as.factor(rez$cluster)\n centers <<- data.frame(rez$centers)\n centers$groupe <- as.factor(1:nrow(centers))\n X$iter <- i\n centers$iter <- i\n \n Xtot <- rbind(Xtot, X)\n centerstot <- rbind(centerstot, centers)\n }\n \n ggplot(Xtot) + \n geom_point(aes(x = x, y = y, color = groupe, group = oid)) + \n geom_point(data = centerstot, mapping = aes(x = x, y = y, fill = groupe),\n pch = 21, colour = \"black\", size = 3) + \n transition_states(iter, transition_length = 2,\n state_length = 1) + \n ggtitle(\"Itération {closest_state}\") \n\n}else{\n X2 <- X\n # CAS 2 : Sortie PDF (une simple figure)\n\n plot1 <- ggplot(X2) + \n geom_point(aes(x = x, y = y, color = groupe)) + \n geom_point(data = centers, mapping = aes(x = x, y = y, fill = groupe),\n pch = 21, colour = \"black\", size = 3) + \n ggtitle(\"Itération 1\")\n \n plots <- list(plot1)\n for(i in 2:4){\n centers$groupe <- NULL\n rez <- kmeans(X[, c(1,2)], centers = centers[, c(1,2)], iter.max = 1)\n \n X2$groupe <- as.factor(rez$cluster)\n \n centers <- data.frame(rez$centers)\n centers$groupe <- as.factor(1:nrow(centers))\n \n new_plot <- ggplot(X2) + \n geom_point(aes(x = x, y = y, color = groupe)) + \n geom_point(data = centers, mapping = aes(x = x, y = y, fill = groupe),\n pch = 21, colour = \"black\", size = 3)+ \n ggtitle(paste0(\"Itération \", i))\n plots[[i]] <- new_plot\n \n }\n ggarrange(plotlist = plots, common.legend = TRUE, ncol = 2, nrow = 2, legend = \"none\")\n \n}\n```\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Centre de groupe et _k-means_**\n:::\n::: bloc_notes-body\nÀ nouveau, puisque chaque itération du *k-means* nécessite de recalculer les centres des groupes formés, des problèmes peuvent être rencontrés avec certains types de distance. C'est pourquoi il est recommandé d'utiliser la distance euclidienne avec le *k-means* original. Si des distances plus complexes doivent être utilisées, il est préférable d'utiliser la classification ascendante hiérarchique.\n:::\n:::\n\n#### Choix du nombre optimal de groupes {#sec-13412}\n\nComme pour la CAH, le principal enjeu avec le *k-means* est de déterminer le nombre idéal de groupes pour effectuer la classification. Si ce nombre n'est pas connu à l'avance et qu'aucune forte justification théorique n'existe, il est possible d'utiliser les mêmes techniques que pour la CAH, soit la méthode du coude, l'indicateur de silhouette ou la méthode GAP.\n\n\n### K-médianes {#sec-1342}\n\nLe *k-medians* est une variante du *k-means*. Contrairement au *k-means* privilégiant la distance euclidienne, le *k-medians* est à utiliser en priorité avec une distance de Manhattan. En effet, le centre d'un groupe n'est pas déterminé comme la moyenne des variables des observations appartenant à ce groupe (*k-means*), mais comme la médiane pour chaque variable (*k-medians*). En dehors de ces deux spécificités, il reprend le fonctionnement décrit plus haut pour le *k-means*. Il est particulièrement pertinent de l'utiliser quand un jeu de données comprend un très grand nombre de colonnes, car dans ce contexte, la distance euclidienne peine à représenter les différences entre les observations. De plus, l'utilisation de la médiane le rend moins sensible aux valeurs extrêmes.\n\n\n### K-médoïds {#sec-1343}\n\nLe *k-médoïds* est également une variante du *k-means*. Le *k-means* crée des groupes en cherchant les centres de ces groupes dans l'espace multidimensionnel des données. Ces centres de groupes peuvent très bien ne pas correspondre à un point du jeu de données, au même titre que la moyenne d'une variable ne coïncide que rarement avec une observation réelle de cette variable. Pour le *k-médoïds*, les groupes sont formés en cherchant les centres de ces groupes **parmi** les observations du jeu de données. Ainsi, chaque groupe est centré sur une observation réelle, la plus similaire à l'ensemble des observations du groupe.\n\nL'algorithme effectue les opérations suivantes : \n\n1. Sélectionner aléatoirement *k* observations du jeu de données, elles constituent les centres des groupes initiaux.\n\n2. Attribuer chaque observation au centre du groupe le plus proche.\n\n3. Tant que la nouvelle solution est plus efficace, effectuer les opérations suivantes : \n * pour chaque centre *m* et pour chaque observation *o*,\n * considérer l'inversion de *m* et *o*\n * si cette permutation est meilleure que les précédentes, la conserver en mémoire\n * effectuer la meilleure permutation retenue si elle améliore la classification, sinon l'algorithme prend fin.\n \nLe *k-médoïds* est moins utilisé que le *k-means*, mais il est plus performant quand des distances autres que la distance euclidienne sont utilisées ou encore que des valeurs aberrantes/extrêmes sont présentes dans les données.\n\n### Mise en œuvre dans R {#sec-1344}\n\nPour cet exemple, nous proposons d'utiliser le jeu de données spatiales `LyonIris` du *package* `geocmeans`. Ce jeu de données spatiales pour l'agglomération lyonnaise (France) comprend dix variables, dont quatre environnementales (EN) et six socioéconomiques (SE), pour les îlots regroupés pour l'information statistique (IRIS) de l'agglomération lyonnaise (@tbl-datageocmeans et @fig-datacartoacp). Nous proposons de réaliser une analyse similaire à celle de l'article de @2021_4, soit de classer les IRIS de Lyon selon ces caractéristiques pour déterminer si certains groupes d'IRIS combinent des situations désavantageuses sur les plans sociaux et environnementaux, dans une perspective d'équité environnementale.\n\nNotez ici que la fonction `st_drop_geometry` provenant du package `sf` permet de retirer l'information géographique du jeu de données `LyonIris` pour obtenir un simple `dataframe`.\n\n```{r}\n#| label: tbl-datageocmeans\n#| tbl-cap: Statistiques descriptives du jeu de données LyonIris\n#| echo: false\n#| message: false\n#| warning: false\nlibrary(geocmeans)\nlibrary(sf)\n\ndata(LyonIris)\nData <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\",\n \"Pct0_14\" , \"Pct_65\" , \"Pct_Img\",\n \"TxChom1564\" , \"Pct_brevet\" , \"NivVieMed\")])\n\nintitule <- c(\"Bruit routier (Lden dB(A))\",\n \"Dioxyde d'azote (ug/m^3^)\",\n \"Particules fines (PM$_{2,5}$)\",\n \"Canopée (%)\",\n \"Moins de 15 ans (%)\",\n \"65 ans et plus (%)\",\n \"Immigrants (%)\",\n \"Taux de chômage\",\n \"Personnes à faible scolarité (%)\",\n \"Médiane du niveau de vie (Euros)\" )\n\nstats <- data.frame(variable = names(Data),\n nom = intitule,\n type = c(\"EN\" , \"EN\" , \"EN\" , \"EN\" , \"SE\" , \"SE\" , \"SE\" , \"SE\" , \"SE\" , \"SE\"),\n moy = round(sapply(Data, mean), 2),\n et = round(sapply(Data, sd), 2), \n minimum = round(sapply(Data, min), 2), \n maximum = round(sapply(Data, max), 2)\n )\nknitr::kable(stats,\n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t digits = 1,\n col.names = c(\"Nom\" , \"Intitulé\" , \"Type\" , \"Moy.\", \"E.-T.\", \"Min.\", \"Max.\"),\n align= c(\"l\" , \"l\", \"c\" , \"r\", \"r\", \"r\", \"r\")\n )\n```\n\n\n#### Préparation des données {#sec-13441}\n\nLa première étape consiste donc à charger les données et à les préparer pour l'analyse. Toutes les variables que nous utilisons sont des variables continues. Cependant, elles ne sont pas exprimées dans la même échelle, nous proposons donc de les standardiser ici en les centrant (moyenne = 0) et en les réduisant (écart-type = 1). Cette opération peut être effectuée simplement dans R en utilisant la fonction `scale`.\n\n```{r}\n#| label: kmeansB\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n# Chargement des données\nlibrary(geocmeans)\nlibrary(sf)\n\ndata(LyonIris)\n\n# NB : LyonIris est un objet spatial, il faut donc extraire uniquement son DataFrame\nX <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\" , \"Pct0_14\" , \"Pct_65\" , \"Pct_Img\",\n \"TxChom1564\" , \"Pct_brevet\" , \"NivVieMed\")])\n\n# Centrage et réduction de chaque colonne du DataFrame\nfor (col in names(X)){\n X[[col]] <- scale(X[[col]], center = TRUE, scale = TRUE)\n}\n\n```\n\n#### Choix du nombre de groupes optimal {#sec-13442}\n\nLa seconde étape consiste à déterminer le nombre de groupes optimal. Pour cela, nous comparons les résultats des trois méthodes proposées : la méthode du coude, l'indice de silhouette et la méthode GAP. Pour chaque méthode, nous testons les nombres de groupes de 2 à 10.\n\n##### Méthode du coude {#sec-134421}\n\nCommençons par appliquer la méthode du coude. Nous calculons donc l'inertie expliquée par la classification pour différentes valeurs de *k* (nombre de groupes) avant de construire la @fig-kmeansC.\n\n```{r}\n#| label: fig-kmeansC\n#| message: false\n#| fig-cap: Inertie expliquée pour différents nombres de groupes pour le k-means\n#| warning: false\n#| out-width: \"75%\"\nks <- 2:10\n\n## ---- Méthode du coude ---- ##\ninertie_exps <- sapply(ks, function(k){\n # calcul du kmeans avec k\n resultat <- kmeans(X, centers = k)\n # calcul de l'inertie expliquée (1 - inertie intragroupe / inertie totale)\n inertie_exp <- 1-(sum(resultat$withinss) / resultat$totss)\n return(inertie_exp)\n})\n\ndf <- data.frame(\n k = ks,\n inertie_exp = inertie_exps\n)\n\nggplot(df) + \n geom_line(aes(x = k, y = inertie_exp)) + \n geom_point(aes(x = k, y = inertie_exp), color = \"red\") + \n labs(x = \"nombre de groupes\", y = \"inertie expliquée (%)\")\n\n\n```\nDans l'article original, quatre groupes avaient été retenus. Nous pouvons constater ici qu'un coude fort se situe à k = 3 et qu'au-delà de cette limite, l'ajout d'un groupe supplémentaire contribue à expliquer une plus petite partie de l'inertie supplémentaire comparativement au précédent.\n\n##### Indice de silhouette {#sec-134422}\n\nPoursuivons avec l'indice de silhouette calculé de nouveau avec des valeurs de *k* allant de 2 à 10. Notez que nous devons au préalable créer une matrice de distances entre les observations du jeu de données pour construire notre indice de silhouette. Puisque nous utilisons l'algorithme *k-means*, nous utilisons la distance euclidienne.\n\n```{r}\n#| label: fig-kmeansD\n#| fig-cap: Indice de silhouette pour différents nombres de groupes pour le k-means\n#| out-width: \"75%\"\n#| message: false\n#| warning: false\nks <- 2:10\n\n# calcul d'une matrice de distance euclidienne entre les observations\ndist_mat <- dist(X, method = \"euclidean\")\n\n## ---- indice de silhouette ---- ##\nvalues <- sapply(ks, function(k){\n resultat <- kmeans(X, centers = k)\n groupes <- resultat$cluster\n # calcul des valeurs de silhouette\n sil <- silhouette(groupes, dist = dist_mat)\n # extraction de l'indice global (moyenne des moyennes)\n idx <- mean(summary(sil)$clus.avg.widths)\n return(idx)\n})\n\ndf <- data.frame(\n k = ks,\n silhouette = values\n)\n\nggplot(df) + \n geom_line(aes(x = k, y = silhouette)) + \n geom_point(aes(x = k, y = silhouette), color = \"red\") + \n labs(x = \"nombre de groupes\", y = \"Indice de silhouette\")\n\n\n```\n\nÀ nouveau, la @fig-kmeansD indique que le nombre de groupes optimal est trois selon l'indice de silhouette.\n\n##### Méthode GAP {#sec-134423}\n\nPour appliquer la méthode GAP, nous proposons d'utiliser la fonction `clusGap` du *package* `NbClust`. Pour l'utiliser, il est nécessaire de définir une fonction renvoyant pour le nombre de groupes *k* et le jeu de données *x* une liste comprenant un vecteur attribuant chaque observation à chaque groupe. Il est possible de considérer ce type de fonction comme un « adaptateur ».\n\n```{r}\n#| label: fig-kmeansE\n#| out-width: \"75%\"\n#| fig-cap: Méthode GAP pour différents nombres de groupes pour le k-means\n#| fig-align: center\n#| message: false\n#| warning: false\nlibrary(NbClust)\n\n# définition de la fonction adaptateur\nadaptor <- function(x, k){\n clust <- kmeans(x, k)\n return(list(\n \"cluster\" = clust$cluster\n ))\n}\n\n# calcul de la méthode GAP\nvals <- clusGap(X, adaptor, K.max = 10, verbose = FALSE)\ntab <- data.frame(vals$Tab)\ntab$k <- 1:nrow(tab)\n\n# détermination des valeurs de k retenues par la méthode (1ere et 2e)\nis_valid <- sapply(2:nrow(tab), function(i){\n tab[i-1,\"gap\"] >= (tab[i,\"gap\"] - tab[i,\"SE.sim\"])\n})\nvalids <- subset(tab, is_valid)[1,]\nvalids2 <- subset(tab, is_valid)[2,]\n\n# réalisation du graphique\nggplot(tab) + \n geom_line(aes(x = k, y = gap)) + \n geom_segment(x = valids$k, xend = valids$k, y = min(tab$gap), yend = valids$gap, \n linetype = \"dashed\") +\n geom_segment(x = valids2$k, xend = valids2$k, y = min(tab$gap), yend = valids2$gap, \n linetype = \"dashed\") +\n geom_point(aes(x = k, y = gap), color = \"red\") + \n scale_x_continuous(breaks = 1:10) + \n labs(x = \"nombre de groupes\", y = \"GAP\")\n \n\n```\nLa @fig-kmeansE indique également que le nombre de groupes à retenir est trois. Nous retenons cependant quatre groupes pour pouvoir plus facilement comparer nos résultats avec ceux de l'article original.\n\n#### Application l'algorithme du *k-means* {#sec-13443}\n\nMaintenant que nous avons choisi le nombre de groupes à former, nous pouvons simplement appliquer la fonction `kmeans` présente de base dans R.\n\n```{r}\n#| label: kmeansF\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nset.seed(145)\nresultats <- kmeans(X, centers = 4)\n```\n\n#### Interprétation des résultats {#sec-13444}\n\nUne fois les groupes obtenus, l'étape la plus importante est de parvenir à interpréter ces groupes. Pour cela, il est nécessaire de les explorer en profondeur au travers des variables utilisées pour les constituer. Dans notre cas, le jeu de données `LyonIris` est spatialisé, nous pouvons donc commencer par cartographier les groupes.\n\n```{r}\n#| label: fig-kmeansG\n#| fig-cap: Cartographie des groupes obtenus avec la méthode du k-means\n#| fig-align: center\n#| out-width: \"75%\"\n#| message: false\n#| warning: false\nlibrary(tmap)\nLyonIris$groupes <- paste(\"groupe\", resultats$cluster, sep = \" \")\n\ntm_shape(LyonIris) + \n tm_polygons(col = \"groupes\", palette =\n c(\"#EFBE89\", \"#4A6A9F\", \"#7DB47C\", \"#FAF29C\"), lty = 1, lwd = 0.1)\n\n```\n\nIl est ainsi possible de constater que le groupe 3 forme un ensemble assez compact d'IRIS au centre de Lyon. Le groupe 4 correspond quant à lui à des IRIS situés en périphérie plutôt éloignée, essentiellement à l'ouest. Le groupe 1 correspond à une périphérie proche du groupe 2 et apparaît comme un ensemble d'enclaves dispersées.\n\nPour distinguer rapidement les profils des différents groupes, il est possible d'utiliser un graphique en radar. La construction d'un tel graphique peut être un peu fastidieuse dans R, cependant le *package* `geocmeans` propose une fonction assez pratique : `spiderPlots`.\n\n```{r}\n#| label: fig-kmeansH\n#| fig-cap: Graphiques en radar pour les groupes issus du k-means\n#| fig-align: center\n#| out-width: \"90%\"\n#| message: false\n#| warning: false\n\nlibrary(geocmeans)\n\n# création d'une matrice d'appartenance binaire des groupes\nmatrice_gp <- fastDummies::dummy_cols(resultats$cluster, remove_selected_columns = TRUE)\n\n# réalisation du graphique\npar(mfrow=c(3,2), mai = c(0.1,0.1,0.1,0.1))\nplots <- spiderPlots(X, matrice_gp, \n chartcolors = c(\"#EFBE89\", \"#4A6A9F\", \"#7DB47C\", \"#FAF29C\"))\n\n```\n\nIl est ainsi possible de constater, à la @fig-kmeansH, que le groupe 3 est caractérisé par un niveau de vie élevé, mais par des niveaux de concentration de pollution atmosphérique plus élevés également. Le groupe 4 en revanche est caractérisé par un important couvert végétal, un niveau de vie médian élevé et une plus forte proportion de personnes de plus de 65 ans. Le groupe 1 est quant à lui marqué par des niveaux sonores plus élevés. Enfin, le groupe 2 se caractérise par une plus grande proportion de population ayant obtenu comme diplôme le plus élevé le brevet des collèges, d'immigrants, de jeunes de moins de 15 ans et un taux de chômage plus élevé.\n\nNotez que ces graphiques nous permettent rapidement de nous faire une idée des caractéristiques des groupes, mais uniquement sur une échelle relative. En effet, ils ne nous indiquent à aucun moment la taille des écarts entre les groupes. Pour cela, il est nécessaire de réaliser des graphiques en violon pour chaque variable. Pour ce type de graphique, il est préférable d'utiliser les données originales non transformées pour pouvoir mieux appréhender si les différences entre les groupes sont importantes ou négligeables.\n\n```{r}\n#| label: fig-kmeansI\n#| fig-cap: Graphiques en violon pour les groupes issus du k-means\n#| out-width: \"100%\"\n#| fig-align: center\n#| message: false\n#| warning: false\nlibrary(ggpubr)\nX2 <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\" , \"Pct0_14\",\n \"Pct_65\" , \"Pct_Img\" , \"TxChom1564\" , \"Pct_brevet\",\n \"NivVieMed\")])\n\nplots <- violinPlots(X2, as.character(resultats$cluster))\nggarrange(plotlist = plots, ncol = 2, nrow = 5)\n```\n\nIl est également recommandé de calculer des statistiques descriptives par groupe et de les rapporter dans un tableau.\n\n```{r}\n#| label: kmeansJ\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"100%\"\n# obtention d'un tableau par groupe\ntableaux <- summarizeClusters(X2, matrice_gp, dec = 1, silent = TRUE)\n\n# concaténation des tableaux\ntableau_tot <- do.call(rbind, tableaux)\n```\n\n```{r}\n#| label: tbl-kmeansK\n#| tbl-cap: Descriptions des quatre groupes obtenus\n#| echo: false\n#| fig-align: center\n#| message: false\n#| warning: false\nlibrary(fastDummies)\n\ntableau_tot2 <- apply(tableau_tot, MARGIN = 2, unlist)\ntableau_tot <- data.frame(tableau_tot2)\ntableau_tot$stat <- rep(row.names(tableaux[[1]]),4)\ntableau_tot <- tableau_tot[, c(\"stat\", names(X2))]\n\nok_col_names <- gsub(\"_\" , \"\", names(X2), fixed = TRUE)\n\nmy_table <- knitr::kable(tableau_tot, row.names = FALSE, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t\t\t digits = 1,\n col.names = c(\"\", ok_col_names), \n align = c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\"))\n\nmy_table2 <- group_rows(my_table,\n index = c(\n \"groupe 1\" = 9,\n \"groupe 2\" = 9,\n \"groupe 3\" = 9,\n \"groupe 4\" = 9\n )\n )\n\nmy_table2 <- gsub(pattern = \"NApadding\", replacement = \"padding\",x = my_table2, fixed = TRUE)\nmy_table2 <- gsub(pattern = \"\", replacement = '',x = my_table2, fixed = TRUE)\nmy_table2\n```\n\nLes constats que nous avons faits précédemment sont confirmés par la @fig-kmeansI et le @tbl-kmeansK. Nous retrouvons ici les groupes originaux décrits dans l'article de @2021_4 : \n\n* **Groupe 1** : les espaces interstitiels, formant une périphérie proche du centre et relativement hétérogène sur les variables étudiées, mais caractérisée par des niveaux de bruit importants.\n\n* **Groupe 2** : les banlieues jeunes et défavorisées, avec des niveaux d'exposition aux pollutions atmosphérique et sonore relativement élevés comparativement à l'ensemble de la région.\n\n* **Groupe 3** : les quartiers centraux aisés, mais marqués par les plus hauts niveaux de pollution atmosphérique.\n\n* **Groupe 4** : les communes rurales, aisées et vieillissantes.\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Interprétation interactive**\n:::\n::: bloc_astuce-body\nSi, comme dans notre exemple, vos données comportent une dimension spatiale, le *package* `geocmeans` propose une fonction intéressante appelée `sp_clust_explorer` démarrant une application permettant d'explorer les résultats de votre classification. Le seul enjeu est de créer un objet de la classe `FCMres`. Voici un court exemple : \n\n```{r}\n#| label: kmeansK2\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"100%\"\n#| eval: false\n\n# création d'une matrice binaire d'appartenance\nkmeans_mat <- dummy_cols(resultats$cluster, remove_selected_columns = TRUE)\n\n# extraction des centres de notre classification\ncentres <- resultats$centers\n\n# création de l'objet FCMres\nkmeansres <- FCMres(list(\n \"Centers\" = centres,\n \"Belongings\" = kmeans_mat,\n \"Data\" = X2,\n \"m\" = 1,\n \"algo\" = \"kmeans\"\n))\n\n# démarrage de l'application shiny\nsp_clust_explorer(object = kmeansres, spatial = LyonIris)\n\n```\n:::\n:::\n\n#### K-médianes et K-médoides {#sec-13455}\n\nNous présentons simplement ici comment effectuer la même analyse en utilisant les variantes du *k-means*, soit le *k-medians* et le *k-mediods*.\n\nIl existe relativement peu d'implémentation du *k-medians* dans R, nous optons donc ici pour la fonction `kGmedian` du *package* `Gmedian`. Pour le *k-mediods*, nous avons retenu la fonction `pam` du *package* `cluster`.\n\n```{r}\n#| label: kmeansL\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"100%\"\n\nlibrary(Gmedian)\nk_median_res <- kGmedian(X, 4)\n\nlibrary(cluster)\nk_mediods_res <- pam(X,4)\n\n```\n\nJuste pour le plaisir des yeux, nous pouvons cartographier les trois classifications obtenues en nous assurant au préalable de faire coïncider les groupes les plus similaires de nos trois classifications.\n\n```{r}\n#| label: fig-kmeansM\n#| fig-cap: Comparaison géographique des résultats obtenus pour le k-means, le k-medians et le k-medoids\n#| fig-align: center\n#| out-width: \"100%\"\n#| message: false\n#| warning: false\n\nmatrice_gp_kmeans <- dummy_cols(resultats$cluster,\n remove_selected_columns = TRUE)\nmatrice_gp_kmedians <- dummy_cols(as.vector(k_median_res$cluster),\n remove_selected_columns = TRUE)\nmatrice_gp_kmedioids <- dummy_cols(k_mediods_res$cluster,\n remove_selected_columns = TRUE)\n\n# Appariement des groupes du k-medians avec ceux du kmeans\nmatrice_gp_kmedians <- geocmeans::groups_matching(as.matrix(matrice_gp_kmeans),\n as.matrix(matrice_gp_kmedians))\n\n# Appariement des groupes du k-medioids avec ceux du kmeans\nmatrice_gp_kmedioids <- geocmeans::groups_matching(as.matrix(matrice_gp_kmeans),\n as.matrix(matrice_gp_kmedioids))\n\n# ajouts des colonnes nécessaires à LyonIris\ncolnames(matrice_gp_kmeans) <- paste0(\"groupe_\", 1:4)\ncolnames(matrice_gp_kmedians) <- paste0(\"groupe_\", 1:4)\ncolnames(matrice_gp_kmedioids) <- paste0(\"groupe_\", 1:4)\n\nLyonIris$kmeans <- colnames(matrice_gp_kmeans)[max.col(matrice_gp_kmeans)]\nLyonIris$kmedians <- colnames(matrice_gp_kmedians)[max.col(matrice_gp_kmedians)]\nLyonIris$kmedioids <- colnames(matrice_gp_kmedioids)[max.col(matrice_gp_kmedioids)]\n\n# construction de la figure\ncouleurs <- c(\"#EFBE89\", \"#4A6A9F\", \"#7DB47C\", \"#FAF29C\")\n\nmap1 <- tm_shape(LyonIris) + \n tm_polygons(col = \"kmeans\", palette = couleurs, lty = 1, lwd = 0.1)\nmap2 <- tm_shape(LyonIris) + \n tm_polygons(col = \"kmedians\", palette = couleurs, lty = 1, lwd = 0.1)\nmap3 <- tm_shape(LyonIris) + \n tm_polygons(col = \"kmedioids\", palette = couleurs, lty = 1, lwd = 0.1)\n\ntmap_arrange(map1, map2, map3, \n ncol = 2, nrow = 2)\n\n```\n\nLes trois cartes sont très similaires (@fig-kmeansM), ce qui signifie que les trois algorithmes tendent à attribuer les observations aux mêmes groupes. Cependant, nous observons des différences, notamment au nord avec des observations alternant entre les groupes 2 et 3 selon la méthode employée. Cela peut notamment signifier que ces observations sont « indécises », qu'il est difficile de les attribuer définitivement à une catégorie en particulier. Pour prendre en compte cette forme d'incertitude, il est possible d'opter pour des méthodes de classification en logique floue.\n\n### Extensions en logique floue : *c-means*, *c-medoids* {#sec-1346}\n\nComme nous l'avons mentionné en introduction de cette section, les méthodes de classification floues ont pour objectif d'évaluer le degré d'appartenance de chaque observation à chaque groupe plutôt que d'attribuer chaque observation à un seul groupe. Il est ainsi possible de repérer des observations incertaines, à cheval entre plusieurs groupes. Nous présentons ici deux algorithmes appartenant à cette famille : le *c-means* et le *c-medoids*. Il s'agit dans les deux cas d'extensions des *k-means* et *k-medoids* vus précédemment.\n\nPour ces deux méthodes, comme pour le *k-means*, le nombre de groupes *k* doit être spécifié. Elles comprennent cependant un paramètre supplémentaire : *m*, appelé paramètre de floutage qui contrôle à quel point le résultat obtenu sera flou ou strict. Une valeur de 1 produit une classification stricte (chaque observation appartient à un seul groupe) et une valeur plus grande conduit à des classifications de plus en plus floues, jusqu'à ce que chaque observation appartienne à un degré identique à chacun des groupes. Il est recommandé de sélectionner *m* en même temps que *k*, car ces deux valeurs influencent simultanément la qualité de la classification. La meilleure approche consiste à tester un ensemble de combinaisons de *m* et de *k* et à comparer les valeurs obtenues pour différents indicateurs de qualité de classification floue. Parmi ces indicateurs, il est notamment recommandé d'utiliser le pourcentage de l'inertie expliquée, l'indice de silhouette pour classification floue, l'indice de Xie et Beni [-@xie1991validity], et de Fukuyama et Sugeno [@fukuyama1989].\n\n#### Mise en œuvre du *c-means* dans R {#sec-13461}\n\nLe *package* `fclust` comprend un très grand nombre de méthodes pour effectuer des classifications floues, nous l'utilisons donc en priorité ici en combinaison avec des fonctions d'interprétation du *package* `geocmeans`.\n\n##### Préparation des données\n\nComme pour le *k-means*, cette méthode nécessite de disposer d'un jeu de données ne comprenant que des variables quantitatives dans la même échelle. Nous commençons donc à nouveau par standardiser nos données. Pour varier les plaisirs, nous optons cette fois-ci pour une transformation des variables dans une échelle allant de 0 à 100.\n\n```{r}\n#| label: cmeansA\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nlibrary(fclust)\n\ndata(LyonIris)\n\n# NB : LyonIris est un objet spatial, il faut donc extraire uniquement son DataFrame\nX <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\" , \"Pct0_14\",\n \"Pct_65\" , \"Pct_Img\",\n \"TxChom1564\" , \"Pct_brevet\" , \"NivVieMed\")])\n\n# changement d'échelle des données (0 à 100)\nto_0_100 <- function(x){\n return((x-min(x)) / (max(x) - min(x)) * 100)\n}\n\nfor (col in names(X)){\n X[[col]] <- to_0_100(X[[col]])\n}\n\n```\n\n##### Sélection de *k* et de *m*\n\nLa seconde étape consiste à sélectionner les valeurs optimales pour *k* et *m*. Nous testons ici toutes les valeurs de k de 2 à 7, et les valeurs de *m* de 1,5 à 2,5 (avec des écarts de 0,1).\n\n```{r}\n#| label: fig-cmeansB\n#| fig-align: center\n#| fig-cap: Sélection des paramètres k et m pour l'algorithme c-means\n#| out-width: \"75%\"\n#| message: false\n#| warning: false\nlibrary(e1071)\nset.seed(123)\nms <- seq(1.5,2.5,by = 0.1)\nks <- 2:7\n\n\n# calcul de toutes les combinaisons\ncombinaisons <- expand.grid(ms, ks)\n\neval_indices <- c(\"Explained.inertia\", \"Silhouette.index\", \"FukuyamaSugeno.index\")\n\nvalues <- apply(combinaisons, MARGIN = 1, FUN = function(row){\n m <- row[[1]]\n k <- row[[2]]\n resultats <- FKM(X, k, m)\n idx <- geocmeans::calcqualityIndexes(as.matrix(X),\n as.matrix(resultats$U), \n m = m,\n indices = eval_indices)\n return(c(k, m, unlist(idx)))\n})\n\ndf_scores <- data.frame(t(values))\nnames(df_scores) <- c(\"k\", \"m\", \"inertie\", \"silhouette\", \"FukuyamaSugeno\")\n\n# changer l'échelle de l'indice pour un graphique plus joli\ndf_scores$FukuyamaSugeno <- round(df_scores$FukuyamaSugeno/10000,2)\n\n# création de trois figures pour représenter les trois indicateurs\nlibrary(viridis)\n\nplot1 <- ggplot(df_scores) + \n geom_raster(aes(x = k, y = m, fill = inertie)) + \n scale_fill_viridis() + \n scale_x_continuous(breaks = c(2,3,4,5,6,7)) +\n coord_fixed(ratio=4) + \n guides(fill = guide_colourbar(barwidth = 5, barheight = 0.5)) +\n labs(fill = \"Inertie expliquée\") + \n theme(legend.position = \"bottom\", legend.box = \"horizontal\",\n legend.title = element_text( size=9), legend.text=element_text(size=8))\n\nplot2 <- ggplot(df_scores) + \n geom_raster(aes(x = k, y = m, fill = silhouette)) + \n scale_fill_viridis() + \n scale_x_continuous(breaks = c(2,3,4,5,6,7)) +\n coord_fixed(ratio=4) + \n guides(fill = guide_colourbar(barwidth = 5, barheight = 0.5)) +\n labs(fill = \"Indice de silhouette\") + \n theme(legend.position = \"bottom\", legend.box = \"horizontal\",\n legend.title = element_text( size=9), legend.text=element_text(size=8))\n\nplot3 <- ggplot(df_scores) + \n geom_raster(aes(x = k, y = m, fill = FukuyamaSugeno)) + \n scale_fill_viridis() + \n scale_x_continuous(breaks = c(2,3,4,5,6,7)) +\n coord_fixed(ratio=4) + \n guides(fill = guide_colourbar(barwidth = 5, barheight = 0.5)) +\n labs(fill = \"Indice de Fukuyama et Sugeno\") + \n theme(legend.position = \"bottom\", legend.box = \"horizontal\",\n legend.title = element_text( size=9), legend.text=element_text(size=8))\n\nggarrange(plot1, plot2, plot3, ncol = 2, nrow = 2)\n```\n\nLes trois graphiques à la @fig-cmeansB semblent indiquer des solutions différentes. Sans surprise, augmenter le niveau de flou (*m*) réduit l'inertie expliquée, alors qu'augmenter le nombre de groupes (*k*) augmente l'inertie expliquée. L'indice de silhouette indique assez clairement que le nombre de trois groupes serait le meilleur choix, suivi par deux ou quatre groupes, si *m* est inférieur à 1,8. Cependant, ne retenir que trois groupes ne permet d'expliquer que 30% de l'inertie. Afin de nous rapprocher des résultats de l'article original [@2021_4], nous retenons `m = 1,5` et `k = 4`.\n\n##### Application l'algorithme *c-means*\n\nAvec *k* et *m* définis, il ne reste plus qu'à appliquer l'algorithme à nos observations.\n\n```{r}\n#| label: cmeansC\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\nset.seed(123)\ncmeans_resultats <- FKM(X, 4, 1.5)\n```\n\nL'objet obtenu `cmeans_resultats` contient les résultats de la classification. Plus spécifiquement, `cmeans_resultats$U` est la matrice d'appartenance, soit une matrice de taille *n* x *k*, dont chaque case $U_{ij}$ indique la probabilité pour l'observation *i* d'appartenir au groupe *j*. `cmeans_resultats$H` contient le centre des groupes, et `cmeans_resultats$Clus`, le groupe auquel chaque observation à le plus de chances d'appartenir. Pour comparer plus facilement nos résultats avec ceux du *k-means*, nous pouvons changer l'ordre des groupes obtenus pour les faire coïncider avec les groupes les plus similaires obtenus avec la méthode *k-means*.\n\n```{r}\n#| label: cmeansC2\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"75%\"\n\n# changeons l'ordre des groupes\nU <- cmeans_resultats$U\nU2 <- geocmeans::groups_matching(as.matrix(matrice_gp_kmeans), as.matrix(U))\n\n# mais aussi du centre des classes\nidx <- as.integer(gsub(\"Clus \" , \"\", colnames(U2), fixed = TRUE))\nH2 <- cmeans_resultats$H[idx,]\n\n# et recalcul du groupe le plus probable\nClus2 <- data.frame(\n \"Cluster\" = (1:4)[max.col(U2, ties.method=\"first\")],\n \"Membership degree\" = apply(U2, MARGIN = 1, max)\n)\n\ncolnames(U2) <- paste(\"Clus\",1:4, sep = \" \")\nrownames(H2) <- paste(\"Clus\",1:4, sep = \" \")\n\ncmeans_resultats$U <- U2\ncmeans_resultats$H <- H2\ncmeans_resultats$Clus <- Clus2\n```\n\n##### Interprétation des résultats\n\nGlobalement, les approches pour interpréter les résultats issus d'une classification obtenue par *c-means* sont les mêmes que pour une classification obtenue par *k-means*.\n\nCommençons donc par créer plusieurs cartes des probabilités d'appartenir aux différents groupes.\n\n```{r}\n#| label: fig-cmeansD\n#| fig-align: center\n#| fig-cap: Cartographie des probabilités d'appartenir aux quatre groupes identifiés par l'algorithme c-means\n#| message: false\n#| warning: false\n#| out-width: \"100%\"\nmaps <- mapClusters(LyonIris, cmeans_resultats$U)\n\ntmap_arrange(maps$ProbaMaps, ncol = 2, nrow = 2)\n```\n\nSur les cartes de la @fig-cmeansD, l'intensité de bleu correspond à la probabilité pour chaque IRIS d'appartenir aux différents groupes. Nous retrouvons les principales structures spatiales que nous avons identifiées avec le *k-means*; cependant, nous pouvons à présent constater que le groupe 1 est bien plus incertain que les autres. Nous pouvons une fois encore générer un graphique en radar pour comparer les profils des quatre groupes.\n\n```{r}\n#| label: fig-cmeansE\n#| fig-align: center\n#| fig-cap: Graphique en radar pour les résultats du c-means\n#| out-width: \"100%\"\n#| message: false\n#| warning: false\n\npar(mfrow=c(3,2), mai = c(0.1,0.1,0.1,0.1))\nspiderPlots(X, cmeans_resultats$U,\n chartcolors = c(\"#EFBE89\", \"#4A6A9F\", \"#7DB47C\", \"#FAF29C\"))\n\n```\n\nSans surprise, nous retrouvons essentiellement les profils que nous avons obtenus avec le *k-means* dans la @fig-cmeansE. Pour compléter la lecture des résultats, il est nécessaire de se pencher sur le tableau des statistiques descriptives des différents groupes. Une fois encore, nous proposons d'utiliser la fonction `summarizeClusters` du *package* `geocmeans`. Notez que cette fonction calcule les statistiques descriptives pondérées en fonction de l'appartenance des observations aux groupes. Ainsi, une observation ayant une faible chance d'appartenir à un groupe ne contribue que faiblement aux statistiques descriptives de ce groupe.\n\n```{r}\n#| label: cmeansF\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"100%\"\ndf <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\" , \"Pct0_14\",\n \"Pct_65\" , \"Pct_Img\", \"TxChom1564\",\n \"Pct_brevet\" , \"NivVieMed\")])\n\ntableaux <- summarizeClusters(data = df, \n belongmatrix = cmeans_resultats$U,\n weighted = TRUE, dec = 1)\n\ntableau_tot <- do.call(rbind, tableaux)\n```\n\n```{r}\n#| label: tbl-cmeansG\n#| tbl-cap: Description des groupes avec la méthode c-means\n#| echo: false\n#| message: false\n#| warning: false\ntableau_tot <- apply(tableau_tot, MARGIN = 2, unlist)\ntableau_tot <- data.frame(tableau_tot)\ntableau_tot$stat <- rep(row.names(tableaux[[1]]),4)\ntableau_tot <- tableau_tot[, c(\"stat\", names(X2))]\n\nok_col_names <- gsub(\"_\" , \"\", names(X2), fixed = TRUE)\n\nmy_table <- knitr::kable(tableau_tot, row.names = FALSE, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n\t\t\t\t\t col.names = c(\"\", ok_col_names),\n align=c(\"l\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\"))\n\nmy_table2 <- group_rows(my_table,\n index = c(\n \"groupe 1\" = 9,\n \"groupe 2\" = 9,\n \"groupe 3\" = 9,\n \"groupe 4\" = 9\n )\n )\n\nmy_table2 <- gsub(pattern = \"NApadding\", replacement = \"padding\",x = my_table2, fixed = TRUE)\nmy_table2 <- gsub(pattern = \"padding-left: 2em\", replacement = \"padding-left: 0em\",x = my_table2, fixed = TRUE)\nmy_table2 <- gsub(pattern = \"\", replacement = '',x = my_table2, fixed = TRUE)\nmy_table2\n```\n\n#### Mise en œuvre du *c-medoids* dans R {#sec-13462}\n\nLa méthode du *c-medoids* dans R peut être mise en œuvre avec la fonction `FKM.med` du *package* `fclust`. Le processus d'analyse et de validation est identique à celui présenté ci-dessus pour le *c-means*. Nous ne donnons donc pas un exemple complet de la méthode.\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Stabilité des groupes obtenus par les méthodes de nuées dynamiques**\n:::\n::: bloc_aller_loin-body\nPuisque la méthode *k-means* et ses variantes reposent sur une initialisation aléatoire de leur algorithme, les résultats peuvent varier en fonction de cet état de départ. Dans certains contextes, il est possible que les résultats obtenus varient significativement, ce qui signifie que les groupes obtenus ne sont pas représentatifs de la population étudiée. Une solution pour vérifier si ce problème se pose est simplement de relancer l'algorithme un grand nombre de fois (généralement 1000) et de comparer les résultats obtenus au cours de ces réplications.\n\nCette méthode est rarement implémentée directement et requiert d'écrire sa propre fonction. `geocmeans` dispose d'une fonction déjà existante, mais ne pouvant être appliquée qu'avec l'algorithme *c-means*. Nous proposons ici une implémentation pour la méthode *k-means* qui peut facilement être adaptée aux autres méthodes de classifications heuristiques.\n\nLa démarche à suivre est la suivante : \n\n1. Appliquer l'algorithme une première fois pour obtenir une classification de référence à laquelle nous comparerons toutes les réplications.\n\n2. Effectuer 1000 itérations au cours desquelles : \n + Une nouvelle classification est calculée.\n + Les groupes obtenus sont comparés à ceux de la classification de référence.\n + L'indice de Jacard est calculé entre les groupes des deux classifications.\n + Les valeurs de l'indice de Jacard sont enregistrées.\n + Les centres des groupes sont enregistrés.\n \nAinsi, nous obtenons 1000 valeurs de l'indice de Jacard pour chaque groupe. Cet indice permet de mesurer le degré d'accord entre deux variables (ici les probabilités d'appartenance des observations au même groupe pour deux classifications différentes.) Une valeur moyenne en dessous de 0,5 indique qu'un groupe est très instable, car nous obtenons des résultats très différents lors des réplications. Une valeur entre 0,6 et 0,75 indique qu'un groupe semble bien exister dans les données, bien que marqué par une certaine incertitude. Une valeur au-dessus de 0,8 indique un groupe bien identifié et stable.\n\nNous obtenons également les centres des groupes des 1000 classifications. Il est ainsi possible de représenter leurs histogrammes et de déterminer si les centres des groupes sont stables (unimodalité et faible variance) ou incertains (plusieurs modes et/ou forte variance).\n\n```{r}\n#| label: kmeansStab1\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"100%\"\n\n# X sera le jeu de données pour la classification\n# clust_ref sera le vecteur indiquant le groupe de chaque observation obtenu par kmeans\n# nsim sera le nombre de simulations à effectuer\nkmeans_stability <- function(X, clust_ref, nsim, verbose = TRUE){\n \n # définition de la matrice d'appartenance originale\n k <- length(unique(clust_ref))\n ref_mat <- dummy_cols(clust_ref, remove_selected_columns = TRUE)\n colnames(ref_mat) <- paste0(\"groupe_\",1:k)\n \n # lancement des itérations\n sim_resultats <- lapply(1:nsim, function(i){\n \n # afficher la progression si requis\n if(verbose){\n print(paste0(\"iteration numeros : \", i, \"/\", nsim))\n }\n # calculer le kmeans\n km_res <- kmeans(X, k)\n sim_mat <- dummy_cols(km_res$cluster, remove_selected_columns = TRUE)\n \n # ajustement de l'ordre des groupes avec geocmeans\n sim_mat <- groups_matching(as.matrix(ref_mat), as.matrix(sim_mat))\n \n # calcul des indices de jacard\n jac_idx <- sapply(1:k, function(j){\n calc_jaccard_idx(sim_mat[,j], ref_mat[,j])\n })\n \n # récuperation des centres des groupes\n idx <- as.integer(gsub(\".data_\" , \"\", colnames(sim_mat), fixed = TRUE))\n centers <- data.frame(km_res$centers)\n centers <- centers[idx,]\n centers$groupe <- 1:k\n \n return(list(\n \"jac_idx\" = jac_idx,\n \"centers\" = centers\n ))\n \n })\n \n # les simulations sont finies, nous pouvons combiner les résultats\n all_jac_values <- do.call(rbind, lapply(sim_resultats, function(x){x$jac_idx}))\n all_centers <- do.call(rbind, lapply(sim_resultats, function(x){x$centers}))\n return(list(\n \"jacard_values\" = all_jac_values,\n \"centers\" = all_centers\n ))\n}\n\n```\n\nIl ne nous reste plus qu'à utiliser notre nouvelle fonction pour déterminer si les groupes obtenus avec notre *k-means* sont stables.\n\n```{r}\n#| label: kmeansStab2\n#| fig-align: center\n#| message: false\n#| warning: false\n#| out-width: \"100%\"\ndata(LyonIris)\nset.seed(123)\n\n# NB : LyonIris est un objet spatial, il faut donc extraire uniquement son DataFrame\nX <- st_drop_geometry(LyonIris[c(\"Lden\" , \"NO2\" , \"PM25\" , \"VegHautPrt\" , \"Pct0_14\" , \"Pct_65\" , \"Pct_Img\",\n \"TxChom1564\" , \"Pct_brevet\" , \"NivVieMed\")])\n\n# Centrage et réduction de chaque colonne du DataFrame\nfor (col in names(X)){\n X[[col]] <- scale(X[[col]], center = TRUE, scale = TRUE)\n}\n\n# calcul du kmeans de référence\nkmeans_ref <- kmeans(X, 4)\n\n# application de la fonction de stabilité\nstab_results <- kmeans_stability(X, kmeans_ref$cluster, nsim = 1000, verbose = FALSE)\n\n```\n\nNous pouvons à présent vérifier la stabilité de nos quatre groupes.\n\n```{r}\n#| label: fig-kmeansStab3\n#| fig-align: center\n#| fig-cap: Indices de Jacard obtenus sur 1000 réplications du k-means\n#| message: false\n#| warning: false\n#| out-width: \"90%\"\n\njacard_values <- data.frame(stab_results$jacard_values)\nnames(jacard_values) <- paste(\"groupe\", 1:4, sep = \"_\")\n\ndf <- reshape2::melt(jacard_values)\ndf$groupes <- as.factor(df$variable)\n\nggplot(df) + \n geom_histogram(aes(x = value), bins = 30) + \n facet_wrap(vars(groupes), ncol = 2) + \n labs(x = \"\", y = \"Indice de Jacard\")\n\n```\n\nLa @fig-kmeansStab3 indique clairement que les groupes 1 et 2 sont très stables, car les valeurs de Jacard obtenues sont le plus souvent supérieures à 0,75. Le groupe 3 a le plus souvent des valeurs légèrement inférieures aux deux premiers groupes, mais tout de même bien supérieures à 0,5. En revanche, le groupe 4 a un grand nombre de valeurs inférieures à 0,5 indiquant une tendance du groupe à se dissoudre lors des réplications.\n\nConsidérant que le dernier groupe est le plus instable, nous décidons d'observer les valeurs des centres qu'il obtient pour les différentes réplications.\n\n```{r}\n#| label: fig-kmeansStab4\n#| fig-align: center\n#| fig-cap: Distributions des valeurs des centres du groupe 4 sur 1000 itérations\n#| message: false\n#| warning: false\n#| out-width: \"90%\"\n\ncenters_groupe4 <- subset(stab_results$centers, stab_results$centers$groupe == 4)\ncenters_groupe4$groupe <- NULL\n\ndf <- reshape2::melt(centers_groupe4)\ndf$variable <- as.factor(df$variable)\n\nggplot(df) + \n geom_histogram(aes(x = value), bins = 30) + \n facet_wrap(vars(variable), ncol = 3, scales = \"free\") + \n labs(x = \"\", y = \"\")\n\n```\n\nLes différents histogrammes de la @fig-kmeansStab4 indiquent clairement que pour plusieurs variables (`Lden`, `NO2`, `PM25`, `Pct_Img`, et `NivVieMed`) les caractéristiques du groupe 4 varient grandement sur l'ensemble des réplications. Nous pouvons comparer ce graphique à celui du groupe 2 qui est bien plus stable.\n\n```{r}\n#| label: fig-kmeansStab5\n#| fig-cap: Distributions des valeurs des centres du groupe 2 sur 1000 itérations\n#| fig-align: center\n#| out-width: \"90%\"\n#| message: false\n#| warning: false\n\ncenters_groupe2 <- subset(stab_results$centers, stab_results$centers$groupe == 2)\ncenters_groupe2$groupe <- NULL\n\ndf <- reshape2::melt(centers_groupe2)\ndf$variable <- as.factor(df$variable)\n\nggplot(df) + \n geom_histogram(aes(x = value), bins = 30) + \n facet_wrap(vars(variable), ncol = 3, scales = \"free\") + \n labs(x = \"\", y = \"\")\n\n```\n\nNous pouvons constater une plus faible variance des résultats obtenus (en regardant notamment l'axe horizontal) pour les centres des groupes à la @fig-kmeansStab5.\n:::\n:::\n\n\n## Conclusion sur la cinquième partie {#sec-135}\n\nDans le cadre de cette cinquième partie du livre, nous avons abordé les principales méthodes factorielles et les principales méthodes de classification non supervisée. Les premières sont des méthodes de réduction de données puisqu'elles permettent de résumer l'information d'un tableau en quelques nouvelles variables synthétiques. Les secondes permettent de regrouper les observations d'un tableau en plusieurs groupes homogènes. Il existe donc une complémentarité évidente entre ces deux groupes de méthodes : si le tableau initial comprend un grand nombre de variables, il est possible de lui appliquer une méthode factorielle produisant de nouvelles variables synthétiques qui sont ensuite utilisées pour calculer une méthode de classification non supervisée.\n\n![Complémentarité entre les méthodes factorielles et les méthodes de classification non supervisée](images/Chap13/AnalysesFactoClassif.png){#fig-MFMCComplementarite width=\"45%\" fig-align=\"center\"}\n\n## Quiz de révision du chapitre {#sec-136}\n\n```{r}\n#| label: quizChapitre13\n#| echo: false\n#| warning: false\n#| results: asis\nsource(\"code_complementaire/QuizzFunctions.R\")\nquizz_classif <- quizz(\"quiz/Chapitre13_classification.yml\", \"quizz_classif\")\nrender_quizz(quizz_classif)\n```\n\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"13-MethodeClassification.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/14-Annexes.qmd.json b/.quarto/idx/14-Annexes.qmd.json new file mode 100644 index 0000000..bc91d2b --- /dev/null +++ b/.quarto/idx/14-Annexes.qmd.json @@ -0,0 +1 @@ +{"title":"Annexes","markdown":{"headingText":"Annexes","headingAttr":{"id":"sec-chap14","classes":[],"keyvalue":[]},"containsRefs":false,"markdown":"\n## Table des valeurs critiques de khi-deux {#sec-141}\n\nLa courte syntaxe R ci-dessous permet de générer le @tbl-tableCritiqueKhi2 avec les valeurs critiques du khi-deux pour différents degrés de signification (valeurs de *p*).\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| results: hide\nlibrary(stargazer)\n\n# vecteur pour les degrés de liberté de 1 à 30, puis 40 et 50\ndl <- c(1:30, 40, 50, 100, 250, 500) \n# la fonction qchisq permet d'obtenir la valeur théorique en fonction \n# d'une valeur de p et d'un nombre de degrés de liberté\ntableKhi2 <- cbind(dl,\n p0.10 = round(qchisq(p = 0.90, df = dl, lower.tail = TRUE), 3),\n p0.05 = round(qchisq(p = 0.95, df = dl, lower.tail = TRUE), 3),\n p0.01 = round(qchisq(p = 0.99, df = dl, lower.tail = TRUE), 3),\n p0.001 =round(qchisq(p = 0.999, df = dl, lower.tail = TRUE), 3))\n# Impression du tableau avec la library stargazer\nstargazer(tableKhi2, type = \"text\", summary = FALSE, rownames = FALSE, align = TRUE, digits = 2,\n title = \"Distribution des valeurs critiques du Khi2\")\n```\n\n\n```{r}\n#| label: tbl-tableCritiqueKhi2\n#| tbl-cap: Distribution des valeurs critiques du khi-deux\n#| echo: false\n#| message: false\n#| warning: false\nknitr::kable(tableKhi2, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n digits = 2,\n col.names = c(\"dl\", \"p = 0,10\", \"p = 0,05\", \"p = 0,01\", \"p = 0,001\"),\n align = c(\"r\", \"r\", \"r\", \"r\", \"r\"),\n position = \"HOLD_position\"\n)\n```\n\n\n## Table des valeurs critiques de Fisher {#sec-142}\n\nLa courte syntaxe R ci-dessous permet de générer les tableaux [-@tbl-CritiqueF1], [-@tbl-CritiqueF2] et [-@tbl-CritiqueF3] avec les valeurs critiques de *F* avec *p* = 0,05.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| results: hide\nlibrary(stargazer)\n\ndl1 <- c(1:10, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400, 500, 1000)\ndl2 <- c(1:10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 500, 1000, 2000)\nmatrice <- matrix(ncol = length(dl1), nrow = length(dl2), byrow = TRUE)\nfor(r in 1:length(dl1)){\n for(c in 1:length(dl2)){\n matrice[c,r] <- round(qf(p = 0.05, dl1[r], dl2[c], lower.tail = FALSE), 2)\n }\n}\n\ntableF_p0.05 <- data.frame(dl2 = dl2, matrice)\nnames(tableF_p0.05) <- c(\"dl2\", paste0(\"dl1=\",dl1))\n\nstargazer(tableF_p0.05, type = \"text\", summary = FALSE, rownames = FALSE, align = TRUE, digits = 3,\n title = \"Distribution des valeurs critiques de F avec p = 0,05\")\n```\n\n\n```{r}\n#| label: tbl-CritiqueF1\n#| tbl-cap: Distribution des valeurs critiques de F avec p = 0,05\n#| echo: false\n#| message: false\n#| warning: false\nnomcols <- names(tableF_p0.05)\nknitr::kable(tableF_p0.05[,1:11], \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = nomcols[1:11],\n align = c(\"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\"),\n position = \"HOLD_position\")\n```\n\n\n\n```{r}\n#| label: tbl-CritiqueF2\n#| tbl-cap: Distribution des valeurs critiques de F avec p = 0,05 (suite)\n#| echo: false\n#| message: false\n#| warning: false\nknitr::kable(tableF_p0.05[,c(1,12:20)], \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names=nomcols[c(1,12:20)],\n align= c(\"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\"),\n position = \"HOLD_position\")\n```\n\n\n\n```{r}\n#| label: tbl-CritiqueF3\n#| tbl-cap: Distribution des valeurs critiques de F avec p = 0,05 (suite)\n#| echo: false\n#| message: false\n#| warning: false\nknitr::kable(tableF_p0.05[,c(1,21:26)], \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names=nomcols[c(1,21:26)],\n align= c(\"r\", \"r\", \"r\", \"r\", \"r\", \"r\", \"r\"),\n position = \"HOLD_position\")\n```\n\n## Table des valeurs critiques de *t* {#sec-143}\n\nLa courte syntaxe R ci-dessous permet de générer le @tbl-tableCritiqueT avec les valeurs critiques de *t* avec *p* = 0,10, 0,05, 0,01 et 0,01.\n\n```{r}\n#| echo: true\n#| message: false\n#| warning: false\n#| results: hide\nlibrary(stargazer)\n\n# vecteur pour les degrés de liberté de 1 à 30, puis 40 et 50\ndl <- c(1:30, 40, 50, 60, 70, 80, 90, 100, 250, 500, 1000, 2500) \n# la fonction qchisq permet d'obtenir la valeur théorique en fonction \n# d'une valeur de p et d'un nombre de degrés de liberté\ntableT <- cbind(dl,\n p0.10 = round(qt(p = 1 - (0.10/2), df = dl),2),\n p0.05 = round(qt(p = 1 - (0.05/2), df = dl),2),\n p0.01 = round(qt(p = 1 - (0.01/2), df = dl),2),\n p0.001 = round(qt(p = 1 - (0.001/2), df = dl),2))\n# Impression du tableau avec la library stargazer\nstargazer(tableT, type = \"text\", summary = FALSE, rownames = FALSE, align = TRUE, digits = 2,\n title=\"Distribution des valeurs critiques de t\")\n```\n\n```{r}\n#| label: tbl-tableCritiqueT\n#| tbl-cap: Distribution des valeurs critiques de t\n#| echo: false\n#| message: false\n#| warning: false\n# vecteur pour les degrés de liberté de 1 à 30, puis 40 et 50\nknitr::kable(tableT, \n format.args = list(decimal.mark = ',', big.mark = \" \"),\n col.names = c(\"dl\", \"p = 0,10\", \"p = 0,05\", \"p = 0,01\", \"p = 0,001\"),\n align = c(\"r\", \"r\", \"r\", \"r\", \"r\"),\n position = \"HOLD_position\"\n)\n```\n\n\n```{r}\n#| echo: false\n#| results: asis\nif(knitr::is_latex_output()){\n cat(\"# Bibliographie {-}\")\n}\n```\n\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"14-Annexes.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/index.qmd.json b/.quarto/idx/index.qmd.json new file mode 100644 index 0000000..11bb44e --- /dev/null +++ b/.quarto/idx/index.qmd.json @@ -0,0 +1 @@ +{"title":"Préface","markdown":{"headingText":"Préface","headingAttr":{"id":"","classes":["unnumbered"],"keyvalue":[]},"containsRefs":false,"markdown":"```{=tex}\n\\renewcommand{\\partname}{} % Réinitialiser partie\n```\n\n**Résumé :** Ce livre vise à décrire une panoplie de méthodes quantitatives utilisées en sciences sociales avec le logiciel ouvert R. Il a d'ailleurs été écrit intégralement dans R avec Quarto. Le contenu est pensé pour être accessible à tous et toutes, même à ceux et celles n'ayant presque aucune base en statistique ou en programmation. Les personnes plus expérimentées y découvriront des sections sur des méthodes plus avancées comme les modèles à effets mixtes, les modèles multiniveaux, les modèles généralisés additifs ainsi que les méthodes factorielles et de classification. Ceux et celles souhaitant migrer progressivement d'un autre logiciel statistique vers R trouveront dans cet ouvrage les éléments pour une transition en douceur. La philosophie de ce livre est de donner toutes les clefs de compréhension et de mise en œuvre des méthodes abordées dans R. La présentation des méthodes est basée sur une approche compréhensive et intuitive plutôt que mathématique, sans pour autant que la rigueur statistique soit négligée.\n\n**Remerciements :** Ce manuel a été réalisé avec le soutien de la fabriqueREL. Fondée en 2019, la fabriqueREL est portée par divers établissements d'enseignement supérieur du Québec et agit en collaboration avec les services de soutien pédagogique et les bibliothèques. Son but est de faire des ressources éducatives libres (REL) le matériel privilégié en enseignement supérieur au Québec.\n\n**Maquette de la page couverture et identité graphique du livre :** Andrés Henao Florez.\n\n**Mise en page :** Philippe Apparicio et Marie-Hélène Gadbois Del Carpio.\n\n**Révision linguistique :** Denise Latreille.\n\n© Philippe Apparicio et Jérémy Gelb.\n\n\n**Pour citer cet ouvrage :** Apparicio P. et J. Gelb (2024). *Méthodes quantitatives en sciences sociales : un grand bol d’R*. Université de Sherbrooke, Département de géomatique appliquée. fabriqueREL. Licence CC BY-SA.

\n\n![](images/introduction/CouvertureP2.png){width=\"80%\" fig-align=\"left\"}\n\n\n\nCe livre vise à décrire une panoplie de méthodes quantitatives utilisées en sciences sociales avec le logiciel ouvert R. Il a d'ailleurs été écrit intégralement dans R avec [Quatro](https://quarto.org/). Le contenu est pensé pour être accessible à tous et toutes, même à ceux et celles n'ayant presque aucune base en statistique ou en programmation. Les personnes plus expérimentées y découvriront des sections sur des méthodes plus avancées comme les modèles à effets mixtes, les modèles multiniveaux, les modèles généralisés additifs ainsi que les méthodes factorielles et de classification. Ceux et celles souhaitant migrer progressivement d'un autre logiciel statistique vers R trouveront dans cet ouvrage les éléments pour une transition en douceur. La philosophie de ce livre est de donner toutes les clefs de compréhension et de mise en œuvre des méthodes abordées dans R. La présentation des méthodes est basée sur une approche compréhensive et intuitive plutôt que mathématique, sans pour autant que la rigueur statistique ne soit négligée. Servez-vous votre boisson chaude ou froide favorite et installez-vous dans votre meilleur fauteuil. Bonne lecture!\n\n## Un manuel sous la forme d'une ressource éducative libre {-#sect001}\n\n**Pourquoi un manuel sous licence libre?**\n\nLes logiciels libres sont aujourd'hui très répandus. Comparativement aux logiciels propriétaires, l'accès au code source permet à quiconque de l'utiliser, de le modifier, de le dupliquer et de le partager. Le logiciel R, dans lequel sont mises en œuvre les méthodes quantitatives décrites décrites dans ce livre, est d'ailleurs à la fois un langage de programmation et un logiciel libre (sous la licence publique générale [GNU GPL2](https://fr.wikipedia.org/wiki/Licence_publique_g%C3%A9n%C3%A9rale_GNU)). Par analogie aux logiciels libres, il existe aussi des **ressources éducatives libres (REL)** « dont la licence accorde les permissions désignées par les 5R (**Retenir --- Réutiliser --- Réviser --- Remixer --- Redistribuer**) et donc permet nécessairement la modification » ([***fabriqueREL***](https://fabriquerel.org/rel/)). La licence de ce livre, CC BY-SA (@fig-Licence), permet donc de :\n\n- **Retenir**, c'est-à-dire télécharger et imprimer gratuitement le livre. Notez qu'il aurait été plutôt surprenant d'écrire un livre payant sur un logiciel libre et donc gratuit. Aussi, nous aurions été très embarrassés que des personnes étudiantes avec des ressources financières limitées doivent payer pour avoir accès au livre, sans pour autant savoir préalablement si le contenu est réellement adapté à leurs besoins.\n\n- **Réutiliser**, c'est-à-dire utiliser la totalité ou une section du livre sans limitation et sans compensation financière. Cela permet ainsi à d'autres personnes enseignantes de l'utiliser dans le cadre d'activités pédagogiques.\n\n- **Réviser**, c'est-à-dire modifier, adapter et traduire le contenu en fonction d'un besoin pédagogique précis puisqu'aucun manuel n'est parfait, tant s'en faut! Le livre a d'ailleurs été écrit intégralement dans R avec [Quatro](https://quarto.org/). Quiconque peut ainsi télécharger gratuitement le code source du livre sur [github](https://github.com/SerieBoldR/MethodesQuantitatives) et le modifier à sa guise (voir l'encadré intitulé *Suggestions d'adaptation du manuel*).\n\n- **Remixer**, c'est-à-dire « combiner la ressource avec d'autres ressources dont la licence le permet aussi pour créer une nouvelle ressource intégrée » ([***fabriqueREL***](https://fabriquerel.org/rel/)).\n\n- **Redistribuer**, c'est-à-dire distribuer, en totalité ou en partie, le manuel ou une version révisée sur d'autres canaux que le site Web du livre (par exemple, sur le site Moodle de votre université ou en faire une version imprimée).\n\nLa licence de ce livre, CC BY-SA (@fig-Licence), oblige donc à :\n\n- Attribuer la paternité de l'auteur dans vos versions dérivées, ainsi qu'une mention concernant les grandes modifications apportées, en utilisant la formulation suivante : Apparicio Philippe et Jérémy Gelb (2024). *Méthodes quantitatives en sciences sociales : un grand bol d'R*. Université de Sherbrooke. fabriqueREL. Licence CC BY-SA.\n\n- Utiliser la même licence ou une licence similaire à toutes versions dérivées.\n\n![Licence Creative Commons du livre](images/introduction/Licence.JPG){#fig-Licence width=\"80%\" fig-align=\"center\"}\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n\n**Suggestions d'adaptation du manuel**\n:::\n\n::: bloc_astuce-body\nPour chaque méthode d'analyse spatiale abordée dans le livre, une description détaillée et une mise en œuvre dans R sont disponibles. Par conséquent, plusieurs adaptations du manuel sont possibles :\n\n- Conserver uniquement les chapitres sur les méthodes ciblées dans votre cours.\n\n- En faire une version imprimée et la distribuer aux personnes étudiantes.\n\n- Modifier la description d'une ou de plusieurs méthodes en effectuant les mises à jour directement dans les chapitres.\n\n- Insérer ses propres jeux de données dans les sections intitulées *Mise en œuvre dans R*.\n\n- Modifier les tableaux et figures.\n\n- Ajouter une série d'exercices.\n\n- Modifier les quiz de révision.\n\n- Rédiger un nouveau chapitre.\n\n- Modifier des syntaxes R. Plusieurs *packages* R peuvent être utilisés pour mettre en œuvre telle ou telle méthode. Ces derniers évoluent aussi très vite et de nouveaux *packages* sont proposés fréquemment. Par conséquent, il peut être judicieux de modifier une syntaxe R du livre en fonction de ses habitudes de programmation dans R (utilisation d'autres *packages* que ceux utilisés dans le manuel par exemple) ou de bien mettre à jour une syntaxe à la suite de la parution d'un nouveau *package* plus performant ou intéressant.\n\n- Toute autre adaptation qui permet de répondre au mieux à un besoin pédagogique.\n:::\n:::\n\n## Un manuel conçu comme un projet collaboratif {-#sect002}\n\nIl existe actuellement de nombreux livres sous licence ouverte écrits avec [rmarkdown](https://rmarkdown.rstudio.com/) ou [Quarto](https://quarto.org/), répertoriés sur les sites de [https://bookdown.org/](https://bookdown.org/) et de [https://quarto.org/docs/gallery/#books](https://quarto.org/docs/gallery/#books). Sans surprise, R étant un logiciel libre dédié aux méthodes statistiques et à la science des données, plusieurs abordent les méthodes quantitatives, notamment :\n\n- [Beyond Multiple Linear Regression: Applied Generalized Linear Models and Multilevel Models in R](https://bookdown.org/roback/bookdown-BeyondMLR/) [@roback2021beyond], CC BY-NC-SA.\n\n- [Introduction to Econometrics with R](https://www.econometrics-with-r.org/) [@hanck2019introduction], CC BY-NC-SA.\n\n- [Statistical Inference via Data Science: A ModernDive into R and the Tidyverse](https://moderndive.com/) [@ismay2019statistical], CC BY-NC-SA.\n\n- [R Graphics Cookbook, 2nd edition](https://r-graphics.org/) [@Chang2018], CC BY.\n\nPar contre, la grande majorité de ces livres numériques rédigés avec R sont en anglais. À notre connaissance, ce projet constitue le premier manuel numérique en français sur les méthodes quantitatives appliquées aux sciences sociales réalisé avec `Quatro`. La première version du livre étant lancée, il est grand temps de planifier les suivantes! Pour ce faire, nous considérons ce livre comme un **projet collaboratif visant à mobiliser la communauté universitaire francophone qui enseigne les statistiques en sciences sociales avec R**. Plusieurs raisons motivent cette vision collaborative :\n\n- **Rien n'est parfait!** Cette première version comprend sûrement des coquilles et certaines sections mériteraient d'être améliorées. Les commentaires et suggestions visant à améliorer son contenu sont les bienvenus.\n\n- **La table des matières doit être impérativement extensible!** De nombreuses méthodes statistiques très utilisées en sciences sociales ne sont pas abordées dans ce livre et mériteraient d'être ajoutées dans une version ultérieure : certaines extensions des régressions linéaires (régressions Rigge et Lasso, Tobit, quantile, etc.), les modèles d'équations simultanées, les analyses de données longitudinales (entre autres, modèles de survie, régression par panel), les modèles d'équations structurelles et bien d'autres! Par conséquent, si vous êtes intéressé(e)s, à ajouter un nouveau chapitre ou une partie du livre, nous vous invitons vivement à communiquer avec nous ou à diffuser sous une licence similaire votre version dérivée. L’objectif étant de continuer à faire tourner la roue du libre et, idéalement, que les futures versions soient corédigées par une communauté d’auteurs et d'autrices spécialistes en méthodes quantitatives.\n\n\n## Comment lire ce livre? {-#sect003}\n\nLe livre comprend plusieurs types de blocs de texte qui en facilitent la lecture.\n\n::: bloc_package\n::: bloc_package-header\n::: bloc_package-icon\n:::\n\n**Bloc *packages***\n:::\n\n::: bloc_package-body\nHabituellement localisé au début d'un chapitre, il comprend la liste des *packages* R utilisés pour un chapitre.\n:::\n:::\n\n::: bloc_objectif\n::: bloc_objectif-header\n::: bloc_objectif-icon\n:::\n**Bloc objectif**\n:::\n::: bloc_objectif-body\nIl comprend une description des objectifs d'un chapitre ou d'une section.\n:::\n:::\n\n::: bloc_notes\n::: bloc_notes-header\n::: bloc_notes-icon\n:::\n**Bloc notes**\n:::\n::: bloc_notes-body\nIl comprend une information secondaire sur une notion, une idée abordée dans une section.\n:::\n:::\n\n::: bloc_aller_loin\n::: bloc_aller_loin-header\n::: bloc_aller_loin-icon\n:::\n**Bloc pour aller plus loin**\n:::\n::: bloc_aller_loin-body\nIl comprend des références ou des extensions d'une méthode abordée dans une section.\n:::\n:::\n\n::: bloc_astuce\n::: bloc_astuce-header\n::: bloc_astuce-icon\n:::\n**Bloc astuce**\n:::\n::: bloc_astuce-body\nIl décrit un élément qui vous facilitera la vie : une propriété statistique, un *package*, une fonction, une syntaxe R.\n:::\n:::\n\n::: bloc_attention\n::: bloc_attention-header\n::: bloc_attention-icon\n:::\n**Bloc attention**\n:::\n::: bloc_attention-body\nIl comprend une notion ou un élément important à bien maîtriser.\n:::\n:::\n\n::: bloc_exercice\n::: bloc_exercice-header\n::: bloc_exercice-icon\n:::\n\n**Bloc exercice**\n:::\n\n::: bloc_exercice-body\nIl comprend un court exercice de révision à la fin de chaque chapitre.\n:::\n:::\n\n## Comment utiliser les données du livre pour reproduire les exemples? {-#sect003B}\n\nCe livre comprend des exemples détaillés et appliqués dans R pour chacune des méthodes abordées. Ces exemples se basent sur des jeux de données structurés et mis à disposition avec le livre. Ils sont disponibles sur le *repo github* dans le sous-dossier `data`, à l'adresse . \n\nUne autre option est de télécharger le *repo* complet du livre directement sur *github* () en cliquant sur le bouton `Code`, puis le bouton `Download ZIP` (@fig-downloaffromgit). Les données se trouvent alors dans le sous-dossier nommé `data`.\n\n![Téléchargement de l'intégralité du livre](images/introduction/download_github.png){#fig-downloaffromgit width=\"40%\" fig-align=\"center\"}\n\n## Liste des *packages* utilisés {-#sect004}\n\nPour écrire ce livre, nous avons utilisé de nombreux *packages* que vous pouvez installer avec le code ci-dessous.\n\n```{r}\n#| echo: true\n#| eval: false\n#| message: false\n#| warning: false\n\n# Liste des packages\nListePackages <- c(\"actuar\", \"AER\", \"apaTables\", \"boot\", \"car\", \"caret\", \"chorddiag\", \"classInt\", \n \"cluster\", \"clusterCrit\", \"correlation\", \"corrplot\", \"DescTools\", \"DHARMa\", \n \"dplyr\", \"effectsize\", \"ellipse\", \"FactoMineR\", \"fastDummies\", \"fitdistrplus\", \n \"fmsb\", \"foreign\", \"gamlss\", \"gamlss.add\", \"gamlss.dist\", \"geocmeans\", \"gganimate\",\n \"ggeffects\", \"ggplot2\", \"ggpubr\", \"ggpubr\", \"ggpubr\", \"ggpubr\", \"ggspatial\",\n \"ggthemes\", \"gmodels\", \"grid\", \"gridExtra\", \"Hmisc\", \"itsadug\", \"kableExtra\", \n \"LaplacesDemon\", \"lme4\", \"lmtest\", \"lubridate\", \"MASS\", \"merTools\", \"metR\", \n \"mgcv\", \"moments\", \"MuMIn\", \"NbClust\", \"nortest\", \"pdftools\", \"performance\", \n \"ppcor\", \"proxy\", \"qqplotr\", \"QuantPsyc\", \"QuantPsyc\", \"QuantPsyc\",\n \"RColorBrewer\", \"reshape2\", \"ROCR\", \"rstatix\", \"sandwich\", \"sas7bdat\", \"segmented\",\n \"sf\", \"SimDesign\", \"sjstats\", \"snow\", \"splines2\", \"stargazer\", \"stats\", \"stringr\", \n \"textrank\", \"tmap\", \"tmap\", \"treemap\", \"udpipe\", \"vcd\", \"VGAM\", \"VGAM\", \"viridis\", \n \"Weighted.Desc.Stat\", \"wordcloud2\", \"xlsx\")\n# Packages non installés dans la liste\nPackagesNonInstalles <- ListePackages[!(ListePackages %in% installed.packages()[,\"Package\"])]\n# Installation des packages manquants\nif(length(new.packages)) install.packages(PackagesNonInstalles)\n```\n\n## Structure du livre {-#sect005}\n\nLe livre est organisé autour de cinq grandes parties.\n\n\n**Partie 1. La découverte de R.** Dans cette première partie, nous discutons brièvement de l’histoire et de la philosophie de R. Nous voyons ensuite comment installer R et RStudio. Les bases du langage R (particulièrement les principaux objets que sont le vecteur, la matrice, la liste et le *dataframe*) ainsi que la manipulation des données avec R sont aussi largement abordés dans le [chapitre @sec-chap01].\n\n**Partie 2. Analyses univariées et représentations graphiques**. Cette seconde partie comprend deux chapitres. Dans le [chapitre @sec-chap02], nous décrivons dans un premier temps les différents types de données (primaires *versus* secondaires, transversales *versus* longitudinales, spatiales *versus* aspatiales, individuelles *versus* agrégées), les différents types de variables quantitatives (discrètes et continues) et qualitatives (nominales et ordinales) et les principales distributions de variables utilisées en sciences sociales (uniforme, Bernoulli, binomiale, géométrique, binomiale négative, poisson, poisson avec excès de zéros, gaussienne, gaussienne asymétrique, log-normale, Student, Cauchy, Chi-carré, exponentielle, Gamma, bêta, Weibull et Pareto). Dans un second temps, nous abordons les statistiques descriptives pour des variables quantitatives (paramètres de tendance centrale, paramètres de position, paramètres de dispersion, paramètres de forme), puis qualitatives (fréquences absolues, relatives et cumulées).\n\nDans le [chapitre @sec-chap03], nous illustrons les incroyables capacités graphiques de R en mettant en œuvre les principaux graphiques (histogramme, graphique de densité, nuage de points, graphique en lignes, boîtes à moustache, graphique en violon, graphique en barre, graphique circulaire), quelques graphiques particuliers (graphique en radar, diagramme d'accord, nuage de mots, carte proportionnelle) et une initiation aux cartes choroplèthes.\n\n**Partie 3. Analyses bivariées.** Cette troisième partie comprend trois chapitres dans lesquelles sont présentées les principales méthodes exploratoires et confirmatoires bivariées permettant d'évaluer la relation entre deux variables. Plus spécifiquement, nous présentons puis mettons en œuvre dans R les méthodes permettant d'explorer les relations entre deux variables quantitatives (covariance, corrélation et régression linéaire simple) dans le [chapitre @sec-chap04], deux variables qualitatives (tableau de contingence et test du khi-deux) dans le [chapitre @sec-chap05] et une variable quantitative avec une variable qualitative avec deux modalités (tests de Student, de Welch et de Wilcoxon) ou avec plus de deux modalités (ANOVA et test de Kruskal-Wallis) dans le [chapitre @sec-chap06].\n\n\n**Partie 4. Modèles de régression**. Dans cette quatrième partie sont présentées les principales méthodes de statistique inférentielle utilisées en sciences sociales : la régression linéaire multiple ([chapitre @sec-chap07]), les régressions linéaires généralisées ([chapitre @sec-chap08]), les régressions à effets mixtes ([chapitre @sec-chap09]), les régressions multiniveaux ([chapitre @sec-chap10]), et les modèles généralisés additifs ([chapitre @sec-chap11]).\n\n**Partie 5. Analyses exploratoires multivariées**. Dans cette cinquième partie sont abordées les méthodes de statistique exploratoire et descriptive permettant de décrire des tableaux de données comprenant plusieurs variables. Nous décrivons d'abord les méthodes de réduction de données : les méthodes factorielles dans le [chapitre @sec-chap12] (analyses de composantes principales, analyses factorielles de correspondances, analyses factorielles de correspondances multiples) et les méthodes de classification non supervisées dans le [chapitre @sec-chap13] (classification ascendante hiérarchique, k-moyennes, k-médianes, k-médoïdes et leurs extensions en logique floue comme les c-moyennes et c-médianes).\n\n\n## Pourquoi faut-il programmer en sciences sociales? {-#sect006}\n\nVous contrasterez rapidement que R est un véritable langage de programmation. L'apprentissage de ce langage de programmation est-il pour autant pertinent pour les étudiants et étudiantes en sciences sociales? Il est vrai que la programmation n'est pas une compétence qui vient d'emblée à l'esprit lorsque l'on s'intéresse à la recherche aux sciences sociales. Pourtant, elle est de plus en plus importante, et ce, pour plusieurs raisons :\n\n* Une part toujours plus grande des phénomènes sociaux se produisent ou peuvent s'observer au travers d'environnements numériques. Être capable d'exploiter efficacement ces outils permet d'extraire des données riches sur des phénomènes complexes, tel qu’en témoignent des études récentes sur la propagation de la désinformation sur les réseaux sociaux [@allcott2017social], la migration des personnes [@spyratos2019quantifying], la propagation et les risques de contamination de la COVID-19 [@boulos2020geographical]. Le plus souvent, les interfaces (API par exemple) permettant d'accéder à ces données nécessitent des habiletés en programmation.\n\n* La quantité de données numériques ouvertes et accessibles en ligne croit chaque année sur des sujets très divers. La plupart des villes et des gouvernements ont maintenant leur portail de données ouvertes auxquelles s'ajoutent les données produites par des projets collaboratifs comme [OpenStreetMap](https://www.openstreetmap.org) ou [NoisePlanet](https://noise-planet.org/map_noisecapture/index.html). Récupérer ces données et les structurer pour les utiliser à des fins de recherche nécessitent le plus souvent des compétences en programmation.\n\n* Les méthodes quantitatives connaissent également un développement très important. Les logiciels propriétaires peinent à suivre la cadence de ce développement, contrairement aux logiciels à code source ouvert (comme R) qui permettent d'avoir accès aux dernières méthodes. Il est souvent long et coûteux de développer une interface graphique pour un logiciel, ce qui explique que la plupart de ces programmes en sont dépourvus et nécessitent alors de savoir programmer pour les utiliser.\n\n* Savoir programmer donne une liberté considérable en recherche. Cette compétence permet notamment de ne plus être limité(e) aux fonctionnalités proposées par des logiciels spécifiques. Il devient possible d'innover tant en matière de structuration, d'exploration et d'analyse des données que de représentation des résultats en écrivant ses propres fonctions. Cette flexibilité contribue directement à la production d'une recherche de meilleure qualité et plus diversifiée.\n\n* Programmer permet également d'automatiser des tâches qui autrement seraient extrêmement répétitives comme : déplacer et renommer une centaine de fichiers; retirer les lignes inutiles dans un ensemble de fichiers et les compiler dans une seule base de données; vérifier parmi des milliers d'adresses lesquelles sont valides; récupérer chaque jour les messages postés sur un forum. Autant de tâches faciles à automatiser si l'on sait programmer.\n\n* Dans un logiciel avec une interface graphique, il est compliqué de conserver un historique des opérations effectuées. Programmer permet au contraire de garder une trace de l'ensemble des actions effectuées au cours d'un projet de recherche. En effet, le code utilisé reste disponible et permet de reproduire (ou d'adapter) la méthode et les résultats obtenus, ce qui est essentiel dans le monde de la recherche. À cela s'ajoute le fait que chaque ligne de code que vous écrivez vient s'ajouter à un capital de code que vous possédez, car elles pourront être réutilisées dans d'autres projets!\n\n\n## Remerciements {-#sect007}\n\nDe nombreuses personnes ont contribué à l'élaboration de ce manuel. Ce projet a bénéficié du soutien pédagogique et financier de la [**_fabriqueREL_**](https://fabriquerel.org/) (ressources éducatives libres). Les différentes rencontres avec le comité de suivi nous ont permis de comprendre l'univers des ressources éducatives libres (REL) et notamment leurs [fameux 5R](https://fabriquerel.org/rel/) (Retenir — Réutiliser — Réviser — Remixer — Redistribuer), de mieux définir le besoin pédagogique visé par ce manuel, d'identifier des outils et des ressources pédagogiques pertinents pour son élaboration. Ainsi, nous remercions chaleureusement les membres de suivi de la *fabriqueREL* pour leur support inconditionnel : \n\n- Myriam Beaudet, bibliothécaire à l'Université de Sherbrooke.\n- Marianne Dubé, conseillère pédagogique à l'Université de Sherbrooke et coordonnatrice de la fabriqueREL.\n-\tMyrian Grondin, bibliothécaire à l'Institut national de la recherche scientifique (INRS).\n- Claude Potvin, conseiller en formation à l'Université Laval.\n- Serge Allary, vice-recteur adjoint aux études de l'Université de Sherbrooke.\n\nNous tenons aussi à remercier sincèrement les étudiants et étudiantes du cours **Méthodes quantitatives appliquées aux études urbaines (EUR8219)** du programme de maîtrise en études urbaines de l'INRS. Leurs commentaires et suggestions nous ont permis d'améliorer grandement les versions préliminaires de ce manuel qui ont été utilisées dans le cadre de ce cours.\n\nNous remercions les membres du comité de révision pour leurs commentaires et suggestions très constructifs. Ce comité est composé de trois étudiantes et deux professeurs de l’[INRS](https://inrs.ca/) :\n\n-\tVictoria Gay-Gauvin, étudiante à la maîtrise en études urbaines.\n- Salomé Vallette, étudiante au doctorat en études urbaines.\n- Diana Pena Ruiz, étudiante au doctorat en études des populations.\n- [Benoît Laplante](https://inrs.ca/la-recherche/professeurs/benoit-laplante/), professeur enseignant aux programmes de maîtrise et de doctorat en études des populations.\n- [Xavier Leloup](https://inrs.ca/la-recherche/professeurs/xavier-leloup/), professeur enseignant au programme de doctorat en études urbaines.\n\nFinalement, nous remercions Denise Latreille, réviseure linguistique et chargée de cours à l'Université Sherbrooke, pour la révision du manuel.\n\n## Dédicace toute spéciale à Cargo et Ambrée {-#sect008}\n\nFait cocasse, l'écriture de ce livre a démarré lorsque Philippe Apparicio était famille d'accueil d'un chiot de la [Fondation Mira](https://www.mira.ca/fr/), un organisme à but non lucratif qui forme des chiens-guides et d’assistance pour accroître l’autonomie et l’inclusion sociale des personnes vivant avec un handicap visuel ou moteur, ainsi que des jeunes présentant un trouble du spectre de l’autisme (TSA). En fin de rédaction du livre, ce fut au tour de Jérémy Gelb d'être famille d'accueil d'un autre chiot Mira. Nous remercions chaleureusement la [Fondation Mira](https://www.mira.ca/fr/) pour nous avoir donné l'occasion de vivre cette expérience incroyable. Ce livre est donc dédié au beau Cargo et à la belle Ambrée qui nous ont tant supportés dans l'écriture du livre. Il n’y a rien de plus relaxant que d’écrire un livre de statistique avec un chiot qui dort à ses pieds!\n\n\n![Cargo et Ambrée, chiots de la Fondation Mira](images/introduction/CargoAmbre.png){#fig-CargoAmbre width=\"60%\" fig-align=\"center\"}\n\n\n```{r}\n#| message = FALSE,\n#| warning = FALSE,\n#| include = FALSE\nsource(\"code_complementaire/JG_helper.R\")\nsource(\"code_complementaire/QuizzFunctions.R\")\n```\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"knitr"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"index.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/idx/references.qmd.json b/.quarto/idx/references.qmd.json new file mode 100644 index 0000000..2ba5c52 --- /dev/null +++ b/.quarto/idx/references.qmd.json @@ -0,0 +1 @@ +{"title":"Bibliographie","markdown":{"headingText":"Bibliographie","headingAttr":{"id":"","classes":["unnumbered"],"keyvalue":[]},"containsRefs":true,"markdown":"\n::: {#refs}\n:::\n","srcMarkdownNoYaml":""},"formats":{"html":{"identifier":{"display-name":"HTML","target-format":"html","base-format":"html"},"execute":{"fig-width":7,"fig-height":5,"fig-format":"retina","fig-dpi":96,"df-print":"default","error":false,"eval":true,"cache":null,"freeze":false,"echo":true,"output":true,"warning":true,"include":true,"keep-md":false,"keep-ipynb":false,"ipynb":null,"enabled":null,"daemon":null,"daemon-restart":false,"debug":false,"ipynb-filters":[],"engine":"markdown"},"render":{"keep-tex":false,"keep-source":false,"keep-hidden":false,"prefer-html":false,"output-divs":true,"output-ext":"html","fig-align":"default","fig-pos":null,"fig-env":null,"code-fold":"none","code-overflow":"scroll","code-link":true,"code-line-numbers":false,"code-tools":false,"tbl-colwidths":"auto","merge-includes":true,"inline-includes":false,"preserve-yaml":false,"latex-auto-mk":true,"latex-auto-install":true,"latex-clean":true,"latex-max-runs":10,"latex-makeindex":"makeindex","latex-makeindex-opts":[],"latex-tlmgr-opts":[],"latex-input-paths":[],"latex-output-dir":null,"link-external-icon":false,"link-external-newwindow":false,"self-contained-math":false,"format-resources":[],"notebook-links":true,"format-links":true},"pandoc":{"standalone":true,"wrap":"none","default-image-extension":"png","to":"html","css":["css/quizlib.min.css"],"output-file":"references.html"},"language":{"toc-title-document":"Table des matières","toc-title-website":"Sur cette page","related-formats-title":"Autres formats","related-notebooks-title":"Notebooks","source-notebooks-prefix":"La source","section-title-abstract":"Résumé","section-title-appendices":"Annexes","section-title-footnotes":"Notes de bas de page","section-title-references":"Les références","section-title-reuse":"Réutilisation","section-title-copyright":"Droits d'auteur","section-title-citation":"Citation","appendix-attribution-cite-as":"Veuillez citer ce travail comme suit :","appendix-attribution-bibtex":"BibTeX","title-block-author-single":"Auteur·rice","title-block-author-plural":"Auteurs","title-block-affiliation-single":"Affiliation","title-block-affiliation-plural":"Affiliations","title-block-published":"Date de publication","title-block-modified":"Modifié","callout-tip-title":"Astuce","callout-note-title":"Note","callout-warning-title":"Avertissement","callout-important-title":"Important","callout-caution-title":"Mise en garde","code-summary":"Code","code-tools-menu-caption":"Code","code-tools-show-all-code":"Montrer tout le code","code-tools-hide-all-code":"Cacher tout le code","code-tools-view-source":"Voir les sources","code-tools-source-code":"Code source","code-line":"Ligne","code-lines":"Lignes","copy-button-tooltip":"Copier vers le presse-papier","copy-button-tooltip-success":"Copié","repo-action-links-edit":"Modifier cette page","repo-action-links-source":"Voir la source","repo-action-links-issue":"Signaler un problème ou
formuler une suggestion","back-to-top":"Retour au sommet","search-no-results-text":"Pas de résultats","search-matching-documents-text":"documents trouvés","search-copy-link-title":"Copier le lien vers la recherche","search-hide-matches-text":"Cacher les correspondances additionnelles","search-more-match-text":"correspondance de plus dans ce document","search-more-matches-text":"correspondances de plus dans ce document","search-clear-button-title":"Effacer","search-detached-cancel-button-title":"Annuler","search-submit-button-title":"Envoyer","search":"Recherche","toggle-section":"Basculer la section","toggle-sidebar":"Basculer la barre latérale","toggle-dark-mode":"Basculer le mode sombre","toggle-reader-mode":"Basculer en mode lecteur","toggle-navigation":"Basculer la navigation","crossref-fig-title":"Figure","crossref-tbl-title":"Table","crossref-lst-title":"Listing","crossref-thm-title":"Théorème","crossref-lem-title":"Lemme","crossref-cor-title":"Corollaire","crossref-prp-title":"Proposition","crossref-cnj-title":"Conjecture","crossref-def-title":"Définition","crossref-exm-title":"Exemple","crossref-exr-title":"Exercice","crossref-ch-prefix":"Chapitre","crossref-apx-prefix":"Annexe","crossref-sec-prefix":"Section","crossref-eq-prefix":"Équation","crossref-lof-title":"Liste des Figures","crossref-lot-title":"Liste des Tables","crossref-lol-title":"Liste des Listings","environment-proof-title":"Preuve","environment-remark-title":"Remarque","environment-solution-title":"Solution","listing-page-order-by":"Trier par","listing-page-order-by-default":"Ordre par défaut","listing-page-order-by-date-asc":"Le plus ancien","listing-page-order-by-date-desc":"Le plus récent","listing-page-order-by-number-desc":"Descendant","listing-page-order-by-number-asc":"Ascendant","listing-page-field-date":"Date","listing-page-field-title":"Titre","listing-page-field-description":"Description","listing-page-field-author":"Auteur·rice","listing-page-field-filename":"Nom de fichier","listing-page-field-filemodified":"Modifié","listing-page-field-subtitle":"Sous-titre","listing-page-field-readingtime":"Temps de lecture","listing-page-field-categories":"Catégories","listing-page-minutes-compact":"{0} min.","listing-page-category-all":"Tous","listing-page-no-matches":"Aucun article correspondant"},"metadata":{"lang":"fr","fig-responsive":true,"quarto-version":"1.3.353","license":"CC BY-SA","crossref":{"fig-prefix":"figure","tbl-prefix":"tableau","sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","tbl-title":"Tableau","eq-title":"Équation"},"bibliography":["references.bib"],"csl":"StyleINRS.csl","colorlinks":true,"theme":{"light":["cosmo","css/r4ds.scss"]},"fontsize":"11pt","mainfont":"Helvetica Neue,Helvetica,Arial,sans-serif","monofont":"SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace"},"extensions":{"book":{"multiFile":true}}}},"projectFormats":["html"]} \ No newline at end of file diff --git a/.quarto/xref/19cd9939 b/.quarto/xref/19cd9939 new file mode 100644 index 0000000..7ba9a7d --- /dev/null +++ b/.quarto/xref/19cd9939 @@ -0,0 +1 @@ +{"entries":[{"key":"sec-chap10","order":{"section":[10,0,0,0,0,0,0],"number":1}},{"caption":"10.4.5 Comparaison des quatre modèles","key":"sec-1045","order":{"section":[10,4,5,0,0,0,0],"number":17}},{"caption":"Résultats du modèle avec les variables indépendantes aux niveaux 1 et 2 (modèle 3)","key":"tbl-Modele3","order":{"section":[10,2,2,3,0,0,0],"number":5}},{"caption":"","key":"eq-multiniveauModeleVide","order":{"section":[10,2,2,1,0,0,0],"number":1}},{"caption":"Résultats du modèle vide (modèle 1)","key":"tbl-ModeleVide","order":{"section":[10,2,2,1,0,0,0],"number":2}},{"caption":"Résultats du modèle avec les variables indépendantes centrées au niveau 1 (modèle 2)","key":"tbl-Modele2b","order":{"section":[10,2,2,2,0,0,0],"number":4}},{"caption":"Statistiques descriptives pour les variables des modèles multiniveaux","key":"tbl-Multi","order":{"section":[10,2,1,0,0,0,0],"number":1}},{"caption":"10.2.2.1 Modèle vide","key":"sec-10221","order":{"section":[10,2,2,1,0,0,0],"number":7}},{"caption":"10.2 Différents types de modèles multiniveaux","key":"sec-102","order":{"section":[10,2,0,0,0,0,0],"number":4}},{"caption":"","key":"eq-multiniveauModele2","order":{"section":[10,2,2,2,0,0,0],"number":3}},{"caption":"Résultats du modèle avec une variable d’interaction entre les deux niveaux 1 et 2 (modèle 4)","key":"tbl-Modele4","order":{"section":[10,2,2,4,0,0,0],"number":6}},{"caption":"10.4 Mise en œuvre dans R","key":"sec-104","order":{"section":[10,4,0,0,0,0,0],"number":12}},{"caption":"10.4.1 Le modèle vide","key":"sec-1041","order":{"section":[10,4,1,0,0,0,0],"number":13}},{"caption":"Résultats du modèle avec les variables indépendantes au niveau 1 (modèle 2)","key":"tbl-Modele2","order":{"section":[10,2,2,2,0,0,0],"number":3}},{"caption":"10.1.1 Répartition de la variance entre les différents niveaux","key":"sec-1011","order":{"section":[10,1,1,0,0,0,0],"number":2}},{"caption":"10.2.2.2 Modèle avec les variables indépendantes du niveau 1","key":"sec-10222","order":{"section":[10,2,2,2,0,0,0],"number":8}},{"caption":"10.4.3 Modèle avec les variables indépendantes aux niveaux 1 et 2","key":"sec-1043","order":{"section":[10,4,3,0,0,0,0],"number":15}},{"caption":"10.4.4 Modèle complet avec une interaction","key":"sec-10414","order":{"section":[10,4,4,0,0,0,0],"number":16}},{"caption":"10.4.2 Modèle avec les variables indépendantes du niveau 1","key":"sec-1042","order":{"section":[10,4,2,0,0,0,0],"number":14}},{"caption":"10.2.1 Description du jeu de données utilisé","key":"sec-1021","order":{"section":[10,2,1,0,0,0,0],"number":5}},{"caption":"","key":"eq-multiniveauModele4","order":{"section":[10,2,2,4,0,0,0],"number":5}},{"caption":"10.2.2.4 Modèle avec une interaction entre deux niveaux","key":"sec-10224","order":{"section":[10,2,2,4,0,0,0],"number":10}},{"caption":"","key":"eq-multiniveauModele3","order":{"section":[10,2,2,3,0,0,0],"number":4}},{"caption":"10.5 Quiz de révision du chapitre","key":"sec-105","order":{"section":[10,5,0,0,0,0,0],"number":18}},{"caption":"","key":"eq-multiniveauIcc","order":{"section":[10,2,2,1,0,0,0],"number":2}},{"caption":"10.1 Modèles multiniveaux : deux intérêts majeurs","key":"sec-101","order":{"section":[10,1,0,0,0,0,0],"number":1}},{"caption":"10.2.2.3 Modèle complet avec les variables indépendantes aux niveaux 1 et 2","key":"sec-10223","order":{"section":[10,2,2,3,0,0,0],"number":9}},{"caption":"10.2.2 Démarche classique pour les modèles multiniveaux","key":"sec-1022","order":{"section":[10,2,2,0,0,0,0],"number":6}},{"caption":"10.3 Conditions d’application des régressions multiniveaux","key":"sec-103","order":{"section":[10,3,0,0,0,0,0],"number":11}},{"caption":"10.1.2 Estimation des coefficients aux différents niveaux","key":"sec-1012","order":{"section":[10,1,2,0,0,0,0],"number":3}}],"headings":["sec-101","sec-1011","sec-1012","sec-102","sec-1021","sec-1022","sec-10221","sec-10222","sec-10223","sec-10224","sec-103","sec-104","sec-1041","sec-1042","sec-1043","sec-10414","sec-1045","sec-105","sec-chap10"],"options":{"eq-prefix":"équation","eq-title":"Équation","sec-prefix":"section","tbl-title":"Tableau","tbl-prefix":"tableau","fig-prefix":"figure","chapter-id":"sec-chap10","fig-title":"Figure","chapters":true}} \ No newline at end of file diff --git a/.quarto/xref/24c5beb5 b/.quarto/xref/24c5beb5 new file mode 100644 index 0000000..3823da1 --- /dev/null +++ b/.quarto/xref/24c5beb5 @@ -0,0 +1 @@ +{"headings":["sec-061","sec-0611","sec-06111","sec-06112","sec-06113","sec-06114","sec-06115","sec-0612","sec-062","sec-0621","sec-06211","sec-06212","sec-06213","sec-0622","sec-0623","sec-06231","sec-06232","sec-0624","sec-063","sec-064","sec-chap06"],"options":{"sec-prefix":"section","fig-title":"Figure","chapters":true,"eq-prefix":"équation","eq-title":"Équation","chapter-id":"sec-chap06","tbl-title":"Tableau","fig-prefix":"figure","tbl-prefix":"tableau"},"entries":[{"order":{"number":1,"section":[6,0,0,0,0,0,0]},"key":"sec-chap06"},{"order":{"number":6,"section":[6,1,1,2,0,0,0]},"caption":"","key":"eq-ghedge"},{"order":{"number":3,"section":[6,1,1,1,0,0,0]},"caption":"6.1.1.1 Principe de base et formulation pour des échantillons dépendants (appariés)","key":"sec-06111"},{"order":{"number":7,"section":[6,1,1,2,0,0,0]},"caption":"","key":"eq-dDelta"},{"order":{"number":5,"section":[6,2,3,1,0,0,0]},"caption":"QQ Plot pour les groupes","key":"fig-Qqplot"},{"order":{"number":3,"section":[6,1,1,3,0,0,0]},"caption":"Pourcentage de locataires par secteur de recensement, région métropolitaine de recensement de Montréal, 2016","key":"fig-locataires"},{"order":{"number":7,"section":[6,2,3,2,0,0,0]},"caption":"QQ Plot pour les groupes","key":"fig-Qqplot2"},{"order":{"number":10,"section":[6,2,1,1,0,0,0]},"caption":"","key":"eq-anova3"},{"order":{"number":6,"section":[6,2,3,2,0,0,0]},"caption":"Graphique de densité et en violon","key":"fig-Anova1b"},{"order":{"number":5,"section":[6,1,1,3,0,0,0]},"caption":"6.1.1.3 Mise en œuvre dans R","key":"sec-06113"},{"order":{"number":9,"section":[6,2,1,1,0,0,0]},"caption":"","key":"eq-anova2"},{"order":{"number":2,"section":[6,1,1,0,0,0,0]},"caption":"","key":"eq-cas2welch"},{"order":{"number":2,"section":[6,2,1,1,0,0,0]},"caption":"Données fictives et calcul des trois variances (cas 1)","key":"tbl-aovfictive1"},{"order":{"number":3,"section":[6,2,1,1,0,0,0]},"caption":"Données fictives et calcul des trois variances (cas 2)","key":"tbl-aovfictive2"},{"order":{"number":15,"section":[6,2,3,0,0,0,0]},"caption":"6.2.3 Mise en œuvre dans R","key":"sec-0623"},{"order":{"number":7,"section":[6,1,1,5,0,0,0]},"caption":"6.1.1.5 Comment rapporter un test de Student ou de Welch?","key":"sec-06115"},{"order":{"number":4,"section":[6,1,1,2,0,0,0]},"caption":"","key":"eq-dcohen"},{"order":{"number":9,"section":[6,2,0,0,0,0,0]},"caption":"6.2 Relation entre une variable quantitative et une variable qualitative à plus de deux modalités","key":"sec-062"},{"order":{"number":2,"section":[6,1,1,1,0,0,0]},"caption":"Boites à moustaches sur des échantillons fictifs appariés","key":"fig-ttest2"},{"order":{"number":13,"section":[6,2,1,2,0,0,0]},"caption":"","key":"eq-anovaF"},{"order":{"number":4,"section":[6,1,1,2,0,0,0]},"caption":"6.1.1.2 Mesure de la taille de l’effet","key":"sec-06112"},{"order":{"number":6,"section":[6,1,1,4,0,0,0]},"caption":"6.1.1.4 Comparaison des moyennes pondérées","key":"sec-06114"},{"order":{"number":1,"section":[6,1,1,2,0,0,0]},"caption":"Conventions pour l’interprétation du d de Cohen","key":"tbl-convcohen"},{"order":{"number":20,"section":[6,4,0,0,0,0,0]},"caption":"6.4 Quiz de révision du chapitre","key":"sec-064"},{"order":{"number":4,"section":[6,2,3,1,0,0,0]},"caption":"Graphiques de densité et en violon","key":"fig-Anova1a"},{"order":{"number":18,"section":[6,2,4,0,0,0,0]},"caption":"6.2.4 Comment rapporter les résultats d’une ANOVA et du test de Kruskal-Wallis","key":"sec-0624"},{"order":{"number":13,"section":[6,2,1,3,0,0,0]},"caption":"6.2.1.3 Conditions d’application de l’ANOVA et solutions de rechange","key":"sec-06213"},{"order":{"number":12,"section":[6,2,1,2,0,0,0]},"caption":"6.2.1.2 Test de Fisher","key":"sec-06212"},{"order":{"number":2,"section":[6,1,1,0,0,0,0]},"caption":"6.1.1 Test t et ses différentes variantes","key":"sec-0611"},{"order":{"number":1,"section":[6,1,1,0,0,0,0]},"caption":"Boîtes à moustaches sur des échantillons fictifs non appariés","key":"fig-ttest1"},{"order":{"number":1,"section":[6,1,0,0,0,0,0]},"caption":"6.1 Relation entre une variable quantitative et une variable qualitative à deux modalités","key":"sec-061"},{"order":{"number":8,"section":[6,3,0,0,0,0,0]},"caption":"Principales méthodes bivariées","key":"fig-PrincipalesAnalysesBivariees"},{"order":{"number":5,"section":[6,1,1,2,0,0,0]},"caption":"","key":"eq-dcohen2"},{"order":{"number":19,"section":[6,3,0,0,0,0,0]},"caption":"6.3 Conclusion sur la troisième partie","key":"sec-063"},{"order":{"number":14,"section":[6,2,2,0,0,0,0]},"caption":"6.2.2 Test non paramétrique de Kruskal-Wallis","key":"sec-0622"},{"order":{"number":16,"section":[6,2,3,1,0,0,0]},"caption":"6.2.3.1 Première ANOVA : différences entre les temps de déplacement","key":"sec-06231"},{"order":{"number":17,"section":[6,2,3,2,0,0,0]},"caption":"6.2.3.2 Deuxième ANOVA : différences entre les niveaux d’exposition au bruit","key":"sec-06232"},{"order":{"number":11,"section":[6,2,1,1,0,0,0]},"caption":"6.2.1.1 Calcul des trois variances pour l’ANOVA","key":"sec-06211"},{"order":{"number":3,"section":[6,1,1,1,0,0,0]},"caption":"","key":"eq-ttestapparie"},{"order":{"number":1,"section":[6,1,1,0,0,0,0]},"caption":"","key":"eq-cas1pooled"},{"order":{"number":10,"section":[6,2,1,0,0,0,0]},"caption":"6.2.1 Analyse de variance","key":"sec-0621"},{"order":{"number":8,"section":[6,1,2,0,0,0,0]},"caption":"6.1.2 Test non paramétrique de Wilcoxon","key":"sec-0612"},{"order":{"number":11,"section":[6,2,1,1,0,0,0]},"caption":"","key":"eq-anova5"},{"order":{"number":8,"section":[6,2,1,1,0,0,0]},"caption":"","key":"eq-anova1"},{"order":{"number":12,"section":[6,2,1,1,0,0,0]},"caption":"","key":"eq-anova6"}]} \ No newline at end of file diff --git a/.quarto/xref/3d6f23dc b/.quarto/xref/3d6f23dc new file mode 100644 index 0000000..70dde29 --- /dev/null +++ b/.quarto/xref/3d6f23dc @@ -0,0 +1 @@ +{"headings":["sec-041","sec-042","sec-0421","sec-0422","sec-043","sec-0431","sec-0432","sec-0433","sec-0434","sec-0435","sec-0436","sec-0437","sec-0438","sec-044","sec-0441","sec-0442","sec-0443","sec-0444","sec-0445","sec-045","sec-chap04"],"entries":[{"key":"sec-chap04","order":{"number":1,"section":[4,0,0,0,0,0,0]}},{"key":"eq-reg3","order":{"number":12,"section":[4,4,3,0,0,0,0]},"caption":""},{"key":"sec-0441","order":{"number":15,"section":[4,4,1,0,0,0,0]},"caption":"4.4.1 Principe de base de la régression linéaire simple"},{"key":"sec-0445","order":{"number":19,"section":[4,4,5,0,0,0,0]},"caption":"4.4.5 Comment rapporter une régression linéaire simple"},{"key":"sec-0436","order":{"number":11,"section":[4,3,6,0,0,0,0]},"caption":"4.3.6 Corrélation partielle"},{"key":"sec-0422","order":{"number":4,"section":[4,2,2,0,0,0,0]},"caption":"4.2.2 Interprétation"},{"key":"eq-reg6","order":{"number":15,"section":[4,4,3,0,0,0,0]},"caption":""},{"key":"eq-reg2","order":{"number":11,"section":[4,4,3,0,0,0,0]},"caption":""},{"key":"eq-bicor","order":{"number":5,"section":[4,3,4,0,0,0,0]},"caption":""},{"key":"fig-corrplot1","order":{"number":9,"section":[4,3,7,0,0,0,0]},"caption":"Matrice de corrélation avec corrplot (chiffres)"},{"key":"eq-cov","order":{"number":1,"section":[4,2,1,0,0,0,0]},"caption":""},{"key":"eq-regsimple","order":{"number":7,"section":[4,4,1,0,0,0,0]},"caption":""},{"key":"sec-044","order":{"number":14,"section":[4,4,0,0,0,0,0]},"caption":"4.4 Régression linéaire simple"},{"key":"fig-coefCorrVar","order":{"number":5,"section":[4,3,2,0,0,0,0]},"caption":"Coefficient de corrélation et proportion de la variance expliquée"},{"key":"sec-0438","order":{"number":13,"section":[4,3,8,0,0,0,0]},"caption":"4.3.8 Comment rapporter des valeurs de corrélations?"},{"key":"fig-fig2","order":{"number":1,"section":[4,1,0,0,0,0,0]},"caption":"Relations linéaires et curvilinéaires entre deux variables continues"},{"key":"eq-corpartielle","order":{"number":6,"section":[4,3,6,0,0,0,0]},"caption":""},{"key":"sec-045","order":{"number":20,"section":[4,5,0,0,0,0,0]},"caption":"4.5 Quiz de révision du chapitre"},{"key":"fig-covariance","order":{"number":3,"section":[4,2,2,0,0,0,0]},"caption":"Covariance et unités de mesure"},{"key":"sec-0434","order":{"number":9,"section":[4,3,4,0,0,0,0]},"caption":"4.3.4 Corrélations robustes (Biweight midcorrelation, Percentage bend correlation et la corrélation pi de Shepherd)"},{"key":"sec-0444","order":{"number":18,"section":[4,4,4,0,0,0,0]},"caption":"4.4.4 Mise en œuvre dans R"},{"key":"eq-reg4","order":{"number":13,"section":[4,4,3,0,0,0,0]},"caption":""},{"key":"tbl-regfictives","order":{"number":3,"section":[4,4,1,0,0,0,0]},"caption":"Données fictives sur l’utilisation du vélo par municipalité"},{"key":"eq-reg5","order":{"number":14,"section":[4,4,3,0,0,0,0]},"caption":""},{"key":"tbl-computeR","order":{"number":5,"section":[4,4,3,0,0,0,0]},"caption":"Calcul du coefficient de détermination"},{"key":"eq-reg7","order":{"number":16,"section":[4,4,3,0,0,0,0]},"caption":""},{"key":"sec-0431","order":{"number":6,"section":[4,3,1,0,0,0,0]},"caption":"4.3.1 Formulation"},{"key":"sec-042","order":{"number":2,"section":[4,2,0,0,0,0,0]},"caption":"4.2 Covariance"},{"key":"eq-b1","order":{"number":9,"section":[4,4,2,0,0,0,0]},"caption":""},{"key":"sec-043","order":{"number":5,"section":[4,3,0,0,0,0,0]},"caption":"4.3 Corrélation"},{"key":"sec-0433","order":{"number":8,"section":[4,3,3,0,0,0,0]},"caption":"4.3.3 Corrélations pour des variables anormalement distribuées (coefficient de Spearman, tau de Kendall)"},{"key":"tbl-robcorr","order":{"number":2,"section":[4,3,4,0,0,0,0]},"caption":"Comparaison de différentes corrélations pour les deux variables"},{"key":"tbl-tableIntervallesCorrelation","order":{"number":1,"section":[4,3,2,0,0,0,0]},"caption":"Intervalles pour l’interprétation du coefficient de corrélation habituellement utilisés en sciences sociales"},{"key":"tbl-regfictives2","order":{"number":4,"section":[4,4,2,0,0,0,0]},"caption":"Valeurs observées, prédites et résidus"},{"key":"sec-0432","order":{"number":7,"section":[4,3,2,0,0,0,0]},"caption":"4.3.2 Interprétation"},{"key":"sec-0435","order":{"number":10,"section":[4,3,5,0,0,0,0]},"caption":"4.3.5 Significativité des coefficients de corrélation"},{"key":"eq-b0","order":{"number":10,"section":[4,4,2,0,0,0,0]},"caption":""},{"key":"fig-ValExtremes","order":{"number":6,"section":[4,3,2,0,0,0,0]},"caption":"Illustation de l’effet des valeurs extrêmes sur le coefficient de Pearson"},{"key":"eq-tau","order":{"number":4,"section":[4,3,3,0,0,0,0]},"caption":""},{"key":"fig-PearsonSpearmanKendall","order":{"number":7,"section":[4,3,3,0,0,0,0]},"caption":"Comparaison des coefficients de Pearson, Spearman et Kendall sur deux variables anormalement distribuées"},{"key":"fig-reg","order":{"number":12,"section":[4,4,1,0,0,0,0]},"caption":"Relation linéaire entre l’utilisation du vélo et la distance au centre-ville"},{"key":"sec-0442","order":{"number":16,"section":[4,4,2,0,0,0,0]},"caption":"4.4.2 Formulation de la droite de régression des moindres carrés ordinaires"},{"key":"fig-corrplot2","order":{"number":10,"section":[4,3,7,0,0,0,0]},"caption":"Matrice de corrélation avec corrplot (chiffres et ellipses)"},{"key":"fig-replicationhist","order":{"number":11,"section":[4,4,0,0,0,0,0]},"caption":"Corrélations significatives obtenues aléatoirement"},{"key":"eq-cor","order":{"number":2,"section":[4,3,1,0,0,0,0]},"caption":""},{"key":"fig-fig9","order":{"number":8,"section":[4,3,5,0,0,0,0]},"caption":"Histogramme pour les valeurs de corrélation issues du Bootstrap"},{"key":"fig-coeffPearson","order":{"number":4,"section":[4,3,2,0,0,0,0]},"caption":"Relations entre deux variables continues et coefficients de corrélation de Pearson"},{"key":"fig-reg2","order":{"number":13,"section":[4,4,2,0,0,0,0]},"caption":"Droite de régression, valeurs observées, prédites et résidus"},{"key":"eq-mco","order":{"number":8,"section":[4,4,2,0,0,0,0]},"caption":""},{"key":"sec-0421","order":{"number":3,"section":[4,2,1,0,0,0,0]},"caption":"4.2.1 Formulation"},{"key":"eq-spearman","order":{"number":3,"section":[4,3,3,0,0,0,0]},"caption":""},{"key":"fig-fig3","order":{"number":2,"section":[4,1,0,0,0,0,0]},"caption":"Exemples de relations curvilinéaires"},{"key":"sec-0443","order":{"number":17,"section":[4,4,3,0,0,0,0]},"caption":"4.4.3 Mesure de la qualité d’ajustement du modèle"},{"key":"sec-0437","order":{"number":12,"section":[4,3,7,0,0,0,0]},"caption":"4.3.7 Mise en œuvre dans R"},{"key":"sec-041","order":{"number":1,"section":[4,1,0,0,0,0,0]},"caption":"4.1 Bref retour sur le postulat de la relation linéaire"}],"options":{"chapters":true,"tbl-title":"Tableau","fig-prefix":"figure","tbl-prefix":"tableau","eq-title":"Équation","eq-prefix":"équation","chapter-id":"sec-chap04","fig-title":"Figure","sec-prefix":"section"}} \ No newline at end of file diff --git a/.quarto/xref/40a20182 b/.quarto/xref/40a20182 new file mode 100644 index 0000000..2d5acd2 --- /dev/null +++ b/.quarto/xref/40a20182 @@ -0,0 +1 @@ +{"headings":["sec-111","sec-1111","sec-1112","sec-1113","sec-1114","sec-112","sec-113","sec-114","sec-115","sec-1151","sec-1152","sec-1153","sec-116","sec-117","sec-1171","sec-1172","sec-118","sec-chap11"],"entries":[{"order":{"number":1,"section":[11,0,0,0,0,0,0]},"key":"sec-chap11"},{"caption":"11.5.3 Splines multivariées et splines d’interaction","order":{"number":12,"section":[11,5,3,0,0,0,0]},"key":"sec-1153"},{"caption":"Spline cyclique variant par groupe","order":{"number":14,"section":[11,5,2,0,0,0,0]},"key":"fig-gam14"},{"caption":"Exemples de splines avancées","order":{"number":1,"section":[11,5,0,0,0,0,0]},"key":"tbl-exemplesplines"},{"caption":"Comparaison de deux splines spatiales","order":{"number":17,"section":[11,6,0,0,0,0,0]},"key":"fig-gam17"},{"caption":"11.8 Quiz de révision du chapitre","order":{"number":17,"section":[11,8,0,0,0,0,0]},"key":"sec-118"},{"caption":"11.4 Multicolinéarité non linéaire","order":{"number":8,"section":[11,4,0,0,0,0,0]},"key":"sec-114"},{"caption":"11.6 Mise en œuvre dans R","order":{"number":13,"section":[11,6,0,0,0,0,0]},"key":"sec-116"},{"caption":"","order":{"number":1,"section":[11,1,0,0,0,0,0]},"key":"eq-glm1B"},{"caption":"Comparaison d’une spline et d’une polynomiale","order":{"number":16,"section":[11,6,0,0,0,0,0]},"key":"fig-gam16"},{"caption":"Spline cyclique pour modéliser la concentration de dioxyde d’azote","order":{"number":13,"section":[11,5,1,0,0,0,0]},"key":"fig-gam13"},{"caption":"Régression par segment","order":{"number":7,"section":[11,1,3,0,0,0,0]},"key":"fig-gam7"},{"caption":"11.5.1 Splines cycliques","order":{"number":10,"section":[11,5,1,0,0,0,0]},"key":"sec-1151"},{"caption":"Sur et sous-ajustement d’une polynomiale","order":{"number":6,"section":[11,1,2,0,0,0,0]},"key":"fig-gam6"},{"caption":"11.5.2 Splines par groupe","order":{"number":11,"section":[11,5,2,0,0,0,0]},"key":"sec-1152"},{"caption":"Relation entre les effets aléatoires des arrondissements et la variable population à faible revenu","order":{"number":22,"section":[11,7,0,2,0,0,0]},"key":"fig-corrrandom"},{"caption":"Pentes et constantes aléatoires pour les arrondissements","order":{"number":21,"section":[11,7,0,2,0,0,0]},"key":"fig-randomconstcoefGAM"},{"caption":"Constantes aléatoires pour les arrondissements avec intervalle de confiance","order":{"number":19,"section":[11,7,0,1,0,0,0]},"key":"fig-randomconstGAM2"},{"caption":"Prédictions pour les différents arrondissements pour une AD fictive moyenne","order":{"number":20,"section":[11,7,0,1,0,0,0]},"key":"fig-randomconstGAM3"},{"caption":"11.7.0.2 GAMM et coefficients aléatoires","order":{"number":16,"section":[11,7,0,2,0,0,0]},"key":"sec-1172"},{"caption":"Relation non linéaire plus complexe","order":{"number":4,"section":[11,1,1,0,0,0,0]},"key":"fig-gam4"},{"caption":"11.7 GAMM","order":{"number":14,"section":[11,7,0,0,0,0,0]},"key":"sec-117"},{"caption":"11.1.3 Non-linéarité par segments","order":{"number":4,"section":[11,1,3,0,0,0,0]},"key":"sec-1113"},{"caption":"Relation non linéaire exponentielle","order":{"number":2,"section":[11,1,1,0,0,0,0]},"key":"fig-gam2"},{"caption":"Patron journalier du dioxyde d’azote et de l’ozone à Paris","order":{"number":1,"section":[11,1,0,0,0,0,0]},"key":"fig-gam1"},{"caption":"Spline triangulaire","order":{"number":10,"section":[11,1,4,0,0,0,0]},"key":"fig-gam10"},{"caption":"11.1.4 Non-linéarité avec des splines","order":{"number":5,"section":[11,1,4,0,0,0,0]},"key":"sec-1114"},{"caption":"Comparaison de différentes bases","order":{"number":11,"section":[11,1,4,0,0,0,0]},"key":"fig-gam11"},{"caption":"11.7.0.1 GAMM et interceptes aléatoires","order":{"number":15,"section":[11,7,0,1,0,0,0]},"key":"sec-1171"},{"caption":"Constantes aléatoires pour les arrondissements","order":{"number":18,"section":[11,7,0,1,0,0,0]},"key":"fig-randomconstGAM"},{"caption":"Visualisation de plusieurs polynomiales","order":{"number":5,"section":[11,1,2,0,0,0,0]},"key":"fig-gam5"},{"caption":"11.1.1 Non-linéarité fonctionnelle","order":{"number":2,"section":[11,1,1,0,0,0,0]},"key":"sec-1111"},{"caption":"Spline triangulaire multipliée par ces coefficients","order":{"number":9,"section":[11,1,4,0,0,0,0]},"key":"fig-gam9"},{"caption":"Pénalisation des splines","order":{"number":12,"section":[11,2,0,0,0,0,0]},"key":"fig-gam12"},{"caption":"Spline d’interaction bivariée","order":{"number":15,"section":[11,5,3,0,0,0,0]},"key":"fig-gam15"},{"caption":"11.3 Interprétation d’une spline","order":{"number":7,"section":[11,3,0,0,0,0,0]},"key":"sec-113"},{"caption":"11.1 Introduction","order":{"number":1,"section":[11,1,0,0,0,0,0]},"key":"sec-111"},{"caption":"11.2 Spline de régression et spline de lissage","order":{"number":6,"section":[11,2,0,0,0,0,0]},"key":"sec-112"},{"caption":"Bases de la spline triangulaire","order":{"number":8,"section":[11,1,4,0,0,0,0]},"key":"fig-gam8"},{"caption":"11.1.2 Non-linéarité avec des polynomiales","order":{"number":3,"section":[11,1,2,0,0,0,0]},"key":"sec-1112"},{"caption":"11.5 Splines avancées","order":{"number":9,"section":[11,5,0,0,0,0,0]},"key":"sec-115"},{"caption":"Autres relations non linéaires","order":{"number":3,"section":[11,1,1,0,0,0,0]},"key":"fig-gam3"}],"options":{"sec-prefix":"section","eq-prefix":"équation","fig-title":"Figure","chapters":true,"tbl-title":"Tableau","fig-prefix":"figure","chapter-id":"sec-chap11","eq-title":"Équation","tbl-prefix":"tableau"}} \ No newline at end of file diff --git a/.quarto/xref/4b2fdbb1 b/.quarto/xref/4b2fdbb1 new file mode 100644 index 0000000..ff481eb --- /dev/null +++ b/.quarto/xref/4b2fdbb1 @@ -0,0 +1 @@ +{"headings":["préface","sect001","sect002","sect003","sect003B","sect004","sect005","sect006","sect007","sect008"],"entries":[{"caption":"Cargo et Ambrée, chiots de la Fondation Mira","key":"fig-CargoAmbre","order":{"number":3,"section":[0,0,0,0,0,0,0]}},{"caption":"Téléchargement de l’intégralité du livre","key":"fig-downloaffromgit","order":{"number":2,"section":[0,0,0,0,0,0,0]}},{"caption":"Licence Creative Commons du livre","key":"fig-Licence","order":{"number":1,"section":[0,0,0,0,0,0,0]}}],"options":{"eq-title":"Équation","fig-title":"Figure","fig-prefix":"figure","tbl-title":"Tableau","sec-prefix":"section","tbl-prefix":"tableau","eq-prefix":"équation","chapters":true}} \ No newline at end of file diff --git a/.quarto/xref/50e63b0f b/.quarto/xref/50e63b0f new file mode 100644 index 0000000..f8faeab --- /dev/null +++ b/.quarto/xref/50e63b0f @@ -0,0 +1 @@ +{"options":{"chapter-id":"sec-chap09","eq-title":"Équation","fig-title":"Figure","sec-prefix":"section","tbl-prefix":"tableau","tbl-title":"Tableau","fig-prefix":"figure","chapters":true,"eq-prefix":"équation"},"entries":[{"order":{"number":1,"section":[9,0,0,0,0,0,0]},"key":"sec-chap09"},{"caption":"Incertitude autour des paramètres de variance obtenue par bootstrap","order":{"number":20,"section":[9,6,2,1,0,0,0]},"key":"fig-glmmvarboot"},{"caption":"Distribution normale bivariée des constantes et des pentes aléatoires","order":{"number":23,"section":[9,6,2,3,0,0,0]},"key":"fig-diagbinomglmm2"},{"caption":"Différentes structures de données hiérarchiques (imbriquée versus croisée)","order":{"number":12,"section":[9,2,3,0,0,0,0]},"key":"fig-crossednested"},{"caption":"Distribution normale univariée des constantes et des pentes aléatoires","order":{"number":22,"section":[9,6,2,3,0,0,0]},"key":"fig-diagbinomglmm1"},{"caption":"","order":{"number":3,"section":[9,2,1,3,0,0,0]},"key":"eq-glmm3"},{"caption":"Distribution normale univariée des constantes aléatoires","order":{"number":13,"section":[9,3,1,0,0,0,0]},"key":"fig-diagglmm1"},{"caption":"Constantes aléatoires estimées par pays (intervalles de confiance obtenus par simulations)","order":{"number":21,"section":[9,6,2,2,0,0,0]},"key":"fig-randomconstantes2b"},{"caption":"9.3 Conditions d’application des GLMM","order":{"number":11,"section":[9,3,0,0,0,0,0]},"key":"sec-093"},{"caption":"Comparaison des effets fixes et aléatoires pour le modèle intégrant l’effet des classes et l’interaction entre les classes et le temps de travail","order":{"number":11,"section":[9,2,3,0,0,0,0]},"key":"fig-fullrandom3"},{"caption":"9.1 Introduction","order":{"number":1,"section":[9,1,0,0,0,0,0]},"key":"sec-091"},{"caption":"Influence du temps de travail sur la performance scolaire d’élèves en tenant compte de l’effet de leur classe et de l’effet de la classe sur l’efficacité du temps de travail (effet aléatoire)","order":{"number":10,"section":[9,2,3,0,0,0,0]},"key":"fig-fullrandom2"},{"caption":"","order":{"number":7,"section":[9,2,3,0,0,0,0]},"key":"eq-glmm7"},{"caption":"9.2.1.2 Prédiction pour de nouveaux groupes","order":{"number":7,"section":[9,2,1,2,0,0,0]},"key":"sec-09222"},{"caption":"9.4 Inférence dans les modèles GLMM","order":{"number":14,"section":[9,4,0,0,0,0,0]},"key":"sec-094"},{"caption":"9.6.2 Ajustement du modèle avec constantes et pentes aléatoires","order":{"number":27,"section":[9,6,2,0,0,0,0]},"key":"sec-0962"},{"caption":"","order":{"number":5,"section":[9,2,2,0,0,0,0]},"key":"eq-glmm5"},{"caption":"Distribution normale bivariée des constantes et des pentes aléatoires","order":{"number":15,"section":[9,3,1,0,0,0,0]},"key":"fig-diagglmm3"},{"caption":"9.4.1.2 Rapports de vraisemblance","order":{"number":17,"section":[9,4,1,2,0,0,0]},"key":"sec-09412"},{"caption":"9.6.2.4 Inférence pour les effets fixes","order":{"number":31,"section":[9,6,2,4,0,0,0]},"key":"sec-09624"},{"caption":"","order":{"number":8,"section":[9,2,3,0,0,0,0]},"key":"eq-glmm8"},{"caption":"9.4.2 Inférence pour les effets aléatoires, effet global","order":{"number":19,"section":[9,4,2,0,0,0,0]},"key":"sec-0942"},{"caption":"9.2.1.1 Resserrement (shrinkage) et mutualisation (partial pooling)","order":{"number":6,"section":[9,2,1,1,0,0,0]},"key":"sec-09221"},{"caption":"9.4.1 Inférence pour les effets fixes","order":{"number":15,"section":[9,4,1,0,0,0,0]},"key":"sec-0941"},{"caption":"9.2.1 GLMM avec constantes aléatoires","order":{"number":5,"section":[9,2,1,0,0,0,0]},"key":"sec-0921"},{"caption":"9.6.1.2 Significativité de l’effet aléatoire","order":{"number":25,"section":[9,6,1,2,0,0,0]},"key":"sec-09612"},{"caption":"","order":{"number":4,"section":[9,2,2,0,0,0,0]},"key":"eq-glmm4"},{"caption":"Multiples distributions normales univariées des constantes et pentes aléatoires","order":{"number":14,"section":[9,3,1,0,0,0,0]},"key":"fig-diagglmm2"},{"caption":"9.6.1.1 Rôle joué par l’effet aléatoire","order":{"number":24,"section":[9,6,1,1,0,0,0]},"key":"sec-09611"},{"caption":"9.4.3 Inférence pour les effets aléatoires, des constantes et des pentes","order":{"number":20,"section":[9,4,3,0,0,0,0]},"key":"sec-0943"},{"caption":"Constantes aléatoires estimées par Pays (IC par simulations)","order":{"number":18,"section":[9,6,1,3,0,0,0]},"key":"fig-randomconstantes1"},{"caption":"9.3.1 Vérification de la distribution des effets aléatoires","order":{"number":12,"section":[9,3,1,0,0,0,0]},"key":"sec-0931"},{"caption":"9.7 Quiz de révision du chapitre","order":{"number":32,"section":[9,7,0,0,0,0,0]},"key":"sec-097"},{"caption":"9.1.2 Terminologie : effets fixes et effets aléatoires","order":{"number":3,"section":[9,1,2,0,0,0,0]},"key":"sec-0912"},{"caption":"9.3.2 Homogénéité des variances au sein des groupes","order":{"number":13,"section":[9,3,2,0,0,0,0]},"key":"sec-0932"},{"caption":"9.6.2.2 Analyse des effets aléatoires","order":{"number":29,"section":[9,6,2,2,0,0,0]},"key":"sec-09622"},{"caption":"","order":{"number":10,"section":[9,2,3,0,0,0,0]},"key":"eq-glmm10"},{"caption":"9.1.1 Indépendance des observations et effets de groupes","order":{"number":2,"section":[9,1,1,0,0,0,0]},"key":"sec-0911"},{"caption":"Distributions obtenues par bootstrap de la variance de l’effet aléatoire, de l’ICC et du R carré conditionnel","order":{"number":17,"section":[9,6,1,2,0,0,0]},"key":"fig-bottdistrib"},{"caption":"9.2.3 GLMM avec constantes et pentes aléatoires","order":{"number":10,"section":[9,2,3,0,0,0,0]},"key":"sec-0924"},{"caption":"","order":{"number":9,"section":[9,2,3,0,0,0,0]},"key":"eq-glmm9"},{"caption":"9.6 Mise en œuvre des GLMM dans R","order":{"number":22,"section":[9,6,0,0,0,0,0]},"key":"sec-096"},{"caption":"Influence du temps de travail sur la performance scolaire d’élèves en tenant compte de l’effet de leur classe et de l’effet de la classe sur l’efficacité du temps de travail (effet fixe)","order":{"number":9,"section":[9,2,3,0,0,0,0]},"key":"fig-fullrandom1"},{"caption":"Influence du temps de travail sur la réussite scolaire d’élèves en interaction avec la classe (effet aléatoire)","order":{"number":8,"section":[9,2,2,0,0,0,0]},"key":"fig-randomslope3"},{"caption":"9.6.1.3 Significativité des différentes constantes","order":{"number":26,"section":[9,6,1,3,0,0,0]},"key":"sec-09613"},{"caption":"","order":{"number":1,"section":[9,2,1,0,0,0,0]},"key":"eq-glmm1"},{"caption":"9.2.2 GLMM avec pentes aléatoires","order":{"number":9,"section":[9,2,2,0,0,0,0]},"key":"sec-0923"},{"caption":"9.2 Principes de base des GLMM","order":{"number":4,"section":[9,2,0,0,0,0,0]},"key":"sec-092"},{"caption":"9.6.1 Ajustement du modèle avec uniquement une constante aléatoire","order":{"number":23,"section":[9,6,1,0,0,0,0]},"key":"sec-0961"},{"caption":"9.6.2.1 Significativité de l’effet aléatoire","order":{"number":28,"section":[9,6,2,1,0,0,0]},"key":"sec-09621"},{"caption":"Influence du temps de travail sur la performance scolaire d’élèves en interaction avec la classe (effet fixe)","order":{"number":6,"section":[9,2,2,0,0,0,0]},"key":"fig-randomslope"},{"caption":"Influence du temps de travail sur la réussite scolaire d’élèves en interaction avec la classe (effet aléatoire)","order":{"number":7,"section":[9,2,2,0,0,0,0]},"key":"fig-randomslope2"},{"caption":"Homogénéité de la variance pour les différents groupes d’un modèle GLMM gaussien","order":{"number":16,"section":[9,3,2,0,0,0,0]},"key":"fig-glmmvariance"},{"caption":"Comparaison des trois modèles à effets aléatoires","order":{"number":1,"section":[9,2,3,0,0,0,0]},"key":"tbl-fullrandom4"},{"caption":"","order":{"number":6,"section":[9,2,3,0,0,0,0]},"key":"eq-glmm6"},{"caption":"Influence du temps de travail sur la performance scolaire d’élèves","order":{"number":2,"section":[9,2,1,0,0,0,0]},"key":"fig-randominter1"},{"caption":"9.5 Conclusion sur les GLMM","order":{"number":21,"section":[9,5,0,0,0,0,0]},"key":"sec-095"},{"caption":"Comparaison des effets des classes pour le modèle à effets fixes versus le modèle à effets aléatoires","order":{"number":5,"section":[9,2,1,1,0,0,0]},"key":"fig-randominter5"},{"caption":"Influence du temps de travail sur la performance scolaire d’élèves en tenant compte de l’effet de leur classe (effet fixe)","order":{"number":3,"section":[9,2,1,0,0,0,0]},"key":"fig-randominter2"},{"caption":"","order":{"number":11,"section":[9,6,1,0,0,0,0]},"key":"eq-glmmbinom1"},{"caption":"","order":{"number":2,"section":[9,2,1,0,0,0,0]},"key":"eq-glmm2"},{"caption":"9.4.1.3 Bootstrapping","order":{"number":18,"section":[9,4,1,3,0,0,0]},"key":"sec-09413"},{"caption":"Influence du temps de travail sur la performance scolaire d’élèves en tenant compte de l’effet de leur classe (effet aléatoire)","order":{"number":4,"section":[9,2,1,0,0,0,0]},"key":"fig-randominter3"},{"caption":"9.2.1.3 Partition de la variance","order":{"number":8,"section":[9,2,1,3,0,0,0]},"key":"sec-09223"},{"caption":"Structure hiérarchique entre élèves, classes et écoles","order":{"number":1,"section":[9,1,1,0,0,0,0]},"key":"fig-glmmecoles"},{"caption":"9.4.1.1 Test classique","order":{"number":16,"section":[9,4,1,1,0,0,0]},"key":"sec-09411"},{"caption":"9.6.2.3 Diagnostic des effets aléatoires","order":{"number":30,"section":[9,6,2,3,0,0,0]},"key":"sec-09623"},{"caption":"Constantes aléatoires estimées par Pays (IC par bootstrap)","order":{"number":19,"section":[9,6,1,3,0,0,0]},"key":"fig-randomconstantes2"}],"headings":["sec-091","sec-0911","sec-0912","sec-092","sec-0921","sec-09221","sec-09222","sec-09223","sec-0923","sec-0924","sec-093","sec-0931","sec-0932","sec-094","sec-0941","sec-09411","sec-09412","sec-09413","sec-0942","sec-0943","sec-095","sec-096","sec-0961","sec-09611","sec-09612","sec-09613","sec-0962","sec-09621","sec-09622","sec-09623","sec-09624","sec-097","sec-chap09"]} \ No newline at end of file diff --git a/.quarto/xref/53469ec4 b/.quarto/xref/53469ec4 new file mode 100644 index 0000000..fc96281 --- /dev/null +++ b/.quarto/xref/53469ec4 @@ -0,0 +1 @@ +{"entries":[],"options":{"tbl-prefix":"tableau","fig-title":"Figure","fig-prefix":"figure","eq-title":"Équation","sec-prefix":"section","tbl-title":"Tableau","eq-prefix":"équation","chapters":true},"headings":[]} \ No newline at end of file diff --git a/.quarto/xref/5c001e14 b/.quarto/xref/5c001e14 new file mode 100644 index 0000000..1816d85 --- /dev/null +++ b/.quarto/xref/5c001e14 @@ -0,0 +1 @@ +{"entries":[{"order":{"section":[8,0,0,0,0,0,0],"number":1},"key":"sec-chap08"},{"order":{"section":[8,1,5,3,1,0,0],"number":13},"caption":"","key":"eq-glm12"},{"order":{"section":[8,2,3,1,0,0,0],"number":23},"caption":"8.2.3.1 Conditions d’application","key":"sec-08231"},{"order":{"section":[8,3,1,3,0,0,0],"number":27},"caption":"Comparaison de la distribution originale et des simulations pour le modèle de quasi-Poisson","key":"fig-comppoissdistr"},{"order":{"section":[8,2,3,2,0,0,0],"number":24},"caption":"8.2.3.2 Exemple appliqué dans R","key":"sec-08232"},{"order":{"section":[8,2,1,3,0,0,0],"number":4},"caption":"Distances de Cook pour le modèle binomial avec toutes les observations","key":"fig-cookdistGLMbinom"},{"order":{"section":[8,3,1,0,0,0,0],"number":29},"caption":"8.3.1 Modèle de Poisson","key":"sec-0831"},{"order":{"section":[8,2,1,0,0,0,0],"number":6},"caption":"Carte d’identité du modèle logistique binomial","key":"tbl-binomidentity"},{"order":{"section":[8,2,4,2,0,0,0],"number":17},"caption":"Coefficients du modèle multinomial A versus B","key":"tbl-coeffsmultinom1"},{"order":{"section":[8,3,3,2,0,0,0],"number":38},"caption":"8.3.3.2 Exemple appliqué dans R","key":"sec-08332"},{"order":{"section":[8,2,4,2,0,0,0],"number":18},"caption":"Distances de Cook pour le modèle logistique multinomial","key":"fig-cookmultinom"},{"order":{"section":[8,1,5,1,3,0,0],"number":11},"caption":"","key":"eq-glm10"},{"order":{"section":[8,3,4,2,0,0,0],"number":38},"caption":"Comparaison de la distribution originale et des simulations pour le modèle de Poisson avec excès de zéros ajusté","key":"fig-compzipdistr"},{"order":{"section":[8,1,5,0,0,0,0],"number":6},"caption":"8.1.5 Vérification l’ajustement","key":"sec-0815"},{"order":{"section":[8,3,4,2,0,0,0],"number":36},"caption":"Diagnostic général des résidus simulés du modèle de Poisson avec excès de zéros ajusté”,","key":"fig-diagzip"},{"order":{"section":[8,3,1,3,0,0,0],"number":26},"caption":"Représentation de la sur-dispersion des données dans le modèle de Poisson","key":"fig-surdisppoiss"},{"order":{"section":[8,1,5,3,2,0,0],"number":5},"caption":"Indicateurs de qualité de prédiction","key":"tbl-confusIndic"},{"order":{"section":[8,3,1,2,0,0,0],"number":19},"caption":"","key":"eq-glm16"},{"order":{"section":[8,4,3,3,0,0,0],"number":34},"caption":"Variables indépendantes utilisées dans le modèle Gamma","key":"tbl-variablegamma"},{"order":{"section":[8,1,6,0,0,0,0],"number":15},"caption":"8.1.6 Comparaison de deux modèles GLM","key":"sec-0816"},{"order":{"section":[8,4,3,3,0,0,0],"number":57},"caption":"Diagnostic général des résidus simulés du modèle Gamma (après suppression d’environ 620 valeurs aberrantes)","key":"fig-gammaresids3"},{"order":{"section":[8,4,1,2,0,0,0],"number":46},"caption":"8.4.1.2 Interprétation des paramètres","key":"sec-08412"},{"order":{"section":[8,4,4,3,0,0,0],"number":62},"caption":"Distances de Cook pour le modèle GLM bêta","key":"fig-cookdistbeta"},{"order":{"section":[8,1,5,1,1,0,0],"number":8},"caption":"8.1.5.1.1 Déviance expliquée","key":"sec-081511"},{"order":{"section":[8,3,1,3,0,0,0],"number":24},"caption":"Distances de Cook pour le modèle de Poisson","key":"fig-poisscookdist"},{"order":{"section":[8,4,3,0,0,0,0],"number":52},"caption":"8.4.3 Modèle GLM avec distribution Gamma","key":"sec-0843"},{"order":{"section":[8,3,1,3,0,0,0],"number":28},"caption":"Comparaison de la distribution originale et des simulations pour le modèle de Poisson","key":"fig-comppoissdistr2"},{"order":{"section":[8,1,1,0,0,0,0],"number":2},"caption":"8.1.1 Formulation d’un GLM","key":"sec-0811"},{"order":{"section":[8,3,4,1,0,0,0],"number":40},"caption":"8.3.4.1 Interprétation des paramètres","key":"sec-08341"},{"order":{"section":[8,4,4,3,0,0,0],"number":64},"caption":"Distances de Cook pour le modèle GLM bêta (suppression de trois observations influentes)","key":"fig-cookdistbeta3"},{"order":{"section":[8,1,0,0,0,0,0],"number":1},"caption":"8.1 Qu’est qu’un modèle GLM?","key":"sec-081"},{"order":{"section":[8,1,5,3,0,0,0],"number":12},"caption":"8.1.5.3 Comparaison des prédictions du modèle avec les valeurs originales","key":"sec-08153"},{"order":{"section":[8,2,1,3,0,0,0],"number":6},"caption":"Distribution des résidus simulés pour le modèle binomial","key":"fig-residsimbinomHistoUnif"},{"order":{"section":[8,1,2,0,0,0,0],"number":3},"caption":"Utilisation de la fonction de lien logistique","key":"fig-linearbinom3"},{"order":{"section":[8,1,1,0,0,0,0],"number":1},"caption":"","key":"eq-regmultiple5B"},{"order":{"section":[8,4,4,1,0,0,0],"number":57},"caption":"8.4.4.1 Conditions d’application","key":"sec-08441"},{"order":{"section":[8,4,3,0,0,0,0],"number":33},"caption":"Carte d’identité du modèle Gamma","key":"tbl-gammadentity"},{"order":{"section":[8,2,1,3,0,0,0],"number":10},"caption":"Résultats du modèle binomial","key":"tbl-coeffbinom"},{"order":{"section":[8,1,4,0,0,0,0],"number":6},"caption":"","key":"eq-glm5"},{"order":{"section":[8,1,2,0,0,0,0],"number":1},"caption":"Exemple de données issues d’une distribution de Bernoulli","key":"fig-linearbinom"},{"order":{"section":[8,3,1,3,0,0,0],"number":25},"caption":"Distances de Cook pour le modèle de Poisson après avoir retiré les valeurs aberrantes","key":"fig-poisscookdist2"},{"order":{"section":[8,2,1,3,0,0,0],"number":7},"caption":"Diagnostic des résidus simulés par le package DHARMa","key":"fig-residsimbinom"},{"order":{"section":[8,4,4,3,0,0,0],"number":63},"caption":"Distances de Cook pour le modèle GLM bêta (suppression de deux observations influentes)","key":"fig-cookdistbeta2"},{"order":{"section":[8,1,5,2,0,0,0],"number":11},"caption":"8.1.5.2 Comparaison des distributions originales et prédites","key":"sec-08152"},{"order":{"section":[8,4,2,3,0,0,0],"number":48},"caption":"Diagnostic général des résidus simulés pour le GLM avec distribution de Student","key":"fig-studentresid"},{"order":{"section":[8,4,3,3,0,0,0],"number":51},"caption":"Distribution des temps de trajet diurne à Montréal","key":"fig-gammadatadistrib"},{"order":{"section":[8,4,3,3,0,0,0],"number":61},"caption":"Effet de la distance à vol d’oiseau sur les temps de trajet à Montréal","key":"fig-distancegamma"},{"order":{"section":[8,1,5,3,1,0,0],"number":12},"caption":"","key":"eq-glm11"},{"order":{"section":[8,3,3,0,0,0,0],"number":36},"caption":"8.3.3 Modèle de Poisson avec excès fixe de zéros","key":"sec-0833"},{"order":{"section":[8,4,2,3,0,0,0],"number":32},"caption":"Résultats du modèle Student","key":"tbl-glmstudentres"},{"order":{"section":[8,4,1,1,0,0,0],"number":45},"caption":"8.4.1.1 Conditions d’application","key":"sec-08411"},{"order":{"section":[8,4,4,0,0,0,0],"number":26},"caption":"","key":"eq-glm20"},{"order":{"section":[8,4,2,3,0,0,0],"number":49},"caption":"Distribution des résidus simulés du modèle GLM avec distribution de Student","key":"fig-studentresid2"},{"order":{"section":[8,5,0,0,0,0,0],"number":71},"caption":"Résumé graphique des principaux GLM abordés","key":"fig-GLMfinal"},{"order":{"section":[8,4,4,3,0,0,0],"number":37},"caption":"Variables indépendantes utilisées dans le modèle bêta","key":"tbl-variablebeta"},{"order":{"section":[8,1,5,3,2,0,0],"number":3},"caption":"Exemple de matrice de confusion multinomiale","key":"tbl-confusmat2"},{"order":{"section":[8,2,1,1,0,0,0],"number":18},"caption":"8.2.1.1 Interprétation des paramètres","key":"sec-08211"},{"order":{"section":[8,3,4,2,0,0,0],"number":28},"caption":"Résultats de la partie logistique du modèle de Poisson avec excès de zéros ajusté","key":"tbl-zapoisstab2"},{"order":{"section":[8,4,4,3,0,0,0],"number":67},"caption":"Relation entre la variable Arrondissement et les résidus simulés du modèle bêta","key":"fig-residsimbeta3"},{"order":{"section":[8,1,4,0,0,0,0],"number":7},"caption":"","key":"eq-glm6"},{"order":{"section":[8,2,3,2,0,0,0],"number":13},"caption":"Distances de Cook pour le modèle logistique des cotes proportionnelles","key":"fig-CookdCotePropor"},{"order":{"section":[8,4,4,3,0,0,0],"number":70},"caption":"Effets marginaux des variables pourcentage de personnes à faible revenu et densité de végétation","key":"fig-betaFR"},{"order":{"section":[8,1,2,0,0,0,0],"number":4},"caption":"","key":"eq-glm3"},{"order":{"section":[8,2,3,2,0,0,0],"number":12},"caption":"Distribution des prix des logements Airbnb","key":"fig-histopriceairbnb"},{"order":{"section":[8,3,4,2,0,0,0],"number":37},"caption":"Diagnostic général des résidus simulés du modèle de Poisson avec excès de zéros ajusté (sans valeurs aberrantes)","key":"fig-diagzip2"},{"order":{"section":[8,4,3,3,0,0,0],"number":54},"caption":"Comparaison de la distribution originale et de simulations issues du modèle Gamma","key":"fig-simdistribgamma"},{"order":{"section":[8,3,5,0,0,0,0],"number":42},"caption":"8.3.5 Conclusion sur les modèles destinés à des variables de comptage","key":"sec-0835"},{"order":{"section":[8,4,2,3,0,0,0],"number":47},"caption":"Distances de Cook pour un modèle GLM avec une distribution de Student après suppression des valeurs fortement influentes","key":"fig-stucookdist2"},{"order":{"section":[8,1,5,1,2,0,0],"number":1},"caption":"Principaux pseudos-R^2","key":"tbl-pseudor2"},{"order":{"section":[8,4,2,0,0,0,0],"number":31},"caption":"Carte d’identité du modèle de Student","key":"tbl-studentdentity"},{"order":{"section":[8,6,0,0,0,0,0],"number":61},"caption":"8.6 Quiz de révision du chapitre","key":"sec-086"},{"order":{"section":[8,3,3,0,0,0,0],"number":25},"caption":"Carte d’identité du modèle de Poisson avec excès fixe de zéros","key":"tbl-poisszidentity"},{"order":{"section":[8,5,0,0,0,0,0],"number":60},"caption":"8.5 Conclusion sur les modèles linéaires généralisés","key":"sec-085"},{"order":{"section":[8,1,5,3,2,0,0],"number":2},"caption":"Exemple de matrice de confusion","key":"tbl-confusmat1"},{"order":{"section":[8,2,3,0,0,0,0],"number":22},"caption":"8.2.3 Modèle logistique des cotes proportionnelles","key":"sec-0823"},{"order":{"section":[8,2,4,2,0,0,0],"number":19},"caption":"Diagnostic général des résidus simulés pour le modèle multinomial","key":"fig-residusmultinom"},{"order":{"section":[8,2,1,3,0,0,0],"number":20},"caption":"8.2.1.3 Exemple appliqué dans R","key":"sec-08213"},{"order":{"section":[8,4,4,3,0,0,0],"number":69},"caption":"Rapports de cote pour les arrondissements dans le modèle bêta","key":"fig-betaArrond"},{"order":{"section":[8,4,3,0,0,0,0],"number":23},"caption":"","key":"eq-glm19"},{"order":{"section":[8,4,2,3,0,0,0],"number":51},"caption":"8.4.2.3 Exemple appliqué dans R","key":"sec-08423"},{"order":{"section":[8,4,4,3,0,0,0],"number":65},"caption":"Diagnostic général des résidus simulés du modèle bêta","key":"fig-residsimbeta"},{"order":{"section":[8,1,5,3,2,0,0],"number":4},"caption":"Inteprétation des valeurs du coefficient de Kappa","key":"tbl-Kappvals"},{"order":{"section":[8,4,4,2,0,0,0],"number":58},"caption":"8.4.4.2 Interprétation des coefficients","key":"sec-08442"},{"order":{"section":[8,4,4,3,0,0,0],"number":59},"caption":"8.4.4.3 Exemple appliqué dans R","key":"sec-08443"},{"order":{"section":[8,4,1,3,0,0,0],"number":42},"caption":"Diagnostic général des résidus simulés pour le modèle gaussien","key":"fig-gaussresid"},{"order":{"section":[8,4,3,3,0,0,0],"number":60},"caption":"Effet de l’heure de départ sur les temps de trajet à Montréal”","key":"fig-heuresgamma"},{"order":{"section":[8,4,4,0,0,0,0],"number":25},"caption":"","key":"eq-correctbeta"},{"order":{"section":[8,3,4,2,0,0,0],"number":41},"caption":"8.3.4.2 Exemple appliqué","key":"sec-08342"},{"order":{"section":[8,4,4,3,0,0,0],"number":66},"caption":"Relation entre chaque variable indépendante et les résidus simulés du modèle bêta","key":"fig-residsimbeta2"},{"order":{"section":[8,1,5,3,2,0,0],"number":15},"caption":"","key":"eq-kappEq"},{"order":{"section":[8,4,3,3,0,0,0],"number":35},"caption":"Résultats pour le modèle GLM Gamma","key":"tbl-coeffsgamma"},{"order":{"section":[8,2,1,3,0,0,0],"number":7},"caption":"Variables indépendantes utilisées pour prédire le mode de transport le plus utilisé","key":"tbl-binomdata"},{"order":{"section":[8,4,4,0,0,0,0],"number":27},"caption":"","key":"eq-glm21"},{"order":{"section":[8,4,3,3,0,0,0],"number":59},"caption":"Effet de l’arrondissement de départ sur les temps de trajet à Montréal”,","key":"fig-arrondgamma"},{"order":{"section":[8,2,1,3,0,0,0],"number":11},"caption":"Effet de l’âge sur la probabilité d’utiliser le vélo comme moyen de déplacement pour son trajet le plus fréquent","key":"fig-agebinom"},{"order":{"section":[8,3,4,2,0,0,0],"number":27},"caption":"Résultats de la partie Poisson du modèle de Poisson avec excès de zéros ajusté","key":"tbl-zapoisstab1"},{"order":{"section":[8,4,3,3,0,0,0],"number":58},"caption":"Comparaison de la variance attendue par le modèle et la variance observée dans les données pour le modèle Gamma","key":"fig-dispgamma"},{"order":{"section":[8,4,3,3,0,0,0],"number":56},"caption":"Diagnostic général des résidus simulés du modèle Gamma","key":"fig-gammaresids2"},{"order":{"section":[8,4,3,3,0,0,0],"number":55},"caption":"Distribution des résidus simulés du modèle Gamma","key":"fig-gammaresids"},{"order":{"section":[8,1,5,3,2,0,0],"number":16},"caption":"","key":"eq-kappEq2"},{"order":{"section":[8,2,4,1,0,0,0],"number":18},"caption":"","key":"eq-glm15"},{"order":{"section":[8,3,1,3,0,0,0],"number":30},"caption":"Comparaison des résidus simulés et de chaque variable indépendante","key":"fig-simrespoiss2"},{"order":{"section":[8,3,2,2,0,0,0],"number":34},"caption":"Comparaison de la distribution originale et des simulations pour le modèle binomial négatif","key":"fig-compnbdistr2"},{"order":{"section":[8,4,3,3,0,0,0],"number":52},"caption":"Distances de Cook pour le modèle Gamma","key":"fig-cookdistgamma"},{"order":{"section":[8,2,2,0,0,0,0],"number":11},"caption":"Carte d’identité du modèle probit binomial","key":"tbl-probitdentity"},{"order":{"section":[8,4,3,3,0,0,0],"number":55},"caption":"8.4.3.3 Exemple appliqué dans R","key":"sec-08433"},{"order":{"section":[8,2,4,2,0,0,0],"number":20},"caption":"Diagnostic des variables indépendantes et des résidus simulés pour le modèle multinomial","key":"fig-residusmultinom2"},{"order":{"section":[8,4,3,2,0,0,0],"number":54},"caption":"8.4.3.2 Conditions d’application","key":"sec-08432"},{"order":{"section":[8,3,4,0,0,0,0],"number":26},"caption":"Carte d’identité du modèle de Poisson avec excès ajusté de zéros","key":"tbl-poisszadentity"},{"order":{"section":[8,1,4,0,0,0,0],"number":9},"caption":"","key":"eq-glm8"},{"order":{"section":[8,2,1,3,0,0,0],"number":10},"caption":"Rapports de cote pour les différents lieux de résidence","key":"fig-villebinom"},{"order":{"section":[8,3,2,2,0,0,0],"number":33},"caption":"Diagnostic général des résidus simulés pour le modèle binomial négatif","key":"fig-diagresnb"},{"order":{"section":[8,4,4,3,0,0,0],"number":68},"caption":"Comparaison entre la distribution originale et les simulations issues du modèle","key":"fig-residsimbeta4"},{"order":{"section":[8,4,3,0,0,0,0],"number":22},"caption":"","key":"eq-glm18"},{"order":{"section":[8,2,2,0,0,0,0],"number":21},"caption":"8.2.2 Modèle probit binomial","key":"sec-0822"},{"order":{"section":[8,4,2,3,0,0,0],"number":50},"caption":"Simulations issues des modèles gaussien et de Student, comparées aux données originales","key":"fig-studentresid3"},{"order":{"section":[8,4,2,3,0,0,0],"number":46},"caption":"Distances de Cook pour un modèle GLM avec une distribution de Student","key":"fig-stucookdist"},{"order":{"section":[8,4,4,0,0,0,0],"number":24},"caption":"","key":"eq-logitbeta"},{"order":{"section":[8,3,2,2,0,0,0],"number":35},"caption":"Représentation de la sur-dispersion des données dans le modèle de Poisson","key":"fig-surdispnb"},{"order":{"section":[8,4,2,2,0,0,0],"number":50},"caption":"8.4.2.2 Interprétation des paramètres","key":"sec-08422"},{"order":{"section":[8,4,2,1,0,0,0],"number":49},"caption":"8.4.2.1 Conditions d’application","key":"sec-08421"},{"order":{"section":[8,2,3,0,0,0,0],"number":12},"caption":"Carte d’identité du modèle logistique des cotes proportionnelles","key":"tbl-cumuldentity"},{"order":{"section":[8,4,2,0,0,0,0],"number":45},"caption":"Effet du paramètre nu sur une distribution de Student","key":"fig-studentdistrib"},{"order":{"section":[8,4,4,3,0,0,0],"number":38},"caption":"Résultats pour le modèle GLM bêta","key":"tbl-coeffsbeta"},{"order":{"section":[8,2,4,1,0,0,0],"number":26},"caption":"8.2.4.1 Conditions d’application","key":"sec-08241"},{"order":{"section":[8,2,4,0,0,0,0],"number":15},"caption":"Carte d’identité du modèle logistique multinomial","key":"tbl-multinomdentity"},{"order":{"section":[8,3,1,3,0,0,0],"number":22},"caption":"Résultats du modèle de quasi-Poisson","key":"tbl-coeffpoiss"},{"order":{"section":[8,2,3,2,0,0,0],"number":16},"caption":"Diagnostic des variables indépendantes et des résidus simulés du modèle des cotes proportionnelles (après correction)","key":"fig-diagressimcumul3"},{"order":{"section":[8,4,1,3,0,0,0],"number":44},"caption":"Comparaison de la distribution originale de la variable et des simulations issues du modèle","key":"fig-gausssim2"},{"order":{"section":[8,3,1,0,0,0,0],"number":20},"caption":"Carte d’identité du modèle de Poisson","key":"tbl-poissondentity"},{"order":{"section":[8,4,1,3,0,0,0],"number":43},"caption":"Comparaison de la distribution originale de la variable et des simulations issues du modèle","key":"fig-gausssim"},{"order":{"section":[8,4,4,0,0,0,0],"number":36},"caption":"Carte d’identité du modèle bêta","key":"tbl-betaentity"},{"order":{"section":[8,3,1,3,0,0,0],"number":29},"caption":"Analyse globale des résidus simulés pour le modèle de quasi-Poisson","key":"fig-simrespoiss"},{"order":{"section":[8,1,3,0,0,0,0],"number":4},"caption":"8.1.3 Conditions d’application","key":"sec-0813"},{"order":{"section":[8,3,2,0,0,0,0],"number":33},"caption":"8.3.2 Modèle binomial négatif","key":"sec-0832"},{"order":{"section":[8,2,4,2,0,0,0],"number":16},"caption":"Variables indépendantes utilisées dans le modèle logistique multinomial","key":"tbl-variablemultinom"},{"order":{"section":[8,4,1,3,0,0,0],"number":41},"caption":"Distances de Cook pour le modèle gaussien après suppression des observations influentes","key":"fig-gausscook2"},{"order":{"section":[8,4,1,3,0,0,0],"number":40},"caption":"Distances de Cook pour le modèle gaussien","key":"fig-gausscook"},{"order":{"section":[8,4,1,3,0,0,0],"number":47},"caption":"8.4.1.3 Exemple appliqué dans R","key":"sec-08413"},{"order":{"section":[8,4,1,0,0,0,0],"number":29},"caption":"Carte d’identité du modèle gaussien","key":"tbl-gaussiandentity"},{"order":{"section":[8,2,4,2,0,0,0],"number":19},"caption":"Coefficients du modèle multinomial A versus D","key":"tbl-coeffsmultinom3"},{"order":{"section":[8,1,2,0,0,0,0],"number":3},"caption":"8.1.2 Autres distributions et rôle de la fonction de lien","key":"sec-0812"},{"order":{"section":[8,2,3,2,0,0,0],"number":13},"caption":"Variables indépendantes utilisées pour prédire la catégorie de prix de logements Airbnb","key":"tbl-variablecumul"},{"order":{"section":[8,2,0,0,0,0,0],"number":16},"caption":"8.2 Modèles GLM pour des variables qualitatives","key":"sec-082"},{"order":{"section":[8,4,0,0,0,0,0],"number":43},"caption":"8.4 Modèles GLM pour des variables continues","key":"sec-084"},{"order":{"section":[8,2,3,2,0,0,0],"number":15},"caption":"Diagnostic des variables indépendantes et des résidus simulés du modèle des cotes proportionnelles","key":"fig-diagressimcumul2"},{"order":{"section":[8,2,4,2,0,0,0],"number":21},"caption":"Diagnostic général des résidus simulés pour le modèle multinomial (version 3)","key":"fig-residusmultinom3"},{"order":{"section":[8,3,5,0,0,0,0],"number":39},"caption":"Processus de sélection d’un modèle pour une variable de comptage","key":"fig-poisswork"},{"order":{"section":[8,2,3,2,0,0,0],"number":14},"caption":"Diagnostic général des résidus simulés du modèle des cotes proportionnelles","key":"fig-diagressimcumul"},{"order":{"section":[8,3,2,0,0,0,0],"number":23},"caption":"Carte d’identité du modèle binomial négatif","key":"tbl-nbdentity"},{"order":{"section":[8,1,6,0,0,0,0],"number":17},"caption":"","key":"eq-glm14"},{"order":{"section":[8,1,2,0,0,0,0],"number":5},"caption":"","key":"eq-glm4"},{"order":{"section":[8,2,3,2,0,0,0],"number":14},"caption":"Coefficients du modèle logistique des cotes proportionnelles","key":"tbl-FinalOrdinale"},{"order":{"section":[8,1,4,0,0,0,0],"number":5},"caption":"8.1.4 Résidus et déviance","key":"sec-0814"},{"order":{"section":[8,2,1,3,0,0,0],"number":8},"caption":"Point d’équilibre entre sensibilité et spécificité","key":"fig-equlibresensispeci"},{"order":{"section":[8,3,2,2,0,0,0],"number":24},"caption":"Résultats du modèle binomial négatif","key":"tbl-coeffsnb"},{"order":{"section":[8,4,3,3,0,0,0],"number":53},"caption":"Distances de Cook pour le modèle Gamma (sans les observations fortement influentes)","key":"fig-cookdistgamma2"},{"order":{"section":[8,2,1,2,0,0,0],"number":19},"caption":"8.2.1.2 Conditions d’application","key":"sec-08212"},{"order":{"section":[8,4,4,0,0,0,0],"number":56},"caption":"8.4.4 Modèle GLM avec une distribution bêta","key":"sec-0844"},{"order":{"section":[8,3,1,3,0,0,0],"number":23},"caption":"Distribution originale du nombre d’accidents par intersection","key":"fig-distripoissmod"},{"order":{"section":[8,2,1,3,0,0,0],"number":5},"caption":"Distances de Cook pour le modèle binomial sans les valeurs aberrantes","key":"fig-cookdistGLMbinom2"},{"order":{"section":[8,2,1,0,0,0,0],"number":17},"caption":"8.2.1 Modèle logistique binomial","key":"sec-0821"},{"order":{"section":[8,4,3,1,0,0,0],"number":53},"caption":"8.4.3.1 Interprétation des paramètres","key":"sec-08431"},{"order":{"section":[8,2,4,2,0,0,0],"number":27},"caption":"8.2.4.2 Exemple appliqué dans R","key":"sec-08242"},{"order":{"section":[8,1,5,1,0,0,0],"number":7},"caption":"8.1.5.1 Mesures d’ajustement","key":"sec-08151"},{"order":{"section":[8,1,1,0,0,0,0],"number":2},"caption":"","key":"eq-glm1"},{"order":{"section":[8,1,1,0,0,0,0],"number":3},"caption":"","key":"eq-glm2"},{"order":{"section":[8,1,5,3,2,0,0],"number":14},"caption":"","key":"eq-glm13"},{"order":{"section":[8,3,2,2,0,0,0],"number":31},"caption":"Distances de Cook pour le modèle binomial négatif","key":"fig-cookdistnb"},{"order":{"section":[8,1,4,0,0,0,0],"number":8},"caption":"","key":"eq-glm7"},{"order":{"section":[8,2,4,2,0,0,0],"number":22},"caption":"Diagnostic général des résidus simulés pour le modèle multinomial (version 4)","key":"fig-residusmultinom4"},{"order":{"section":[8,2,1,3,0,0,0],"number":8},"caption":"Matrice de confusion pour le modèle binomial","key":"tbl-confusmatbinom"},{"order":{"section":[8,3,1,3,0,0,0],"number":21},"caption":"Variables indépendantes utilisées dans le modèle de Poisson","key":"tbl-variablepoiss"},{"order":{"section":[8,1,5,3,1,0,0],"number":13},"caption":"8.1.5.3.1 Pour une variable quantitative","key":"sec-081531"},{"order":{"section":[8,3,2,2,0,0,0],"number":32},"caption":"Distances de Cook pour le modèle binomial négatif (après avoir retiré quatre observations fortement influentes","key":"fig-cookdistnb2"},{"order":{"section":[8,2,3,2,0,0,0],"number":17},"caption":"Prédiction de la probabilité d’appartenance aux trois catégories de prix en fonction de la densité de végétation","key":"fig-predpricecatveg"},{"order":{"section":[8,2,4,0,0,0,0],"number":25},"caption":"8.2.4 Modèle logistique multinomial","key":"sec-0824"},{"order":{"section":[8,4,1,3,0,0,0],"number":30},"caption":"Résultats du modèle gaussien","key":"tbl-tableaugauss"},{"order":{"section":[8,3,1,2,0,0,0],"number":31},"caption":"8.3.1.2 Conditions d’application","key":"sec-08312"},{"order":{"section":[8,3,5,0,0,0,0],"number":21},"caption":"","key":"eq-glmHurdle"},{"order":{"section":[8,1,5,1,1,0,0],"number":10},"caption":"","key":"eq-glm9"},{"order":{"section":[8,4,1,0,0,0,0],"number":44},"caption":"8.4.1 Modèle GLM gaussien","key":"sec-0841"},{"order":{"section":[8,2,4,2,0,0,0],"number":18},"caption":"Coefficients du modèle multinomial A versus C","key":"tbl-coeffsmultinom2"},{"order":{"section":[8,3,1,1,0,0,0],"number":30},"caption":"8.3.1.1 Interprétation des paramètres","key":"sec-08311"},{"order":{"section":[8,3,0,0,0,0,0],"number":28},"caption":"8.3 Modèles GLM pour des variables de comptage","key":"sec-083"},{"order":{"section":[8,1,5,1,3,0,0],"number":10},"caption":"8.1.5.1.3 Critère d’information d’Akaike (AIC)","key":"sec-081513"},{"order":{"section":[8,3,1,3,0,0,0],"number":32},"caption":"8.3.1.3 Exemple appliqué dans R","key":"sec-08313"},{"order":{"section":[8,2,1,3,0,0,0],"number":9},"caption":"Rapports de cote pour les différents pays de l’UE","key":"fig-paysbinom"},{"order":{"section":[8,1,5,3,2,0,0],"number":14},"caption":"8.1.5.3.2 Pour une variable qualitative","key":"sec-081532"},{"order":{"section":[8,4,2,0,0,0,0],"number":48},"caption":"8.4.2 Modèle GLM avec une distribution de Student","key":"sec-0842"},{"order":{"section":[8,2,1,3,0,0,0],"number":9},"caption":"Matrice de confusion pour le modèle binomial","key":"tbl-confusmatbinom2"},{"order":{"section":[8,1,2,0,0,0,0],"number":2},"caption":"Ajustement d’une droite de régression aux données issues d’une distribution de Bernoulli","key":"fig-linearbinom2"},{"order":{"section":[8,3,2,1,0,0,0],"number":20},"caption":"","key":"eq-glm17"},{"order":{"section":[8,3,2,2,0,0,0],"number":35},"caption":"8.3.2.2 Exemple appliqué dans R","key":"sec-08322"},{"order":{"section":[8,3,3,1,0,0,0],"number":37},"caption":"8.3.3.1 Interprétation des paramètres","key":"sec-08331"},{"order":{"section":[8,3,2,1,0,0,0],"number":34},"caption":"8.3.2.1 Conditions d’application","key":"sec-08321"},{"order":{"section":[8,1,5,1,2,0,0],"number":9},"caption":"8.1.5.1.2 Pseudo-R2","key":"sec-081512"},{"order":{"section":[8,3,4,0,0,0,0],"number":39},"caption":"8.3.4 Modèle de Poisson avec excès ajusté de zéros","key":"sec-0834"}],"headings":["sec-081","sec-0811","sec-0812","sec-0813","sec-0814","sec-0815","sec-08151","sec-081511","sec-081512","sec-081513","sec-08152","sec-08153","sec-081531","sec-081532","sec-0816","sec-082","sec-0821","sec-08211","sec-08212","sec-08213","sec-0822","sec-0823","sec-08231","sec-08232","sec-0824","sec-08241","sec-08242","conclusion-sur-les-modèles-pour-des-variables-qualitatives","sec-083","sec-0831","sec-08311","sec-08312","sec-08313","sec-0832","sec-08321","sec-08322","sec-0833","sec-08331","sec-08332","sec-0834","sec-08341","sec-08342","sec-0835","sec-084","sec-0841","sec-08411","sec-08412","sec-08413","sec-0842","sec-08421","sec-08422","sec-08423","sec-0843","sec-08431","sec-08432","sec-08433","sec-0844","sec-08441","sec-08442","sec-08443","sec-085","sec-086","sec-chap08"],"options":{"fig-title":"Figure","sec-prefix":"section","fig-prefix":"figure","eq-title":"Équation","eq-prefix":"équation","tbl-title":"Tableau","tbl-prefix":"tableau","chapter-id":"sec-chap08","chapters":true}} \ No newline at end of file diff --git a/.quarto/xref/6ba11324 b/.quarto/xref/6ba11324 new file mode 100644 index 0000000..a0ad400 --- /dev/null +++ b/.quarto/xref/6ba11324 @@ -0,0 +1 @@ +{"headings":["sec-031","sec-0311","sec-0312","sec-0313","utilisation-des-thèmes","sec-0314","sec-03141","sec-03142","sec-0315","sec-032","sec-0321","sec-03211","sec-03212","sec-03213","sec-03214","sec-0322","sec-0323","sec-03231","sec-03232","sec-03233","sec-0324","sec-03241","sec-0325","sec-0326","sec-0327","sec-0328","sec-033","sec-0331","sec-0332","sec-0333","sec-0334","sec-034","sec-035","sec-036","sec-chap03"],"entries":[{"key":"sec-chap03","order":{"number":1,"section":[3,0,0,0,0,0,0]}},{"key":"sec-03214","caption":"3.2.1.4 Histogramme avec coloration des valeurs extrêmes","order":{"number":14,"section":[3,2,1,4,0,0,0]}},{"key":"fig-fig332","caption":"Nuage de points avec droite de régression","order":{"number":34,"section":[3,2,3,3,0,0,0]}},{"key":"fig-fig329","caption":"Nuage de points simple","order":{"number":31,"section":[3,2,3,2,0,0,0]}},{"key":"fig-fig312","caption":"Thème tufte","order":{"number":13,"section":[3,1,4,0,0,0,0]}},{"key":"tbl-geometries","caption":"Principales géométries proposées par ggplot2","order":{"number":1,"section":[3,1,2,0,0,0,0]}},{"key":"sec-03212","caption":"3.2.1.2 Histogramme de densité","order":{"number":12,"section":[3,2,1,2,0,0,0]}},{"key":"sec-034","caption":"3.4 Cartes","order":{"number":31,"section":[3,4,0,0,0,0,0]}},{"key":"fig-fig339","caption":"Boîtes à moustaches améliorées","order":{"number":41,"section":[3,2,5,0,0,0,0]}},{"key":"sec-0321","caption":"3.2.1 Histogramme","order":{"number":10,"section":[3,2,1,0,0,0,0]}},{"key":"fig-fig342","caption":"Graphiques en violon et boîtes à moustaches","order":{"number":44,"section":[3,2,6,0,0,0,0]}},{"key":"fig-fig335","caption":"Graphique en ligne","order":{"number":37,"section":[3,2,4,0,0,0,0]}},{"key":"sec-0311","caption":"3.1.1 Grammaire","order":{"number":2,"section":[3,1,1,0,0,0,0]}},{"key":"fig-fig320","caption":"Histogrammes à facettes","order":{"number":23,"section":[3,2,1,1,0,0,0]}},{"key":"fig-fig354","caption":"Carte thématique avec tmap","order":{"number":56,"section":[3,4,0,0,0,0,0]}},{"key":"sec-033","caption":"3.3 Graphiques spéciaux","order":{"number":26,"section":[3,3,0,0,0,0,0]}},{"key":"fig-fig347","caption":"Graphique en anneau","order":{"number":49,"section":[3,2,8,0,0,0,0]}},{"key":"fig-fig313","caption":"Thème economist","order":{"number":14,"section":[3,1,4,0,0,0,0]}},{"key":"fig-colorBrewer","caption":"Palette de couleurs de ColorBrewer","order":{"number":20,"section":[3,1,6,0,0,0,0]}},{"key":"sec-0325","caption":"3.2.5 Boîte à moustaches","order":{"number":22,"section":[3,2,5,0,0,0,0]}},{"key":"sec-0324","caption":"3.2.4 Graphique en ligne","order":{"number":20,"section":[3,2,4,0,0,0,0]}},{"key":"sec-0314","caption":"3.1.5 Composition d’une figure avec plusieurs graphiques","order":{"number":5,"section":[3,1,5,0,0,0,0]}},{"key":"fig-fig310","caption":"Thème noir et blanc","order":{"number":11,"section":[3,1,4,0,0,0,0]}},{"key":"sec-0326","caption":"3.2.6 Graphique en violon","order":{"number":23,"section":[3,2,6,0,0,0,0]}},{"key":"fig-fig311","caption":"Thème minimal","order":{"number":12,"section":[3,1,4,0,0,0,0]}},{"key":"sec-036","caption":"3.6 Conclusion sur les graphiques","order":{"number":33,"section":[3,6,0,0,0,0,0]}},{"key":"sec-031","caption":"3.1 Philosophie du ggplot2","order":{"number":1,"section":[3,1,0,0,0,0,0]}},{"key":"fig-fig331","caption":"Densité lissée en deux dimensions","order":{"number":33,"section":[3,2,3,2,0,0,0]}},{"key":"fig-fig37","caption":"Gestion de l’ordre des annotations","order":{"number":8,"section":[3,1,3,0,0,0,0]}},{"key":"sec-0322","caption":"3.2.2 Graphique de densité","order":{"number":15,"section":[3,2,2,0,0,0,0]}},{"key":"fig-fig337","caption":"Graphique en ligne avec marge d’erreur","order":{"number":39,"section":[3,2,4,1,0,0,0]}},{"key":"fig-fig34","caption":"Ajout de titres","order":{"number":5,"section":[3,1,1,0,0,0,0]}},{"key":"sec-03233","caption":"3.2.3.3 Nuage de points et droite de régression","order":{"number":19,"section":[3,2,3,3,0,0,0]}},{"key":"fig-fig38","caption":"Thème classique","order":{"number":9,"section":[3,1,4,0,0,0,0]}},{"key":"sec-0327","caption":"3.2.7 Graphique en barres","order":{"number":24,"section":[3,2,7,0,0,0,0]}},{"key":"fig-fig349","caption":"Diagramme d’accord","order":{"number":51,"section":[3,3,2,0,0,0,0]}},{"key":"sec-035","caption":"3.5 Exportation des graphiques","order":{"number":32,"section":[3,5,0,0,0,0,0]}},{"key":"fig-fig346","caption":"Graphique en tarte","order":{"number":48,"section":[3,2,8,0,0,0,0]}},{"key":"fig-fig319","caption":"Empiler les données d’un DataFrame","order":{"number":22,"section":[3,2,1,1,0,0,0]}},{"key":"fig-fig318","caption":"Histogrammes","order":{"number":21,"section":[3,2,1,1,0,0,0]}},{"key":"sec-0334","caption":"3.3.4 Carte proportionnelle","order":{"number":30,"section":[3,3,4,0,0,0,0]}},{"key":"sec-0313","caption":"3.1.3 Habillage","order":{"number":4,"section":[3,1,3,0,0,0,0]}},{"key":"fig-fig353","caption":"Carte thématique avec ggplot2","order":{"number":55,"section":[3,4,0,0,0,0,0]}},{"key":"fig-fig352","caption":"Treemap","order":{"number":54,"section":[3,3,4,0,0,0,0]}},{"key":"fig-fig355","caption":"Combiner des cartes avec tmap","order":{"number":57,"section":[3,4,0,0,0,0,0]}},{"key":"fig-fig39","caption":"Thème gris","order":{"number":10,"section":[3,1,4,0,0,0,0]}},{"key":"fig-fig325","caption":"Graphiques de densité superposés","order":{"number":28,"section":[3,2,2,0,0,0,0]}},{"key":"fig-fig350","caption":"Nuage de mots pour le SAD de Montréal","order":{"number":52,"section":[3,3,3,0,0,0,0]}},{"key":"fig-fig323","caption":"Histogramme coloré","order":{"number":26,"section":[3,2,1,4,0,0,0]}},{"key":"fig-fig344","caption":"Graphiques en barre simples","order":{"number":46,"section":[3,2,7,0,0,0,0]}},{"key":"sec-0332","caption":"3.3.2 Diagramme d’accord","order":{"number":28,"section":[3,3,2,0,0,0,0]}},{"key":"sec-0333","caption":"3.3.3 Nuage de mots","order":{"number":29,"section":[3,3,3,0,0,0,0]}},{"key":"fig-fig35","caption":"Ajout d’annotations textuelles","order":{"number":6,"section":[3,1,3,0,0,0,0]}},{"key":"fig-fig345","caption":"Graphique en barre empilée","order":{"number":47,"section":[3,2,7,0,0,0,0]}},{"key":"fig-fig315","caption":"Graphique à facettes","order":{"number":16,"section":[3,1,5,1,0,0,0]}},{"key":"fig-fig333","caption":"Nuage de points avec droite de régression quadratique","order":{"number":35,"section":[3,2,3,3,0,0,0]}},{"key":"fig-fig340","caption":"Boîtes à moustaches avec observations","order":{"number":42,"section":[3,2,5,0,0,0,0]}},{"key":"sec-0328","caption":"3.2.8 Graphique circulaire","order":{"number":25,"section":[3,2,8,0,0,0,0]}},{"key":"fig-fig314","caption":"Thème solarized","order":{"number":15,"section":[3,1,4,0,0,0,0]}},{"key":"fig-fig343","caption":"Grands secteurs de Québec","order":{"number":45,"section":[3,2,7,0,0,0,0]}},{"key":"fig-fig321","caption":"Histogrammes de densité","order":{"number":24,"section":[3,2,1,2,0,0,0]}},{"key":"fig-colors","caption":"Couleurs de base","order":{"number":19,"section":[3,1,6,0,0,0,0]}},{"key":"sec-03211","caption":"3.2.1.1 Histogramme simple","order":{"number":11,"section":[3,2,1,1,0,0,0]}},{"key":"fig-fig338","caption":"Boîtes à moustaches","order":{"number":40,"section":[3,2,5,0,0,0,0]}},{"key":"fig-fig30","caption":"Trois composantes d’un graphique, adapté de @wickham2010layered","order":{"number":1,"section":[3,1,1,0,0,0,0]}},{"key":"fig-fig341","caption":"Graphiques en violon","order":{"number":43,"section":[3,2,6,0,0,0,0]}},{"key":"sec-03142","caption":"3.1.5.2 Arrangement des graphiques","order":{"number":7,"section":[3,1,5,2,0,0,0]}},{"key":"sec-032","caption":"3.2 Principaux graphiques","order":{"number":9,"section":[3,2,0,0,0,0,0]}},{"key":"fig-fig334","caption":"Nuage de points avec droite de régression non linéaire","order":{"number":36,"section":[3,2,3,3,0,0,0]}},{"key":"sec-0315","caption":"3.1.6 Couleur","order":{"number":8,"section":[3,1,6,0,0,0,0]}},{"key":"fig-fig31","caption":"Base d’un graphique","order":{"number":2,"section":[3,1,1,0,0,0,0]}},{"key":"fig-fig317","caption":"Figure avec plusieurs graphiques avec ggarrange","order":{"number":18,"section":[3,1,5,2,0,0,0]}},{"key":"fig-fig33","caption":"Autre spécification des arguments mapping et data","order":{"number":4,"section":[3,1,1,0,0,0,0]}},{"key":"sec-0312","caption":"3.1.2 Types de géométries","order":{"number":3,"section":[3,1,2,0,0,0,0]}},{"key":"fig-fig324","caption":"Graphiques de densité à facette","order":{"number":27,"section":[3,2,2,0,0,0,0]}},{"key":"sec-03141","caption":"3.1.5.1 ggplot2 et ses facettes","order":{"number":6,"section":[3,1,5,1,0,0,0]}},{"key":"fig-fig316","caption":"Graphique à facettes en une ligne","order":{"number":17,"section":[3,1,5,1,0,0,0]}},{"key":"fig-fig326","caption":"Nuage de points simple","order":{"number":29,"section":[3,2,3,1,0,0,0]}},{"key":"fig-fig351","caption":"Nuage de mots pour le SAD de Québec","order":{"number":53,"section":[3,3,3,0,0,0,0]}},{"key":"sec-0323","caption":"3.2.3 Nuage de points","order":{"number":16,"section":[3,2,3,0,0,0,0]}},{"key":"sec-03213","caption":"3.2.1.3 Histogramme avec courbe de distribution","order":{"number":13,"section":[3,2,1,3,0,0,0]}},{"key":"fig-fig322","caption":"Histogramme et courbe normale","order":{"number":25,"section":[3,2,1,3,0,0,0]}},{"key":"fig-fig348","caption":"Graphique en anneau","order":{"number":50,"section":[3,3,1,0,0,0,0]}},{"key":"sec-03232","caption":"3.2.3.2 Nuage de points avec densité","order":{"number":18,"section":[3,2,3,2,0,0,0]}},{"key":"fig-fig32","caption":"Ajout des dimensions au graphique","order":{"number":3,"section":[3,1,1,0,0,0,0]}},{"key":"fig-fig356","caption":"Exporter un graphique dans RStudio","order":{"number":58,"section":[3,5,0,0,0,0,0]}},{"key":"sec-03231","caption":"3.2.3.1 Nuage de points simple","order":{"number":17,"section":[3,2,3,1,0,0,0]}},{"key":"fig-fig336","caption":"Graphique en ligne avec barres d’erreur","order":{"number":38,"section":[3,2,4,1,0,0,0]}},{"key":"fig-fig328","caption":"Nuage de points simple avec transparence","order":{"number":30,"section":[3,2,3,1,0,0,0]}},{"key":"sec-03241","caption":"3.2.4.1 Barre d’erreur et en bande","order":{"number":21,"section":[3,2,4,1,0,0,0]}},{"key":"fig-fig36","caption":"Ajout d’annotations géométriques","order":{"number":7,"section":[3,1,3,0,0,0,0]}},{"key":"fig-fig330","caption":"Densité en deux dimensions par hexagones","order":{"number":32,"section":[3,2,3,2,0,0,0]}},{"key":"sec-0331","caption":"3.3.1 Graphique en radar","order":{"number":27,"section":[3,3,1,0,0,0,0]}}],"options":{"fig-prefix":"figure","eq-prefix":"équation","tbl-prefix":"tableau","eq-title":"Équation","chapters":true,"sec-prefix":"section","tbl-title":"Tableau","chapter-id":"sec-chap03","fig-title":"Figure"}} \ No newline at end of file diff --git a/.quarto/xref/7b89e682 b/.quarto/xref/7b89e682 new file mode 100644 index 0000000..817269d --- /dev/null +++ b/.quarto/xref/7b89e682 @@ -0,0 +1 @@ +{"headings":["sec-071","sec-072","sec-0721","sec-0722","sec-073","sec-0731","sec-0732","sec-074","sec-0741","sec-0742","sec-0743","sec-0744","sec-075","sec-0751","sec-07511","sec-07512","sec-0752","sec-0753","sec-07531","sec-07532","sec-07533","sec-0754","sec-07541","sec-07542","sec-07543","sec-076","sec-0761","sec-0762","sec-0763","sec-0764","sec-07641","sec-07642","sec-0766","sec-07661","sec-07662","sec-077","sec-0771","sec-0772","sec-0773","sec-07731","sec-07732","sec-07733","sec-07734","sec-07735","sec-07736","sec-0774","sec-07741","sec-07742","sec-07743","sec-07744","sec-07745","sec-07746","sec-07747","sec-078","sec-chap07"],"options":{"tbl-prefix":"tableau","chapters":true,"chapter-id":"sec-chap07","sec-prefix":"section","fig-prefix":"figure","eq-title":"Équation","tbl-title":"Tableau","fig-title":"Figure","eq-prefix":"équation"},"entries":[{"key":"sec-chap07","order":{"section":[7,0,0,0,0,0,0],"number":1}},{"key":"eq-ValeurT","caption":"","order":{"section":[7,4,3,0,0,0,0],"number":16}},{"key":"sec-0751","caption":"7.5.1 Exploration des relations non linéaires","order":{"section":[7,5,1,0,0,0,0],"number":14}},{"key":"sec-077","caption":"7.7 Mise en œuvre dans R","order":{"section":[7,7,0,0,0,0,0],"number":36}},{"key":"sec-0754","caption":"7.5.4 Variables d’interaction","order":{"section":[7,5,4,0,0,0,0],"number":22}},{"key":"tbl-ModeleInteraction2","caption":"Modèle avec une variable d’interaction entre deux VI continues","order":{"section":[7,5,4,1,0,0,0],"number":11}},{"key":"eq-ToleranceVIF","caption":"","order":{"section":[7,6,4,1,0,0,0],"number":30}},{"key":"tbl-regmodeleLog","caption":"Modèle avec une variable indépendante sous forme logarithmique","order":{"section":[7,5,1,2,0,0,0],"number":4}},{"key":"sec-07541","caption":"7.5.4.1 Variable d’interaction entre deux variables continues","order":{"section":[7,5,4,1,0,0,0],"number":23}},{"key":"sec-078","caption":"7.8 Quiz de révision du chapitre","order":{"section":[7,8,0,0,0,0,0],"number":54}},{"key":"fig-ModeleInteractionBinaireeffectex","caption":"Graphique de l’effet marginal de l’interaction entre une variable quantitative et qualitative","order":{"section":[7,7,4,7,0,0,0],"number":24}},{"key":"sec-07747","caption":"7.7.4.7 Effet marginal pour une variable d’interaction (une VI continue et une VI dichotomique)","order":{"section":[7,7,4,7,0,0,0],"number":53}},{"key":"fig-VerifierNormaliteResidus","caption":"Vérification de la normalité des résidus","order":{"section":[7,6,2,0,0,0,0],"number":9}},{"key":"eq-reginteractioncontinues","caption":"","order":{"section":[7,5,4,1,0,0,0],"number":27}},{"key":"tbl-CoefStand2","caption":"Calcul des coefficients standardisés","order":{"section":[7,4,2,0,0,0,0],"number":3}},{"key":"sec-073","caption":"7.3 Évaluation de la qualité d’ajustement du modèle","order":{"section":[7,3,0,0,0,0,0],"number":5}},{"key":"sec-0732","caption":"7.3.2 Comparaison des modèles incrémentiels","order":{"section":[7,3,2,0,0,0,0],"number":7}},{"key":"tbl-regmodeleDich2","caption":"Modèle avec une variable dichotomique","order":{"section":[7,5,2,0,0,0,0],"number":5}},{"key":"eq-regmultiple3","caption":"","order":{"section":[7,2,1,0,0,0,0],"number":3}},{"key":"fig-ModeleInteraction2heatex","caption":"Effet marginal de l’interaction entre deux variables continues","order":{"section":[7,7,4,6,0,0,0],"number":23}},{"key":"sec-07746","caption":"7.7.4.6 Effet marginal pour une variable d’interaction (deux VI continues)","order":{"section":[7,7,4,6,0,0,0],"number":52}},{"key":"fig-EffetMarginalPolyT","caption":"Effet marginal d’une variable polytomique","order":{"section":[7,7,4,5,0,0,0],"number":22}},{"key":"sec-07641","caption":"7.6.4.1 Comment évaluer la multicolinéarité?","order":{"section":[7,6,4,1,0,0,0],"number":31}},{"key":"fig-HomosComp","caption":"Amélioration de l’homoscédasticité des résidus","order":{"section":[7,7,3,6,0,0,0],"number":17}},{"key":"eq-regpolyordre2","caption":"","order":{"section":[7,5,1,1,0,0,0],"number":21}},{"key":"eq-reginteractioncontinuedicho","caption":"","order":{"section":[7,5,4,2,0,0,0],"number":28}},{"key":"sec-07732","caption":"7.7.3.2 Vérification la normalité des résidus","order":{"section":[7,7,3,2,0,0,0],"number":41}},{"key":"fig-EffetMarginalPoly","caption":"Effet marginal d’une variable polytomique","order":{"section":[7,5,3,3,0,0,0],"number":5}},{"key":"eq-regmultiple4","caption":"","order":{"section":[7,2,1,0,0,0,0],"number":4}},{"key":"sec-07734","caption":"7.7.3.4 Vérification la multicolinéarité excessive","order":{"section":[7,7,3,4,0,0,0],"number":43}},{"key":"fig-EffetMarginalVariableLog","caption":"Effet du logarithme de la densité","order":{"section":[7,7,4,3,0,0,0],"number":20}},{"key":"tbl-datareg","caption":"Statistiques descriptives pour les variables du modèle","order":{"section":[7,3,0,0,0,0,0],"number":1}},{"key":"sec-0742","caption":"7.4.2 Coefficients de régression standardisés : repérer les variables les plus importantes du modèle","order":{"section":[7,4,2,0,0,0,0],"number":10}},{"key":"sec-07743","caption":"7.7.4.3 Effet marginal pour une variable transformée en logarithme","order":{"section":[7,7,4,3,0,0,0],"number":49}},{"key":"sec-0753","caption":"7.5.3 Variable indépendante qualitative polytomique","order":{"section":[7,5,3,0,0,0,0],"number":18}},{"key":"sec-0766","caption":"7.6.5 Absence d’observations aberrantes","order":{"section":[7,6,5,0,0,0,0],"number":33}},{"key":"eq-VIF","caption":"","order":{"section":[7,6,4,1,0,0,0],"number":31}},{"key":"fig-Titi","caption":"Effet marginal d’une variable avec un fonction polynomiale d’ordre 2","order":{"section":[7,7,4,2,0,0,0],"number":19}},{"key":"eq-CoefStand","caption":"","order":{"section":[7,4,2,0,0,0,0],"number":14}},{"key":"sec-0752","caption":"7.5.2 Variable indépendante qualitative dichotomique","order":{"section":[7,5,2,0,0,0,0],"number":17}},{"key":"sec-07733","caption":"7.7.3.3 Évaluation de la linéarité et l’homoscédasticité des résidus","order":{"section":[7,7,3,3,0,0,0],"number":42}},{"key":"sec-0761","caption":"7.6.1 Nombre d’observations","order":{"section":[7,6,1,0,0,0,0],"number":27}},{"key":"sec-0743","caption":"7.4.3 Significativité des coefficients de régression : valeurs de t et de p","order":{"section":[7,4,3,0,0,0,0],"number":11}},{"key":"fig-EffetMarginalDich","caption":"Effet marginal d’une variable dichotomique","order":{"section":[7,5,2,0,0,0,0],"number":4}},{"key":"sec-07742","caption":"7.7.4.2 Effet marginal pour une variable avec une fonction polynomiale d’ordre 2","order":{"section":[7,7,4,2,0,0,0],"number":48}},{"key":"fig-ModeleInteraction2heat2","caption":"Effets marginaux de deux variables continues en cas d’absence d’interaction","order":{"section":[7,5,4,1,0,0,0],"number":7}},{"key":"sec-075","caption":"7.5 Introduction de variables explicatives particulières","order":{"section":[7,5,0,0,0,0,0],"number":13}},{"key":"sec-07736","caption":"7.7.3.6 Construction d’un nouveau modèle en supprimant les observations très influentes du modèle","order":{"section":[7,7,3,6,0,0,0],"number":45}},{"key":"sec-07542","caption":"7.5.4.2 Variable d’interaction entre une variable continue et une variable dichotomique","order":{"section":[7,5,4,2,0,0,0],"number":24}},{"key":"eq-regpolyordre3","caption":"","order":{"section":[7,5,1,1,0,0,0],"number":23}},{"key":"eq-regpolyordre4","caption":"","order":{"section":[7,5,1,1,0,0,0],"number":24}},{"key":"sec-076","caption":"7.6 Diagnostics de la régression","order":{"section":[7,6,0,0,0,0,0],"number":26}},{"key":"sec-0763","caption":"7.6.3 Linéarité et homoscédasticité des résidus","order":{"section":[7,6,3,0,0,0,0],"number":29}},{"key":"sec-07662","caption":"7.6.5.2 Quoi faire avec les observations très influentes du modèle","order":{"section":[7,6,5,2,0,0,0],"number":35}},{"key":"sec-0774","caption":"7.7.4 Graphiques pour les effets marginaux","order":{"section":[7,7,4,0,0,0,0],"number":46}},{"key":"eq-regmultiple1","caption":"","order":{"section":[7,2,1,0,0,0,0],"number":1}},{"key":"sec-07731","caption":"7.7.3.1 Vérification le nombre d’observations","order":{"section":[7,7,3,1,0,0,0],"number":40}},{"key":"fig-VerifierHomoscedasticite","caption":"Distribution des résidus en fonction des valeurs prédites","order":{"section":[7,6,3,0,0,0,0],"number":10}},{"key":"fig-ResidusCompa","caption":"Normalité des résidus avant et après la suppression des valeurs influentes","order":{"section":[7,7,3,6,0,0,0],"number":16}},{"key":"fig-DiaGraphCookLev","caption":"Repérage graphique des valeurs influentes du modèle","order":{"section":[7,7,3,5,0,0,0],"number":15}},{"key":"fig-DiaHomoscedasticite","caption":"Distribution des résidus en fonction des valeurs prédites","order":{"section":[7,7,3,3,0,0,0],"number":14}},{"key":"sec-07735","caption":"7.7.3.5 Répérage des valeurs très influentes du modèle","order":{"section":[7,7,3,5,0,0,0],"number":44}},{"key":"eq-Fincrementiel","caption":"","order":{"section":[7,3,2,0,0,0,0],"number":13}},{"key":"sec-07744","caption":"7.7.4.4 Effet marginal pour une variable dichotomique","order":{"section":[7,7,4,4,0,0,0],"number":50}},{"key":"fig-VerifierNormaliteResidusDia","caption":"Diagnostic : la normalité des résidus","order":{"section":[7,7,3,2,0,0,0],"number":13}},{"key":"fig-ModeleInteraction2heat","caption":"Effet marginal de l’interaction entre deux variables continues","order":{"section":[7,5,4,1,0,0,0],"number":6}},{"key":"sec-07512","caption":"7.5.1.2 Variable indépendante sous forme logarithmique","order":{"section":[7,5,1,2,0,0,0],"number":16}},{"key":"sec-07543","caption":"7.5.4.3 Variable d’interaction entre deux variables dichotomiques","order":{"section":[7,5,4,3,0,0,0],"number":25}},{"key":"fig-EffetMarginalDichCode","caption":"Effet marginal d’une variable dichotomique","order":{"section":[7,7,4,4,0,0,0],"number":21}},{"key":"eq-regmultiple2","caption":"","order":{"section":[7,2,1,0,0,0,0],"number":2}},{"key":"sec-0773","caption":"7.7.3 Diagnostic sur un modèle","order":{"section":[7,7,3,0,0,0,0],"number":39}},{"key":"eq-regmultiple5","caption":"","order":{"section":[7,2,1,0,0,0,0],"number":5}},{"key":"eq-IC99","caption":"","order":{"section":[7,4,4,0,0,0,0],"number":19}},{"key":"fig-OutputRegression","caption":"Différentes parties obtenues avec la fonction summary(Modèle)","order":{"section":[7,7,1,0,0,0,0],"number":12}},{"key":"eq-ICcoef","caption":"","order":{"section":[7,4,4,0,0,0,0],"number":17}},{"key":"sec-0721","caption":"7.2.1 Un peu d’équations…","order":{"section":[7,2,1,0,0,0,0],"number":3}},{"key":"sec-0772","caption":"7.7.2 Comparaison des modèles","order":{"section":[7,7,2,0,0,0,0],"number":38}},{"key":"fig-calculRegPoly2","caption":"Relations linéaire et curvilinéaire","order":{"section":[7,5,1,1,0,0,0],"number":2}},{"key":"sec-0771","caption":"7.7.1 Fonctions lm, summary() et confint()","order":{"section":[7,7,1,0,0,0,0],"number":37}},{"key":"eq-IC95","caption":"","order":{"section":[7,4,4,0,0,0,0],"number":18}},{"key":"sec-07661","caption":"7.6.5.1 Détection des observations très influentes du modèle","order":{"section":[7,6,5,1,0,0,0],"number":34}},{"key":"sec-0722","caption":"7.2.2 Hypothèses de la régression linéaire multiple","order":{"section":[7,2,2,0,0,0,0],"number":4}},{"key":"sec-0731","caption":"7.3.1 Mesures de la qualité d’un modèle","order":{"section":[7,3,1,0,0,0,0],"number":6}},{"key":"tbl-ModeleVarPoly1","caption":"Modèle avec une variable polytomique (ville de Montréal en catégorie de référence)","order":{"section":[7,5,3,2,0,0,0],"number":7}},{"key":"fig-GraphCookLev","caption":"Repérage graphique les valeurs influentes du modèle","order":{"section":[7,6,5,1,0,0,0],"number":11}},{"key":"eq-regmRMSE","caption":"","order":{"section":[7,3,1,0,0,0,0],"number":11}},{"key":"tbl-ModeleInteractionBinaire","caption":"Modèle avec les variables d’interaction entre une VI continue et une VI dichotomique","order":{"section":[7,5,4,2,0,0,0],"number":12}},{"key":"eq-R2ajuste","caption":"","order":{"section":[7,3,2,0,0,0,0],"number":12}},{"key":"sec-07642","caption":"7.6.4.2 Comment régler un problème de multicolinéarité?","order":{"section":[7,6,4,2,0,0,0],"number":32}},{"key":"eq-RegVIF","caption":"","order":{"section":[7,6,4,1,0,0,0],"number":29}},{"key":"sec-0764","caption":"7.6.4 Absence de multicolinéarité excessive","order":{"section":[7,6,4,0,0,0,0],"number":30}},{"key":"sec-07741","caption":"7.7.4.1 Effet marginal pour une variable continue","order":{"section":[7,7,4,1,0,0,0],"number":47}},{"key":"sec-0762","caption":"7.6.2 Normalité des résidus","order":{"section":[7,6,2,0,0,0,0],"number":28}},{"key":"fig-EffetMarginalVariablesContinues","caption":"Effets marginaux pour des variables continues","order":{"section":[7,7,4,1,0,0,0],"number":18}},{"key":"eq-regvarpoly1","caption":"","order":{"section":[7,5,3,1,0,0,0],"number":25}},{"key":"sec-07532","caption":"7.5.3.2 Comment interpréter les coefficients des modalités d’une variable explicative qualitative polytomique","order":{"section":[7,5,3,2,0,0,0],"number":20}},{"key":"sec-07511","caption":"7.5.1.1 Variable indépendante avec une fonction polynomiale","order":{"section":[7,5,1,1,0,0,0],"number":15}},{"key":"sec-0741","caption":"7.4.1 Coefficients de régression : évaluer l’effet des variables indépendantes","order":{"section":[7,4,1,0,0,0,0],"number":9}},{"key":"fig-ModeleInteractionBinaire","caption":"Graphique de l’effet marginal de l’interaction entre une variable quantitative et qualitative","order":{"section":[7,5,4,2,0,0,0],"number":8}},{"key":"tbl-dataregmodel2","caption":"Différentes mesures pour les coefficients","order":{"section":[7,4,1,0,0,0,0],"number":2}},{"key":"sec-07531","caption":"7.5.3.1 Comment construire un modèle de régression avec une variable explicative qualitative polytomique?","order":{"section":[7,5,3,1,0,0,0],"number":19}},{"key":"sec-074","caption":"7.4 Différentes mesures pour les coefficients de régression","order":{"section":[7,4,0,0,0,0,0],"number":8}},{"key":"eq-regmultiple6","caption":"","order":{"section":[7,2,1,0,0,0,0],"number":6}},{"key":"eq-regmFFisher","caption":"","order":{"section":[7,3,1,0,0,0,0],"number":10}},{"key":"eq-DistanceCook","caption":"","order":{"section":[7,6,5,1,0,0,0],"number":32}},{"key":"fig-EffetMarginalVariableLogEtNon","caption":"Effet marginal de la densité de population","order":{"section":[7,5,1,2,0,0,0],"number":3}},{"key":"eq-regvarpoly2","caption":"","order":{"section":[7,5,3,1,0,0,0],"number":26}},{"key":"eq-regmR2","caption":"","order":{"section":[7,3,1,0,0,0,0],"number":9}},{"key":"fig-cadreconcept","caption":"Exemple de cadre conceptuel","order":{"section":[7,1,0,0,0,0,0],"number":1}},{"key":"sec-07745","caption":"7.7.4.5 Effet marginal pour une variable polytomique","order":{"section":[7,7,4,5,0,0,0],"number":51}},{"key":"sec-072","caption":"7.2 Principes de base de la régression linéaire multiple","order":{"section":[7,2,0,0,0,0,0],"number":2}},{"key":"tbl-ModeleVarPoly2","caption":"Modèle avec une variable polytomique (Senneville en catégorie de référence","order":{"section":[7,5,3,2,0,0,0],"number":8}},{"key":"eq-regmultiple8","caption":"","order":{"section":[7,2,1,0,0,0,0],"number":7}},{"key":"eq-IC999","caption":"","order":{"section":[7,4,4,0,0,0,0],"number":20}},{"key":"tbl-ModeleVarPoly3","caption":"Modèle avec une variable polytomique (Montréal-Est en catégorie de référence)","order":{"section":[7,5,3,2,0,0,0],"number":9}},{"key":"sec-0744","caption":"7.4.4 Intervalle de confiance des coefficients","order":{"section":[7,4,4,0,0,0,0],"number":12}},{"key":"sec-07533","caption":"7.5.3.3 Effet marginal d’une variable explicative qualitative polytomique","order":{"section":[7,5,3,3,0,0,0],"number":21}},{"key":"eq-CoefStand2","caption":"","order":{"section":[7,4,2,0,0,0,0],"number":15}},{"key":"tbl-ModeleInteraction1","caption":"Modèle avec la distance au centre-ville (km)","order":{"section":[7,5,4,1,0,0,0],"number":10}},{"key":"sec-071","caption":"7.1 Objectifs de la régression linéaire multiple et construction d’un modèle de régression","order":{"section":[7,1,0,0,0,0,0],"number":1}},{"key":"tbl-transfVarQMuettes","caption":"Transformation d’une variable qualitative en variables muettes pour chaque modalité","order":{"section":[7,5,3,1,0,0,0],"number":6}},{"key":"eq-regmVariances","caption":"","order":{"section":[7,3,1,0,0,0,0],"number":8}},{"key":"eq-regpolyordre2b","caption":"","order":{"section":[7,5,1,1,0,0,0],"number":22}}]} \ No newline at end of file diff --git a/.quarto/xref/8bf5c29e b/.quarto/xref/8bf5c29e new file mode 100644 index 0000000..539cae3 --- /dev/null +++ b/.quarto/xref/8bf5c29e @@ -0,0 +1 @@ +{"headings":["sec-131","sec-132","sec-1321","sec-13211","sec-13212","sec-13213","sec-13214","sec-13215","sec-13216","sec-13217","sec-1322","sec-133","sec-1331","sec-1332","sec-13321","sec-13322","sec-13323","sec-1333","sec-1334","sec-13341","sec-13342","sec-13343","sec-13344","sec-134","sec-1341","sec-13411","sec-13412","sec-1342","sec-1343","sec-1344","sec-13441","sec-13442","sec-134421","sec-134422","sec-134423","sec-13443","sec-13444","sec-13455","sec-1346","sec-13461","préparation-des-données","sélection-de-k-et-de-m","application-lalgorithme-c-means","interprétation-des-résultats","sec-13462","sec-135","sec-136","sec-chap13"],"options":{"tbl-title":"Tableau","sec-prefix":"section","eq-title":"Équation","chapters":true,"fig-title":"Figure","tbl-prefix":"tableau","fig-prefix":"figure","chapter-id":"sec-chap13","eq-prefix":"équation"},"entries":[{"key":"sec-chap13","order":{"number":1,"section":[13,0,0,0,0,0,0]}},{"caption":"13.4.4.4 Interprétation des résultats","key":"sec-13444","order":{"number":37,"section":[13,4,4,4,0,0,0]}},{"caption":"13.3.2.2 Indicateur de silhouette","key":"sec-13322","order":{"number":16,"section":[13,3,2,2,0,0,0]}},{"caption":"Distributions des valeurs des centres du groupe 2 sur 1000 itérations","key":"fig-kmeansStab5","order":{"number":31,"section":[13,4,5,2,0,0,0]}},{"caption":"Valeur de l’indice de silhouette pour différents nombres de groupes (distance euclidienne au carré)","key":"fig-exampleHclust8","order":{"number":17,"section":[13,3,4,4,0,0,0]}},{"caption":"13.2.1.3 Distance du khi-deux","key":"sec-13213","order":{"number":6,"section":[13,2,1,3,0,0,0]}},{"caption":"13.2.2 Inertie","key":"sec-1322","order":{"number":11,"section":[13,2,2,0,0,0,0]}},{"caption":"Graphiques en violon pour les groupes issus du k-means","key":"fig-kmeansI","order":{"number":24,"section":[13,4,4,4,0,0,0]}},{"caption":"13.3.4.2 Application de l’algorithme de classification ascendante hiérarchique","key":"sec-13342","order":{"number":21,"section":[13,3,4,2,0,0,0]}},{"caption":"Algorithme K-means","key":"fig-kmeansA","order":{"number":18,"section":[13,4,1,1,0,0,0]}},{"caption":"13.4.4.3 Application l’algorithme du k-means","key":"sec-13443","order":{"number":36,"section":[13,4,4,3,0,0,0]}},{"caption":"","key":"eq-gapidx","order":{"number":10,"section":[13,3,2,3,0,0,0]}},{"caption":"Cartographie des probabilités d’appartenir aux quatre groupes identifiés par l’algorithme c-means","key":"fig-cmeansD","order":{"number":27,"section":[13,4,5,1,4,0,0]}},{"caption":"Graphiques en radar pour les groupes issus du k-means","key":"fig-kmeansH","order":{"number":23,"section":[13,4,4,4,0,0,0]}},{"caption":"13.2.1.4 Distance de Mahalanobis","key":"sec-13214","order":{"number":7,"section":[13,2,1,4,0,0,0]}},{"caption":"13.2 Notions essentielles en classification","key":"sec-132","order":{"number":2,"section":[13,2,0,0,0,0,0]}},{"caption":"13.3.2.3 Méthode GAP","key":"sec-13323","order":{"number":17,"section":[13,3,2,3,0,0,0]}},{"caption":"13.4.4.2.2 Indice de silhouette","key":"sec-134422","order":{"number":34,"section":[13,4,4,2,2,0,0]}},{"caption":"13.4.5.1 Mise en œuvre du c-means dans R","key":"sec-13461","order":{"number":40,"section":[13,4,5,1,0,0,0]}},{"caption":"Description des groupes avec la méthode c-means","key":"tbl-cmeansG","order":{"number":9,"section":[13,4,5,1,4,0,0]}},{"caption":"","key":"eq-chi2dist","order":{"number":3,"section":[13,2,1,3,0,0,0]}},{"caption":"Comparaison géographique des résultats obtenus pour le k-means, le k-medians et le k-medoids","key":"fig-kmeansM","order":{"number":25,"section":[13,4,4,5,0,0,0]}},{"caption":"13.3.4 Mise en œuvre dans R","key":"sec-1334","order":{"number":19,"section":[13,3,4,0,0,0,0]}},{"caption":"Exemple de données pour la distance de Hamming","key":"tbl-dist4","order":{"number":2,"section":[13,2,1,5,0,0,0]}},{"caption":"","key":"eq-inertia","order":{"number":7,"section":[13,2,2,0,0,0,0]}},{"caption":"13.4 Nuées dynamiques","key":"sec-134","order":{"number":24,"section":[13,4,0,0,0,0,0]}},{"caption":"13.3.3 Limites de la classification ascendante hiérarchique","key":"sec-1333","order":{"number":18,"section":[13,3,3,0,0,0,0]}},{"caption":"Principe de fonctionnement de la classification ascendante hiérarchique (auteur : David Sheehan)","key":"fig-animhclust","order":{"number":12,"section":[13,3,1,0,0,0,0]}},{"caption":"Valeur de l’indice de silhouette pour différents nombres de groupes","key":"fig-exampleHclust4","order":{"number":16,"section":[13,3,4,2,0,0,0]}},{"caption":"13.6 Quiz de révision du chapitre","key":"sec-136","order":{"number":43,"section":[13,6,0,0,0,0,0]}},{"caption":"13.3 Classification ascendante hiérarchique","key":"sec-133","order":{"number":12,"section":[13,3,0,0,0,0,0]}},{"caption":"Représentation de la distance euclidienne","key":"fig-dist1","order":{"number":5,"section":[13,2,1,1,0,0,0]}},{"caption":"Effets de différentes transformations sur la distribution d’une variable","key":"fig-impactTransform","order":{"number":6,"section":[13,2,1,1,0,0,0]}},{"caption":"Distributions des valeurs des centres du groupe 4 sur 1000 itérations","key":"fig-kmeansStab4","order":{"number":30,"section":[13,4,5,2,0,0,0]}},{"caption":"Trois histogrammes pour illustrer le calcul de la distance du khi-deux","key":"fig-dist3","order":{"number":8,"section":[13,2,1,3,0,0,0]}},{"caption":"Distance de Hamming entre les maisons","key":"tbl-dist5","order":{"number":3,"section":[13,2,1,5,0,0,0]}},{"caption":"Complémentarité entre les méthodes factorielles et les méthodes de classification non supervisée","key":"fig-MFMCComplementarite","order":{"number":32,"section":[13,5,0,0,0,0,0]}},{"caption":"Statistiques descriptives du jeu de données LyonIris","key":"tbl-datageocmeans","order":{"number":7,"section":[13,4,4,0,0,0,0]}},{"caption":"","key":"eq-gower","order":{"number":5,"section":[13,2,1,6,0,0,0]}},{"caption":"13.4.3 K-médoïds","key":"sec-1343","order":{"number":29,"section":[13,4,3,0,0,0,0]}},{"caption":"Représentation de l’inertie par groupe pour le jeu de données IRIS","key":"fig-dist7","order":{"number":10,"section":[13,2,2,0,0,0,0]}},{"caption":"Situation de base pour le calcul de distance","key":"fig-dist0","order":{"number":4,"section":[13,2,1,1,0,0,0]}},{"caption":"Indices de Jacard obtenus sur 1000 réplications du k-means","key":"fig-kmeansStab3","order":{"number":29,"section":[13,4,5,2,0,0,0]}},{"caption":"","key":"eq-euclideandist","order":{"number":1,"section":[13,2,1,1,0,0,0]}},{"caption":"13.4.2 K-médianes","key":"sec-1342","order":{"number":28,"section":[13,4,2,0,0,0,0]}},{"caption":"Inertie expliquée pour différents nombres de groupes pour le k-means","key":"fig-kmeansC","order":{"number":19,"section":[13,4,4,2,1,0,0]}},{"caption":"13.3.1 Fonctionnement de l’algorithme","key":"sec-1331","order":{"number":13,"section":[13,3,1,0,0,0,0]}},{"caption":"","key":"eq-silhouetteidx","order":{"number":9,"section":[13,3,2,2,0,0,0]}},{"caption":"Représentation de l’inertie du jeu de données IRIS","key":"fig-dist6","order":{"number":9,"section":[13,2,2,0,0,0,0]}},{"caption":"13.4.5.2 Mise en œuvre du c-medoids dans R","key":"sec-13462","order":{"number":41,"section":[13,4,5,2,0,0,0]}},{"caption":"Graphique en radar pour les résultats du c-means","key":"fig-cmeansE","order":{"number":28,"section":[13,4,5,1,4,0,0]}},{"caption":"13.2.1.6 Distance de Gower","key":"sec-13216","order":{"number":9,"section":[13,2,1,6,0,0,0]}},{"caption":"Caractéristiques des groupes obtenus lors de la CAH","key":"tbl-exampleHclust7","order":{"number":5,"section":[13,3,4,3,0,0,0]}},{"caption":"13.3.4.4 Utilisation de la matrice de distance euclidienne au carré","key":"sec-13344","order":{"number":23,"section":[13,3,4,4,0,0,0]}},{"caption":"Du tableau de données à la matrice de distance","key":"fig-tablvsmat","order":{"number":11,"section":[13,3,1,0,0,0,0]}},{"caption":"13.4.4 Mise en œuvre dans R","key":"sec-1344","order":{"number":30,"section":[13,4,4,0,0,0,0]}},{"caption":"Caractéristiques des groupes obtenus lors de la CAH (distance euclidienne au carré)","key":"tbl-exampleHclust10","order":{"number":6,"section":[13,3,4,4,0,0,0]}},{"caption":"13.4.4.5 K-médianes et K-médoides","key":"sec-13455","order":{"number":38,"section":[13,4,4,5,0,0,0]}},{"caption":"Descriptions des quatre groupes obtenus","key":"tbl-kmeansK","order":{"number":8,"section":[13,4,4,4,0,0,0]}},{"caption":"Principe de base des méthodes de classification non supervisée","key":"fig-ClassifNonNSuperv","order":{"number":1,"section":[13,0,0,0,0,0,0]}},{"caption":"13.4.1.1 Fonctionnement de l’algorithme","key":"sec-13411","order":{"number":26,"section":[13,4,1,1,0,0,0]}},{"caption":"","key":"eq-mahalanobis","order":{"number":4,"section":[13,2,1,4,0,0,0]}},{"caption":"13.2.1 Distance","key":"sec-1321","order":{"number":3,"section":[13,2,1,0,0,0,0]}},{"caption":"13.4.4.2.3 Méthode GAP","key":"sec-134423","order":{"number":35,"section":[13,4,4,2,3,0,0]}},{"caption":"Indice de silhouette pour différents nombres de groupes pour le k-means","key":"fig-kmeansD","order":{"number":20,"section":[13,4,4,2,2,0,0]}},{"caption":"13.3.2.1 Méthode du coude","key":"sec-13321","order":{"number":15,"section":[13,3,2,1,0,0,0]}},{"caption":"Distance du khi-deux entre trois histogrammes","key":"tbl-tabdist3","order":{"number":1,"section":[13,2,1,3,0,0,0]}},{"caption":"13.4.4.2.1 Méthode du coude","key":"sec-134421","order":{"number":33,"section":[13,4,4,2,1,0,0]}},{"caption":"13.5 Conclusion sur la cinquième partie","key":"sec-135","order":{"number":42,"section":[13,5,0,0,0,0,0]}},{"caption":"13.4.4.1 Préparation des données","key":"sec-13441","order":{"number":31,"section":[13,4,4,1,0,0,0]}},{"caption":"13.4.4.2 Choix du nombre de groupes optimal","key":"sec-13442","order":{"number":32,"section":[13,4,4,2,0,0,0]}},{"caption":"Sélection des paramètres k et m pour l’algorithme c-means","key":"fig-cmeansB","order":{"number":26,"section":[13,4,5,1,2,0,0]}},{"caption":"","key":"eq-explainedinertia","order":{"number":8,"section":[13,2,2,0,0,0,0]}},{"caption":"13.2.1.2 Distance de Manhattan","key":"sec-13212","order":{"number":5,"section":[13,2,1,2,0,0,0]}},{"caption":"Équipements recensés dans les différents parcs de Montréal","key":"tbl-exampleHclust1DF","order":{"number":4,"section":[13,3,4,0,0,0,0]}},{"caption":"Méthode GAP pour différents nombres de groupes pour le k-means","key":"fig-kmeansE","order":{"number":21,"section":[13,4,4,2,3,0,0]}},{"caption":"Méthode de l’indice de silhouette","key":"fig-kmeans3","order":{"number":14,"section":[13,3,2,2,0,0,0]}},{"caption":"13.1 Méthodes de classification : un aperçu","key":"sec-131","order":{"number":1,"section":[13,1,0,0,0,0,0]}},{"caption":"","key":"eq-manhattandist","order":{"number":2,"section":[13,2,1,2,0,0,0]}},{"caption":"13.2.1.7 Distance du Phi2","key":"sec-13217","order":{"number":10,"section":[13,2,1,7,0,0,0]}},{"caption":"Méthode du coude","key":"fig-kmeans2","order":{"number":13,"section":[13,3,2,1,0,0,0]}},{"caption":"Représentation de la distance de Manhattan","key":"fig-dist2","order":{"number":7,"section":[13,2,1,2,0,0,0]}},{"caption":"Classifications stricte et floue","key":"fig-floueVSstrict","order":{"number":2,"section":[13,1,0,0,0,0,0]}},{"caption":"13.4.1 K-means","key":"sec-1341","order":{"number":25,"section":[13,4,1,0,0,0,0]}},{"caption":"13.4.1.2 Choix du nombre optimal de groupes","key":"sec-13412","order":{"number":27,"section":[13,4,1,2,0,0,0]}},{"caption":"13.3.2 Choisir le bon nombre de groupes","key":"sec-1332","order":{"number":14,"section":[13,3,2,0,0,0,0]}},{"caption":"","key":"eq-phidist","order":{"number":6,"section":[13,2,1,7,0,0,0]}},{"caption":"Méthode GAP","key":"fig-kmeans4","order":{"number":15,"section":[13,3,2,3,0,0,0]}},{"caption":"Synthèse des principales méthodes de classification (Gelb et Apparicio 2021)","key":"fig-methoClassif","order":{"number":3,"section":[13,1,0,0,0,0,0]}},{"caption":"13.3.4.1 Calcul de la matrice de distance","key":"sec-13341","order":{"number":20,"section":[13,3,4,1,0,0,0]}},{"caption":"13.2.1.1 Distance euclidienne","key":"sec-13211","order":{"number":4,"section":[13,2,1,1,0,0,0]}},{"caption":"13.2.1.5 Distance de Hamming","key":"sec-13215","order":{"number":8,"section":[13,2,1,5,0,0,0]}},{"caption":"13.4.5 Extensions en logique floue : c-means, c-medoids","key":"sec-1346","order":{"number":39,"section":[13,4,5,0,0,0,0]}},{"caption":"13.3.4.3 Interprétation des résultats","key":"sec-13343","order":{"number":22,"section":[13,3,4,3,0,0,0]}},{"caption":"Cartographie des groupes obtenus avec la méthode du k-means","key":"fig-kmeansG","order":{"number":22,"section":[13,4,4,4,0,0,0]}}]} \ No newline at end of file diff --git a/.quarto/xref/INDEX b/.quarto/xref/INDEX new file mode 100644 index 0000000..b271b4e --- /dev/null +++ b/.quarto/xref/INDEX @@ -0,0 +1,53 @@ +{ + "index.qmd": { + "index.html": "4b2fdbb1" + }, + "00-auteurs.qmd": { + "00-auteurs.html": "b3cb89cf" + }, + "01-priseenmainR.qmd": { + "01-priseenmainR.html": "e484d2c4" + }, + "02-univarie.qmd": { + "02-univarie.html": "ce39d7b3" + }, + "03-magiedesgraphiques.qmd": { + "03-magiedesgraphiques.html": "6ba11324" + }, + "04-bivarieeQuantiQuanti.qmd": { + "04-bivarieeQuantiQuanti.html": "3d6f23dc" + }, + "05-bivarieeQualiQuali.qmd": { + "05-bivarieeQualiQuali.html": "a34508e3" + }, + "06-bivarieeQualiQuanti.qmd": { + "06-bivarieeQualiQuanti.html": "24c5beb5" + }, + "07-regressionlineaire.qmd": { + "07-regressionlineaire.html": "7b89e682" + }, + "08-GLM.qmd": { + "08-GLM.html": "5c001e14" + }, + "09-GLMM.qmd": { + "09-GLMM.html": "50e63b0f" + }, + "10-Multiniveau.qmd": { + "10-Multiniveau.html": "19cd9939" + }, + "11-GAM.qmd": { + "11-GAM.html": "40a20182" + }, + "12-AnalysesFactorielles.qmd": { + "12-AnalysesFactorielles.html": "e28e1e20" + }, + "13-MethodeClassification.qmd": { + "13-MethodeClassification.html": "8bf5c29e" + }, + "14-Annexes.qmd": { + "14-Annexes.html": "bd0d0b41" + }, + "references.qmd": { + "references.html": "53469ec4" + } +} \ No newline at end of file diff --git a/.quarto/xref/a34508e3 b/.quarto/xref/a34508e3 new file mode 100644 index 0000000..e7b6b22 --- /dev/null +++ b/.quarto/xref/a34508e3 @@ -0,0 +1 @@ +{"entries":[{"key":"sec-chap05","order":{"number":1,"section":[5,0,0,0,0,0,0]}},{"key":"sec-051","order":{"number":1,"section":[5,1,0,0,0,0,0]},"caption":"5.1 Construction de tableau de contingence"},{"key":"fig-VDC","order":{"number":1,"section":[5,4,0,0,0,0,0]},"caption":"Figure avec la fonction mosaic du package vcd"},{"key":"fig-hml","order":{"number":2,"section":[5,4,0,0,0,0,0]},"caption":"Taille des projets d’habitation à loyer modique selon la période de construction"},{"key":"sec-054","order":{"number":4,"section":[5,4,0,0,0,0,0]},"caption":"5.4 Interprétation d’un tableau de contingence"},{"key":"sec-053","order":{"number":3,"section":[5,3,0,0,0,0,0]},"caption":"5.3 Mise en œuvre dans R"},{"key":"sec-055","order":{"number":5,"section":[5,5,0,0,0,0,0]},"caption":"5.5 Quiz de révision du chapitre"},{"key":"tbl-EncadreAsso","order":{"number":1,"section":[5,2,0,0,0,0,0]},"caption":"Autres mesures d’association entre deux variables qualitatives"},{"key":"tbl-MesuresAssociations","order":{"number":2,"section":[5,3,0,0,0,0,0]},"caption":"Mesures d’association entre deux variables qualitatives"},{"key":"sec-052","order":{"number":2,"section":[5,2,0,0,0,0,0]},"caption":"5.2 Test du khi-deux"}],"headings":["sec-051","sec-052","sec-053","sec-054","sec-055","sec-chap05"],"options":{"fig-title":"Figure","tbl-title":"Tableau","chapter-id":"sec-chap05","chapters":true,"tbl-prefix":"tableau","fig-prefix":"figure","sec-prefix":"section","eq-title":"Équation","eq-prefix":"équation"}} \ No newline at end of file diff --git a/.quarto/xref/b3cb89cf b/.quarto/xref/b3cb89cf new file mode 100644 index 0000000..14f7d35 --- /dev/null +++ b/.quarto/xref/b3cb89cf @@ -0,0 +1 @@ +{"options":{"chapter-id":"auteurs","eq-title":"Équation","chapters":true,"eq-prefix":"équation","tbl-prefix":"tableau","sec-prefix":"section","tbl-title":"Tableau","fig-title":"Figure","fig-prefix":"figure"},"headings":["auteurs"],"entries":[]} \ No newline at end of file diff --git a/.quarto/xref/bd0d0b41 b/.quarto/xref/bd0d0b41 new file mode 100644 index 0000000..9d7226a --- /dev/null +++ b/.quarto/xref/bd0d0b41 @@ -0,0 +1 @@ +{"options":{"tbl-prefix":"tableau","chapters":true,"chapter-id":"sec-chap14","tbl-title":"Tableau","eq-prefix":"équation","fig-prefix":"figure","eq-title":"Équation","sec-prefix":"section","fig-title":"Figure"},"headings":["sec-141","sec-142","sec-143","sec-chap14"],"entries":[{"key":"sec-chap14","order":{"section":[14,0,0,0,0,0,0],"number":1}},{"key":"sec-141","caption":"14.1 Table des valeurs critiques de khi-deux","order":{"section":[14,1,0,0,0,0,0],"number":1}},{"key":"tbl-CritiqueF2","caption":"Distribution des valeurs critiques de F avec p = 0,05 (suite)","order":{"section":[14,2,0,0,0,0,0],"number":3}},{"key":"tbl-tableCritiqueKhi2","caption":"Distribution des valeurs critiques du khi-deux","order":{"section":[14,1,0,0,0,0,0],"number":1}},{"key":"tbl-CritiqueF3","caption":"Distribution des valeurs critiques de F avec p = 0,05 (suite)","order":{"section":[14,2,0,0,0,0,0],"number":4}},{"key":"tbl-tableCritiqueT","caption":"Distribution des valeurs critiques de t","order":{"section":[14,3,0,0,0,0,0],"number":5}},{"key":"sec-143","caption":"14.3 Table des valeurs critiques de t","order":{"section":[14,3,0,0,0,0,0],"number":3}},{"key":"tbl-CritiqueF1","caption":"Distribution des valeurs critiques de F avec p = 0,05","order":{"section":[14,2,0,0,0,0,0],"number":2}},{"key":"sec-142","caption":"14.2 Table des valeurs critiques de Fisher","order":{"section":[14,2,0,0,0,0,0],"number":2}}]} \ No newline at end of file diff --git a/.quarto/xref/ce39d7b3 b/.quarto/xref/ce39d7b3 new file mode 100644 index 0000000..17cfb85 --- /dev/null +++ b/.quarto/xref/ce39d7b3 @@ -0,0 +1 @@ +{"headings":["sec-021","sec-0211","sec-0212","sec-02121","sec-02122","sec-022","sec-0221","sec-0222","sec-0223","sec-0224","sec-023","sec-0231","sec-0232","sec-024","définition-générale","anatomie-dune-distribution","principales-distributions","distribution-uniforme-discrète","distribution-de-bernoulli","distribution-binomiale","distribution-géométrique","distribution-binomiale-négative","distribution-de-poisson","sec-poissonzero","distribution-gaussienne","distribution-gaussienne-asymétrique","distribution-log-normale","sec-024311","distribution-de-cauchy","distribution-du-khi-deux","distribution-exponentielle","sec-024315","sec-024316","distribution-de-weibull","distribution-pareto","cas-particuliers","conclusion-sur-les-distributions","sec-025","sec-0251","sec-0252","sec-0253","sec-0254","vérification-de-la-normalité-dune-variable-quantitative","vérification-de-la-normalité-avec-les-coefficients-dasymétrie-et-daplatissement","vérification-de-la-normalité-avec-des-graphiques","sec-025413","sec-02adjdistrib","temps-de-retard-des-bus-de-la-ville-de-toronto","accidents-de-vélo-à-montréal","sec-0255","sec-02551","sec-02552","sec-0256","sec-02561","sec-02562","sec-02563","sec-026","sec-0261","sec-0262","sec-027","sec-028","sec-chap02"],"options":{"tbl-prefix":"tableau","chapter-id":"sec-chap02","eq-title":"Équation","tbl-title":"Tableau","sec-prefix":"section","fig-title":"Figure","chapters":true,"eq-prefix":"équation","fig-prefix":"figure"},"entries":[{"order":{"section":[2,0,0,0,0,0,0],"number":1},"key":"sec-chap02"},{"caption":"2.1.2.1 Variables qualitatives","order":{"section":[2,1,2,1,0,0,0],"number":4},"key":"sec-02121"},{"caption":"2.5.4.2 Tests pour d’autres formes de distribution","order":{"section":[2,5,4,2,0,0,0],"number":25},"key":"sec-02adjdistrib"},{"caption":"2.6 Statistiques descriptives sur des variables qualitatives et semi-qualitatives","order":{"section":[2,6,0,0,0,0,0],"number":33},"key":"sec-026"},{"caption":"","order":{"section":[2,4,2,0,0,0,0],"number":1},"key":"eq-Bernoulli"},{"caption":"","order":{"section":[2,5,4,1,1,0,0],"number":23},"key":"eq-SkewType1"},{"caption":"Distribution binomiale","order":{"section":[2,4,3,3,0,0,0],"number":8},"key":"fig-fig256"},{"caption":"2.1.1 Notion de variable","order":{"section":[2,1,1,0,0,0,0],"number":2},"key":"sec-0211"},{"caption":"Distribution du khi-deux","order":{"section":[2,4,3,13,0,0,0],"number":18},"key":"fig-fig265"},{"caption":"","order":{"section":[2,4,3,2,0,0,0],"number":3},"key":"eq-BernoulliB"},{"caption":"Distribution de Cauchy","order":{"section":[2,4,3,12,0,0,0],"number":17},"key":"fig-fig264"},{"caption":"2.4.3.7 Distribution de Poisson avec excès de zéros","order":{"section":[2,4,3,7,0,0,0],"number":15},"key":"sec-poissonzero"},{"caption":"","order":{"section":[2,4,2,0,0,0,0],"number":2},"key":"eq-Uniforme"},{"caption":"Comparaison des LogLikelihood des trois distributions","order":{"section":[2,5,4,2,1,0,0],"number":8},"key":"tbl-distribs"},{"caption":"Revenus moyens et médians des ménages en dollars, municipalités de l’île de Montréal, 2015","order":{"section":[2,5,1,0,0,0,0],"number":1},"key":"tbl-RevMoyMed"},{"caption":"2.8 Quiz de révision du chapitre","order":{"section":[2,8,0,0,0,0,0],"number":37},"key":"sec-028"},{"caption":"","order":{"section":[2,4,3,10,0,0,0],"number":11},"key":"eq-loggaussien"},{"caption":"Statistiques de l’aire de jeux la plus proche, par secteur de recensement, pondérées par la population de moins de 10 ans","order":{"section":[2,7,0,0,0,0,0],"number":13},"key":"tbl-MoyPondParc"},{"caption":"","order":{"section":[2,4,3,17,0,0,0],"number":18},"key":"eq-weibull"},{"caption":"Accessibilité aux aires de jeux par secteur de recensement, Communauté métropolitaine de Montréal, 2016","order":{"section":[2,7,0,0,0,0,0],"number":38},"key":"fig-ParcCMM"},{"caption":"Stastistiques descriptives de l’exposition au bruit des cyclistes par minute dans trois villes (dB(A), Laeq 1min)","order":{"section":[2,5,2,0,0,0,0],"number":2},"key":"tbl-Centiles"},{"caption":"Calcul de la moyenne pondérée","order":{"section":[2,7,0,0,0,0,0],"number":12},"key":"tbl-MoyPondCalcul"},{"caption":"2.5 Statistiques descriptives sur des variables quantitatives","order":{"section":[2,5,0,0,0,0,0],"number":19},"key":"sec-025"},{"caption":"","order":{"section":[2,7,0,0,0,0,0],"number":31},"key":"eq-moypond"},{"caption":"Histogrammes et courbe normale","order":{"section":[2,5,4,1,2,0,0],"number":29},"key":"fig-CourbeNormale"},{"caption":"Distribution empirique des temps de retard des bus à Toronto en janvier 2019","order":{"section":[2,5,4,2,1,0,0],"number":31},"key":"fig-bustrt"},{"caption":"","order":{"section":[2,4,3,15,0,0,0],"number":16},"key":"eq-gamma"},{"caption":"Distribution binomiale négative","order":{"section":[2,4,3,5,0,0,0],"number":10},"key":"fig-fig258"},{"caption":"2.7 Statistiques descriptives pondérées : pour aller plus loin","order":{"section":[2,7,0,0,0,0,0],"number":36},"key":"sec-027"},{"caption":"2.2.1 Données secondaires versus données primaires","order":{"section":[2,2,1,0,0,0,0],"number":7},"key":"sec-0221"},{"caption":"Comparaison des distributions ajustées aux données de retard des bus","order":{"section":[2,5,4,2,1,0,0],"number":32},"key":"fig-bustrt2"},{"caption":"2.5.4 Paramètres de forme","order":{"section":[2,5,4,0,0,0,0],"number":23},"key":"sec-0254"},{"caption":"2.5.5 Transformation des variables","order":{"section":[2,5,5,0,0,0,0],"number":26},"key":"sec-0255"},{"caption":"Différents types de fréquences sur une variable semi-qualitative","order":{"section":[2,6,1,0,0,0,0],"number":11},"key":"tbl-Frequences2"},{"caption":"2.3.1 Population, échantillon et inférence","order":{"section":[2,3,1,0,0,0,0],"number":12},"key":"sec-0231"},{"caption":"Différents types de fréquences sur une variable qualitative ou semi-qualitative","order":{"section":[2,6,1,0,0,0,0],"number":10},"key":"tbl-Frequences"},{"caption":"2.6.1 Fréquences","order":{"section":[2,6,1,0,0,0,0],"number":34},"key":"sec-0261"},{"caption":"Histogramme des transformations","order":{"section":[2,5,6,3,0,0,0],"number":36},"key":"fig-GTranf"},{"caption":"Exemples de cartographie avec une discrétisation selon les quantiles","order":{"section":[2,5,2,0,0,0,0],"number":24},"key":"fig-univarie2"},{"caption":"2.5.6.3 Transformation d’une variable dans R","order":{"section":[2,5,6,3,0,0,0],"number":32},"key":"sec-02563"},{"caption":"2.5.6.2 Application à plusieurs variables","order":{"section":[2,5,6,2,0,0,0],"number":31},"key":"sec-02562"},{"caption":"","order":{"section":[2,4,3,18,0,0,0],"number":19},"key":"eq-pareto"},{"caption":"","order":{"section":[2,5,4,1,1,0,0],"number":26},"key":"eq-KurtType1"},{"caption":"Histogramme avec courbe normale","order":{"section":[2,5,6,1,0,0,0],"number":35},"key":"fig-GcourbeNormale"},{"caption":"2.4.3.11 Distribution de Student","order":{"section":[2,4,3,11,0,0,0],"number":16},"key":"sec-024311"},{"caption":"2.3 Statistique descriptive et statistique inférentielle","order":{"section":[2,3,0,0,0,0,0],"number":11},"key":"sec-023"},{"caption":"Illustration de la sensibilité des mesures de dispersion à l’unité de mesure et aux valeurs extrêmes","order":{"section":[2,5,3,0,0,0,0],"number":4},"key":"tbl-datavar2"},{"caption":"2.5.6 Mise en œuvre dans R","order":{"section":[2,5,6,0,0,0,0],"number":29},"key":"sec-0256"},{"caption":"Illustration des trois transformations","order":{"section":[2,5,5,2,0,0,0],"number":9},"key":"tbl-AutresTransformation"},{"caption":"","order":{"section":[2,4,3,13,0,0,0],"number":14},"key":"eq-chi2"},{"caption":"","order":{"section":[2,5,5,2,0,0,0],"number":30},"key":"eq-t01"},{"caption":"Distribution gaussienne asymétrique","order":{"section":[2,4,3,9,0,0,0],"number":14},"key":"fig-fig261"},{"caption":"2.5.5.2 Autres types de transformations","order":{"section":[2,5,5,2,0,0,0],"number":28},"key":"sec-02552"},{"caption":"","order":{"section":[2,4,3,5,0,0,0],"number":6},"key":"eq-binomialnegative"},{"caption":"2.2.3 Données spatiales versus données aspatiales","order":{"section":[2,2,3,0,0,0,0],"number":9},"key":"sec-0223"},{"caption":"2.5.5.1 Transformations visant à atteindre la normalité","order":{"section":[2,5,5,1,0,0,0],"number":27},"key":"sec-02551"},{"caption":"","order":{"section":[2,4,3,8,0,0,0],"number":9},"key":"eq-gaussien"},{"caption":"Différents graphiques pour représenter les fréquences absolues et relatives","order":{"section":[2,6,1,0,0,0,0],"number":37},"key":"fig-GraphiquesFreq1"},{"caption":"Distributions uniformes continues","order":{"section":[2,4,2,0,0,0,0],"number":6},"key":"fig-fig254"},{"caption":"Distribution gaussienne","order":{"section":[2,4,3,8,0,0,0],"number":13},"key":"fig-fig260"},{"caption":"Distribution de Student","order":{"section":[2,4,3,11,0,0,0],"number":16},"key":"fig-fig263"},{"caption":"","order":{"section":[2,5,3,0,0,0,0],"number":20},"key":"eq-variance"},{"caption":"2.1 Notion et types de variable","order":{"section":[2,1,0,0,0,0,0],"number":1},"key":"sec-021"},{"caption":"Formes d’une distribution et coefficients d’asymétrie et d’aplatissement","order":{"section":[2,5,4,1,0,0,0],"number":26},"key":"fig-FormeDistr"},{"caption":"","order":{"section":[2,4,3,16,0,0,0],"number":17},"key":"eq-beta"},{"caption":"Distribution empirique d’un lancer de dé (n = 10)","order":{"section":[2,4,1,0,0,0,0],"number":4},"key":"fig-fig252"},{"caption":"Différents tests d’hypothèse pour la normalité","order":{"section":[2,5,4,1,3,0,0],"number":6},"key":"tbl-testnormalites"},{"caption":"","order":{"section":[2,5,3,0,0,0,0],"number":22},"key":"eq-cv"},{"caption":"2.4 Notion de distribution","order":{"section":[2,4,0,0,0,0,0],"number":14},"key":"sec-024"},{"caption":"Distribution exponentielle","order":{"section":[2,4,3,14,0,0,0],"number":19},"key":"fig-fig266"},{"caption":"","order":{"section":[2,4,3,6,0,0,0],"number":7},"key":"eq-poisson"},{"caption":"Applatissement d’une distribution","order":{"section":[2,5,4,1,1,0,0],"number":28},"key":"fig-kurtosis"},{"caption":"","order":{"section":[2,5,4,1,1,0,0],"number":28},"key":"eq-KurtType3"},{"caption":"2.5.3 Paramètres de dispersion","order":{"section":[2,5,3,0,0,0,0],"number":22},"key":"sec-0253"},{"caption":"2.4.3.15 Distribution Gamma","order":{"section":[2,4,3,15,0,0,0],"number":17},"key":"sec-024315"},{"caption":"Asymétrie d’une distribution","order":{"section":[2,5,4,1,1,0,0],"number":27},"key":"fig-asymetrie"},{"caption":"","order":{"section":[2,4,3,4,0,0,0],"number":5},"key":"eq-geometrique"},{"caption":"","order":{"section":[2,4,3,12,0,0,0],"number":13},"key":"eq-cauchy"},{"caption":"","order":{"section":[2,5,4,1,1,0,0],"number":24},"key":"eq-SkewType2"},{"caption":"Tests de normalité pour différentes distributions","order":{"section":[2,5,4,1,3,0,0],"number":7},"key":"tbl-calcultestnormalites"},{"caption":"Distribution de Pareto","order":{"section":[2,4,3,18,0,0,0],"number":23},"key":"fig-fig270"},{"caption":"2.6.2 Mise en œuvre dans R","order":{"section":[2,6,2,0,0,0,0],"number":35},"key":"sec-0262"},{"caption":"Résumé de la sensibilité de la moyenne et des mesures de dispersion","order":{"section":[2,5,3,0,0,0,0],"number":5},"key":"tbl-resume"},{"caption":"Calcul des mesures de dispersion sur des données fictives","order":{"section":[2,5,3,0,0,0,0],"number":3},"key":"tbl-datavar"},{"caption":"2.5.4.1.3 Vérification de la normalité avec des tests de normalité","order":{"section":[2,5,4,1,3,0,0],"number":24},"key":"sec-025413"},{"caption":"Distribution bêta","order":{"section":[2,4,3,16,0,0,0],"number":21},"key":"fig-fig268"},{"caption":"","order":{"section":[2,5,3,0,0,0,0],"number":21},"key":"eq-ecartype"},{"caption":"Graphique en violon, boîte à moustaches et intervalle interquartile","order":{"section":[2,5,3,0,0,0,0],"number":25},"key":"fig-univarie3"},{"caption":"2.5.1 Paramètres de tendance centrale","order":{"section":[2,5,1,0,0,0,0],"number":20},"key":"sec-0251"},{"caption":"Diagrammes quantile-quantile","order":{"section":[2,5,4,1,2,0,0],"number":30},"key":"fig-qqplot"},{"caption":"Distribution de Poisson avec excès de zéros","order":{"section":[2,4,3,7,0,0,0],"number":12},"key":"fig-fig259b"},{"caption":"Distribution Gamma","order":{"section":[2,4,3,15,0,0,0],"number":20},"key":"fig-fig267"},{"caption":"Distribution théorique d’un lancer de dé","order":{"section":[2,4,1,0,0,0,0],"number":3},"key":"fig-fig251"},{"caption":"Distribution géométrique","order":{"section":[2,4,3,4,0,0,0],"number":9},"key":"fig-fig257"},{"caption":"Dix-huit distributions essentielles, figure inspirée de @SeanOwendist","order":{"section":[2,4,3,0,0,0,0],"number":7},"key":"fig-distribs"},{"caption":"2.5.6.1 Application à une seule variable","order":{"section":[2,5,6,1,0,0,0],"number":30},"key":"sec-02561"},{"caption":"2.2.4 Données individuelles versus données agrégées","order":{"section":[2,2,4,0,0,0,0],"number":10},"key":"sec-0224"},{"caption":"Exemple d’agrégation de données individuelles","order":{"section":[2,2,4,0,0,0,0],"number":2},"key":"fig-univarie1b"},{"caption":"Distribution de Weibull","order":{"section":[2,4,3,17,0,0,0],"number":22},"key":"fig-fig269"},{"caption":"","order":{"section":[2,5,4,1,1,0,0],"number":27},"key":"eq-KurtType2"},{"caption":"2.1.2 Types de variables","order":{"section":[2,1,2,0,0,0,0],"number":3},"key":"sec-0212"},{"caption":"","order":{"section":[2,4,3,3,0,0,0],"number":4},"key":"eq-Binomial"},{"caption":"2.2.2 Données transversales versus données longitudinales","order":{"section":[2,2,2,0,0,0,0],"number":8},"key":"sec-0222"},{"caption":"","order":{"section":[2,4,3,7,0,0,0],"number":8},"key":"eq-poissonzi"},{"caption":"Distribution de Poisson","order":{"section":[2,4,3,6,0,0,0],"number":11},"key":"fig-fig259"},{"caption":"Types de variables","order":{"section":[2,1,2,0,0,0,0],"number":1},"key":"fig-univarie1"},{"caption":"","order":{"section":[2,5,4,1,1,0,0],"number":25},"key":"eq-SkewType3"},{"caption":"2.2 Types de données","order":{"section":[2,2,0,0,0,0,0],"number":6},"key":"sec-022"},{"caption":"Ajustement des distributions de Poisson et Poisson avec excès de zéros","order":{"section":[2,5,4,2,2,0,0],"number":34},"key":"fig-accmtldist"},{"caption":"","order":{"section":[2,4,3,9,0,0,0],"number":10},"key":"eq-skewgaussien"},{"caption":"","order":{"section":[2,5,5,2,0,0,0],"number":29},"key":"eq-scorez"},{"caption":"","order":{"section":[2,4,3,11,0,0,0],"number":12},"key":"eq-student"},{"caption":"2.4.3.16 Distribution bêta","order":{"section":[2,4,3,16,0,0,0],"number":18},"key":"sec-024316"},{"caption":"2.5.2 Paramètres de position","order":{"section":[2,5,2,0,0,0,0],"number":21},"key":"sec-0252"},{"caption":"Distribution log-gaussienne","order":{"section":[2,4,3,10,0,0,0],"number":15},"key":"fig-fig262"},{"caption":"2.1.2.2 Variables quantitatives","order":{"section":[2,1,2,2,0,0,0],"number":5},"key":"sec-02122"},{"caption":"Distribution empirique du nombre d’accidents par intersection impliquant un ou une cycliste à Montréal en 2017 dans les quartiers centraux","order":{"section":[2,5,4,2,2,0,0],"number":33},"key":"fig-accmtl"},{"caption":"2.3.2 Deux grandes familles de méthodes statistiques","order":{"section":[2,3,2,0,0,0,0],"number":13},"key":"sec-0232"},{"caption":"Distribution empirique d’un lancer de dé","order":{"section":[2,4,1,0,0,0,0],"number":5},"key":"fig-fig253"},{"caption":"","order":{"section":[2,4,3,14,0,0,0],"number":15},"key":"eq-exponentiel"}]} \ No newline at end of file diff --git a/.quarto/xref/e28e1e20 b/.quarto/xref/e28e1e20 new file mode 100644 index 0000000..bb8ebb7 --- /dev/null +++ b/.quarto/xref/e28e1e20 @@ -0,0 +1 @@ +{"entries":[{"order":{"number":1,"section":[12,0,0,0,0,0,0]},"key":"sec-chap12"},{"caption":"Graphiques personnalisés pour les valeurs propres","order":{"number":17,"section":[12,2,3,3,0,0,0]},"key":"fig-acpmesgraphs1"},{"caption":"Résultats de l’ACM pour les modalités des variables","order":{"number":23,"section":[12,4,1,2,0,0,0]},"key":"tbl-ACMValeursCoordTab"},{"caption":"Résultats de l’ACP pour les valeurs propres","order":{"number":4,"section":[12,2,2,1,0,0,0]},"key":"tbl-dataacpValeurPropres"},{"caption":"Variables et individus supplémentaires pour l’ACP","order":{"number":10,"section":[12,2,2,3,0,0,0]},"key":"fig-acpvarindcorrsuppl"},{"caption":"12.1.2 Bref historique des méthodes factorielles","order":{"number":3,"section":[12,1,2,0,0,0,0]},"key":"sec-1212"},{"caption":"Tableau pour une ACP","order":{"number":2,"section":[12,2,1,0,0,0,0]},"key":"fig-AnalysesFactoriellesTabACPFig"},{"caption":"Résultats de l’ACM pour les modalités des variables supplémentaires","order":{"number":24,"section":[12,4,1,2,0,0,0]},"key":"tbl-ACMValeursCoordSuppl"},{"caption":"Données relatives du tableau de contingence (fij)","order":{"number":11,"section":[12,3,1,0,0,0,0]},"key":"tbl-afcdataex2"},{"caption":"Graphiques pour les valeurs propres de l’ACP avec factoextra","order":{"number":11,"section":[12,2,3,2,0,0,0]},"key":"fig-factoextra1"},{"caption":"12.3.2.1 Résultats de l’AFC pour les valeurs propres","order":{"number":17,"section":[12,3,2,1,0,0,0]},"key":"sec-12321"},{"caption":"","order":{"number":1,"section":[12,2,1,0,0,0,0]},"key":"eq-ACPdistEuc"},{"caption":"Principe de base des analyses factorielles","order":{"number":1,"section":[12,0,0,0,0,0,0]},"key":"fig-AnalysesFactoriellesFig"},{"caption":"Matrice de corrélation de Pearson entre les variables utilisées pour l’ACP","order":{"number":6,"section":[12,2,2,2,0,0,0]},"key":"tbl-dataacpMatriceCorr"},{"caption":"Jeu de données utilisé pour l’analyse factorielle des correspondances","order":{"number":13,"section":[12,3,2,0,0,0,0]},"key":"tbl-dataAfc"},{"caption":"12.5 Quiz de révision du chapitre","order":{"number":32,"section":[12,5,0,0,0,0,0]},"key":"sec-125"},{"caption":"Premier plan factoriel de l’AFC pour les variables","order":{"number":26,"section":[12,3,2,2,0,0,0]},"key":"fig-afc1erplanfactVars"},{"caption":"Premier plan factoriel de l’ACM pour les individus avec coloration d’une variable avec factoextra","order":{"number":51,"section":[12,4,2,4,0,0,0]},"key":"fig-ACMPlanFactoInd2Facto"},{"caption":"Résultats de l’AFC pour les variables","order":{"number":17,"section":[12,3,2,2,0,0,0]},"key":"tbl-dataafcCoordVars"},{"caption":"12.2.2.1 Résultats de l’ACP pour les valeurs propres","order":{"number":7,"section":[12,2,2,1,0,0,0]},"key":"sec-12221"},{"caption":"12.2.2 Aides à l’interprétation","order":{"number":6,"section":[12,2,2,0,0,0,0]},"key":"sec-1222"},{"caption":"Trajectoires des variables ordinales sur le premier plan factoriel de l’ACM","order":{"number":49,"section":[12,4,2,3,0,0,0]},"key":"fig-ACMMiseEnOeuvreVars4"},{"caption":"12.4.1.2 Résultats de l’ACM pour les modalités des variables","order":{"number":25,"section":[12,4,1,2,0,0,0]},"key":"sec-12412"},{"caption":"Premier plan factoriel de l’ACM pour les modalités supplémentaires","order":{"number":48,"section":[12,4,2,3,0,0,0]},"key":"fig-ACMMiseEnOeuvreVars3"},{"caption":"Lieu de pèlerinage de R","order":{"number":34,"section":[12,4,0,0,0,0,0]},"key":"fig-AnalysesFactoriellesTabACM"},{"caption":"Premier plan factoriel de l’ACM pour les modalités","order":{"number":47,"section":[12,4,2,3,0,0,0]},"key":"fig-ACMMiseEnOeuvreVars2"},{"caption":"","order":{"number":10,"section":[12,3,2,2,0,0,0]},"key":"eq-CtrAFCInd"},{"caption":"Exemple de graphiques pour les résultats des modalités","order":{"number":46,"section":[12,4,2,3,0,0,0]},"key":"fig-ACMMiseEnOeuvreVars1"},{"caption":"12.3.2.2 Résultats de l’AFC pour les variables et les individus","order":{"number":18,"section":[12,3,2,2,0,0,0]},"key":"sec-12322"},{"caption":"12.4.2.3 Exploration graphique des résultats de l’ACM pour les modalités","order":{"number":30,"section":[12,4,2,3,0,0,0]},"key":"sec-124213"},{"caption":"Statistiques descriptives pour le jeu de données utilisé pour l’ACP","order":{"number":3,"section":[12,2,2,0,0,0,0]},"key":"tbl-dataacp"},{"caption":"Graphiques pour les valeurs propres de l’ACM avec factoextra","order":{"number":45,"section":[12,4,2,2,0,0,0]},"key":"fig-ACMCodePartie1VPc"},{"caption":"Graphique pour les valeurs propres de l’ACM avec factoextra","order":{"number":44,"section":[12,4,2,2,0,0,0]},"key":"fig-ACMCodePartie1VPb"},{"caption":"Graphique personnalisé avec la qualité des variables sur les axes retenus de l’ACP","order":{"number":21,"section":[12,2,3,3,0,0,0]},"key":"fig-acpmesgraphs5"},{"caption":"12.4.2.2 Exploration graphique des résultats de l’ACM pour les valeurs propres","order":{"number":29,"section":[12,4,2,2,0,0,0]},"key":"sec-124212"},{"caption":"Premier plan factoriel de l’ACM pour les modalités","order":{"number":38,"section":[12,4,1,2,0,0,0]},"key":"fig-ACMValeursPlanFacto1"},{"caption":"12.4.2 Mise en œuvre dans R","order":{"number":27,"section":[12,4,2,0,0,0,0]},"key":"sec-1242"},{"caption":"Premier plan factoriel de l’ACM pour les individus avec coloration d’une variable","order":{"number":43,"section":[12,4,1,3,0,0,0]},"key":"fig-ACMPlanFacto12Ind2"},{"caption":"12.3.2 Aides à l’interprétation","order":{"number":16,"section":[12,3,2,0,0,0,0]},"key":"sec-1232"},{"caption":"Exemple de tableau de contingence pour l’AFC","order":{"number":7,"section":[12,3,0,0,0,0,0]},"key":"tbl-encadreAFCACP1"},{"caption":"","order":{"number":7,"section":[12,3,2,2,0,0,0]},"key":"eq-CoordPropr1"},{"caption":"12.2.3.3 Personnalisation des graphiques avec les résultats de l’ACP","order":{"number":13,"section":[12,2,3,3,0,0,0]},"key":"sec-12233"},{"caption":"Tableau condensé (données brutes)","order":{"number":19,"section":[12,4,0,0,0,0,0]},"key":"tbl-ACM2"},{"caption":"Graphiques personnalisés avec les contributions des variables","order":{"number":19,"section":[12,2,3,3,0,0,0]},"key":"fig-acpmesgraphs3"},{"caption":"Premier plan factoriel de l’ACP pour les variables avec factoextra","order":{"number":15,"section":[12,2,3,2,0,0,0]},"key":"fig-factoextra5"},{"caption":"12.2.2.3 Résultats de l’ACP pour les individus","order":{"number":9,"section":[12,2,2,3,0,0,0]},"key":"sec-12223"},{"caption":"Corrélation, allongement du nuage de points et axes factoriels","order":{"number":3,"section":[12,2,1,0,0,0,0]},"key":"fig-liaisons2Vars"},{"caption":"12.3.3 Mise en œuvre dans R","order":{"number":19,"section":[12,3,3,0,0,0,0]},"key":"sec-1233"},{"caption":"Cartographie de coordonnées factorielles des individus pour l’AFC","order":{"number":27,"section":[12,3,2,2,0,0,0]},"key":"fig-afc1erplanfactInds2"},{"caption":"12.4.1.3 Résultats de l’ACM pour les individus","order":{"number":26,"section":[12,4,1,3,0,0,0]},"key":"sec-12413"},{"caption":"Trajectoires des variables ordinales sur le premier plan factoriel de l’ACM","order":{"number":41,"section":[12,4,1,2,0,0,0]},"key":"fig-ACMordinaleTrajectoire"},{"caption":"Premier plan factoriel de l’ACM avec toutes les modalités incluant celles supplémentaires","order":{"number":40,"section":[12,4,1,2,0,0,0]},"key":"fig-ACMValeursPlanFactoSupp1"},{"caption":"Trois principales méthodes factorielles","order":{"number":1,"section":[12,1,1,0,0,0,0]},"key":"tbl-typesanalysesfactorielles"},{"caption":"12.2.3.1 Calcul et exploration d’une ACP avec FactoMineR","order":{"number":11,"section":[12,2,3,1,0,0,0]},"key":"sec-12231"},{"caption":"","order":{"number":2,"section":[12,2,1,0,0,0,0]},"key":"eq-ACPcor"},{"caption":"Graphiques pour les résultats des modalités de l’axe 3 de l’ACM","order":{"number":39,"section":[12,4,1,2,0,0,0]},"key":"fig-ACMValeursCoordFig3"},{"caption":"12.1.1 Méthodes factorielles et types de données","order":{"number":2,"section":[12,1,1,0,0,0,0]},"key":"sec-1211"},{"caption":"Résultats de l’ACM pour les valeurs propres","order":{"number":22,"section":[12,4,1,1,0,0,0]},"key":"tbl-ACMValeursPropresTab"},{"caption":"Premier plan factoriel pour les individus","order":{"number":8,"section":[12,2,2,3,0,0,0]},"key":"fig-acp1erplanfactIndiv"},{"caption":"Histogramme des valeurs propres de l’AFC","order":{"number":25,"section":[12,3,2,1,0,0,0]},"key":"fig-afcGraphVP"},{"caption":"Cartographie des coordonnées factorielles des individus","order":{"number":9,"section":[12,2,2,3,0,0,0]},"key":"fig-acpcartoindiv"},{"caption":"12.3.1 Recherche d’une simplification basée sur la distance du khi-deux","order":{"number":15,"section":[12,3,1,0,0,0,0]},"key":"sec-1231"},{"caption":"12.4.2.1 Calcul d’une ACM avec FactoMineR","order":{"number":28,"section":[12,4,2,1,0,0,0]},"key":"sec-12421"},{"caption":"Cartographie des coordonnées factorielles des individus","order":{"number":22,"section":[12,2,3,3,0,0,0]},"key":"fig-acpmesgraphs6"},{"caption":"Graphiques personnalisés pour les valeurs propres pour l’ACP","order":{"number":5,"section":[12,2,2,1,0,0,0]},"key":"fig-acpgraphvp"},{"caption":"Graphiques pour les résultats des modalités de l’axe 2 de l’ACM","order":{"number":37,"section":[12,4,1,2,0,0,0]},"key":"fig-ACMValeursCoordFig2"},{"caption":"12.3.3.2 Exploration graphique des résultats de l’AFC avec factoextra","order":{"number":21,"section":[12,3,3,2,0,0,0]},"key":"sec-12332"},{"caption":"Graphiques pour les résultats des modalités de l’axe 1 de l’ACM","order":{"number":36,"section":[12,4,1,2,0,0,0]},"key":"fig-ACMValeursCoordFig1"},{"caption":"Tableau de contingence pour une AFC","order":{"number":23,"section":[12,3,0,0,0,0,0]},"key":"fig-AnalysesFactoriellesTabAFCFig"},{"caption":"12.4.1.1 Résultats de l’ACM pour les valeurs propres","order":{"number":24,"section":[12,4,1,1,0,0,0]},"key":"sec-12411"},{"caption":"Qualité des variables sur les trois premières composantes avec factoextra","order":{"number":14,"section":[12,2,3,2,0,0,0]},"key":"fig-factoextra4"},{"caption":"","order":{"number":3,"section":[12,2,1,0,0,0,0]},"key":"eq-ACPcov"},{"caption":"Variables qualitatives extraites du sondage sur l’agriculture urbaine de la Ville de Montréal","order":{"number":21,"section":[12,4,1,0,0,0,0]},"key":"tbl-dataACM"},{"caption":"12.4.1 Aides à l’interprétation","order":{"number":23,"section":[12,4,1,0,0,0,0]},"key":"sec-1241"},{"caption":"Premier plan factoriel de l’ACM pour les individus avec factoextra","order":{"number":50,"section":[12,4,2,4,0,0,0]},"key":"fig-ACMPlanFactoInd1Facto"},{"caption":"Exemple d’un tableau de contingence transformé (pourcentage en ligne) pour l’ACP","order":{"number":8,"section":[12,3,0,0,0,0,0]},"key":"tbl-encadreAFCACP2"},{"caption":"","order":{"number":4,"section":[12,2,2,1,0,0,0]},"key":"eq-scorezacpnormee"},{"caption":"Histogrammes personnalisés avec les coordonnées factorielles pour les variables","order":{"number":18,"section":[12,2,3,3,0,0,0]},"key":"fig-acpmesgraphs2"},{"caption":"12.4 Analyse de correspondances multiples (ACM)","order":{"number":22,"section":[12,4,0,0,0,0,0]},"key":"sec-124"},{"caption":"12.2.3.2 Exploration graphique des résultats de l’ACP avec factoextra","order":{"number":12,"section":[12,2,3,2,0,0,0]},"key":"sec-12232"},{"caption":"Contributions des variables avec factoextra","order":{"number":30,"section":[12,3,3,2,0,0,0]},"key":"fig-acp1erplanfactVars2a"},{"caption":"Cartographie de coordonnées factorielles des individus pour l’AFC","order":{"number":33,"section":[12,3,3,2,0,0,0]},"key":"fig-afc1erplanfactInds2B"},{"caption":"Profils des lignes et des colonnes","order":{"number":10,"section":[12,3,1,0,0,0,0]},"key":"tbl-afcProfilsLignesCols"},{"caption":"Ajout de modalités supplémentaires sur le premier plan factoriel l’AFC avec factoextra","order":{"number":32,"section":[12,3,3,2,0,0,0]},"key":"fig-afcAjoutModalites2"},{"caption":"Graphiques personnalisés avec les cosinus carrés des variables","order":{"number":20,"section":[12,2,3,3,0,0,0]},"key":"fig-acpmesgraphs4"},{"caption":"12.2 Analyses en composantes principales (ACP)","order":{"number":4,"section":[12,2,0,0,0,0,0]},"key":"sec-122"},{"caption":"12.1 Aperçu des méthodes factorielles","order":{"number":1,"section":[12,1,0,0,0,0,0]},"key":"sec-121"},{"caption":"Données brutes du tableau de contingence","order":{"number":9,"section":[12,3,1,0,0,0,0]},"key":"tbl-afcdataex1"},{"caption":"Graphiques pour les valeurs propres de l’AFC avec factoextra","order":{"number":29,"section":[12,3,3,2,0,0,0]},"key":"fig-factoextraAFC1"},{"caption":"Données fictives","order":{"number":2,"section":[12,2,1,0,0,0,0]},"key":"tbl-distanceACPindi"},{"caption":"12.3.3.1 Calcul d’une AFC avec FactoMineR","order":{"number":20,"section":[12,3,3,1,0,0,0]},"key":"sec-12331"},{"caption":"Ajout de modalités supplémentaires sur le premier plan factoriel de l’AFC","order":{"number":28,"section":[12,3,2,2,0,0,0]},"key":"fig-afcAjoutModalites"},{"caption":"Tableau disjonctif complet","order":{"number":20,"section":[12,4,0,0,0,0,0]},"key":"tbl-ACM3"},{"caption":"12.2.1 Recherche d’une simplification","order":{"number":5,"section":[12,2,1,0,0,0,0]},"key":"sec-1221"},{"caption":"Coordonnées factorielles des variables","order":{"number":6,"section":[12,2,2,2,0,0,0]},"key":"fig-acpgraphvarscoords"},{"caption":"","order":{"number":9,"section":[12,3,2,2,0,0,0]},"key":"eq-CtrAFCVar"},{"caption":"Premier plan factoriel de l’ACM pour les individus","order":{"number":42,"section":[12,4,1,3,0,0,0]},"key":"fig-ACMPlanFacto12Ind1"},{"caption":"12.2.2.2 Résultats de l’ACP pour les variables","order":{"number":8,"section":[12,2,2,2,0,0,0]},"key":"sec-12222"},{"caption":"12.4.2.4 Exploration graphique des résultats de l’ACM pour les individus","order":{"number":31,"section":[12,4,2,4,0,0,0]},"key":"sec-124214"},{"caption":"Résultats de l’AFC pour les valeurs propres","order":{"number":15,"section":[12,3,2,1,0,0,0]},"key":"tbl-dataafcValeurPropres"},{"caption":"Cartographie des dix variables utilisées pour l’ACP","order":{"number":4,"section":[12,2,2,0,0,0,0]},"key":"fig-datacartoacp"},{"caption":"Cartographie des modalités de la variable mode de transport utilisée pour l’AFC","order":{"number":24,"section":[12,3,2,0,0,0,0]},"key":"fig-cartovarAFC"},{"caption":"","order":{"number":6,"section":[12,3,1,0,0,0,0]},"key":"eq-khideuxcolonnes"},{"caption":"Premier plan factoriel de l’ACP pour les individus avec factoextra","order":{"number":16,"section":[12,2,3,2,0,0,0]},"key":"fig-factoextra6"},{"caption":"Résultats de l’ACP pour les variables","order":{"number":5,"section":[12,2,2,2,0,0,0]},"key":"tbl-dataacpCoordVars"},{"caption":"Premier plan factoriel de l’ACP pour les variables","order":{"number":7,"section":[12,2,2,2,0,0,0]},"key":"fig-acp1erplanfactVars"},{"caption":"Premier plan factoriel de l’AFC pour les variables et les individus avec factoextra","order":{"number":31,"section":[12,3,3,2,0,0,0]},"key":"fig-afc1erplanfactVars2b"},{"caption":"Contributions des variables à la deuxième composante avec factoextra","order":{"number":13,"section":[12,2,3,2,0,0,0]},"key":"fig-factoextra3"},{"caption":"Contributions des variables à la première composante avec factoextra","order":{"number":12,"section":[12,2,3,2,0,0,0]},"key":"fig-factoextra2"},{"caption":"Résultats du test du khi-deux sur le tableau de contingence","order":{"number":14,"section":[12,3,2,1,0,0,0]},"key":"tbl-dataafckhi2"},{"caption":"Exemple de variables qualitatives issues d’une enquête","order":{"number":18,"section":[12,4,0,0,0,0,0]},"key":"tbl-ACM1"},{"caption":"12.3 Analyse factorielle des correspondances (AFC)","order":{"number":14,"section":[12,3,0,0,0,0,0]},"key":"sec-123"},{"caption":"","order":{"number":8,"section":[12,3,2,2,0,0,0]},"key":"eq-CoordPropr2"},{"caption":"","order":{"number":5,"section":[12,3,1,0,0,0,0]},"key":"eq-khideuxlignes"},{"caption":"Graphiques pour les valeurs propres pour l’ACM","order":{"number":35,"section":[12,4,1,1,0,0,0]},"key":"fig-ACMValeursPropresFig"},{"caption":"Distances du khi-deux entre les modalités I et les modalités J","order":{"number":12,"section":[12,3,1,0,0,0,0]},"key":"tbl-MatriceDistKhi"},{"caption":"Vérification des deux propriétés des coordonnées factorielles pour les variables","order":{"number":16,"section":[12,3,2,2,0,0,0]},"key":"tbl-dataafcCoordVars2"},{"caption":"12.2.3 Mise en œuvre dans R","order":{"number":10,"section":[12,2,3,0,0,0,0]},"key":"sec-1223"}],"options":{"chapter-id":"sec-chap12","tbl-title":"Tableau","fig-title":"Figure","fig-prefix":"figure","sec-prefix":"section","tbl-prefix":"tableau","chapters":true,"eq-prefix":"équation","eq-title":"Équation"},"headings":["sec-121","sec-1211","sec-1212","sec-122","sec-1221","sec-1222","sec-12221","sec-12222","sec-12223","sec-1223","sec-12231","sec-12232","sec-12233","sec-123","sec-1231","sec-1232","sec-12321","sec-12322","sec-1233","sec-12331","sec-12332","sec-124","sec-1241","sec-12411","sec-12412","sec-12413","sec-1242","sec-12421","sec-124212","sec-124213","sec-124214","sec-125","sec-chap12"]} \ No newline at end of file diff --git a/.quarto/xref/e484d2c4 b/.quarto/xref/e484d2c4 new file mode 100644 index 0000000..47d0277 --- /dev/null +++ b/.quarto/xref/e484d2c4 @@ -0,0 +1 @@ +{"headings":["sec-011","sec-012","sec-0121","sec-0122","sec-0123","sec-01231","sec-01232","sec-01233","aide-disponible","sec-013","sec-0131","sec-0132","sec-0_133","sec-0134","sec-0135","sec-01351","sec-01352","sec-01353","sec-0136","sec-01361","sec-01362","sec-01363","sec-01364","sec-01365","sec-014","sec-0141","sec-01411","sec-01412","sec-01413","sec-01414","sec-01415","sec-01416","sec-0142","sec-01421","sec-01422","sec-014221","sec-014222","sec-014223","sec-014224","sec-01423","sec-01424","sec-01425","sec-014251","sec-014252","sec-014253","sec-014254","sec-01426","sec-014261","sec-014262","sec-014263","sec-014264","sec-01427","sec-014271","sec-014272","sec-01428","sec-014281","sec-014282","sec-014283","sec-01429","sec-014291","sec-014292","sec-016","sec-017","sec-018","sec-019","sec-0110","sec-chap01"],"options":{"chapters":true,"fig-title":"Figure","tbl-prefix":"tableau","eq-prefix":"équation","chapter-id":"sec-chap01","sec-prefix":"section","fig-prefix":"figure","eq-title":"Équation","tbl-title":"Tableau"},"entries":[{"order":{"number":1,"section":[1,0,0,0,0,0,0]},"key":"sec-chap01"},{"caption":"1.4.2.5.2 Remplacement du texte","order":{"number":43,"section":[1,4,2,5,2,0,0]},"key":"sec-014252"},{"caption":"1.4.2.7.1 Cas binaire avec ifelse","order":{"number":52,"section":[1,4,2,7,1,0,0]},"key":"sec-014271"},{"caption":"1.4.2.7 Recodage des variables","order":{"number":51,"section":[1,4,2,7,0,0,0]},"key":"sec-01427"},{"caption":"1.4.1.4 Lecture d’un fichier sav (SPSS)","order":{"number":29,"section":[1,4,1,4,0,0,0]},"key":"sec-01414"},{"caption":"1.4.2.2.1 Sélection d’une colonne","order":{"number":35,"section":[1,4,2,2,1,0,0]},"key":"sec-014221"},{"caption":"Opérateurs mathématiques","order":{"number":1,"section":[1,3,5,1,0,0,0]},"key":"tbl-OperateurMath"},{"caption":"RStudio avec le style pastel on dark","order":{"number":6,"section":[1,2,2,0,0,0,0]},"key":"fig-fig07"},{"caption":"1.4 Manipulation de données","order":{"number":24,"section":[1,4,0,0,0,0,0]},"key":"sec-014"},{"caption":"Navigation dans des sections de codes avec RStudio","order":{"number":17,"section":[1,5,0,0,0,0,0]},"key":"fig-sectionsRstudio"},{"caption":"1.4.2.6.1 Du texte à la date","order":{"number":47,"section":[1,4,2,6,1,0,0]},"key":"sec-014261"},{"caption":"1.2 Environnement de travail","order":{"number":2,"section":[1,2,0,0,0,0,0]},"key":"sec-012"},{"caption":"1.4.2.2.4 Modification du nom des colonnes","order":{"number":38,"section":[1,4,2,2,4,0,0]},"key":"sec-014224"},{"caption":"1.2.3 Installation et chargement un package","order":{"number":5,"section":[1,2,3,0,0,0,0]},"key":"sec-0123"},{"caption":"1.4.2.9.2 Jointure de DataFrames","order":{"number":60,"section":[1,4,2,9,2,0,0]},"key":"sec-014292"},{"caption":"Temps nécessaire pour lire les données en fonction du type de fichiers","order":{"number":5,"section":[1,4,1,6,0,0,0]},"key":"tbl-tableduration"},{"caption":"1.9 Quiz de révision du chapitre","order":{"number":65,"section":[1,9,0,0,0,0,0]},"key":"sec-0110"},{"caption":"1.4.2.4 Fonctions mathématiques","order":{"number":40,"section":[1,4,2,4,0,0,0]},"key":"sec-01424"},{"caption":"Structure de dossier recommandée pour un projet avec R","order":{"number":18,"section":[1,5,0,0,0,0,0]},"key":"fig-structFolder"},{"caption":"1.3.5.3 Opérateurs logiques","order":{"number":17,"section":[1,3,5,3,0,0,0]},"key":"sec-01353"},{"caption":"1.4.2.6.4 Fuseau horaire","order":{"number":50,"section":[1,4,2,6,4,0,0]},"key":"sec-014264"},{"caption":"1.4.2 Manipulation d’un DataFrame","order":{"number":32,"section":[1,4,2,0,0,0,0]},"key":"sec-0142"},{"caption":"1.4.1.6 Lecture d’un fichier xlsx (Excel)","order":{"number":31,"section":[1,4,1,6,0,0,0]},"key":"sec-01416"},{"caption":"1.4.2.5.4 Concaténation du texte","order":{"number":45,"section":[1,4,2,5,4,0,0]},"key":"sec-014254"},{"caption":"Lieu de pèlerinage de R","order":{"number":1,"section":[1,1,0,0,0,0,0]},"key":"fig-Plaque"},{"caption":"1.1 Histoire et philosophie de R","order":{"number":1,"section":[1,1,0,0,0,0,0]},"key":"sec-011"},{"caption":"1.4.2.5.1 Majuscules et minuscules","order":{"number":42,"section":[1,4,2,5,1,0,0]},"key":"sec-014251"},{"caption":"1.3.6.2 Matrices","order":{"number":20,"section":[1,3,6,2,0,0,0]},"key":"sec-01362"},{"caption":"Métaphore sur les langages et programmes d’analyse statistique","order":{"number":3,"section":[1,1,0,0,0,0,0]},"key":"fig-fig03"},{"caption":"1.4.2.6 Manipulation des colonnes de type date","order":{"number":46,"section":[1,4,2,6,0,0,0]},"key":"sec-01426"},{"caption":"Description des packages","order":{"number":9,"section":[1,2,4,0,0,0,0]},"key":"fig-fig010"},{"caption":"1.3.6.4 DataFrames","order":{"number":22,"section":[1,3,6,4,0,0,0]},"key":"sec-01364"},{"caption":"Fusion de DataFrames","order":{"number":15,"section":[1,4,2,9,1,0,0]},"key":"fig-fig016"},{"caption":"Environnement de base de RStudio","order":{"number":5,"section":[1,2,2,0,0,0,0]},"key":"fig-fig06"},{"caption":"1.3.2 Objets et expressions","order":{"number":11,"section":[1,3,2,0,0,0,0]},"key":"sec-0132"},{"caption":"1.4.2.2.3 Suppression de colonnes","order":{"number":37,"section":[1,4,2,2,3,0,0]},"key":"sec-014223"},{"caption":"1.6 Enregistrement des résultats","order":{"number":62,"section":[1,6,0,0,0,0,0]},"key":"sec-017"},{"caption":"1.4.2.5 Fonctions pour manipuler des chaînes de caractères","order":{"number":41,"section":[1,4,2,5,0,0,0]},"key":"sec-01425"},{"caption":"Opérateurs logiques","order":{"number":3,"section":[1,3,5,3,0,0,0]},"key":"tbl-tableOperateurLogi"},{"caption":"Ressources pertinente pour en apprendre plus sur R","order":{"number":7,"section":[1,8,0,0,0,0,0]},"key":"tbl-tableRessources"},{"caption":"1.8 Conclusion et ressources pertinentes","order":{"number":64,"section":[1,8,0,0,0,0,0]},"key":"sec-019"},{"caption":"1.7 Session de travail","order":{"number":63,"section":[1,7,0,0,0,0,0]},"key":"sec-018"},{"caption":"Bouton charger un fichier RDA","order":{"number":20,"section":[1,6,0,0,0,0,0]},"key":"fig-loadobj"},{"caption":"Bouton enregistrer la session","order":{"number":19,"section":[1,6,0,0,0,0,0]},"key":"fig-saveobj"},{"caption":"Exécuter du code dans RStudio","order":{"number":8,"section":[1,2,2,0,0,0,0]},"key":"fig-fig09"},{"caption":"1.5 Code R bien structuré","order":{"number":61,"section":[1,5,0,0,0,0,0]},"key":"sec-016"},{"caption":"Jointure de DataFrames","order":{"number":16,"section":[1,4,2,9,2,0,0]},"key":"fig-fig017"},{"caption":"1.4.2.6.3 Calcul d’une durée entre deux datetime","order":{"number":49,"section":[1,4,2,6,3,0,0]},"key":"sec-014263"},{"caption":"1.4.2.9.1 Fusion de DataFrames par ajout","order":{"number":59,"section":[1,4,2,9,1,0,0]},"key":"sec-014291"},{"caption":"1.4.2.9 Fusion de DataFrames","order":{"number":58,"section":[1,4,2,9,0,0,0]},"key":"sec-01429"},{"caption":"1.3.4 Principaux types de données","order":{"number":13,"section":[1,3,4,0,0,0,0]},"key":"sec-0134"},{"caption":"Avantages et inconvénients du tidyverse","order":{"number":6,"section":[1,4,2,1,0,0,0]},"key":"tbl-Tidyverse"},{"caption":"1.4.2.1 Petit mot sur le tidyverse","order":{"number":33,"section":[1,4,2,1,0,0,0]},"key":"sec-01421"},{"caption":"1.2.3.3 Chargement d’un package","order":{"number":8,"section":[1,2,3,3,0,0,0]},"key":"sec-01233"},{"caption":"Répartition temporelle des accidents à vélo","order":{"number":14,"section":[1,4,2,6,3,0,0]},"key":"fig-fig015"},{"caption":"Fenêtres de RStudio","order":{"number":7,"section":[1,2,2,0,0,0,0]},"key":"fig-fig08"},{"caption":"1.4.2.6.2 Extraction des informations d’une date","order":{"number":48,"section":[1,4,2,6,2,0,0]},"key":"sec-014262"},{"caption":"1.3.5.1 Opérateurs mathématiques","order":{"number":15,"section":[1,3,5,1,0,0,0]},"key":"sec-01351"},{"caption":"1.4.2.8.2 Sous-sélection des colonnes","order":{"number":56,"section":[1,4,2,8,2,0,0]},"key":"sec-014282"},{"caption":"1.4.2.8.1 Sous-sélection des lignes","order":{"number":55,"section":[1,4,2,8,1,0,0]},"key":"sec-014281"},{"caption":"1.2.2 Environnement RStudio","order":{"number":4,"section":[1,2,2,0,0,0,0]},"key":"sec-0122"},{"caption":"1.4.2.8 Sous-sélection d’un DataFrame","order":{"number":54,"section":[1,4,2,8,0,0,0]},"key":"sec-01428"},{"caption":"1.4.2.2 Gestion des colonnes d’un DataFrame","order":{"number":34,"section":[1,4,2,2,0,0,0]},"key":"sec-01422"},{"caption":"1.4.2.7.2 Cas multiple avec la case_when","order":{"number":53,"section":[1,4,2,7,2,0,0]},"key":"sec-014272"},{"caption":"1.4.1.1 Lecture d’un fichier csv","order":{"number":26,"section":[1,4,1,1,0,0,0]},"key":"sec-01411"},{"caption":"1.3.1 Hello World!","order":{"number":10,"section":[1,3,1,0,0,0,0]},"key":"sec-0131"},{"caption":"1.4.2.3 Calcul de nouvelles variables","order":{"number":39,"section":[1,4,2,3,0,0,0]},"key":"sec-01423"},{"caption":"1.3.6 Structures de données","order":{"number":18,"section":[1,3,6,0,0,0,0]},"key":"sec-0136"},{"caption":"Du vecteur à la matrice","order":{"number":11,"section":[1,3,6,2,0,0,0]},"key":"fig-fig012"},{"caption":"1.4.2.5.3 Découpage du texte","order":{"number":44,"section":[1,4,2,5,3,0,0]},"key":"sec-014253"},{"caption":"1.3.6.5 Listes","order":{"number":23,"section":[1,3,6,5,0,0,0]},"key":"sec-01365"},{"caption":"1.3.5 Opérateurs","order":{"number":14,"section":[1,3,5,0,0,0,0]},"key":"sec-0135"},{"caption":"De la donnée au DataFrame","order":{"number":13,"section":[1,3,6,4,0,0,0]},"key":"fig-fig013"},{"caption":"Arguments de la fonction round","order":{"number":10,"section":[1,3,3,0,0,0,0]},"key":"fig-fig011"},{"caption":"Nombre d’articles trouvés sur Google Scholar (source : Robert A. Muenchen)","order":{"number":2,"section":[1,1,0,0,0,0,0]},"key":"fig-ArticlesR"},{"caption":"1.2.3.2 Installation d’un package depuis GitHub","order":{"number":7,"section":[1,2,3,2,0,0,0]},"key":"sec-01232"},{"caption":"1.3.6.3 Arrays","order":{"number":21,"section":[1,3,6,3,0,0,0]},"key":"sec-01363"},{"caption":"1.3.3 Fonctions et arguments","order":{"number":12,"section":[1,3,3,0,0,0,0]},"key":"sec-0_133"},{"caption":"1.4.1.3 Lecture d’un fichier dta (Stata)","order":{"number":28,"section":[1,4,1,3,0,0,0]},"key":"sec-01413"},{"caption":"Opérateurs relationnels","order":{"number":2,"section":[1,3,5,2,0,0,0]},"key":"tbl-OperateurRelationnels"},{"caption":"1.3.6.1 Vecteurs","order":{"number":19,"section":[1,3,6,1,0,0,0]},"key":"sec-01361"},{"caption":"1.4.2.8.3 Sélection des colonnes et des lignes","order":{"number":57,"section":[1,4,2,8,3,0,0]},"key":"sec-014283"},{"caption":"Premier DataFrame","order":{"number":4,"section":[1,3,6,4,0,0,0]},"key":"tbl-tabfirsttable"},{"caption":"1.4.1 Chargement d’un DataFrame depuis un fichier","order":{"number":25,"section":[1,4,1,0,0,0,0]},"key":"sec-0141"},{"caption":"1.4.1.2 Lecture d’un fichier dbase","order":{"number":27,"section":[1,4,1,2,0,0,0]},"key":"sec-01412"},{"caption":"1.4.1.5 Lecture d’un fichier sas7bdat (SAS)","order":{"number":30,"section":[1,4,1,5,0,0,0]},"key":"sec-01415"},{"caption":"1.2.1 Installation de R","order":{"number":3,"section":[1,2,1,0,0,0,0]},"key":"sec-0121"},{"caption":"1.3 Bases du langage R","order":{"number":9,"section":[1,3,0,0,0,0,0]},"key":"sec-013"},{"caption":"1.2.3.1 Installation d’un package depuis CRAN","order":{"number":6,"section":[1,2,3,1,0,0,0]},"key":"sec-01231"},{"caption":"Console de base de R","order":{"number":4,"section":[1,2,1,0,0,0,0]},"key":"fig-fig05"},{"caption":"1.3.5.2 Opérateurs relationnels","order":{"number":16,"section":[1,3,5,2,0,0,0]},"key":"sec-01352"},{"caption":"1.4.2.2.2 Sélection de plusieurs colonnes","order":{"number":36,"section":[1,4,2,2,2,0,0]},"key":"sec-014222"}]} \ No newline at end of file diff --git a/01-priseenmainR.qmd b/01-priseenmainR.qmd index a6fe822..37afc6c 100644 --- a/01-priseenmainR.qmd +++ b/01-priseenmainR.qmd @@ -35,7 +35,7 @@ R a été créé par Ross Ihaka et Robert Gentleman à l'Université d'Auckland R a cependant réussi à s'imposer tant dans le milieu de la recherche que dans le secteur privé. Pour s'en convaincre, il suffit de lire l'excellent article concernant la popularité des logiciels d'analyse de données tiré du site [r4stats.com](http://r4stats.com/articles/popularity){target="_blank"} (@fig-ArticlesR). -![Nombre d'articles trouvés sur Google Scholar (source : Robert A. Muenchen)](images/chap01/r_citations.jpg){#fig-ArticlesR width="50%" fig-align="center"} +![Nombre d'articles trouvés sur Google Scholar (source : Robert A. Muenchen)](images/Chap01/r_citations.jpg){#fig-ArticlesR width="50%" fig-align="center"} Les nombreux atouts de R justifient largement sa popularité sans cesse croissante : @@ -73,7 +73,7 @@ Pour conclure cette section, l'illustration partagée sur Twitter par Darren L D (@fig-fig03) : R apparaît clairement comme une communauté hétéroclite, mais diversifiée et adaptable. -![Métaphore sur les langages et programmes d'analyse statistique](images/chap01/softwares_and_cars.jpeg){#fig-fig03 width="60%" fig-align="center"} +![Métaphore sur les langages et programmes d'analyse statistique](images/Chap01/softwares_and_cars.jpeg){#fig-fig03 width="60%" fig-align="center"} Dans ce livre, nous détaillons les *packages* utilisés dans chaque section avec un encadré spécifique. @@ -101,7 +101,7 @@ Dans cette section, nous vous proposons une visite de l'environnement de travail La première étape pour travailler avec R est bien sûr de l'installer. Pour cela, il suffit de visiter le site web de [CRAN](https://cran.r-project.org/){target="_blank"} et de télécharger la dernière version de R en fonction de votre système d'exploitation : Windows, Linux ou Mac. Une fois installé, si vous démarrez R immédiatement, vous aurez accès à une console, plutôt rudimentaire, attendant sagement vos instructions (@fig-fig05). -![Console de base de R](images/chap01/r_console.jpeg){#fig-fig05 width="85%" fig-align="center"} +![Console de base de R](images/Chap01/r_console.jpeg){#fig-fig05 width="85%" fig-align="center"} Notez que vous pouvez aussi télécharger des versions plus anciennes de R en allant sur ce [lien](https://cran.r-project.org/bin/windows/base/old/){target="_blank"}. Cela peut être intéressant lorsque vous voulez reproduire des résultats d'une autre étude ou que certains *packages* ne sont plus disponibles dans les nouvelles versions. @@ -110,7 +110,7 @@ Notez que vous pouvez aussi télécharger des versions plus anciennes de R en al Rares sont les adeptes de R qui préfèrent travailler directement avec la console classique. Nous vous recommandons vivement d'utiliser RStudio, un environnement de développement (*IDE*) dédié à R offrant une intégration très intéressante d'une console, d'un éditeur de texte, d'une fenêtre de visualisation des données et d'une autre pour les graphiques, d'un accès à la documentation, etc. En d'autres termes, si R est un vélo minimaliste, RStudio permet d'y rajouter des freins, des vitesses, un porte-bagages, des garde-boues et une selle confortable. Vous pouvez [télécharger](https://rstudio.com/products/rstudio/download){target="_blank"} et installer RStudio sur Windows, Linux et Mac. La version de base est gratuite, mais l'entreprise qui développe ce logiciel propose aussi des versions commerciales du logiciel qui assurent essentiellement une assistance technique. Il existe d'autres environnements de développement pour travailler avec R (Visual Studio Code, Jupyter, Tinn-R, Radiant, RIDE, etc.), mais RStudio offre à ce jour la meilleure option en termes de facilité d'installation, de prise en main et de fonctionnalités proposées (voir l'interface de RStudio à la @fig-fig06). -![Environnement de base de RStudio](images/chap01/r_studio_01.jpeg){#fig-fig06 width="85%" fig-align="center"} +![Environnement de base de RStudio](images/Chap01/r_studio_01.jpeg){#fig-fig06 width="85%" fig-align="center"} Avant d'aller plus loin, notez que : @@ -119,7 +119,7 @@ Avant d'aller plus loin, notez que : * L'aspect de RStudio peut être modifié en naviguant dans l'onglet *Tools/Global Options* et dans le volet *Appearance*. Nous avons une préférence pour le mode sombre avec le style *pastel on dark* (@fig-fig07), mais libre à vous de choisir le style qui vous convient. -![RStudio avec le style pastel on dark](images/chap01/r_studio_02.jpeg){#fig-fig07 width="85%" fig-align="center"} +![RStudio avec le style pastel on dark](images/Chap01/r_studio_02.jpeg){#fig-fig07 width="85%" fig-align="center"} Une fois ces détails réglés, vous pouvez ouvrir votre première feuille de code en allant dans l'onglet *File/New File/R Script*. Votre environnement est maintenant découpé en quatre fenêtres (@fig-fig08) : @@ -132,7 +132,7 @@ Une fois ces détails réglés, vous pouvez ouvrir votre première feuille de co 4. La fenêtre de l'aide, des graphiques et de l'explorateur de fichiers. Vous pouvez accéder ici à la documentation de R et des *packages* que vous utilisez, aux sorties graphiques que vous produisez et aux dossiers de votre environnement de travail. -![Fenêtres de RStudio](images/chap01/r_studio_03.jpeg){#fig-fig08 width="85%" fig-align="center"} +![Fenêtres de RStudio](images/Chap01/r_studio_03.jpeg){#fig-fig08 width="85%" fig-align="center"} Prenons un bref exemple : tapez la syntaxe suivante dans l'éditeur de code (fenêtre 1 à la @fig-fig08) : @@ -144,7 +144,7 @@ ma_somme <- 4+4 Sélectionnez ensuite cette syntaxe (mettre en surbrillance avec la souris) et utilisez le raccourci *Ctrl+Entrée* ou cliquez sur le bouton *Run* (avec la flèche verte) pour envoyer cette syntaxe à la console qui l'exécutera immédiatement. Notez que rien ne se passe tant que le code n'est pas envoyé à la console. Il s'agit donc de deux étapes distinctes : écrire son code, puis l'envoyer à la console. Constatez également qu'un objet *ma_somme* est apparu dans votre environnement et que sa valeur est bien 8. Votre console se « souvient » de cette valeur : elle est actuellement stockée dans votre mémoire vive sous le nom de *ma_somme* (@fig-fig09). -![Exécuter du code dans RStudio](images/chap01/r_studio_04.jpeg){#fig-fig09 width="85%" fig-align="center"} +![Exécuter du code dans RStudio](images/Chap01/r_studio_04.jpeg){#fig-fig09 width="85%" fig-align="center"} Pour conclure cette section, nous vous invitons à enregistrer votre première syntaxe R (*File/Save As*) dans un fichier **.R** que vous pouvez appeler `mon_premier_script.R` par exemple. Fermez ensuite RStudio, redémarrez-le et ouvrez (*File/Open File*) votre fichier `mon_premier_script.R`. Vous pouvez constater que votre code est toujours présent, mais que votre environnement est vide tant que vous n'exécutez pas votre syntaxe. En effet, lorsque vous fermez RStudio, l'environnement est vidé pour libérer de la mémoire vive. Cela peut poser problème lorsque certains codes sont très longs à exécuter, nous verrons donc plus tard comment enregistrer l'environnement en cours pour le recharger par la suite. @@ -207,7 +207,7 @@ Cela signifie que le *package* que vous tentez de charger n'est pas encore insta Lorsque vous installez des *packages* dans R, vous téléchargez aussi leur documentation. Tous les *packages* de *CRAN* disposent d'une documentation, ce qui n'est pas forcément vrai pour ceux sur *GitHub*. Dans RStudio, vous pouvez accéder à la documentation des *packages* dans l'onglet **Packages** (@fig-fig010). Vous pouvez utiliser la barre de recherche pour retrouver rapidement un *package* installé. Si vous cliquez sur le nom du *package*, vous accédez directement à sa documentation dans cette fenêtre. -![Description des packages](images/chap01/rstudio_packages.jpeg){#fig-fig010 width="45%" fig-align="center"} +![Description des packages](images/Chap01/rstudio_packages.jpeg){#fig-fig010 width="45%" fig-align="center"} Vous pouvez également accéder à ces informations en utilisant la syntaxe suivante dans votre console : @@ -319,7 +319,7 @@ round(taille) Pour effectuer leurs opérations, les fonctions ont généralement besoin d'**arguments**. Ici, `taille` est un argument passé à la fonction `round`. Si nous regardons la documentation de `round` avec `help(round)` (@fig-fig011), nous constatons que cette fonction prend en réalité deux arguments : *x* et *digits*. Le premier est le nombre que nous souhaitons arrondir et le second est le nombre de décimales à conserver. Nous pouvons lire dans la documentation que la valeur par défaut de *digits* est 0, ce qui explique que `round(taille)` a produit le résultat de 176. -![Arguments de la fonction `round`](images/chap01/help_round.jpeg){#fig-fig011 width="35%" fig-align="center"} +![Arguments de la fonction `round`](images/Chap01/help_round.jpeg){#fig-fig011 width="35%" fig-align="center"} Réutilisons maintenant la fonction `round`, mais en gardant une décimale : @@ -670,7 +670,7 @@ print(dim(matrice2)) Comme vous pouvez le constater, la fonction `cbind` permet de concaténer des vecteurs comme s'ils étaient les colonnes d'une matrice, alors que `rbind` les combine comme s'ils étaient les lignes d'une matrice. La @fig-fig012 présente graphiquement le passage du vecteur à la matrice. -![Du vecteur à la matrice](images/chap01/vecteur_to_matrix.png){#fig-fig012 width="30%" fig-align="center"} +![Du vecteur à la matrice](images/Chap01/vecteur_to_matrix.png){#fig-fig012 width="30%" fig-align="center"} Notez que vous pouvez transposer une matrice avec la fonction `t`. Si nous essayons maintenant de comparer la matrice 1 à la matrice 2 nous allons avoir une erreur, car elles n'ont pas les mêmes dimensions. @@ -694,7 +694,7 @@ Le résultat souligne bien que nous avons les mêmes valeurs dans les deux matri S'il est rare de travailler avec des matrices, il est encore plus rare de manipuler des *arrays*. Un *array* est une matrice spéciale qui peut avoir plus que deux dimensions. Un cas simple serait un *array* en trois dimensions : lignes, colonnes, profondeur, que nous pourrions représenter comme un cube, ou une série de matrices de mêmes dimensions et empilées. Au-delà de trois dimensions, il devient difficile de les représenter mentalement. Cette structure de données peut être utilisée pour représenter les différentes bandes spectrales d'une image satellitaire. Les lignes et les colonnes délimiteraient les pixels de l'image et la profondeur délimiterait les différentes bandes composant l'image (@fig-fig012). -![Un array avec trois dimensions](images/chap01/array.png){#fig-fig013 width="15%" fig-align="center"} +![Un array avec trois dimensions](images/Chap01/array.png){#fig-fig013 width="15%" fig-align="center"} Créons un *array* en combinant trois matrices avec la fonction `array`. Chacune de ces matrices est composée respectivement de 1, de 2 et de 3 et a une dimension de 5 x 5. L'*array* final a donc une dimension de 5 x 5 x 3. @@ -737,7 +737,7 @@ knitr::kable(df, Dans RStudio, vous pouvez visualiser votre tableau de données avec la fonction `View(df)`. Comme vous pouvez le constater, chaque vecteur est devenu une colonne de votre tableau de données *df*. La @fig-fig013 résume ce passage d'une simple donnée à un *DataFrame* en passant par un vecteur. -![De la donnée au DataFrame](images/chap01/vecteur_to_dataframe.png){#fig-fig013 width="25%" fig-align="center"} +![De la donnée au DataFrame](images/Chap01/vecteur_to_dataframe.png){#fig-fig013 width="25%" fig-align="center"} Plusieurs fonctions de base de R fournissent des informations importantes sur un *DataFrame* : @@ -1629,7 +1629,7 @@ Terminons cette section avec la fusion de *DataFrames*. Nous distinguons deux m Ajouter deux *DataFrames* peut se faire en fonction de leurs colonnes ou en fonction de leurs lignes. Dans ces deux cas, nous utilisons respectivement les fonctions `cbind` et `rbind`. La @fig-fig016 résume graphiquement le fonctionnement des deux fonctions. -![Fusion de DataFrames](images/chap01/rbind_cbind.png){#fig-fig016 width="30%" fig-align="center"} +![Fusion de DataFrames](images/Chap01/rbind_cbind.png){#fig-fig016 width="30%" fig-align="center"} Pour que `cbind` fonctionne, il faut que les deux *DataFrames* aient le même nombre de lignes. Pour `rbind`, les deux *DataFrames* doivent avoir le même nombre de colonnes. Prenons à nouveau comme exemple le jeu de données iris. Nous commençons par le séparer en trois sous-jeux de données comprenant chacun une espèce d'iris. Puis, nous fusionnons deux d'entre eux avec la fonction `rbind`. @@ -1668,7 +1668,7 @@ Une jointure est une opération un peu plus complexe qu'un simple ajout. L'idée Ces trois jointures sont présentées à la @fig-fig017; pour ces trois cas, la colonne commune se nomme *id*. -![Jointure de DataFrames](images/chap01/merging.png){#fig-fig017 width="30%" fig-align="center"} +![Jointure de DataFrames](images/Chap01/merging.png){#fig-fig017 width="30%" fig-align="center"} Vous retiendrez que les deux dernières jointures peuvent produire des valeurs manquantes. Pour réaliser ces opérations, nous utilisons la fonction `merge`. Prenons un exemple simple à partir d'un petit jeu de données. @@ -1828,12 +1828,12 @@ summary_all_num_cols <- function(dataset){ #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ``` -![Navigation dans des sections de codes avec RStudio](images/chap01/sections_rstudio.png){#fig-sectionsRstudio width="100%" fig-align="center"} +![Navigation dans des sections de codes avec RStudio](images/Chap01/sections_rstudio.png){#fig-sectionsRstudio width="100%" fig-align="center"} 8. **Adopter une structure globale pour vos projets** : au-delà du script, il est nécessaire de bien structurer vos projets, le plus important étant d'utiliser une structure commune à chaque projet pour vous faciliter le travail. Nous proposons à la @fig-structFolder un exemple de structure assez générale pouvant être utilisée dans la plupart des cas. Elle sépare notamment les données originales des données structurées, ainsi que les fonctions complémentaires et la structuration des données du principal bloc d'analyse. -![Structure de dossier recommandée pour un projet avec R](images/chap01/structurationprojet.png){#fig-structFolder width="50%" fig-align="center"} +![Structure de dossier recommandée pour un projet avec R](images/Chap01/structurationprojet.png){#fig-structFolder width="50%" fig-align="center"} **Ne négligez jamais l'importance d'un code bien écrit et documenté !** @@ -1854,7 +1854,7 @@ save.image(file = 'chemin/vers/mon/fichier/session.RData', compress = TRUE) Vous pouvez aussi utiliser le bouton d'enregistrement dans l'onglet *Environnement* dans RStudio (@fig-saveobj). -![Bouton enregistrer la session](images/chap01/save_session.png){#fig-saveobj width="25%" fig-align="center"} +![Bouton enregistrer la session](images/Chap01/save_session.png){#fig-saveobj width="25%" fig-align="center"} Il est recommandé de compresser ces fichiers (`compress = TRUE`) pour minimiser leur taille. Pour n'enregistrer que certains objets (ici `iris` et `noms_cols`), vous pouvez adapter cette syntaxe : @@ -1872,7 +1872,7 @@ load(file = 'chemin/vers/mon/fichier/mes_objet.RData') ou d'utiliser le bouton *ouvrir* de l'onglet *Environnement* dans RStudio (@fig-loadobj). -![Bouton charger un fichier RDA](images/chap01/load_session.png){#fig-loadobj width="25%" fig-align="center"} +![Bouton charger un fichier RDA](images/Chap01/load_session.png){#fig-loadobj width="25%" fig-align="center"} ## Session de travail {#sec-018} diff --git a/01-priseenmainR_files/figure-html/fig-fig015-1.png b/01-priseenmainR_files/figure-html/fig-fig015-1.png new file mode 100644 index 0000000..4f175ee Binary files /dev/null and b/01-priseenmainR_files/figure-html/fig-fig015-1.png differ diff --git a/02-univarie_files/figure-html/fig-CourbeNormale-1.png b/02-univarie_files/figure-html/fig-CourbeNormale-1.png new file mode 100644 index 0000000..623bcf6 Binary files /dev/null and b/02-univarie_files/figure-html/fig-CourbeNormale-1.png differ diff --git a/02-univarie_files/figure-html/fig-GTranf-1.png b/02-univarie_files/figure-html/fig-GTranf-1.png new file mode 100644 index 0000000..7b69641 Binary files /dev/null and b/02-univarie_files/figure-html/fig-GTranf-1.png differ diff --git a/02-univarie_files/figure-html/fig-GcourbeNormale-1.png b/02-univarie_files/figure-html/fig-GcourbeNormale-1.png new file mode 100644 index 0000000..7f5c783 Binary files /dev/null and b/02-univarie_files/figure-html/fig-GcourbeNormale-1.png differ diff --git a/02-univarie_files/figure-html/fig-GraphiquesFreq1-1.png b/02-univarie_files/figure-html/fig-GraphiquesFreq1-1.png new file mode 100644 index 0000000..986eb97 Binary files /dev/null and b/02-univarie_files/figure-html/fig-GraphiquesFreq1-1.png differ diff --git a/02-univarie_files/figure-html/fig-accmtl-1.png b/02-univarie_files/figure-html/fig-accmtl-1.png new file mode 100644 index 0000000..73eed28 Binary files /dev/null and b/02-univarie_files/figure-html/fig-accmtl-1.png differ diff --git a/02-univarie_files/figure-html/fig-accmtldist-1.png b/02-univarie_files/figure-html/fig-accmtldist-1.png new file mode 100644 index 0000000..bc2838c Binary files /dev/null and b/02-univarie_files/figure-html/fig-accmtldist-1.png differ diff --git a/02-univarie_files/figure-html/fig-asymetrie-1.png b/02-univarie_files/figure-html/fig-asymetrie-1.png new file mode 100644 index 0000000..bd0988f Binary files /dev/null and b/02-univarie_files/figure-html/fig-asymetrie-1.png differ diff --git a/02-univarie_files/figure-html/fig-bustrt-1.png b/02-univarie_files/figure-html/fig-bustrt-1.png new file mode 100644 index 0000000..640f08e Binary files /dev/null and b/02-univarie_files/figure-html/fig-bustrt-1.png differ diff --git a/02-univarie_files/figure-html/fig-bustrt2-1.png b/02-univarie_files/figure-html/fig-bustrt2-1.png new file mode 100644 index 0000000..63459bc Binary files /dev/null and b/02-univarie_files/figure-html/fig-bustrt2-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig251-1.png b/02-univarie_files/figure-html/fig-fig251-1.png new file mode 100644 index 0000000..8469c1e Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig251-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig252-1.png b/02-univarie_files/figure-html/fig-fig252-1.png new file mode 100644 index 0000000..8e7c9a2 Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig252-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig253-1.png b/02-univarie_files/figure-html/fig-fig253-1.png new file mode 100644 index 0000000..ac0a35c Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig253-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig254-1.png b/02-univarie_files/figure-html/fig-fig254-1.png new file mode 100644 index 0000000..1ab3504 Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig254-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig256-1.png b/02-univarie_files/figure-html/fig-fig256-1.png new file mode 100644 index 0000000..e9bdfe2 Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig256-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig257-1.png b/02-univarie_files/figure-html/fig-fig257-1.png new file mode 100644 index 0000000..e18687d Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig257-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig258-1.png b/02-univarie_files/figure-html/fig-fig258-1.png new file mode 100644 index 0000000..2595998 Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig258-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig259-1.png b/02-univarie_files/figure-html/fig-fig259-1.png new file mode 100644 index 0000000..13e1c0c Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig259-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig259b-1.png b/02-univarie_files/figure-html/fig-fig259b-1.png new file mode 100644 index 0000000..05809bf Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig259b-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig260-1.png b/02-univarie_files/figure-html/fig-fig260-1.png new file mode 100644 index 0000000..f94e80a Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig260-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig261-1.png b/02-univarie_files/figure-html/fig-fig261-1.png new file mode 100644 index 0000000..e14660b Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig261-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig262-1.png b/02-univarie_files/figure-html/fig-fig262-1.png new file mode 100644 index 0000000..5333fcf Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig262-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig263-1.png b/02-univarie_files/figure-html/fig-fig263-1.png new file mode 100644 index 0000000..98edec5 Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig263-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig264-1.png b/02-univarie_files/figure-html/fig-fig264-1.png new file mode 100644 index 0000000..a880d08 Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig264-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig265-1.png b/02-univarie_files/figure-html/fig-fig265-1.png new file mode 100644 index 0000000..b0f1a97 Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig265-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig266-1.png b/02-univarie_files/figure-html/fig-fig266-1.png new file mode 100644 index 0000000..62ae973 Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig266-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig267-1.png b/02-univarie_files/figure-html/fig-fig267-1.png new file mode 100644 index 0000000..71cc8be Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig267-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig268-1.png b/02-univarie_files/figure-html/fig-fig268-1.png new file mode 100644 index 0000000..15c377c Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig268-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig269-1.png b/02-univarie_files/figure-html/fig-fig269-1.png new file mode 100644 index 0000000..e59b2c8 Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig269-1.png differ diff --git a/02-univarie_files/figure-html/fig-fig270-1.png b/02-univarie_files/figure-html/fig-fig270-1.png new file mode 100644 index 0000000..46850c2 Binary files /dev/null and b/02-univarie_files/figure-html/fig-fig270-1.png differ diff --git a/02-univarie_files/figure-html/fig-kurtosis-1.png b/02-univarie_files/figure-html/fig-kurtosis-1.png new file mode 100644 index 0000000..1e53c30 Binary files /dev/null and b/02-univarie_files/figure-html/fig-kurtosis-1.png differ diff --git a/02-univarie_files/figure-html/fig-qqplot-1.png b/02-univarie_files/figure-html/fig-qqplot-1.png new file mode 100644 index 0000000..abdcb6b Binary files /dev/null and b/02-univarie_files/figure-html/fig-qqplot-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-colorBrewer-1.png b/03-magiedesgraphiques_files/figure-html/fig-colorBrewer-1.png new file mode 100644 index 0000000..075edf8 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-colorBrewer-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig31-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig31-1.png new file mode 100644 index 0000000..d84ef21 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig31-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig310-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig310-1.png new file mode 100644 index 0000000..819a446 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig310-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig311-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig311-1.png new file mode 100644 index 0000000..901a429 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig311-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig312-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig312-1.png new file mode 100644 index 0000000..40fe3ce Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig312-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig313-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig313-1.png new file mode 100644 index 0000000..702452f Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig313-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig314-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig314-1.png new file mode 100644 index 0000000..62ab33d Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig314-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig315-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig315-1.png new file mode 100644 index 0000000..b6f53eb Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig315-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig316-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig316-1.png new file mode 100644 index 0000000..1f1586d Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig316-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig317-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig317-1.png new file mode 100644 index 0000000..79d02b6 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig317-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig318-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig318-1.png new file mode 100644 index 0000000..bfe33ce Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig318-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig32-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig32-1.png new file mode 100644 index 0000000..dedcd8e Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig32-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig320-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig320-1.png new file mode 100644 index 0000000..3b4ffad Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig320-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig321-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig321-1.png new file mode 100644 index 0000000..8ffaca8 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig321-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig322-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig322-1.png new file mode 100644 index 0000000..fc0047f Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig322-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig323-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig323-1.png new file mode 100644 index 0000000..92e9a42 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig323-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig324-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig324-1.png new file mode 100644 index 0000000..5af1ad0 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig324-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig325-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig325-1.png new file mode 100644 index 0000000..c380a5a Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig325-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig326-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig326-1.png new file mode 100644 index 0000000..b623018 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig326-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig328-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig328-1.png new file mode 100644 index 0000000..4927497 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig328-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig329-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig329-1.png new file mode 100644 index 0000000..a751a8a Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig329-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig33-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig33-1.png new file mode 100644 index 0000000..dedcd8e Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig33-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig330-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig330-1.png new file mode 100644 index 0000000..811674a Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig330-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig331-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig331-1.png new file mode 100644 index 0000000..72a5f17 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig331-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig332-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig332-1.png new file mode 100644 index 0000000..2d40048 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig332-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig333-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig333-1.png new file mode 100644 index 0000000..287ab61 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig333-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig334-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig334-1.png new file mode 100644 index 0000000..85b0c33 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig334-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig335-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig335-1.png new file mode 100644 index 0000000..4ef6044 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig335-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig336-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig336-1.png new file mode 100644 index 0000000..3b3f8b4 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig336-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig337-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig337-1.png new file mode 100644 index 0000000..2c1b4e8 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig337-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig338-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig338-1.png new file mode 100644 index 0000000..13a27d0 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig338-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig339-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig339-1.png new file mode 100644 index 0000000..c5451e0 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig339-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig34-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig34-1.png new file mode 100644 index 0000000..388f232 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig34-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig340-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig340-1.png new file mode 100644 index 0000000..ba575a8 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig340-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig341-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig341-1.png new file mode 100644 index 0000000..b6d1e00 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig341-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig342-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig342-1.png new file mode 100644 index 0000000..33f2ba4 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig342-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig344-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig344-1.png new file mode 100644 index 0000000..0138824 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig344-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig345-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig345-1.png new file mode 100644 index 0000000..7be6798 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig345-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig346-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig346-1.png new file mode 100644 index 0000000..123f7ef Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig346-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig347-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig347-1.png new file mode 100644 index 0000000..9f98b51 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig347-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig348-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig348-1.png new file mode 100644 index 0000000..d86e788 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig348-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig35-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig35-1.png new file mode 100644 index 0000000..71fa62a Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig35-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig352-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig352-1.png new file mode 100644 index 0000000..ada62c0 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig352-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig353-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig353-1.png new file mode 100644 index 0000000..2620cd3 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig353-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig354-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig354-1.png new file mode 100644 index 0000000..77b949a Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig354-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig355-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig355-1.png new file mode 100644 index 0000000..379c2a8 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig355-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig36-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig36-1.png new file mode 100644 index 0000000..5d03cd3 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig36-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig37-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig37-1.png new file mode 100644 index 0000000..045e237 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig37-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig38-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig38-1.png new file mode 100644 index 0000000..6a7dceb Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig38-1.png differ diff --git a/03-magiedesgraphiques_files/figure-html/fig-fig39-1.png b/03-magiedesgraphiques_files/figure-html/fig-fig39-1.png new file mode 100644 index 0000000..c428138 Binary files /dev/null and b/03-magiedesgraphiques_files/figure-html/fig-fig39-1.png differ diff --git a/04-bivarieeQuantiQuanti_files/figure-html/fig-PearsonSpearmanKendall-1.png b/04-bivarieeQuantiQuanti_files/figure-html/fig-PearsonSpearmanKendall-1.png new file mode 100644 index 0000000..51cb3da Binary files /dev/null and b/04-bivarieeQuantiQuanti_files/figure-html/fig-PearsonSpearmanKendall-1.png differ diff --git a/04-bivarieeQuantiQuanti_files/figure-html/fig-ValExtremes-1.png b/04-bivarieeQuantiQuanti_files/figure-html/fig-ValExtremes-1.png new file mode 100644 index 0000000..5ef95d9 Binary files /dev/null and b/04-bivarieeQuantiQuanti_files/figure-html/fig-ValExtremes-1.png differ diff --git a/04-bivarieeQuantiQuanti_files/figure-html/fig-coefCorrVar-1.png b/04-bivarieeQuantiQuanti_files/figure-html/fig-coefCorrVar-1.png new file mode 100644 index 0000000..28835f5 Binary files /dev/null and b/04-bivarieeQuantiQuanti_files/figure-html/fig-coefCorrVar-1.png differ diff --git a/04-bivarieeQuantiQuanti_files/figure-html/fig-coeffPearson-1.png b/04-bivarieeQuantiQuanti_files/figure-html/fig-coeffPearson-1.png new file mode 100644 index 0000000..25fefa2 Binary files /dev/null and b/04-bivarieeQuantiQuanti_files/figure-html/fig-coeffPearson-1.png differ diff --git a/04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot1-1.png b/04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot1-1.png new file mode 100644 index 0000000..b06471a Binary files /dev/null and b/04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot1-1.png differ diff --git a/04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot2-1.png b/04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot2-1.png new file mode 100644 index 0000000..c373b52 Binary files /dev/null and b/04-bivarieeQuantiQuanti_files/figure-html/fig-corrplot2-1.png differ diff --git a/04-bivarieeQuantiQuanti_files/figure-html/fig-covariance-1.png b/04-bivarieeQuantiQuanti_files/figure-html/fig-covariance-1.png new file mode 100644 index 0000000..eb56942 Binary files /dev/null and b/04-bivarieeQuantiQuanti_files/figure-html/fig-covariance-1.png differ diff --git a/04-bivarieeQuantiQuanti_files/figure-html/fig-fig9-1.png b/04-bivarieeQuantiQuanti_files/figure-html/fig-fig9-1.png new file mode 100644 index 0000000..f9257dc Binary files /dev/null and b/04-bivarieeQuantiQuanti_files/figure-html/fig-fig9-1.png differ diff --git a/04-bivarieeQuantiQuanti_files/figure-html/fig-reg-1.png b/04-bivarieeQuantiQuanti_files/figure-html/fig-reg-1.png new file mode 100644 index 0000000..2ba680c Binary files /dev/null and b/04-bivarieeQuantiQuanti_files/figure-html/fig-reg-1.png differ diff --git a/04-bivarieeQuantiQuanti_files/figure-html/fig-reg2-1.png b/04-bivarieeQuantiQuanti_files/figure-html/fig-reg2-1.png new file mode 100644 index 0000000..3c2088d Binary files /dev/null and b/04-bivarieeQuantiQuanti_files/figure-html/fig-reg2-1.png differ diff --git a/05-bivarieeQualiQuali_files/figure-html/fig-VDC-1.png b/05-bivarieeQualiQuali_files/figure-html/fig-VDC-1.png new file mode 100644 index 0000000..3bb2e1d Binary files /dev/null and b/05-bivarieeQualiQuali_files/figure-html/fig-VDC-1.png differ diff --git a/06-bivarieeQualiQuanti_files/figure-html/fig-Anova1a-1.png b/06-bivarieeQualiQuanti_files/figure-html/fig-Anova1a-1.png new file mode 100644 index 0000000..034c23c Binary files /dev/null and b/06-bivarieeQualiQuanti_files/figure-html/fig-Anova1a-1.png differ diff --git a/06-bivarieeQualiQuanti_files/figure-html/fig-Anova1b-1.png b/06-bivarieeQualiQuanti_files/figure-html/fig-Anova1b-1.png new file mode 100644 index 0000000..d90efb5 Binary files /dev/null and b/06-bivarieeQualiQuanti_files/figure-html/fig-Anova1b-1.png differ diff --git a/06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot-1.png b/06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot-1.png new file mode 100644 index 0000000..a37ff74 Binary files /dev/null and b/06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot-1.png differ diff --git a/06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot2-1.png b/06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot2-1.png new file mode 100644 index 0000000..70cb6cf Binary files /dev/null and b/06-bivarieeQualiQuanti_files/figure-html/fig-Qqplot2-1.png differ diff --git a/06-bivarieeQualiQuanti_files/figure-html/fig-ttest1-1.png b/06-bivarieeQualiQuanti_files/figure-html/fig-ttest1-1.png new file mode 100644 index 0000000..9a2dd35 Binary files /dev/null and b/06-bivarieeQualiQuanti_files/figure-html/fig-ttest1-1.png differ diff --git a/06-bivarieeQualiQuanti_files/figure-html/fig-ttest2-1.png b/06-bivarieeQualiQuanti_files/figure-html/fig-ttest2-1.png new file mode 100644 index 0000000..d027205 Binary files /dev/null and b/06-bivarieeQualiQuanti_files/figure-html/fig-ttest2-1.png differ diff --git a/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-4-1.png b/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-4-1.png new file mode 100644 index 0000000..58a82af Binary files /dev/null and b/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-4-1.png differ diff --git a/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-1.png b/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-1.png new file mode 100644 index 0000000..3c8f10d Binary files /dev/null and b/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-1.png differ diff --git a/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-2.png b/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-2.png new file mode 100644 index 0000000..5b221e9 Binary files /dev/null and b/06-bivarieeQualiQuanti_files/figure-html/unnamed-chunk-6-2.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-DiaGraphCookLev-1.png b/07-regressionlineaire_files/figure-html/fig-DiaGraphCookLev-1.png new file mode 100644 index 0000000..0e6832f Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-DiaGraphCookLev-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-DiaHomoscedasticite-1.png b/07-regressionlineaire_files/figure-html/fig-DiaHomoscedasticite-1.png new file mode 100644 index 0000000..7b3643a Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-DiaHomoscedasticite-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-EffetMarginalDich-1.png b/07-regressionlineaire_files/figure-html/fig-EffetMarginalDich-1.png new file mode 100644 index 0000000..a24196f Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-EffetMarginalDich-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-EffetMarginalDichCode-1.png b/07-regressionlineaire_files/figure-html/fig-EffetMarginalDichCode-1.png new file mode 100644 index 0000000..69f202e Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-EffetMarginalDichCode-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-EffetMarginalPoly-1.png b/07-regressionlineaire_files/figure-html/fig-EffetMarginalPoly-1.png new file mode 100644 index 0000000..ae28913 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-EffetMarginalPoly-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-EffetMarginalPolyT-1.png b/07-regressionlineaire_files/figure-html/fig-EffetMarginalPolyT-1.png new file mode 100644 index 0000000..cde3e82 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-EffetMarginalPolyT-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLog-1.png b/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLog-1.png new file mode 100644 index 0000000..d2061da Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLog-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLogEtNon-1.png b/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLogEtNon-1.png new file mode 100644 index 0000000..3eae679 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariableLogEtNon-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariablesContinues-1.png b/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariablesContinues-1.png new file mode 100644 index 0000000..26c99fc Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-EffetMarginalVariablesContinues-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-GraphCookLev-1.png b/07-regressionlineaire_files/figure-html/fig-GraphCookLev-1.png new file mode 100644 index 0000000..3ddbff0 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-GraphCookLev-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-HomosComp-1.png b/07-regressionlineaire_files/figure-html/fig-HomosComp-1.png new file mode 100644 index 0000000..5555008 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-HomosComp-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat-1.png b/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat-1.png new file mode 100644 index 0000000..faceaed Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat2-1.png b/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat2-1.png new file mode 100644 index 0000000..ad0ad2b Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heat2-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heatex-1.png b/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heatex-1.png new file mode 100644 index 0000000..9ec3040 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-ModeleInteraction2heatex-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaire-1.png b/07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaire-1.png new file mode 100644 index 0000000..5712667 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaire-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaireeffectex-1.png b/07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaireeffectex-1.png new file mode 100644 index 0000000..5712667 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-ModeleInteractionBinaireeffectex-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-ResidusCompa-1.png b/07-regressionlineaire_files/figure-html/fig-ResidusCompa-1.png new file mode 100644 index 0000000..6fe353e Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-ResidusCompa-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-Titi-1.png b/07-regressionlineaire_files/figure-html/fig-Titi-1.png new file mode 100644 index 0000000..555cde4 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-Titi-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-VerifierHomoscedasticite-1.png b/07-regressionlineaire_files/figure-html/fig-VerifierHomoscedasticite-1.png new file mode 100644 index 0000000..29df78c Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-VerifierHomoscedasticite-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidus-1.png b/07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidus-1.png new file mode 100644 index 0000000..d1866f0 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidus-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidusDia-1.png b/07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidusDia-1.png new file mode 100644 index 0000000..55a87da Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-VerifierNormaliteResidusDia-1.png differ diff --git a/07-regressionlineaire_files/figure-html/fig-calculRegPoly2-1.png b/07-regressionlineaire_files/figure-html/fig-calculRegPoly2-1.png new file mode 100644 index 0000000..9ff8a64 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/fig-calculRegPoly2-1.png differ diff --git a/07-regressionlineaire_files/figure-html/unnamed-chunk-45-1.png b/07-regressionlineaire_files/figure-html/unnamed-chunk-45-1.png new file mode 100644 index 0000000..7b3643a Binary files /dev/null and b/07-regressionlineaire_files/figure-html/unnamed-chunk-45-1.png differ diff --git a/07-regressionlineaire_files/figure-html/unnamed-chunk-53-1.png b/07-regressionlineaire_files/figure-html/unnamed-chunk-53-1.png new file mode 100644 index 0000000..5555008 Binary files /dev/null and b/07-regressionlineaire_files/figure-html/unnamed-chunk-53-1.png differ diff --git a/08-GLM_files/figure-html/fig-CookdCotePropor-1.png b/08-GLM_files/figure-html/fig-CookdCotePropor-1.png new file mode 100644 index 0000000..41ef3a1 Binary files /dev/null and b/08-GLM_files/figure-html/fig-CookdCotePropor-1.png differ diff --git a/08-GLM_files/figure-html/fig-agebinom-1.png b/08-GLM_files/figure-html/fig-agebinom-1.png new file mode 100644 index 0000000..e817841 Binary files /dev/null and b/08-GLM_files/figure-html/fig-agebinom-1.png differ diff --git a/08-GLM_files/figure-html/fig-arrondgamma-1.png b/08-GLM_files/figure-html/fig-arrondgamma-1.png new file mode 100644 index 0000000..addd3b0 Binary files /dev/null and b/08-GLM_files/figure-html/fig-arrondgamma-1.png differ diff --git a/08-GLM_files/figure-html/fig-betaArrond-1.png b/08-GLM_files/figure-html/fig-betaArrond-1.png new file mode 100644 index 0000000..7573ac9 Binary files /dev/null and b/08-GLM_files/figure-html/fig-betaArrond-1.png differ diff --git a/08-GLM_files/figure-html/fig-betaFR-1.png b/08-GLM_files/figure-html/fig-betaFR-1.png new file mode 100644 index 0000000..e87a01e Binary files /dev/null and b/08-GLM_files/figure-html/fig-betaFR-1.png differ diff --git a/08-GLM_files/figure-html/fig-compnbdistr2-1.png b/08-GLM_files/figure-html/fig-compnbdistr2-1.png new file mode 100644 index 0000000..8dfc888 Binary files /dev/null and b/08-GLM_files/figure-html/fig-compnbdistr2-1.png differ diff --git a/08-GLM_files/figure-html/fig-comppoissdistr-1.png b/08-GLM_files/figure-html/fig-comppoissdistr-1.png new file mode 100644 index 0000000..a1cc869 Binary files /dev/null and b/08-GLM_files/figure-html/fig-comppoissdistr-1.png differ diff --git a/08-GLM_files/figure-html/fig-comppoissdistr2-1.png b/08-GLM_files/figure-html/fig-comppoissdistr2-1.png new file mode 100644 index 0000000..540dde1 Binary files /dev/null and b/08-GLM_files/figure-html/fig-comppoissdistr2-1.png differ diff --git a/08-GLM_files/figure-html/fig-compzipdistr-1.png b/08-GLM_files/figure-html/fig-compzipdistr-1.png new file mode 100644 index 0000000..f3d4daa Binary files /dev/null and b/08-GLM_files/figure-html/fig-compzipdistr-1.png differ diff --git a/08-GLM_files/figure-html/fig-cookdistGLMbinom-1.png b/08-GLM_files/figure-html/fig-cookdistGLMbinom-1.png new file mode 100644 index 0000000..a24f6fe Binary files /dev/null and b/08-GLM_files/figure-html/fig-cookdistGLMbinom-1.png differ diff --git a/08-GLM_files/figure-html/fig-cookdistGLMbinom2-1.png b/08-GLM_files/figure-html/fig-cookdistGLMbinom2-1.png new file mode 100644 index 0000000..40eff1d Binary files /dev/null and b/08-GLM_files/figure-html/fig-cookdistGLMbinom2-1.png differ diff --git a/08-GLM_files/figure-html/fig-cookdistbeta-1.png b/08-GLM_files/figure-html/fig-cookdistbeta-1.png new file mode 100644 index 0000000..06c1ea4 Binary files /dev/null and b/08-GLM_files/figure-html/fig-cookdistbeta-1.png differ diff --git a/08-GLM_files/figure-html/fig-cookdistbeta2-1.png b/08-GLM_files/figure-html/fig-cookdistbeta2-1.png new file mode 100644 index 0000000..f0eab5c Binary files /dev/null and b/08-GLM_files/figure-html/fig-cookdistbeta2-1.png differ diff --git a/08-GLM_files/figure-html/fig-cookdistbeta3-1.png b/08-GLM_files/figure-html/fig-cookdistbeta3-1.png new file mode 100644 index 0000000..295970a Binary files /dev/null and b/08-GLM_files/figure-html/fig-cookdistbeta3-1.png differ diff --git a/08-GLM_files/figure-html/fig-cookdistgamma-1.png b/08-GLM_files/figure-html/fig-cookdistgamma-1.png new file mode 100644 index 0000000..6959779 Binary files /dev/null and b/08-GLM_files/figure-html/fig-cookdistgamma-1.png differ diff --git a/08-GLM_files/figure-html/fig-cookdistgamma2-1.png b/08-GLM_files/figure-html/fig-cookdistgamma2-1.png new file mode 100644 index 0000000..e6057b3 Binary files /dev/null and b/08-GLM_files/figure-html/fig-cookdistgamma2-1.png differ diff --git a/08-GLM_files/figure-html/fig-cookdistnb-1.png b/08-GLM_files/figure-html/fig-cookdistnb-1.png new file mode 100644 index 0000000..acc2bde Binary files /dev/null and b/08-GLM_files/figure-html/fig-cookdistnb-1.png differ diff --git a/08-GLM_files/figure-html/fig-cookdistnb2-1.png b/08-GLM_files/figure-html/fig-cookdistnb2-1.png new file mode 100644 index 0000000..70e2014 Binary files /dev/null and b/08-GLM_files/figure-html/fig-cookdistnb2-1.png differ diff --git a/08-GLM_files/figure-html/fig-cookmultinom-1.png b/08-GLM_files/figure-html/fig-cookmultinom-1.png new file mode 100644 index 0000000..2904141 Binary files /dev/null and b/08-GLM_files/figure-html/fig-cookmultinom-1.png differ diff --git a/08-GLM_files/figure-html/fig-diagresnb-1.png b/08-GLM_files/figure-html/fig-diagresnb-1.png new file mode 100644 index 0000000..e91b740 Binary files /dev/null and b/08-GLM_files/figure-html/fig-diagresnb-1.png differ diff --git a/08-GLM_files/figure-html/fig-diagressimcumul-1.png b/08-GLM_files/figure-html/fig-diagressimcumul-1.png new file mode 100644 index 0000000..704c5be Binary files /dev/null and b/08-GLM_files/figure-html/fig-diagressimcumul-1.png differ diff --git a/08-GLM_files/figure-html/fig-diagzip2-1.png b/08-GLM_files/figure-html/fig-diagzip2-1.png new file mode 100644 index 0000000..9f80117 Binary files /dev/null and b/08-GLM_files/figure-html/fig-diagzip2-1.png differ diff --git a/08-GLM_files/figure-html/fig-dispgamma-1.png b/08-GLM_files/figure-html/fig-dispgamma-1.png new file mode 100644 index 0000000..dcfe187 Binary files /dev/null and b/08-GLM_files/figure-html/fig-dispgamma-1.png differ diff --git a/08-GLM_files/figure-html/fig-distancegamma-1.png b/08-GLM_files/figure-html/fig-distancegamma-1.png new file mode 100644 index 0000000..9166275 Binary files /dev/null and b/08-GLM_files/figure-html/fig-distancegamma-1.png differ diff --git a/08-GLM_files/figure-html/fig-distripoissmod-1.png b/08-GLM_files/figure-html/fig-distripoissmod-1.png new file mode 100644 index 0000000..ef12162 Binary files /dev/null and b/08-GLM_files/figure-html/fig-distripoissmod-1.png differ diff --git a/08-GLM_files/figure-html/fig-equlibresensispeci-1.png b/08-GLM_files/figure-html/fig-equlibresensispeci-1.png new file mode 100644 index 0000000..5652cbc Binary files /dev/null and b/08-GLM_files/figure-html/fig-equlibresensispeci-1.png differ diff --git a/08-GLM_files/figure-html/fig-gammadatadistrib-1.png b/08-GLM_files/figure-html/fig-gammadatadistrib-1.png new file mode 100644 index 0000000..6ae9ab8 Binary files /dev/null and b/08-GLM_files/figure-html/fig-gammadatadistrib-1.png differ diff --git a/08-GLM_files/figure-html/fig-gammaresids-1.png b/08-GLM_files/figure-html/fig-gammaresids-1.png new file mode 100644 index 0000000..6c0f5d0 Binary files /dev/null and b/08-GLM_files/figure-html/fig-gammaresids-1.png differ diff --git a/08-GLM_files/figure-html/fig-gammaresids2-1.png b/08-GLM_files/figure-html/fig-gammaresids2-1.png new file mode 100644 index 0000000..1a426be Binary files /dev/null and b/08-GLM_files/figure-html/fig-gammaresids2-1.png differ diff --git a/08-GLM_files/figure-html/fig-gammaresids3-1.png b/08-GLM_files/figure-html/fig-gammaresids3-1.png new file mode 100644 index 0000000..96e8bbb Binary files /dev/null and b/08-GLM_files/figure-html/fig-gammaresids3-1.png differ diff --git a/08-GLM_files/figure-html/fig-gausscook-1.png b/08-GLM_files/figure-html/fig-gausscook-1.png new file mode 100644 index 0000000..f99df15 Binary files /dev/null and b/08-GLM_files/figure-html/fig-gausscook-1.png differ diff --git a/08-GLM_files/figure-html/fig-gausscook2-1.png b/08-GLM_files/figure-html/fig-gausscook2-1.png new file mode 100644 index 0000000..055d799 Binary files /dev/null and b/08-GLM_files/figure-html/fig-gausscook2-1.png differ diff --git a/08-GLM_files/figure-html/fig-gaussresid-1.png b/08-GLM_files/figure-html/fig-gaussresid-1.png new file mode 100644 index 0000000..7e0baf1 Binary files /dev/null and b/08-GLM_files/figure-html/fig-gaussresid-1.png differ diff --git a/08-GLM_files/figure-html/fig-gausssim-1.png b/08-GLM_files/figure-html/fig-gausssim-1.png new file mode 100644 index 0000000..4f973fc Binary files /dev/null and b/08-GLM_files/figure-html/fig-gausssim-1.png differ diff --git a/08-GLM_files/figure-html/fig-gausssim2-1.png b/08-GLM_files/figure-html/fig-gausssim2-1.png new file mode 100644 index 0000000..790abdb Binary files /dev/null and b/08-GLM_files/figure-html/fig-gausssim2-1.png differ diff --git a/08-GLM_files/figure-html/fig-heuresgamma-1.png b/08-GLM_files/figure-html/fig-heuresgamma-1.png new file mode 100644 index 0000000..e96e5a1 Binary files /dev/null and b/08-GLM_files/figure-html/fig-heuresgamma-1.png differ diff --git a/08-GLM_files/figure-html/fig-histopriceairbnb-1.png b/08-GLM_files/figure-html/fig-histopriceairbnb-1.png new file mode 100644 index 0000000..d765bda Binary files /dev/null and b/08-GLM_files/figure-html/fig-histopriceairbnb-1.png differ diff --git a/08-GLM_files/figure-html/fig-linearbinom-1.png b/08-GLM_files/figure-html/fig-linearbinom-1.png new file mode 100644 index 0000000..04dd039 Binary files /dev/null and b/08-GLM_files/figure-html/fig-linearbinom-1.png differ diff --git a/08-GLM_files/figure-html/fig-linearbinom2-1.png b/08-GLM_files/figure-html/fig-linearbinom2-1.png new file mode 100644 index 0000000..b5b5893 Binary files /dev/null and b/08-GLM_files/figure-html/fig-linearbinom2-1.png differ diff --git a/08-GLM_files/figure-html/fig-linearbinom3-1.png b/08-GLM_files/figure-html/fig-linearbinom3-1.png new file mode 100644 index 0000000..e8c0d2f Binary files /dev/null and b/08-GLM_files/figure-html/fig-linearbinom3-1.png differ diff --git a/08-GLM_files/figure-html/fig-paysbinom-1.png b/08-GLM_files/figure-html/fig-paysbinom-1.png new file mode 100644 index 0000000..6845b7f Binary files /dev/null and b/08-GLM_files/figure-html/fig-paysbinom-1.png differ diff --git a/08-GLM_files/figure-html/fig-poisscookdist-1.png b/08-GLM_files/figure-html/fig-poisscookdist-1.png new file mode 100644 index 0000000..ebed630 Binary files /dev/null and b/08-GLM_files/figure-html/fig-poisscookdist-1.png differ diff --git a/08-GLM_files/figure-html/fig-poisscookdist2-1.png b/08-GLM_files/figure-html/fig-poisscookdist2-1.png new file mode 100644 index 0000000..b134f69 Binary files /dev/null and b/08-GLM_files/figure-html/fig-poisscookdist2-1.png differ diff --git a/08-GLM_files/figure-html/fig-predpricecatveg-1.png b/08-GLM_files/figure-html/fig-predpricecatveg-1.png new file mode 100644 index 0000000..8eb451e Binary files /dev/null and b/08-GLM_files/figure-html/fig-predpricecatveg-1.png differ diff --git a/08-GLM_files/figure-html/fig-residsimbeta-1.png b/08-GLM_files/figure-html/fig-residsimbeta-1.png new file mode 100644 index 0000000..e6ba333 Binary files /dev/null and b/08-GLM_files/figure-html/fig-residsimbeta-1.png differ diff --git a/08-GLM_files/figure-html/fig-residsimbeta3-1.png b/08-GLM_files/figure-html/fig-residsimbeta3-1.png new file mode 100644 index 0000000..4d5c837 Binary files /dev/null and b/08-GLM_files/figure-html/fig-residsimbeta3-1.png differ diff --git a/08-GLM_files/figure-html/fig-residsimbeta4-1.png b/08-GLM_files/figure-html/fig-residsimbeta4-1.png new file mode 100644 index 0000000..eb4dfcd Binary files /dev/null and b/08-GLM_files/figure-html/fig-residsimbeta4-1.png differ diff --git a/08-GLM_files/figure-html/fig-residsimbinomHistoUnif-1.png b/08-GLM_files/figure-html/fig-residsimbinomHistoUnif-1.png new file mode 100644 index 0000000..e02e167 Binary files /dev/null and b/08-GLM_files/figure-html/fig-residsimbinomHistoUnif-1.png differ diff --git a/08-GLM_files/figure-html/fig-residusmultinom-1.png b/08-GLM_files/figure-html/fig-residusmultinom-1.png new file mode 100644 index 0000000..f2b7e9d Binary files /dev/null and b/08-GLM_files/figure-html/fig-residusmultinom-1.png differ diff --git a/08-GLM_files/figure-html/fig-residusmultinom4-1.png b/08-GLM_files/figure-html/fig-residusmultinom4-1.png new file mode 100644 index 0000000..8d22b6c Binary files /dev/null and b/08-GLM_files/figure-html/fig-residusmultinom4-1.png differ diff --git a/08-GLM_files/figure-html/fig-simdistribgamma-1.png b/08-GLM_files/figure-html/fig-simdistribgamma-1.png new file mode 100644 index 0000000..72b8cdf Binary files /dev/null and b/08-GLM_files/figure-html/fig-simdistribgamma-1.png differ diff --git a/08-GLM_files/figure-html/fig-simrespoiss-1.png b/08-GLM_files/figure-html/fig-simrespoiss-1.png new file mode 100644 index 0000000..05e34ff Binary files /dev/null and b/08-GLM_files/figure-html/fig-simrespoiss-1.png differ diff --git a/08-GLM_files/figure-html/fig-stucookdist-1.png b/08-GLM_files/figure-html/fig-stucookdist-1.png new file mode 100644 index 0000000..8d8bcf8 Binary files /dev/null and b/08-GLM_files/figure-html/fig-stucookdist-1.png differ diff --git a/08-GLM_files/figure-html/fig-stucookdist2-1.png b/08-GLM_files/figure-html/fig-stucookdist2-1.png new file mode 100644 index 0000000..97587e4 Binary files /dev/null and b/08-GLM_files/figure-html/fig-stucookdist2-1.png differ diff --git a/08-GLM_files/figure-html/fig-studentdistrib-1.png b/08-GLM_files/figure-html/fig-studentdistrib-1.png new file mode 100644 index 0000000..0a9dff9 Binary files /dev/null and b/08-GLM_files/figure-html/fig-studentdistrib-1.png differ diff --git a/08-GLM_files/figure-html/fig-studentresid-1.png b/08-GLM_files/figure-html/fig-studentresid-1.png new file mode 100644 index 0000000..4462967 Binary files /dev/null and b/08-GLM_files/figure-html/fig-studentresid-1.png differ diff --git a/08-GLM_files/figure-html/fig-studentresid2-1.png b/08-GLM_files/figure-html/fig-studentresid2-1.png new file mode 100644 index 0000000..9b4941d Binary files /dev/null and b/08-GLM_files/figure-html/fig-studentresid2-1.png differ diff --git a/08-GLM_files/figure-html/fig-studentresid3-1.png b/08-GLM_files/figure-html/fig-studentresid3-1.png new file mode 100644 index 0000000..751aa88 Binary files /dev/null and b/08-GLM_files/figure-html/fig-studentresid3-1.png differ diff --git a/08-GLM_files/figure-html/fig-surdispnb-1.png b/08-GLM_files/figure-html/fig-surdispnb-1.png new file mode 100644 index 0000000..bbea9d8 Binary files /dev/null and b/08-GLM_files/figure-html/fig-surdispnb-1.png differ diff --git a/08-GLM_files/figure-html/fig-surdisppoiss-1.png b/08-GLM_files/figure-html/fig-surdisppoiss-1.png new file mode 100644 index 0000000..dc24d0c Binary files /dev/null and b/08-GLM_files/figure-html/fig-surdisppoiss-1.png differ diff --git a/08-GLM_files/figure-html/fig-villebinom-1.png b/08-GLM_files/figure-html/fig-villebinom-1.png new file mode 100644 index 0000000..8fb8c6b Binary files /dev/null and b/08-GLM_files/figure-html/fig-villebinom-1.png differ diff --git a/09-GLMM_files/figure-html/fig-bottdistrib-1.png b/09-GLMM_files/figure-html/fig-bottdistrib-1.png new file mode 100644 index 0000000..b4c6626 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-bottdistrib-1.png differ diff --git a/09-GLMM_files/figure-html/fig-diagbinomglmm1-1.png b/09-GLMM_files/figure-html/fig-diagbinomglmm1-1.png new file mode 100644 index 0000000..9a1c302 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-diagbinomglmm1-1.png differ diff --git a/09-GLMM_files/figure-html/fig-diagbinomglmm2-1.png b/09-GLMM_files/figure-html/fig-diagbinomglmm2-1.png new file mode 100644 index 0000000..34fb1ee Binary files /dev/null and b/09-GLMM_files/figure-html/fig-diagbinomglmm2-1.png differ diff --git a/09-GLMM_files/figure-html/fig-diagglmm1-1.png b/09-GLMM_files/figure-html/fig-diagglmm1-1.png new file mode 100644 index 0000000..66870e2 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-diagglmm1-1.png differ diff --git a/09-GLMM_files/figure-html/fig-diagglmm2-1.png b/09-GLMM_files/figure-html/fig-diagglmm2-1.png new file mode 100644 index 0000000..6513eb8 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-diagglmm2-1.png differ diff --git a/09-GLMM_files/figure-html/fig-diagglmm3-1.png b/09-GLMM_files/figure-html/fig-diagglmm3-1.png new file mode 100644 index 0000000..d79a3d3 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-diagglmm3-1.png differ diff --git a/09-GLMM_files/figure-html/fig-fullrandom1-1.png b/09-GLMM_files/figure-html/fig-fullrandom1-1.png new file mode 100644 index 0000000..2de1a02 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-fullrandom1-1.png differ diff --git a/09-GLMM_files/figure-html/fig-fullrandom2-1.png b/09-GLMM_files/figure-html/fig-fullrandom2-1.png new file mode 100644 index 0000000..a2c4f88 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-fullrandom2-1.png differ diff --git a/09-GLMM_files/figure-html/fig-fullrandom3-1.png b/09-GLMM_files/figure-html/fig-fullrandom3-1.png new file mode 100644 index 0000000..47893c1 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-fullrandom3-1.png differ diff --git a/09-GLMM_files/figure-html/fig-glmmvarboot-1.png b/09-GLMM_files/figure-html/fig-glmmvarboot-1.png new file mode 100644 index 0000000..e6add16 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-glmmvarboot-1.png differ diff --git a/09-GLMM_files/figure-html/fig-glmmvariance-1.png b/09-GLMM_files/figure-html/fig-glmmvariance-1.png new file mode 100644 index 0000000..cb5d7d6 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-glmmvariance-1.png differ diff --git a/09-GLMM_files/figure-html/fig-randomconstantes1-1.png b/09-GLMM_files/figure-html/fig-randomconstantes1-1.png new file mode 100644 index 0000000..9043ba0 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-randomconstantes1-1.png differ diff --git a/09-GLMM_files/figure-html/fig-randomconstantes2-1.png b/09-GLMM_files/figure-html/fig-randomconstantes2-1.png new file mode 100644 index 0000000..bb9e0fa Binary files /dev/null and b/09-GLMM_files/figure-html/fig-randomconstantes2-1.png differ diff --git a/09-GLMM_files/figure-html/fig-randomconstantes2b-1.png b/09-GLMM_files/figure-html/fig-randomconstantes2b-1.png new file mode 100644 index 0000000..d87d3d8 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-randomconstantes2b-1.png differ diff --git a/09-GLMM_files/figure-html/fig-randominter1-1.png b/09-GLMM_files/figure-html/fig-randominter1-1.png new file mode 100644 index 0000000..6414a87 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-randominter1-1.png differ diff --git a/09-GLMM_files/figure-html/fig-randominter2-1.png b/09-GLMM_files/figure-html/fig-randominter2-1.png new file mode 100644 index 0000000..02b36c4 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-randominter2-1.png differ diff --git a/09-GLMM_files/figure-html/fig-randominter3-1.png b/09-GLMM_files/figure-html/fig-randominter3-1.png new file mode 100644 index 0000000..440b1df Binary files /dev/null and b/09-GLMM_files/figure-html/fig-randominter3-1.png differ diff --git a/09-GLMM_files/figure-html/fig-randominter5-1.png b/09-GLMM_files/figure-html/fig-randominter5-1.png new file mode 100644 index 0000000..dbaac75 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-randominter5-1.png differ diff --git a/09-GLMM_files/figure-html/fig-randomslope-1.png b/09-GLMM_files/figure-html/fig-randomslope-1.png new file mode 100644 index 0000000..7722015 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-randomslope-1.png differ diff --git a/09-GLMM_files/figure-html/fig-randomslope2-1.png b/09-GLMM_files/figure-html/fig-randomslope2-1.png new file mode 100644 index 0000000..22e5b17 Binary files /dev/null and b/09-GLMM_files/figure-html/fig-randomslope2-1.png differ diff --git a/09-GLMM_files/figure-html/fig-randomslope3-1.png b/09-GLMM_files/figure-html/fig-randomslope3-1.png new file mode 100644 index 0000000..fb5a79b Binary files /dev/null and b/09-GLMM_files/figure-html/fig-randomslope3-1.png differ diff --git a/docs/11-GAM.html b/11-GAM.html similarity index 94% rename from docs/11-GAM.html rename to 11-GAM.html index 2115dbe..320cb2a 100644 --- a/docs/11-GAM.html +++ b/11-GAM.html @@ -379,7 +379,7 @@

Les coefficients \(\beta\) permettent de quantifier l’effet des variables indépendantes (X) sur la moyenne (l’espérance) (\(\mu\)) de la variable dépendante (Y). Un coefficient \(\beta_k\) négatif indique que, si la variable \(X_k\) augmente, alors la variable Y tend à diminuer et inversement, si le coefficient est positif. L’inconvénient de cette formulation est que le modèle est capable de capter uniquement des relations linéaires entre ces variables. Or, il existe de nombreuses situations dans lesquelles une variable indépendante a un lien non linéaire avec une variable dépendante; voici quelques exemples :

  • Si nous mesurons le niveau de bruit émis par une source sonore (variable dépendante) à plusieurs endroits et que nous tentons de prédire l’intensité sonore en fonction de la distance à la source (variable indépendante), nous pouvons nous attendre à observer une relation non linéaire entre les deux. En effet, le son étant une énergie se dispersant selon une sphère dans l’espace, son intensité est inversement proportionnelle au carré de la distance avec la source sonore.

  • -
  • La concentration de la pollution atmosphérique en ville suit généralement des patrons temporels et spatiaux influencés directement par la météorologie et les activités humaines. Autrement dit, il serait absurde d’introduire l’espace de façon linéaire (avec un gradient nord-sud ou est-ouest), ou le moment de la journée de façon linéaire (comme si la pollution augmentait du matin au soir ou inversement). En guise d’exemple, la figure 11.1, tirée de Gelb et Apparicio (2020), illustre bien ces variations temporelles pour deux polluants (le dioxyde d’azote et l’ozone).

  • +
  • La concentration de la pollution atmosphérique en ville suit généralement des patrons temporels et spatiaux influencés directement par la météorologie et les activités humaines. Autrement dit, il serait absurde d’introduire l’espace de façon linéaire (avec un gradient nord-sud ou est-ouest), ou le moment de la journée de façon linéaire (comme si la pollution augmentait du matin au soir ou inversement). En guise d’exemple, la figure fig-gam1, tirée de Gelb et Apparicio (2020), illustre bien ces variations temporelles pour deux polluants (le dioxyde d’azote et l’ozone).

@@ -388,7 +388,7 @@

11.1.1 Non-linéarité fonctionnelle

Il existe de nombreuses façons d’introduire des relations non linéaires dans un modèle. La première et la plus simple à mettre en œuvre est de transformer la variable indépendante à l’aide d’une fonction inverse, exponentielle, logarithmique ou autre.

-

Prenons un premier exemple avec une variable Y que nous tentons de prédire avec une variable X, présenté à la figure 11.2. Si nous ajustons une droite de régression à ces données (en bleu), nous constatons que l’augmentation de X est associée à une augmentation de Y. Cependant, la droite de régression est très éloignée des données et ne capte qu’une petite partie de la relation. Une lecture attentive permet de constater que l’effet de X sur Y augmente de plus en plus rapidement à mesure que X augmente. Cette forme est caractéristique d’une relation exponentielle. Nous pouvons donc transformer la variable X avec la fonction exponentielle afin d’obtenir un meilleur ajustement (en rouge).

+

Prenons un premier exemple avec une variable Y que nous tentons de prédire avec une variable X, présenté à la figure fig-gam2. Si nous ajustons une droite de régression à ces données (en bleu), nous constatons que l’augmentation de X est associée à une augmentation de Y. Cependant, la droite de régression est très éloignée des données et ne capte qu’une petite partie de la relation. Une lecture attentive permet de constater que l’effet de X sur Y augmente de plus en plus rapidement à mesure que X augmente. Cette forme est caractéristique d’une relation exponentielle. Nous pouvons donc transformer la variable X avec la fonction exponentielle afin d’obtenir un meilleur ajustement (en rouge).

@@ -397,7 +397,7 @@

-

La figure 11.3 illustre trois autres situations avec les fonctions logarithmique, logistique inverse et racine carrée. Cette approche peut donner des résultats intéressants si vous disposez d’une bonne justification théorique sur la forme attendue de la relation entre X et Y.

+

La figure fig-gam3 illustre trois autres situations avec les fonctions logarithmique, logistique inverse et racine carrée. Cette approche peut donner des résultats intéressants si vous disposez d’une bonne justification théorique sur la forme attendue de la relation entre X et Y.

@@ -406,7 +406,7 @@

-

Il existe également des cas de figure dans lesquels aucune fonction ne donne de résultats pertinents, comme illustré à la figure 11.4. Nous constatons facilement qu’aucune des fonctions proposées n’est capable de bien capter la relation entre les deux variables. Puisque cette relation est complexe, il convient alors d’utiliser une autre stratégie pour la modéliser.

+

Il existe également des cas de figure dans lesquels aucune fonction ne donne de résultats pertinents, comme illustré à la figure fig-gam4. Nous constatons facilement qu’aucune des fonctions proposées n’est capable de bien capter la relation entre les deux variables. Puisque cette relation est complexe, il convient alors d’utiliser une autre stratégie pour la modéliser.

@@ -417,7 +417,7 @@

11.1.2 Non-linéarité avec des polynomiales

-

Nous avons vu, dans le chapitre sur la régression simple (section 7.5.1.1), qu’il est possible d’utiliser des polynomiales pour ajuster des relations non linéaires. Pour rappel, il s’agit simplement d’ajouter à un modèle la variable X à différents exposants (\(X+X^2+\dots+X^k\)). Chaque exposant supplémentaire (chaque ordre supplémentaire) permet au modèle d’ajuster une relation plus complexe. Rien de tel qu’un graphique pour illustrer le tout (figure 11.5).

+

Nous avons vu, dans le chapitre sur la régression simple (section sec-07511), qu’il est possible d’utiliser des polynomiales pour ajuster des relations non linéaires. Pour rappel, il s’agit simplement d’ajouter à un modèle la variable X à différents exposants (\(X+X^2+\dots+X^k\)). Chaque exposant supplémentaire (chaque ordre supplémentaire) permet au modèle d’ajuster une relation plus complexe. Rien de tel qu’un graphique pour illustrer le tout (figure fig-gam5).

@@ -426,7 +426,7 @@

-

L’enjeu est de sélectionner le bon nombre de degrés de la polynomiale pour le modèle. Chaque degré supplémentaire constitue une nouvelle variable dans le modèle, et donc un paramètre supplémentaire. Un trop faible nombre de degrés produit des courbes trop simplistes, alors qu’un nombre trop élevé conduit à un surajustement (overfitting en anglais) du modèle. La figure 11.6 illustre ces deux situations.

+

L’enjeu est de sélectionner le bon nombre de degrés de la polynomiale pour le modèle. Chaque degré supplémentaire constitue une nouvelle variable dans le modèle, et donc un paramètre supplémentaire. Un trop faible nombre de degrés produit des courbes trop simplistes, alors qu’un nombre trop élevé conduit à un surajustement (overfitting en anglais) du modèle. La figure fig-gam6 illustre ces deux situations.

@@ -438,7 +438,7 @@

Un des problèmes inhérents à l’approche des polynomiales est la difficulté d’interprétation. En effet, les coefficients ne sont pas directement interprétables et seule une figure représentant les prédictions du modèle permet d’avoir une idée de l’effet de la variable X sur la variable Y.

11.1.3 Non-linéarité par segments

-

Un compromis intéressant offrant une interprétation simple et une relation potentiellement complexe consiste à découper la variable X en segments, puis d’ajuster un coefficient pour chacun de ces segments. Nous obtenons ainsi une ligne brisée et des coefficients faciles à interpréter (figure 11.7). Nous ne présentons pas d’exemple d’application dans R, mais sachez que le package segmented permet d’ajuster ce type de modèle.

+

Un compromis intéressant offrant une interprétation simple et une relation potentiellement complexe consiste à découper la variable X en segments, puis d’ajuster un coefficient pour chacun de ces segments. Nous obtenons ainsi une ligne brisée et des coefficients faciles à interpréter (figure fig-gam7). Nous ne présentons pas d’exemple d’application dans R, mais sachez que le package segmented permet d’ajuster ce type de modèle.

@@ -448,7 +448,7 @@

L’enjeu est alors de déterminer le nombre de points et la localisation de points de rupture. L’inconvénient majeur de cette approche est qu’en réalité, peu de phénomènes sont marqués par des ruptures très nettes.

-

À la figure 11.7, nous avons divisé la variable X en trois segments (\(k_1\), \(k_2\) et \(k_3\)), définis respectivement avec les intervalles suivants : [0,00-0,22], [0,22-0,41] et [0,41-1,00]. Concrètement, cela revient à diviser la variable X en trois nouvelles variables \(X_{k1}\), \(X_{k2}\), et \(X_{k3}\). La valeur de \(X_{ik}\) est égale à \(x_i\) si \(x_i\) se trouve dans l’intervalle propre à k, et à 0 autrement. Ici, nous obtenons trois coefficients :

+

À la figure fig-gam7, nous avons divisé la variable X en trois segments (\(k_1\), \(k_2\) et \(k_3\)), définis respectivement avec les intervalles suivants : [0,00-0,22], [0,22-0,41] et [0,41-1,00]. Concrètement, cela revient à diviser la variable X en trois nouvelles variables \(X_{k1}\), \(X_{k2}\), et \(X_{k3}\). La valeur de \(X_{ik}\) est égale à \(x_i\) si \(x_i\) se trouve dans l’intervalle propre à k, et à 0 autrement. Ici, nous obtenons trois coefficients :

  • le premier est positif, une augmentation de X sur le premier segment est associée à une augmentation de Y;

  • le second est négatif, une augmentation de X sur le second segment est associée à une diminution de Y;

  • @@ -457,7 +457,7 @@

    11.1.4 Non-linéarité avec des splines

    La dernière approche, et certainement la plus flexible, est d’utiliser ce que l’on appelle une spline pour capter des relations non linéaires. Une spline est une fonction créant des variables supplémentaires à partir d’une variable X et d’une fonction de base. Ces variables supplémentaires, appelées bases (basis en anglais), sont ajoutées au modèle; la sommation de leurs valeurs multipliées par leurs coefficients permet de capter les relations non linéaires entre une variable dépendante et une variable indépendante. Le nombre de bases et leur localisation (plus souvent appelé nœuds) permettent de contrôler la complexité de la fonction non linéaire.

    -

    Prenons un premier exemple simple avec une fonction de base triangulaire (tent basis en anglais). Nous créons ici une spline avec sept nœuds répartis équitablement sur l’intervalle de valeurs de la variable X. Les sept bases qui en résultent sont présentées à la figure 11.8. Dans cette figure, chaque sommet d’un triangle correspond à un nœud et chaque triangle correspond à une base.

    +

    Prenons un premier exemple simple avec une fonction de base triangulaire (tent basis en anglais). Nous créons ici une spline avec sept nœuds répartis équitablement sur l’intervalle de valeurs de la variable X. Les sept bases qui en résultent sont présentées à la figure fig-gam8. Dans cette figure, chaque sommet d’un triangle correspond à un nœud et chaque triangle correspond à une base.

    @@ -466,7 +466,7 @@

    -

    En ajoutant ces bases dans notre modèle de régression, nous pouvons ajuster un coefficient pour chacune et le représenter en multipliant ces bases par les coefficients obtenus avec une simple régression linéaire (figure 11.9).

    +

    En ajoutant ces bases dans notre modèle de régression, nous pouvons ajuster un coefficient pour chacune et le représenter en multipliant ces bases par les coefficients obtenus avec une simple régression linéaire (figure fig-gam9).

    @@ -475,7 +475,7 @@

    -

    Nous remarquons ainsi que les bases correspondant à des valeurs plus fortes de Y ont reçu des coefficients plus élevés. Pour reconstituer la fonction non linéaire, il suffit d’additionner ces bases multipliées par leurs coefficients, soit la ligne bleue à la figure 11.10.

    +

    Nous remarquons ainsi que les bases correspondant à des valeurs plus fortes de Y ont reçu des coefficients plus élevés. Pour reconstituer la fonction non linéaire, il suffit d’additionner ces bases multipliées par leurs coefficients, soit la ligne bleue à la figure fig-gam10.

    @@ -502,7 +502,7 @@

    plus \(\lambda\) tend vers 0, plus la pénalisation est faible et plus la spline de lissage devient une simple spline de régression;

  • à l’inverse, plus elle est forte, plus la pénalité est importante, au point que la spline peut se résumer à une simple ligne droite.

-

Cela est illustré à la figure 11.12 comprenant trois splines avec 20 nœuds et des valeurs \(\lambda\) différentes contrôlant la force de la pénalité.

+

Cela est illustré à la figure fig-gam12 comprenant trois splines avec 20 nœuds et des valeurs \(\lambda\) différentes contrôlant la force de la pénalité.

Bien évidemment, nous constatons qu’avec la spline de régression (non pénalisée), 20 nœuds conduisent à un fort surajustement du modèle. En revanche, les splines de lissage (pénalisées) permettent de corriger ce problème de surajustement. Toutefois, une valeur trop importante de \(\lambda\) conduit à un sous-ajustement du modèle (ici \(\lambda = 3\) et \(\lambda = 100\), lignes verte et bleue).

@@ -512,7 +512,7 @@

-

Avec les splines de lissage, l’enjeu est de sélectionner une valeur optimale de \(\lambda\). Le plus souvent, les packages R estiment eux-mêmes ce paramètre à partir des données utilisées dans le modèle. Toutefois, gardez en mémoire que vous pouvez modifier ce paramètre. Mentionnons également que les splines de lissage peuvent être reparamétrées dans un modèle pour être intégrées comme des effets aléatoires. Dans ce cas-ci, \(\lambda\) est remplacé par un simple paramètre de variance directement estimé dans le modèle (Wood 2004).

+

Avec les splines de lissage, l’enjeu est de sélectionner une valeur optimale de \(\lambda\). Le plus souvent, les packages R estiment eux-mêmes ce paramètre à partir des données utilisées dans le modèle. Toutefois, gardez en mémoire que vous pouvez modifier ce paramètre. Mentionnons également que les splines de lissage peuvent être reparamétrées dans un modèle pour être intégrées comme des effets aléatoires. Dans ce cas-ci, \(\lambda\) est remplacé par un simple paramètre de variance directement estimé dans le modèle (Wood 2004).

11.3 Interprétation d’une spline

@@ -579,7 +579,7 @@

11.5.1 Splines cycliques

Une spline cyclique est une extension d’une spline classique dont les bases aux extrémités sont spécifiées de telle sorte que la valeur au départ de la spline soit la même que celle à la fin de la spline. Cela permet à la spline de former une boucle, ce qui est particulièrement intéressant pour des variables dont le 0 et la valeur maximale correspondent en réalité à la même valeur. L’exemple le plus parlant est certainement le cas d’une variable représentant la mesure d’un angle en degrés. Les valeurs de 0 et 360 sont identiques et les valeurs 350 et 10 sont toutes les deux à une distance de 10 degrés de 0. Un autre exemple possible serait de considérer l’heure comme une variable continue; dans ce cas, 24 h et 0 h signifient la même chose.

-

Prenons un exemple concret. Nous souhaitons modéliser la concentration de dioxyde d’azote (NO2) à Paris, mesurée par un ensemble de stations fixes. Nous pourrions nous attendre à ce que le NO2 suive chaque jour un certain patron. Concrètement, à proximité d’axes routiers majeurs, nous nous attendons à observer des pics suivant les flux pendulaires. À la figure 11.13, nous retrouvons bien les deux pics attendus correspondant aux heures de pointe du matin et du soir. Aussi, comme indiqué par la ligne rouge, la valeur prédite par la spline est la même à 24 h et à 0 h.

+

Prenons un exemple concret. Nous souhaitons modéliser la concentration de dioxyde d’azote (NO2) à Paris, mesurée par un ensemble de stations fixes. Nous pourrions nous attendre à ce que le NO2 suive chaque jour un certain patron. Concrètement, à proximité d’axes routiers majeurs, nous nous attendons à observer des pics suivant les flux pendulaires. À la figure fig-gam13, nous retrouvons bien les deux pics attendus correspondant aux heures de pointe du matin et du soir. Aussi, comme indiqué par la ligne rouge, la valeur prédite par la spline est la même à 24 h et à 0 h.

@@ -591,7 +591,7 @@

11.5.2 Splines par groupe

Tel qu’abordé dans les chapitres précédents, il arrive régulièrement que les observations appartiennent à différents groupes. Dans ce cas de figure, nous pouvons être amenés à vérifier si la relation décrite par une spline est identique pour chacun des groupes d’observations. Il s’agit alors d’ajuster une spline différente par groupe. Dans l’exemple précédent, chaque valeur de NO2 a été mesurée par une station fixe de mesure spécifique. Compte tenu du fait que l’environnement autour de chaque station est particulier, nous pourrions s’attendre à ce que les valeurs de NO2 ne présentent pas exactement les mêmes patrons journaliers pour chaque station.

-

À la figure 11.14, il est possible de constater que le NO2 suit globalement le même patron temporel pour l’ensemble des stations à l’exception de trois d’entres-elles. Il s’agit en réalité de stations situées dans des secteurs ruraux de la région parisienne, et donc moins impactées par le trafic routier.

+

À la figure fig-gam14, il est possible de constater que le NO2 suit globalement le même patron temporel pour l’ensemble des stations à l’exception de trois d’entres-elles. Il s’agit en réalité de stations situées dans des secteurs ruraux de la région parisienne, et donc moins impactées par le trafic routier.

@@ -604,7 +604,7 @@

11.5.3 Splines multivariées et splines d’interaction

Jusqu’ici, nous n’avons considéré que des splines ne s’appliquant qu’à une seule variable indépendante; cependant, il est possible de construire des splines multivariées s’ajustant simultanément sur plusieurs variables indépendantes. L’objectif est alors de modéliser les potentielles interactions non linéaires entre les variables indépendantes combinées dans une même spline. Prenons un exemple concret, dans la section sur les modèles GLM, nous avons modélisé la couverture des aires de diffusion (AD) à Montréal par des îlots de chaleur. Parmi les variables indépendantes, nous avons notamment utilisé la distance au centre-ville ainsi que la part de la surface végétalisée des AD. Nous pourrions formuler l’hypothèse que ces deux variables influencent conjointement et de façon non linéaire la proportion de la surface d’îlot de chaleur dans chaque AD. Pour représenter une spline sur plusieurs dimensions, nous utilisons alors une carte de chaleur dont la couleur représente la valeur de la variable dépendante prédite en fonction des deux variables indépendantes.

Il est important de distinguer la spline d’interaction et la spline multivariée. La première est utilisée lorsque les variables indépendantes introduites dans la spline ne sont pas exprimées sur la même échelle et n’évoluent pas conjointement. L’exemple donné ci-dessus avec les variables de végétation et de distance au centre-ville est un exemple de spline d’interaction, la première variable étant exprimée en pourcentage et l’autre en mètres. De plus, ces deux variables ne sont pas conjointes, mais bien distinctes l’une de l’autre. Un cas typique où une spline multivariée serait à privilégier est le cas de l’ajout des coordonnées spatiales dans le modèle. L’emplacement des AD est mesuré par deux variables (coordonnées spatiales x et y) toutes les deux exprimées en mètres évoluant conjointement, au sens où les coordonnées x n’interagissent pas avec les coordonnées y, mais forment à elles deux un espace propre. Au-delà de la problématique de l’échelle des données, il est important de retenir que les splines d’interaction tendent à être davantage pénalisées que les splines multivariées.

-

La spline d’interaction représentée à la figure 11.15 indique que les AD avec la plus grande proportion de leur surface couverte par des îlots de chaleur sont situées à moins de 25 kilomètres du centre-ville, au-delà de cette distance, cette proportion chute en bas de 0,1, soit 10 % de la surface de l’AD. En revanche, à proximité du centre-ville (moins d’un kilomètre), même les AD disposant d’un fort pourcentage de surface végétalisée sont tout de même marquées par un fort pourcentage de surface couverte par des îlots de chaleur.

+

La spline d’interaction représentée à la figure fig-gam15 indique que les AD avec la plus grande proportion de leur surface couverte par des îlots de chaleur sont situées à moins de 25 kilomètres du centre-ville, au-delà de cette distance, cette proportion chute en bas de 0,1, soit 10 % de la surface de l’AD. En revanche, à proximité du centre-ville (moins d’un kilomètre), même les AD disposant d’un fort pourcentage de surface végétalisée sont tout de même marquées par un fort pourcentage de surface couverte par des îlots de chaleur.

Les splines bivariées sont fréquemment utilisées pour capturer un potentiel patron spatial dans les données. En effet, si nous disposons des coordonnées spatiales de chaque observation (x, y), il est possible d’ajuster une spline bivariée sur ces coordonnées, contrôlant ainsi l’effet de l’espace.

@@ -891,7 +891,7 @@

-

Or, il s’avère que les deux splines spatiales sont très similaires (figure 11.17). Par conséquent, il est vraisemblablement plus pertinent de conserver la plus simple des deux. Notez que le Mont-Royal, compris dans le cercle central avec une isoligne à 0, est caractérisé par des valeurs plus faibles d’îlots de chaleur, alors que les quartiers centraux situés un peu plus au nord sont au contraire marqués par des pourcentages d’îlots de chaleur supérieurs de 20 points de pourcentage en moyenne.

+

Or, il s’avère que les deux splines spatiales sont très similaires (figure fig-gam17). Par conséquent, il est vraisemblablement plus pertinent de conserver la plus simple des deux. Notez que le Mont-Royal, compris dans le cercle central avec une isoligne à 0, est caractérisé par des valeurs plus faibles d’îlots de chaleur, alors que les quartiers centraux situés un peu plus au nord sont au contraire marqués par des pourcentages d’îlots de chaleur supérieurs de 20 points de pourcentage en moyenne.

11.7 GAMM

Bien entendu, il est possible de combiner les modèles généralisés additifs (GAM) avec les modèles à effet mixtes (GLMM) abordés dans les sections précédentes. Ces modèles généralisés additifs à effets mixtes (GAMM) peuvent facilement être mis en œuvre avec mgcv.

@@ -939,7 +939,7 @@

-

Nous constatons ainsi, à la figure 11.18, que pour une partie des arrondissements, la densité d’îlot de chaleur est systématiquement supérieure à la moyenne régionale représentée ici par la ligne rouge (0 = effet moyen pour tous les arrondissements). Il convient alors d’améliorer ce graphique en ajoutant le niveau d’incertitude associé à chaque intercepte. Pour ce faire, nous utilisons la fonction extract_random_effects du package mixedup. Notez que ce package n’est actuellement pas disponible sur CRAN et doit être téléchargé sur github avec la commande suivante :

+

Nous constatons ainsi, à la figure fig-randomconstGAM, que pour une partie des arrondissements, la densité d’îlot de chaleur est systématiquement supérieure à la moyenne régionale représentée ici par la ligne rouge (0 = effet moyen pour tous les arrondissements). Il convient alors d’améliorer ce graphique en ajoutant le niveau d’incertitude associé à chaque intercepte. Pour ce faire, nous utilisons la fonction extract_random_effects du package mixedup. Notez que ce package n’est actuellement pas disponible sur CRAN et doit être téléchargé sur github avec la commande suivante :

remotes::install_github('m-clark/mixedup')
@@ -947,7 +947,7 @@

source("code_complementaire/gam_functions.R")

-

Nous pouvons ensuite procéder à l’extraction des effets aléatoires et les représenter à nouveau (figure 11.19).

+

Nous pouvons ensuite procéder à l’extraction des effets aléatoires et les représenter à nouveau (figure fig-randomconstGAM2).

df_re <- extract_random_effects.gam(model4, re = "Arrond")
 
@@ -1005,7 +1005,7 @@ 

-

Nous constatons ainsi, à la figure 11.20, que pour une hypothétique aire de diffusion moyenne, la différence de densité d’îlot de chaleur peut être de 0,32 (32 % de la surface de l’AD) entre les arrondissements Verdun et Dollard-des-Ormeaux.

+

Nous constatons ainsi, à la figure fig-randomconstGAM3, que pour une hypothétique aire de diffusion moyenne, la différence de densité d’îlot de chaleur peut être de 0,32 (32 % de la surface de l’AD) entre les arrondissements Verdun et Dollard-des-Ormeaux.

11.7.0.2 GAMM et coefficients aléatoires

En plus des interceptes aléatoires, il est aussi possible de définir des coefficients aléatoires. Reprenons notre exemple et tentons de faire varier l’effet de la variable PopFRPct en fonction de l’arrondissement.

@@ -1016,7 +1016,7 @@

s(PopFRPct, Arrond, bs = "re"), data = dataset, family = betar(link = "logit"))

-

Notez ici une distinction importante! Le modèle n’assume aucune corrélation entre les coefficients aléatoires pour la variable PopFRPct et pour les constantes aléatoires. Il est présumé que ces deux effets proviennent de deux distributions normales distinctes. En d’autres termes, le modèle ne dispose pas des paramètres nécessaires pour vérifier si les arrondissements avec les constantes les plus fortes (avec des densités supérieures d’îlot de chaleur) sont aussi des arrondissements dans lesquels l’effet de la variable PopFRPct est plus prononcé (et vice-versa). Pour plus d’informations sur cette distinction, référez-vous à la section 9.2.3.

+

Notez ici une distinction importante! Le modèle n’assume aucune corrélation entre les coefficients aléatoires pour la variable PopFRPct et pour les constantes aléatoires. Il est présumé que ces deux effets proviennent de deux distributions normales distinctes. En d’autres termes, le modèle ne dispose pas des paramètres nécessaires pour vérifier si les arrondissements avec les constantes les plus fortes (avec des densités supérieures d’îlot de chaleur) sont aussi des arrondissements dans lesquels l’effet de la variable PopFRPct est plus prononcé (et vice-versa). Pour plus d’informations sur cette distinction, référez-vous à la section sec-0924.

AIC(model4, model5)
@@ -1025,7 +1025,7 @@

-

Ce dernier modèle présente une valeur de l’AIC plus faible et serait donc ainsi mieux ajusté que notre modèle avec seulement un intercepte aléatoire. Nous pouvons donc extraire les coefficients aléatoires et les représenter à la figure 11.21.

+

Ce dernier modèle présente une valeur de l’AIC plus faible et serait donc ainsi mieux ajusté que notre modèle avec seulement un intercepte aléatoire. Nous pouvons donc extraire les coefficients aléatoires et les représenter à la figure fig-randomconstcoefGAM.

df_re <- extract_random_effects.gam(model5)
 df_re <- subset(df_re, df_re$effect == 'PopFRPct')
@@ -1091,7 +1091,7 @@ 

-

À lecture de la partie du résumé consacrée aux résultats pour les effets aléatoires, nous constatons que la corrélation entre les interceptes aléatoires et les coefficients aléatoires est de -0,65. Cela signifie que pour les arrondissements avec des interceptes élevés (plus grande proportion d’îlots de chaleur), l’effet de la variable PopFRPct tend à être plus faible. Autrement dit, dans les arrondissements avec beaucoup d’îlots de chaleur, les personnes à faible revenu ont tendance à être moins exposées, tel qu’illustré à la figure 11.22).

+

À lecture de la partie du résumé consacrée aux résultats pour les effets aléatoires, nous constatons que la corrélation entre les interceptes aléatoires et les coefficients aléatoires est de -0,65. Cela signifie que pour les arrondissements avec des interceptes élevés (plus grande proportion d’îlots de chaleur), l’effet de la variable PopFRPct tend à être plus faible. Autrement dit, dans les arrondissements avec beaucoup d’îlots de chaleur, les personnes à faible revenu ont tendance à être moins exposées, tel qu’illustré à la figure fig-corrrandom).

df <- ranef(randomPart)
 df$arrond <- rownames(df)
@@ -1169,7 +1169,7 @@ 

-Relisez l’introduction du chapitre 11 au besoin. +Relisez l’introduction du chapitre sec-chap11 au besoin.
@@ -1214,7 +1214,7 @@

-Relisez au besoin la section 11.1. +Relisez au besoin la section sec-111.
@@ -1259,7 +1259,7 @@

-Relisez au besoin la section 11.1.4. +Relisez au besoin la section sec-1114.
@@ -1296,7 +1296,7 @@

-Relisez au besoin la section 11.1.4. +Relisez au besoin la section sec-1114.
@@ -1341,7 +1341,7 @@

-Relisez au besoin la section 11.3. +Relisez au besoin la section sec-113.
@@ -1386,7 +1386,7 @@

-Relisez au besoin la section 11.5. +Relisez au besoin la section sec-115.
@@ -1415,7 +1415,7 @@

-Relisez au besoin la section 11.5. +Relisez au besoin la section sec-115.
@@ -1444,7 +1444,7 @@

-Relisez au besoin la section 11.4. +Relisez au besoin la section sec-114.
@@ -1493,7 +1493,7 @@

- -

Les trois graphiques à la figure 13.26 semblent indiquer des solutions différentes. Sans surprise, augmenter le niveau de flou (m) réduit l’inertie expliquée, alors qu’augmenter le nombre de groupes (k) augmente l’inertie expliquée. L’indice de silhouette indique assez clairement que le nombre de trois groupes serait le meilleur choix, suivi par deux ou quatre groupes, si m est inférieur à 1,8. Cependant, ne retenir que trois groupes ne permet d’expliquer que 30% de l’inertie. Afin de nous rapprocher des résultats de l’article original (Gelb et Apparicio 2021), nous retenons m = 1,5 et k = 4.

+

Les trois graphiques à la figure fig-cmeansB semblent indiquer des solutions différentes. Sans surprise, augmenter le niveau de flou (m) réduit l’inertie expliquée, alors qu’augmenter le nombre de groupes (k) augmente l’inertie expliquée. L’indice de silhouette indique assez clairement que le nombre de trois groupes serait le meilleur choix, suivi par deux ou quatre groupes, si m est inférieur à 1,8. Cependant, ne retenir que trois groupes ne permet d’expliquer que 30% de l’inertie. Afin de nous rapprocher des résultats de l’article original (Gelb et Apparicio 2021), nous retenons m = 1,5 et k = 4.

13.4.5.1.3 Application l’algorithme c-means
@@ -2979,7 +2979,7 @@

-

Sur les cartes de la figure 13.27, l’intensité de bleu correspond à la probabilité pour chaque IRIS d’appartenir aux différents groupes. Nous retrouvons les principales structures spatiales que nous avons identifiées avec le k-means; cependant, nous pouvons à présent constater que le groupe 1 est bien plus incertain que les autres. Nous pouvons une fois encore générer un graphique en radar pour comparer les profils des quatre groupes.

+

Sur les cartes de la figure fig-cmeansD, l’intensité de bleu correspond à la probabilité pour chaque IRIS d’appartenir aux différents groupes. Nous retrouvons les principales structures spatiales que nous avons identifiées avec le k-means; cependant, nous pouvons à présent constater que le groupe 1 est bien plus incertain que les autres. Nous pouvons une fois encore générer un graphique en radar pour comparer les profils des quatre groupes.

par(mfrow=c(3,2), mai = c(0.1,0.1,0.1,0.1))
 spiderPlots(X, cmeans_resultats$U,
@@ -2991,7 +2991,7 @@ 

-

Sans surprise, nous retrouvons essentiellement les profils que nous avons obtenus avec le k-means dans la figure 13.28. Pour compléter la lecture des résultats, il est nécessaire de se pencher sur le tableau des statistiques descriptives des différents groupes. Une fois encore, nous proposons d’utiliser la fonction summarizeClusters du package geocmeans. Notez que cette fonction calcule les statistiques descriptives pondérées en fonction de l’appartenance des observations aux groupes. Ainsi, une observation ayant une faible chance d’appartenir à un groupe ne contribue que faiblement aux statistiques descriptives de ce groupe.

+

Sans surprise, nous retrouvons essentiellement les profils que nous avons obtenus avec le k-means dans la figure fig-cmeansE. Pour compléter la lecture des résultats, il est nécessaire de se pencher sur le tableau des statistiques descriptives des différents groupes. Une fois encore, nous proposons d’utiliser la fonction summarizeClusters du package geocmeans. Notez que cette fonction calcule les statistiques descriptives pondérées en fonction de l’appartenance des observations aux groupes. Ainsi, une observation ayant une faible chance d’appartenir à un groupe ne contribue que faiblement aux statistiques descriptives de ce groupe.

df <-  st_drop_geometry(LyonIris[c("Lden" , "NO2" , "PM25" , "VegHautPrt" , "Pct0_14",
                                    "Pct_65" , "Pct_Img", "TxChom1564",
@@ -3629,7 +3629,7 @@ 

-

La figure 13.29 indique clairement que les groupes 1 et 2 sont très stables, car les valeurs de Jacard obtenues sont le plus souvent supérieures à 0,75. Le groupe 3 a le plus souvent des valeurs légèrement inférieures aux deux premiers groupes, mais tout de même bien supérieures à 0,5. En revanche, le groupe 4 a un grand nombre de valeurs inférieures à 0,5 indiquant une tendance du groupe à se dissoudre lors des réplications.

+

La figure fig-kmeansStab3 indique clairement que les groupes 1 et 2 sont très stables, car les valeurs de Jacard obtenues sont le plus souvent supérieures à 0,75. Le groupe 3 a le plus souvent des valeurs légèrement inférieures aux deux premiers groupes, mais tout de même bien supérieures à 0,5. En revanche, le groupe 4 a un grand nombre de valeurs inférieures à 0,5 indiquant une tendance du groupe à se dissoudre lors des réplications.

Considérant que le dernier groupe est le plus instable, nous décidons d’observer les valeurs des centres qu’il obtient pour les différentes réplications.

centers_groupe4 <- subset(stab_results$centers, stab_results$centers$groupe == 4)
@@ -3649,7 +3649,7 @@ 

-

Les différents histogrammes de la figure 13.30 indiquent clairement que pour plusieurs variables (Lden, NO2, PM25, Pct_Img, et NivVieMed) les caractéristiques du groupe 4 varient grandement sur l’ensemble des réplications. Nous pouvons comparer ce graphique à celui du groupe 2 qui est bien plus stable.

+

Les différents histogrammes de la figure fig-kmeansStab4 indiquent clairement que pour plusieurs variables (Lden, NO2, PM25, Pct_Img, et NivVieMed) les caractéristiques du groupe 4 varient grandement sur l’ensemble des réplications. Nous pouvons comparer ce graphique à celui du groupe 2 qui est bien plus stable.

centers_groupe2 <- subset(stab_results$centers, stab_results$centers$groupe == 2)
 centers_groupe2$groupe <- NULL
@@ -3668,7 +3668,7 @@ 

-

Nous pouvons constater une plus faible variance des résultats obtenus (en regardant notamment l’axe horizontal) pour les centres des groupes à la figure 13.31.

+

Nous pouvons constater une plus faible variance des résultats obtenus (en regardant notamment l’axe horizontal) pour les centres des groupes à la figure fig-kmeansStab5.

@@ -3737,7 +3737,7 @@

-Relisez au besoin la section 13.1. +Relisez au besoin la section sec-131.
@@ -3782,7 +3782,7 @@

-Relisez au besoin la section 13.1. +Relisez au besoin la section sec-131.
@@ -3819,7 +3819,7 @@

-Relisez au besoin la section 13.4.4. +Relisez au besoin la section sec-1344.
@@ -3864,7 +3864,7 @@

-Relisez au besoin la section 13.3. +Relisez au besoin la section sec-133.
@@ -3909,7 +3909,7 @@

-Relisez au besoin la section 13.4.4. +Relisez au besoin la section sec-1344.

@@ -3924,7 +3924,7 @@

-

-

Comme vous pouvez le constater, la fonction cbind permet de concaténer des vecteurs comme s’ils étaient les colonnes d’une matrice, alors que rbind les combine comme s’ils étaient les lignes d’une matrice. La figure 1.11 présente graphiquement le passage du vecteur à la matrice.

+

Comme vous pouvez le constater, la fonction cbind permet de concaténer des vecteurs comme s’ils étaient les colonnes d’une matrice, alors que rbind les combine comme s’ils étaient les lignes d’une matrice. La figure fig-fig012 présente graphiquement le passage du vecteur à la matrice.

-

+

Figure 1.11: Du vecteur à la matrice

Notez que vous pouvez transposer une matrice avec la fonction t. Si nous essayons maintenant de comparer la matrice 1 à la matrice 2 nous allons avoir une erreur, car elles n’ont pas les mêmes dimensions.

@@ -1036,9 +1036,9 @@

1.3.6.3 Arrays

-

S’il est rare de travailler avec des matrices, il est encore plus rare de manipuler des arrays. Un array est une matrice spéciale qui peut avoir plus que deux dimensions. Un cas simple serait un array en trois dimensions : lignes, colonnes, profondeur, que nous pourrions représenter comme un cube, ou une série de matrices de mêmes dimensions et empilées. Au-delà de trois dimensions, il devient difficile de les représenter mentalement. Cette structure de données peut être utilisée pour représenter les différentes bandes spectrales d’une image satellitaire. Les lignes et les colonnes délimiteraient les pixels de l’image et la profondeur délimiterait les différentes bandes composant l’image (figure 1.11).

+

S’il est rare de travailler avec des matrices, il est encore plus rare de manipuler des arrays. Un array est une matrice spéciale qui peut avoir plus que deux dimensions. Un cas simple serait un array en trois dimensions : lignes, colonnes, profondeur, que nous pourrions représenter comme un cube, ou une série de matrices de mêmes dimensions et empilées. Au-delà de trois dimensions, il devient difficile de les représenter mentalement. Cette structure de données peut être utilisée pour représenter les différentes bandes spectrales d’une image satellitaire. Les lignes et les colonnes délimiteraient les pixels de l’image et la profondeur délimiterait les différentes bandes composant l’image (figure fig-fig012).

-

+

Figure 1.12: Un array avec trois dimensions

Créons un array en combinant trois matrices avec la fonction array. Chacune de ces matrices est composée respectivement de 1, de 2 et de 3 et a une dimension de 5 x 5. L’array final a donc une dimension de 5 x 5 x 3.

@@ -1082,7 +1082,7 @@

1.3.6.4 DataFrames

-

S’il est rare de manipuler des matrices et des arrays, le DataFrame (tableau de données en français) est la structure de données la plus souvent utilisée. Dans cette structure, chaque ligne du tableau représente un individu et chaque colonne représente une caractéristique de cet individu. Ces colonnes ont des noms qui permettent facilement d’accéder à leurs valeurs. Créons un DataFrame (tableau 1.4) à partir de nos quatre vecteurs et de la fonction data.frame.

+

S’il est rare de manipuler des matrices et des arrays, le DataFrame (tableau de données en français) est la structure de données la plus souvent utilisée. Dans cette structure, chaque ligne du tableau représente un individu et chaque colonne représente une caractéristique de cet individu. Ces colonnes ont des noms qui permettent facilement d’accéder à leurs valeurs. Créons un DataFrame (tableau tbl-tabfirsttable) à partir de nos quatre vecteurs et de la fonction data.frame.

df <- data.frame(
   "age" = ages,
@@ -1138,9 +1138,9 @@ 

-

Dans RStudio, vous pouvez visualiser votre tableau de données avec la fonction View(df). Comme vous pouvez le constater, chaque vecteur est devenu une colonne de votre tableau de données df. La figure 1.13 résume ce passage d’une simple donnée à un DataFrame en passant par un vecteur.

+

Dans RStudio, vous pouvez visualiser votre tableau de données avec la fonction View(df). Comme vous pouvez le constater, chaque vecteur est devenu une colonne de votre tableau de données df. La figure fig-fig013 résume ce passage d’une simple donnée à un DataFrame en passant par un vecteur.

-

+

Figure 1.13: De la donnée au DataFrame

Plusieurs fonctions de base de R fournissent des informations importantes sur un DataFrame :

@@ -1323,7 +1323,7 @@

1.4.1.6 Lecture d’un fichier xlsx (Excel)

-

Lire un fichier Excel dans R n’est pas toujours une tâche facile. Généralement, nous recommandons d’exporter le fichier en question au format csv dans un premier temps, puis de le lire avec la fonction read.csv dans un second temps (section 1.4.1.1).

+

Lire un fichier Excel dans R n’est pas toujours une tâche facile. Généralement, nous recommandons d’exporter le fichier en question au format csv dans un premier temps, puis de le lire avec la fonction read.csv dans un second temps (section sec-01411).

Il est néanmoins possible de lire directement un fichier xlsx avec le package xlsx. Ce dernier requiert que le logiciel JAVA soit installé sur votre ordinateur (Windows, Mac ou Linux). Si vous utilisez la version 64 bit de R, vous devrez télécharger et installer la version 64 bit de JAVA. Une fois que ce logiciel tiers est installé, il ne vous restera plus qu’à installer (install.packages("xlsx")) et charger (library(xlsx)) le package xlsx. Sous windows, il est possible que vous deviez également installer manuellement le package rJava et indiquer à R où se trouve JAVA sur votre ordinateur. La procédure est détaillée ici.

library(xlsx)
@@ -1358,7 +1358,7 @@ 

Le DataFrame df6 a 951 observations et 48 colonnes

-

Si nous comparons les temps d’exécution (tableau 1.5), nous constatons que la lecture des fichiers xlsx peut être extrêmement longue si nous ne spécifions pas le type des colonnes, ce qui peut devenir problématique pour des fichiers volumineux. Notez également que la lecture d’un fichier csv devient de plus en plus laborieuse à mesure que sa taille augmente. Si vous devez un jour charger des fichiers csv de plusieurs gigaoctets, nous vous recommandons vivement d’utiliser la fonction fread du package data.table qui est beaucoup plus rapide.

+

Si nous comparons les temps d’exécution (tableau tbl-tableduration), nous constatons que la lecture des fichiers xlsx peut être extrêmement longue si nous ne spécifions pas le type des colonnes, ce qui peut devenir problématique pour des fichiers volumineux. Notez également que la lecture d’un fichier csv devient de plus en plus laborieuse à mesure que sa taille augmente. Si vous devez un jour charger des fichiers csv de plusieurs gigaoctets, nous vous recommandons vivement d’utiliser la fonction fread du package data.table qui est beaucoup plus rapide.

@@ -1371,15 +1371,15 @@

read.csv -0,03 +0,02 read.dbf -0,03 +0,02 read.spss -0,01 +0,00 read.dta @@ -1387,15 +1387,15 @@

read.sas7bdat -0,54 +0,51 read.xlsx -12,21 +12,44 read.xlsx2 -0,41 +0,47 @@ -1409,7 +1409,7 @@

1.4.2.1 Petit mot sur le tidyverse

-

tidyverse est un ensemble de packages conçus pour faciliter la structuration et la manipulation des données dans R. Avant d’aller plus loin, il est important d’aborder brièvement un débat actuel dans la Communauté R. Entre 2010 et 2020, l’utilisation du tidyverse s’est peu à peu répandue. Développé et maintenu par Hadley Wickham, tidyverse introduit une philosophie et une grammaire spécifiques qui diffèrent du langage R traditionnel. Une partie de la communauté a pour ainsi dire complètement embrassé le tidyverse et de nombreux packages, en dehors du tidyverse, ont adopté sa grammaire et sa philosophie. À l’inverse, une autre partie de la communauté est contre cette évolution (voir l’article du blogue suivant). Les arguments pour et contre tidyverse sont résumés dans le (tableau 1.6).

+

tidyverse est un ensemble de packages conçus pour faciliter la structuration et la manipulation des données dans R. Avant d’aller plus loin, il est important d’aborder brièvement un débat actuel dans la Communauté R. Entre 2010 et 2020, l’utilisation du tidyverse s’est peu à peu répandue. Développé et maintenu par Hadley Wickham, tidyverse introduit une philosophie et une grammaire spécifiques qui diffèrent du langage R traditionnel. Une partie de la communauté a pour ainsi dire complètement embrassé le tidyverse et de nombreux packages, en dehors du tidyverse, ont adopté sa grammaire et sa philosophie. À l’inverse, une autre partie de la communauté est contre cette évolution (voir l’article du blogue suivant). Les arguments pour et contre tidyverse sont résumés dans le (tableau tbl-Tidyverse).

@@ -1535,7 +1535,7 @@

1.4.2.3 Calcul de nouvelles variables

-

Il est possible d’utiliser les colonnes de type numérique pour calculer de nouvelles colonnes en utilisant les opérateurs mathématiques vus dans la section 1.3.5. Prenons un exemple concret : calculons la densité de population par secteur de recensement dans notre DataFrame, puis affichons un résumé de cette nouvelle variable.

+

Il est possible d’utiliser les colonnes de type numérique pour calculer de nouvelles colonnes en utilisant les opérateurs mathématiques vus dans la section sec-0135. Prenons un exemple concret : calculons la densité de population par secteur de recensement dans notre DataFrame, puis affichons un résumé de cette nouvelle variable.

# Calcul de la densité
 df$pop_density_2016 <- df$Pop2016 / df$KM2
@@ -1828,7 +1828,7 @@ 

-

Nous observons clairement deux pics, un premier entre 0 et 100 (entre 7 h et 8 h 30 environ) et un second plus important entre 550 et 650 (entre 16 h et 17 h 30 environ), ce qui correspond sans surprise aux heures de pointe (figure 1.14). Il est intéressant de noter que plus d’accidents se produisent à l’heure de pointe du soir qu’à celle du matin.

+

Nous observons clairement deux pics, un premier entre 0 et 100 (entre 7 h et 8 h 30 environ) et un second plus important entre 550 et 650 (entre 16 h et 17 h 30 environ), ce qui correspond sans surprise aux heures de pointe (figure fig-fig015). Il est intéressant de noter que plus d’accidents se produisent à l’heure de pointe du soir qu’à celle du matin.

1.4.2.6.4 Fuseau horaire

Lorsque nous travaillons avec des données provenant de différents endroits dans le monde ou que nous devons tenir compte des heures d’été et d’hiver, il convient de tenir compte du fuseau horaire. Pour créer une date avec un fuseau horaire, il est possible d’utiliser le paramètre tz dans la fonction as_datetime et d’utiliser l’identifiant du fuseau approprié. Dans notre cas, les données d’accident ont été collectées à Montréal, qui a un décalage de -5 heures par rapport au temps de référence UTC (+1 heure en été). Le code spécifique de ce fuseau horaire est EDT; il est facile de trouver ces codes avec le site web timeanddate.com.

@@ -1843,7 +1843,7 @@

1.4.2.7.1 Cas binaire avec ifelse
-

Si nous ne souhaitons créer que deux catégories, le plus simple est d’utiliser la fonction ifelse. Cette fonction évalue une condition (section 1.3.5) pour chaque ligne d’un DataFrame et produit un nouveau vecteur. Créons donc une variable binaire indiquant si une collision a eu lieu durant les heures de pointe ou hors heures de pointe. Nous devons alors évaluer les conditions suivantes :

+

Si nous ne souhaitons créer que deux catégories, le plus simple est d’utiliser la fonction ifelse. Cette fonction évalue une condition (section sec-0135) pour chaque ligne d’un DataFrame et produit un nouveau vecteur. Créons donc une variable binaire indiquant si une collision a eu lieu durant les heures de pointe ou hors heures de pointe. Nous devons alors évaluer les conditions suivantes :

Est-ce que l’accident a eu lieu entre 7 h (0) ET 9 h (120), OU entre 16 h 30 (570) ET 18 h 30 (690)?

table(is.na(accidents_df$diff_time_num))
@@ -1968,10 +1968,10 @@

[1] TRUE

-

Vous pouvez utiliser, dans les deux cas, tous les opérateurs vus dans les sections 1.3.5.1 et 1.3.5.3. L’enjeu est d’arriver à créer un vecteur booléen final permettant d’identifier les observations à conserver.

+

Vous pouvez utiliser, dans les deux cas, tous les opérateurs vus dans les sections sec-01351 et sec-01353. L’enjeu est d’arriver à créer un vecteur booléen final permettant d’identifier les observations à conserver.

1.4.2.8.2 Sous-sélection des colonnes
-

Nous avons déjà vu comment sélectionner des colonnes en utilisant leur nom ou leur index dans la section 1.4.2.2.1. Ajoutons ici un cas particulier où nous souhaitons sélectionner des colonnes selon une condition. Par exemple, nous pourrions vouloir conserver que les colonnes comprenant le mot Length. Pour cela, nous utilisons la fonction grepl, permettant de déterminer si des caractères sont présents dans une chaîne de caractères.

+

Nous avons déjà vu comment sélectionner des colonnes en utilisant leur nom ou leur index dans la section sec-014221. Ajoutons ici un cas particulier où nous souhaitons sélectionner des colonnes selon une condition. Par exemple, nous pourrions vouloir conserver que les colonnes comprenant le mot Length. Pour cela, nous utilisons la fonction grepl, permettant de déterminer si des caractères sont présents dans une chaîne de caractères.

nom_cols <- names(iris)
 print(nom_cols)
@@ -2026,9 +2026,9 @@

Terminons cette section avec la fusion de DataFrames. Nous distinguons deux méthodes répondant à des besoins différents : par ajout ou par jointure.

1.4.2.9.1 Fusion de DataFrames par ajout
-

Ajouter deux DataFrames peut se faire en fonction de leurs colonnes ou en fonction de leurs lignes. Dans ces deux cas, nous utilisons respectivement les fonctions cbind et rbind. La figure 1.15 résume graphiquement le fonctionnement des deux fonctions.

+

Ajouter deux DataFrames peut se faire en fonction de leurs colonnes ou en fonction de leurs lignes. Dans ces deux cas, nous utilisons respectivement les fonctions cbind et rbind. La figure fig-fig016 résume graphiquement le fonctionnement des deux fonctions.

-

+

Figure 1.15: Fusion de DataFrames

Pour que cbind fonctionne, il faut que les deux DataFrames aient le même nombre de lignes. Pour rbind, les deux DataFrames doivent avoir le même nombre de colonnes. Prenons à nouveau comme exemple le jeu de données iris. Nous commençons par le séparer en trois sous-jeux de données comprenant chacun une espèce d’iris. Puis, nous fusionnons deux d’entre eux avec la fonction rbind.

@@ -2059,9 +2059,9 @@

La jointure complète permettant de combiner les éléments présents dans A ou B.

  • La jointure à gauche, permettant de ne conserver que les éléments présents dans A même s’ils n’ont pas de correspondance dans B.

  • -

    Ces trois jointures sont présentées à la figure 1.16; pour ces trois cas, la colonne commune se nomme id.

    +

    Ces trois jointures sont présentées à la figure fig-fig017; pour ces trois cas, la colonne commune se nomme id.

    -

    +

    Figure 1.16: Jointure de DataFrames

    Vous retiendrez que les deux dernières jointures peuvent produire des valeurs manquantes. Pour réaliser ces opérations, nous utilisons la fonction merge. Prenons un exemple simple à partir d’un petit jeu de données.

    @@ -2200,7 +2200,7 @@

    1. -Exploiter les commentaires délimitant les sections dans RStudio : il est possible d’écrire des commentaires d’une certaine façon pour que l’IDE les détecte comme des délimiteurs de sections. L’intérêt principal est que nous pouvons ensuite facilement naviguer entre ces sections en utilisant RStudio comme montré à la figure 1.17, mais aussi masquer des sections afin de faciliter la lecture du reste du code. Pour délimiter une section, il suffit d’ajouter une ligne de commentaire comprenant quatre fois les caractères -, = ou # à la suite.
    2. +Exploiter les commentaires délimitant les sections dans RStudio : il est possible d’écrire des commentaires d’une certaine façon pour que l’IDE les détecte comme des délimiteurs de sections. L’intérêt principal est que nous pouvons ensuite facilement naviguer entre ces sections en utilisant RStudio comme montré à la figure fig-sectionsRstudio, mais aussi masquer des sections afin de faciliter la lecture du reste du code. Pour délimiter une section, il suffit d’ajouter une ligne de commentaire comprenant quatre fois les caractères -, = ou # à la suite.
    # Voici ma section 1 ----------------------------------
    @@ -2216,15 +2216,15 @@ 

    #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    -

    +

    Figure 1.17: Navigation dans des sections de codes avec RStudio
    1. -Adopter une structure globale pour vos projets : au-delà du script, il est nécessaire de bien structurer vos projets, le plus important étant d’utiliser une structure commune à chaque projet pour vous faciliter le travail. Nous proposons à la figure 1.18 un exemple de structure assez générale pouvant être utilisée dans la plupart des cas. Elle sépare notamment les données originales des données structurées, ainsi que les fonctions complémentaires et la structuration des données du principal bloc d’analyse.
    2. +Adopter une structure globale pour vos projets : au-delà du script, il est nécessaire de bien structurer vos projets, le plus important étant d’utiliser une structure commune à chaque projet pour vous faciliter le travail. Nous proposons à la figure fig-structFolder un exemple de structure assez générale pouvant être utilisée dans la plupart des cas. Elle sépare notamment les données originales des données structurées, ainsi que les fonctions complémentaires et la structuration des données du principal bloc d’analyse.
    -

    +

    Figure 1.18: Structure de dossier recommandée pour un projet avec R

    Ne négligez jamais l’importance d’un code bien écrit et documenté !

    @@ -2236,9 +2236,9 @@

    save.image(file = 'chemin/vers/mon/fichier/session.RData', compress = TRUE)

    -

    Vous pouvez aussi utiliser le bouton d’enregistrement dans l’onglet Environnement dans RStudio (figure 1.19).

    +

    Vous pouvez aussi utiliser le bouton d’enregistrement dans l’onglet Environnement dans RStudio (figure fig-saveobj).

    -

    +

    Figure 1.19: Bouton enregistrer la session

    Il est recommandé de compresser ces fichiers (compress = TRUE) pour minimiser leur taille. Pour n’enregistrer que certains objets (ici iris et noms_cols), vous pouvez adapter cette syntaxe :

    @@ -2249,14 +2249,14 @@

    load(file = 'chemin/vers/mon/fichier/mes_objet.RData')

    -

    ou d’utiliser le bouton ouvrir de l’onglet Environnement dans RStudio (figure 1.20).

    +

    ou d’utiliser le bouton ouvrir de l’onglet Environnement dans RStudio (figure fig-loadobj).

    -

    +

    Figure 1.20: Bouton charger un fichier RDA

    1.7 Session de travail

    -

    Comme vous avez pu le constater dans les sections Section 1.6 et Section 1.4.1, il est nécessaire de connaître les chemins vers les fichiers que vous souhaitez utiliser dans votre code R. Si tous ces fichiers sont organisés dans un même dossier (ce que nous vous recommandons à la figure 1.18, il est possible de définir un répertoire de travail avec la fonction setwd. Il est recommandé d’effectuer cette étape au début de votre code R, après le chargement des packages. Ainsi, vous n’aurez pas besoin de réécrire à chaque fois le chemin complet pour accéder à vos fichiers.

    +

    Comme vous avez pu le constater dans les sections sec-017 et sec-0141, il est nécessaire de connaître les chemins vers les fichiers que vous souhaitez utiliser dans votre code R. Si tous ces fichiers sont organisés dans un même dossier (ce que nous vous recommandons à la figure fig-structFolder, il est possible de définir un répertoire de travail avec la fonction setwd. Il est recommandé d’effectuer cette étape au début de votre code R, après le chargement des packages. Ainsi, vous n’aurez pas besoin de réécrire à chaque fois le chemin complet pour accéder à vos fichiers.

    # Chemin complet
     mes_donnes <- read.csv("C:/projets/articles/2022/mon_projet/data/mes_donnes.csv")
    @@ -2280,7 +2280,7 @@ 

    La seconde est l’utilisation de la fonctionnalité projects de RStudio.

    1.8 Conclusion et ressources pertinentes

    -

    Voilà qui conclut ce chapitre sur les bases du langage R. Vous avez maintenant les connaissances nécessaires pour commencer à travailler. N’hésitez pas à revenir sur les différentes sous-sections au besoin! Quelques ressources pertinentes qui pourraient vous être utiles sont aussi reportées au tableau 1.7

    +

    Voilà qui conclut ce chapitre sur les bases du langage R. Vous avez maintenant les connaissances nécessaires pour commencer à travailler. N’hésitez pas à revenir sur les différentes sous-sections au besoin! Quelques ressources pertinentes qui pourraient vous être utiles sont aussi reportées au tableau tbl-tableRessources

    @@ -2375,7 +2375,7 @@

    -Relisez au besoin la section 1.7. +Relisez au besoin la section sec-018.
    @@ -2420,7 +2420,7 @@

    -Relisez au besoin le début de la section 1.2. +Relisez au besoin le début de la section sec-012.
    @@ -2449,7 +2449,7 @@

    -Relisez au besoin la section 1.2.3. +Relisez au besoin la section sec-0123.
    @@ -2478,7 +2478,7 @@

    -Relisez au besoin la section 1.3.6. +Relisez au besoin la section sec-0136.
    @@ -2523,7 +2523,7 @@

    -Relisez au besoin la section 1.3.6. +Relisez au besoin la section sec-0136.
    @@ -2568,7 +2568,7 @@

    -Relisez au besoin la section 1.4.2.9. +Relisez au besoin la section sec-01429.
    @@ -2597,7 +2597,7 @@

    -Relisez le deuxième encadré à la section 1.4.2.9.2. +Relisez le deuxième encadré à la section sec-014292.
    diff --git a/docs/02-univarie.html b/docs/02-univarie.html index 291231b..47fee24 100644 --- a/docs/02-univarie.html +++ b/docs/02-univarie.html @@ -398,7 +398,7 @@

    2.1.1 Notion de variable

    D’un point de vue empirique, une variable est une propriété, une caractéristique d’une unité statistique, d’une observation. Il convient alors de bien saisir à quelle unité d’analyse (ou unité d’observation) s’appliquent les valeurs d’une variable : des personnes, des ménages, des municipalités, des entreprises, etc. Par exemple, pour des individus, l’âge, le genre ou encore le revenu sont autant de caractéristiques qui peuvent être mesurées à partir de variables. Autrement dit, une variable permet de mesurer un phénomène (dans un intervalle de valeurs, c’est-à-dire de manière quantitative) ou de le qualifier (avec plusieurs catégories, c’est-à-dire de manière qualitative).

    -

    D’un point de vue plus théorique, une variable permet d’opérationnaliser un concept en sciences sociales (Gilles et Maranda 1994, 30), soit une « idée générale et abstraite que se fait l’esprit humain d’un objet de pensée concret ou abstrait, et qui lui permet de rattacher à ce même objet les diverses perceptions qu’il en a, et d’en organiser les connaissances » (Larousse). En effet, la construction d’un modèle théorique suppose d’opérationnaliser différents concepts et d’établir les relations qu’ils partagent entre eux. Or, l’opérationnalisation d’un concept nécessite soit de mesurer (dans un intervalle de valeurs, c’est-à-dire de manière quantitative), soit de qualifier (avec plusieurs catégories, c’est-à-dire de manière qualitative) un phénomène.

    +

    D’un point de vue plus théorique, une variable permet d’opérationnaliser un concept en sciences sociales (Gilles et Maranda 1994, 30), soit une « idée générale et abstraite que se fait l’esprit humain d’un objet de pensée concret ou abstrait, et qui lui permet de rattacher à ce même objet les diverses perceptions qu’il en a, et d’en organiser les connaissances » (Larousse). En effet, la construction d’un modèle théorique suppose d’opérationnaliser différents concepts et d’établir les relations qu’ils partagent entre eux. Or, l’opérationnalisation d’un concept nécessite soit de mesurer (dans un intervalle de valeurs, c’est-à-dire de manière quantitative), soit de qualifier (avec plusieurs catégories, c’est-à-dire de manière qualitative) un phénomène.

    @@ -426,7 +426,7 @@

    2.1.2 Types de variables

    -

    Nous distinguons habituellement les variables qualitatives (nominale ou ordinale) des variables quantitatives (discrète ou continue). Comme illustré à la figure 2.1, plusieurs mécanismes différents visent à qualifier, à classer, à compter ou à mesurer afin de caractériser les unités statistiques (observations) d’une population ou d’un échantillon.

    +

    Nous distinguons habituellement les variables qualitatives (nominale ou ordinale) des variables quantitatives (discrète ou continue). Comme illustré à la figure fig-univarie1, plusieurs mécanismes différents visent à qualifier, à classer, à compter ou à mesurer afin de caractériser les unités statistiques (observations) d’une population ou d’un échantillon.

    Figure 2.1: Types de variables
    @@ -491,7 +491,7 @@

    2.2.4 Données individuelles versus données agrégées

    Comme son nom l’indique, pour des données individuelles, chaque observation correspond à un individu. Les microdonnées de recensements ou d’enquêtes, par exemple, sont des données individuelles pour lesquelles toute une série de variables est disponible. Une étude analysant les caractéristiques de chaque arbre d’un quartier nécessite aussi des données individuelles : l’information doit être disponible pour chaque arbre. Pour les microdonnées des recensements canadiens, « chaque enregistrement au niveau de la personne comprend des identifiants (comme les identifiants du ménage et de la famille), des variables géographiques et des variables directes et dérivées tirées du questionnaire » (Statistique Canada). Comme signalé plus haut, ces microdonnées de recensements ou d’enquêtes sont uniquement accessibles dans les centres de données de recherche (CDR).

    Les données individuelles peuvent être agrégées à un niveau supérieur. Prenons le cas de microdonnées d’un recensement. Les informations disponibles pour chaque individu sont agrégées par territoire géographique (province, région économique, division de recensement, subdivision de recensement, région et agglomération de recensement, secteurs de recensement, aires de diffusion, etc.) en fonction du lieu de résidence des individus. Des sommaires statistiques – basés sur la moyenne, la médiane, la somme ou la proportion de chacune des variables mesurées au niveau individuel (âge, sexe, situation familiale, revenu, etc.) – sont alors construits pour ces différents découpages géographiques (Statistique Canada).

    -

    L’agrégation n’est pas nécessairement géographique. En éducation, il est fréquent de travailler avec des données concernant les élèves, mais agrégées au niveau des écoles. La figure 2.2 donne un exemple simple d’agrégation de données individuelles.

    +

    L’agrégation n’est pas nécessairement géographique. En éducation, il est fréquent de travailler avec des données concernant les élèves, mais agrégées au niveau des écoles. La figure fig-univarie1b donne un exemple simple d’agrégation de données individuelles.

    Figure 2.2: Exemple d’agrégation de données individuelles
    @@ -505,7 +505,7 @@

    Il convient d’être prudent dans l’analyse des données agrégées. Très fréquente en géographie, l’erreur écologique (ecological fallacy en anglais) est une mauvaise interprétation des résultats. Elle consiste à attribuer des constats obtenus à partir de données agrégées pour un territoire aux individus qui forment la population de ce territoire. À l’inverse, attribuer des résultats à partir de données individuelles à des territoires est une erreur atomiste.

    -

    Prenons un exemple concret tiré d’une étude récente sur la localisation des écoles primaires et le bruit aérien dans la région métropolitaine de Toronto (Audrin, Apparicio et Séguin 2021). Un des objectifs de cette étude est de vérifier si les écoles primaires (ns = 1420) avec des niveaux de bruit aérien élevés présentent des niveaux de réussite scolaire plus faibles. Les résultats de leur étude démontrent que les enfants scolarisés dans les écoles primaires avec à des niveaux élevés de bruit aérien sont issus de milieux plus défavorisés et ont plus souvent une langue maternelle autre que la langue d’enseignement. Aussi, les écoles avec des niveaux de bruit aérien élevés présentent des niveaux de réussite scolaire plus faibles.

    +

    Prenons un exemple concret tiré d’une étude récente sur la localisation des écoles primaires et le bruit aérien dans la région métropolitaine de Toronto (Audrin, Apparicio et Séguin 2021). Un des objectifs de cette étude est de vérifier si les écoles primaires (ns = 1420) avec des niveaux de bruit aérien élevés présentent des niveaux de réussite scolaire plus faibles. Les résultats de leur étude démontrent que les enfants scolarisés dans les écoles primaires avec à des niveaux élevés de bruit aérien sont issus de milieux plus défavorisés et ont plus souvent une langue maternelle autre que la langue d’enseignement. Aussi, les écoles avec des niveaux de bruit aérien élevés présentent des niveaux de réussite scolaire plus faibles.

    Toutefois, étant donné que les variables sur la réussite scolaire sont mesurées au niveau de l’école (soit les pourcentages d’élèves ayant atteint ou dépassé la norme provinciale en lecture, en écriture et en mathématique, respectivement pour la 3e année et la 6e année) et non au niveau individuel, nous ne pouvons pas conclure que le bruit aérien à un impact significatif sur la réussite scolaire des élèves :

    « Nous avons pu démontrer que les écoles primaires localisées dans la zone NEF 25 présentent des taux de réussite plus faibles. Rappelons toutefois qu’une association obtenue avec des données agrégées ne peut pas nous permettre de conclure à une influence directe au niveau individuel, car l’agrégation des données entraîne une perte d’information. Cette erreur d’interprétation dite erreur écologique (ecological fallacy) tend à laisser penser que les associations entre les groupes s’appliquent à chaque individu (Robinson, 1950). Nos résultats gagneraient à être corroborés à partir d’analyses reposant sur des données individuelles ».

    @@ -557,10 +557,10 @@

    Autre exemple, une autre chercheuse souhaite comprendre les facteurs influençant le sentiment de sécurité des cyclistes dans un quartier. De nouveau, elle ne peut pas enquêter sur l’ensemble des cyclistes du quartier et devra constituer un échantillon représentatif. Par la suite, la mise en œuvre de techniques inférentielles lui permettra d’identifier les caractéristiques individuelles (âge, sexe, habiletés à vélo, etc.) et de l’environnement urbain (types de voies empruntés, niveaux de trafic, de pollution, de bruit, etc.) ayant des effets significatifs sur le sentiment de sécurité. Si l’échantillon est représentatif, les résultats pourront être généralisés à l’ensemble des cyclistes du quartier.

    2.3.2 Deux grandes familles de méthodes statistiques

    -

    Nous distinguons habituellement deux grandes familles de méthodes statistiques : la statistique descriptive et exploratoire et la statistiques inférentielle et confirmatoire. Il existe de nombreuses définitions de ces deux branches de la statistique, celles proposées de Lebart et al. (1995) étant parmi les plus abouties :

    +

    Nous distinguons habituellement deux grandes familles de méthodes statistiques : la statistique descriptive et exploratoire et la statistiques inférentielle et confirmatoire. Il existe de nombreuses définitions de ces deux branches de la statistique, celles proposées de Lebart et al. (1995) étant parmi les plus abouties :

    • « La statistique descriptive et exploratoire : elle permet, par des résumés et des graphiques plus ou moins élaborés, de décrire des ensembles de données statistiques, d’établir des relations entre les variables sans faire jouer de rôle privilégié à une variable particulière. Les conclusions ne portent dans cette phase de travail que sur les données étudiées, sans être inférées à une population plus large. L’analyse exploratoire s’appuie essentiellement sur des notions élémentaires telles que des indicateurs de moyenne et de dispersion, sur des représentations graphiques. […]

    • -
    • La statistique inférentielle et confirmatoire : elle permet de valider ou d’infirmer, à partir de tests statistiques ou de modèles probabilistes, des hypothèses formulées a priori (ou après une phase exploratoire), et d’extrapoler, c’est-à-dire d’étendre certaines propriétés d’un échantillon à une population plus large. Les conclusions obtenues à partir des données vont au-delà de ces données. La statistique confirmatoire fait surtout appel aux méthodes dites explicatives et prévisionnelles, destinées, comme leurs noms l’indiquent, à expliquer puis à prévoir, suivant des règles de décision, une variable privilégiée à l’aide d’une ou plusieurs variables explicatives (régressions multiples et logistiques, analyse de variance, analyse discriminante, segmentation, etc.) » (Lebart, Morineau et Piron 1995, 209).

    • +
    • La statistique inférentielle et confirmatoire : elle permet de valider ou d’infirmer, à partir de tests statistiques ou de modèles probabilistes, des hypothèses formulées a priori (ou après une phase exploratoire), et d’extrapoler, c’est-à-dire d’étendre certaines propriétés d’un échantillon à une population plus large. Les conclusions obtenues à partir des données vont au-delà de ces données. La statistique confirmatoire fait surtout appel aux méthodes dites explicatives et prévisionnelles, destinées, comme leurs noms l’indiquent, à expliquer puis à prévoir, suivant des règles de décision, une variable privilégiée à l’aide d’une ou plusieurs variables explicatives (régressions multiples et logistiques, analyse de variance, analyse discriminante, segmentation, etc.) » (Lebart, Morineau et Piron 1995, 209).

    2.4 Notion de distribution

    @@ -591,7 +591,7 @@

    Une distribution est toujours définie dans un intervalle en dehors duquel elle n’est définie; les valeurs dans cet intervalle sont appelées l’espace d’échantillonnage. Il s’agit donc des valeurs possibles que peut produire l’expérience. La somme des probabilités de l’ensemble des valeurs de l’espace d’échantillonnage est 1 (100 %). Intuitivement, cela signifie que si nous réalisons l’expérience, nous obtenons nécessairement un résultat, et que la somme des probabilités est répartie entre tous les résultats possibles de l’expérience. En langage mathématique, nous disons que l’intégrale de la fonction de densité d’une distribution est 1 dans son intervalle de définition.

    Prenons un exemple concret avec l’expérience suivante : tirer à pile ou face avec une pièce de monnaie non truquée. Si l’on souhaite décrire la probabilité d’obtenir pile ou face, nous pouvons utiliser une distribution qui aura comme espace d’échantillonnage [pile; face] et ces deux valeurs auront chacune comme probabilité 0,5. Il est facile d’étendre cet exemple au cas d’un dé à six faces. La distribution de probabilité décrivant l’expérience « lancer le dé » a pour espace d’échantillonnage [1,2,3,4,5,6], chacune de ces valeurs étant associée à la probabilité de 1/6.

    -

    Chacune des deux expériences précédentes est régie par une distribution appartenant à la famille des distributions discrètes. Elles servent à représenter des expériences dont le nombre de valeurs possibles est fini. Par opposition, la seconde famille de distributions regroupe les distributions continues, décrivant des expériences dont le nombre de résultats possibles est en principe infini. Par exemple, mesurer la taille d’une personne adulte sélectionnée au hasard peut produire en principe un nombre infini de valeurs. Les distributions sont utiles pour décrire les résultats potentiels d’une expérience. Reprenons notre exemple du dé. Nous savons que chaque face a une chance sur six d’être tirée au hasard. Nous pouvons représenter cette distribution avec un graphique (figure 2.3).

    +

    Chacune des deux expériences précédentes est régie par une distribution appartenant à la famille des distributions discrètes. Elles servent à représenter des expériences dont le nombre de valeurs possibles est fini. Par opposition, la seconde famille de distributions regroupe les distributions continues, décrivant des expériences dont le nombre de résultats possibles est en principe infini. Par exemple, mesurer la taille d’une personne adulte sélectionnée au hasard peut produire en principe un nombre infini de valeurs. Les distributions sont utiles pour décrire les résultats potentiels d’une expérience. Reprenons notre exemple du dé. Nous savons que chaque face a une chance sur six d’être tirée au hasard. Nous pouvons représenter cette distribution avec un graphique (figure fig-fig251).

    @@ -600,7 +600,7 @@

    -

    Nous avons donc sous les yeux un modèle statistique décrivant le comportement attendu d’un dé, soit sa distribution théorique. Cependant, si nous effectuons dix fois l’expérience (nous collectons donc un échantillon), nous obtiendrons une distribution différente de cette distribution théorique (figure 2.4).

    +

    Nous avons donc sous les yeux un modèle statistique décrivant le comportement attendu d’un dé, soit sa distribution théorique. Cependant, si nous effectuons dix fois l’expérience (nous collectons donc un échantillon), nous obtiendrons une distribution différente de cette distribution théorique (figure fig-fig252).

    @@ -610,7 +610,7 @@

    Il s’agit de la distribution empirique. Chaque échantillon aura sa propre distribution empirique. Cependant, comme le prédit la loi des grands nombres : si une expérience est répétée un grand nombre de fois, la probabilité empirique d’un résultat se rapproche de la probabilité théorique à mesure que le nombre de répétitions augmente. Du point de vue de la théorie des probabilités, chaque échantillon correspond à un ensemble de tirages aléatoires effectués à partir de la distribution théorique du phénomène étudié.

    -

    Pour nous en convaincre, collectons trois échantillons de lancer de dé de respectivement 30, 100 et 1000 observations (figure 2.5). Comme le montre la figure 2.4, nous connaissons la distribution théorique qui régit cette expérience.

    +

    Pour nous en convaincre, collectons trois échantillons de lancer de dé de respectivement 30, 100 et 1000 observations (figure fig-fig253). Comme le montre la figure fig-fig252, nous connaissons la distribution théorique qui régit cette expérience.

    @@ -643,7 +643,7 @@

    -

    La fonction de densité de la distribution uniforme a donc deux paramètres, a et b, représentant respectivement les valeurs maximale et minimale au-delà desquelles les valeurs ont une probabilité 0 d’être obtenues. Pour avoir une meilleure intuition de ce que décrit une fonction de densité, il est intéressant de la représenter avec un graphique (figure 2.6). Notez que sur ce graphique, l’axe des ordonnées n’indique pas précisément la probabilité associée à chaque valeur, car celle-ci est infinitésimale. Il sert uniquement à représenter la valeur de la fonction de densité de la distribution pour chaque valeur de x.

    +

    La fonction de densité de la distribution uniforme a donc deux paramètres, a et b, représentant respectivement les valeurs maximale et minimale au-delà desquelles les valeurs ont une probabilité 0 d’être obtenues. Pour avoir une meilleure intuition de ce que décrit une fonction de densité, il est intéressant de la représenter avec un graphique (figure fig-fig254). Notez que sur ce graphique, l’axe des ordonnées n’indique pas précisément la probabilité associée à chaque valeur, car celle-ci est infinitésimale. Il sert uniquement à représenter la valeur de la fonction de densité de la distribution pour chaque valeur de x.

    @@ -696,10 +696,10 @@

    2.4.3 Principales distributions

    Il existe un très grand nombre de distributions théoriques et parmi elles, de nombreuses sont en fait des cas spéciaux d’autres distributions. Pour un petit aperçu du « bestiaire », vous pouvez faire un saut à la page Univariate Distribution Relationships, qui liste près de 80 distributions.

    -

    Nous nous concentrons ici sur une sélection de dix-huit distributions très répandues en sciences sociales. La figure 2.7 présente graphiquement leurs fonctions de masse et de densité présentées dans cette section. Notez que ces graphiques correspondent tous à une forme possible de chaque distribution. En modifiant leurs paramètres, il est possible de produire une figure très différente. Les distributions discrètes sont représentées avec des graphiques en barre, et les distributions continues avec des graphiques de densité.

    +

    Nous nous concentrons ici sur une sélection de dix-huit distributions très répandues en sciences sociales. La figure fig-distribs présente graphiquement leurs fonctions de masse et de densité présentées dans cette section. Notez que ces graphiques correspondent tous à une forme possible de chaque distribution. En modifiant leurs paramètres, il est possible de produire une figure très différente. Les distributions discrètes sont représentées avec des graphiques en barre, et les distributions continues avec des graphiques de densité.

    -
    Figure 2.7: Dix-huit distributions essentielles, figure inspirée de Sean (2018)
    +
    Figure 2.7: Dix-huit distributions essentielles, figure inspirée de Sean (2018)

    2.4.3.1 Distribution uniforme discrète

    @@ -720,7 +720,7 @@

    \[ f(x ; n )=\binom{n}{x}p^x(1-p)^{n-x} \tag{2.4}\]

    -

    avec x le nombre de tirages réussis sur n essais avec une probabilité p de réussite à chaque tirage (figure 2.8). Pour reprendre l’exemple précédent concernant les accidents de la route, une distribution binomiale permettrait de représenter la distribution du nombre de cyclistes ayant survécu sur dix personnes à vélo impliquées dans un accident avec une voiture à une intersection.

    +

    avec x le nombre de tirages réussis sur n essais avec une probabilité p de réussite à chaque tirage (figure fig-fig256). Pour reprendre l’exemple précédent concernant les accidents de la route, une distribution binomiale permettrait de représenter la distribution du nombre de cyclistes ayant survécu sur dix personnes à vélo impliquées dans un accident avec une voiture à une intersection.

    @@ -735,7 +735,7 @@

    \[ f(x; p)= (1-p)^xp \tag{2.5}\]

    -

    avec x le nombre de tentatives avant d’obtenir une réussite, \(f(x)\) la probabilité que le premier succès n’arrive qu’après x tentatives et p la probabilité de réussite à chaque tentative (figure 2.9). Cette distribution est notamment utilisée en marketing pour modéliser le nombre d’appels nécessaires avant de réussir une vente.

    +

    avec x le nombre de tentatives avant d’obtenir une réussite, \(f(x)\) la probabilité que le premier succès n’arrive qu’après x tentatives et p la probabilité de réussite à chaque tentative (figure fig-fig257). Cette distribution est notamment utilisée en marketing pour modéliser le nombre d’appels nécessaires avant de réussir une vente.

    @@ -753,7 +753,7 @@

    -

    avec x le nombre de tentatives avant d’obtenir n réussites et p la probabilité d’obtenir une réussite à chaque tentative (figure 2.10). Cette distribution pourrait être utilisée pour modéliser le nombre de questionnaires x à envoyer pour une enquête pour obtenir au moins n réponses, sachant que la probabilité d’une réponse est p.

    +

    avec x le nombre de tentatives avant d’obtenir n réussites et p la probabilité d’obtenir une réussite à chaque tentative (figure fig-fig258). Cette distribution pourrait être utilisée pour modéliser le nombre de questionnaires x à envoyer pour une enquête pour obtenir au moins n réponses, sachant que la probabilité d’une réponse est p.

    @@ -806,7 +806,7 @@

    99,7 % dans l’intervalle \([\mu- 3\sigma≤x≤ \mu+ 3\sigma]\) -

    Autrement dit, dans le cas d’une distribution normale, il est très invraisemblable d’observer des données situées à plus de trois écarts types de la moyenne. Ces différentes égalités sont vraies quelles que soient les valeurs de la moyenne et de l’écart-type. Notez ici que lorsque \(\mu = 0\) et \(\sigma = 1\), nous obtenons la loi normale générale (ou centrée réduite) (section 2.5.5.2).

    +

    Autrement dit, dans le cas d’une distribution normale, il est très invraisemblable d’observer des données situées à plus de trois écarts types de la moyenne. Ces différentes égalités sont vraies quelles que soient les valeurs de la moyenne et de l’écart-type. Notez ici que lorsque \(\mu = 0\) et \(\sigma = 1\), nous obtenons la loi normale générale (ou centrée réduite) (section sec-02552).

    @@ -967,7 +967,7 @@

    -

    Au-delà de la question de la répartition de la richesse, la distribution de Pareto peut également être utilisée pour décrire la répartition de la taille des villes (Reed 2002), la popularité des hommes sur Tinder ou la taille des fichiers échangés sur Internet (Reed et Jorgensen 2004). Pour ces trois exemples, nous avons les situations suivantes : de nombreuses petites villes, profils peu attractifs, petits fichiers échangés et à l’inverse très peu de grandes villes, profils très attractifs, gros fichiers échangés.

    +

    Au-delà de la question de la répartition de la richesse, la distribution de Pareto peut également être utilisée pour décrire la répartition de la taille des villes (Reed 2002), la popularité des hommes sur Tinder ou la taille des fichiers échangés sur Internet (Reed et Jorgensen 2004). Pour ces trois exemples, nous avons les situations suivantes : de nombreuses petites villes, profils peu attractifs, petits fichiers échangés et à l’inverse très peu de grandes villes, profils très attractifs, gros fichiers échangés.

    La loi de Pareto est liée à la loi exponentielle. Si une variable aléatoire suit une loi de Pareto, le logarithme du quotient de cette variable et de son paramètre de localisation est une variable aléatoire qui suit une loi exponentielle.

    2.4.3.19 Cas particuliers

    @@ -980,7 +980,7 @@

    Les distributions tronquées, souvent confondues avec les distributions censurées, décrivent des situations où des données au-delà d’une certaine limite sont impossibles à collecter et retirées simplement de l’analyse.

    2.4.4 Conclusion sur les distributions

    -

    Voilà qui conclut cette exploration des principales distributions à connaître. L’idée n’est bien sûr pas de toutes les retenir par cœur (et encore moins les formules mathématiques), mais plutôt de se rappeler dans quels contextes elles peuvent être utiles. Vous aurez certainement besoin de relire cette section avant d’aborder le chapitre 8 portant sur les modèles linéaires généralisés (GLM). Wikipédia dispose d’informations très détaillées sur chaque distribution si vous avez besoin d’informations complémentaires. Pour un tour d’horizon plus exhaustif des distributions, vous pouvez aussi faire un tour sur les projets ProbOnto et the ultimate probability distribution explorer.

    +

    Voilà qui conclut cette exploration des principales distributions à connaître. L’idée n’est bien sûr pas de toutes les retenir par cœur (et encore moins les formules mathématiques), mais plutôt de se rappeler dans quels contextes elles peuvent être utiles. Vous aurez certainement besoin de relire cette section avant d’aborder le chapitre sec-chap08 portant sur les modèles linéaires généralisés (GLM). Wikipédia dispose d’informations très détaillées sur chaque distribution si vous avez besoin d’informations complémentaires. Pour un tour d’horizon plus exhaustif des distributions, vous pouvez aussi faire un tour sur les projets ProbOnto et the ultimate probability distribution explorer.

    2.5 Statistiques descriptives sur des variables quantitatives

    @@ -991,7 +991,7 @@

    La médiane est la valeur qui coupe la distribution d’une variable d’une population ou d’un échantillon en deux parties égales. Autrement dit, 50 % des valeurs des observations lui sont supérieures et 50 % lui sont inférieures.

  • Le mode est la valeur la plus fréquente parmi un ensemble d’observations pour une variable. Il s’applique ainsi à des variables discrètes (avec un nombre fini de valeurs discrètes dans un intervalle donné) et non à des variables continues (avec un nombre infini de valeurs réelles dans un intervalle donné). Prenons deux variables : l’une discrète relative au nombre d’accidents par intersection (avec \(X \in \left[0,20\right]\)) et l’autre continue relative à la distance de dépassement (en mètres) d’une personne à vélo par une personne conduisant un véhicule motorisé (avec \(X \in \left[0,5\right]\)). Pour la première, le mode – la valeur la plus fréquente – est certainement 0. Pour la seconde, identifier le mode n’est pas pertinent puisqu’il peut y avoir un nombre infini de valeurs entre 0 et 5 mètres.

  • -

    Il convient de ne pas confondre moyenne et médiane! Dans le tableau 2.1, nous avons reporté les valeurs moyennes et médianes des revenus des ménages pour les municipalités de l’île de Montréal en 2015. Par exemple, les 8685 ménages résidant à Wesmount disposaient en moyenne d’un revenu de 295 099 $; la moitié de ces 8685 ménages avaient un revenu inférieur à 100 153 $ et l’autre moitié un revenu supérieur à cette valeur (médiane). Cela démontre clairement que la moyenne peut être grandement affectée par des valeurs extrêmes (faibles ou fortes). Autrement dit, plus l’écart entre les valeurs de la moyenne et la médiane est important, plus les données de la variable sont inégalement réparties. À Westmount, soit la municipalité la plus nantie de l’île de Montréal, les valeurs extrêmes sont des ménages avec des revenus très élevés tirant fortement la moyenne vers le haut. À l’inverse, le faible écart entre les valeurs moyenne et médiane dans la municipalité de Montréal-Est (58 594 $ versus 50 318 $) souligne que les revenus des ménages sont plus également répartis. Cela explique que pour comparer les revenus totaux ou d’emploi entre différents groupes (selon le sexe, le groupe d’âge, le niveau d’éducation, la municipalité ou région métropolitaine, etc.), nous privilégions habituellement l’utilisation des revenus médians.

    +

    Il convient de ne pas confondre moyenne et médiane! Dans le tableau tbl-RevMoyMed, nous avons reporté les valeurs moyennes et médianes des revenus des ménages pour les municipalités de l’île de Montréal en 2015. Par exemple, les 8685 ménages résidant à Wesmount disposaient en moyenne d’un revenu de 295 099 $; la moitié de ces 8685 ménages avaient un revenu inférieur à 100 153 $ et l’autre moitié un revenu supérieur à cette valeur (médiane). Cela démontre clairement que la moyenne peut être grandement affectée par des valeurs extrêmes (faibles ou fortes). Autrement dit, plus l’écart entre les valeurs de la moyenne et la médiane est important, plus les données de la variable sont inégalement réparties. À Westmount, soit la municipalité la plus nantie de l’île de Montréal, les valeurs extrêmes sont des ménages avec des revenus très élevés tirant fortement la moyenne vers le haut. À l’inverse, le faible écart entre les valeurs moyenne et médiane dans la municipalité de Montréal-Est (58 594 $ versus 50 318 $) souligne que les revenus des ménages sont plus également répartis. Cela explique que pour comparer les revenus totaux ou d’emploi entre différents groupes (selon le sexe, le groupe d’âge, le niveau d’éducation, la municipalité ou région métropolitaine, etc.), nous privilégions habituellement l’utilisation des revenus médians.

    @@ -1120,12 +1120,12 @@

    Les déciles (de D1 à D9) qui divisent une distribution en dix parties égales (10 %).
  • Les centiles (de C1 à C99) qui divisent une distribution en cent parties égales (1 %).
  • -

    En cartographie, les quartiles et les quintiles sont souvent utilisés pour discrétiser une variable quantitative (continue ou discrète) en quatre ou cinq classes et plus rarement, en dix classes (déciles). Avec les quartiles, les bornes des classes qui comprennent chacune 25 % des unités spatiales sont définies comme suit : [Min à Q1], [Q1 à Q2], [Q2 à Q3] et [Q3 à Max]. La méthode de discrétisation selon les quartiles ou quintiles permet de repérer, en un coup d’œil, à quelle tranche de 25 % ou de 20 % des données appartient chacune des unités spatiales. Cette méthode de discrétisation est aussi utile pour comparer plusieurs cartes et vérifier si deux phénomènes sont ou non colocalisés (Pumain et Béguin 1994). En guise d’exemple, les pourcentages de personnes à faible revenu et de locataires par secteur de recensement ont clairement des distributions spatiales très semblables dans la région métropolitaine de Montréal en 2016 (figure 2.24).

    +

    En cartographie, les quartiles et les quintiles sont souvent utilisés pour discrétiser une variable quantitative (continue ou discrète) en quatre ou cinq classes et plus rarement, en dix classes (déciles). Avec les quartiles, les bornes des classes qui comprennent chacune 25 % des unités spatiales sont définies comme suit : [Min à Q1], [Q1 à Q2], [Q2 à Q3] et [Q3 à Max]. La méthode de discrétisation selon les quartiles ou quintiles permet de repérer, en un coup d’œil, à quelle tranche de 25 % ou de 20 % des données appartient chacune des unités spatiales. Cette méthode de discrétisation est aussi utile pour comparer plusieurs cartes et vérifier si deux phénomènes sont ou non colocalisés (Pumain et Béguin 1994). En guise d’exemple, les pourcentages de personnes à faible revenu et de locataires par secteur de recensement ont clairement des distributions spatiales très semblables dans la région métropolitaine de Montréal en 2016 (figure fig-univarie2).

    Figure 2.24: Exemples de cartographie avec une discrétisation selon les quantiles
    -

    Une lecture attentive des valeurs des centiles permet de repérer la présence de valeurs extrêmes, voire aberrantes, dans un jeu de données. Il n’est donc pas rare de les voir reportées dans un tableau de statistiques descriptives d’un article scientifique, et ce, afin de décrire succinctement les variables à l’étude. Par exemple, dans une étude récente comparant les niveaux d’exposition au bruit des cyclistes dans trois villes (Apparicio et Gelb 2020), les auteurs reportent à la fois les valeurs moyennes et celles de plusieurs centiles. Globalement, la lecture des valeurs moyennes permet de constater que, sur la base des données collectées, les cyclistes sont plus exposés au bruit à Paris qu’à Montréal et Copenhague (73,4 dB(A) contre 70,7 et 68,4, tableau 2.2). Compte tenu de l’échelle logarithmique du bruit, la différence de 5 dB(A) entre les valeurs moyennes du bruit de Copenhague et de Paris peut être considérée comme une multiplication de l’énergie sonore par plus de 3. Pour Paris, l’analyse des quartiles montre que durant 25 % du temps des trajets à vélo (plus de 63 heures de collecte), les participantes et participants ont été exposés à des niveaux de bruit soit inférieurs à 69,1 dB(A) (premier quartile), soit supérieurs à 74 dB(A) (troisième quartile). Quant à l’analyse des centiles, elle permet de constater que durant 5 % et 10 % du temps, les participantes et participants étaient exposés à des niveaux de bruit très élevés, dépassant 75 dB(A) (C90 = 76 et C90 = 77,2).

    +

    Une lecture attentive des valeurs des centiles permet de repérer la présence de valeurs extrêmes, voire aberrantes, dans un jeu de données. Il n’est donc pas rare de les voir reportées dans un tableau de statistiques descriptives d’un article scientifique, et ce, afin de décrire succinctement les variables à l’étude. Par exemple, dans une étude récente comparant les niveaux d’exposition au bruit des cyclistes dans trois villes (Apparicio et Gelb 2020), les auteurs reportent à la fois les valeurs moyennes et celles de plusieurs centiles. Globalement, la lecture des valeurs moyennes permet de constater que, sur la base des données collectées, les cyclistes sont plus exposés au bruit à Paris qu’à Montréal et Copenhague (73,4 dB(A) contre 70,7 et 68,4, tableau tbl-Centiles). Compte tenu de l’échelle logarithmique du bruit, la différence de 5 dB(A) entre les valeurs moyennes du bruit de Copenhague et de Paris peut être considérée comme une multiplication de l’énergie sonore par plus de 3. Pour Paris, l’analyse des quartiles montre que durant 25 % du temps des trajets à vélo (plus de 63 heures de collecte), les participantes et participants ont été exposés à des niveaux de bruit soit inférieurs à 69,1 dB(A) (premier quartile), soit supérieurs à 74 dB(A) (troisième quartile). Quant à l’analyse des centiles, elle permet de constater que durant 5 % et 10 % du temps, les participantes et participants étaient exposés à des niveaux de bruit très élevés, dépassant 75 dB(A) (C90 = 76 et C90 = 77,2).

    @@ -1217,18 +1217,18 @@

    2.5.3 Paramètres de dispersion

    -

    Cinq principales mesures de dispersion permettent d’évaluer la variabilité des valeurs d’une variable quantitative : l’étendue, l’écart interquartile, la variance, l’écart-type et le coefficient de variation. Notez d’emblée que cette dernière mesure ne s’applique pas à des variables d’intervalle (section 2.1.2.2).

    +

    Cinq principales mesures de dispersion permettent d’évaluer la variabilité des valeurs d’une variable quantitative : l’étendue, l’écart interquartile, la variance, l’écart-type et le coefficient de variation. Notez d’emblée que cette dernière mesure ne s’applique pas à des variables d’intervalle (section sec-02122).

    • L’étendue est la différence entre les valeurs minimale et maximale d’une variable, soit l’intervalle des valeurs dans lequel elle a été mesurée. Il convient d’analyser avec prudence cette mesure puisqu’elle inclut dans son calcul des valeurs potentiellement extrêmes, voire aberrantes (faibles ou fortes).

    • -
    • L’intervalle ou écart interquartile est la différence entre les troisième et premier quartiles (Q3 − Q1). Il représente ainsi une mesure de la dispersion des valeurs de 50 % des observations centrales de la distribution. Plus la valeur de l’écart interquartile est élevée, plus la dispersion des 50 % des observations centrales est forte. Contrairement à l’étendue, cette mesure élimine l’influence des valeurs extrêmes puisqu’elle ne tient pas compte des 25 % des observations les plus faibles [Min à Q1] et des 25 % des observations les plus fortes [Q3 à Max]. Graphiquement, l’intervalle interquartile est représenté à l’aide d’une boîte à moustaches (boxplot en anglais) : plus l’intervalle interquartile est grand, plus la boîte est allongée (figure 2.25).

    • +
    • L’intervalle ou écart interquartile est la différence entre les troisième et premier quartiles (Q3 − Q1). Il représente ainsi une mesure de la dispersion des valeurs de 50 % des observations centrales de la distribution. Plus la valeur de l’écart interquartile est élevée, plus la dispersion des 50 % des observations centrales est forte. Contrairement à l’étendue, cette mesure élimine l’influence des valeurs extrêmes puisqu’elle ne tient pas compte des 25 % des observations les plus faibles [Min à Q1] et des 25 % des observations les plus fortes [Q3 à Max]. Graphiquement, l’intervalle interquartile est représenté à l’aide d’une boîte à moustaches (boxplot en anglais) : plus l’intervalle interquartile est grand, plus la boîte est allongée (figure fig-univarie3).

    Figure 2.25: Graphique en violon, boîte à moustaches et intervalle interquartile
      -
    • La variance est la somme des déviations à la moyenne au carré (numérateur) divisée par le nombre d’observations pour une population (\(\sigma^2\)) ou divisée par le nombre d’observations moins une (\(s^2\)) pour un échantillon (équation 2.20). Puisque les déviations à la moyenne sont mises au carré, la valeur de la variance (tout comme celle de l’écart-type) est toujours positive. Plus sa valeur est élevée, plus les observations sont dispersées autour de la moyenne. La variance représente ainsi l’écart au carré moyen des observations à la moyenne.

    • -
    • L’écart-type est la racine carrée de la variance (équation 2.21). Rappelez-vous que la variance est calculée à partir des déviations à la moyenne mises au carré. Étant donné que l’écart-type est la racine carrée de la variance, il est donc évalué dans la même unité que la variable, contrairement à la variance. Bien entendu, comme pour la variance, plus la valeur de l’écart-type est élevée, plus la distribution des observations autour de la moyenne est dispersée.

    • +
    • La variance est la somme des déviations à la moyenne au carré (numérateur) divisée par le nombre d’observations pour une population (\(\sigma^2\)) ou divisée par le nombre d’observations moins une (\(s^2\)) pour un échantillon (équation eq-variance). Puisque les déviations à la moyenne sont mises au carré, la valeur de la variance (tout comme celle de l’écart-type) est toujours positive. Plus sa valeur est élevée, plus les observations sont dispersées autour de la moyenne. La variance représente ainsi l’écart au carré moyen des observations à la moyenne.

    • +
    • L’écart-type est la racine carrée de la variance (équation eq-ecartype). Rappelez-vous que la variance est calculée à partir des déviations à la moyenne mises au carré. Étant donné que l’écart-type est la racine carrée de la variance, il est donc évalué dans la même unité que la variable, contrairement à la variance. Bien entendu, comme pour la variance, plus la valeur de l’écart-type est élevée, plus la distribution des observations autour de la moyenne est dispersée.

    \[ \sigma^2=\frac{\sum_{i=1}^n (x_{i}-\mu)^2}{n} \text{ ou } s^2=\frac{\sum_{i=1}^n (x_{i}-\bar{x})^2}{n-1} @@ -1252,20 +1252,20 @@

    • -Le coefficient de variation (CV) est le rapport entre l’écart-type et la moyenne, représentant ainsi une standardisation de l’écart-type ou, en d’autres termes, une mesure de dispersion relative (équation 2.22). L’écart-type étant exprimé dans l’unité de mesure de la variable, il ne peut pas être utilisé pour comparer les dispersions de variables exprimées des unités de mesure différentes (par exemple, en pourcentage, en kilomètres, en dollars, etc.). Pour y remédier, nous utilisons le coefficient de variation : une variable est plus dispersée qu’une autre si la valeur de son CV est plus élevée. Certaines personnes préfèrent multiplier la valeur du CV par 100 : l’écart-type est alors exprimé en pourcentage de la moyenne.
    • +Le coefficient de variation (CV) est le rapport entre l’écart-type et la moyenne, représentant ainsi une standardisation de l’écart-type ou, en d’autres termes, une mesure de dispersion relative (équation eq-cv). L’écart-type étant exprimé dans l’unité de mesure de la variable, il ne peut pas être utilisé pour comparer les dispersions de variables exprimées des unités de mesure différentes (par exemple, en pourcentage, en kilomètres, en dollars, etc.). Pour y remédier, nous utilisons le coefficient de variation : une variable est plus dispersée qu’une autre si la valeur de son CV est plus élevée. Certaines personnes préfèrent multiplier la valeur du CV par 100 : l’écart-type est alors exprimé en pourcentage de la moyenne.

    \[ CV=\frac{\sigma}{\mu} \text{ ou } CV=\frac{s^2}{\bar{x}} \tag{2.22}\]

    -

    Illustrons comment calculer les cinq mesures de dispersion précédemment décrites à partir de valeurs fictives pour huit observations (colonne intitulée \(x_i\) au tableau 2.3). Les différentes statistiques reportées dans ce tableau sont calculées comme suit :

    +

    Illustrons comment calculer les cinq mesures de dispersion précédemment décrites à partir de valeurs fictives pour huit observations (colonne intitulée \(x_i\) au tableau tbl-datavar). Les différentes statistiques reportées dans ce tableau sont calculées comme suit :

    • La moyenne est la somme divisée par le nombre d’observations, soit \(\mbox{248/8}=\mbox{31}\).

    • L’étendue est la différence entre les valeurs maximale et minimale, soit \(\mbox{40}-\mbox{22}=\mbox{30}\).

    • Les quartiles coupent la distribution en quatre parties égales. Avec huit observations triées par ordre croissant, le premier quartile est égal à la valeur de la deuxième observation (soit 25), la médiane à celle de la quatrième (30), le troisième quartile à celle de la sixième (35).

    • L’écart interquartile est la différence entre Q3 et Q1, soit \(\mbox{35}-\mbox{25}=\mbox{10}\).

    • -
    • La seconde colonne du tableau est l’écart à la moyenne (\(x_i-\bar{x}\)), soit \(\mbox{22} - \mbox{31} = -\mbox{9}\) pour l’observation 1; la somme de ces écarts est toujours égale à 0. La troisième colonne est cette déviation mise au carré (\((x_i-\bar{x})^2\)), soit \(-\mbox{9}^2 = \mbox{81}\), toujours pour l’observation 1. La somme de ces déviations à la moyenne au carré (268) représente le numérateur de la variance (équation 2.20). En divisant cette somme par le nombre d’observations, nous obtenons la variance pour une population (\(\mbox{268}/\mbox{8}=\mbox{33,5}\)) tandis que la variance d’un échantillon est égale à \(\mbox{268}/(\mbox{8}-\mbox{1})=\mbox{38,29}\).

    • -
    • L’écart-type est la racine carrée de la variance (équation 2.21), soit \(\sigma=\sqrt{\mbox{33,5}}=\mbox{5,79}\) et \(s=\sqrt{\mbox{38,29}}=\mbox{6,19}\).

    • -
    • Finalement, les valeurs des coefficients de variation (équation 2.22) sont de \(\mbox{5,79}/\mbox{31}=\mbox{0,19}\) pour une population et \(\mbox{6,19}/\mbox{31}=\mbox{0,20}\) pour un échantillon.

    • +
    • La seconde colonne du tableau est l’écart à la moyenne (\(x_i-\bar{x}\)), soit \(\mbox{22} - \mbox{31} = -\mbox{9}\) pour l’observation 1; la somme de ces écarts est toujours égale à 0. La troisième colonne est cette déviation mise au carré (\((x_i-\bar{x})^2\)), soit \(-\mbox{9}^2 = \mbox{81}\), toujours pour l’observation 1. La somme de ces déviations à la moyenne au carré (268) représente le numérateur de la variance (équation eq-variance). En divisant cette somme par le nombre d’observations, nous obtenons la variance pour une population (\(\mbox{268}/\mbox{8}=\mbox{33,5}\)) tandis que la variance d’un échantillon est égale à \(\mbox{268}/(\mbox{8}-\mbox{1})=\mbox{38,29}\).

    • +
    • L’écart-type est la racine carrée de la variance (équation eq-ecartype), soit \(\sigma=\sqrt{\mbox{33,5}}=\mbox{5,79}\) et \(s=\sqrt{\mbox{38,29}}=\mbox{6,19}\).

    • +
    • Finalement, les valeurs des coefficients de variation (équation eq-cv) sont de \(\mbox{5,79}/\mbox{31}=\mbox{0,19}\) pour une population et \(\mbox{6,19}/\mbox{31}=\mbox{0,20}\) pour un échantillon.

    @@ -1422,7 +1422,7 @@

    -

    Le tableau 2.4 vise à démontrer, à partir de trois variables, comment certaines mesures de dispersion sont sensibles à l’unité de mesure et/ou aux valeurs extrêmes.

    +

    Le tableau tbl-datavar2 vise à démontrer, à partir de trois variables, comment certaines mesures de dispersion sont sensibles à l’unité de mesure et/ou aux valeurs extrêmes.

    Concernant l’unité de mesure, nous avons créé deux variables A et B, où B étant simplement A multipliée par 10. Pour A, les valeurs de la moyenne, de l’étendue et de l’intervalle interquartile sont respectivement 31, 18 et 10. Sans surprise, celles de B sont multipliées par 10 (310, 180, 100). La variance étant la moyenne des déviations à la moyenne au carré, elle est égale à 33,50 pour A et donc à \(\mbox{33,50}\times10^2=\mbox{3350}\) pour B; l’écart-type de B est égal à celui de A multiplié par 10. Cela démontre que l’étendue, l’intervalle interquartile, la variance et l’écart-type sont des mesures de dispersion dépendantes de l’unité de mesure. Par contre, étant donné que le coefficient de variation (CV) est le rapport de l’écart-type avec la moyenne, il a la même valeur pour A et B, ce qui démontre que le CV est bien une mesure de dispersion relative permettant de comparer des variables exprimées dans des unités de mesure différentes.

    Concernant la sensibilité aux valeurs extrêmes, nous avons créé la variable C pour laquelle seule la huitième observation a une valeur différente (40 pour A et 105 pour B). Cette valeur de 105 pourrait être soit une valeur extrême positive mesurée, soit une valeur aberrante (par exemple, si l’unité de mesure était un pourcentage variant de 0 à 100 %). Cette valeur a un impact important sur la moyenne (31 contre 39,12) et l’étendue (18 contre 83) et corollairement sur la variance (33,50 contre 641,86), l’écart-type (5,79 contre 25,33) et le coefficient de variation (0,19 contre 0,65). Par contre, comme l’intervalle interquartile est calculé sur 50 % des observations centrales (\(\mbox{Q3}-\mbox{Q1}\)), il n’est pas affecté par cette valeur extrême.

    @@ -1595,7 +1595,7 @@

    Il est vivement recommandé de réaliser les trois démarches!

    -

    Une distribution est normale quand elle est symétrique et mésokurtique (figure 2.26).

    +

    Une distribution est normale quand elle est symétrique et mésokurtique (figure fig-FormeDistr).

    Figure 2.26: Formes d’une distribution et coefficients d’asymétrie et d’aplatissement
    @@ -1603,7 +1603,7 @@

    2.5.4.1.1 Vérification de la normalité avec les coefficients d’asymétrie et d’aplatissement

    Une distribution est dite symétrique quand la moyenne arithmétique est au centre de la distribution, c’est-à-dire que les observations sont bien réparties de part et d’autre de la moyenne qui est alors égale à la médiane et au mode (nous utilisons uniquement le mode pour une variable discrète et non pour une variable continue). Pour évaluer l’asymétrie, nous utilisons habituellement le coefficient d’asymétrie (skewness en anglais).

    -

    Sachez toutefois qu’il existe trois façons (formules) pour le calculer (Joanes et Gill 1998) : \(g_1\) est la formule classique (équation 2.23), disponible dans R avec la fonction skewness du package moments), \(G_1\) est une version ajustée (équation 2.24), utilisée dans les logiciels SAS et SPSS notamment) et \(b_1\) est une autre version ajustée (équation 2.25), utilisée par les logiciels MINITAB et BMDP). Nous verrons qu’avec les packages DescTools ou e1071, il est possible de calculer ces trois méthodes. Aussi, pour de grands échantillons (\(n>100\)), il y a très peu de différences entre les résultats produits par ces trois formules (Joanes et Gill 1998). Quelle que soit la formule utilisée, le coefficient d’asymétrie s’interprète comme suit (figure 2.27) :

    +

    Sachez toutefois qu’il existe trois façons (formules) pour le calculer (Joanes et Gill 1998) : \(g_1\) est la formule classique (équation eq-SkewType1), disponible dans R avec la fonction skewness du package moments), \(G_1\) est une version ajustée (équation eq-SkewType2), utilisée dans les logiciels SAS et SPSS notamment) et \(b_1\) est une autre version ajustée (équation eq-SkewType3), utilisée par les logiciels MINITAB et BMDP). Nous verrons qu’avec les packages DescTools ou e1071, il est possible de calculer ces trois méthodes. Aussi, pour de grands échantillons (\(n>100\)), il y a très peu de différences entre les résultats produits par ces trois formules (Joanes et Gill 1998). Quelle que soit la formule utilisée, le coefficient d’asymétrie s’interprète comme suit (figure fig-asymetrie) :

    • Quand la valeur du skewness est négative, la distribution est asymétrique négative. La distribution est alors tirée à gauche par des valeurs extrêmes faibles, mais peu nombreuses. Nous employons souvent l’expression la queue de distribution est étirée vers la gauche. La moyenne est alors inférieure à la médiane.

    • Quand la valeur du skewness est égale à 0, la distribution est symétrique (la médiane est égale à la moyenne). Pour une variable discrète, les valeurs du mode, de la moyenne et de la médiane sont égales.

    • @@ -1626,7 +1626,7 @@

    -

    Pour évaluer l’aplatissement d’une distribution, nous utilisons le coefficient d’aplatissement (kurtosis en anglais). Là encore, il existe trois formules pour le calculer (équations 2.26, 2.27, 2.28) qui renvoient des valeurs très semblables pour de grands échantillons (Joanes et Gill 1998). Cette mesure s’interprète comme suit (figure 2.27) :

    +

    Pour évaluer l’aplatissement d’une distribution, nous utilisons le coefficient d’aplatissement (kurtosis en anglais). Là encore, il existe trois formules pour le calculer (équations eq-KurtType1, eq-KurtType2, eq-KurtType3) qui renvoient des valeurs très semblables pour de grands échantillons (Joanes et Gill 1998). Cette mesure s’interprète comme suit (figure fig-asymetrie) :

    • Quand la valeur du kurtosis est négative, la distribution est platikurtique. La distribution est dite plate, c’est-à-dire que la valeur de l’écart-type est importante (comparativement à une distribution normale), signalant une grande dispersion des valeurs de part et d’autre la moyenne. s

    • Quand la valeur du kurtosis est égale à 0, la distribution est mésokurtique, ce qui est typique d’une distribution normale.

    • @@ -1657,7 +1657,7 @@

      Kurtosis normalisé

      -

      Regardez attentivement les équations 2.26, 2.27, 2.28; vous remarquez que pour \(g_2\) et \(b_2\), il y a une soustraction de 3 et une addition 6 pour \(G_2\). Nous parlons alors de kurtosis normalisé (excess kurtosis en anglais). Pour une distribution normale, il prend la valeur de 0, comparativement à la valeur de 3 pour un kurtosis non normalisé. Par conséquent, avant de calculer le kurtosis, il convient de s’assurer que la fonction que vous utilisez implémente une méthode de calcul normalisée (donnant une valeur de 0 pour une distribution normale). Par exemple, la fonction Kurt du package DescTools calcule les trois formules normalisées tandis que la fonction kurtosis du package moments renvoie un kurtosis non normalisé.

      +

      Regardez attentivement les équations eq-KurtType1, eq-KurtType2, eq-KurtType3; vous remarquez que pour \(g_2\) et \(b_2\), il y a une soustraction de 3 et une addition 6 pour \(G_2\). Nous parlons alors de kurtosis normalisé (excess kurtosis en anglais). Pour une distribution normale, il prend la valeur de 0, comparativement à la valeur de 3 pour un kurtosis non normalisé. Par conséquent, avant de calculer le kurtosis, il convient de s’assurer que la fonction que vous utilisez implémente une méthode de calcul normalisée (donnant une valeur de 0 pour une distribution normale). Par exemple, la fonction Kurt du package DescTools calcule les trois formules normalisées tandis que la fonction kurtosis du package moments renvoie un kurtosis non normalisé.

      library(DescTools)
       library(moments)
      @@ -1665,18 +1665,18 @@ 

      Normale <- rnorm(1500,0,1) round(DescTools::Kurt(Normale),3)

      -
      [1] -0.167
      +
      [1] -0.066
      round(moments::kurtosis(Normale),3)
      -
      [1] 2.837
      +
      [1] 2.938

    2.5.4.1.2 Vérification de la normalité avec des graphiques
    -

    Les graphiques sont un excellent moyen de vérifier visuellement si une distribution est normale ou pas. Bien entendu, les histogrammes, que nous avons déjà largement utilisés, sont un incontournable. À titre de rappel, ils permettent de représenter la forme de la distribution des données (figure 2.29). Un autre type de graphique intéressant est le diagramme quantile-quantile (Q-Q plot en anglais), qui permet de comparer la distribution d’une variable avec une distribution gaussienne (normale). Trois éléments composent ce graphique comme illustré à la figure 2.30 :

    +

    Les graphiques sont un excellent moyen de vérifier visuellement si une distribution est normale ou pas. Bien entendu, les histogrammes, que nous avons déjà largement utilisés, sont un incontournable. À titre de rappel, ils permettent de représenter la forme de la distribution des données (figure fig-CourbeNormale). Un autre type de graphique intéressant est le diagramme quantile-quantile (Q-Q plot en anglais), qui permet de comparer la distribution d’une variable avec une distribution gaussienne (normale). Trois éléments composent ce graphique comme illustré à la figure fig-qqplot :

    • les points, représentant les observations de la variable;
    • la distribution gaussienne (normale), représentée par une ligne;
    • @@ -1701,7 +1701,7 @@

    2.5.4.1.3 Vérification de la normalité avec des tests de normalité
    -

    Cinq principaux tests d’hypothèse permettent de vérifier la normalité d’une variable : les tests de Kolmogorov-Smirnov (KS), de Lilliefors (LF), de Shapiro-Wilk (SW), d’Anderson-Darling et de Jarque-Bera (JB). Sachez toutefois qu’il y en a d’autres non discutés ici (tests d’Agostino–Pearson, de Cramer–von Mises, de Ryan-Joiner, de Shapiro–Francia, etc.). Pour les formules et une description détaillée de ces tests, vous pouvez consulter Razali et al. (2011) ou Yap et Sim (2011). Quel test choisir? Plusieurs auteur(e)s ont comparé ces différents tests à partir de plusieurs échantillons, et ce, en faisant varier la forme de la distribution et le nombre d’observations (Razali et Wah 2011; Yap et Sim 2011). Selon Razali et al. (2011), le meilleur test semble être celui de Shapiro-Wilk, puis ceux d’Anderson-Darling, de Lilliefors et de Kolmogorov-Smirnov. Yap et Sim (2011) concluent aussi que le Shapiro-Wilk semble être le plus performant.

    +

    Cinq principaux tests d’hypothèse permettent de vérifier la normalité d’une variable : les tests de Kolmogorov-Smirnov (KS), de Lilliefors (LF), de Shapiro-Wilk (SW), d’Anderson-Darling et de Jarque-Bera (JB). Sachez toutefois qu’il y en a d’autres non discutés ici (tests d’Agostino–Pearson, de Cramer–von Mises, de Ryan-Joiner, de Shapiro–Francia, etc.). Pour les formules et une description détaillée de ces tests, vous pouvez consulter Razali et al. (2011) ou Yap et Sim (2011). Quel test choisir? Plusieurs auteur(e)s ont comparé ces différents tests à partir de plusieurs échantillons, et ce, en faisant varier la forme de la distribution et le nombre d’observations (Razali et Wah 2011; Yap et Sim 2011). Selon Razali et al. (2011), le meilleur test semble être celui de Shapiro-Wilk, puis ceux d’Anderson-Darling, de Lilliefors et de Kolmogorov-Smirnov. Yap et Sim (2011) concluent aussi que le Shapiro-Wilk semble être le plus performant.

    Quoi qu’il en soit, ces cinq tests postulent que la variable suit une distribution gaussienne (hypothèse nulle, H0).

    Cela signifie que si la valeur de p associée à la valeur de chacun des tests est inférieure ou égale au seuil alpha choisi (habituellement \(\alpha=\mbox{0,05}\)), la distribution est anormale. À l’inverse, si \(p>\mbox{0,05}\), la distribution est normale.

    @@ -1750,7 +1750,7 @@

    Jarque-Bera -Basé sur un test du type multiplicateur de Lagrange, ce test utilise dans son calcul les valeurs du Skewness et du Kurtosis. Plus sa valeur s’approche de 0, plus la distribution est normale. Ce test est surtout utilisé pour vérifier si les résidus d’un modèle de régression linéaire sont normalement distribués; nous y reviendrons dans le chapitre sur la régression multiple. Il s’écrit \(JB=\frac{1}{6} \left({g_1}^2+\frac{{g_1}^2}{4} \right)\) avec \(g_1\) et \(g_2\) qui sont respectivement les valeurs du skewness et du kurtosis de la variable (voir les équations 2.23 et 2.26. +Basé sur un test du type multiplicateur de Lagrange, ce test utilise dans son calcul les valeurs du Skewness et du Kurtosis. Plus sa valeur s’approche de 0, plus la distribution est normale. Ce test est surtout utilisé pour vérifier si les résidus d’un modèle de régression linéaire sont normalement distribués; nous y reviendrons dans le chapitre sur la régression multiple. Il s’écrit \(JB=\frac{1}{6} \left({g_1}^2+\frac{{g_1}^2}{4} \right)\) avec \(g_1\) et \(g_2\) qui sont respectivement les valeurs du skewness et du kurtosis de la variable (voir les équations eq-SkewType1 et eq-KurtType1. JarqueBeraTest du package DescTools @@ -1760,7 +1760,7 @@

    -

    Dans le tableau 2.7 sont reportées les valeurs des différents tests pour les cinq types de distribution générés à la figure 2.29. Sans surprise, pour l’ensemble des tests, la valeur de p est inférieure à 0,05 pour la distribution normale.

    +

    Dans le tableau tbl-calcultestnormalites sont reportées les valeurs des différents tests pour les cinq types de distribution générés à la figure fig-CourbeNormale. Sans surprise, pour l’ensemble des tests, la valeur de p est inférieure à 0,05 pour la distribution normale.

    @@ -1788,88 +1788,88 @@

    S Skewness --0,034 -1,557 --1,346 -0,031 --0,015 +-0,019 +1,091 +-1,522 +1,018 +-0,058 K Kurtosis -0,077 -3,121 -3,037 -5,578 --0,979 +-0,108 +1,091 +3,841 +10,560 +-0,949 KS Kolmogorov-Smirnov (KS) -0,033 -0,128 -0,103 -0,094 -0,050 +0,029 +0,113 +0,107 +0,083 +0,054 LF Lilliefors (LF) -0,033 -0,128 -0,103 -0,094 -0,050 +0,029 +0,113 +0,107 +0,083 +0,054 SW Shapiro-Wilk (SW) -0,997 -0,877 -0,909 +0,998 0,918 -0,973 +0,881 +0,900 +0,974 AD Anderson-Darling (AD) -0,488 -14,690 -10,002 -9,432 -2,523 +0,370 +11,045 +13,573 +7,334 +2,332 JB Jarque-Bera (JB) -0,997 -732,590 -401,154 -1 606,203 -14,916 +0,040 +157,701 +570,327 +4 261,705 +14,034 KS.p KS (valeur p) -0,649 -0,000 +0,791 0,000 0,000 -0,162 +0,002 +0,112 LF.p LF (valeur p) -0,208 +0,384 0,000 0,000 0,000 -0,004 +0,002 SW.p SW (valeur p) -0,523 +0,702 0,000 0,000 0,000 @@ -1878,7 +1878,7 @@

    AD.p AD (valeur p) -0,223 +0,424 0,000 0,000 0,000 @@ -1887,7 +1887,7 @@

    JB.p JB (valeur p) -0,608 +0,980 0,000 0,000 0,000 @@ -1951,7 +1951,7 @@

    Qu’est-ce que le loglikelihood?

    -

    Le loglikelihood est une mesure de l’ajustement d’un modèle à des données. Il est utilisé à peu près partout en statistique. Comprendre sa signification est donc un exercice important pour développer une meilleure intuition du fonctionnement général de nombreuses méthodes. Si les concepts de fonction de densité et de fonction de masse vous semblent encore flous, reportez-vous à la section 2.4 sur les distributions dans un premier temps.

    +

    Le loglikelihood est une mesure de l’ajustement d’un modèle à des données. Il est utilisé à peu près partout en statistique. Comprendre sa signification est donc un exercice important pour développer une meilleure intuition du fonctionnement général de nombreuses méthodes. Si les concepts de fonction de densité et de fonction de masse vous semblent encore flous, reportez-vous à la section sec-024 sur les distributions dans un premier temps.

    Admettons que nous disposons d’une variable continue v que nous tentons de modéliser avec une distribution d (il peut s’agir de n’importe quelle distribution). d a une fonction de densité avec laquelle il est possible de calculer, pour chacune des valeurs de v, la probabilité d’être observée selon le modèle d.

    Prenons un exemple concret dans R. Admettons que nous avons une variable comprenant 10 valeurs (oui, c’est un petit échantillon, mais c’est pour faire un exemple simple).

    @@ -2087,7 +2087,7 @@

    -

    Visuellement, nous constatons que la distribution de Pareto est un mauvais choix. Pour les trois autres distributions, la comparaison des valeurs de loglikelihood s’impose (tableau 2.8).

    +

    Visuellement, nous constatons que la distribution de Pareto est un mauvais choix. Pour les trois autres distributions, la comparaison des valeurs de loglikelihood s’impose (tableau tbl-distribs).

    @@ -2156,7 +2156,7 @@

    Par conséquent, si un matin à Toronto votre bus a plus de 45 minutes de retard, bravo, vous êtes tombé sur une des très rares occasions où un tel retard se produit!

    2.5.4.2.2 Accidents de vélo à Montréal
    -

    Le second jeu de données représente le nombre d’accidents de la route impliquant un vélo sur les intersections dans les quartiers centraux de Montréal (figure 2.33). Le jeu de données complet est disponible sur le site des données ouvertes de la Ville de Montréal. Puisque ces données correspondent à des comptages, la première distribution à envisager est la distribution de Poisson. Cependant, puisque nous aurons également un grand nombre d’intersections sans accident, il serait judicieux de tester la distribution de Poisson avec excès de zéro.

    +

    Le second jeu de données représente le nombre d’accidents de la route impliquant un vélo sur les intersections dans les quartiers centraux de Montréal (figure fig-accmtl). Le jeu de données complet est disponible sur le site des données ouvertes de la Ville de Montréal. Puisque ces données correspondent à des comptages, la première distribution à envisager est la distribution de Poisson. Cependant, puisque nous aurons également un grand nombre d’intersections sans accident, il serait judicieux de tester la distribution de Poisson avec excès de zéro.

    library(ggplot2)
     # charger le jeu de données
    @@ -2177,7 +2177,7 @@ 

    -

    Nous avons effectivement de nombreux zéros, alors essayons d’ajuster nos deux distributions à ce jeu de données. Dans la figure 2.34, les barres grises représentent la distribution empirique du jeu de données et les barres rouges, les distributions théoriques ajustées. Nous utilisons ici le package gamlss.dist pour avoir la fonction de masse d’une distribution de Poisson avec excès de zéros.

    +

    Nous avons effectivement de nombreux zéros, alors essayons d’ajuster nos deux distributions à ce jeu de données. Dans la figure fig-accmtldist, les barres grises représentent la distribution empirique du jeu de données et les barres rouges, les distributions théoriques ajustées. Nous utilisons ici le package gamlss.dist pour avoir la fonction de masse d’une distribution de Poisson avec excès de zéros.

    library(gamlss.dist)
     # Ajuster le modèle de poisson
    @@ -2218,7 +2218,7 @@ 

    -

    Visuellement, comme nous pouvons l’observer à la figure 2.34), le modèle avec excès de zéro semble s’imposer. Nous pouvons vérifier cette impression avec la comparaison des loglikelihood.

    +

    Visuellement, comme nous pouvons l’observer à la figure fig-accmtldist), le modèle avec excès de zéro semble s’imposer. Nous pouvons vérifier cette impression avec la comparaison des loglikelihood.

    print(model_poisson$loglik)
    @@ -2259,7 +2259,7 @@

    2.5.5 Transformation des variables

    2.5.5.1 Transformations visant à atteindre la normalité

    -

    Comme énoncé au début de cette section, plusieurs méthodes statistiques nécessitent que la variable quantitative soit normalement distribuée. C’est notamment le cas de l’analyse de variance et des tests t (abordés dans les chapitres suivants) qui fournissent des résultats plus robustes lorsque la variable est normalement distribuée. Plusieurs transformations sont possibles, les plus courantes étant la racine carrée, le logarithme et l’inverse de la variable. Selon plusieurs auteur(e)s (notamment, les statisticiennes Barbara G. Tabacknick et Linda S. Fidell (2007, 89)), en fonction du type (positive ou négative) et du degré d’asymétrie, les transformations suivantes sont possibles afin d’améliorer la normalité de la variable :

    +

    Comme énoncé au début de cette section, plusieurs méthodes statistiques nécessitent que la variable quantitative soit normalement distribuée. C’est notamment le cas de l’analyse de variance et des tests t (abordés dans les chapitres suivants) qui fournissent des résultats plus robustes lorsque la variable est normalement distribuée. Plusieurs transformations sont possibles, les plus courantes étant la racine carrée, le logarithme et l’inverse de la variable. Selon plusieurs auteur(e)s (notamment, les statisticiennes Barbara G. Tabacknick et Linda S. Fidell (2007, 89)), en fonction du type (positive ou négative) et du degré d’asymétrie, les transformations suivantes sont possibles afin d’améliorer la normalité de la variable :

    • Asymétrie positive modérée : la racine carrée de la variable X avec la fonction sqrt(df$x).
    • Asymétrie positive importante : le logarithme de la variable avec log10(df$x).
    • @@ -2299,7 +2299,7 @@

      Transformation des variables pour atteindre la normalité : ce n’est pas toujours la panacée!

    -

    La transformation des données fait et fera encore longtemps débat à la fois parmi les statisticien(ne)s, et les personnes utilisatrices débutantes ou avancées des méthodes quantitatives. Field et al. (2012, 193) résument le tout avec humour : « to transform or not transform, that is the question ».

    +

    La transformation des données fait et fera encore longtemps débat à la fois parmi les statisticien(ne)s, et les personnes utilisatrices débutantes ou avancées des méthodes quantitatives. Field et al. (2012, 193) résument le tout avec humour : « to transform or not transform, that is the question ».

    Avantages de la transformation

    • L’obtention de résultats plus robustes.

    • @@ -2307,7 +2307,7 @@

      Inconvénients de la transformation

        -
      • Une variable transformée est plus difficile à interpréter puisque cela change l’unité de mesure de la variable. Prenons un exemple concret : vous souhaitez comparer les moyennes de revenu de deux groupes A et B. Vous obtenez une différence de 15 000 $, soit une valeur facile à interpréter. Par contre, si la variable a été préalablement transformée en logarithme, il est possible que vous obteniez une différence de 9, ce qui est beaucoup moins parlant. Aussi, en transformant la variable en log, vous ne comparez plus les moyennes arithmétiques des deux groupes, mais plutôt leurs moyennes géométriques (Field, Miles et Field 2012, 193).

      • +
      • Une variable transformée est plus difficile à interpréter puisque cela change l’unité de mesure de la variable. Prenons un exemple concret : vous souhaitez comparer les moyennes de revenu de deux groupes A et B. Vous obtenez une différence de 15 000 $, soit une valeur facile à interpréter. Par contre, si la variable a été préalablement transformée en logarithme, il est possible que vous obteniez une différence de 9, ce qui est beaucoup moins parlant. Aussi, en transformant la variable en log, vous ne comparez plus les moyennes arithmétiques des deux groupes, mais plutôt leurs moyennes géométriques (Field, Miles et Field 2012, 193).

      • Pourquoi perdre la forme initiale de la distribution du phénomène à expliquer? Il est possible, pour de nombreuses méthodes de choisir la distribution que nous souhaitons utiliser, il n’est donc pas nécessaire de toujours se limiter à la distribution normale. Par exemple, dans les modèles de régression généralisés (GLM), nous pourrions indiquer que la variable indépendante suit une distribution de Student plutôt que de vouloir à tout prix la rendre normale. De même, certains tests non paramétriques permettent d’analyser des variables ne suivant pas une distribution normale.

      Démarche à suivre avant et après la transformation

      @@ -2323,14 +2323,14 @@

      Les trois transformations les plus couramment utilisées sont :

      • -La côte \(z\) (z score en anglais) qui consiste à soustraire à chaque valeur sa moyenne (soit un centrage), puis à la diviser par son écart-type (soit une réduction) (équation 2.29). Par conséquent, nous parlons aussi de variable centrée réduite qui a comme propriétés intéressantes une moyenne égale à 0 et un écart-type égal à 1 (la variance est aussi égale à 1 puisque 12 = 1). Nous verrons que cette transformation est largement utilisée dans les méthodes de classification (chapitre 13) et les méthodes factorielles (chapitre 12).
      • +La côte \(z\) (z score en anglais) qui consiste à soustraire à chaque valeur sa moyenne (soit un centrage), puis à la diviser par son écart-type (soit une réduction) (équation eq-scorez). Par conséquent, nous parlons aussi de variable centrée réduite qui a comme propriétés intéressantes une moyenne égale à 0 et un écart-type égal à 1 (la variance est aussi égale à 1 puisque 12 = 1). Nous verrons que cette transformation est largement utilisée dans les méthodes de classification (chapitre sec-chap13) et les méthodes factorielles (chapitre sec-chap12).

      \[ z= \frac{x_i-\mu}{\sigma} \tag{2.29}\]

        -
      • La transformation en rang qui consiste simplement à trier une variable en ordre croissant, puis à affecter le rang de chaque observation de 1 à \(n\). Cette transformation est très utilisée quand la variable est très anormalement distribuée, notamment pour calculer le coefficient de corrélation de Spearman (section 4.3.3) et certains tests non paramétriques (sections 6.1.2 et 6.2.2).

      • -
      • La transformation sur une échelle de 0 à 1 (ou de 0 à 100) qui consiste à soustraite à chaque observation la valeur minimale et à diviser le tout par l’étendue (équation 2.30).

      • +
      • La transformation en rang qui consiste simplement à trier une variable en ordre croissant, puis à affecter le rang de chaque observation de 1 à \(n\). Cette transformation est très utilisée quand la variable est très anormalement distribuée, notamment pour calculer le coefficient de corrélation de Spearman (section sec-0433) et certains tests non paramétriques (sections sec-0612 et sec-0622).

      • +
      • La transformation sur une échelle de 0 à 1 (ou de 0 à 100) qui consiste à soustraite à chaque observation la valeur minimale et à diviser le tout par l’étendue (équation eq-t01).

      \[ X_{\in\lbrack0-1\rbrack}= \frac{x_i-max}{max-min} \text{ ou } X_{\in\lbrack0-100\rbrack}= \frac{x_i-min}{max-min}\times100 @@ -2453,7 +2453,7 @@

      Utilité des transformations

    -

    Ces trois transformations sont parfois utilisées pour générer un indice composite à partir de plusieurs variables ou encore dans une analyse de sensibilité avec les indices de Sobol (1993).

    +

    Ces trois transformations sont parfois utilisées pour générer un indice composite à partir de plusieurs variables ou encore dans une analyse de sensibilité avec les indices de Sobol (1993).

    @@ -2626,7 +2626,7 @@

    -

    Pour construire un histogramme avec la courbe normale, consultez la section 3.2.1.3 ou la syntaxe ci-dessous.

    +

    Pour construire un histogramme avec la courbe normale, consultez la section sec-03213 ou la syntaxe ci-dessous.

    moyenne <- mean(dataMTL$PctFRev)
     ecart_type <- sd(dataMTL$PctFRev)
    @@ -2979,7 +2979,7 @@ 

    2.6 Statistiques descriptives sur des variables qualitatives et semi-qualitatives

    2.6.1 Fréquences

    -

    En guise de rappel, les variables nominales, ordinales et semi-quantitatives comprennent plusieurs modalités pour lesquelles plusieurs types de fréquences sont généralement calculées. Pour illustrer le tout, nous avons extrait du recensement de 2016 de Statistique Canada les effectifs des modalités de la variable sur le principal mode de transport utilisé pour les déplacements domicile-travail, et ce, pour la subdivision de recensement (MRC) de l’île de Montréal (tableau 2.10). Les différents types de fréquences sont les suivantes :

    +

    En guise de rappel, les variables nominales, ordinales et semi-quantitatives comprennent plusieurs modalités pour lesquelles plusieurs types de fréquences sont généralement calculées. Pour illustrer le tout, nous avons extrait du recensement de 2016 de Statistique Canada les effectifs des modalités de la variable sur le principal mode de transport utilisé pour les déplacements domicile-travail, et ce, pour la subdivision de recensement (MRC) de l’île de Montréal (tableau tbl-Frequences). Les différents types de fréquences sont les suivantes :

    • Les fréquences absolues simples (FAS) ou fréquences observées représentent le nombre d’observations pour chacune des modalités. Par exemple, sur 857 540 personnes réalisant des trajets domicile-travail (ligne totale), seulement 30 645 optent pour le vélo, alors que 427 530 conduisent un véhicule motorisé (automobile, camion ou fourgonnette) comme principal mode de transport.

    • Les fréquences relatives simples (FRS) sont les proportions de chaque modalité sur le total (\(\mbox{30 645}/\mbox{857 540}=\mbox{0,036}\)); leur somme est égale à 1. Elles peuvent bien entendu être exprimées en pourcentage (\(\mbox{30 645}/\mbox{857 540} \times \mbox{100}=\mbox{3,57}\)); leur somme est alors égale à 100 %. Par exemple, 3,7 % de ces personnes utilisent le vélo comme mode de transport principal.

    • @@ -3087,9 +3087,9 @@

      Le calcul et l’analyse des fréquences cumulées (absolues et relatives) sont très souvent inutiles pour les variables nominales.

      -

      Par exemple, au tableau 2.10, la fréquence cumulée relative (en %) est de 87,43 % pour la troisième ligne. Cela signifie que 87,43 % des navetteur(ve)s se déplacent en véhicule motorisé (personne conductrice ou passagère) ou en transport en commun. Par contre, si la troisième modalité avait été à pied, le pourcentage aurait été de 61,02 (\(\mbox{52,93}+\mbox{8,09}\)). Si vous souhaitez calculer les fréquences cumulées sur une variable nominale, assurez-vous que l’ordre des modalités vous convient et de le modifier au besoin. Sinon, abstenez-vous de les calculer!

      +

      Par exemple, au tableau tbl-Frequences, la fréquence cumulée relative (en %) est de 87,43 % pour la troisième ligne. Cela signifie que 87,43 % des navetteur(ve)s se déplacent en véhicule motorisé (personne conductrice ou passagère) ou en transport en commun. Par contre, si la troisième modalité avait été à pied, le pourcentage aurait été de 61,02 (\(\mbox{52,93}+\mbox{8,09}\)). Si vous souhaitez calculer les fréquences cumulées sur une variable nominale, assurez-vous que l’ordre des modalités vous convient et de le modifier au besoin. Sinon, abstenez-vous de les calculer!

      Les fréquences cumulées : très utiles pour l’analyse des variables ordinales ou semi-quantitatives

      -

      Pour des modalités hiérarchisées (variable ordinale ou semi-quantitative), l’analyse des fréquences cumulées (absolues et relatives) est par contre très intéressante. Par exemple, au tableau 2.11, elle permet de constater rapidement que sur l’île de Montréal, plus du quart de la population à moins de 25 ans (27,91 %) et 83,33 %, moins de 65 ans.

      +

      Pour des modalités hiérarchisées (variable ordinale ou semi-quantitative), l’analyse des fréquences cumulées (absolues et relatives) est par contre très intéressante. Par exemple, au tableau tbl-Frequences2, elle permet de constater rapidement que sur l’île de Montréal, plus du quart de la population à moins de 25 ans (27,91 %) et 83,33 %, moins de 65 ans.

    @@ -3175,7 +3175,7 @@

    -

    Différents graphiques peuvent être construits pour illustrer la répartition des observations : les graphiques en barres (verticales et horizontales) avec les fréquences absolues et les diagrammes circulaires ou en anneau pour les fréquences relatives (figure 2.37). Ces graphiques seront présentés plus en détail dans le chapitre suivant.

    +

    Différents graphiques peuvent être construits pour illustrer la répartition des observations : les graphiques en barres (verticales et horizontales) avec les fréquences absolues et les diagrammes circulaires ou en anneau pour les fréquences relatives (figure fig-GraphiquesFreq1). Ces graphiques seront présentés plus en détail dans le chapitre suivant.

    @@ -3186,7 +3186,7 @@

    2.6.2 Mise en œuvre dans R

    -

    La syntaxe ci-dessous permet de calculer les différentes fréquences présentées au tableau 2.11. Notez que pour les fréquences cumulées, nous utilisons la fonction cumsum.

    +

    La syntaxe ci-dessous permet de calculer les différentes fréquences présentées au tableau tbl-Frequences2. Notez que pour les fréquences cumulées, nous utilisons la fonction cumsum.

    # Vecteur pour les noms des modalités
     Modalite <- c("0 à 14 ans",
    @@ -3222,7 +3222,7 @@ 

    2.7 Statistiques descriptives pondérées : pour aller plus loin

    -

    Dans la section 2.5, les différentes statistiques descriptives sur des variables quantitatives – paramètres de tendance centrale, de position, de dispersion et de forme – ont été largement abordées. Il est possible de calculer ces différentes statistiques en tenant compte d’une pondération. La statistique descriptive pondérée la plus connue est certainement la moyenne arithmétique pondérée. Son calcul est très simple. Pour chaque observation, deux valeurs sont disponibles :

    +

    Dans la section sec-025, les différentes statistiques descriptives sur des variables quantitatives – paramètres de tendance centrale, de position, de dispersion et de forme – ont été largement abordées. Il est possible de calculer ces différentes statistiques en tenant compte d’une pondération. La statistique descriptive pondérée la plus connue est certainement la moyenne arithmétique pondérée. Son calcul est très simple. Pour chaque observation, deux valeurs sont disponibles :

    • \(x_i\), soit la valeur de la variable \(X\) pour l’observation \(i\) @@ -3301,18 +3301,18 @@

      Calcul d’autres statistiques descriptives pondérées

      -

      Nous ne reportons pas ici les formules des versions pondérées de toutes les statistiques descriptives. Retenez toutefois le principe suivant permettant de les calculer à partir de l’exemple du tableau 2.12. Pour la variable X, dupliquons respectivement 20, 80, 50, 200 fois les observations 1 à 4. Si nous calculons la moyenne arithmétique sur ces valeurs dupliquées, alors cette valeur est identique à celle de la moyenne arithmétique pondérée. Le même principe reposant sur la duplication des valeurs s’applique à l’ensemble des statistiques descriptives.

      +

      Nous ne reportons pas ici les formules des versions pondérées de toutes les statistiques descriptives. Retenez toutefois le principe suivant permettant de les calculer à partir de l’exemple du tableau tbl-MoyPondCalcul. Pour la variable X, dupliquons respectivement 20, 80, 50, 200 fois les observations 1 à 4. Si nous calculons la moyenne arithmétique sur ces valeurs dupliquées, alors cette valeur est identique à celle de la moyenne arithmétique pondérée. Le même principe reposant sur la duplication des valeurs s’applique à l’ensemble des statistiques descriptives.

      -

      Dans un article récent, Alvarenga et al. (2018) évaluent l’accessibilité aux aires de jeux dans les parcs de la Communauté métropolitaine de Montréal (CMM). Pour les 881 secteurs de recensement de la CMM, ils ont calculé la distance à pied à l’aire de jeux la plus proche à travers le réseau de rues. Ce résultat, cartographié à la figure 2.38), permet d’avancer le constat suivant : « la quasi-totalité des secteurs de recensement de l’agglomération de Montréal présente des distances de l’aire de jeux la plus proche inférieures à 500 m, alors que les secteurs situés à plus d’un kilomètre d’une aire de jeux sont très majoritairement localisés dans les couronnes nord et sud de la CMM » (De Alvarenga, Apparicio et Séguin 2018, 238).

      -

      Pour chaque secteur de recensement, Alvarenga et al. (2018) disposent des données suivantes :

      +

      Dans un article récent, Alvarenga et al. (2018) évaluent l’accessibilité aux aires de jeux dans les parcs de la Communauté métropolitaine de Montréal (CMM). Pour les 881 secteurs de recensement de la CMM, ils ont calculé la distance à pied à l’aire de jeux la plus proche à travers le réseau de rues. Ce résultat, cartographié à la figure fig-ParcCMM), permet d’avancer le constat suivant : « la quasi-totalité des secteurs de recensement de l’agglomération de Montréal présente des distances de l’aire de jeux la plus proche inférieures à 500 m, alors que les secteurs situés à plus d’un kilomètre d’une aire de jeux sont très majoritairement localisés dans les couronnes nord et sud de la CMM » (De Alvarenga, Apparicio et Séguin 2018, 238).

      +

      Pour chaque secteur de recensement, Alvarenga et al. (2018) disposent des données suivantes :

      • \(x_i\), soit la distance à l’aire de jeux la plus proche pour le secteur de recensement i;
      • \(w_i\), la pondération, soit le nombre d’enfants de moins de dix ans.
      -

      Il est alors possible de calculer les statistiques descriptives de la proximité à l’aire de jeux la plus proche en tenant compte du nombre d’enfants résidant dans chaque secteur de recensement (tableau 2.13). Cet exercice permet de conclure que : « […] globalement, les enfants ont une bonne accessibilité aux aires de jeux sur le territoire de la CMM. […] Les enfants sont en moyenne à un peu plus de 500 m de l’aire de jeux la plus proche (moyenne = 559; médiane = 512). Toutefois, les valeurs percentiles extrêmes signalent que respectivement 10 % et 5 % des enfants résident à près de 800 m et à plus de 1000 m de l’aire de jeux la plus proche » (2018, 236).

      +

      Il est alors possible de calculer les statistiques descriptives de la proximité à l’aire de jeux la plus proche en tenant compte du nombre d’enfants résidant dans chaque secteur de recensement (tableau tbl-MoyPondParc). Cet exercice permet de conclure que : « […] globalement, les enfants ont une bonne accessibilité aux aires de jeux sur le territoire de la CMM. […] Les enfants sont en moyenne à un peu plus de 500 m de l’aire de jeux la plus proche (moyenne = 559; médiane = 512). Toutefois, les valeurs percentiles extrêmes signalent que respectivement 10 % et 5 % des enfants résident à près de 800 m et à plus de 1000 m de l’aire de jeux la plus proche » (2018, 236).

      Figure 2.38: Accessibilité aux aires de jeux par secteur de recensement, Communauté métropolitaine de Montréal, 2016
      @@ -3471,7 +3471,7 @@

      -Relisez au besoin la section 2.1.2. +Relisez au besoin la section sec-0212.
      @@ -3516,7 +3516,7 @@

      -Relisez au besoin le début de la section 1.2. +Relisez au besoin le début de la section sec-012.
      @@ -3545,7 +3545,7 @@

      -Relisez au besoin la section 2.2. +Relisez au besoin la section sec-022.
      @@ -3574,7 +3574,7 @@

      -Relisez au besoin la section 2.2.4. +Relisez au besoin la section sec-0224.
      @@ -3603,7 +3603,7 @@

      -Relisez au besoin la section 2.4. +Relisez au besoin la section sec-024.
      @@ -3632,7 +3632,7 @@

      -Relisez au besoin la section 2.5.1. +Relisez au besoin la section sec-0251.
      @@ -3685,7 +3685,7 @@

      -Relisez au besoin la section 2.5.2. +Relisez au besoin la section sec-0252.
      @@ -3730,7 +3730,7 @@

      -Relisez au besoin la section 2.5.3. +Relisez au besoin la section sec-0253.
      @@ -3775,7 +3775,7 @@

      -Relisez au besoin la section 2.5.4. +Relisez au besoin la section sec-0254.
      @@ -3820,7 +3820,7 @@

      -Relisez au besoin la section 2.5.5.2. +Relisez au besoin la section sec-02552.
      @@ -3861,7 +3861,7 @@

      - -

      Pour le moment, le graphique est vide (figure 3.2). La seconde étape consiste à lui ajouter des données (au travers du paramètre data) et à définir les dimensions à associer aux données (avec le paramètre mapping et la fonction aes()). Dans notre cas, nous voulons utiliser les coordonnées X pour représenter la largeur des sépales, et les coordonnées Y pour représenter la longueur des sépales. Enfin, nous souhaitons représenter les observations par des points, nous utiliserons donc la géométrie geom_point.

      +

      Pour le moment, le graphique est vide (figure fig-fig31). La seconde étape consiste à lui ajouter des données (au travers du paramètre data) et à définir les dimensions à associer aux données (avec le paramètre mapping et la fonction aes()). Dans notre cas, nous voulons utiliser les coordonnées X pour représenter la largeur des sépales, et les coordonnées Y pour représenter la longueur des sépales. Enfin, nous souhaitons représenter les observations par des points, nous utiliserons donc la géométrie geom_point.

      ggplot(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
         geom_point()
      @@ -464,7 +464,7 @@

      -

      Ce graphique ne comprend qu’un seul calque avec une géométrie de type point (figure 3.3). Chaque calque est ajouté avec l’opérateur + qui permet de superposer des calques, le dernier apparaissant au-dessus des autres. Les arguments mapping et data sont définis ici dans la fonction ggplot et sont donc appliqués à tous les calques qui composent le graphique. Il est aussi possible de définir mapping et data au sein des fonctions des géométries :

      +

      Ce graphique ne comprend qu’un seul calque avec une géométrie de type point (figure fig-fig32). Chaque calque est ajouté avec l’opérateur + qui permet de superposer des calques, le dernier apparaissant au-dessus des autres. Les arguments mapping et data sont définis ici dans la fonction ggplot et sont donc appliqués à tous les calques qui composent le graphique. Il est aussi possible de définir mapping et data au sein des fonctions des géométries :

      ggplot() +
         geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris)
      @@ -475,7 +475,7 @@

      -

      La troisième étape consiste à ajouter au graphique des annotations. Pour notre cas, il faudrait ajouter un titre, un sous-titre et des intitulés plus clairs pour les axes X et Y, ce qu’il est possible de faire avec la fonction labs (figure 3.5).

      +

      La troisième étape consiste à ajouter au graphique des annotations. Pour notre cas, il faudrait ajouter un titre, un sous-titre et des intitulés plus clairs pour les axes X et Y, ce qu’il est possible de faire avec la fonction labs (figure fig-fig34).

      ggplot() +
         geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
      @@ -491,7 +491,7 @@ 

    3.1.2 Types de géométries

    -

    Le package ggplot2 permet d’utiliser un très grand nombre de géométries différentes. Dans le tableau 3.1, nous avons reporté les principales géométries disponibles afin que vous puissiez vous faire une idée du « bestiaire » existant. Il ne s’agit que d’un extrait des principales fonctions. Sachez qu’il existe aussi des packages proposant des géométries supplémentaires pour compléter ggplot2.

    +

    Le package ggplot2 permet d’utiliser un très grand nombre de géométries différentes. Dans le tableau tbl-geometries, nous avons reporté les principales géométries disponibles afin que vous puissiez vous faire une idée du « bestiaire » existant. Il ne s’agit que d’un extrait des principales fonctions. Sachez qu’il existe aussi des packages proposant des géométries supplémentaires pour compléter ggplot2.

    @@ -647,7 +647,7 @@

    3.1.4 Utilisation des thèmes

    De nombreux autres éléments peuvent être modifiés dans un graphique comme les paramètres des polices, l’arrière-plan, la grille de repères, etc. Il peut être fastidieux de paramétrer tous ces éléments. Une option intéressante est d’utiliser des thèmes déjà préconstruits. Le package ggplot2 propose une dizaine de thèmes : constatons leur impact sur le graphique précédent.

    ggplot() +
    @@ -665,7 +665,7 @@ 

    ggplot() +
    @@ -683,7 +683,7 @@ 

    ggplot() +
    @@ -701,7 +701,7 @@ 

    ggplot() +
    @@ -720,7 +720,7 @@ 

    Il est aussi possible d’utiliser le package ggthemes qui apporte des thèmes complémentaires intéressants dont :

    library(ggthemes)
    @@ -739,7 +739,7 @@ 

      -
    • Le thème economist (theme_economist, inspiré de la revue du même nom) (figure 3.14)
    • +
    • Le thème economist (theme_economist, inspiré de la revue du même nom) (figure fig-fig313)
    ggplot() +
    @@ -757,7 +757,7 @@ 

    ggplot() +
    @@ -784,7 +784,7 @@ 

    3.1.5.1 ggplot2 et ses facettes

    -

    Nous pourrions souhaiter réaliser une figure composite avec le jeu de données iris et séparer notre nuage de points en trois graphiques distincts selon l’espèce des iris (figure 3.16). Pour cela, il faut au préalable convertir la variable espèce en facteur.

    +

    Nous pourrions souhaiter réaliser une figure composite avec le jeu de données iris et séparer notre nuage de points en trois graphiques distincts selon l’espèce des iris (figure fig-fig315). Pour cela, il faut au préalable convertir la variable espèce en facteur.

    iris$Species_fac <- as.factor(iris$Species)
     
    @@ -802,7 +802,7 @@ 

    -

    Notez que le nom de la variable (ici Species_fac) doit être spécifié au sein d’une sous-fonction vars : vars(Species_fac). Nous aurions aussi pu réaliser le graphique sur une seule ligne en spécifiant ncol = 3 (figure 3.17).

    +

    Notez que le nom de la variable (ici Species_fac) doit être spécifié au sein d’une sous-fonction vars : vars(Species_fac). Nous aurions aussi pu réaliser le graphique sur une seule ligne en spécifiant ncol = 3 (figure fig-fig316).

    ggplot() +
       geom_point(mapping = aes(x = Sepal.Length, y = Sepal.Width), data = iris) +
    @@ -820,7 +820,7 @@ 

    3.1.5.2 Arrangement des graphiques

    -

    La solution avec les facettes est très pratique, mais également très limitée puisqu’elle ne permet pas de créer une figure avec des graphiques combinant plusieurs types de géométries. ggarrange du package ggpubr permet tout simplement de combiner des graphiques déjà existant. Créons deux nuages de points comparant plusieurs variables en fonction de l’espèce des iris, puis combinons-les (figure 3.18). Attribuons également aux points une couleur en fonction de l’espèce des fleurs, afin de mieux les distinguer en associant la variable Species au paramètre color.

    +

    La solution avec les facettes est très pratique, mais également très limitée puisqu’elle ne permet pas de créer une figure avec des graphiques combinant plusieurs types de géométries. ggarrange du package ggpubr permet tout simplement de combiner des graphiques déjà existant. Créons deux nuages de points comparant plusieurs variables en fonction de l’espèce des iris, puis combinons-les (figure fig-fig317). Attribuons également aux points une couleur en fonction de l’espèce des fleurs, afin de mieux les distinguer en associant la variable Species au paramètre color.

    library(ggpubr)
     
    @@ -867,7 +867,7 @@ 

    3.1.6 Couleur

    Dans un graphique, la couleur peut être utilisée à la fois pour représenter une variable quantitative (dégradé de couleur ou mise en classes), ou une variable qualitative (couleur par catégorie). Dans ggplot2, il est possible d’attribuer une couleur au contour des géométries avec l’argument color et au remplissage avec l’argument fill. Il est possible de spécifier une couleur de trois façons dans R :

      -
    • En utilisant le nom de la couleur dans une chaîne de caractère : "chartreuse4". R dispose de 657 noms de couleurs prédéfinis. Pour tous les afficher, utilisez la fonction colors(), qui permet de les visualiser (figure 3.19).
    • +
    • En utilisant le nom de la couleur dans une chaîne de caractère : "chartreuse4". R dispose de 657 noms de couleurs prédéfinis. Pour tous les afficher, utilisez la fonction colors(), qui permet de les visualiser (figure fig-colors).

    @@ -877,7 +877,7 @@

    En indiquant le code hexadécimal de la couleur. Il s’agit d’une suite de six lettres et de chiffres précédée par un dièse : "#99ff33".

  • En utilisant une notation RGB (rouge, vert, bleu, transparence). Cette notation doit contenir quatre nombres entre 0 et 1 (0 % et 100 %), indiquant respectivement la quantité de rouge, de vert, de bleu et la transparence. Ces quatre nombres sont donnés comme argument à la fonction rgb : rgb(0.6, 1, 0.2, 0).

  • -

    Le choix des couleurs est un problème plus complexe que la manière de les spécifier. Il existe d’ailleurs tout un pan de la sémiologie graphique dédié à la question du choix et de l’association des couleurs. Une première ressource intéressante est ColorBrewer. Il s’agit d’une sélection de palettes de couleurs particulièrement efficaces et dont certaines sont même adaptées pour les personnes daltoniennes (figure 3.20). Il est possible d’accéder directement aux palettes dans R grâce au package RColorBrewer et la fonction brewer.pal :

    +

    Le choix des couleurs est un problème plus complexe que la manière de les spécifier. Il existe d’ailleurs tout un pan de la sémiologie graphique dédié à la question du choix et de l’association des couleurs. Une première ressource intéressante est ColorBrewer. Il s’agit d’une sélection de palettes de couleurs particulièrement efficaces et dont certaines sont même adaptées pour les personnes daltoniennes (figure fig-colorBrewer). Il est possible d’accéder directement aux palettes dans R grâce au package RColorBrewer et la fonction brewer.pal :

    library(RColorBrewer)
     display.brewer.all()
    @@ -907,7 +907,7 @@

    L’histogramme permet de décrire graphiquement la forme de la distribution d’une variable. Pour le réaliser, nous utilisons la fonction geom_histogram. Le paramètre le plus important est le nombre de barres (bins) qui composent l’histogramme. Plus ce nombre est grand, plus l’histogramme est précis et, à l’inverse, plus il est petit, plus l’histogramme est simplifié. En revanche, il faut éviter d’utiliser un nombre de barres trop élevé comparativement au nombre d’observations disponibles dans le jeu de données, sinon l’histogramme risque d’avoir plein de trous.

    3.2.1.1 Histogramme simple

    -

    Générons quatre variables ayant respectivement une distribution gaussienne, Student, Gamma et bêta, puis réalisons un histogramme pour chacune de ces variables et combinons-les avec la fonction ggarrange (figure 3.21).

    +

    Générons quatre variables ayant respectivement une distribution gaussienne, Student, Gamma et bêta, puis réalisons un histogramme pour chacune de ces variables et combinons-les avec la fonction ggarrange (figure fig-fig318).

    distribs <- data.frame(
       gaussien = rnorm(1000, mean = 5, sd = 1.5),
    @@ -942,7 +942,7 @@ 

    -

    Notez que cette syntaxe est très lourde. Dans le cas présent, il serait plus judicieux d’utiliser la fonction facet_wrap. Pour cela, nous devons au préalable empiler nos données, ce qui signifie changer la forme du DataFrame actuel, qui comprend quatre colonnes (gaussien, Gamma, bêta et student) et 1000 observations, pour qu’il n’ait plus que deux colonnes (la valeur originale et le nom de l’ancienne colonne) et 4000 observations. La figure 3.22 décrit graphiquement ce processus qui peut être effectué avec la fonction melt du package reshape2.

    +

    Notez que cette syntaxe est très lourde. Dans le cas présent, il serait plus judicieux d’utiliser la fonction facet_wrap. Pour cela, nous devons au préalable empiler nos données, ce qui signifie changer la forme du DataFrame actuel, qui comprend quatre colonnes (gaussien, Gamma, bêta et student) et 1000 observations, pour qu’il n’ait plus que deux colonnes (la valeur originale et le nom de l’ancienne colonne) et 4000 observations. La figure fig-fig319 décrit graphiquement ce processus qui peut être effectué avec la fonction melt du package reshape2.

    Figure 3.22: Empiler les données d’un DataFrame
    @@ -1400,7 +1400,7 @@

    3.2.7 Graphique en barres

    -

    Les graphiques en barres permettent de représenter des quantités (hauteur des barres) réparties dans des catégories (une barre par catégorie). Nous proposons ici un exemple avec des données de déplacements issues de l’Enquête origine-destination 2017 - Région Québec-Lévis, au niveau des grands secteurs. La figure 3.44, tirée du rapport intitulé La mobilité des personnes dans la région de Québec-Lévis (Volet Enquête-ménages : faits saillants) délimite ces grands secteurs.

    +

    Les graphiques en barres permettent de représenter des quantités (hauteur des barres) réparties dans des catégories (une barre par catégorie). Nous proposons ici un exemple avec des données de déplacements issues de l’Enquête origine-destination 2017 - Région Québec-Lévis, au niveau des grands secteurs. La figure fig-fig342, tirée du rapport intitulé La mobilité des personnes dans la région de Québec-Lévis (Volet Enquête-ménages : faits saillants) délimite ces grands secteurs.

    Figure 3.45: Grands secteurs de Québec
    @@ -1722,14 +1722,14 @@

    groupnameFontsize = 12, groupnamePadding = 5) }

    -
    -
    Figure 3.51: Diagramme d’accord
    +
    +
    Figure 3.51: Diagramme d’accord

    Le graphique permet de remarquer que la plupart des flux s’effectuent au sein d’un même secteur. La majorité des déplacements se font au sein du secteur Sainte-Foy (segment rouge central). Nous pouvons cependant constater que les secteurs des Rivières, de la Cité-Limoilou et de la Haute-Saint-Charles attirent une plus grande quantité et diversité de flux. Si vous lisez ce livre dans un navigateur web (et pas au format pdf), le graphique est interactif! En plaçant votre souris sur un lien, vous verrez s’afficher le nombre de déplacements qu’il représente.

    3.3.3 Nuage de mots

    -

    Un nuage de mots est un graphique utilisé en analyse de texte pour représenter les mots les plus importants d’un document. Mesurer l’importance des termes dans un document est une discipline à part entière (Natural Language Processing). Nous proposons un simple exemple ici avec la méthode TextRank (basée sur la théorie des graphes) proposée par Mihalcea et Tarau (2004) et implémentée dans le package textrank. Nous avons également besoin des packages udpipe (fournissant des dictionnaires linguistiques), RColorBrewer (pour sélectionner une palette de couleurs) et wordcloud2 (pour générer le graphique). En guise d’exemple, nous avons choisi d’extraire les textes de deux schémas d’aménagement et de développement (SAD), ceux des agglomérations de Québec et de Montréal en vigueur en 2020. Il s’agit de deux documents de planification définissant les lignes directrices de l’organisation physique du territoire des municipalités régionales de comté (MRC) ou des agglomérations. Pour ces deux documents, nous nous concentrons sur le chapitre portant sur les grandes orientations d’aménagement et de développement, soit les pages 30 à 135 pour Québec et 30 à 97 pour Montréal. Pour extraire les textes des fichiers pdf, nous utilisons le package pdftools.

    +

    Un nuage de mots est un graphique utilisé en analyse de texte pour représenter les mots les plus importants d’un document. Mesurer l’importance des termes dans un document est une discipline à part entière (Natural Language Processing). Nous proposons un simple exemple ici avec la méthode TextRank (basée sur la théorie des graphes) proposée par Mihalcea et Tarau (2004) et implémentée dans le package textrank. Nous avons également besoin des packages udpipe (fournissant des dictionnaires linguistiques), RColorBrewer (pour sélectionner une palette de couleurs) et wordcloud2 (pour générer le graphique). En guise d’exemple, nous avons choisi d’extraire les textes de deux schémas d’aménagement et de développement (SAD), ceux des agglomérations de Québec et de Montréal en vigueur en 2020. Il s’agit de deux documents de planification définissant les lignes directrices de l’organisation physique du territoire des municipalités régionales de comté (MRC) ou des agglomérations. Pour ces deux documents, nous nous concentrons sur le chapitre portant sur les grandes orientations d’aménagement et de développement, soit les pages 30 à 135 pour Québec et 30 à 97 pour Montréal. Pour extraire les textes des fichiers pdf, nous utilisons le package pdftools.

    Nous devons donc réaliser les étapes suivantes pour produire le nuage de mots :

    1. Extraire les sections qui nous intéressent des fichiers pdf.
    2. @@ -1873,7 +1873,7 @@

      spatialdf <- st_read("data/bivariee/IlotsVeg2006.shp")

    Reading layer `IlotsVeg2006' from data source 
    -  `C:\Users\appariciop\OneDrive - USherbrooke\____TEMP\_____QUATRO_MethodesQuanti\data\bivariee\IlotsVeg2006.shp' 
    +  `C:\Users\appariciop\OneDrive - USherbrooke\Articles Publies ne pas supprimer\_Livres\BolR_MethodesQuantitatives\data\bivariee\IlotsVeg2006.shp' 
       using driver `ESRI Shapefile'
     Simple feature collection with 10213 features and 12 fields
     Geometry type: MULTIPOLYGON
    @@ -1980,7 +1980,7 @@ 

    3.5 Exportation des graphiques

    -

    Tous les graphiques que nous avons construits dans ce chapitre peuvent être exportés assez facilement. Dans RStudio, vous pouvez directement cliquer sur le bouton Export (figure 3.58) pour enregistrer votre figure au format image ou au format pdf (vectoriel). Notez qu’avec la seconde option, vous pourrez retoucher votre graphique avec un logiciel externe comme Inkscape ou Illustrator.

    +

    Tous les graphiques que nous avons construits dans ce chapitre peuvent être exportés assez facilement. Dans RStudio, vous pouvez directement cliquer sur le bouton Export (figure fig-fig356) pour enregistrer votre figure au format image ou au format pdf (vectoriel). Notez qu’avec la seconde option, vous pourrez retoucher votre graphique avec un logiciel externe comme Inkscape ou Illustrator.

    Figure 3.58: Exporter un graphique dans RStudio
    @@ -2028,7 +2028,7 @@

    -

    4.1 Bref retour sur le postulat de la relation linéaire

    -

    Vérifier le postulat de la linéarité consiste à évaluer si deux variables quantitatives varient dans le même sens ou bien en sens contraire. Toutefois, la relation entre deux variables quantitatives n’est pas forcément linéaire. En guise d’illustration, la figure 4.1 permet de distinguer quatre types de relations :

    +

    Vérifier le postulat de la linéarité consiste à évaluer si deux variables quantitatives varient dans le même sens ou bien en sens contraire. Toutefois, la relation entre deux variables quantitatives n’est pas forcément linéaire. En guise d’illustration, la figure fig-fig2 permet de distinguer quatre types de relations :

    • Le cas a illustre une relation linéaire positive entre les deux variables puisqu’elles vont dans le même sens. Autrement dit, quand les valeurs de X augmentent, celles de Y augmentent aussi. En guise d’exemple, pour les secteurs de recensement d’une métropole donnée, il est fort probable que le coût moyen du loyer soit associé positivement avec le revenu médian des ménages. Graphiquement parlant, il est clair qu’une droite dans ce nuage de points résumerait efficacement la relation entre ces deux variables.

    • Le cas b illustre une relation linéaire négative entre les deux variables puisqu’elles vont en sens inverse. Autrement dit, quand les valeurs de X augmentent, celles de Y diminuent, et inversement. En guise d’exemple, pour les secteurs de recensement d’une métropole donnée, il est fort probable que le revenu médian des ménages soit associé négativement avec le taux de chômage. De nouveau, une droite résumerait efficacement cette relation.

    • @@ -406,33 +406,33 @@

      Figure 4.1: Relations linéaires et curvilinéaires entre deux variables continues

    -

    Prenons un exemple concret pour illustrer le cas c. Dans une étude portant sur l’équité environnementale et la végétation à Montréal, Pham et al. (2012) ont montré qu’il existe une relation curvilinéaire entre l’âge médian des bâtiments résidentiels (axe des abscisses) et les couvertures végétales (axes des ordonnées) :

    +

    Prenons un exemple concret pour illustrer le cas c. Dans une étude portant sur l’équité environnementale et la végétation à Montréal, Pham et al. (2012) ont montré qu’il existe une relation curvilinéaire entre l’âge médian des bâtiments résidentiels (axe des abscisses) et les couvertures végétales (axes des ordonnées) :

    • La couverture de la végétation totale et celle des arbres augmentent quand l’âge médian des bâtiments croît jusqu’à atteindre un pic autour de 60 ans (autour de 1950). Nous pouvons supposer que les secteurs récemment construits, surtout ceux dans les banlieues, présentent des niveaux de végétation plus faibles. Au fur et à mesure que le quartier vieillit, les arbres plantés lors du développement résidentiel deviennent matures — canopée plus importante –, d’où l’augmentation des valeurs de la couverture végétale totale et de celle des arbres.

    • -
    • Par contre, dans les secteurs développés avant les années 1950, la densité du bâti est plus forte, laissant ainsi moins de place pour la végétation, ce qui explique une diminution des variables relatives à la couverture végétale (figure 4.2).

    • +
    • Par contre, dans les secteurs développés avant les années 1950, la densité du bâti est plus forte, laissant ainsi moins de place pour la végétation, ce qui explique une diminution des variables relatives à la couverture végétale (figure fig-fig3).

    Figure 4.2: Exemples de relations curvilinéaires
    -

    Dans les sous-sections suivantes, nous décrivons deux statistiques descriptives et exploratoires – la covariance (section 4.2) et la corrélation (section 4.3) – utilisées pour évaluer la relation linéaire entre deux variables continues (cas a et b à la figure 4.1). Ces deux mesures permettent de mesurer le degré d’association entre deux variables, sans que l’une soit la variable dépendante (variable à expliquer) et l’autre, la variable indépendante (variable explicative). Puis, nous décrivons la régression linéaire simple (section 4.4) qui permet justement de prédire une variable dépendante (Y) à partir d’une variable indépendante (X).

    +

    Dans les sous-sections suivantes, nous décrivons deux statistiques descriptives et exploratoires – la covariance (section sec-042) et la corrélation (section sec-043) – utilisées pour évaluer la relation linéaire entre deux variables continues (cas a et b à la figure fig-fig2). Ces deux mesures permettent de mesurer le degré d’association entre deux variables, sans que l’une soit la variable dépendante (variable à expliquer) et l’autre, la variable indépendante (variable explicative). Puis, nous décrivons la régression linéaire simple (section sec-044) qui permet justement de prédire une variable dépendante (Y) à partir d’une variable indépendante (X).

    4.2 Covariance

    4.2.1 Formulation

    -

    La covariance (équation 4.1), écrite \(cov(x,y)\), est égale à la moyenne du produit des écarts des valeurs des deux variables par rapport à leurs moyennes respectives :

    +

    La covariance (équation eq-cov), écrite \(cov(x,y)\), est égale à la moyenne du produit des écarts des valeurs des deux variables par rapport à leurs moyennes respectives :

    \[ cov(x,y) = \frac{\sum_{i=1}^n (x_{i}-\bar{x})(y_{i}-\bar{y})}{n-1} = \frac{covariation}{n-1} \tag{4.1}\]

    avec \(n\) étant le nombre d’observations; \(\bar{x}\) et \(\bar{y}\) (prononcez x et y barre) étant les moyennes respectives des variables X et Y.

    4.2.2 Interprétation

    -

    Le numérateur de l’équation 4.1 représente la covariation, soit la somme du produit des déviations des valeurs \(x_{i}\) et \(y_{i}\) par rapport à leurs moyennes respectives (\(\bar{x}\) et \(\bar{y}\)). La covariance est donc la covariation divisée par le nombre d’observations, soit la moyenne de la covariation. Sa valeur peut être positive ou négative :

    +

    Le numérateur de l’équation eq-cov représente la covariation, soit la somme du produit des déviations des valeurs \(x_{i}\) et \(y_{i}\) par rapport à leurs moyennes respectives (\(\bar{x}\) et \(\bar{y}\)). La covariance est donc la covariation divisée par le nombre d’observations, soit la moyenne de la covariation. Sa valeur peut être positive ou négative :

    • Positive quand les deux variables varient dans le même sens, c’est-à-dire lorsque les valeurs de la variable X s’éloignent de la moyenne, les valeurs de Y s’éloignent aussi dans le même sens; et elle est négative pour une situation inverse.

    • Quand la covariance est égale à 0, il n’y a pas de relation entre les variables X et Y. Plus sa valeur absolue est élevée, plus la relation entre les deux variables X et Y est importante.

    -

    Ainsi, la covariance correspond à un centrage des variables, c’est-à-dire à soustraire à chaque valeur de la variable sa moyenne correspondante. L’inconvénient majeur de l’utilisation de la covariance est qu’elle est tributaire des unités de mesure des deux variables. Par exemple, si nous calculons la covariance entre le pourcentage de personnes à faible revenu et la densité de population (habitants au km2) au niveau des secteurs de recensement de la région métropolitaine de Montréal, nous obtenons une valeur de covariance de 33 625. En revanche, si la densité de population est exprimée en milliers d’habitants au km2, la valeur de la covariance sera de 33,625, alors que la relation linéaire entre les deux variables reste la même comme illustré à la figure 4.3. Pour remédier à ce problème, nous privilégions l’utilisation du coefficient de corrélation.

    +

    Ainsi, la covariance correspond à un centrage des variables, c’est-à-dire à soustraire à chaque valeur de la variable sa moyenne correspondante. L’inconvénient majeur de l’utilisation de la covariance est qu’elle est tributaire des unités de mesure des deux variables. Par exemple, si nous calculons la covariance entre le pourcentage de personnes à faible revenu et la densité de population (habitants au km2) au niveau des secteurs de recensement de la région métropolitaine de Montréal, nous obtenons une valeur de covariance de 33 625. En revanche, si la densité de population est exprimée en milliers d’habitants au km2, la valeur de la covariance sera de 33,625, alors que la relation linéaire entre les deux variables reste la même comme illustré à la figure fig-covariance. Pour remédier à ce problème, nous privilégions l’utilisation du coefficient de corrélation.

    @@ -473,8 +473,8 @@

    cat("Corrélation de Pearson = ", round(cor1,5), "\nMoyenne du produit des variables centrées réduites =", round(cor2,5))

    -
    Corrélation de Pearson =  0.79321 
    -Moyenne du produit des variables centrées réduites = 0.79321
    +
    Corrélation de Pearson =  0.78657 
    +Moyenne du produit des variables centrées réduites = 0.78657

    @@ -483,7 +483,7 @@

  • 0 quand il n’y a pas de relation linéaire entre les variables X et Y;
  • −1 quand il y a une relation linéaire négative parfaite;
  • -
  • 1 quand il y a une relation linéaire positive parfaite (figure 4.4).
  • +
  • 1 quand il y a une relation linéaire positive parfaite (figure fig-coeffPearson).
  • @@ -493,7 +493,7 @@

    -

    Concrètement, le signe du coefficient de corrélation indique si la relation est positive ou négative et la valeur absolue du coefficient indique le degré d’association entre les deux variables. Reste à savoir comment déterminer qu’une valeur de corrélation est faible, moyenne ou forte. En sciences sociales, nous utilisons habituellement les intervalles de valeurs reportés au tableau 4.1. Toutefois, ces seuils sont tout à fait arbitraires. En effet, dépendamment de la discipline de recherche (sciences sociales, sciences de la santé, sciences physiques, etc.) et des variables à l’étude, l’interprétation d’une valeur de corrélation peut varier. Par exemple, en sciences sociales, une valeur de corrélation de 0,2 est considérée comme très faible alors qu’en sciences de la santé, elle pourrait être considérée comme intéressante. À l’opposé, une valeur de 0,9 en sciences physiques pourrait être considérée comme faible. Il convient alors d’utiliser ces intervalles avec précaution.

    +

    Concrètement, le signe du coefficient de corrélation indique si la relation est positive ou négative et la valeur absolue du coefficient indique le degré d’association entre les deux variables. Reste à savoir comment déterminer qu’une valeur de corrélation est faible, moyenne ou forte. En sciences sociales, nous utilisons habituellement les intervalles de valeurs reportés au tableau tbl-tableIntervallesCorrelation. Toutefois, ces seuils sont tout à fait arbitraires. En effet, dépendamment de la discipline de recherche (sciences sociales, sciences de la santé, sciences physiques, etc.) et des variables à l’étude, l’interprétation d’une valeur de corrélation peut varier. Par exemple, en sciences sociales, une valeur de corrélation de 0,2 est considérée comme très faible alors qu’en sciences de la santé, elle pourrait être considérée comme intéressante. À l’opposé, une valeur de 0,9 en sciences physiques pourrait être considérée comme faible. Il convient alors d’utiliser ces intervalles avec précaution.

    @@ -525,7 +525,7 @@

    -

    Le coefficient de corrélation mis au carré représente le coefficient de détermination et indique la proportion de la variance de la variable Y expliquée par la variable X et inversement. Par exemple, un coefficient de corrélation de −0,70 signale que 49 % de la variance de la variable de Y est expliquée par X (figure 4.5).

    +

    Le coefficient de corrélation mis au carré représente le coefficient de détermination et indique la proportion de la variance de la variable Y expliquée par la variable X et inversement. Par exemple, un coefficient de corrélation de −0,70 signale que 49 % de la variance de la variable de Y est expliquée par X (figure fig-coefCorrVar).

    @@ -534,7 +534,7 @@

    -

    Condition d’application. L’utilisation du coefficient de corrélation de Pearson nécessite que les deux variables continues soient normalement distribuées et qu’elles ne comprennent pas de valeurs aberrantes ou extrêmes. D’ailleurs, plus le nombre d’observations est réduit, plus la présence de valeurs extrêmes a une répercussion importante sur le résultat du coefficient de corrélation de Pearson. En guise d’exemple, dans le nuage de points à gauche de la figure 4.6, il est possible d’identifier des valeurs extrêmes qui se démarquent nettement dans le jeu de données : six observations avec une densité de population supérieure à 20 000 habitants au km2 et deux observations avec un pourcentage de 65 ans et plus supérieur à 55 %. Si l’on supprime ces observations (ce qui est défendable dans ce contexte) – soit moins d’un pour cent des observations du jeu de données initial –, la valeur du coefficient de corrélation passe de −0,158 à −0,194, signalant une augmentation du degré d’association entre les deux variables.

    +

    Condition d’application. L’utilisation du coefficient de corrélation de Pearson nécessite que les deux variables continues soient normalement distribuées et qu’elles ne comprennent pas de valeurs aberrantes ou extrêmes. D’ailleurs, plus le nombre d’observations est réduit, plus la présence de valeurs extrêmes a une répercussion importante sur le résultat du coefficient de corrélation de Pearson. En guise d’exemple, dans le nuage de points à gauche de la figure fig-ValExtremes, il est possible d’identifier des valeurs extrêmes qui se démarquent nettement dans le jeu de données : six observations avec une densité de population supérieure à 20 000 habitants au km2 et deux observations avec un pourcentage de 65 ans et plus supérieur à 55 %. Si l’on supprime ces observations (ce qui est défendable dans ce contexte) – soit moins d’un pour cent des observations du jeu de données initial –, la valeur du coefficient de corrélation passe de −0,158 à −0,194, signalant une augmentation du degré d’association entre les deux variables.

    @@ -549,7 +549,7 @@

    \[ r_{xy} = \frac{cov(rg_{x}, rg_{y})}{\sigma_{rg_{x}}\sigma_{rg_{y}}} \tag{4.3}\]

    -

    La syntaxe ci-dessous démontre clairement que le coefficient de Spearman est bien le coefficient de Pearson calculé sur les rangs (section 4.3.1).

    +

    La syntaxe ci-dessous démontre clairement que le coefficient de Spearman est bien le coefficient de Pearson calculé sur les rangs (section sec-0431).

    df <- read.csv("data/bivariee/sr_rmr_mtl_2016.csv")
     # Transformation des deux variables en rangs
    @@ -587,10 +587,10 @@ 

    -

    À la lecture des deux histogrammes à la figure 4.7, il est clair que les variables densité de population et pourcentage de personnes ayant 65 ou plus sont très anormalement distribuées. Dans ce contexte, l’utilisation du coefficient de Pearson peut nous amener à mésestimer la relation existant entre les deux variables. Notez que les coefficients de Spearman et de Kendall sont tous les deux plus faibles.

    +

    À la lecture des deux histogrammes à la figure fig-PearsonSpearmanKendall, il est clair que les variables densité de population et pourcentage de personnes ayant 65 ou plus sont très anormalement distribuées. Dans ce contexte, l’utilisation du coefficient de Pearson peut nous amener à mésestimer la relation existant entre les deux variables. Notez que les coefficients de Spearman et de Kendall sont tous les deux plus faibles.

    4.3.4 Corrélations robustes (Biweight midcorrelation, Percentage bend correlation et la corrélation pi de Shepherd)

    -

    Dans l’exemple donné à la figure 4.6, nous avions identifié des valeurs extrêmes et les avons retiré du jeu de données. Cette pratique peut tout à fait se justifier quand les données sont erronées (un capteur de pollution renvoyant une valeur négative, un questionnaire rempli par un mauvais plaisantin, etc.), mais parfois les cas extrêmes font partie du phénomène à analyser. Dans ce contexte, les identifier et les retirer peut paraître arbitraire. Une solution plus élégante est d’utiliser des méthodes dites robustes, c’est-à-dire moins sensibles aux valeurs extrêmes. Pour les corrélations, la Biweight midcorrelation (Wilcox 1994) est au coefficient de Pearson ce que la médiane est à la moyenne. Il est donc pertinent de l’utiliser pour des jeux de données présentant potentiellement des valeurs extrêmes. Elle est calculée comme suit :

    +

    Dans l’exemple donné à la figure fig-ValExtremes, nous avions identifié des valeurs extrêmes et les avons retiré du jeu de données. Cette pratique peut tout à fait se justifier quand les données sont erronées (un capteur de pollution renvoyant une valeur négative, un questionnaire rempli par un mauvais plaisantin, etc.), mais parfois les cas extrêmes font partie du phénomène à analyser. Dans ce contexte, les identifier et les retirer peut paraître arbitraire. Une solution plus élégante est d’utiliser des méthodes dites robustes, c’est-à-dire moins sensibles aux valeurs extrêmes. Pour les corrélations, la Biweight midcorrelation (Wilcox 1994) est au coefficient de Pearson ce que la médiane est à la moyenne. Il est donc pertinent de l’utiliser pour des jeux de données présentant potentiellement des valeurs extrêmes. Elle est calculée comme suit :

    \[ \begin{aligned} &u_{i} = \frac{x_{i} - med(x)}{9 \times (med(|x_{i} - med(x)|))} \text{ et } v_{i} = \frac{y_{i} - med(y)}{9 \times (med(|y_{i} - med(y)|))}\\ @@ -604,9 +604,9 @@

    -

    Comme le souligne l’équation 4.5, la Biweight midcorrelation est basée sur les écarts à la médiane, plutôt que sur les écarts à la moyenne.

    -

    Assez proche de la Biweight midcorrelation, la Percentage bend correlation se base également sur la médiane des variables X et Y. Le principe général est de donner un poids plus faible dans le calcul de cette corrélation à un certain pourcentage des observations (20 % sont généralement recommandés) dont la valeur est éloignée de la médiane. Pour une description complète de la méthode, vous pouvez lire l’article de Wilcox (1994).

    -

    Enfin, une autre option est l’utilisation de la corrélation \(pi\) de Sherphred (Schwarzkopf, Haas et Rees 2012). Il s’agit simplement d’une méthode en deux étapes. Premièrement, les valeurs extrêmes sont identifiées à l’aide d’une approche par bootstrap utilisant la distance de Mahalanobis (calculant les écarts multivariés entre les observations). Deuxièmement, le coefficient de Spearman est calculé sur les observations restantes.

    +

    Comme le souligne l’équation eq-bicor, la Biweight midcorrelation est basée sur les écarts à la médiane, plutôt que sur les écarts à la moyenne.

    +

    Assez proche de la Biweight midcorrelation, la Percentage bend correlation se base également sur la médiane des variables X et Y. Le principe général est de donner un poids plus faible dans le calcul de cette corrélation à un certain pourcentage des observations (20 % sont généralement recommandés) dont la valeur est éloignée de la médiane. Pour une description complète de la méthode, vous pouvez lire l’article de Wilcox (1994).

    +

    Enfin, une autre option est l’utilisation de la corrélation \(pi\) de Sherphred (Schwarzkopf, Haas et Rees 2012). Il s’agit simplement d’une méthode en deux étapes. Premièrement, les valeurs extrêmes sont identifiées à l’aide d’une approche par bootstrap utilisant la distance de Mahalanobis (calculant les écarts multivariés entre les observations). Deuxièmement, le coefficient de Spearman est calculé sur les observations restantes.

    Appliquons ces corrélations aux données précédentes. Notez que ce simple code d’une dizaine de lignes permet d’explorer rapidement la corrélation entre deux variables selon six mesures de corrélation.

    library("correlation")
    @@ -821,7 +821,7 @@ 

    +t1* -0.1580801 -0.0006694822 0.04048709
    # Intervalle de confiance du bootstrap à 95 %
     boot.ci(boot.out = corBootstraped, conf = 0.95, type = "all")
    @@ -834,10 +834,10 @@

    # Comparaison de l'intervalle classique basé sur la valeur de T
    @@ -1091,7 +1091,7 @@ 

    Une image vaut mille mots, surtout pour une matrice de corrélation!

    -

    Le package corrplot vous permet justement de construire de belles figures avec une matrice de corrélation (figures 4.9 et 4.10). L’intérêt de ce type de figure est de repérer rapidement des associations intéressantes lorsque nous calculons les corrélations entre un grand nombre de variables.

    +

    Le package corrplot vous permet justement de construire de belles figures avec une matrice de corrélation (figures fig-corrplot1 et fig-corrplot2). L’intérêt de ce type de figure est de repérer rapidement des associations intéressantes lorsque nous calculons les corrélations entre un grand nombre de variables.

    @@ -1152,13 +1152,13 @@

    Répondre à cette question relève de la statistique inférentielle. Il s’agit en effet d’établir une équation simple du type \(Y = a + bX\) pour expliquer et prédire les valeurs d’une variable dépendante (Y) à partir d’une variable indépendante (X). L’équation de la régression est construite grâce à un jeu de données (un échantillon). À partir de cette équation, il est possible de prédire la valeur attendue de Y pour n’importe quelle valeur de X. Nous appelons cette équation un modèle, car elle cherche à représenter la réalité de façon simplifiée.

    -

    La régression linéaire simple relève ainsi de la statistique inférentielle et se distingue ainsi de la covariance (section 4.2) et de la corrélation (section 4.3) qui relèvent quant à eux de la statistique bivariée descriptive et exploratoire.

    +

    La régression linéaire simple relève ainsi de la statistique inférentielle et se distingue ainsi de la covariance (section sec-042) et de la corrélation (section sec-043) qui relèvent quant à eux de la statistique bivariée descriptive et exploratoire.

    Par exemple, la régression linéaire simple pourrait être utilisée pour expliquer les notes d’un groupe d’étudiants et d’étudiantes à un examen (variable dépendante Y) en fonction du nombre d’heures consacrées à la révision des notes de cours (variable indépendante X). Une fois l’équation de régression déterminée et si le modèle est efficace, nous pourrons prédire les notes des personnes inscrites au cours la session suivante en fonction du temps qu’ils ou qu’elles prévoient passer à étudier, et ce, avant l’examen.

    Formulons un exemple d’application de la régression linéaire simple en études urbaines. Dans le cadre d’une étude sur les îlots de chaleur urbains, la température de surface (variable dépendante) pourrait être expliquée par la proportion de la superficie de l’îlot couverte par de la végétation (variable indépendante). Nous supposons alors que plus cette proportion est importante, plus la température est faible et inversement, soit une relation linéaire négative. Si le modèle est efficace, nous pourrions prédire la température moyenne des îlots d’une autre municipalité pour laquelle nous ne disposons pas d’une carte de température, et repérer ainsi les îlots de chaleur potentiels. Bien entendu, il est peu probable que nous arrivions à prédire efficacement la température moyenne des îlots avec uniquement la couverture végétale comme variable explicative. En effet, bien d’autres caractéristiques de la forme urbaine peuvent influencer ce phénomène comme la densité du bâti, la couleur des toits, les occupations du sol présentes, l’effet des canyons urbains, etc. Il faudrait alors inclure non pas une, mais plusieurs variables explicatives (indépendantes).

    -

    Ainsi, nous distinguons la régression linéaire simple (une seule variable indépendante) de la régression linéaire multiple (plusieurs variables indépendantes); cette dernière est largement abordée au chapitre 7.

    +

    Ainsi, nous distinguons la régression linéaire simple (une seule variable indépendante) de la régression linéaire multiple (plusieurs variables indépendantes); cette dernière est largement abordée au chapitre sec-chap07.

    -

    Dans cette section, nous décrivons succinctement la régression linéaire simple. Concrètement, nous voyons comment déterminer la droite de régression, interpréter ses différents paramètres du modèle et évaluer la qualité d’ajustement du modèle. Nous n’abordons ni les hypothèses liées au modèle de régression linéaire des moindres carrés ordinaires (MCO) ni les conditions d’application. Ces éléments sont expliqués au chapitre 7, consacré à la régression linéaire multiple.

    +

    Dans cette section, nous décrivons succinctement la régression linéaire simple. Concrètement, nous voyons comment déterminer la droite de régression, interpréter ses différents paramètres du modèle et évaluer la qualité d’ajustement du modèle. Nous n’abordons ni les hypothèses liées au modèle de régression linéaire des moindres carrés ordinaires (MCO) ni les conditions d’application. Ces éléments sont expliqués au chapitre sec-chap07, consacré à la régression linéaire multiple.

    @@ -1173,7 +1173,7 @@

  • Avoir les doigts jaunes est associé au cancer du poumon. Bien entendu, les doigts jaunes ne causent pas le cancer : c’est un facteur confondant puisque fumer augmente les risques du cancer du poumon et jaunit aussi les doigts.

  • -

    Dans un article intitulé Chocolate Consumption, Cognitive Function, and Nobel Laureates, Messerli (2012) a trouvé une corrélation positive entre la consommation de chocolat par habitant et le nombre de prix Nobel pour dix millions d’habitants pour 23 pays. Ce résultat a d’ailleurs été rapporté par de nombreux médias, sans pour autant que Messerli (2012) et les journalistes concluent à un lien de causalité entre les deux variables :

    +

    Dans un article intitulé Chocolate Consumption, Cognitive Function, and Nobel Laureates, Messerli (2012) a trouvé une corrélation positive entre la consommation de chocolat par habitant et le nombre de prix Nobel pour dix millions d’habitants pour 23 pays. Ce résultat a d’ailleurs été rapporté par de nombreux médias, sans pour autant que Messerli (2012) et les journalistes concluent à un lien de causalité entre les deux variables :

    • Radio Canada

    • La Presse

    • @@ -1235,7 +1235,7 @@

      avec \(\widehat{y_i}\) et \(x_{i}\) qui sont respectivement la valeur prédite de la variable dépendante et la valeur de la variable indépendante pour l’observation \(i\). \(\beta_{0}\) est la constante (intercept en anglais) et représente la valeur prédite de la variable Y quand X est égale à 0. \(\beta_{1}\) est le coefficient de régression pour la variable X, soit la pente de la droite. Ce coefficient nous informe sur la relation entre les deux variables : s’il est positif, la relation est positive; s’il est négatif, la relation est négative; s’il est proche de 0, la relation est nulle (la droite est alors horizontale). Plus la valeur absolue de \(\beta_{1}\) est élevée, plus la pente est forte et plus la variable Y varie à chaque changement d’une unité de la variable X.

      -

      Considérons un exemple fictif de dix municipalités d’une région métropolitaine pour lesquelles nous disposons de deux variables : le pourcentage de personnes occupées se rendant au travail principalement à vélo et la distance entre chaque municipalité et le centre-ville de la région métropolitaine (tableau 4.3).

      +

      Considérons un exemple fictif de dix municipalités d’une région métropolitaine pour lesquelles nous disposons de deux variables : le pourcentage de personnes occupées se rendant au travail principalement à vélo et la distance entre chaque municipalité et le centre-ville de la région métropolitaine (tableau tbl-regfictives).

      @@ -1302,7 +1302,7 @@

      -

      D’emblée, à la lecture du nuage de points (figure 4.12), nous décelons une forte relation linéaire négative entre les deux variables : plus la distance entre la municipalité et le centre-ville de la région métropolitaine augmente, plus le pourcentage de cyclistes est faible, ce qui est confirmé par le coefficient de corrélation (r = −0,90). La droite de régression (en rouge à la figure 4.12) qui résume le mieux la relation entre Vélo (variable dépendante) et KmCV (variable indépendante) s’écrit alors : Vélo = 30,603 − 1,448 x KmCV.

      +

      D’emblée, à la lecture du nuage de points (figure fig-reg), nous décelons une forte relation linéaire négative entre les deux variables : plus la distance entre la municipalité et le centre-ville de la région métropolitaine augmente, plus le pourcentage de cyclistes est faible, ce qui est confirmé par le coefficient de corrélation (r = −0,90). La droite de régression (en rouge à la figure fig-reg) qui résume le mieux la relation entre Vélo (variable dépendante) et KmCV (variable indépendante) s’écrit alors : Vélo = 30,603 − 1,448 x KmCV.

      La valeur du coefficient de régression (\(\beta_{1}\)) est de −1,448. Le signe de ce coefficient décrit une relation négative entre les deux variables. Ainsi, à chaque ajout d’une unité de la distance entre la municipalité et le centre-ville (exprimée en kilomètres), le pourcentage de cyclistes diminue de 1,448. Retenez que l’unité de mesure de la variable dépendante est très importante pour bien interpréter le coefficient de régression. En effet, si la distance au centre-ville n’était pas exprimée en kilomètres, mais plutôt en mètres, \(\beta_1\) serait égal à −0,001448. Dans la même optique, l’ajout de 10 km de distance entre une municipalité et le centre-ville fait diminuer le pourcentage de cyclistes de −14,48 points de pourcentage.

      Avec, cette équation de régression, il est possible de prédire le pourcentage de cyclistes pour n’importe quelle municipalité de la région métropolitaine. Par exemple, pour des distances de 5, 10 ou 20 kilomètres, les pourcentages de cyclistes seraient de :

        @@ -1320,11 +1320,11 @@

  • 4.4.2 Formulation de la droite de régression des moindres carrés ordinaires

    -

    Reste à savoir comment sont estimés les différents paramètres de l’équation, soit \(\beta_0\) et \(\beta_1\). À la figure 4.13, les points noirs représentent les valeurs observées (\(y_i\)) et les points bleus, les valeurs prédites (\(\widehat{y_i}\)) par l’équation du modèle. Les traits noirs verticaux représentent, pour chaque observation \(i\), l’écart entre la valeur observée et la valeur prédite, dénommé résidu (\(\epsilon_i\), prononcez epsilon de i ou plus simplement le résidu pour i ou le terme d’erreur de i). Si un point est au-dessus de la droite de régression, la valeur observée est alors supérieure à la valeur prédite (\(y_i > \widehat{y_i}\)) et inversement, si le point est au-dessous de la droite (\(y_i < \widehat{y_i}\)). Plus cet écart (\(\epsilon_i\)) est important, plus l’observation s’éloigne de la prédiction du modèle et, par extension, moins bon est le modèle. Au tableau 4.4, vous constaterez que la somme des résidus est égale à zéro. La méthode des moindres carrés ordinaires (MCO) vise à minimiser les écarts au carré entre les valeurs observées (\(y_i\)) et prédites (\(\beta_0+\beta_1 x_i\), soit \(\widehat{y_i}\)) :

    +

    Reste à savoir comment sont estimés les différents paramètres de l’équation, soit \(\beta_0\) et \(\beta_1\). À la figure fig-reg2, les points noirs représentent les valeurs observées (\(y_i\)) et les points bleus, les valeurs prédites (\(\widehat{y_i}\)) par l’équation du modèle. Les traits noirs verticaux représentent, pour chaque observation \(i\), l’écart entre la valeur observée et la valeur prédite, dénommé résidu (\(\epsilon_i\), prononcez epsilon de i ou plus simplement le résidu pour i ou le terme d’erreur de i). Si un point est au-dessus de la droite de régression, la valeur observée est alors supérieure à la valeur prédite (\(y_i > \widehat{y_i}\)) et inversement, si le point est au-dessous de la droite (\(y_i < \widehat{y_i}\)). Plus cet écart (\(\epsilon_i\)) est important, plus l’observation s’éloigne de la prédiction du modèle et, par extension, moins bon est le modèle. Au tableau tbl-regfictives2, vous constaterez que la somme des résidus est égale à zéro. La méthode des moindres carrés ordinaires (MCO) vise à minimiser les écarts au carré entre les valeurs observées (\(y_i\)) et prédites (\(\beta_0+\beta_1 x_i\), soit \(\widehat{y_i}\)) :

    \[ min\sum_{i=1}^n{(y_i-(\beta_0+\beta_1 x_i))^2} \tag{4.8}\]

    -

    Pour minimiser ces écarts, le coefficient de régression \(\beta_1\) représente le rapport entre la covariance entre X et Y et la variance de Y (équation 4.9), tandis que la constante \(\beta_0\) est la moyenne de la variable Y moins le produit de la moyenne de X et de son coefficient de régression (équation 4.10).

    +

    Pour minimiser ces écarts, le coefficient de régression \(\beta_1\) représente le rapport entre la covariance entre X et Y et la variance de Y (équation eq-b1), tandis que la constante \(\beta_0\) est la moyenne de la variable Y moins le produit de la moyenne de X et de son coefficient de régression (équation eq-b0).

    \[ \beta_1 = \frac{\sum_{i=1}^n (x_{i}-\bar{x})(y_{i}-\bar{y})}{\sum_{i=1}^n (x_i-\bar{x})^2} = \frac{cov(X,Y)}{var(X)} \tag{4.9}\]

    @@ -1456,7 +1456,7 @@

    \[ Y = \underbrace{\beta_0 + \beta_1 X}_{\mbox{partie expliquée par le modèle}}+ \underbrace{\epsilon}_{\mbox{partie non expliquée}} \tag{4.12}\]

    -

    Par exemple, pour la municipalité A au tableau 4.4, nous avons : \(y_A = \widehat{y}_A - \epsilon_A \Rightarrow \mbox{12,5} = \mbox{10,138}+\mbox{2,362}\). Souvenez-vous que la variance d’une variable est la somme des écarts à la moyenne, divisée par le nombre d’observations. Par extension, il est alors possible de décomposer la variance de Y comme suit :

    +

    Par exemple, pour la municipalité A au tableau tbl-regfictives2, nous avons : \(y_A = \widehat{y}_A - \epsilon_A \Rightarrow \mbox{12,5} = \mbox{10,138}+\mbox{2,362}\). Souvenez-vous que la variance d’une variable est la somme des écarts à la moyenne, divisée par le nombre d’observations. Par extension, il est alors possible de décomposer la variance de Y comme suit :

    \[ \underbrace{\sum_{i=1}^n (y_{i}-\bar{y})^2}_{\mbox{variance de Y}} = \underbrace{\sum_{i=1}^n (\widehat{y}_i-\bar{y})^2}_{\mbox{var. expliquée}} + \underbrace{\sum_{i=1}^n (y_{i}-\widehat{y})^2}_{\mbox{var. non expliquée}} \Rightarrow SCT = SCE + SCR @@ -1467,7 +1467,7 @@

    SCE est la somme des écarts au carré des valeurs prédites à la moyenne (regression sum of squares en anglais)

  • SCR est la somme des carrés des résidus (sum of squared errors en anglais).

  • -

    Autrement dit, la variance totale est égale à la variance expliquée plus la variance non expliquée. Au tableau 4.5, vous pouvez repérer les valeurs de SCT, SCE et SCR et constater que 279,30 = 227,04 + 52,26 et 27,93 = 22,70 + 5,23.

    +

    Autrement dit, la variance totale est égale à la variance expliquée plus la variance non expliquée. Au tableau tbl-computeR, vous pouvez repérer les valeurs de SCT, SCE et SCR et constater que 279,30 = 227,04 + 52,26 et 27,93 = 22,70 + 5,23.

    @@ -1625,13 +1625,13 @@

    \[ R^2 = \frac{SCE}{SCT} \mbox{ avec } R^2 \in \left[0,1\right] \tag{4.15}\]

    -

    Comparativement au RMSE qui est une mesure absolue, le coefficient de détermination est une mesure relative qui varie de 0 à 1. Il exprime la proportion de la variance de Y qui est expliquée par la variable X; autrement dit, plus sa valeur est élevée, plus X influence/est capable de prédire Y. Dans le cas présent, nous avons : R2 = 227,04 / 279,3 = 0,8129, ce qui signale que 81,3 % de la variance du pourcentage de cyclistes est expliquée par la distance entre la municipalité et le centre-ville de la région métropolitaine. Tel que signalé dans la section 4.3.2, la racine carrée du coefficient de détermination (R2) est égale au coefficient de corrélation (\(r\)) entre les deux variables.

    +

    Comparativement au RMSE qui est une mesure absolue, le coefficient de détermination est une mesure relative qui varie de 0 à 1. Il exprime la proportion de la variance de Y qui est expliquée par la variable X; autrement dit, plus sa valeur est élevée, plus X influence/est capable de prédire Y. Dans le cas présent, nous avons : R2 = 227,04 / 279,3 = 0,8129, ce qui signale que 81,3 % de la variance du pourcentage de cyclistes est expliquée par la distance entre la municipalité et le centre-ville de la région métropolitaine. Tel que signalé dans la section sec-0432, la racine carrée du coefficient de détermination (R2) est égale au coefficient de corrélation (\(r\)) entre les deux variables.

    Calcul de la statistique F de Fisher

    La statistique F de Fisher permet de vérifier la significativité globale du modèle.

    \[ F = (n-2)\frac{R^2}{1-R^2} = (n-2)\frac{SCE}{SCR} \tag{4.16}\]

    -

    L’hypothèse nulle (H0 avec \(\beta_1=0\)) est rejetée si la valeur calculée de F est supérieure à la valeur critique de la table F avec 1, n-2 degrés de liberté et un seuil \(\alpha\) (p = 0,05 habituellement) (voir la table des valeurs critiques de F, section 14.2). Notez que nous utilisons rarement la table F puisqu’avec la fonction pf(f obtenu, 1, n-2, lower.tail = FALSE), nous obtenons obtient directement la valeur de p associée à la valeur de F. Concrètement, si le test F est significatif (avec p < 0,05), plus la valeur de F est élevée, plus le modèle est efficace (et plus le R2 sera également élevé).

    +

    L’hypothèse nulle (H0 avec \(\beta_1=0\)) est rejetée si la valeur calculée de F est supérieure à la valeur critique de la table F avec 1, n-2 degrés de liberté et un seuil \(\alpha\) (p = 0,05 habituellement) (voir la table des valeurs critiques de F, section sec-142). Notez que nous utilisons rarement la table F puisqu’avec la fonction pf(f obtenu, 1, n-2, lower.tail = FALSE), nous obtenons obtient directement la valeur de p associée à la valeur de F. Concrètement, si le test F est significatif (avec p < 0,05), plus la valeur de F est élevée, plus le modèle est efficace (et plus le R2 sera également élevé).

    Notez que la fonction summary renvoie les résultats du modèle, dont notamment le test F de Fisher.

    # utiliser la fonction summary
    @@ -1757,7 +1757,7 @@ 

    -Relisez au besoin la section 4.1. +Relisez au besoin la section sec-041.
    @@ -1802,7 +1802,7 @@

    -Relisez au besoin la section 4.1. +Relisez au besoin la section sec-041.
    @@ -1847,7 +1847,7 @@

    -Relisez au besoin la section 4.2.2. +Relisez au besoin la section sec-0422.
    @@ -1892,7 +1892,7 @@

    -Relisez au besoin la section 4.3.3. +Relisez au besoin la section sec-0433.
    @@ -1937,7 +1937,7 @@

    -Relisez au besoin la section 4.2.2. +Relisez au besoin la section sec-0422.
    @@ -1982,7 +1982,7 @@

    -Relisez au besoin la section 4.1. +Relisez au besoin la section sec-041.
    @@ -2019,7 +2019,7 @@

    -Relisez au besoin la section 4.3.3. +Relisez au besoin la section sec-0433.
    @@ -2056,7 +2056,7 @@

    -Relisez au besoin la section 4.4.2. +Relisez au besoin la section sec-0442.
    @@ -2093,7 +2093,7 @@

    -Relisez au besoin la section 4.4.3. +Relisez au besoin la section sec-0443.
    @@ -2130,7 +2130,7 @@

    -Relire le deuxième encadré à la section 4.4. +Relire le deuxième encadré à la section sec-044.
    @@ -2163,7 +2163,7 @@

    -

    5.1 Construction de tableau de contingence

    -

    Les données du tableau de contingence suivant décrivent 279 projets d’habitation à loyer modique (HLM) dans l’ancienne ville de Montréal, croisant les modalités de la période de construction (en colonne) et de la taille (en ligne) des projets HLM (Apparicio 2002). Les différents éléments du tableau sont décrits ci-dessous.

    +

    Les données du tableau de contingence suivant décrivent 279 projets d’habitation à loyer modique (HLM) dans l’ancienne ville de Montréal, croisant les modalités de la période de construction (en colonne) et de la taille (en ligne) des projets HLM (Apparicio 2002). Les différents éléments du tableau sont décrits ci-dessous.

    • Les fréquences observées (Count au tableau ci-dessous), nommées communément \(f_{ij}\), correspondent aux observations appartenant à la fois à la ie modalité de la variable en ligne et à la je modalité de la variable en colonne. À titre d’exemple, nous comptons 14 projets HLM construits entre 1985 et 1989 comprenant moins de 25 logements.

    • Les marges du tableau sont les totaux pour chaque modalité en ligne (\(n_{i.}\)) et en colonne (\(n_{j.}\)). En guise d’exemple, sur les 279 projets HLM, 53 comprennent de 25 à 49 logements et 56 ont été construites entre 1968 et 1974. Bien entendu, la somme des marges en ligne (\(n_{i.}\)) est égale au nombre total d’observations (\(n_{ij}\)), tout comme la somme de marges en colonne (\(n_{.j}\)).

    • @@ -414,7 +414,7 @@

      5.2 Test du khi-deux

      Avec le test du khi-deux, nous postulons qu’il y a indépendance entre les modalités des deux variables qualitatives, soit l’hypothèse nulle (H0). Puis, nous calculons le nombre de degrés de liberté : \(DL = (n-1)(l-1)\), avec \(l\) et \(n\) étant respectivement les nombres de modalités en ligne et en colonne. Pour notre tableau de contingence, nous avons 12 degrés de liberté : \((4-1)(5-1)=12\).

      -

      À partir du nombre de degrés de liberté et d’un seuil critique de significativité (prenons 5 % ici), nous pouvons trouver la valeur critique de khi-deux dans la table des valeurs critiques du khi-deux, soit 21,03 (section 14.1). Puisque la valeur du khi-deux calculée dans le tableau de contingence (63,54) est bien supérieure à celle obtenue dans le tableau des valeurs critiques (21,03), nous pouvons rejeter l’hypothèse d’indépendance au seuil de 5 %. Autrement dit, si les deux variables n’étaient pas associées, nous aurions eu moins de 5 % de chances de collecter des données avec ce niveau d’association, ce qui nous permet de rejeter l’hypothèse nulle (absence d’association). Notez que le test reste significatif avec des seuils de 1 % (p = 0,01) et 0,1 % (p = 0,001) puisque les valeurs critiques sont de 26,22 et de 32,91.

      +

      À partir du nombre de degrés de liberté et d’un seuil critique de significativité (prenons 5 % ici), nous pouvons trouver la valeur critique de khi-deux dans la table des valeurs critiques du khi-deux, soit 21,03 (section sec-141). Puisque la valeur du khi-deux calculée dans le tableau de contingence (63,54) est bien supérieure à celle obtenue dans le tableau des valeurs critiques (21,03), nous pouvons rejeter l’hypothèse d’indépendance au seuil de 5 %. Autrement dit, si les deux variables n’étaient pas associées, nous aurions eu moins de 5 % de chances de collecter des données avec ce niveau d’association, ce qui nous permet de rejeter l’hypothèse nulle (absence d’association). Notez que le test reste significatif avec des seuils de 1 % (p = 0,01) et 0,1 % (p = 0,001) puisque les valeurs critiques sont de 26,22 et de 32,91.

      Bien entendu, une fois que nous connaissons le nombre de degrés de liberté, nous pouvons directement calculer les valeurs critiques pour différents seuils de signification et éviter ainsi de recourir à la table du du khi-deux. Dans la même veine, nous pouvons aussi calculer la valeur de p d’un tableau de contingence en spécifiant le nombre de degrés de liberté et la valeur du khi-deux obtenue.

      cat("Valeurs critiques du khi-deux avec le nombre de degrés de liberté", "\n",
      @@ -442,7 +442,7 @@ 

      Autres mesures d’association

      -

      Outre le khi-deux, d’autres mesures d’association permettent de mesurer le degré d’association entre deux variables qualitatives. Les plus courantes sont reportées dans le tableau 5.1. À des fins de comparaison, le khi-deux décrit précédemment est aussi reporté sur la première ligne du tableau.

      +

      Outre le khi-deux, d’autres mesures d’association permettent de mesurer le degré d’association entre deux variables qualitatives. Les plus courantes sont reportées dans le tableau tbl-EncadreAsso. À des fins de comparaison, le khi-deux décrit précédemment est aussi reporté sur la première ligne du tableau.

      @@ -698,7 +698,7 @@

    -

    Pour obtenir les autres mesures d’association (tableau 5.2), nous pourrons utiliser la syntaxe suivante :

    +

    Pour obtenir les autres mesures d’association (tableau tbl-MesuresAssociations), nous pourrons utiliser la syntaxe suivante :

    df1 <- read.csv("data/bivariee/hlm.csv")
     # Fonction pour calculer les autres mesures d'association
    @@ -813,7 +813,7 @@ 

    Repérer les contributions au khi-deux les plus importantes

    -

    Pour repérer rapidement les cellules où les contributions au khi-deux sont les plus fortes, vous pouvez construire un graphique avec la fonction mosaic du package vcd. À la figure 5.1, la taille des rectangles représente les effectifs entre les deux modalités tandis que les associations sont représentées comme suit : en gris lorsqu’elles ne sont pas significatives, en rouge pour des déviations significatives et négatives et en bleu pour des déviations significatives et positives.

    +

    Pour repérer rapidement les cellules où les contributions au khi-deux sont les plus fortes, vous pouvez construire un graphique avec la fonction mosaic du package vcd. À la figure fig-VDC, la taille des rectangles représente les effectifs entre les deux modalités tandis que les associations sont représentées comme suit : en gris lorsqu’elles ne sont pas significatives, en rouge pour des déviations significatives et négatives et en bleu pour des déviations significatives et positives.

    library(vcd)
     mosaic(~ Taille+Periode, 
    @@ -829,8 +829,8 @@ 

    -

    Exemple d’interprétation. « Les résultats du test du khi-deux signalent qu’il existe des associations entre les modalités de la taille et de la période de construction des projets d’habitation (\(\chi\) = 63,5, p < 0,001). Les fortes contributions au khi-deux et le signe positif ou négatif des déviations correspondantes permettent de repérer cinq associations majeures entre les modalités de taille et de période de construction des projets HLM : 1) la répulsion entre les projets d’habitation de moins de 25 logements et la période de construction 1964-1974; 2) l’attraction entre les projets d’habitation de 100 logements et plus et la période de construction de 1969-1974; 3) l’attraction entre les projets d’habitation de moins de 25 logements et la période de construction de 1990-1994; 4) la répulsion entre les projets d’habitation de 50 à 99 logements et la période de construction 1990-1994; 5) la répulsion entre les projets d’habitation de 100 logements et plus et la période de construction 1990-1994. On observe donc une tendance bien marquée dans l’évolution du type de construction entre 1970 et 1994 : entre 1969 et 1974, on a construit de grandes habitations dépassant souvent 100 logements; du milieu des années 1970 à la fin des années 1980, on privilégie la construction d’habitations de taille plus modeste, entre 50 et 100 logements; tandis qu’au début des années 1990, on opte plutôt pour des habitations de taille réduite (moins de 50 logements). Quelques chiffres à l’appui : sur les 56 habitations réalisées entre 1969 et 1974, 20 ont plus de 100 logements, 20 comprennent entre 50 et 99 logements et seules 10 ont moins de 25 logements. Près de la moitié des habitations construites entre 1975 et 1989 regroupent 50 à 99 logements (43,8 % pour la période 1975-1979, 45,8 % pour 1980-1984 et 44,7 % pour 1985-1989). Par contre, 51 % des habitations érigés à partir de 1990 disposent de moins de 25 logements » (Apparicio (2002), p. 117-118). Notez que cette évolution décroissante est aussi soutenue par le coefficient négatif de la corrélation polychorique.

    -

    Vous pouvez aussi construire un graphique pour appuyer vos constats, soit avec les pourcentages en ligne ou en colonne (figure 5.2 tirée de Apparicio (2002)).

    +

    Exemple d’interprétation. « Les résultats du test du khi-deux signalent qu’il existe des associations entre les modalités de la taille et de la période de construction des projets d’habitation (\(\chi\) = 63,5, p < 0,001). Les fortes contributions au khi-deux et le signe positif ou négatif des déviations correspondantes permettent de repérer cinq associations majeures entre les modalités de taille et de période de construction des projets HLM : 1) la répulsion entre les projets d’habitation de moins de 25 logements et la période de construction 1964-1974; 2) l’attraction entre les projets d’habitation de 100 logements et plus et la période de construction de 1969-1974; 3) l’attraction entre les projets d’habitation de moins de 25 logements et la période de construction de 1990-1994; 4) la répulsion entre les projets d’habitation de 50 à 99 logements et la période de construction 1990-1994; 5) la répulsion entre les projets d’habitation de 100 logements et plus et la période de construction 1990-1994. On observe donc une tendance bien marquée dans l’évolution du type de construction entre 1970 et 1994 : entre 1969 et 1974, on a construit de grandes habitations dépassant souvent 100 logements; du milieu des années 1970 à la fin des années 1980, on privilégie la construction d’habitations de taille plus modeste, entre 50 et 100 logements; tandis qu’au début des années 1990, on opte plutôt pour des habitations de taille réduite (moins de 50 logements). Quelques chiffres à l’appui : sur les 56 habitations réalisées entre 1969 et 1974, 20 ont plus de 100 logements, 20 comprennent entre 50 et 99 logements et seules 10 ont moins de 25 logements. Près de la moitié des habitations construites entre 1975 et 1989 regroupent 50 à 99 logements (43,8 % pour la période 1975-1979, 45,8 % pour 1980-1984 et 44,7 % pour 1985-1989). Par contre, 51 % des habitations érigés à partir de 1990 disposent de moins de 25 logements » (Apparicio (2002), p. 117-118). Notez que cette évolution décroissante est aussi soutenue par le coefficient négatif de la corrélation polychorique.

    +

    Vous pouvez aussi construire un graphique pour appuyer vos constats, soit avec les pourcentages en ligne ou en colonne (figure fig-hml tirée de Apparicio (2002)).

    Figure 5.2: Taille des projets d’habitation à loyer modique selon la période de construction
    @@ -897,7 +897,7 @@

    -Relisez au besoin l’introduction du chapitre 5. +Relisez au besoin l’introduction du chapitre sec-chap05.
    @@ -958,7 +958,7 @@

    -Relisez au besoin la section 5.1. +Relisez au besoin la section sec-051.
    @@ -1019,7 +1019,7 @@

    -Relisez au besoin l’encadré à la section 5.2. +Relisez au besoin l’encadré à la section sec-052.
    @@ -1048,7 +1048,7 @@

    -Relisez au besoin la section 5.4. +Relisez au besoin la section sec-054.
    @@ -1081,7 +1081,7 @@

    -

    6.2.3 Mise en œuvre dans R

    -

    Dans une étude récente, Apparicio et al. (2018) ont comparé les expositions au bruit et à la pollution atmosphérique aux heures de pointe à Montréal en fonction du mode de transport utilisé. Pour ce faire, trois équipes de trois personnes ont été constituées : une personne à vélo, une autre en automobile et une dernière se déplaçant en transport en commun, équipées de capteurs de pollution, de sonomètres, de vêtements biométriques et d’une montre GPS. Chaque matin, à huit heures précises, les membres de chaque équipe ont réalisé un trajet d’un quartier périphérique de Montréal vers un pôle d’enseignement (université) ou d’emploi localisé au centre-ville. Le trajet inverse était réalisé le soir à 17 h. Au total, une centaine de trajets ont ainsi été réalisés. Des analyses de variance ont ainsi permis de comparer les trois modes (automobile, vélo et transport en commun) en fonction des temps de déplacement, des niveaux d’exposition au bruit, des niveaux d’exposition au dioxyde d’azote et de la dose totale inhalée de dioxyde d’azote. Nous vous proposons ici d’analyser une partie de ces données.

    +

    Dans une étude récente, Apparicio et al. (2018) ont comparé les expositions au bruit et à la pollution atmosphérique aux heures de pointe à Montréal en fonction du mode de transport utilisé. Pour ce faire, trois équipes de trois personnes ont été constituées : une personne à vélo, une autre en automobile et une dernière se déplaçant en transport en commun, équipées de capteurs de pollution, de sonomètres, de vêtements biométriques et d’une montre GPS. Chaque matin, à huit heures précises, les membres de chaque équipe ont réalisé un trajet d’un quartier périphérique de Montréal vers un pôle d’enseignement (université) ou d’emploi localisé au centre-ville. Le trajet inverse était réalisé le soir à 17 h. Au total, une centaine de trajets ont ainsi été réalisés. Des analyses de variance ont ainsi permis de comparer les trois modes (automobile, vélo et transport en commun) en fonction des temps de déplacement, des niveaux d’exposition au bruit, des niveaux d’exposition au dioxyde d’azote et de la dose totale inhalée de dioxyde d’azote. Nous vous proposons ici d’analyser une partie de ces données.

    6.2.3.1 Première ANOVA : différences entre les temps de déplacement

    Comme première analyse de variance, nous vérifions si les moyennes des temps de déplacement sont différentes entre les trois modes de transport.

    @@ -1756,7 +1756,7 @@

    -

    Pour visualiser la distribution des données pour les trois groupes, vous pouvez créer des graphiques de densité et en violon (figure 6.4). La juxtaposition des trois distributions montre que les distributions des valeurs pour les trois groupes sont globalement similaires. Cela est corroboré par le fait que les boîtes du graphique en violon sont situées à la même hauteur. Autrement dit, à la lecture des deux graphiques, il ne semble pas y avoir de différences significatives entre les trois groupes en termes de temps de déplacement.

    +

    Pour visualiser la distribution des données pour les trois groupes, vous pouvez créer des graphiques de densité et en violon (figure fig-Anova1a). La juxtaposition des trois distributions montre que les distributions des valeurs pour les trois groupes sont globalement similaires. Cela est corroboré par le fait que les boîtes du graphique en violon sont situées à la même hauteur. Autrement dit, à la lecture des deux graphiques, il ne semble pas y avoir de différences significatives entre les trois groupes en termes de temps de déplacement.

    library("ggplot2")
     library("ggpubr")
    @@ -1783,7 +1783,7 @@ 

    -

    Nous pouvons vérifier si les échantillons sont normalement distribués avec la fonction shapiro_test du package rstatix. À titre de rappel, l’hypothèse nulle (H0) de ce test est que la distribution est normale. Par conséquent, quand la valeur de p associée à la statistique de Shapiro est supérieure à 0,05, alors nous ne pouvons rejeter l’hypothèse d’une distribution normale (autrement dit, la distribution est anormale). À la lecture des résultats ci-dessous, seul le groupe utilisant le transport en commun présente une distribution proche de la normalité (p = 0,0504). Ce test étant très restrictif, il est fortement conseillé de visualiser le diagramme quantile-quantile pour chaque groupe (graphique QQ plot) (figure 6.5). Ces graphiques sont utilisés pour déterminer visuellement si une distribution empirique (observée sur des données), s’approche d’une distribution théorique (ici la loi normale). Si effectivement les deux distributions sont proches, les points du diagramme devraient tous tomber sur une ligne droite parfaite. Un intervalle de confiance (représenté ici en gris) peut être construit pour obtenir une interprétation plus nuancée. Dans notre cas, seules deux observations pour le vélo et deux autres pour l’automobile s’éloignent vraiment de la ligne droite. Nous pouvons considérer que ces trois distributions s’approchent d’une distribution normale.

    +

    Nous pouvons vérifier si les échantillons sont normalement distribués avec la fonction shapiro_test du package rstatix. À titre de rappel, l’hypothèse nulle (H0) de ce test est que la distribution est normale. Par conséquent, quand la valeur de p associée à la statistique de Shapiro est supérieure à 0,05, alors nous ne pouvons rejeter l’hypothèse d’une distribution normale (autrement dit, la distribution est anormale). À la lecture des résultats ci-dessous, seul le groupe utilisant le transport en commun présente une distribution proche de la normalité (p = 0,0504). Ce test étant très restrictif, il est fortement conseillé de visualiser le diagramme quantile-quantile pour chaque groupe (graphique QQ plot) (figure fig-Qqplot). Ces graphiques sont utilisés pour déterminer visuellement si une distribution empirique (observée sur des données), s’approche d’une distribution théorique (ici la loi normale). Si effectivement les deux distributions sont proches, les points du diagramme devraient tous tomber sur une ligne droite parfaite. Un intervalle de confiance (représenté ici en gris) peut être construit pour obtenir une interprétation plus nuancée. Dans notre cas, seules deux observations pour le vélo et deux autres pour l’automobile s’éloignent vraiment de la ligne droite. Nous pouvons considérer que ces trois distributions s’approchent d’une distribution normale.

    library("dplyr")
     library("ggpubr")
    @@ -1895,7 +1895,7 @@ 

    -

    À la lecture des graphiques de densité et en violon (figure 6.6), il semble clair que les niveaux d’exposition au bruit sont plus faibles pour les automobilistes et plus élevés pour les cyclistes et surtout les personnes en transport en commun. En outre, la distribution des valeurs d’exposition au bruit dans le transport en commun semble bimodale. Cela s’explique par le fait que les niveaux de bruit sont beaucoup plus élevés dans le métro que dans les autobus.

    +

    À la lecture des graphiques de densité et en violon (figure fig-Anova1b), il semble clair que les niveaux d’exposition au bruit sont plus faibles pour les automobilistes et plus élevés pour les cyclistes et surtout les personnes en transport en commun. En outre, la distribution des valeurs d’exposition au bruit dans le transport en commun semble bimodale. Cela s’explique par le fait que les niveaux de bruit sont beaucoup plus élevés dans le métro que dans les autobus.

    library("ggplot2")
     library("ggpubr")
    @@ -1921,7 +1921,7 @@ 

    -

    Le test de Shapiro et les graphiques QQ plot (figure 6.7) révèlent que les distributions des trois groupes sont anormales. Ce résultat n’est pas surprenant si l’on tient compte de la nature logarithmique de l’échelle décibel.

    +

    Le test de Shapiro et les graphiques QQ plot (figure fig-Qqplot2) révèlent que les distributions des trois groupes sont anormales. Ce résultat n’est pas surprenant si l’on tient compte de la nature logarithmique de l’échelle décibel.

    library("dplyr")
     library("ggpubr")
    @@ -2087,7 +2087,7 @@ 

    6.3 Conclusion sur la troisième partie

    -

    Dans le cadre de cette troisième partie du livre, nous avons abordé les principales méthodes exploratoires et confirmatoires bivariées permettant d’évaluer la relation entre deux variables. La figure 6.8 propose un résumé de ces méthodes.

    +

    Dans le cadre de cette troisième partie du livre, nous avons abordé les principales méthodes exploratoires et confirmatoires bivariées permettant d’évaluer la relation entre deux variables. La figure fig-PrincipalesAnalysesBivariees propose un résumé de ces méthodes.

    Figure 6.8: Principales méthodes bivariées
    @@ -2151,7 +2151,7 @@

    -Relisez au besoin la section 6.1.1. +Relisez au besoin la section sec-0611.
    @@ -2196,7 +2196,7 @@

    -Relisez au besoin la section 6.1.2. +Relisez au besoin la section sec-0612.
    @@ -2241,7 +2241,7 @@

    -Relisez au besoin le début de la section 6.1.1. +Relisez au besoin le début de la section sec-0611.
    @@ -2270,7 +2270,7 @@

    -Relisez au besoin la section 6.1.1. +Relisez au besoin la section sec-0611.
    @@ -2307,7 +2307,7 @@

    -Relisez au besoin la section 6.1.1.1. +Relisez au besoin la section sec-06111.
    @@ -2336,7 +2336,7 @@

    -Relisez au besoin la section 6.2.1.1. +Relisez au besoin la section sec-06211.
    @@ -2365,7 +2365,7 @@

    -Relisez au besoin la section 6.2.1.3. +Relisez au besoin la section sec-06213.
    @@ -2418,7 +2418,7 @@

    -Relisez au besoin la section 6.2.2. +Relisez au besoin la section sec-0622.
    @@ -2447,7 +2447,7 @@

    -Relire le deuxième encadré à la section 6.2.1.1. +Relire le deuxième encadré à la section sec-06211.
    @@ -2484,7 +2484,7 @@

    -Relire le deuxième encadré à la section 6.2.4. +Relire le deuxième encadré à la section sec-0624.
    @@ -2565,7 +2565,7 @@

    -

    7.3 Évaluation de la qualité d’ajustement du modèle

    -

    Pour illustrer la régression linéaire multiple, nous utilisons un jeu de données tiré d’un article portant sur la distribution spatiale de la végétation sur l’île de Montréal abordée sous l’angle de l’équité environnementale (Apparicio et al. 2016). Dans cette étude, les auteurs veulent vérifier si certains groupes de population (personnes à faible revenu, minorités visibles, personnes âgées et enfants de moins de 15 ans) ont ou non une accessibilité plus limitée à la végétation urbaine. En d’autres termes, cet article tente de répondre à la question suivante : une fois contrôlées les caractéristiques de la forme urbaine (densité de population et âge du bâti), est-ce que les quatre groupes de population résident dans des îlots urbains avec proportionnellement moins ou plus de végétation?

    -

    Dans le tableau 7.1, sont reportées les variables utilisées (calculées au niveau des îlots de l’île de Montréal) introduites dans le modèle de régression :

    +

    Pour illustrer la régression linéaire multiple, nous utilisons un jeu de données tiré d’un article portant sur la distribution spatiale de la végétation sur l’île de Montréal abordée sous l’angle de l’équité environnementale (Apparicio et al. 2016). Dans cette étude, les auteurs veulent vérifier si certains groupes de population (personnes à faible revenu, minorités visibles, personnes âgées et enfants de moins de 15 ans) ont ou non une accessibilité plus limitée à la végétation urbaine. En d’autres termes, cet article tente de répondre à la question suivante : une fois contrôlées les caractéristiques de la forme urbaine (densité de population et âge du bâti), est-ce que les quatre groupes de population résident dans des îlots urbains avec proportionnellement moins ou plus de végétation?

    +

    Dans le tableau tbl-datareg, sont reportées les variables utilisées (calculées au niveau des îlots de l’île de Montréal) introduites dans le modèle de régression :

    • le pourcentage de la superficie de l’îlot couverte par de la végétation, soit la variable indépendante (VI);

    • deux variables indépendantes de contrôle (VC) relatives à la forme urbaine;

    • @@ -652,11 +652,11 @@

      7.3.1 Mesures de la qualité d’un modèle

      -

      Comme pour la régression linéaire simple (section 4.4), les trois mesures les plus couramment utilisées pour évaluer la qualité d’un modèle sont :

      +

      Comme pour la régression linéaire simple (section sec-044), les trois mesures les plus couramment utilisées pour évaluer la qualité d’un modèle sont :

        -
      • Le coefficient de détermination (R2) qui indique la proportion de la variance de la variable dépendante expliquée par les variables indépendantes du modèle (équation 7.9). Il varie ainsi de 0 à 1.

      • -
      • La statistique de Fisher qui permet d’évaluer la significativité globale du modèle (équation 7.10). Dans le cas d’une régression linéaire multiple, l’hypothèse nulle du test F est que toutes les valeurs des coefficients de régression des variables indépendantes sont égales à 0; autrement dit, qu’aucune des variables indépendantes n’a d’effet sur la variable dépendante. Tel que décrit à la section 4.4.3, il est possible d’obtenir une valeur de p rattachée à la statistique F avec k degrés de liberté au dénominateur et n-k-1 degrés de liberté au numérateur (k et n étant respectivement le nombre de variables indépendantes et le nombre d’observations). Lorsque la valeur de p est inférieure à 0,05, nous pourrons en conclure que le modèle est globalement significatif, c’est-à-dire qu’au moins un coefficient de régression est significativement différent de zéro. Notez qu’il est plutôt rare qu’un modèle de régression, comprenant plusieurs variables indépendantes, soit globalement non significatif (P > 0,05), et ce, surtout s’il est basé sur un cadre conceptuel et théorique solide. Le test de la statistique de Fisher est donc facile à passer et ne constitue pas une preuve absolue de la pertinence du modèle.

      • -
      • L’erreur quadratique moyenne (RMSE) qui indique l’erreur absolue moyenne du modèle exprimée dans l’unité de mesure de la variable dépendante, autrement dit l’écart absolu moyen entre les valeurs observées et prédites du modèle (équation 7.11). Une valeur élevée indique que le modèle se trompe largement en moyenne et inversement.

      • +
      • Le coefficient de détermination (R2) qui indique la proportion de la variance de la variable dépendante expliquée par les variables indépendantes du modèle (équation eq-regmR2). Il varie ainsi de 0 à 1.

      • +
      • La statistique de Fisher qui permet d’évaluer la significativité globale du modèle (équation eq-regmFFisher). Dans le cas d’une régression linéaire multiple, l’hypothèse nulle du test F est que toutes les valeurs des coefficients de régression des variables indépendantes sont égales à 0; autrement dit, qu’aucune des variables indépendantes n’a d’effet sur la variable dépendante. Tel que décrit à la section sec-0443, il est possible d’obtenir une valeur de p rattachée à la statistique F avec k degrés de liberté au dénominateur et n-k-1 degrés de liberté au numérateur (k et n étant respectivement le nombre de variables indépendantes et le nombre d’observations). Lorsque la valeur de p est inférieure à 0,05, nous pourrons en conclure que le modèle est globalement significatif, c’est-à-dire qu’au moins un coefficient de régression est significativement différent de zéro. Notez qu’il est plutôt rare qu’un modèle de régression, comprenant plusieurs variables indépendantes, soit globalement non significatif (P > 0,05), et ce, surtout s’il est basé sur un cadre conceptuel et théorique solide. Le test de la statistique de Fisher est donc facile à passer et ne constitue pas une preuve absolue de la pertinence du modèle.

      • +
      • L’erreur quadratique moyenne (RMSE) qui indique l’erreur absolue moyenne du modèle exprimée dans l’unité de mesure de la variable dépendante, autrement dit l’écart absolu moyen entre les valeurs observées et prédites du modèle (équation eq-regmRMSE). Une valeur élevée indique que le modèle se trompe largement en moyenne et inversement.

      @@ -692,7 +692,7 @@

      -

      Globalement, plus un modèle de régression est efficace, plus les valeurs du R2 et de la statistique F sont élevées et inversement, plus celle de RMSE est faible. En effet, remarquez qu’à l’équation 7.10, la statistique F peut être obtenue à partir du R2; par conséquent, plus la valeur du R2 est forte (proche de 1), plus celle de F est aussi élevée. Notez aussi que plus un modèle est performant, plus la partie expliquée par le modèle (SCE) est importante et plus celle non expliquée (SCR) est faible; ce qui signifie que plus le R2 est proche de 1 (équation 7.9), plus le RMSE – calculé à partir du SCR – est faible (équation 7.11).

      +

      Globalement, plus un modèle de régression est efficace, plus les valeurs du R2 et de la statistique F sont élevées et inversement, plus celle de RMSE est faible. En effet, remarquez qu’à l’équation eq-regmFFisher, la statistique F peut être obtenue à partir du R2; par conséquent, plus la valeur du R2 est forte (proche de 1), plus celle de F est aussi élevée. Notez aussi que plus un modèle est performant, plus la partie expliquée par le modèle (SCE) est importante et plus celle non expliquée (SCR) est faible; ce qui signifie que plus le R2 est proche de 1 (équation eq-regmR2), plus le RMSE – calculé à partir du SCR – est faible (équation eq-regmRMSE).

      La syntaxe R ci-dessous illustre comment calculer les différentes variances (SCT, SCE et SCR) à partir des valeurs observées et prédites par le modèle, puis les valeurs du R2, de F et du RMSE. Nous verrons par la suite qu’il est possible d’obtenir directement ces valeurs à partir de la fonction summary(VotreModele).

      # Chargement des données
      @@ -747,7 +747,7 @@ 

      Notez que ce principe de parcimonie ne signifie pas que vous devez systématiquement retirer toutes les variables non significatives de votre analyse. En effet, il peut y avoir un intérêt théorique à démontrer l’absence de relation entre des variables. Il s’agit plutôt d’une ligne de conduite à garder à l’esprit lors de l’élaboration du cadre théorique et de l’interprétation des résultats.

      -

      Mathématiquement, plus nous ajoutons de variables supplémentaires dans un modèle, plus le R2 augmente. On ne peut donc pas utiliser directement le R2 pour comparer deux modèles de régression ne comprenant pas le même nombre de variables indépendantes. Nous privilégions alors l’utilisation du R2 ajusté qui, comme illustré dans l’équation 7.12, tient compte à la fois des nombres d’observations et des variables indépendantes utilisées pour construire le modèle.

      +

      Mathématiquement, plus nous ajoutons de variables supplémentaires dans un modèle, plus le R2 augmente. On ne peut donc pas utiliser directement le R2 pour comparer deux modèles de régression ne comprenant pas le même nombre de variables indépendantes. Nous privilégions alors l’utilisation du R2 ajusté qui, comme illustré dans l’équation eq-R2ajuste, tient compte à la fois des nombres d’observations et des variables indépendantes utilisées pour construire le modèle.

      \[ R^2_{\text {ajusté}}= 1 - \frac{(1-R^2)(n-1)}{n-k-1} \mbox{ avec } R^2_{\text {ajusté}} \in \left[0,1\right] \tag{7.12}\]

      @@ -757,7 +757,7 @@

      avec \(R^2_1\) et \(R^2_2\) étant les coefficients de détermination des modèles 1 et 2 et \(k_1\) et \(k_2\) étant les nombres de variables indépendantes qu’ils comprennent (\(k_2 > k_1\)).

      Illustrons le tout avec deux modèles. Dans la syntaxe R ci-dessous, nous avons construit un premier modèle avec uniquement les variables de contrôle (modele1), soit deux variables indépendantes (HABHA et AgeMedian). Puis, dans un second modèle (modele2), nous ajoutons comme variables indépendantes les pourcentages des quatre groupes de population (Pct_014, Pct_65P, Pct_MV, Pct_FR). Repérez comment sont calculés les R2 ajustés pour les modèles et le F incrémentiel.

      -

      Le R2 ajusté passe de 0,269 à 0,418 des modèles 1 à 2 signalant que l’ajout des quatre variables indépendantes augmente considérablement la variance expliquée. Autrement dit, le second modèle est bien plus performant. Le F incrémentiel s’élève à 653,8 et est significatif (p < 0,001). Notez que la syntaxe ci-dessous illustre comment calculer les valeurs du R2 ajusté et du F incrémentiel à partir des équations 7.12 et 7.13. Sachez toutefois qu’il est possible d’obtenir directement le R2 ajusté avec la fonction summary(VotreModele) et le F incrémentiel avec la fonction anova(modele1, modele2).

      +

      Le R2 ajusté passe de 0,269 à 0,418 des modèles 1 à 2 signalant que l’ajout des quatre variables indépendantes augmente considérablement la variance expliquée. Autrement dit, le second modèle est bien plus performant. Le F incrémentiel s’élève à 653,8 et est significatif (p < 0,001). Notez que la syntaxe ci-dessous illustre comment calculer les valeurs du R2 ajusté et du F incrémentiel à partir des équations eq-R2ajuste et eq-Fincrementiel. Sachez toutefois qu’il est possible d’obtenir directement le R2 ajusté avec la fonction summary(VotreModele) et le F incrémentiel avec la fonction anova(modele1, modele2).

      modele1 <- lm(VegPct ~ HABHA+AgeMedian, data = DataFinal)
       modele2 <- lm(VegPct ~ HABHA+AgeMedian+Pct_014+Pct_65P+Pct_MV+Pct_FR, data = DataFinal)
      @@ -850,7 +850,7 @@ 

      7.4.1 Coefficients de régression : évaluer l’effet des variables indépendantes

      -

      Les différents résultats pour les coefficients sont reportés au tableau 7.2.

      +

      Les différents résultats pour les coefficients sont reportés au tableau tbl-dataregmodel2.

      La constante (\(\beta_0\)) est la valeur attendue de la variable dépendante (Y) quand les valeurs de toutes les variables indépendantes sont égales à 0. Pour ce modèle, quand les variables indépendantes sont égales à 0, plus du quart de la superficie des îlots serait en moyenne couverte par de la végétation (\(\beta_0\) = 26,36). Notez que la constante n’a pas toujours une interprétation pratique. Il est par exemple très invraisemblable d’avoir un îlot avec de la population dans lequel il n’y aurait aucune personne à faible revenu, aucune personne ne déclarant appartenir à une minorité visible, aucun enfant de moins de 15 ans et aucune personne âgée de 65 ans et plus. La constante a donc avant tout un rôle mathématique dans le modèle.

      Le coefficient de régression (\(\beta_1\) à \(\beta_k\)) indique le changement de la variable dépendante (Y) lorsque la variable indépendante augmente d’une unité, toutes choses étant égales par ailleurs. Il permet ainsi d’évaluer l’effet d’une augmentation d’une unité dans laquelle est mesurée la VI sur la VD.

      @@ -966,7 +966,7 @@

      -

      À partir des coefficients du tableau 7.2, l’équation du modèle de régression s’écrit alors comme suit :

      +

      À partir des coefficients du tableau tbl-dataregmodel2, l’équation du modèle de régression s’écrit alors comme suit :

      VegPct = 26,356 − 0,070 HABHA + 0,011 AgeMedian + 1,084 Pct_014 + 0,401 Pct_65P −0,031 Pct_MV − 0,348 Pct_FR + e

      Comment interpréter un coefficient de régression pour une variable indépendante?

      Le signe du coefficient de régression indique si la variable indépendante est associée positivement ou négativement avec la variable dépendante. Par exemple, plus la densité de population est importante à travers les îlots de l’île de Montréal, plus la couverture végétale diminue.

      @@ -978,7 +978,7 @@

      7.4.2 Coefficients de régression standardisés : repérer les variables les plus importantes du modèle

      Un coefficient de régression est exprimé dans les unités de mesure des variables indépendante (VI) et dépendante (VD) : une augmentation d’une unité de la VI a un effet de \(\beta\) (valeur de coefficient) unité de mesure sur la VD, toutes choses étant égales par ailleurs. Prenons l’exemple d’un modèle fictif dans lequel une variable indépendante mesurée en mètres obtient un coefficient de régression de 0,000502. Si cette variable était exprimée en kilomètres et non en mètres, son coefficient serait alors de 0,502 (\(0,000502 \times 1000 = 0,502\)). Cela explique que pour certaines variables, il est souvent préférable de modifier l’unité de mesure, particulièrement pour les variables de distance ou de revenu. Par exemple, dans un modèle de régression, nous introduisons habituellement une variable de revenu par tranche de mille dollars ou le loyer mensuel par tranche de cent dollars, puisque les coefficients du revenu ou de loyer exprimé en dollars risquent d’être extrêmement faibles. Concrètement, cela signifie que nous divisons la variable revenu par 1000 et celle du loyer par 100 avant de l’introduire dans le modèle.

      -

      Du fait de leur unités de mesure souvent différentes, vous aurez compris que nous ne pouvons pas comparer directement les coefficients de régression afin de repérer la ou les variables indépendantes (X) qui ont les effets (impacts) les plus importants sur la variable dépendante (Y). Pour remédier à ce problème, nous utilisons les coefficients de régression standardisés. Ces coefficients standardisés sont simplement les valeurs de coefficients de régression qui seraient obtenus si toutes les variables du modèle (VD et VI) étaient préalablement centrées réduites (soit avec une moyenne égale à 0 et un écart-type égal à 1; consultez la section 2.5.5.2 pour un rappel). Puisque toutes les variables du modèle sont exprimées en écarts-types, les coefficients standardisés permettent ainsi d’évaluer l’effet relatif des VI sur la VD. Cela permet ainsi de repérer la ou les variables les plus « importantes » du modèle.

      +

      Du fait de leur unités de mesure souvent différentes, vous aurez compris que nous ne pouvons pas comparer directement les coefficients de régression afin de repérer la ou les variables indépendantes (X) qui ont les effets (impacts) les plus importants sur la variable dépendante (Y). Pour remédier à ce problème, nous utilisons les coefficients de régression standardisés. Ces coefficients standardisés sont simplement les valeurs de coefficients de régression qui seraient obtenus si toutes les variables du modèle (VD et VI) étaient préalablement centrées réduites (soit avec une moyenne égale à 0 et un écart-type égal à 1; consultez la section sec-02552 pour un rappel). Puisque toutes les variables du modèle sont exprimées en écarts-types, les coefficients standardisés permettent ainsi d’évaluer l’effet relatif des VI sur la VD. Cela permet ainsi de repérer la ou les variables les plus « importantes » du modèle.

      L’interprétation d’un coefficient de régression standardisé est donc la suivante : il indique le changement en termes d’unités d’écart-type de la variable dépendante (Y) à chaque ajout d’un écart-type de la variable indépendante, toutes choses étant égales par ailleurs.

      Le coefficient de régression standardisé peut être aussi facilement calculé en utilisant les écarts-types des deux variables VI et VD :

      \[ @@ -987,7 +987,7 @@

      La syntaxe R ci-dessous illustre trois façons d’obtenir les coefficients standardisés :

      • en centrant et réduisant préalablement les variables avec la fonction scale avant de construire le modèle avec la fonction lm;

      • -
      • en calculant les écarts-types de VD et de VI et en appliquant l’équation 7.14;

      • +
      • en calculant les écarts-types de VD et de VI et en appliquant l’équation eq-CoefStand;

      • avec la fonction lm.beta du package QuantPsyc. Cette dernière méthode est moins « verbeuse » (deux lignes de code uniquement), mais nécessite de charger un package supplémentaire.

      @@ -1098,7 +1098,7 @@

      avec 1,084 étant le coefficient de régression de Pct_014, 5,295 et 18,562 étant respectivement les écarts-types de Pct_014 (variable indépendante) et de VegPct (variable dépendante).

      -

      Au tableau 7.3, nous constatons que la valeur absolue du coefficient de régression pour HABHA est inférieure à celle de Pct_65P (−0,070 versus 0,401), ce qui n’est pas le cas pour leur coefficient standardisé (−0,281 versus 0,179). Rappelez-vous aussi que nous ne pouvons pas directement comparer les effets de ces deux variables à partir des coefficients de régression puisqu’elles sont exprimées dans des unités de mesure différentes : HABHA est exprimée en habitants par hectare et Pct_65P en pourcentage. À la lecture des coefficients standardisés, nous pouvons en conclure que la variable HABHA a un effet relatif plus important que Pct_65P (−0,281 versus 0,179).

      +

      Au tableau tbl-CoefStand2, nous constatons que la valeur absolue du coefficient de régression pour HABHA est inférieure à celle de Pct_65P (−0,070 versus 0,401), ce qui n’est pas le cas pour leur coefficient standardisé (−0,281 versus 0,179). Rappelez-vous aussi que nous ne pouvons pas directement comparer les effets de ces deux variables à partir des coefficients de régression puisqu’elles sont exprimées dans des unités de mesure différentes : HABHA est exprimée en habitants par hectare et Pct_65P en pourcentage. À la lecture des coefficients standardisés, nous pouvons en conclure que la variable HABHA a un effet relatif plus important que Pct_65P (−0,281 versus 0,179).

      7.4.3 Significativité des coefficients de régression : valeurs de t et de p

      @@ -1106,7 +1106,7 @@

      \[ t=\frac{\beta_k - 0}{s(\beta_k)} \tag{7.16}\]

      -

      avec \(s(\beta_k)\) étant l’erreur type du coefficient de régression. Notez que dans l’équation 7.16, nous indiquons habituellement \(-0\), pour signaler que l’on veut vérifier si le coefficient est différent de 0. En guise d’exemple, au tableau 7.2, la valeur de t de la variable HABHA est bien égale à :

      +

      avec \(s(\beta_k)\) étant l’erreur type du coefficient de régression. Notez que dans l’équation eq-ValeurT, nous indiquons habituellement \(-0\), pour signaler que l’on veut vérifier si le coefficient est différent de 0. En guise d’exemple, au tableau tbl-dataregmodel2, la valeur de t de la variable HABHA est bien égale à :

      \(\mbox{−0,070401 / 0,002202 = −31,975}\).

      @@ -1118,10 +1118,10 @@

      1. Poser l’hypothèse nulle (H0) stipulant que le coefficient est égal à 0, soit \(H_0 : \beta_k = 0\). L’hypothèse alternative (H1) est que le coefficient est différent de 0, soit \(H_1 : B_k \neq 0\).

      2. -
      3. Calculer la valeur de t, soit le coefficient de régression divisé par son erreur type (équation 7.16).

      4. +
      5. Calculer la valeur de t, soit le coefficient de régression divisé par son erreur type (équation eq-ValeurT).

      6. Calculer le nombre de degrés de liberté, soit \(dl = n − k - 1\), n et k étant respectivement les nombres d’observations et de variables indépendantes.

      7. Choisir un seuil de signification alpha (5 %, 1 % ou 0,1 %, soit p = 0,05, 0,01 ou 0,01).

      8. -
      9. Trouver la valeur critique de t dans la table T de Student (section 14.3) avec p et le nombre de degrés de liberté (dl).

      10. +
      11. Trouver la valeur critique de t dans la table T de Student (section sec-143) avec p et le nombre de degrés de liberté (dl).

      12. Valider ou réfuter l’hypothèse nulle (H0) :

        @@ -1141,16 +1141,16 @@

        Si un coefficient est significatif au seuil de 5 % dans notre modèle, cela signifie que si, pour l’ensemble d’une population, la valeur du coefficient est de 0 en réalité, alors nous avions moins de 5 % de chances de collecter un échantillon (pour cette population) ayant produit un coefficient aussi fort que celui que nous observons dans notre propre échantillon. Par conséquent, il serait très invraisemblable que le coefficient soit 0 puisque nous avons effectivement collecté un tel échantillon. Il s’agit d’une forme d’argumentation par l’absurde propre à la statistique fréquentiste.

        Notez que si 100 études étaient conduites sur le même sujet et dans les mêmes conditions, nous nous attendrions à ce que 5 d’entre elles trouvent un coefficient significatif, du fait de la variation des échantillons. Ce constat souligne le fait que la recherche est un effort collectif et qu’une seule étude n’est pas suffisante pour trancher sur un sujet. Les revues systématiques de la littérature sont donc des travaux particulièrement importants pour la construction du consensus scientifique.

        Ne pas confondre significativité et effet de la variable indépendante

        -

        Attention, un coefficient significatif n’est pas toujours intéressant! Autrement dit, bien qu’il soit significatif à un seuil donné (par exemple, p = 0,05), cela ne veut pas dire pour autant qu’il ait un effet important sur la variable dépendante. Il faut donc analyser simultanément les valeurs de p et des coefficients de régression. Afin de mieux saisir l’effet d’un coefficient significatif, il est intéressant de représenter graphiquement l’effet marginal d’une variable indépendante (VI) sur une variable dépendante (VD), une fois contrôlées les autres VI du modèle de régression (section 7.7.4).

        +

        Attention, un coefficient significatif n’est pas toujours intéressant! Autrement dit, bien qu’il soit significatif à un seuil donné (par exemple, p = 0,05), cela ne veut pas dire pour autant qu’il ait un effet important sur la variable dépendante. Il faut donc analyser simultanément les valeurs de p et des coefficients de régression. Afin de mieux saisir l’effet d’un coefficient significatif, il est intéressant de représenter graphiquement l’effet marginal d’une variable indépendante (VI) sur une variable dépendante (VD), une fois contrôlées les autres VI du modèle de régression (section sec-0774).

      -

      Prenons deux variables indépendantes du tableau 7.2HABHA et AgeMedian – et vérifions si leurs coefficients de régression respectifs (−0,070 et 0,011) sont significatifs. Appliquons la démarche décrite dans l’encadré ci-dessus :

      +

      Prenons deux variables indépendantes du tableau tbl-dataregmodel2HABHA et AgeMedian – et vérifions si leurs coefficients de régression respectifs (−0,070 et 0,011) sont significatifs. Appliquons la démarche décrite dans l’encadré ci-dessus :

      1. Nous posons l’hypothèse nulle stipulant que la valeur de ces deux coefficients est égale à 0, soit \(H_0 : \beta_k = 0\).

      2. La valeur de t est égale à −0,070401 / 0,002202 = −31,97139 pour HABHA et à 0,010790 / 0,006369 = 1,694144 pour AgeMedian.

      3. Le nombre de degrés de liberté est égal à \(\mbox{dl} = \mbox{n}-\mbox{k}-\mbox{1} = \mbox{10 210} − \mbox{6} - \mbox{1} = \mbox{10 203}\).

      4. Nous choisissons respectivement les seuils \(\alpha\) de 0,10, 0,05, 0,01 ou 0,001.

      5. -
      6. Avec 10210 degrés de liberté, les valeurs critiques de la table T de Student (section 13.3) sont de 1,65 (p = 0,10), 1,96 (p = 0,05), 2,58 (p = 0,01), 3,29 (p = 0,001).

      7. +
      8. Avec 10210 degrés de liberté, les valeurs critiques de la table T de Student (section sec-133) sont de 1,65 (p = 0,10), 1,96 (p = 0,05), 2,58 (p = 0,01), 3,29 (p = 0,001).

      9. Il reste à valider ou réfuter l’hypothèse nulle (H0) :

        @@ -1193,7 +1193,7 @@

      -

      D’autre part, la fonction summary renvoie d’emblée les valeurs de t et de p. Par convention, R, comme la plupart des logiciels d’analyses statistiques, utilise aussi des symboles pour indiquer le seuil de signification du coefficient (voir tableau 7.3) :

      +

      D’autre part, la fonction summary renvoie d’emblée les valeurs de t et de p. Par convention, R, comme la plupart des logiciels d’analyses statistiques, utilise aussi des symboles pour indiquer le seuil de signification du coefficient (voir tableau tbl-CoefStand2) :

      ’***’ p <= 0,001

      ’**’ p <= 0,01

      ’*’ p <= 0,05

      @@ -1250,7 +1250,7 @@

      \[ \mbox{Intervalle à 99,9 \%\: } IC_{\beta_k}= \left[ \beta_k - 3,29 \times s(\beta_k) ; \beta_k + 3,29 \times s(\beta_k) \right] \tag{7.20}\]

      -

      La syntaxe R ci-dessous illustre comment calculer les intervalles de confiance à 95 % à partir de l’équation 7.17. Rappelez-vous toutefois qu’il est bien plus simple d’utiliser la fonction confint:

      +

      La syntaxe R ci-dessous illustre comment calculer les intervalles de confiance à 95 % à partir de l’équation eq-ICcoef. Rappelez-vous toutefois qu’il est bien plus simple d’utiliser la fonction confint:

      • round(confint(Modele1, level=.95),3)
      • round(confint(Modele1, level=.99),3)
      • @@ -1339,11 +1339,11 @@

        7.5.1 Exploration des relations non linéaires

        7.5.1.1 Variable indépendante avec une fonction polynomiale

        -

        Dans la section 4.1, nous avons vu que la relation entre deux variables continues n’est pas toujours linéaire; elle peut être aussi curvilinéaire. Pour explorer les relations curvilinéaires, nous introduisons la variable indépendante sous la forme polynomiale d’ordre 2 (voir le prochain encadré). L’équation de régression s’écrit alors :

        +

        Dans la section sec-041, nous avons vu que la relation entre deux variables continues n’est pas toujours linéaire; elle peut être aussi curvilinéaire. Pour explorer les relations curvilinéaires, nous introduisons la variable indépendante sous la forme polynomiale d’ordre 2 (voir le prochain encadré). L’équation de régression s’écrit alors :

        \[ Y = b_{0} + b_{1}X_{1} + b_{11}X_{1}^2 + b_{2}X_{2} +\ldots+ b_{k}X_{k} + e \tag{7.21}\]

        -

        Dans l’équation 7.21, la première variable indépendante est introduite dans le modèle de régression à la fois dans sa forme originelle et mise au carré : \(b_{1}X_{1} + b_{11}X_{1}^2\). Un coefficient différent est ajusté pour chacune de ces deux versions de la variable \(X_{1}\).

        +

        Dans l’équation eq-regpolyordre2, la première variable indépendante est introduite dans le modèle de régression à la fois dans sa forme originelle et mise au carré : \(b_{1}X_{1} + b_{11}X_{1}^2\). Un coefficient différent est ajusté pour chacune de ces deux versions de la variable \(X_{1}\).

        La démographie est probablement la discipline des sciences sociales qui a le plus recours aux régressions polynomiales. En effet, la variable âge est souvent introduite comme variable explicative dans sa forme originale et mise au carré. L’objectif est de vérifier si l’âge partage ou non une relation curvilinéaire avec un phénomène donné : par exemple, il pourrait y être associé positivement jusqu’à un certain seuil (45 ans par exemple), puis négativement à partir de ce seuil.

        @@ -1353,7 +1353,7 @@

        Régression polynomiale et nombre d’ordres

        -

        Sachez qu’il est aussi possible de construire des régressions polynomiales avec plus de deux ordres. Par exemple, une régression polynomiale d’ordre 3 comprend une variable dans sa forme originelle, puis mise au carré et au cube. Cela a l’inconvénient d’augmenter corollairement le nombre de coefficients. Nous verrons au chapitre 11 qu’il existe une solution plus élégante et efficace : le recours aux modèles de régressions linéaires généralisés additifs avec des splines. Dans le cadre de cette section, nous nous limitons à des régressions polynomiales d’ordre 2.

        +

        Sachez qu’il est aussi possible de construire des régressions polynomiales avec plus de deux ordres. Par exemple, une régression polynomiale d’ordre 3 comprend une variable dans sa forme originelle, puis mise au carré et au cube. Cela a l’inconvénient d’augmenter corollairement le nombre de coefficients. Nous verrons au chapitre sec-chap11 qu’il existe une solution plus élégante et efficace : le recours aux modèles de régressions linéaires généralisés additifs avec des splines. Dans le cadre de cette section, nous nous limitons à des régressions polynomiales d’ordre 2.

        \[ \mbox{Ordre 2 : } Y = b_{0} + b_{1}X_{1} + b_{11}X_{}^2 + b_{2}X_{2} +\ldots+ b_{k}X_{k} + e \tag{7.22}\]

        @@ -1459,7 +1459,7 @@

        Construction d’un graphique des effets marginaux

        Pour visualiser la relation linéaire et curvilinéaire, nous vous proposons de réaliser un graphique des effets marginaux à partir de la syntaxe ci-dessous.

        -

        Les graphiques des effets marginaux permettent de visualiser l’impact d’une variable indépendante sur la variable dépendante d’une régression. Nous nous basons pour cela sur les prédictions effectuées par le modèle. Admettons que nous nous intéressons à l’effet de la variable X1 sur la variable Y. Il est possible de créer de nouvelles données fictives pour lesquelles l’ensemble des autres variables X sont fixées à leur moyenne respective, et seule X1 est autorisée à varier. En utilisant l’équation de régression du modèle sur ces données fictives, nous pouvons observer l’évolution de la valeur prédite de Y quand X1 augmente ou diminue, et ce, toutes choses étant égales par ailleurs (puisque toutes les autres variables ont une valeur fixe). Cette approche est particulièrement intéressante pour décrire des effets non linéaires obtenus avec des polynomiales, mais aussi des interactions comme nous le verrons plus tard. Elle est également utilisée dans les modèles linéaires généralisés (GLM) et additifs (GAM) (chapitres 8 et 11). Notez qu’il est aussi important de représenter, sur ce type de graphique, l’incertitude de la prédiction. Pour cela, il est possible de construire des intervalles de confiance à 95 % autour de la prédiction en utilisant l’erreur standard de la prédiction (renvoyée par la fonction predict).

        +

        Les graphiques des effets marginaux permettent de visualiser l’impact d’une variable indépendante sur la variable dépendante d’une régression. Nous nous basons pour cela sur les prédictions effectuées par le modèle. Admettons que nous nous intéressons à l’effet de la variable X1 sur la variable Y. Il est possible de créer de nouvelles données fictives pour lesquelles l’ensemble des autres variables X sont fixées à leur moyenne respective, et seule X1 est autorisée à varier. En utilisant l’équation de régression du modèle sur ces données fictives, nous pouvons observer l’évolution de la valeur prédite de Y quand X1 augmente ou diminue, et ce, toutes choses étant égales par ailleurs (puisque toutes les autres variables ont une valeur fixe). Cette approche est particulièrement intéressante pour décrire des effets non linéaires obtenus avec des polynomiales, mais aussi des interactions comme nous le verrons plus tard. Elle est également utilisée dans les modèles linéaires généralisés (GLM) et additifs (GAM) (chapitres sec-chap08 et sec-chap11). Notez qu’il est aussi important de représenter, sur ce type de graphique, l’incertitude de la prédiction. Pour cela, il est possible de construire des intervalles de confiance à 95 % autour de la prédiction en utilisant l’erreur standard de la prédiction (renvoyée par la fonction predict).

        library(ggplot2)
         # Statistique sur la variable AgeMedian qui varie de 0 à 226 ans
        @@ -1522,11 +1522,11 @@ 

        -

        La figure 7.2 démontre bien que la relation linéaire n’est pas significative : la pente est extrêmement faible, ce qui signale que l’effet de l’âge médian est presque nul (B = 0,0108, p = 0,0902). En revanche, la relation curvilinéaire est plus intéressante : la couverture végétale croît quand l’âge médian des bâtiments dans l’îlot augmente de 0 à 60 ans environ, puis elle décroît.

        +

        La figure fig-calculRegPoly2 démontre bien que la relation linéaire n’est pas significative : la pente est extrêmement faible, ce qui signale que l’effet de l’âge médian est presque nul (B = 0,0108, p = 0,0902). En revanche, la relation curvilinéaire est plus intéressante : la couverture végétale croît quand l’âge médian des bâtiments dans l’îlot augmente de 0 à 60 ans environ, puis elle décroît.

        7.5.1.2 Variable indépendante sous forme logarithmique

        -

        Une autre manière d’explorer une relation non linéaire est d’intégrer la variable sous forme logarithmique (Hanck et al. 2019, 212‑218). L’interprétation du coefficient de régression est alors plus complexe : 1 % d’augmentation de la variable \(X_k\) entraîne un changement de \(\mbox{0,01} \times \beta_k\) de la variable dépendante. Autrement dit, il n’est plus exprimé dans les unités de mesure originales des deux variables.

        -

        Au tableau 7.4, le coefficient de -6,855 pour la variable logHABHA s’interprète alors comme suit : un changement de 1 % de la variable densité de population entraîne une diminution de \(\mbox{0,01} \times -\mbox{6,855 =} -\mbox{0,07}\) de la couverture végétale dans l’île, toutes choses étant égales par ailleurs.

        +

        Une autre manière d’explorer une relation non linéaire est d’intégrer la variable sous forme logarithmique (Hanck et al. 2019, 212‑218). L’interprétation du coefficient de régression est alors plus complexe : 1 % d’augmentation de la variable \(X_k\) entraîne un changement de \(\mbox{0,01} \times \beta_k\) de la variable dépendante. Autrement dit, il n’est plus exprimé dans les unités de mesure originales des deux variables.

        +

        Au tableau tbl-regmodeleLog, le coefficient de -6,855 pour la variable logHABHA s’interprète alors comme suit : un changement de 1 % de la variable densité de population entraîne une diminution de \(\mbox{0,01} \times -\mbox{6,855 =} -\mbox{0,07}\) de la couverture végétale dans l’île, toutes choses étant égales par ailleurs.

        @@ -1641,7 +1641,7 @@

        Puisque l’interprétation du coefficient de régression de \(log(\beta_k)\) est plus complexe, il convient de s’assurer que son apport au modèle est justifié, et ce, de deux façons :

        • Comparez les mesures d’ajustement des deux modèles (surtout les R2 ajustés). Si le R2 ajusté du modèle avec \(log(\beta_k)\) est plus élevé que celui avec \(\beta_k\), alors la transformation logarithmique fait de votre variable indépendante un meilleur prédicteur, toutes choses étant égales par ailleurs.

        • -
        • Construisez les graphiques des effets marginaux de votre variable afin de vérifier si la relation qu’elle partage avec votre VD est plutôt logarithmique que linéaire (figure 7.3). Notez que cette approche graphique peut aussi ne donner aucune indication lorsque vos données sont très dispersées ou que la relation est faible entre votre variable dépendante et indépendante.

        • +
        • Construisez les graphiques des effets marginaux de votre variable afin de vérifier si la relation qu’elle partage avec votre VD est plutôt logarithmique que linéaire (figure fig-EffetMarginalVariableLogEtNon). Notez que cette approche graphique peut aussi ne donner aucune indication lorsque vos données sont très dispersées ou que la relation est faible entre votre variable dépendante et indépendante.

        library(ggpubr)
        @@ -1688,9 +1688,9 @@ 

      7.5.2 Variable indépendante qualitative dichotomique

      -

      Il est très fréquent d’introduire une variable qualitative dichotomique comme variable explicative ou de contrôle dans un modèle. À titre de rappel, une variable dichotomique comprend deux modalités (section 2.1.2).

      +

      Il est très fréquent d’introduire une variable qualitative dichotomique comme variable explicative ou de contrôle dans un modèle. À titre de rappel, une variable dichotomique comprend deux modalités (section sec-0212).

      Dans le modèle ci-dessous, nous voulons vérifier si un îlot situé sur le territoire de la ville de Montréal a proportionnellement moins de végétation qu’un îlot situé dans une autre municipalité de l’île de Montréal, toutes choses étant égales par ailleurs. Pour ce faire, nous créons une variable binaire dénommée VilleMtl qui prend la valeur de 1 pour les îlots de la ville de Montréal et 0 pour ceux d’une autre municipalité.

      -

      Nous obtenons ainsi un coefficient de régression pour VilleMtl de -7,699 (tableau 7.5). Cela signifie que si toutes les autres variables indépendantes du modèle étaient constantes, alors un îlot de la ville de Montréal aurait en moyenne une valeur de -7,7 % de moins de végétation comparativement à un îlot situé dans une autre municipalité.

      +

      Nous obtenons ainsi un coefficient de régression pour VilleMtl de -7,699 (tableau tbl-regmodeleDich2). Cela signifie que si toutes les autres variables indépendantes du modèle étaient constantes, alors un îlot de la ville de Montréal aurait en moyenne une valeur de -7,7 % de moins de végétation comparativement à un îlot situé dans une autre municipalité.

      # Création d'une variable muette pour Montréal (0 ou 1)
       DataFinal$VilleMtl <- ifelse(DataFinal$SDRNOM == "Montréal", 1, 0)
      @@ -1831,10 +1831,10 @@ 

      Pour une variable dichotomique, le coefficient indique le changement de Y quand les observations appartiennent à la modalité qui a la valeur de 1 (ici la ville de Montréal), comparativement à celle qui a la valeur de 0 (autres municipalités de l’île de Montréal), toutes choses étant égales par ailleurs.

      La modalité qui a la valeur de 0 est alors appelée modalité ou catégorie de référence.

      Autrement dit, si la variable avait été codée : 0 pour la ville de Montréal et 1 pour les autres municipalités, alors le coefficient aurait été de 7,699.

      -

      Pour éviter d’oublier quelle est la modalité de référence (valeur de 0), nous verrons plus tard (dans la section mise en œuvre des modèles de régression dans R (section 7.7) qu’il peut être préférable de définir un facteur avec la fonction as.factor et d’indiquer la catégorie de référence avec la fonction relevel(x, ref).

      +

      Pour éviter d’oublier quelle est la modalité de référence (valeur de 0), nous verrons plus tard (dans la section mise en œuvre des modèles de régression dans R (section sec-077) qu’il peut être préférable de définir un facteur avec la fonction as.factor et d’indiquer la catégorie de référence avec la fonction relevel(x, ref).

      -

      Comme pour une variable indépendante introduite avec une fonction polynomiale, il peut être très intéressant d’illustrer l’effet marginal de la variable dichotomique avec un graphique qui montre l’écart entre les moyennes des deux modalités, une fois contrôlées les autres variables indépendantes (figure 7.4). Notez que dans ce graphique, les barres d’erreurs situées au sommet des rectangles représentent les intervalles à 95 % des prédictions du modèle.

      +

      Comme pour une variable indépendante introduite avec une fonction polynomiale, il peut être très intéressant d’illustrer l’effet marginal de la variable dichotomique avec un graphique qui montre l’écart entre les moyennes des deux modalités, une fois contrôlées les autres variables indépendantes (figure fig-EffetMarginalDich). Notez que dans ce graphique, les barres d’erreurs situées au sommet des rectangles représentent les intervalles à 95 % des prédictions du modèle.

      @@ -1845,14 +1845,14 @@

      7.5.3 Variable indépendante qualitative polytomique

      -

      Il est possible d’introduire une variable qualitative polytomique comme variable explicative ou de contrôle dans un modèle. À titre de rappel, une variable polytomique comprend plus de deux modalités, qu’elle soit nominale ou ordinale (section 2.1.2).

      +

      Il est possible d’introduire une variable qualitative polytomique comme variable explicative ou de contrôle dans un modèle. À titre de rappel, une variable polytomique comprend plus de deux modalités, qu’elle soit nominale ou ordinale (section sec-0212).

      En guise d’exemple, une variable qualitative pourrait être : différents groupes de population (groupes d’âge, minorités visibles, catégories socioprofessionnelles, etc.), différents territoires ou régions (ville centrale, première couronne, deuxième couronne, etc.), une variable continue transformée en quatre ou cinq catégories ordinales selon les quartiles ou les quintiles.

      7.5.3.1 Comment construire un modèle de régression avec une variable explicative qualitative polytomique?

      Prenons l’exemple d’un modèle de régression comprenant deux variables indépendantes : l’une continue (X1), l’autre qualitative (X2) avec quatre modalités (A, B, C et D). L’introduction de la variable qualitative dans le modèle revient à :

        -
      • Transformer chaque modalité en variable muette (binaire). Nous avons ainsi quatre nouvelles variables binaires : X2A, X2B, X2C et X2D. Par exemple, pour X2A, les observations de la modalité A se verront affecter la valeur de 1 versus 0 pour les autres observations. La même démarche s’applique à X2B, X2C et X2D (voir tableau 7.6).

      • -
      • Toutes les modalités transformées en variables muettes sont introduites dans le modèle comme variables indépendantes sauf celle servant de catégorie de référence. Pourquoi sauf une? Si nous mettions toutes les modalités en variable muette, alors chaque observation serait repérée par une valeur de 1, « il y aurait alors une parfaite multicolinéarité et aucune solution unique pour les coefficients de régression ne pourrait être trouvée » (Bressoux 2010, 128).

      • +
      • Transformer chaque modalité en variable muette (binaire). Nous avons ainsi quatre nouvelles variables binaires : X2A, X2B, X2C et X2D. Par exemple, pour X2A, les observations de la modalité A se verront affecter la valeur de 1 versus 0 pour les autres observations. La même démarche s’applique à X2B, X2C et X2D (voir tableau tbl-transfVarQMuettes).

      • +
      • Toutes les modalités transformées en variables muettes sont introduites dans le modèle comme variables indépendantes sauf celle servant de catégorie de référence. Pourquoi sauf une? Si nous mettions toutes les modalités en variable muette, alors chaque observation serait repérée par une valeur de 1, « il y aurait alors une parfaite multicolinéarité et aucune solution unique pour les coefficients de régression ne pourrait être trouvée » (Bressoux 2010, 128).

      • Par exemple, si nous choisissons la modalité A comme catégorie de référence, l’équation de régression s’écrit alors :

      \[ @@ -1882,8 +1882,8 @@

      1 -53,95 -18,36 +44,27 +18,71 A 1 0 @@ -1892,8 +1892,8 @@

      2 -41,38 -28,49 +38,12 +22,08 A 1 0 @@ -1902,8 +1902,8 @@

      3 -31,67 -32,53 +60,94 +18,88 A 1 0 @@ -1912,8 +1912,8 @@

      4 -57,24 -12,49 +46,03 +19,77 B 0 1 @@ -1922,8 +1922,8 @@

      5 -56,11 -11,30 +45,61 +16,16 B 0 1 @@ -1932,8 +1932,8 @@

      6 -39,64 -9,53 +51,43 +22,61 B 0 1 @@ -1942,8 +1942,8 @@

      7 -43,36 -11,00 +35,56 +16,06 C 0 0 @@ -1952,8 +1952,8 @@

      8 -39,20 -24,90 +38,75 +23,77 C 0 0 @@ -1962,8 +1962,8 @@

      9 -48,23 -14,08 +45,91 +11,70 D 0 0 @@ -1972,8 +1972,8 @@

      10 -62,16 -12,77 +65,31 +23,83 D 0 0 @@ -1987,7 +1987,7 @@

      7.5.3.2 Comment interpréter les coefficients des modalités d’une variable explicative qualitative polytomique

      -

      Les coefficients des différentes modalités s’interprètent en fonction de la catégorie de référence. Dans l’exemple ci-dessous, nous avons inclus la ville de Montréal comme catégorie de référence (tableau 7.7). Toutes choses étant égales par ailleurs, nous pouvons alors constater que  :

      +

      Les coefficients des différentes modalités s’interprètent en fonction de la catégorie de référence. Dans l’exemple ci-dessous, nous avons inclus la ville de Montréal comme catégorie de référence (tableau tbl-ModeleVarPoly1). Toutes choses étant égales par ailleurs, nous pouvons alors constater que  :

      • en moyenne, les îlots résidentiels de Senneville et de Baie-D’Urfé ont respectivement 23,235 % et 21,400 % plus de végétation que ceux de la ville de Montréal.

      • la seule municipalité comprenant en moyenne moins de végétation dans ses îlots résidentiels est Montréal-Est (-13,334 %).

      • @@ -2213,7 +2213,7 @@

        -

        Utilisons maintenant comme référence la municipalité qui avait le coefficient le plus fort dans le modèle précédent, soit Senneville (tableau 7.8). Bien entendu, les coefficients des variables continues et de la constante ne changent pas. Par contre, les coefficients de toutes les municipalités sont négatifs puisque la municipalité de Senneville est celle qui a proportionnellement le plus de végétation dans ses îlots, toutes choses étant égales par ailleurs.

        +

        Utilisons maintenant comme référence la municipalité qui avait le coefficient le plus fort dans le modèle précédent, soit Senneville (tableau tbl-ModeleVarPoly2). Bien entendu, les coefficients des variables continues et de la constante ne changent pas. Par contre, les coefficients de toutes les municipalités sont négatifs puisque la municipalité de Senneville est celle qui a proportionnellement le plus de végétation dans ses îlots, toutes choses étant égales par ailleurs.

        @@ -2433,7 +2433,7 @@

        -

        À l’inverse, si nous utilisons Montréal-Est comme modalité de référence, soit la municipalité avec le coefficient le plus faible dans le premier modèle, tous les coefficients deviendront positifs (tableau 7.9).

        +

        À l’inverse, si nous utilisons Montréal-Est comme modalité de référence, soit la municipalité avec le coefficient le plus faible dans le premier modèle, tous les coefficients deviendront positifs (tableau tbl-ModeleVarPoly3).

        @@ -2673,7 +2673,7 @@

      7.5.3.3 Effet marginal d’une variable explicative qualitative polytomique

      -

      Comme pour une variable dichotomique, il est possible d’illustrer l’effet marginal de la variable qualitative dichotomique avec un graphique. Quelle que soit la catégorie de référence choisie, le graphique est le même. La figure 7.5 illustre ainsi la valeur moyenne, avec son intervalle de confiance à 95 %, de la végétation dans les îlots résidentiels de chacune des municipalités de la région de Montréal, ceteris paribus.

      +

      Comme pour une variable dichotomique, il est possible d’illustrer l’effet marginal de la variable qualitative dichotomique avec un graphique. Quelle que soit la catégorie de référence choisie, le graphique est le même. La figure fig-EffetMarginalPoly illustre ainsi la valeur moyenne, avec son intervalle de confiance à 95 %, de la végétation dans les îlots résidentiels de chacune des municipalités de la région de Montréal, ceteris paribus.

      @@ -2691,7 +2691,7 @@

      Un nouveau coefficient (\(\beta_{3}\)) s’ajoute pour l’interaction (la multiplication) entre les deux variables continues. Pourquoi ajouter une interaction entre deux variables? L’objectif est d’évaluer l’effet d’une augmentation de \(\beta_{1}\) en fonction d’un niveau donné de \(\beta_{2}\) et inversement. Cela permet ainsi de répondre à la question suivante : l’effet de la variable \(\beta_{1}\) est-il influencé par la variable \(\beta_{2}\) et inversement?

      -

      Prenons un exemple concret pour illustrer le tout. Premièrement, nous ajoutons DistCBDkm comme VI, soit la distance au centre-ville exprimée en kilomètres. Notez que pour ne pas surspécifier le modèle, les variables dichotomique VilleMtl ou polytomique Municipalité ont été préalablement ôtées. Le coefficient (B = 0,659, p < 0,001) signale que plus nous nous éloignons du centre-ville, plus la couverture végétale des îlots augmente significativement. En guise d’exemple, toutes choses étant égales par ailleurs, un îlot situé à dix kilomètres du centre-ville aura en moyenne 6,59 % plus de végétation (tableau 7.10).

      +

      Prenons un exemple concret pour illustrer le tout. Premièrement, nous ajoutons DistCBDkm comme VI, soit la distance au centre-ville exprimée en kilomètres. Notez que pour ne pas surspécifier le modèle, les variables dichotomique VilleMtl ou polytomique Municipalité ont été préalablement ôtées. Le coefficient (B = 0,659, p < 0,001) signale que plus nous nous éloignons du centre-ville, plus la couverture végétale des îlots augmente significativement. En guise d’exemple, toutes choses étant égales par ailleurs, un îlot situé à dix kilomètres du centre-ville aura en moyenne 6,59 % plus de végétation (tableau tbl-ModeleInteraction1).

      @@ -2783,8 +2783,8 @@

      -

      Dans ce modèle (tableau 7.10), les pourcentages d’enfants de moins de 15 ans et de 65 ans et plus (Pct_014 et Pct_65P) sont associés positivement à la variable dépendante tandis que le pourcentage de personnes à faible revenu (Pct_FR) est associé négativement.

      -

      Que se passe-t-il si nous introduisons une variable d’interaction entre DistCBDkm et Pct_FR (tableau 7.11)? L’effet du pourcentage de personnes à faible revenu (%) est significatif et négatif lorsqu’il est mis en interaction avec la distance au centre-ville. Cela indique que plus l’îlot est éloigné du centre-ville, plus Pct_FR a un effet négatif sur la couverture végétale (B = −0,011, p < 0,001).

      +

      Dans ce modèle (tableau tbl-ModeleInteraction1), les pourcentages d’enfants de moins de 15 ans et de 65 ans et plus (Pct_014 et Pct_65P) sont associés positivement à la variable dépendante tandis que le pourcentage de personnes à faible revenu (Pct_FR) est associé négativement.

      +

      Que se passe-t-il si nous introduisons une variable d’interaction entre DistCBDkm et Pct_FR (tableau tbl-ModeleInteraction2)? L’effet du pourcentage de personnes à faible revenu (%) est significatif et négatif lorsqu’il est mis en interaction avec la distance au centre-ville. Cela indique que plus l’îlot est éloigné du centre-ville, plus Pct_FR a un effet négatif sur la couverture végétale (B = −0,011, p < 0,001).

      @@ -2884,8 +2884,8 @@

      -

      À nouveau, il est possible de représenter l’effet de cette interaction à l’aide d’un graphique des effets marginaux. Notez cependant que nous devons représenter l’effet simultané de deux variables indépendantes sur notre variable dépendante, ce qu’il est possible de faire avec une carte de chaleur. La figure 7.6 représente donc l’effet moyen de l’interaction sur la prédiction dans le premier panneau, ainsi que l’intervalle de confiance à 95 % de la prédiction dans les deuxième et troisième panneaux.

      -

      Nous constatons ainsi que le modèle prédit des valeurs de végétation les plus faibles lorsque le pourcentage de personnes à faible revenu est élevé et que la distance au centre-ville est élevée (en haut à droite à la figure 7.6). En revanche, les valeurs les plus élevées de végétation sont atteintes lorsque la distance au centre-ville est élevée et que le pourcentage de personnes à faible revenu est faible (en bas à droite). Il semble donc que l’éloignement au centre-ville soit associé avec une augmentation de la densité végétale, mais que cette augmentation puisse être mitigée par l’augmentation parallèle du pourcentage de personnes à faible revenu.

      +

      À nouveau, il est possible de représenter l’effet de cette interaction à l’aide d’un graphique des effets marginaux. Notez cependant que nous devons représenter l’effet simultané de deux variables indépendantes sur notre variable dépendante, ce qu’il est possible de faire avec une carte de chaleur. La figure fig-ModeleInteraction2heat représente donc l’effet moyen de l’interaction sur la prédiction dans le premier panneau, ainsi que l’intervalle de confiance à 95 % de la prédiction dans les deuxième et troisième panneaux.

      +

      Nous constatons ainsi que le modèle prédit des valeurs de végétation les plus faibles lorsque le pourcentage de personnes à faible revenu est élevé et que la distance au centre-ville est élevée (en haut à droite à la figure fig-ModeleInteraction2heat). En revanche, les valeurs les plus élevées de végétation sont atteintes lorsque la distance au centre-ville est élevée et que le pourcentage de personnes à faible revenu est faible (en bas à droite). Il semble donc que l’éloignement au centre-ville soit associé avec une augmentation de la densité végétale, mais que cette augmentation puisse être mitigée par l’augmentation parallèle du pourcentage de personnes à faible revenu.

      @@ -2894,7 +2894,7 @@

      -

      Notez que dans la figure 7.6, la relation entre les deux variables indépendantes et la variable dépendante apparaît non linéaire du fait de l’interaction. À titre de comparaison, si nous utilisons les prédictions du modèle 5 (sans interaction), nous obtenons les prédictions présentées à la figure 7.7. Vous pouvez constater sur cette figure sans interaction que les deux effets des variables indépendantes sont linéaires puisque toutes les lignes sont parallèles.

      +

      Notez que dans la figure fig-ModeleInteraction2heat, la relation entre les deux variables indépendantes et la variable dépendante apparaît non linéaire du fait de l’interaction. À titre de comparaison, si nous utilisons les prédictions du modèle 5 (sans interaction), nous obtenons les prédictions présentées à la figure fig-ModeleInteraction2heat2. Vous pouvez constater sur cette figure sans interaction que les deux effets des variables indépendantes sont linéaires puisque toutes les lignes sont parallèles.

      @@ -2909,11 +2909,11 @@

      \[ Y = \beta_{0} + \beta_{1}X_{1} + \beta_{2}D_{2} + \beta_{3}(X_{1}\times D_{2}) +\ldots+ \beta_{k}X_{k} + e \tag{7.28}\]

      -

      Pour interpréter le coefficient \(B_3\), il convient alors de bien connaître le nom de la modalité ayant la valeur de 1 (0 étant la modalité de référence). Dans le modèle présenté au tableau 7.12, nous avons multiplié la variable dichotomique ville de Montréal (VilleMtl) avec le pourcentage de personnes à faible revenu (Pct_FR). Les résultats de ce modèle démontrent que, toutes choses étant égales par ailleurs :

      +

      Pour interpréter le coefficient \(B_3\), il convient alors de bien connaître le nom de la modalité ayant la valeur de 1 (0 étant la modalité de référence). Dans le modèle présenté au tableau tbl-ModeleInteractionBinaire, nous avons multiplié la variable dichotomique ville de Montréal (VilleMtl) avec le pourcentage de personnes à faible revenu (Pct_FR). Les résultats de ce modèle démontrent que, toutes choses étant égales par ailleurs :

      • À chaque augmentation d’une unité du pourcentage à faible revenu (Pct_FR), le pourcentage de la couverture végétale diminue significativement de −0,444.

      • Comparativement à un îlot situé dans une autre municipalité de l’île de Montréal, un îlot de la ville de Montréal a en moyenne −9,804 de couverture végétale.

      • -
      • À chaque augmentation d’une unité de Pct_FR pour un îlot de la Ville Montréal, la couverture végétale augmente de 0,166 comparativement à une autre municipalité de l’île. En d’autres termes, le Pct_FR sur le territoire de la ville de Montréal est associé à une diminution de la couverture végétale moins forte que les autres municipalités, comme illustré à la figure 7.8) (pentes en rouge et en bleu).

      • +
      • À chaque augmentation d’une unité de Pct_FR pour un îlot de la Ville Montréal, la couverture végétale augmente de 0,166 comparativement à une autre municipalité de l’île. En d’autres termes, le Pct_FR sur le territoire de la ville de Montréal est associé à une diminution de la couverture végétale moins forte que les autres municipalités, comme illustré à la figure fig-ModeleInteractionBinaire) (pentes en rouge et en bleu).

      @@ -3014,7 +3014,7 @@

      -

      L’interaction entre une variable qualitative et une variable quantitative peut être représentée par un graphique des effets marginaux. La pente (coefficient) de la variable quantitative varie en fonction des deux catégories de la variable qualitative dichotomique (figure 7.8).

      +

      L’interaction entre une variable qualitative et une variable quantitative peut être représentée par un graphique des effets marginaux. La pente (coefficient) de la variable quantitative varie en fonction des deux catégories de la variable qualitative dichotomique (figure fig-ModeleInteractionBinaire).

      @@ -3033,7 +3033,7 @@

      Variable d’interaction entre deux variables dichotomiques

      -

      Nous avons vu qu’il est possible d’introduire une variable d’interaction entre deux variables continues ou entre une variable continue et une autre dichotomique. Sachez qu’il est aussi possible d’introduire une interaction entre deux variables dichotomiques. Sur le sujet, vous pouvez consulter la section 8.3 de l’excellent ouvrage de Hanck et al. (2019).

      +

      Nous avons vu qu’il est possible d’introduire une variable d’interaction entre deux variables continues ou entre une variable continue et une autre dichotomique. Sachez qu’il est aussi possible d’introduire une interaction entre deux variables dichotomiques. Sur le sujet, vous pouvez consulter la section 8.3 de l’excellent ouvrage de Hanck et al. (2019).

    @@ -3043,7 +3043,7 @@

    7.6.1 Nombre d’observations

    Tous les auteurs ne s’entendent pas sur le nombre d’observations minimal que devrait comprendre une régression linéaire multiple, tant s’en faut! Parallèlement, d’autres auteurs proposent aussi des méthodes de simulation pour estimer les coefficients de régression sur un jeu de données comprenant peu d’observations. Bien qu’aucune règle ne soit bien établie, la question du nombre d’observations mérite d’être posée puisqu’un modèle basé sur trop peu d’observations risque de produire des coefficients de régression peu fiables. Par faible fiabilité des coefficients, nous entendons que la suppression d’une ou de plusieurs observations pourrait drastiquement changer l’effet et/ou la significativité d’une ou de plusieurs variables explicatives.

    -

    Dans un ouvrage classique intitulé Using Multivariate Statistics, Barbara Tabachnick et Linda Fidell (2007, 123‑124) proposent deux règles de pouce (à la louche) :

    +

    Dans un ouvrage classique intitulé Using Multivariate Statistics, Barbara Tabachnick et Linda Fidell (2007, 123‑124) proposent deux règles de pouce (à la louche) :

    1. \(n \geq 50 + 8k\) avec \(n\) et \(k\) étant respectivement les nombres d’observations et de variables indépendantes, pour tester le coefficient de corrélation multiple (R2).

    2. \(n \geq 104 + k\) pour tester individuellement chaque variable indépendante.

    3. @@ -3051,11 +3051,11 @@

      Dans le modèle, nous avons 10 210 observations et variables indépendantes. Les deux conditions sont donc largement respectées.

    7.6.2 Normalité des résidus

    -

    Pour vérifier si les résidus sont normalement distribués, trois démarches largement décrites dans la section 2.5.4 peuvent être utilisées :

    +

    Pour vérifier si les résidus sont normalement distribués, trois démarches largement décrites dans la section sec-0254 peuvent être utilisées :

    • le calcul des coefficients d’asymétrie et d’aplatissement;
    • les tests de normalité, particulièrement celui de Jarque-Bera basé sur un test multiplicateur de Lagrange;
    • -
    • les graphiques (histogramme avec courbe normale et diagramme quantile-quantile) (figure 7.9).
    • +
    • les graphiques (histogramme avec courbe normale et diagramme quantile-quantile) (figure fig-VerifierNormaliteResidus).

    Les deux premières démarches étant parfois très restrictives, nous accordons habituellement une attention particulière aux graphiques.

    Pour notre modèle, les coefficients d’asymétrie (−0,263) et d’aplatissement (1,149) signalent que la distribution est plutôt symétrique, mais leptokurtique, c’est-à-dire que les valeurs des résidus sont bien réparties autour de 0, mais avec une faible dispersion. Puisque la valeur de p associée au test de Jarque-Bera est inférieure à 0,05, nous pouvons en conclure que la distribution des résidus est anormale. La forme pointue de la distribution est d’ailleurs confirmée à la lecture de l’histogramme avec la courbe normale et du diagramme quantile-quantile.

    @@ -3080,7 +3080,7 @@

    7.6.3 Linéarité et homoscédasticité des résidus

    -

    Un modèle est efficace si la dispersion des résidus est homogène sur tout le spectre des valeurs prédites de la variable dépendante. Dans le cas d’une absence d’homoscédasticité – appelée problème d’hétéroscédasticité –, le nuage de points construit à partir des résidus et des valeurs prédites (figure 7.10) prend la forme d’une trompette ou d’un entonnoir : les résidus sont alors faibles quand les valeurs prédites sont faibles et sont de plus en plus élevés au fur et à mesure que les valeurs prédites augmentent.

    +

    Un modèle est efficace si la dispersion des résidus est homogène sur tout le spectre des valeurs prédites de la variable dépendante. Dans le cas d’une absence d’homoscédasticité – appelée problème d’hétéroscédasticité –, le nuage de points construit à partir des résidus et des valeurs prédites (figure fig-VerifierHomoscedasticite) prend la forme d’une trompette ou d’un entonnoir : les résidus sont alors faibles quand les valeurs prédites sont faibles et sont de plus en plus élevés au fur et à mesure que les valeurs prédites augmentent.

    @@ -3118,13 +3118,13 @@

      -
    1. À partir de cette équation, nous obtenons ainsi un \(R^2\) qui nous indique la proportion de la variance de \(X_1\) expliquée par les autres VI. Par convention, nous calculons la tolérance (équation 7.30) qui indique la proportion de la variance de \(X_k\) n’étant pas expliquée par les autres VI. En guise d’exemple, une valeur de tolérance égale à 0,1 signale que 90 % de la variance de \(X_k\) est expliqué par les autres variables, ce qui est un problème de multicolinéarité en soit. Concrètement, plus la valeur de la tolérance est proche de zéro, plus c’est problématique.
    2. +
    3. À partir de cette équation, nous obtenons ainsi un \(R^2\) qui nous indique la proportion de la variance de \(X_1\) expliquée par les autres VI. Par convention, nous calculons la tolérance (équation eq-ToleranceVIF) qui indique la proportion de la variance de \(X_k\) n’étant pas expliquée par les autres VI. En guise d’exemple, une valeur de tolérance égale à 0,1 signale que 90 % de la variance de \(X_k\) est expliqué par les autres variables, ce qui est un problème de multicolinéarité en soit. Concrètement, plus la valeur de la tolérance est proche de zéro, plus c’est problématique.

    \[ \mbox{Tolérance}_k=1-R_k^2=\frac{1}{VIF_k} \tag{7.30}\]

      -
    1. Puis, nous calculons le facteur d’inflation de la variance (équation 7.31). Là encore, des règles de pouce (à la louche) sont utilisées. Certains considéreront une valeur de VIF supérieur à 10 (soit une tolérance à 0,1 ou inférieure) comme problématique, d’autres retiendront le seuil de 5 plus conservateur (soit une tolérance à 0,2 ou inférieure).
    2. +
    3. Puis, nous calculons le facteur d’inflation de la variance (équation eq-VIF). Là encore, des règles de pouce (à la louche) sont utilisées. Certains considéreront une valeur de VIF supérieur à 10 (soit une tolérance à 0,1 ou inférieure) comme problématique, d’autres retiendront le seuil de 5 plus conservateur (soit une tolérance à 0,2 ou inférieure).

    \[ VIF_k = \frac{1}{1-R_k^2} @@ -3145,7 +3145,7 @@

    7.6.4.2 Comment régler un problème de multicolinéarité?

      -
    • La prudence est de mise! Si une ou plusieurs variables présentent une valeur de VIF supérieure à 5, construisez une matrice de corrélation de Pearson (section 4.3.7) et repérez les valeurs de corrélation supérieures à 0,8 ou inférieures à −0,8. Vous repérerez ainsi les corrélations problématiques entre deux variables indépendantes du modèle.

    • +
    • La prudence est de mise! Si une ou plusieurs variables présentent une valeur de VIF supérieure à 5, construisez une matrice de corrélation de Pearson (section sec-0437) et repérez les valeurs de corrélation supérieures à 0,8 ou inférieures à −0,8. Vous repérerez ainsi les corrélations problématiques entre deux variables indépendantes du modèle.

    • Refaites ensuite un modèle en ôtant la variable indépendante avec la plus forte valeur de VIF (7 ou 12 par exemple), et revérifiez les valeurs de VIF. Refaites cette étape si le problème de multicolinéarité excessive persiste.

    @@ -3177,11 +3177,11 @@

    7.6.5 Absence d’observations aberrantes

    7.6.5.1 Détection des observations très influentes du modèle

    -

    Lors de l’analyse des corrélations (section 4.3), nous avons vu que des valeurs extrêmes peuvent avoir un impact important sur le coefficient de corrélation de Pearson. Le même principe s’applique à la régression multiple, pour laquelle nous nous s’attendrions à ce que chaque observation joue un rôle équivalent dans la détermination de l’équation du modèle.

    +

    Lors de l’analyse des corrélations (section sec-043), nous avons vu que des valeurs extrêmes peuvent avoir un impact important sur le coefficient de corrélation de Pearson. Le même principe s’applique à la régression multiple, pour laquelle nous nous s’attendrions à ce que chaque observation joue un rôle équivalent dans la détermination de l’équation du modèle.

    Autrement dit, il est possible que certaines observations avec des valeurs extrêmes – fortement dissemblables des autres – aient une influence importante, voire démesurée, dans l’estimation du modèle. Concrètement, cela signifie que si elles étaient ôtées, les coefficients de régression et la qualité d’ajustement du modèle pourraient changer drastiquement. Deux mesures sont habituellement utilisées pour évaluer l’influence de chaque observation sur le modèle :

    • -La statistique de la distance de Cook qui mesure l’influence de chaque observation sur les résultats du modèle. Brièvement, la distance de Cook évalue l’influence de l’observation i en la supprimant du modèle (équation 7.32). Plus sa valeur est élevée, plus l’observation joue un rôle important dans la détermination de l’équation de régression.
    • +La statistique de la distance de Cook qui mesure l’influence de chaque observation sur les résultats du modèle. Brièvement, la distance de Cook évalue l’influence de l’observation i en la supprimant du modèle (équation eq-DistanceCook). Plus sa valeur est élevée, plus l’observation joue un rôle important dans la détermination de l’équation de régression.

    \[ D_i = \frac{\sum_{j=1}^n(\widehat{y}_i-\widehat{y}_{i(j)})^2}{ks^2} @@ -3205,7 +3205,7 @@

    -

    Le critère de \(4/n\) étant plutôt sévère, nous privilégions généralement celui de \(8/n\), voire \(16/n\). Il est aussi possible de construire un nuage de points pour les repérer (figure 7.11).

    +

    Le critère de \(4/n\) étant plutôt sévère, nous privilégions généralement celui de \(8/n\), voire \(16/n\). Il est aussi possible de construire un nuage de points pour les repérer (figure fig-GraphCookLev).

    @@ -3220,7 +3220,7 @@

  • Recourir à des régressions boostrap, ce qui permet généralement de supprimer l’effet de ces observations. Brièvement, le principe général est de créer un nombre élevé d’échantillons du jeu de données initial (1000 à 2000 itérations par exemple) et de construire un modèle de régression pour chacun d’eux. On obtiendra ainsi des intervalles de confiance pour les coefficients de régression et les mesures d’ajustement du modèle.

  • Supprimer les observations trop influentes (avec l’un des critères de \(4/n\), \(8/n\) et \(16/n\) vus plus haut). Une fois supprimées, il convient 1) de recalculer le modèle, 2) de refaire le diagnostic de la régression au complet et finalement, 3) de comparer les modèles avant et après suppression des valeurs trop influentes, notamment la qualité d’ajustement du modèle (R2 ajusté) et les coefficients de régression. Des changements importants indiqueront que le premier modèle est potentiellement biaisé.

  • -
  • Utiliser un modèle linéaire généralisé (GLM) permettant d’utiliser une distribution différente correspondant plus à votre jeu de données (chapitre 8).

  • +
  • Utiliser un modèle linéaire généralisé (GLM) permettant d’utiliser une distribution différente correspondant plus à votre jeu de données (chapitre sec-chap08).

  • 7.7 Mise en œuvre dans R

    @@ -3282,7 +3282,7 @@

    data = DataFinal) # summary(Modele7) -

    À la figure 7.12, les résultats de la régression linéaire multiple, obtenus avec la summary(monModele), sont présentés en quatre sections distinctes :

    +

    À la figure fig-OutputRegression, les résultats de la régression linéaire multiple, obtenus avec la summary(monModele), sont présentés en quatre sections distinctes :

    1. Le rappel de l’équation du modèle.

    2. Quelques statistiques descriptives sur les résidus du modèle, soit la différence entre les valeurs observées et prédites.

    3. @@ -3310,7 +3310,7 @@

    7.7.2 Comparaison des modèles

    -

    Tel que détaillé à la section 7.3.2, pour comparer des modèles imbriqués, il convient d’analyser les valeurs du R2 ajusté et du F incrémentiel, ce qui peut être fait en trois étapes.

    +

    Tel que détaillé à la section sec-0732, pour comparer des modèles imbriqués, il convient d’analyser les valeurs du R2 ajusté et du F incrémentiel, ce qui peut être fait en trois étapes.

    Première étape. Il peut être judicieux d’afficher l’équation des différents modèles afin de se remémorer les VI introduites dans chacun d’eux, et ce, avec la fonction MonModèle$call$formula.

    # Rappel des équations des huit modèles 
    @@ -3646,7 +3646,7 @@ 

    -

    Vous pouvez également construire un nuage de points avec la distance de Cook et l’effet de levier (leverage value) pour repérer visuellement les observations très influentes (figure 7.15).

    +

    Vous pouvez également construire un nuage de points avec la distance de Cook et l’effet de levier (leverage value) pour repérer visuellement les observations très influentes (figure fig-DiaGraphCookLev).

    library(car)
     library(ggpubr)
    @@ -3717,7 +3717,7 @@ 

    l’asymétrie est très similaire (-0,260 à -0,265);

  • l’aplatissement s’est amélioré (1,183 à 0,164);

  • le test de Jarque-Bera signale toujours un problème de normalité (p < 0,001), mais sa valeur a nettement diminué (548,7 à 131,24);

  • -
  • les graphiques démontrent une nette amélioration de la normalité des résidus (figure 7.16).

  • +
  • les graphiques démontrent une nette amélioration de la normalité des résidus (figure fig-ResidusCompa).

  • # 1. coefficients d’asymétrie et d’aplatissement 
    @@ -4198,7 +4198,7 @@ 

    -Relisez au besoin la section 7.3.2. +Relisez au besoin la section sec-0732.
    @@ -4227,7 +4227,7 @@

    -Relisez au besoin la section 7.3.1. +Relisez au besoin la section sec-0731.
    @@ -4272,7 +4272,7 @@

    -Relisez au besoin le début de la section 7.3.2. +Relisez au besoin le début de la section sec-0732.
    @@ -4301,7 +4301,7 @@

    -Relisez au besoin la section 7.4.2. +Relisez au besoin la section sec-0742.
    @@ -4338,7 +4338,7 @@

    -Relisez au besoin la section 7.4.3. +Relisez au besoin la section sec-0743.
    @@ -4383,7 +4383,7 @@

    -Relisez au besoin la [section Section 7.4.3). +Relisez au besoin la [section sec-0743).
    @@ -4420,7 +4420,7 @@

    -Relisez au besoin la section 7.4.4. +Relisez au besoin la section sec-0744.
    @@ -4449,7 +4449,7 @@

    -Relisez le deuxième encadré à la section 7.6. +Relisez le deuxième encadré à la section sec-076.
    @@ -4514,7 +4514,7 @@

    -

    8.1.4 Résidus et déviance

    Dans la section sur la régression linéaire simple, nous avons présenté la notion de résidu, soit l’écart entre la valeur observée (réelle) de Y et la valeur prédite par le modèle. Pour un modèle GLM, ces résidus traditionnels (aussi appelés résidus naturels) ne sont pas très informatifs si la variable à modéliser est binaire, multinomiale ou même de comptage. Lorsque l’on travaille avec des GLM, nous préférons utiliser trois autres formes de résidus, soit les résidus de Pearson, les résidus de déviance et les résidus simulés.

    @@ -483,7 +483,7 @@

    avec \(\mu_i\) et \(p_i\) les prédictions du modèle pour l’observation i.

    -

    Les résidus de déviance sont basés sur le concept de likelihood présenté dans la section 2.5.4.2. Pour rappel, le likelihood, ou la vraisemblance d’un modèle, correspond à la probabilité conjointe d’avoir observé les données Y selon le modèle étudié. Pour des raisons mathématiques (voir section 2.5.4.2), le log likelihood est plus souvent calculé. Plus cette valeur est forte, moins le modèle se trompe. Cette interprétation est donc inverse à celle des résidus classiques, c’est pourquoi le log likelihood est généralement multiplié par −2 pour retrouver une interprétation intuitive. Ainsi, pour chaque observation i, nous pouvons calculer :

    +

    Les résidus de déviance sont basés sur le concept de likelihood présenté dans la section sec-02adjdistrib. Pour rappel, le likelihood, ou la vraisemblance d’un modèle, correspond à la probabilité conjointe d’avoir observé les données Y selon le modèle étudié. Pour des raisons mathématiques (voir section sec-02adjdistrib), le log likelihood est plus souvent calculé. Plus cette valeur est forte, moins le modèle se trompe. Cette interprétation est donc inverse à celle des résidus classiques, c’est pourquoi le log likelihood est généralement multiplié par −2 pour retrouver une interprétation intuitive. Ainsi, pour chaque observation i, nous pouvons calculer :

    \[ d_i = \mbox{-2} \times log(P(y_i|M_e)) \tag{8.8}\]

    @@ -493,13 +493,13 @@

    Il s’agit donc d’une quantité représentant à quel point le modèle est erroné vis-à-vis des données. Notez qu’en tant que telle, la déviance n’a pas d’interprétation directe en revanche, elle est utilisée pour calculer des mesures d’ajustement des modèles GLM.

    -

    Les résidus simulés sont une avancée récente dans le monde des GLM, ils fournissent une définition et une interprétation harmonisée des résidus pour l’ensemble des modèles GLM. Dans la section sur les LM (section 7.2.2), nous avons vu comment interpréter les graphiques des résidus pour détecter d’éventuels problèmes dans le modèle. Cependant, cette technique est bien plus compliquée à mettre en œuvre pour les GLM puisque la forme attendue des résidus varie en fonction de la distribution choisie pour modéliser Y. La façon la plus efficace de procéder est d’interpréter les graphiques des résidus simulés qui ont la particularité d’être identiquement distribués, quel que soit le modèle GLM construit. Ces résidus simulés sont compris entre 0 et 1 et sont calculés de la manière suivante :

    +

    Les résidus simulés sont une avancée récente dans le monde des GLM, ils fournissent une définition et une interprétation harmonisée des résidus pour l’ensemble des modèles GLM. Dans la section sur les LM (section sec-0722), nous avons vu comment interpréter les graphiques des résidus pour détecter d’éventuels problèmes dans le modèle. Cependant, cette technique est bien plus compliquée à mettre en œuvre pour les GLM puisque la forme attendue des résidus varie en fonction de la distribution choisie pour modéliser Y. La façon la plus efficace de procéder est d’interpréter les graphiques des résidus simulés qui ont la particularité d’être identiquement distribués, quel que soit le modèle GLM construit. Ces résidus simulés sont compris entre 0 et 1 et sont calculés de la manière suivante :

      -
    • À partir du modèle GLM construit, simuler S fois (généralement 1 000) une variable Y’ avec autant d’observation (n) que Y. Cette variable simulée est une combinaison de la prédiction du modèle (coefficient et variables indépendantes) et de sa dispersion (variance). Ces simulations représentent des variations vraisemblables de la variable Y si le modèle est correctement spécifié. En d’autres termes, si le modèle représente bien le phénomène à l’origine de la variable Y, alors les simulations Y’ issues du modèle devraient être proches de la variable Y originale. Pour une explication plus détaillée de ce que signifie simuler des données à partir d’un modèle, référez-vous au bloc attention intitulé Distinction entre simulation et prédiction dans la section 8.1.5.2.

    • +
    • À partir du modèle GLM construit, simuler S fois (généralement 1 000) une variable Y’ avec autant d’observation (n) que Y. Cette variable simulée est une combinaison de la prédiction du modèle (coefficient et variables indépendantes) et de sa dispersion (variance). Ces simulations représentent des variations vraisemblables de la variable Y si le modèle est correctement spécifié. En d’autres termes, si le modèle représente bien le phénomène à l’origine de la variable Y, alors les simulations Y’ issues du modèle devraient être proches de la variable Y originale. Pour une explication plus détaillée de ce que signifie simuler des données à partir d’un modèle, référez-vous au bloc attention intitulé Distinction entre simulation et prédiction dans la section sec-08152.

    • Pour chaque observation, nous obtenons ainsi S valeurs formant une distribution \(Ds_i\), soit les valeurs simulées par le modèle pour cette observation.

    • Pour chacune de ces distributions, nous calculons la probabilité cumulative d’observer la vraie valeur \(Y_i\) d’après la distribution \(Ds_i\). Cette valeur est comprise entre 0 (toutes les valeurs simulées sont plus grandes que \(Y_i\)) et 1 (toutes les valeurs simulées sont inférieures à \(Y_i\)).

    -

    Si le modèle est correctement spécifié, le résultat attendu est que la distribution de ces résidus est uniforme. En effet, il y a autant de chances que les simulations produisent des résultats supérieurs ou inférieurs à \(Y_i\) si le modèle représente bien le phénomène (Dunn et Smyth 1996; Gelman et Hill 2006). Si la distribution des résidus ne suit pas une loi uniforme, cela signifie que le modèle échoue à reproduire le phénomène à l’origine de Y, ce qui doit nous alerter sur sa pertinence.

    +

    Si le modèle est correctement spécifié, le résultat attendu est que la distribution de ces résidus est uniforme. En effet, il y a autant de chances que les simulations produisent des résultats supérieurs ou inférieurs à \(Y_i\) si le modèle représente bien le phénomène (Dunn et Smyth 1996; Gelman et Hill 2006). Si la distribution des résidus ne suit pas une loi uniforme, cela signifie que le modèle échoue à reproduire le phénomène à l’origine de Y, ce qui doit nous alerter sur sa pertinence.

    8.1.5 Vérification l’ajustement

    Il existe trois façons de vérifier l’ajustement d’un modèle GLM :

    @@ -518,7 +518,7 @@

    \[ \mbox{déviance expliquée} = \frac{D(M_n) - D(M_e)}{D(M_n)} = 1- \frac{D(M_e)}{D(M_n)} \tag{8.10}\]

    -

    Il s’agit donc d’un simple calcul de pourcentage entre la déviance maximale (\(D(M_n)\)) et la déviance expliquée par le modèle étudié (\(D(M_n )-D(M_e)\)). Cet indicateur est compris entre 0 et 1 : plus il est petit, plus la capacité de prédiction du modèle est faible. Attention, cet indicateur ne tient pas compte de la complexité du modèle. Ajouter une variable indépendante supplémentaire ne fait qu’augmenter la déviance expliquée, ce qui ne signifie pas que la complexification du modèle soit justifiée (voir l’encadré sur le principe de parcimonie, section 7.3.2).

    +

    Il s’agit donc d’un simple calcul de pourcentage entre la déviance maximale (\(D(M_n)\)) et la déviance expliquée par le modèle étudié (\(D(M_n )-D(M_e)\)). Cet indicateur est compris entre 0 et 1 : plus il est petit, plus la capacité de prédiction du modèle est faible. Attention, cet indicateur ne tient pas compte de la complexité du modèle. Ajouter une variable indépendante supplémentaire ne fait qu’augmenter la déviance expliquée, ce qui ne signifie pas que la complexification du modèle soit justifiée (voir l’encadré sur le principe de parcimonie, section sec-0732).

    8.1.5.1.2 Pseudo-R2
    @@ -570,7 +570,7 @@

    -

    En dehors du pseudo-R2 de McFadden ajusté, aucune de ces mesures ne tient compte de la complexité du modèle. Il est cependant important de les reporter, car des valeurs très faibles indiquent vraisemblablement un modèle avec une moindre capacité informative. À l’inverse, des valeurs trop fortes pourraient indiquer un problème de surajustement (voir encadré sur le principe de parcimonie, section 7.3.2).

    +

    En dehors du pseudo-R2 de McFadden ajusté, aucune de ces mesures ne tient compte de la complexité du modèle. Il est cependant important de les reporter, car des valeurs très faibles indiquent vraisemblablement un modèle avec une moindre capacité informative. À l’inverse, des valeurs trop fortes pourraient indiquer un problème de surajustement (voir encadré sur le principe de parcimonie, section sec-0732).

    8.1.5.1.3 Critère d’information d’Akaike (AIC)

    Probablement l’indicateur le plus répandu, sa formule est relativement simple, car il s’agit seulement d’un ajustement de la déviance :

    @@ -578,7 +578,7 @@

    avec K le nombre de paramètres à estimer dans le modèle (coefficients, paramètres de distribution, etc.).

    -

    L’AIC n’a pas d’interprétation directe, mais permet de comparer deux modèles imbriqués (section 7.3.2). Plus l’AIC est petit, mieux le modèle est ajusté. L’idée derrière cet indicateur est relativement simple. Si la déviance D est grande, alors le modèle est mal ajusté. Ajouter des paramètres (des coefficients pour de nouvelles variables X, par exemple) ne peut que réduire D, mais cette réduction n’est pas forcément suffisamment grande pour justifier la complexification du modèle. L’AIC pondère donc D en lui ajoutant 2 fois le nombre de paramètres du modèle. Un modèle plus simple (avec moins de paramètres) parvenant à une même déviance est préférable à un modèle complexe (principe de parcimonie ou du rasoir d’Ockham), ce que permet de « quantifier » l’AIC. Attention, l’AIC ne peut pas être utilisé pour comparer des modèles non imbriqués. Notez que d’autres indicateurs similaires comme le WAIC, le BIC et le DIC sont utilisés dans un contexte d’inférence bayésienne. Retenez simplement que ces indicateurs sont conceptuellement proches du AIC et s’interprètent (à peu de choses près) de la même façon.

    +

    L’AIC n’a pas d’interprétation directe, mais permet de comparer deux modèles imbriqués (section sec-0732). Plus l’AIC est petit, mieux le modèle est ajusté. L’idée derrière cet indicateur est relativement simple. Si la déviance D est grande, alors le modèle est mal ajusté. Ajouter des paramètres (des coefficients pour de nouvelles variables X, par exemple) ne peut que réduire D, mais cette réduction n’est pas forcément suffisamment grande pour justifier la complexification du modèle. L’AIC pondère donc D en lui ajoutant 2 fois le nombre de paramètres du modèle. Un modèle plus simple (avec moins de paramètres) parvenant à une même déviance est préférable à un modèle complexe (principe de parcimonie ou du rasoir d’Ockham), ce que permet de « quantifier » l’AIC. Attention, l’AIC ne peut pas être utilisé pour comparer des modèles non imbriqués. Notez que d’autres indicateurs similaires comme le WAIC, le BIC et le DIC sont utilisés dans un contexte d’inférence bayésienne. Retenez simplement que ces indicateurs sont conceptuellement proches du AIC et s’interprètent (à peu de choses près) de la même façon.

    8.1.5.2 Comparaison des distributions originales et prédites

    Une façon rapide de vérifier si un modèle est mal ajusté est de comparer la forme de la distribution originale et celle capturée par le modèle. L’idée est la suivante : si le modèle est bien ajusté aux données, il est possible de se servir de celui-ci pour générer de nouvelles données dont la distribution ressemble à celle des données originales. Si une différence importante est observable, alors les résultats du modèle ne sont pas fiables, car le modèle échoue à reproduire le phénomène étudié. Cette lecture graphique ne permet pas de s’assurer que le modèle est valide ou bien ajusté, mais simplement d’écarter rapidement les mauvais candidats. Notez que cette méthode ne s’applique pas lorsque la variable modélisée est binaire, multinomiale ou ordinale. Le graphique à réaliser comprend donc la distribution de la variable dépendante Y (représentée avec un histogramme ou un graphique de densité) et plusieurs distributions simulées à partir du modèle. Cette approche est plus répandue dans la statistique bayésienne, mais elle reste pertinente dans l’approche fréquentiste. Il est rare de reporter ces figures, mais elles doivent faire partie de votre diagnostic.

    @@ -648,8 +648,8 @@

    -

    En colonne du tableau 8.2, nous avons les catégories observées et en ligne, les catégories prédites. La diagonale représente les prédictions correctes. Dans le cas présent, le modèle a bien catégorisé 35 (15 + 20) observations sur 43, soit une précision totale de 81,4 %; huit sont mal classifiées (18,6 %); cinq avec la modalité A ont été catégorisées comme des B, soit 20 % des A, et seules trois B ont été catégorisées comme des A (13 %).

    -

    La matrice ci-dessus (tableau 8.2) ne comporte que deux catégories possibles puisque la variable Y modélisée est binaire. Il est facile d’étendre le concept de matrice de confusion au cas des variables avec plus de deux modalités (multinomiale). Le tableau 8.3 est un exemple de matrice de confusion multinomiale.

    +

    En colonne du tableau tbl-confusmat1, nous avons les catégories observées et en ligne, les catégories prédites. La diagonale représente les prédictions correctes. Dans le cas présent, le modèle a bien catégorisé 35 (15 + 20) observations sur 43, soit une précision totale de 81,4 %; huit sont mal classifiées (18,6 %); cinq avec la modalité A ont été catégorisées comme des B, soit 20 % des A, et seules trois B ont été catégorisées comme des A (13 %).

    +

    La matrice ci-dessus (tableau tbl-confusmat1) ne comporte que deux catégories possibles puisque la variable Y modélisée est binaire. Il est facile d’étendre le concept de matrice de confusion au cas des variables avec plus de deux modalités (multinomiale). Le tableau tbl-confusmat2 est un exemple de matrice de confusion multinomiale.

    @@ -727,16 +727,16 @@

    Il est possible de calculer les moyennes pondérées des différents indicateurs (macro-indicateurs) afin de disposer d’une valeur d’ensemble pour le modèle. La pondération est faite en fonction du nombre de cas observé de chaque catégorie; l’idée étant qu’il est moins grave d’avoir des indicateurs plus faibles pour des catégories moins fréquentes. Cependant, il est tout à fait possible que cette pondération ne soit pas souhaitable. C’est par exemple le cas dans de nombreuses études en santé portant sur des maladies rares où l’attention est concentrée sur ces catégories peu fréquentes.

    -

    Le coefficient de Kappa (variant de 0 à 1) peut aussi être utilisé pour quantifier la fidélité générale de la prédiction du modèle. Il est calculé avec l’équation 8.15 :

    +

    Le coefficient de Kappa (variant de 0 à 1) peut aussi être utilisé pour quantifier la fidélité générale de la prédiction du modèle. Il est calculé avec l’équation eq-kappEq :

    \[ k = \frac{Pr(a)-Pr(e)}{1-Pr(e)} \tag{8.15}\]

    -

    avec \(Pr(a)\) la proportion d’accords entre les catégories observées et les catégories prédites, et \(Pr(e)\) la probabilité d’un accord aléatoire entre les catégories observées et les catégories prédites (équation 8.16).

    +

    avec \(Pr(a)\) la proportion d’accords entre les catégories observées et les catégories prédites, et \(Pr(e)\) la probabilité d’un accord aléatoire entre les catégories observées et les catégories prédites (équation eq-kappEq2).

    \[ Pr(e) = \sum^{J}_{j=1} \frac{Cnt_{prédit}(j)}{n\times2} \times \frac{Cnt_{réel}(j)}{n\times2} \tag{8.16}\]

    avec n le nombre d’observations, \(Cnt_{prédit}(j)\) le nombre de fois où le modèle prédit la catégorie j et \(Cnt_{réel}(j)\) le nombre de fois où la catégorie j a été observée.

    -

    Pour l’interprétation du coefficient de Kappa, référez-vous au tableau 8.4.

    +

    Pour l’interprétation du coefficient de Kappa, référez-vous au tableau tbl-Kappvals.

    @@ -776,8 +776,8 @@

    -

    Enfin, un test statistique basé sur la distribution binomiale peut être utilisé pour vérifier que le modèle atteint un niveau de précision supérieur au seuil de non-information. Ce seuil correspond à la proportion de la modalité la plus présente dans le jeu de données. Dans la matrice de confusion utilisée dans le tableau 8.4, ce seuil est de 30,5 % (catégorie D), ce qui signifie qu’un modèle prédisant tout le temps la catégorie D aurait une précision de 30,5 % pour cette catégorie. Il est donc nécessaire que notre modèle fasse mieux que ce seuil.

    -

    Dans le cas de la matrice de confusion du tableau 8.3, nous obtenons donc les valeurs affichées dans le tableau 8.5.

    +

    Enfin, un test statistique basé sur la distribution binomiale peut être utilisé pour vérifier que le modèle atteint un niveau de précision supérieur au seuil de non-information. Ce seuil correspond à la proportion de la modalité la plus présente dans le jeu de données. Dans la matrice de confusion utilisée dans le tableau tbl-Kappvals, ce seuil est de 30,5 % (catégorie D), ce qui signifie qu’un modèle prédisant tout le temps la catégorie D aurait une précision de 30,5 % pour cette catégorie. Il est donc nécessaire que notre modèle fasse mieux que ce seuil.

    +

    Dans le cas de la matrice de confusion du tableau tbl-confusmat2, nous obtenons donc les valeurs affichées dans le tableau tbl-confusIndic.

    @@ -837,7 +837,7 @@

    -

    À la lecture du tableau 8.5, nous remarquons que :

    +

    À la lecture du tableau tbl-confusIndic, nous remarquons que :

    • La catégorie D est la moins bien prédite des quatre catégories (faible précision et faible rappel).

    • La catégorie C a une forte précision, mais un faible rappel, ce qui signifie que de nombreuses observations étant originalement des A, B ou D ont été prédites comme des C. Ce constat est également vrai pour la catégorie B.

    • @@ -845,12 +845,12 @@

      La probabilité que la précision du modèle ne dépasse pas le seuil de non-information est inférieure à 0,001, indiquant que le modèle à une précision supérieure à ce seuil.

    8.1.6 Comparaison de deux modèles GLM

    -

    Tel qu’abordé dans le chapitre sur les régressions linéaires classiques, il est courant de comparer plusieurs modèles imbriqués (section 7.3.2). Cette procédure permet de déterminer si l’ajout d’une ou de plusieurs variables contribue à significativement améliorer le modèle. Il est possible d’appliquer la même démarche aux GLM à l’aide du test de rapport de vraisemblance (likelihood ratio test). Le principe de base de ce test est de comparer le likelihood de deux modèles GLM imbriqués; la valeur de ce test se calcule avec l’équation suivante :

    +

    Tel qu’abordé dans le chapitre sur les régressions linéaires classiques, il est courant de comparer plusieurs modèles imbriqués (section sec-0732). Cette procédure permet de déterminer si l’ajout d’une ou de plusieurs variables contribue à significativement améliorer le modèle. Il est possible d’appliquer la même démarche aux GLM à l’aide du test de rapport de vraisemblance (likelihood ratio test). Le principe de base de ce test est de comparer le likelihood de deux modèles GLM imbriqués; la valeur de ce test se calcule avec l’équation suivante :

    \[ LR = 2(loglik(M_2) - loglik(M_1)) \tag{8.17}\]

    avec \(M_2\) un modèle reprenant toutes les variables du modèle \(M_1\), impliquant donc que \(loglik(M_2) >= loglik(M_1)\).

    -

    Avec ce test, nous supposons que le modèle \(M_2\), qui comporte plus de paramètres que le modèle \(M_1\), devrait être mieux ajusté aux données. Si c’est bien le cas, la différence entre les loglikelihood de deux modèles devrait être supérieure à zéro. La valeur calculée LR suit une distribution du khi-deux avec un nombre de degrés de liberté égal au nombre de paramètres supplémentaires dans le modèle \(M_2\) comparativement à \(M_1\). Avec ces deux informations, il est possible de déterminer la valeur de p associée à ce test et de déterminer si \(M_2\) est significativement mieux ajusté que \(M_1\) aux données. Notez qu’il existe aussi deux autres tests (test de Wald et test de Lagrange) ayant la même fonction. Il s’agit, dans les deux cas, d’approximation du test de rapport des vraisemblances dont la puissance statistique est inférieure au test de rapport de vraisemblance (Neyman, Pearson et Pearson 1933).

    +

    Avec ce test, nous supposons que le modèle \(M_2\), qui comporte plus de paramètres que le modèle \(M_1\), devrait être mieux ajusté aux données. Si c’est bien le cas, la différence entre les loglikelihood de deux modèles devrait être supérieure à zéro. La valeur calculée LR suit une distribution du khi-deux avec un nombre de degrés de liberté égal au nombre de paramètres supplémentaires dans le modèle \(M_2\) comparativement à \(M_1\). Avec ces deux informations, il est possible de déterminer la valeur de p associée à ce test et de déterminer si \(M_2\) est significativement mieux ajusté que \(M_1\) aux données. Notez qu’il existe aussi deux autres tests (test de Wald et test de Lagrange) ayant la même fonction. Il s’agit, dans les deux cas, d’approximation du test de rapport des vraisemblances dont la puissance statistique est inférieure au test de rapport de vraisemblance (Neyman, Pearson et Pearson 1933).

    Dans les prochaines sections, nous décrivons les modèles GLM les plus couramment utilisés. Il en existe de nombreuses variantes que nous ne pouvons pas toutes décrire ici. L’objectif est de comprendre les rouages de ces modèles afin de pouvoir, en cas de besoin, transposer ces connaissances sur des modèles plus spécifiques. Pour faciliter la lecture de ces sections, nous vous proposons une carte d’identité de chacun des modèles présentés. Elles contiennent l’ensemble des informations pertinentes à retenir pour chaque modèle.

    8.2 Modèles GLM pour des variables qualitatives

    @@ -945,11 +945,11 @@

    La conséquence directe de la sur-dispersion est la sous-estimation de la variance des coefficients de régression. En d’autres termes, la sur-dispersion conduit à sous-estimer notre incertitude quant aux coefficients obtenus et réduit les valeurs de p calculées pour ces coefficients. Les risques de trouver des résultats significatifs à cause des fluctuations d’échantillonnage augmentent.

    Pour détecter une sur-dispersion ou une sous-dispersion dans un modèle logistique binomial, il est possible d’observer les résidus de déviance du modèle. Ces derniers sont supposés suivre une distribution du khi-deux avec n−k degrés de liberté (avec n le nombre d’observations et k le nombre de coefficients dans le modèle). Par conséquent, la somme des résidus de déviance d’un modèle logistique binomiale divisée par le nombre de degrés de liberté devrait être proche de 1. Une légère déviation (jusqu’à 0,15 au-dessus ou au-dessous de 1) n’est pas alarmante; au-delà, il est nécessaire d’ajuster le modèle.

    -

    Notez que si la variable Y modélisée est exactement binaire (chaque expérience est indépendante et n’est composée que d’un seul tirage) et que le modèle utilise donc une distribution de Bernoulli, le test précédent pour détecter une éventuelle sur-dispersion n’est pas valide. Hilbe (2009) parle de sur-dispersion implicite pour le modèle de Bernoulli et recommande notamment de toujours ajuster les erreurs standards des modèles utilisant des distributions de Bernoulli, binomiale et de Poisson. L’idée ici est d’éviter d’être trop optimiste face à l’incertitude du modèle sur les coefficients et de l’ajuster en conséquence. Pour cela, il est possible d’utiliser des quasi-distributions ou des estimateurs robustes (Zeileis 2004). Notez que si le modèle ne souffre pas de sur ou sous-dispersion, ces ajustements produisent des résultats équivalents aux résultats non ajustés.

    +

    Notez que si la variable Y modélisée est exactement binaire (chaque expérience est indépendante et n’est composée que d’un seul tirage) et que le modèle utilise donc une distribution de Bernoulli, le test précédent pour détecter une éventuelle sur-dispersion n’est pas valide. Hilbe (2009) parle de sur-dispersion implicite pour le modèle de Bernoulli et recommande notamment de toujours ajuster les erreurs standards des modèles utilisant des distributions de Bernoulli, binomiale et de Poisson. L’idée ici est d’éviter d’être trop optimiste face à l’incertitude du modèle sur les coefficients et de l’ajuster en conséquence. Pour cela, il est possible d’utiliser des quasi-distributions ou des estimateurs robustes (Zeileis 2004). Notez que si le modèle ne souffre pas de sur ou sous-dispersion, ces ajustements produisent des résultats équivalents aux résultats non ajustés.

    8.2.1.3 Exemple appliqué dans R

    Présentation des données

    -

    Pour illustrer le modèle logistique binomial, nous utilisons ici un jeu de données proposé par l’Union européenne : l’enquête de déplacement sur la demande pour des systèmes de transports innovants. Pour cette enquête, un échantillon de 1 000 individus représentatifs de la population a été constitué dans chacun des 26 États membres de l’UE, soit un total de 26 000 observations. Pour chaque individu, plusieurs informations ont été collectées relatives à la catégorie socioprofessionnelle, le mode de transport le plus fréquent, le temps du trajet de son déplacement le plus fréquent et son niveau de sensibilité à la cause environnementale. Nous modélisons ici la probabilité qu’un individu déclare utiliser le plus fréquemment le vélo comme moyen de transport. Les variables explicatives sont résumées au tableau 8.7. Il existe bien évidemment un grand nombre de facteurs individuels qui influence la prise de décision sur le mode de transport. Les résultats de ce modèle ne doivent donc pas être pris avec un grand sérieux; il est uniquement construit à des fins pédagogiques, sans cadre conceptuel solide.

    +

    Pour illustrer le modèle logistique binomial, nous utilisons ici un jeu de données proposé par l’Union européenne : l’enquête de déplacement sur la demande pour des systèmes de transports innovants. Pour cette enquête, un échantillon de 1 000 individus représentatifs de la population a été constitué dans chacun des 26 États membres de l’UE, soit un total de 26 000 observations. Pour chaque individu, plusieurs informations ont été collectées relatives à la catégorie socioprofessionnelle, le mode de transport le plus fréquent, le temps du trajet de son déplacement le plus fréquent et son niveau de sensibilité à la cause environnementale. Nous modélisons ici la probabilité qu’un individu déclare utiliser le plus fréquemment le vélo comme moyen de transport. Les variables explicatives sont résumées au tableau tbl-binomdata. Il existe bien évidemment un grand nombre de facteurs individuels qui influence la prise de décision sur le mode de transport. Les résultats de ce modèle ne doivent donc pas être pris avec un grand sérieux; il est uniquement construit à des fins pédagogiques, sans cadre conceptuel solide.

    @@ -1055,7 +1055,7 @@

    -

    La seconde étape de vérification est le calcul des distances de Cook et l’identification d’éventuelles valeurs aberrantes (figure 8.4).

    +

    La seconde étape de vérification est le calcul des distances de Cook et l’identification d’éventuelles valeurs aberrantes (figure fig-cookdistGLMbinom).

    # Calcul et représentation des distances de Cook
     cookd <- data.frame(
    @@ -1075,7 +1075,7 @@ 

    -

    Le calcul de la distance de Cook révèle un ensemble d’observations se démarquant nettement des autres (délimitées dans la figure 8.4) par la ligne rouge). Nous les isolons dans un premier temps pour les analyser.

    +

    Le calcul de la distance de Cook révèle un ensemble d’observations se démarquant nettement des autres (délimitées dans la figure fig-cookdistGLMbinom) par la ligne rouge). Nous les isolons dans un premier temps pour les analyser.

    # Isoler les observations avec de très fortes valeurs de Cook
     # valeur seuil choisie : 0,002
    @@ -1156,8 +1156,8 @@ 

    -

    Après avoir retiré ces valeurs aberrantes, nous n’observons plus de nouveaux cas singuliers avec les distances de Cook (figure 8.5).

    -

    La prochaine étape de vérification des conditions d’application est l’analyse des résidus simulés. Nous commençons donc par calculer ces résidus et afficher leur histogramme (figure 8.6).

    +

    Après avoir retiré ces valeurs aberrantes, nous n’observons plus de nouveaux cas singuliers avec les distances de Cook (figure fig-cookdistGLMbinom2).

    +

    La prochaine étape de vérification des conditions d’application est l’analyse des résidus simulés. Nous commençons donc par calculer ces résidus et afficher leur histogramme (figure fig-residsimbinomHistoUnif).

    library(DHARMa)
     # Extraire les probabilités prédites par le modèle
    @@ -1184,7 +1184,7 @@ 

    -

    L’histogramme indique clairement que les résidus simulés suivent une distribution uniforme (figure 8.6). Il est possible d’aller plus loin dans le diagnostic en utilisant la fonction plot sur l’objet sim_res. La partie de droite de la figure ainsi obtenue (figure 8.7) est un diagramme de quantiles-quantiles (ou Q-Q plot). Les points du graphique sont supposés suivre une ligne droite matérialisée par la ligne rouge. Une déviation de cette ligne indique un éloignement des résidus de leur distribution attendue. Trois tests sont également réalisés par la fonction :

    +

    L’histogramme indique clairement que les résidus simulés suivent une distribution uniforme (figure fig-residsimbinomHistoUnif). Il est possible d’aller plus loin dans le diagnostic en utilisant la fonction plot sur l’objet sim_res. La partie de droite de la figure ainsi obtenue (figure fig-residsimbinom) est un diagramme de quantiles-quantiles (ou Q-Q plot). Les points du graphique sont supposés suivre une ligne droite matérialisée par la ligne rouge. Une déviation de cette ligne indique un éloignement des résidus de leur distribution attendue. Trois tests sont également réalisés par la fonction :

    • Le premier (Test de Kolmogorov-Smirnov, KS test) permet de tester si les points dévient significativement de la ligne droite. Dans notre cas, la valeur de p n’est pas significative, indiquant que les résidus ne dévient pas de la distribution uniforme.

    • Le second test permet de vérifier la présence de sur ou sous-dispersion. Dans notre cas, ce test n’est pas significatif, n’indiquant aucun problème de sur-dispersion ou de sous-dispersion.

    • @@ -1298,7 +1298,7 @@

    -

    Nous constatons à la figure 8.8 que si la valeur du seuil est 0 %, alors la prédiction a une sensibilité parfaite (le modèle prédit toujours 1, donc tous les 1 sont détectés); à l’inverse, si le seuil choisi est 100 %, alors la prédiction à une spécificité parfaite (le modèle prédit toujours 0, donc tous les 0 sont détectés). Dans notre cas, la valeur d’équilibre est d’environ 0,148, donc si le modèle prédit une probabilité au moins égale à 14,8 % qu’un individu utilise le vélo pour son déplacement le plus fréquent, nous devons l’attribuer à la catégorie cycliste. Avec ce seuil, nous pouvons convertir les probabilités prédites en classes prédites et construire notre matrice de confusion.

    +

    Nous constatons à la figure fig-equlibresensispeci que si la valeur du seuil est 0 %, alors la prédiction a une sensibilité parfaite (le modèle prédit toujours 1, donc tous les 1 sont détectés); à l’inverse, si le seuil choisi est 100 %, alors la prédiction à une spécificité parfaite (le modèle prédit toujours 0, donc tous les 0 sont détectés). Dans notre cas, la valeur d’équilibre est d’environ 0,148, donc si le modèle prédit une probabilité au moins égale à 14,8 % qu’un individu utilise le vélo pour son déplacement le plus fréquent, nous devons l’attribuer à la catégorie cycliste. Avec ce seuil, nous pouvons convertir les probabilités prédites en classes prédites et construire notre matrice de confusion.

    library(caret) # pour la matrice de confusion
     # Calcul des catégories prédites
    @@ -1336,7 +1336,7 @@ 

    -

    Les résultats proposés par le package caret sont exhaustifs; nous vous proposons ici une façon de les présenter dans deux tableaux : l’un présente la matrice de confusion (tableau 8.8) et l’autre, les indicateurs de qualité de prédiction (tableau 8.9).

    +

    Les résultats proposés par le package caret sont exhaustifs; nous vous proposons ici une façon de les présenter dans deux tableaux : l’un présente la matrice de confusion (tableau tbl-confusmatbinom) et l’autre, les indicateurs de qualité de prédiction (tableau tbl-confusmatbinom2).

    @@ -1508,8 +1508,8 @@

    -

    Dans la figure 8.9, la barre horizontale pour chaque pays représente l’intervalle de confiance de son rapport de cotes (le point); plus cette ligne est longue, plus grande est l’incertitude autour de ce paramètre. Lorsque les lignes de deux pays se chevauchent, cela signifie qu’il n’y a pas de différence significative au seuil 0,05 entre les rapports de cotes des deux pays. La ligne rouge tracée à x = 1, représente le rapport de cotes du pays de référence (ici l’Allemagne). Nous constatons ainsi que comparativement à un individu vivant en Allemagne, ceux vivant au Danemark et aux Pays-Bas ont 2,4 fois plus de chances d’utiliser le vélo pour leur déplacement le plus fréquent. Les Pays de l’Ouest (France, Luxembourg, Royaume-Uni, Irlande) et du Sud (Grèce, Italie, Espagne, Portugal) ont en revanche des rapports de cotes plus faibles. En France, les chances qu’un individu utilise le vélo pour son trajet le plus fréquent sont 3,22 (1/0,31) fois plus faibles que si l’individu vivait en Allemagne.

    -

    Pour le reste des coefficients et des rapports de cotes, nous les rapportons dans le tableau 8.10.

    +

    Dans la figure fig-paysbinom, la barre horizontale pour chaque pays représente l’intervalle de confiance de son rapport de cotes (le point); plus cette ligne est longue, plus grande est l’incertitude autour de ce paramètre. Lorsque les lignes de deux pays se chevauchent, cela signifie qu’il n’y a pas de différence significative au seuil 0,05 entre les rapports de cotes des deux pays. La ligne rouge tracée à x = 1, représente le rapport de cotes du pays de référence (ici l’Allemagne). Nous constatons ainsi que comparativement à un individu vivant en Allemagne, ceux vivant au Danemark et aux Pays-Bas ont 2,4 fois plus de chances d’utiliser le vélo pour leur déplacement le plus fréquent. Les Pays de l’Ouest (France, Luxembourg, Royaume-Uni, Irlande) et du Sud (Grèce, Italie, Espagne, Portugal) ont en revanche des rapports de cotes plus faibles. En France, les chances qu’un individu utilise le vélo pour son trajet le plus fréquent sont 3,22 (1/0,31) fois plus faibles que si l’individu vivait en Allemagne.

    +

    Pour le reste des coefficients et des rapports de cotes, nous les rapportons dans le tableau tbl-coeffbinom.

    @@ -1812,7 +1812,7 @@

    Les chances pour un individu d’utiliser le vélo pour son trajet le plus fréquent sont augmentées de 45 % s’il s’agit d’un homme plutôt qu’une femme. Pour l’âge, nous constatons un effet relativement faible puisque chaque année supplémentaire réduit les chances qu’un individu utilise le vélo comme mode de transport pour son trajet le plus fréquent de 0,9 % \(((\mbox{0,991}-\mbox{1})\times\mbox{100})\). Le fait d’être sans emploi augmente les chances d’utiliser le vélo de 29 % comparativement au fait d’avoir un emploi. Concernant le niveau d’éducation, seul le coefficient pour le groupe des personnes de la catégorie « secondaire inférieure » est significatif, indiquant que les personnes de ce groupe ont 35 % de chances en plus d’utiliser le vélo comme mode de transport pour leur déplacement le plus fréquent comparativement aux personnes de la catégorie « premier cycle ». Pour le revenu, seul le groupe avec de très faibles revenus se distingue significativement du groupe avec un revenu élevé avec un rapport de cotes de 1,27, soit 27 % de chances en plus d’utiliser le vélo.

    -

    Comparativement à ceux vivant dans une aire métropolitaine, les personnes vivant dans de petites, moyennes et grandes villes ont des chances accrues d’utiliser le vélo comme mode de déplacement pour leur trajet le plus fréquent. En revanche, nous n’observons aucune différence entre la probabilité d’utiliser le vélo dans une métropole et en zone rurale. La figure 8.10 permet de clairement visualiser cette situation. Rappelons que la référence est la situation : vivre dans une région métropolitaine, représentée par la ligne verticale rouge. Plusieurs pistes d’interprétation peuvent être envisagées pour ce résultat :

    +

    Comparativement à ceux vivant dans une aire métropolitaine, les personnes vivant dans de petites, moyennes et grandes villes ont des chances accrues d’utiliser le vélo comme mode de déplacement pour leur trajet le plus fréquent. En revanche, nous n’observons aucune différence entre la probabilité d’utiliser le vélo dans une métropole et en zone rurale. La figure fig-villebinom permet de clairement visualiser cette situation. Rappelons que la référence est la situation : vivre dans une région métropolitaine, représentée par la ligne verticale rouge. Plusieurs pistes d’interprétation peuvent être envisagées pour ce résultat :

    • En métropole et dans les zones rurales, les distances domicile-travail tendent à être plus grandes que dans les petites, moyennes et grandes villes.

    • En métropole, le système de transport en commun est davantage développé et entre donc en concurrence avec les modes de transport actifs.

    • @@ -1912,7 +1912,7 @@

    -

    La figure 8.11 permet de bien constater la diminution de la probabilité d’utiliser le vélo pour son trajet le plus fréquent avec l’âge, mais cette réduction est relativement ténue. Dans le cas utilisé en exemple, l’individu ne serait plus classé cycliste qu’après 67 ans.

    +

    La figure fig-agebinom permet de bien constater la diminution de la probabilité d’utiliser le vélo pour son trajet le plus fréquent avec l’âge, mais cette réduction est relativement ténue. Dans le cas utilisé en exemple, l’individu ne serait plus classé cycliste qu’après 67 ans.

    8.2.2 Modèle probit binomial

    Le modèle GLM probit binomial est pour ainsi dire le frère du modèle logistique binomial. La seule différence entre les deux réside dans l’utilisation d’une autre fonction de lien: probit plutôt que logistique. La fonction de lien probit (Φ) correspond à la fonction cumulative de la distribution normale et a également une forme de S. Cette version du modèle est plus souvent utilisée par les économistes. Le principal changement réside dans l’interprétation des coefficients \(\beta_0\) et \(\beta\). Du fait de la transformation probit, ces derniers indiquent le changement en termes de scores Z de la probabilité modélisée. Vous conviendrez qu’il ne s’agit pas d’une échelle très intuitive; la plupart du temps, seuls la significativité et le signe (positif ou négatif) des coefficients sont interprétés.

    @@ -1965,7 +1965,7 @@

    8.2.3 Modèle logistique des cotes proportionnelles

    -

    Le modèle logistique des cotes proportionnelles (aussi appelé modèle logistique cumulatif) est utilisé pour modéliser une variable qualitative ordinale. Un exemple classique de ce type de variable est une échelle de satisfaction (très insatisfait, insatisfait, mitigé, satisfait, très satisfait) qui peut être recodée avec des valeurs numériques (0, 1, 2, 3, 4; ces échelons étant notés j). Il n’existe pas à proprement parler de distribution pour représenter ces données, mais avec une petite astuce, il est possible de simplement utiliser la distribution binomiale. Cette astuce consiste à poser l’hypothèse de la proportionnalité des cotes, soit que le passage de la catégorie 0 à la catégorie 1 est proportionnel au passage de la catégorie 1 à la catégorie 2 et ainsi de suite. Si cette hypothèse est respectée, alors les coefficients du modèle pourront autant décrire le passage de la catégorie satisfait à celle très satisfait que le passage de insatisfait à mitigé. Si cette hypothèse n’est pas respectée, il faudrait des coefficients différents pour représenter les passages d’une catégorie à l’autre (ce qui est le cas pour le modèle multinomial présenté dans la section 8.2.4).

    +

    Le modèle logistique des cotes proportionnelles (aussi appelé modèle logistique cumulatif) est utilisé pour modéliser une variable qualitative ordinale. Un exemple classique de ce type de variable est une échelle de satisfaction (très insatisfait, insatisfait, mitigé, satisfait, très satisfait) qui peut être recodée avec des valeurs numériques (0, 1, 2, 3, 4; ces échelons étant notés j). Il n’existe pas à proprement parler de distribution pour représenter ces données, mais avec une petite astuce, il est possible de simplement utiliser la distribution binomiale. Cette astuce consiste à poser l’hypothèse de la proportionnalité des cotes, soit que le passage de la catégorie 0 à la catégorie 1 est proportionnel au passage de la catégorie 1 à la catégorie 2 et ainsi de suite. Si cette hypothèse est respectée, alors les coefficients du modèle pourront autant décrire le passage de la catégorie satisfait à celle très satisfait que le passage de insatisfait à mitigé. Si cette hypothèse n’est pas respectée, il faudrait des coefficients différents pour représenter les passages d’une catégorie à l’autre (ce qui est le cas pour le modèle multinomial présenté dans la section sec-0824).

    @@ -2018,18 +2018,18 @@

    8.2.3.1 Conditions d’application

    Les conditions d’application sont les mêmes que pour un modèle binomial, avec bien sûr l’ajout de l’hypothèse sur la proportionnalité des cotes. Selon cette hypothèse, l’effet de chaque variable indépendante est identique sur la probabilité de passer d’un échelon de la variable Y au suivant. Afin de tester cette condition, deux approches sont envisageables :

      -
    1. Utiliser l’approche de Brant (1990). Il s’agit d’un test statistique comparant les résultats du modèle ordinal avec ceux d’une série de modèles logistiques binomiaux (1 pour chaque catégorie possible de Y).

    2. +
    3. Utiliser l’approche de Brant (1990). Il s’agit d’un test statistique comparant les résultats du modèle ordinal avec ceux d’une série de modèles logistiques binomiaux (1 pour chaque catégorie possible de Y).

    4. Ajuster un modèle ordinal sans l’hypothèse de proportionnalité des cotes et effectuer un test de ratio des likelihood pour vérifier si le premier est significativement mieux ajusté.

    Si certaines variables ne respectent pas cette condition d’application, trois options sont possibles pour y remédier :

    1. Supprimer la variable du modèle (à éviter si cette variable est importante dans votre cadre théorique).

    2. Autoriser la variable à avoir un effet différent entre chaque palier (possible avec le package VGAM).

    3. -
    4. Changer de modèle et opter pour un modèle des catégories adjacentes. Il s’agit du cas particulier où toutes les variables sont autorisées à changer à chaque niveau. Ne pas confondre ce dernier modèle et le modèle multinomial (section 8.2.4), puisque le modèle des catégories adjacentes continue à prédire la probabilité de passer à une catégorie supérieure.

    5. +
    6. Changer de modèle et opter pour un modèle des catégories adjacentes. Il s’agit du cas particulier où toutes les variables sont autorisées à changer à chaque niveau. Ne pas confondre ce dernier modèle et le modèle multinomial (section sec-0824), puisque le modèle des catégories adjacentes continue à prédire la probabilité de passer à une catégorie supérieure.

    8.2.3.2 Exemple appliqué dans R

    -

    Pour cet exemple, nous analysons un jeu de données proposé par Inside Airbnb, une organisation sans but lucratif collectant des données des annonces sur le site d’Airbnb pour alimenter le débat sur l’effet de cette société sur les quartiers. Plus spécifiquement, nous utilisons le jeu de données pour Montréal compilé le 30 juin 2020. Nous modélisons ici le prix par nuit des logements, ce type d’exercice est appelé modélisation hédonique. Il est particulièrement utilisé en économie urbaine pour évaluer les déterminants du marché immobilier et prédire son évolution. Le cas d’Airbnb a déjà été étudié dans plusieurs articles (Teubner, Hawlitschek et Dann 2017; Wang et Nicolau 2017; Zhang et al. 2017). Il en ressort notamment que le niveau de confiance inspiré par l’hôte, les caractéristiques intrinsèques du logement et sa localisation sont les principales variables indépendantes de son prix. Nous construisons donc notre modèle sur cette base. Notez que nous avons décidé de retirer les logements avec des prix supérieurs à 250 $ par nuit qui constituent des cas particuliers et qui devraient faire l’objet d’une analyse à part entière. Nous avons également retiré les observations pour lesquelles certaines données sont manquantes, et obtenons un nombre final de 9 051 observations.

    -

    La distribution originale du prix des logements dans notre jeu de données est présentée à la figure 8.12.

    +

    Pour cet exemple, nous analysons un jeu de données proposé par Inside Airbnb, une organisation sans but lucratif collectant des données des annonces sur le site d’Airbnb pour alimenter le débat sur l’effet de cette société sur les quartiers. Plus spécifiquement, nous utilisons le jeu de données pour Montréal compilé le 30 juin 2020. Nous modélisons ici le prix par nuit des logements, ce type d’exercice est appelé modélisation hédonique. Il est particulièrement utilisé en économie urbaine pour évaluer les déterminants du marché immobilier et prédire son évolution. Le cas d’Airbnb a déjà été étudié dans plusieurs articles (Teubner, Hawlitschek et Dann 2017; Wang et Nicolau 2017; Zhang et al. 2017). Il en ressort notamment que le niveau de confiance inspiré par l’hôte, les caractéristiques intrinsèques du logement et sa localisation sont les principales variables indépendantes de son prix. Nous construisons donc notre modèle sur cette base. Notez que nous avons décidé de retirer les logements avec des prix supérieurs à 250 $ par nuit qui constituent des cas particuliers et qui devraient faire l’objet d’une analyse à part entière. Nous avons également retiré les observations pour lesquelles certaines données sont manquantes, et obtenons un nombre final de 9 051 observations.

    +

    La distribution originale du prix des logements dans notre jeu de données est présentée à la figure fig-histopriceairbnb.

    # Charger le jeu de données
     data_airbnb <- read.csv("data/glm/airbnb_data.csv")
    @@ -2060,7 +2060,7 @@ 

    -

    Le tableau 8.13 présente l’ensemble des variables utilisées dans le modèle.

    +

    Le tableau tbl-variablecumul présente l’ensemble des variables utilisées dans le modèle.

    @@ -2214,7 +2214,7 @@

    -

    Les distances de Cook (figure 8.13) nous permettent d’identifier quelques observations potentiellement trop influentes, mais elles semblent être différentes d’un graphique à l’autre. Nous décidons donc de ne pas retirer d’observations à ce stade et de passer à l’analyse des résidus simulés. Pour effectuer des simulations à partir de ce modèle, nous nous basons sur les probabilités d’appartenance prédites par le modèle.

    +

    Les distances de Cook (figure fig-CookdCotePropor) nous permettent d’identifier quelques observations potentiellement trop influentes, mais elles semblent être différentes d’un graphique à l’autre. Nous décidons donc de ne pas retirer d’observations à ce stade et de passer à l’analyse des résidus simulés. Pour effectuer des simulations à partir de ce modèle, nous nous basons sur les probabilités d’appartenance prédites par le modèle.

    # Extraire les probabilités prédites
     predicted <- predict(modele, type = "response")
    @@ -2244,7 +2244,7 @@ 

    
       1   2   3 
    -719 255  26 
    +713 257 30

    À partir de ces simulations de prédiction, nous pouvons réaliser un diagnostic des résidus simulés grâce au package DHARMa.

    @@ -2266,7 +2266,7 @@

    -

    La figure 8.14 nous indique que les résidus simulés suivent bien une distribution uniforme et qu’aucune valeur aberrante n’est observable. Pour affiner notre diagnostic, nous vérifions également si aucune relation ne semble exister entre chaque variable indépendante et les résidus.

    +

    La figure fig-diagressimcumul nous indique que les résidus simulés suivent bien une distribution uniforme et qu’aucune valeur aberrante n’est observable. Pour affiner notre diagnostic, nous vérifions également si aucune relation ne semble exister entre chaque variable indépendante et les résidus.

    # Préparons un plot multiple
     par(mfrow=c(3,4))
    @@ -2296,7 +2296,7 @@ 

    La fonction plotResiduals du package DHARMa produit des graphiques peu esthétiques, mais pratiques pour effectuer ce type de diagnostic.

    -

    La figure 8.15 indique qu’aucune relation marquée n’existe entre nos variables indépendantes et nos résidus simulés, sauf pour la variable nombre de lits. En effet, nous pouvons constater que les résidus ont tendance à être toujours plus faibles quand le nombre de lits augmente. Cet effet est sûrement lié au fait qu’au-delà de cinq lits, le logement en question est vraisemblablement un dortoir. Il pourrait être judicieux de retirer ces observations de l’analyse, considérant qu’elles sont peu nombreuses et constituent un type de logement particulier.

    +

    La figure fig-diagressimcumul2 indique qu’aucune relation marquée n’existe entre nos variables indépendantes et nos résidus simulés, sauf pour la variable nombre de lits. En effet, nous pouvons constater que les résidus ont tendance à être toujours plus faibles quand le nombre de lits augmente. Cet effet est sûrement lié au fait qu’au-delà de cinq lits, le logement en question est vraisemblablement un dortoir. Il pourrait être judicieux de retirer ces observations de l’analyse, considérant qu’elles sont peu nombreuses et constituent un type de logement particulier.

    data_airbnb2 <- subset(data_airbnb, data_airbnb$beds <=5)
     modele2 <- vglm(fac_price_cat ~ beds  + 
    @@ -2308,7 +2308,7 @@ 

    reverse = TRUE), data = data_airbnb2, model = T)

    -

    Nous pouvons ensuite recalculer les résidus simulés pour observer si cette tendance a été corrigée. La figure 8.16 montre qu’une bonne partie du problème a été corrigée; cependant, il semble tout de même que les résidus soient plus forts pour les logements avec un seul lit.

    +

    Nous pouvons ensuite recalculer les résidus simulés pour observer si cette tendance a été corrigée. La figure fig-diagressimcumul3 montre qu’une bonne partie du problème a été corrigée; cependant, il semble tout de même que les résidus soient plus forts pour les logements avec un seul lit.

    # Nous effectuerons 1000 simulations
     nsim <- 1000
    @@ -2518,7 +2518,7 @@ 

    -

    Pour faciliter la lecture des résultats, nous proposons le tableau 8.14.

    +

    Pour faciliter la lecture des résultats, nous proposons le tableau tbl-FinalOrdinale.

    @@ -2832,11 +2832,11 @@

    -

    Nous constatons, à la figure 8.17, que les probabilités d’appartenir aux niveaux 2 et 3 diminuent à mesure qu’augmente le pourcentage de végétation. La probabilité d’appartenir à la classe 2 et plus (en rouge) passe de plus de 95 % en cas d’absence de végétation et à environ 75 % avec 80 % de végétation dans un rayon de 500 mètres. Comme vous pouvez le constater, la probabilité \(P[Y=1]\) est la symétrie de \(P[Y>=2]\) puisque \(P[Y=1]+P[Y>=2] = 1\).

    +

    Nous constatons, à la figure fig-predpricecatveg, que les probabilités d’appartenir aux niveaux 2 et 3 diminuent à mesure qu’augmente le pourcentage de végétation. La probabilité d’appartenir à la classe 2 et plus (en rouge) passe de plus de 95 % en cas d’absence de végétation et à environ 75 % avec 80 % de végétation dans un rayon de 500 mètres. Comme vous pouvez le constater, la probabilité \(P[Y=1]\) est la symétrie de \(P[Y>=2]\) puisque \(P[Y=1]+P[Y>=2] = 1\).

    8.2.4 Modèle logistique multinomial

    La régression logistique multinomiale est utilisée pour modéliser une variable Y qualitative multinomiale, c’est-à-dire une variable dont les modalités ne peuvent pas être ordonnées. Dans le modèle précédent, nous avons vu qu’il était possible de modéliser une variable ordinale avec une distribution binomiale en formulant l’hypothèse de la proportionnalité des cotes. Avec une variable multinomiale, cette hypothèse ne tient plus, car les catégories ne sont plus ordonnées. Il faut donc formuler le modèle différemment.

    -

    L’idée derrière un modèle multinomial est de choisir une catégorie de référence, puis de modéliser les probabilités d’appartenir à chaque autre catégorie plutôt qu’à cette catégorie de référence (tableau 8.15). Si nous avons K catégories possibles dans notre variable Y, nous obtenons K-1 comparaisons. Chaque comparaison est modélisée avec sa propre équation, ce qui génère de nombreux paramètres. Par exemple, admettons que notre variable Y a cinq catégories et que nous disposons de six variables X prédictives. Nous avons ainsi 4 (5-1) équations de régression avec 7 paramètres (6 coefficients et une constante), soit 28 coefficients à analyser.

    +

    L’idée derrière un modèle multinomial est de choisir une catégorie de référence, puis de modéliser les probabilités d’appartenir à chaque autre catégorie plutôt qu’à cette catégorie de référence (tableau tbl-multinomdentity). Si nous avons K catégories possibles dans notre variable Y, nous obtenons K-1 comparaisons. Chaque comparaison est modélisée avec sa propre équation, ce qui génère de nombreux paramètres. Par exemple, admettons que notre variable Y a cinq catégories et que nous disposons de six variables X prédictives. Nous avons ainsi 4 (5-1) équations de régression avec 7 paramètres (6 coefficients et une constante), soit 28 coefficients à analyser.

    Considérant cette tendance à la multiplication des coefficients, il est fréquent de recourir à une méthode appelée Analyse de type 3 pour limiter au maximum le nombre de variables indépendantes (VI) dans le modèle. L’idée de cette méthode est de recalculer plusieurs versions du modèle dans lesquelles une variable indépendante est retirée, puis de réaliser un test de rapport de vraisemblance en comparant ce nouveau modèle (complet moins une VI) au modèle complet (toutes les VI) pour vérifier si la variable en question améliore significativement le modèle. Il est alors possible de retirer toutes les variables dont l’apport est négligeable si elles sont également peu intéressantes du point de vue théorique.

    @@ -2889,7 +2889,7 @@

    8.2.4.1 Conditions d’application

    Les conditions d’application sont les mêmes que pour un modèle binomial, avec l’ajout de l’hypothèse sur l’indépendance des alternatives non pertinentes. Cette dernière suppose que le choix entre deux catégories est indépendant des catégories proposées. Voici un exemple simple pour illustrer cette hypothèse: admettons que nous disposons d’une trentaine de personnes et que nous leur demandons la couleur de leurs yeux. Cette variable ne serait pas affectée par la présence de nouvelles couleurs en dehors de notre échantillon. En revanche, si nous leur demandons de choisir un mode de transport parmi une liste pour se rendre à leur lieu de travail, leur réponse serait nécessairement affectée par la liste des modes de transport disponibles. Les tests développés pour vérifier cette hypothèse sont connus pour leur faible fiabilité. Il est plus pertinent de décider théoriquement si cette hypothèse est valide ou non. Dans le cas contraire, il est possible d’utiliser une classe de modèle logistique plus rare: le modèle logistique imbriqué.

    Notez également que le grand nombre de paramètres dans ce type de modèle implique de disposer d’un plus grand nombre d’observations afin d’avoir suffisamment d’information dans chaque catégorie pour ajuster tous les paramètres.

    -

    Pour vérifier la présence de sur-dispersion, il est possible, dans le cas du modèle multinomial, de calculer le rapport entre le khi-deux de Pearson et le nombre de degrés de liberté du modèle. Si ce rapport est supérieur à 1 (des valeurs jusqu’à 1,15 ne sont pas problématiques), alors le modèle souffre de sur-dispersion (SAS Institute Inc 2020a). Le khi-deux de Pearson est simplement la somme des résidus de Pearson au carré dans le cas d’un modèle GLM.

    +

    Pour vérifier la présence de sur-dispersion, il est possible, dans le cas du modèle multinomial, de calculer le rapport entre le khi-deux de Pearson et le nombre de degrés de liberté du modèle. Si ce rapport est supérieur à 1 (des valeurs jusqu’à 1,15 ne sont pas problématiques), alors le modèle souffre de sur-dispersion (SAS Institute Inc 2020a). Le khi-deux de Pearson est simplement la somme des résidus de Pearson au carré dans le cas d’un modèle GLM.

    \[ \chi^2 = \sum_{i=1}^N\sum_{c=1}^K{\frac{(y_{ic} - p_{ic})^2}{p_{ic}}} \tag{8.18}\]

    @@ -2903,12 +2903,12 @@

    Le modèle logistique imbriqué

    -

    Du fait de sa proximité avec les modèles à effets mixtes que nous abordons au chapitre 9, nous ne détaillons pas ici le modèle logistique imbriqué, mais présentons plutôt son principe général. Il s’agit d’une généralisation du modèle logistique multinomial basé sur l’idée que certaines catégories pourraient être regroupées dans des « nids » (nest en anglais). Dans ces groupes, les erreurs peuvent être corrélées, indiquant ainsi que si une catégorie est manquante, une autre catégorie du même groupe sera préférée. Un paramètre \(\lambda\) contrôle spécifiquement cette corrélation et permet de mesurer sa force une fois le modèle ajusté. Il peut être pertinent de comparer un modèle imbriqué à un modèle multinomial pour déterminer lequel des deux est le mieux ajusté aux données.

    +

    Du fait de sa proximité avec les modèles à effets mixtes que nous abordons au chapitre sec-chap09, nous ne détaillons pas ici le modèle logistique imbriqué, mais présentons plutôt son principe général. Il s’agit d’une généralisation du modèle logistique multinomial basé sur l’idée que certaines catégories pourraient être regroupées dans des « nids » (nest en anglais). Dans ces groupes, les erreurs peuvent être corrélées, indiquant ainsi que si une catégorie est manquante, une autre catégorie du même groupe sera préférée. Un paramètre \(\lambda\) contrôle spécifiquement cette corrélation et permet de mesurer sa force une fois le modèle ajusté. Il peut être pertinent de comparer un modèle imbriqué à un modèle multinomial pour déterminer lequel des deux est le mieux ajusté aux données.

    8.2.4.2 Exemple appliqué dans R

    -

    Pour cet exemple, nous reproduisons une partie de l’analyse effectuée dans l’étude de McFadden (2016). Cet article s’intéresse aux écarts entre les croyances des individus et les connaissances scientifiques sur les sujets des OGM et du réchauffement climatique. Les auteurs utilisent pour cela des données issues d’une enquête auprès de 961 individus formant un échantillon représentatif de la population des États-Unis. Les données issues de cette enquête sont téléchargeables sur le site de l’éditeur, ce qui nous permet ici de reproduire l’analyse effectuée par les auteurs. Deux questions sont centrales dans l’enquête :

    +

    Pour cet exemple, nous reproduisons une partie de l’analyse effectuée dans l’étude de McFadden (2016). Cet article s’intéresse aux écarts entre les croyances des individus et les connaissances scientifiques sur les sujets des OGM et du réchauffement climatique. Les auteurs utilisent pour cela des données issues d’une enquête auprès de 961 individus formant un échantillon représentatif de la population des États-Unis. Les données issues de cette enquête sont téléchargeables sur le site de l’éditeur, ce qui nous permet ici de reproduire l’analyse effectuée par les auteurs. Deux questions sont centrales dans l’enquête :

    • Dans quelle mesure êtes-vous en accord ou en désaccord avec la phrase suivante : les plantations génétiquement modifiées sont sans danger pour la consommation ?
    • Dans quelle mesure êtes-vous en accord ou en désaccord avec la phrase suivante : la Terre se réchauffe du fait des activités humaines ?
    • @@ -2920,7 +2920,7 @@

      C. Les individus sont en accord sur les OGM, mais en désaccord sur le réchauffement climatique.
    • D. Les individus sont en désaccord avec les deux propositions.
    -

    Un modèle logistique multinomial a été utilisé pour déterminer quels facteurs contribuent à la probabilité d’appartenir à ces différentes catégories. Les variables indépendantes présentes dans le modèle sont détaillées dans le tableau 8.16. Les auteurs avaient notamment conclu que :

    +

    Un modèle logistique multinomial a été utilisé pour déterminer quels facteurs contribuent à la probabilité d’appartenir à ces différentes catégories. Les variables indépendantes présentes dans le modèle sont détaillées dans le tableau tbl-variablemultinom. Les auteurs avaient notamment conclu que :

    • Les effets des connaissances (réelles ou perçues) sur l’appartenance aux différentes catégories n’étaient pas uniformes et pouvaient varier en fonction du sujet.

    • L’orientation politique avait une influence significative sur les croyances.

    • @@ -3049,7 +3049,7 @@

      [1] 1.045889 -

      La troisième étape de la vérification des conditions d’application est l’analyse des distances de Cook. À nouveau, puisque le modèle évalue la probabilité d’appartenir à \(K-1\) catégorie, nous pouvons calculer \(K-1\) résidus par observation et par extension \(K-1\) distances de Cook. Aucune observation ne semble se détacher nettement dans la figure 8.18. Nous décidons donc pour le moment de conserver toutes les observations.

      +

      La troisième étape de la vérification des conditions d’application est l’analyse des distances de Cook. À nouveau, puisque le modèle évalue la probabilité d’appartenir à \(K-1\) catégorie, nous pouvons calculer \(K-1\) résidus par observation et par extension \(K-1\) distances de Cook. Aucune observation ne semble se détacher nettement dans la figure fig-cookmultinom. Nous décidons donc pour le moment de conserver toutes les observations.

      # Extraction des résidus
       res <- residuals(modele, type = "pearson")
      @@ -3109,7 +3109,7 @@ 

      family = multinomial(refLevel = "A"), model = T)

      Nous pouvons à présent passer à l’analyse des résidus simulés. Le problème avec ce modèle est que sa variable Y est qualitative alors que la méthode d’analyse des résidus du package DHARMa ne peut traiter que des variables quantitatives, binaires ou ordinales. Pour rappel, il est possible d’envisager la prédiction d’un modèle logistique multinomial comme la prédiction d’une série de modèles logistiques binomiaux. En représentant nos prédictions de cette façon, nous pouvons à nouveau utiliser le package DHARMa pour analyser nos résidus. Veuillez noter que cette approche n’est pas optimale et que cette section du livre peut être amenée à changer.

      -

      La figure 8.19 indique que les résidus suivent bien une distribution uniforme et qu’aucune valeur aberrante n’est observable.

      +

      La figure fig-residusmultinom indique que les résidus suivent bien une distribution uniforme et qu’aucune valeur aberrante n’est observable.

      # Extraire les prédictions du modèle
       categories <- c("B" , "C" , "D")
      @@ -3157,7 +3157,7 @@ 

      -

      La figure 8.20 permet d’affiner le diagnostic en s’assurant de l’absence de relation entre les variables indépendantes et les résidus. Il est possible de remarquer des irrégularités pour les variables de perception (premier et second panneaux). Dans les deux cas, la catégorie 1 (fort désaccord) se démarque nettement des autres catégories. Nous proposons donc de les recoder comme des variables binaires : en désaccord / pas en désaccord pour minimiser cet effet.

      +

      La figure fig-residusmultinom2 permet d’affiner le diagnostic en s’assurant de l’absence de relation entre les variables indépendantes et les résidus. Il est possible de remarquer des irrégularités pour les variables de perception (premier et second panneaux). Dans les deux cas, la catégorie 1 (fort désaccord) se démarque nettement des autres catégories. Nous proposons donc de les recoder comme des variables binaires : en désaccord / pas en désaccord pour minimiser cet effet.

      # Recomposer les données pour coller au format
       # étendu de la prediction
      @@ -3177,7 +3177,7 @@ 

      -

      Nous réajustons donc le modèle et recalculons nos résidus ajustés (masqué ici pour alléger le document). La figure 8.21 nous confirme que le problème a été corrigé.

      +

      Nous réajustons donc le modèle et recalculons nos résidus ajustés (masqué ici pour alléger le document). La figure fig-residusmultinom3 nous confirme que le problème a été corrigé.

      # Convertir les variables ordinales et variables binaires
       data_quest$PercepOGMDes <- ifelse(data_quest$PercepOGM %in% c(1,2), 1,0)
      @@ -3236,7 +3236,7 @@ 

      [1] 1.010319

      -

      Nous n’avons donc plus de séparation complète ni de sur ou sous-dispersion et les résidus simulés de la quatrième version du modèle sont toujours acceptables (figure 8.22).

      +

      Nous n’avons donc plus de séparation complète ni de sur ou sous-dispersion et les résidus simulés de la quatrième version du modèle sont toujours acceptables (figure fig-residusmultinom4).

      # Extraire les prédictions du modèle
       categories <- c("B" , "C" , "D")
      @@ -3359,7 +3359,7 @@ 

      La précision globale (macro) du modèle est de 60 % et dépasse significativement le seuil de non-information. L’indicateur de Kappa indique un accord modéré entre la prédiction et les valeurs réelles. Les catégories C et D sont les catégories avec la plus faible précision, indiquant ainsi que le modèle a tendance à manquer les prédictions pour les individus en désaccord avec le consensus scientifique sur le réchauffement climatique. Les indices de rappel sont également très faibles pour les catégories B, C et D, indiquant que très peu d’observations appartenant originalement à ces groupes ont bien été classées dans ces groupes. La capacité de prédiction du modèle est donc relativement faible.

      Interprétation des résultats

      -

      Puisque nous disposons de quatre catégories dans notre variable Y, nous obtenons au final trois tableaux de coefficients. Il est possible de visualiser l’ensemble des coefficients du modèle avec la fonction summary, nous proposons les tableaux 8.17, 8.18 et 8.19 pour présenter l’ensemble des résultats.

      +

      Puisque nous disposons de quatre catégories dans notre variable Y, nous obtenons au final trois tableaux de coefficients. Il est possible de visualiser l’ensemble des coefficients du modèle avec la fonction summary, nous proposons les tableaux tbl-coeffsmultinom1, tbl-coeffsmultinom2 et tbl-coeffsmultinom3 pour présenter l’ensemble des résultats.

      @@ -3497,7 +3497,7 @@

      -

      Le tableau 8.17 compare donc le groupe A (en accord avec la recherche scientifique sur les deux sujets) et le groupe B (en désaccord sur la question des OGM). Les résultats indiquent que le fait de se percevoir en désaccord avec le consensus scientifique sur la question des OGM multiplie par sept les chances d’appartenir au groupe B comparativement au groupe A. Cependant, pour chaque bonne réponse supplémentaire sur les questions testant les connaissances sur les OGM, les chances d’appartenir au groupe B comparativement au groupe A diminuent de 28 %. Ainsi, un individu ayant répondu correctement aux trois questions verrait ses chances réduites de 63 % d’appartenir au groupe B (\(exp(-\text{0,33}\times\text{3})\)). Il est intéressant de noter que les variables concernant le réchauffement climatique n’ont pas d’effet significatif ici. La variable CRT indique qu’à chaque bonne réponse supplémentaire au test de cognition, les chances d’appartenir au groupe B augmentent de 42 %. Un individu qui aurait répondu aux trois questions du test aurait donc 2,9 fois plus de chances d’appartenir au groupe B qu’au groupe A. Concernant le parti politique, comparativement à une personne se déclarant plus proche du parti démocrate, les personnes proches du parti républicain ou d’un autre parti ont près de deux fois plus de chances d’appartenir au groupe B. Enfin, une femme, comparativement à un homme, a 3,6 fois plus de chance d’appartenir au groupe B.

      +

      Le tableau tbl-coeffsmultinom1 compare donc le groupe A (en accord avec la recherche scientifique sur les deux sujets) et le groupe B (en désaccord sur la question des OGM). Les résultats indiquent que le fait de se percevoir en désaccord avec le consensus scientifique sur la question des OGM multiplie par sept les chances d’appartenir au groupe B comparativement au groupe A. Cependant, pour chaque bonne réponse supplémentaire sur les questions testant les connaissances sur les OGM, les chances d’appartenir au groupe B comparativement au groupe A diminuent de 28 %. Ainsi, un individu ayant répondu correctement aux trois questions verrait ses chances réduites de 63 % d’appartenir au groupe B (\(exp(-\text{0,33}\times\text{3})\)). Il est intéressant de noter que les variables concernant le réchauffement climatique n’ont pas d’effet significatif ici. La variable CRT indique qu’à chaque bonne réponse supplémentaire au test de cognition, les chances d’appartenir au groupe B augmentent de 42 %. Un individu qui aurait répondu aux trois questions du test aurait donc 2,9 fois plus de chances d’appartenir au groupe B qu’au groupe A. Concernant le parti politique, comparativement à une personne se déclarant plus proche du parti démocrate, les personnes proches du parti républicain ou d’un autre parti ont près de deux fois plus de chances d’appartenir au groupe B. Enfin, une femme, comparativement à un homme, a 3,6 fois plus de chance d’appartenir au groupe B.

      @@ -3635,7 +3635,7 @@

      -

      Le tableau 8.18 compare les groupes A et C (en désaccord sur le réchauffement climatique). Il est intéressant de noter ici que se percevoir en désaccord avec la recherche scientifique est associé avec une forte augmentation des chances d’appartenir au groupe C. Cependant, un plus grand nombre de bonnes réponses aux questions sur le réchauffement climatique est également associé avec une augmentation des chances (30 % à chaque bonne réponse supplémentaire) d’appartenir au groupe C. Le CRT n’a cette fois-ci pas d’effet. Se déclarer proche du parti républicain, comparativement au parti démocrate, multiplie les chances par 2,5 d’appartenir au groupe C. Comparativement au tableau précédent, le fait d’être une femme diminue les chances de 36 % d’appartenir au groupe C.

      +

      Le tableau tbl-coeffsmultinom2 compare les groupes A et C (en désaccord sur le réchauffement climatique). Il est intéressant de noter ici que se percevoir en désaccord avec la recherche scientifique est associé avec une forte augmentation des chances d’appartenir au groupe C. Cependant, un plus grand nombre de bonnes réponses aux questions sur le réchauffement climatique est également associé avec une augmentation des chances (30 % à chaque bonne réponse supplémentaire) d’appartenir au groupe C. Le CRT n’a cette fois-ci pas d’effet. Se déclarer proche du parti républicain, comparativement au parti démocrate, multiplie les chances par 2,5 d’appartenir au groupe C. Comparativement au tableau précédent, le fait d’être une femme diminue les chances de 36 % d’appartenir au groupe C.

      @@ -3773,8 +3773,8 @@

      -

      Le dernier tableau (8.19) compare le groupe A au groupe D (en désaccord sur les deux sujets). Les variables les plus importantes sont une fois encore le fait de se sentir en désaccord avec la recherche scientifique et le degré de connaissance sur les OGM. La variable concernant le parti politique est significative au seuil 0,05 et exprime toujours une tendance accrue pour les individus du parti républicain à appartenir au groupe D.

      -

      Nos propres conclusions corroborent celles de l’article original. Une des conclusions intéressantes est que le rejet du consensus scientifique ne semble pas nécessairement être associé à un déficit d’information ni à une plus faible capacité analytique, mais relèverait davantage d’une polarisation politique. Notez que cette littérature sur les croyances et la confiance dans la recherche est complexe, si le sujet vous intéresse, la discussion de l’article de McFadden (2016) est un bon point de départ.

      +

      Le dernier tableau (tbl-coeffsmultinom3) compare le groupe A au groupe D (en désaccord sur les deux sujets). Les variables les plus importantes sont une fois encore le fait de se sentir en désaccord avec la recherche scientifique et le degré de connaissance sur les OGM. La variable concernant le parti politique est significative au seuil 0,05 et exprime toujours une tendance accrue pour les individus du parti républicain à appartenir au groupe D.

      +

      Nos propres conclusions corroborent celles de l’article original. Une des conclusions intéressantes est que le rejet du consensus scientifique ne semble pas nécessairement être associé à un déficit d’information ni à une plus faible capacité analytique, mais relèverait davantage d’une polarisation politique. Notez que cette littérature sur les croyances et la confiance dans la recherche est complexe, si le sujet vous intéresse, la discussion de l’article de McFadden (2016) est un bon point de départ.

    8.2.5 Conclusion sur les modèles pour des variables qualitatives

    Nous avons vu dans cette section, les trois principales formes de modèles GLM pour modéliser une variable binaire (modèle binomial), une variable ordinale (modèle de cotes proportionnel) et une variable multinomiale (modèle multinomial). Pour ces trois modèles, nous avons vu que la distribution utilisée est toujours la distribution binomiale et la fonction de lien logistique. Les coefficients obtenus s’interprètent comme des rapports de cotes, une fois qu’ils sont transformés avec la fonction exponentielle.

    @@ -3849,15 +3849,15 @@

    Il existe des fonctions dans R qui calculent ces prédictions à partir des équations des modèles. Il est cependant essentiel de bien saisir ce comportement multiplicatif induit par la fonction de lien log.

    8.3.1.2 Conditions d’application

    -

    Puisque la distribution de Poisson n’a qu’un seul paramètre, le modèle GLM de Poisson est exposé au même problème potentiel de sur-dispersion que les modèles binomiaux de la section précédente. Référez-vous à la section 8.2.1.2 pour davantage de détails sur le problème posé par la sur-dispersion. Pour détecter une potentielle sur-dispersion dans un modèle de Poisson, il est possible, dans un premier temps, de calculer le ratio entre la déviance du modèle et son nombre de degrés de liberté (SAS Institute Inc 2020b). Ce ratio doit être proche de 1, s’il est plus grand, le modèle souffre de sur-dispersion.

    +

    Puisque la distribution de Poisson n’a qu’un seul paramètre, le modèle GLM de Poisson est exposé au même problème potentiel de sur-dispersion que les modèles binomiaux de la section précédente. Référez-vous à la section sec-08212 pour davantage de détails sur le problème posé par la sur-dispersion. Pour détecter une potentielle sur-dispersion dans un modèle de Poisson, il est possible, dans un premier temps, de calculer le ratio entre la déviance du modèle et son nombre de degrés de liberté (SAS Institute Inc 2020b). Ce ratio doit être proche de 1, s’il est plus grand, le modèle souffre de sur-dispersion.

    \[ \hat{\phi} = \frac{D(modele)}{N-p} \tag{8.19}\]

    avec \(N\) et \(p\) étant respectivement les nombres d’observations et de paramètres. Il est également possible de tester formellement si la sur-dispersion est significative avec un test de dispersion.

    -

    La question de l’excès de zéros a été abordée dans la section 2.4.3.7 du chapitre 2. Il s’agit d’une situation où un plus grand nombre de zéros sont présents dans les données que ce que suppose la distribution de Poisson. Dans ce cas, il convient d’utiliser la distribution de Poisson avec excès de zéros.

    +

    La question de l’excès de zéros a été abordée dans la section sec-poissonzero du chapitre sec-chap02. Il s’agit d’une situation où un plus grand nombre de zéros sont présents dans les données que ce que suppose la distribution de Poisson. Dans ce cas, il convient d’utiliser la distribution de Poisson avec excès de zéros.

    8.3.1.3 Exemple appliqué dans R

    -

    Pour cet exemple, nous reproduisons l’analyse effectuée dans l’article de Cloutier et al. (2014). L’enjeu de cette étude était de modéliser le nombre de piétons blessés autour de plus de 500 carrefours dans les quartiers centraux de Montréal. Pour cela, trois types de variables étaient utilisées : des variables décrivant l’intersection, des variables décrivant les activités humaines dans un rayon d’un kilomètre autour de l’intersection et des variables représentant le trafic routier autour de l’intersection. Un effet direct de ce type d’étude est bien évidemment l’établissement de meilleures pratiques d’aménagement réduisant les risques encourus par les piétons lors de leurs déplacements en ville. Le tableau 8.21 présente l’ensemble des variables utilisées dans l’analyse.

    +

    Pour cet exemple, nous reproduisons l’analyse effectuée dans l’article de Cloutier et al. (2014). L’enjeu de cette étude était de modéliser le nombre de piétons blessés autour de plus de 500 carrefours dans les quartiers centraux de Montréal. Pour cela, trois types de variables étaient utilisées : des variables décrivant l’intersection, des variables décrivant les activités humaines dans un rayon d’un kilomètre autour de l’intersection et des variables représentant le trafic routier autour de l’intersection. Un effet direct de ce type d’étude est bien évidemment l’établissement de meilleures pratiques d’aménagement réduisant les risques encourus par les piétons lors de leurs déplacements en ville. Le tableau tbl-variablepoiss présente l’ensemble des variables utilisées dans l’analyse.

    @@ -3953,7 +3953,7 @@

    -

    La distribution originale de la variable est décrite à la figure 8.23. Les barres grises représentent la distribution du nombre d’accidents et les barres rouges une distribution de Poisson ajustée sans variable indépendante (modèle nul). Ce premier graphique peut laisser penser qu’un modèle de Poisson n’est pas nécessairement le plus adapté considérant le grand nombre d’intersections pour lesquelles nous n’avons aucun accident. Cependant, rappelons que la variable Y n’a pas besoin de suivre une distribution de Poisson. Dans un modèle GLM, l’hypothèse que nous formulons est que la variable dépendante (Y) conditionnée par les variables indépendantes (X) suit une certaine distribution (ici Poisson).

    +

    La distribution originale de la variable est décrite à la figure fig-distripoissmod. Les barres grises représentent la distribution du nombre d’accidents et les barres rouges une distribution de Poisson ajustée sans variable indépendante (modèle nul). Ce premier graphique peut laisser penser qu’un modèle de Poisson n’est pas nécessairement le plus adapté considérant le grand nombre d’intersections pour lesquelles nous n’avons aucun accident. Cependant, rappelons que la variable Y n’a pas besoin de suivre une distribution de Poisson. Dans un modèle GLM, l’hypothèse que nous formulons est que la variable dépendante (Y) conditionnée par les variables indépendantes (X) suit une certaine distribution (ici Poisson).

    # Chargement des données
     data_accidents <- read.csv("data/glm/accident_pietons.csv", sep = ";")
    @@ -4029,7 +4029,7 @@ 

    -

    La figure 8.24 signale la présence de trois observations avec des valeurs extrêmement fortes de distance de Cook. Nous les isolons dans un premier temps pour les analyser.

    +

    La figure fig-poisscookdist signale la présence de trois observations avec des valeurs extrêmement fortes de distance de Cook. Nous les isolons dans un premier temps pour les analyser.

    cas_etrange <- subset(data_accidents, cooksd>0.1)
     print(cas_etrange)
    @@ -4075,7 +4075,7 @@

    -

    La figure 8.25 montre que nous n’avons plus d’observations fortement influentes dans le modèle après avoir retiré les trois observations identifiées précédemment. Nous devons à présent vérifier l’absence de sur-dispersion.

    +

    La figure fig-poisscookdist2 montre que nous n’avons plus d’observations fortement influentes dans le modèle après avoir retiré les trois observations identifiées précédemment. Nous devons à présent vérifier l’absence de sur-dispersion.

    # Calcul du rapport entre déviance et nombre de degrés de liberté du modèle
     deviance(modele)/(nrow(data2) - modele$rank)
    @@ -4101,7 +4101,7 @@

    Contrairement à la forme classique d’un modèle de Poisson pour laquelle la dispersion attendue est de 1, le test nous indique qu’une dispersion de 1,89 serait mieux ajustée aux données.

    -

    Il est également possible d’illuster cet écart à l’aide d’un graphique représentant les valeurs réelles, les valeurs prédites, ainsi que la variance (sous forme de barres d’erreurs) attendue par le modèle (figure 8.26). Nous constatons ainsi que les valeurs réelles (en rouge) ont largement tendance à dépasser la variance attendue par le modèle, surtout pour les valeurs les plus faibles de la distribution.

    +

    Il est également possible d’illuster cet écart à l’aide d’un graphique représentant les valeurs réelles, les valeurs prédites, ainsi que la variance (sous forme de barres d’erreurs) attendue par le modèle (figure fig-surdisppoiss). Nous constatons ainsi que les valeurs réelles (en rouge) ont largement tendance à dépasser la variance attendue par le modèle, surtout pour les valeurs les plus faibles de la distribution.

    # Extraction des prédictions du modèle
     lambdas <- predict(modele, type = "response")
    @@ -4136,7 +4136,7 @@ 

    -

    Pour tenir compte de cette particularité des données, nous modifions légèrement le modèle pour utiliser une distribution de quasi-Poisson, intégrant spécifiquement un paramètre de dispersion. Cet ajustement ne modifie pas l’estimation des coefficients du modèle, mais modifie le calcul des erreurs standards et par extension les valeurs de p pour les rendre moins sensibles au problème de sur-dispersion. Une autre approche aurait été de calculer une version robuste des erreurs standards avec le package sandwich comme nous l’avons fait dans la section 8.2.1 sur le modèle binomial. Après réajustement du modèle, le nouveau paramètre de dispersion estimé est de 1,92.

    +

    Pour tenir compte de cette particularité des données, nous modifions légèrement le modèle pour utiliser une distribution de quasi-Poisson, intégrant spécifiquement un paramètre de dispersion. Cet ajustement ne modifie pas l’estimation des coefficients du modèle, mais modifie le calcul des erreurs standards et par extension les valeurs de p pour les rendre moins sensibles au problème de sur-dispersion. Une autre approche aurait été de calculer une version robuste des erreurs standards avec le package sandwich comme nous l’avons fait dans la section sec-0821 sur le modèle binomial. Après réajustement du modèle, le nouveau paramètre de dispersion estimé est de 1,92.

    @@ -4155,7 +4155,7 @@

    family = quasipoisson(link="log"), data = data2)

    -

    Nous pouvons à présent comparer la distribution originale des données et les simulations issues du modèle. Notez que contrairement à la distribution de Poisson simple, il n’existe pas dans R de fonction pour simuler des valeurs issues d’une distribution de quasi-Poisson. Il est cependant possible d’exploiter sa proximité théorique avec la distribution binomiale négative pour définir notre propre fonction de simulation. La figure 8.27 permet de comparer la distribution originale (en gris) et l’intervalle de confiance à 95 % des simulations (en rouge). Nous remarquons que le modèle semble capturer efficacement la forme générale de la distribution originale. À titre de comparaison, nous pouvons effectuer le même exercice avec la distribution de Poisson classique (le code n’est pas montré pour éviter les répétitions). La figure 8.28 montre qu’un simple modèle de Poisson est très éloigné de la distribution originale de Y.

    +

    Nous pouvons à présent comparer la distribution originale des données et les simulations issues du modèle. Notez que contrairement à la distribution de Poisson simple, il n’existe pas dans R de fonction pour simuler des valeurs issues d’une distribution de quasi-Poisson. Il est cependant possible d’exploiter sa proximité théorique avec la distribution binomiale négative pour définir notre propre fonction de simulation. La figure fig-comppoissdistr permet de comparer la distribution originale (en gris) et l’intervalle de confiance à 95 % des simulations (en rouge). Nous remarquons que le modèle semble capturer efficacement la forme générale de la distribution originale. À titre de comparaison, nous pouvons effectuer le même exercice avec la distribution de Poisson classique (le code n’est pas montré pour éviter les répétitions). La figure fig-comppoissdistr2 montre qu’un simple modèle de Poisson est très éloigné de la distribution originale de Y.

    # Définition d'une fonction pour simuler des données quasi-Poisson
     rqpois <- function(n, lambda, disp) {
    @@ -4219,7 +4219,7 @@ 

    -

    La prochaine étape du diagnostic est l’analyse des résidus simulés. La figure 8.29 indique que les résidus du modèle suivent bien une distribution uniforme et qu’aucune valeur aberrante n’est observable.

    +

    La prochaine étape du diagnostic est l’analyse des résidus simulés. La figure fig-simrespoiss indique que les résidus du modèle suivent bien une distribution uniforme et qu’aucune valeur aberrante n’est observable.

    # Génération de 1000 simulations pour chaque prédiction
     disp <- 1.918757 # trouvable dans le summary(modele2)
    @@ -4242,7 +4242,7 @@ 

    -

    Pour affiner notre diagnostic, nous pouvons également comparer les résidus simulés et chaque variable indépendante. La figure 8.30 n’indique aucune relation problématique entre nos variables indépendantes et les résidus.

    +

    Pour affiner notre diagnostic, nous pouvons également comparer les résidus simulés et chaque variable indépendante. La figure fig-simrespoiss2 n’indique aucune relation problématique entre nos variables indépendantes et les résidus.

    par(mfrow=c(3,4))
     vars <- c("Feux_auto", "Feux_piet", "Pass_piet", "Terreplein", "Apaisement",
    @@ -4302,7 +4302,7 @@ 

    L’erreur quadratique moyenne du modèle est de 1,84, ce que signifie qu’en moyenne le modèle se trompe d’environ deux accidents pour chaque intersection. Cette valeur est relativement élevée si nous la comparons avec le nombre moyen d’accidents, soit 1,5. Cela s’explique certainement par le grand nombre de zéros dans la variable Y qui tendent à tirer les prédictions vers le bas.

    Interprétation des résultats

    -

    L’ensemble des coefficients du modèle sont accessibles via la fonction summary. Puisque la fonction de lien du modèle est la fonction log, il est pertinent de convertir les coefficients avec la fonction exp afin de pouvoir les interpréter sur l’échelle originale (nombre d'accidents) plutôt que l’échelle logarithmique (log(nombre d'accidents)). N’oubliez pas que ces effets sont multiplicatifs une fois transformés avec la fonction exp. Nous pouvons également utiliser les erreurs standards pour calculer des intervalles de confiance à 95 % des exponentiels des coefficients. Le tableau 8.22 présente l’ensemble des informations pertinentes pour l’interprétation des résultats.

    +

    L’ensemble des coefficients du modèle sont accessibles via la fonction summary. Puisque la fonction de lien du modèle est la fonction log, il est pertinent de convertir les coefficients avec la fonction exp afin de pouvoir les interpréter sur l’échelle originale (nombre d'accidents) plutôt que l’échelle logarithmique (log(nombre d'accidents)). N’oubliez pas que ces effets sont multiplicatifs une fois transformés avec la fonction exp. Nous pouvons également utiliser les erreurs standards pour calculer des intervalles de confiance à 95 % des exponentiels des coefficients. Le tableau tbl-coeffpoiss présente l’ensemble des informations pertinentes pour l’interprétation des résultats.

    # Calcul des coefficients en exponentiel et des intervalles de confiance
     tableau <- summary(modele2)$coefficients
    @@ -4553,7 +4553,7 @@ 

    -

    Nous observons, dans la figure 8.31, que quatre observations se distinguent très nettement des autres.

    +

    Nous observons, dans la figure fig-cookdistnb, que quatre observations se distinguent très nettement des autres.

    cas_etrange <- subset(data_accidents, cooksd > 0.03)
     print(cas_etrange)
    @@ -4603,7 +4603,7 @@

    -

    Après avoir retiré ces quatre observations, les distances de Cook ne révèlent plus d’observations fortement influentes dans le modèle (figure 8.32). La prochaine étape du diagnostic est donc d’analyser les résidus simulés.

    +

    Après avoir retiré ces quatre observations, les distances de Cook ne révèlent plus d’observations fortement influentes dans le modèle (figure fig-cookdistnb2). La prochaine étape du diagnostic est donc d’analyser les résidus simulés.

    # Extraction de la valeur de theta
     theta <- modelnb$family$getTheta(T)
    @@ -4631,7 +4631,7 @@ 

    -

    La figure 8.33 présentant le diagnostic des résidus simulés, montre que ces derniers suivent bien une distribution uniforme et aucun problème de dispersion ni de valeurs aberrantes. La figure 8.34 permet de comparer la distribution originale de la variable Y et les simulations issues du modèle (intervalles de confiance représentés en bleu). Nous constatons que le modèle parvient bien à reproduire la distribution originale, et ce, même pour les valeurs les plus extrèmes de la distribution.

    +

    La figure fig-diagresnb présentant le diagnostic des résidus simulés, montre que ces derniers suivent bien une distribution uniforme et aucun problème de dispersion ni de valeurs aberrantes. La figure fig-compnbdistr2 permet de comparer la distribution originale de la variable Y et les simulations issues du modèle (intervalles de confiance représentés en bleu). Nous constatons que le modèle parvient bien à reproduire la distribution originale, et ce, même pour les valeurs les plus extrèmes de la distribution.

    # Extraction des valeurs prédites par le modèle
     mus <- predict(modelnb, type = "response")
    @@ -4683,7 +4683,7 @@ 

    -

    À titre de comparaison, nous pouvons à nouveau réaliser le graphique permettant de visualiser si la variance attendue par le modèle est proche de celle effectivement observée dans les données. Nous avons constaté avec ce graphique, lorsque nous ajustions un modèle de Poisson, que la variance des données était trop grande comparativement à celle attendue par le modèle (figure 8.26).

    +

    À titre de comparaison, nous pouvons à nouveau réaliser le graphique permettant de visualiser si la variance attendue par le modèle est proche de celle effectivement observée dans les données. Nous avons constaté avec ce graphique, lorsque nous ajustions un modèle de Poisson, que la variance des données était trop grande comparativement à celle attendue par le modèle (figure fig-surdisppoiss).

    # Extraction des prédictions du modèle
     mus <- predict(modelnb, type = "response")
    @@ -4718,7 +4718,7 @@ 

    -

    Nous pouvons ainsi constater à la figure 8.35 que le modèle binomial négatif autorise une variance bien plus large que le modèle de Poisson et est ainsi mieux ajusté aux données.

    +

    Nous pouvons ainsi constater à la figure fig-surdispnb que le modèle binomial négatif autorise une variance bien plus large que le modèle de Poisson et est ainsi mieux ajusté aux données.

    Vérification de la qualité d’ajustement

    # Calcul des pseudo R2
    @@ -4749,7 +4749,7 @@ 

    Le modèle parvient à expliquer 45 % de la déviance. Il obtient un R2 ajusté de McFadden de 0,14 et un R2 de Nagelkerke de 0,42. L’erreur moyenne quadratique de la prédiction est de 1,82, ce qui est identique au modèle de Poisson ajusté précédemment.

    Interprétation des résultats

    -

    Il est possible d’accéder à l’ensemble des coefficients du modèle via la fonction summary. À nouveau, les coefficients doivent être convertis avec la fonction exponentielle (du fait de la fonction de lien log) et interprétés comme des effets multiplicatifs. Le tableau 8.24 présente les coefficients estimés par le modèle. Les résultats sont très similaires à ceux du modèle de quasi-Poisson original. Nous notons cependant que la variable représentant la présence d’un feu pour piéton n’est plus significative au seuil de 0,05.

    +

    Il est possible d’accéder à l’ensemble des coefficients du modèle via la fonction summary. À nouveau, les coefficients doivent être convertis avec la fonction exponentielle (du fait de la fonction de lien log) et interprétés comme des effets multiplicatifs. Le tableau tbl-coeffsnb présente les coefficients estimés par le modèle. Les résultats sont très similaires à ceux du modèle de quasi-Poisson original. Nous notons cependant que la variable représentant la présence d’un feu pour piéton n’est plus significative au seuil de 0,05.

    @@ -5104,7 +5104,7 @@

    -

    La figure 8.36 indique deux problèmes importants dans le modèle : la présence de valeurs aberrantes ainsi qu’un potentiel problème de dispersion. Nous commençons donc par identifier ces valeurs aberrantes.

    +

    La figure fig-diagzip indique deux problèmes importants dans le modèle : la présence de valeurs aberrantes ainsi qu’un potentiel problème de dispersion. Nous commençons donc par identifier ces valeurs aberrantes.

    # Identification des outliers
     isOutlier <- outliers(sim_res, return = "logical", lowerQuantile = 0.001,
    @@ -5114,28 +5114,31 @@ 

        Nbr_acci Feux_auto Feux_piet Pass_piet Terreplein Apaisement EmpTotBuffer
     1         19         1         1         1          1          0     7208.538
    +2         13         1         1         1          0          0    15198.958
     5         12         1         0         1          0          0     8585.350
     26         7         0         0         1          0          0     1342.625
    +34         6         0         0         1          0          0    12516.410
     44         5         0         0         0          0          0     4998.519
    -74         3         0         0         0          0          0     1103.884
    -481        0         0         0         0          0          0     4072.706
    +482        0         0         0         0          0          0     1813.911
         Densite_pop  Entropie DensiteInter Long_arterePS Artere NB_voies5 log_acci
     1      5980.923 0.8073926     42.41597       6955.00      1         1 2.995732
    +2     11696.805 0.6432018     86.50445       9581.51      1         0 2.639057
     5      8655.430 0.7607852     89.11495       6412.27      0         0 2.564949
     26     2751.012 0.0000000     73.35344       2849.66      0         0 2.079442
    +34     8950.942 0.4300549     74.91879       8443.01      1         0 1.945910
     44     8090.478 0.7879618     66.86856       4517.65      0         0 1.791759
    -74     4191.428 0.5486432     56.52712       3691.33      0         0 1.386294
    -481    9014.759 0.7510579     50.32579       3947.19      0         0 0.000000
    -    catego_acci catego_acci2 Arret VAG sum_app LogEmploi AccOrdinal    PopHa
    -1             1            1     0   1       4  8.883021          2 5.980923
    -5             1            1     0   1       4  9.057813          2 8.655430
    -26            1            1     1   1       3  7.202382          2 2.751012
    -44            1            1     1   1       4  8.516897          2 8.090478
    -74            1            0     1   1       4  7.006590          2 4.191428
    -481           0            0     1   1       4  8.312063          0 9.014759
    -

    -
    -

    Nous retirons des données les quelques observations pouvant avoir une trop forte influence sur le modèle. Après réajustement, la figure 8.37 nous informe que nous n’avons plus de valeurs aberrantes restantes ni de fort problème de dispersion. En revanche, le premier quantile des résidus tant à être plus faible que ce que nous aurions pu nous attendre d’une distribution uniforme. Ce constat laisse penser que le modèle a du mal à bien identifier les faux zéros. Ce résultat n’est pas étonnant, car aucune variable n’avait été identifiée à cette fin dans l’article original (Cloutier et al. 2014) qui utilisait un modèle binomial négatif.

    +482 8988.260 0.4486079 60.93742 3821.78 1 0 0.000000 + catego_acci catego_acci2 Arret VAG sum_app LogEmploi AccOrdinal PopHa +1 1 1 0 1 4 8.883021 2 5.980923 +2 1 1 0 1 4 9.628982 2 11.696805 +5 1 1 0 1 4 9.057813 2 8.655430 +26 1 1 1 1 3 7.202382 2 2.751012 +34 1 1 1 0 3 9.434796 2 8.950942 +44 1 1 1 1 4 8.516897 2 8.090478 +482 0 0 0 0 3 7.503240 0 8.988260

    +
    +
    +

    Nous retirons des données les quelques observations pouvant avoir une trop forte influence sur le modèle. Après réajustement, la figure fig-diagzip2 nous informe que nous n’avons plus de valeurs aberrantes restantes ni de fort problème de dispersion. En revanche, le premier quantile des résidus tant à être plus faible que ce que nous aurions pu nous attendre d’une distribution uniforme. Ce constat laisse penser que le modèle a du mal à bien identifier les faux zéros. Ce résultat n’est pas étonnant, car aucune variable n’avait été identifiée à cette fin dans l’article original (Cloutier et al. 2014) qui utilisait un modèle binomial négatif.

    data2 <- subset(data_accidents, isOutlier == FALSE)
     # Ajuster une première version du modèle
    @@ -5146,17 +5149,17 @@ 

    family = ZIP(mu.link = "log", sigma.link="logit"), data = data2)

    -
    GAMLSS-RS iteration 1: Global Deviance = 1377.478 
    -GAMLSS-RS iteration 2: Global Deviance = 1368.424 
    -GAMLSS-RS iteration 3: Global Deviance = 1365.835 
    -GAMLSS-RS iteration 4: Global Deviance = 1365.067 
    -GAMLSS-RS iteration 5: Global Deviance = 1364.803 
    -GAMLSS-RS iteration 6: Global Deviance = 1364.713 
    -GAMLSS-RS iteration 7: Global Deviance = 1364.681 
    -GAMLSS-RS iteration 8: Global Deviance = 1364.67 
    -GAMLSS-RS iteration 9: Global Deviance = 1364.666 
    -GAMLSS-RS iteration 10: Global Deviance = 1364.664 
    -GAMLSS-RS iteration 11: Global Deviance = 1364.663 
    +
    GAMLSS-RS iteration 1: Global Deviance = 1364.723 
    +GAMLSS-RS iteration 2: Global Deviance = 1356.21 
    +GAMLSS-RS iteration 3: Global Deviance = 1353.425 
    +GAMLSS-RS iteration 4: Global Deviance = 1352.45 
    +GAMLSS-RS iteration 5: Global Deviance = 1352.067 
    +GAMLSS-RS iteration 6: Global Deviance = 1351.924 
    +GAMLSS-RS iteration 7: Global Deviance = 1351.87 
    +GAMLSS-RS iteration 8: Global Deviance = 1351.851 
    +GAMLSS-RS iteration 9: Global Deviance = 1351.845 
    +GAMLSS-RS iteration 10: Global Deviance = 1351.842 
    +GAMLSS-RS iteration 11: Global Deviance = 1351.841 
    # Extraire la prédiction des valeurs lambda
     lambdas <- predict(modelza, type = "response", what = "mu")
    @@ -5186,7 +5189,7 @@ 

    -

    Nous pouvons une fois encore comparer des simulations issues du modèle et de la distribution originale de la variable Y. La figure 8.38 montre clairement que les simulations du modèle (en bleu) sont très éloignées dans la distribution originale (en gris), ce qui remet directement en question la pertinence de ce modèle.

    +

    Nous pouvons une fois encore comparer des simulations issues du modèle et de la distribution originale de la variable Y. La figure fig-compzipdistr montre clairement que les simulations du modèle (en bleu) sont très éloignées dans la distribution originale (en gris), ce qui remet directement en question la pertinence de ce modèle.

    #| # Extraire la prédiction des valeurs lambda
     lambdas <- predict(modelza, type = "response", what = "mu")
    @@ -5255,21 +5258,21 @@ 

    )

    $`deviance expliquee`
    -[1] 0.1146181
    +[1] 0.09930469
     
     $`McFadden ajuste`
    -'log Lik.' 0.3632167 (df=18)
    +'log Lik.' 0.355712 (df=18)
     
     $`Cox and Snell`
    -'log Lik.' 0.812355 (df=18)
    +'log Lik.' 0.8002923 (df=18)
     
     $Nagelkerke
    -'log Lik.' 0.8223711 (df=18)
    +'log Lik.' 0.8110203 (df=18)
    # Calcul du RMSE
     sqrt(mean((preds - data2$Nbr_acci)**2))
    -
    [1] 2.641866
    +
    [1] 2.566753

    Le modèle avec excès de zéro ajusté ne parvient à expliquer que 11 % de la déviance totale. Il obtient toutefois des valeurs de R2 assez hautes (McFadden ajusté : 0,36, Nagerlkerke : 0,82). Son RMSE est très élevé (2,6), comparativement à celui que nous avons obtenu avec le modèle binomial négatif (1,9). Considérant ces éléments, ce modèle est nettement moins informatif que le modèle binomial négatif et ne devrait pas être retenu. Nous montrons tout de même ici comment interpréter ces résultats.

    @@ -5295,19 +5298,19 @@

    # Multiplication par 1000 des coefficients de population
    @@ -5373,7 +5376,7 @@ 

    "IC 2,5 % exp(Coeff.)" , "IC 97,5 % exp(Coeff.)", "Sign.") colnames(part_logit) <- c("Coeff." , "Val.p" , "RC" , "IC 2,5 % RC" , "IC 97,5 % RC", "Sign.")

    -

    Nous rapportons les résultats de ce modèle de Poisson avec excès de zéro ajusté dans les tableaux 8.27 et 8.28.

    +

    Nous rapportons les résultats de ce modèle de Poisson avec excès de zéro ajusté dans les tableaux tbl-zapoisstab1 et tbl-zapoisstab2.

    @@ -5400,89 +5403,89 @@

    (Intercept) --2.792 +-2.555 <0.001 -0.061 -0.021 -0.178 +0.078 +0.027 +0.228 *** Feux_auto -0.585 -0.002 -1.795 -1.234 -2.611 -** +0.721 +<0.001 +2.056 +1.379 +3.064 +*** Feux_piet -0.421 +0.394 <0.001 -1.523 -1.241 -1.869 +1.483 +1.196 +1.84 *** Pass_piet -0.434 -0.027 -1.543 -1.053 -2.261 -* +0.279 +0.164 +1.321 +0.893 +1.955 + Terreplein --0.33 -0.048 -0.719 -0.518 -0.996 +-0.334 +0.045 +0.716 +0.517 +0.992 * Apaisement -0.232 +0.233 0.131 -1.261 -0.934 -1.704 +1.262 +0.933 +1.706 LogEmploi -0.181 -0.016 -1.199 -1.036 -1.388 +0.154 +0.043 +1.167 +1.005 +1.355 * Densite_pop -0.089 +0.081 <0.001 -1.093 -1.061 -1.125 +1.084 +1.052 +1.118 *** Entropie --0.299 -0.308 -0.741 -0.417 -1.317 +-0.066 +0.831 +0.936 +0.512 +1.712 DensiteInter 0.004 -0.056 +0.086 1.004 1 1.008 @@ -5490,29 +5493,29 @@

    Long_arterePS -0.009 -0.661 -1.009 +0.01 +0.635 +1.01 0.97 -1.049 +1.051 Artere -0.099 -0.374 -1.104 -0.888 -1.371 +0.013 +0.915 +1.013 +0.8 +1.283 NB_voies5 -0.43 +0.495 <0.001 -1.537 -1.26 -1.875 +1.641 +1.329 +2.026 *** @@ -5537,47 +5540,47 @@

    (Intercept) -0.995 -0.082 -2.704 -0.882 -8.292 +1.036 +0.064 +2.817 +0.945 +8.399 . Feux_auto --1.737 -0.005 -0.176 -0.052 -0.597 +-1.562 +0.01 +0.21 +0.065 +0.681 ** Feux_piet -0.341 -0.65 -1.406 -0.324 -6.111 +0.083 +0.911 +1.086 +0.253 +4.658 Densite_pop --0.12 -0.032 -0.887 -0.794 -0.99 +-0.123 +0.027 +0.884 +0.793 +0.986 * NB_voies5 --2.033 -0.179 -0.131 -0.007 -2.532 +-1.552 +0.122 +0.212 +0.03 +1.508 @@ -5589,7 +5592,7 @@

    Concernant les coefficients pour la partie Poisson du modèle, nous observons que les présences d’un feu de circulation et d’un feu pour piéton contribuent à multiplier respectivement par 2 et 1,5 le nombre attendu d’accidents à une intersection. De même, la présence d’un axe de circulation à cinq voies augmente de 57 % le nombre d’accidents. Enfin, la densité de population est aussi associée à une augmentation du nombre d’accidents : pour 1 000 habitants supplémentaires autour de l’intersection, nous augmentons le nombre d’accidents attendu de 9 %.

    8.3.5 Conclusion sur les modèles destinés à des variables de comptage

    -

    Dans cette section, nous avons vu que modéliser une variable de comptage ne doit pas toujours être réalisé avec une simple distribution de Poisson. Il est nécessaire de tenir compte de la sur ou sous-dispersion potentielle ainsi que de l’excès de zéros. Nous n’avons cependant pas couvert tous les cas. Il est en effet possible d’ajuster des modèles avec une distribution binomiale négative avec excès de zéros (avec le package gamlss), ainsi que des modèles de Hurdle. Ces derniers ont une approche différente de celle proposée par les distributions ajustées pour tenir compte de l’excès de zéro que nous détaillons dans l’encadré « pour aller plus loin » ci-dessous. Le processus de sélection du modèle peut être résumé avec la figure 8.39. Notez que même en suivant cette procédure, rien ne garantit que votre modèle final reflète bien les données que vous étudiez. L’analyse approfondie des résidus et des prédictions du modèle est la seule façon de déterminer si oui ou non le modèle est fiable.

    +

    Dans cette section, nous avons vu que modéliser une variable de comptage ne doit pas toujours être réalisé avec une simple distribution de Poisson. Il est nécessaire de tenir compte de la sur ou sous-dispersion potentielle ainsi que de l’excès de zéros. Nous n’avons cependant pas couvert tous les cas. Il est en effet possible d’ajuster des modèles avec une distribution binomiale négative avec excès de zéros (avec le package gamlss), ainsi que des modèles de Hurdle. Ces derniers ont une approche différente de celle proposée par les distributions ajustées pour tenir compte de l’excès de zéro que nous détaillons dans l’encadré « pour aller plus loin » ci-dessous. Le processus de sélection du modèle peut être résumé avec la figure fig-poisswork. Notez que même en suivant cette procédure, rien ne garantit que votre modèle final reflète bien les données que vous étudiez. L’analyse approfondie des résidus et des prédictions du modèle est la seule façon de déterminer si oui ou non le modèle est fiable.

    Figure 8.39: Processus de sélection d’un modèle pour une variable de comptage
    @@ -5618,7 +5621,7 @@

    8.4 Modèles GLM pour des variables continues

    -

    Comme nous l’avons vu dans la section 2.4, il existe un grand nombre de distributions permettant de décrire une grande diversité de variables continues. Il serait fastidieux de toutes les présenter, nous revenons donc seulement sur les plus fréquentes.

    +

    Comme nous l’avons vu dans la section sec-024, il existe un grand nombre de distributions permettant de décrire une grande diversité de variables continues. Il serait fastidieux de toutes les présenter, nous revenons donc seulement sur les plus fréquentes.

    8.4.1 Modèle GLM gaussien

    Comme nous l’avons vu en introduction, le modèle GLM gaussien est le plus simple puisqu’il correspond à la transposition de la régression linéaire classique (des moindres carrés) dans la forme des modèles généralisés.

    @@ -5682,7 +5685,7 @@

    \(\sigma\) : l’écart-type de Y après avoir contrôlé les variables X. Il peut s’interpréter comme l’incertitude restante après modélisation de la moyenne de Y. Concrètement, si vous utilisez votre équation de régression pour prédire une nouvelle valeur de Y : \(\hat{Y}\), l’intervalle de confiance à 95 % de cette prédiction est (\(\hat{Y} - 3\sigma\text{ ; }\hat{Y} + 3\sigma\)). Vous noterez donc que plus \(\sigma\) est grand, plus grande est l’incertitude de la prédiction.

    8.4.1.3 Exemple appliqué dans R

    -

    Pour cet exemple, nous reprenons le modèle LM que nous avons présenté dans la section 7.7. À titre de rappel, l’objectif est de modéliser la densité végétale dans les secteurs de recensement de Montréal. Pour cela, nous utilisons des variables relatives aux populations vulnérables physiologiquement ou socioéconomiquement, tout en contrôlant l’effet de la forme urbaine. Parmi ces dernières, l’âge médian des bâtiments est ajouté au modèle avec une polynomiale d’ordre deux, et la densité d’habitants est transformée avec la fonction logarithmique.

    +

    Pour cet exemple, nous reprenons le modèle LM que nous avons présenté dans la section sec-077. À titre de rappel, l’objectif est de modéliser la densité végétale dans les secteurs de recensement de Montréal. Pour cela, nous utilisons des variables relatives aux populations vulnérables physiologiquement ou socioéconomiquement, tout en contrôlant l’effet de la forme urbaine. Parmi ces dernières, l’âge médian des bâtiments est ajouté au modèle avec une polynomiale d’ordre deux, et la densité d’habitants est transformée avec la fonction logarithmique.

    Vérification des conditions d’application

    La première étape de la vérification des conditions d’application est bien sûr de s’assurer de l’absence de multicolinéarité excessive.

    @@ -5711,7 +5714,7 @@

    -

    La figure 8.40 indique clairement que quatre observations sont très influentes dans le modèle.

    +

    La figure fig-gausscook indique clairement que quatre observations sont très influentes dans le modèle.

    # Sélection des cas étranges
     cas_etranges <- subset(DataFinal, cooksd > 0.03)
    @@ -5738,7 +5741,7 @@ 

    -

    Une fois ces observations retirées, les nouvelles distances de Cook ne révèlent plus d’observations fortement influentes (figure 8.41). Nous pouvons passer à l’analyse des résidus simulés. La figure 8.42 démontre que la distribution des résidus est significativement différente d’une distribution uniforme, que des valeurs aberrantes sont encore présentes et qu’il existe un lien entre résidus et prédiction dans le modèle.

    +

    Une fois ces observations retirées, les nouvelles distances de Cook ne révèlent plus d’observations fortement influentes (figure fig-gausscook2). Nous pouvons passer à l’analyse des résidus simulés. La figure fig-gaussresid démontre que la distribution des résidus est significativement différente d’une distribution uniforme, que des valeurs aberrantes sont encore présentes et qu’il existe un lien entre résidus et prédiction dans le modèle.

    # Extraction des prédictions du modèle
     mus <- predict(modele, type = 'response')
    @@ -5765,7 +5768,7 @@ 

    -

    Pour mieux cerner ce problème, nous pouvons, dans un premier temps, comparer la distribution originale des données et les simulations issues du modèle. La figure 8.43 montre clairement que la distribution normale est mal ajustée aux données. Ces dernières sont légèrement asymétriques et ne peuvent pas être inférieures à zéro, ce que la distribution normale ne parvient pas à reproduire.

    +

    Pour mieux cerner ce problème, nous pouvons, dans un premier temps, comparer la distribution originale des données et les simulations issues du modèle. La figure fig-gausssim montre clairement que la distribution normale est mal ajustée aux données. Ces dernières sont légèrement asymétriques et ne peuvent pas être inférieures à zéro, ce que la distribution normale ne parvient pas à reproduire.

    df <- reshape2::melt(mat_sims[,1:30])
     ggplot() + 
    @@ -5819,7 +5822,7 @@ 

    -

    À nouveau, nous constatons à la figure 8.44 que le modèle s’attend à trouver des valeurs négatives pour la concentration de végétation, ce qui n’est pas possible dans notre cas. En revanche, il semble que la variance soit bien homogène puisque la dispersion des observations semble suivre à peu près la dispersion attendue par le modèle (en noir).

    +

    À nouveau, nous constatons à la figure fig-gausssim2 que le modèle s’attend à trouver des valeurs négatives pour la concentration de végétation, ce qui n’est pas possible dans notre cas. En revanche, il semble que la variance soit bien homogène puisque la dispersion des observations semble suivre à peu près la dispersion attendue par le modèle (en noir).

    Malgré ces différents constats indiquant clairement qu’un modèle gaussien est un choix sous-optimal pour ces données, nous poursuivons l’analyse de ce modèle.

    Vérification de la qualité d’ajustement

    @@ -5859,7 +5862,7 @@

    L’erreur quadratique moyenne et de 13,5 points de pourcentage, ce qui indique que le modèle a une assez faible capacité prédictive.

    Interprétation des résultats

    -

    L’ensemble des coefficients du modèle sont accessibles via la fonction summary; le tableau 8.30 présente les résultats pour les coefficients du modèle.

    +

    L’ensemble des coefficients du modèle sont accessibles via la fonction summary; le tableau tbl-tableaugauss présente les résultats pour les coefficients du modèle.

    @@ -5961,10 +5964,10 @@

    -

    Les résultats de la régression linéaire multiple ont déjà été interprétés dans la section 7.7.1, nous ne commenterons pas ici les résultats du modèle GLM gaussien qui sont identiques.

    +

    Les résultats de la régression linéaire multiple ont déjà été interprétés dans la section sec-0771, nous ne commenterons pas ici les résultats du modèle GLM gaussien qui sont identiques.

    8.4.2 Modèle GLM avec une distribution de Student

    -

    Pour rappel, la distribution de Student ressemble à une distribution normale (section 2.4.3.11). Elle est symétrique autour de sa moyenne et a également une forme de cloche. Cependant, elle dispose de queues lourdes, ce qui signifie qu’elle permet de représenter des phénomènes présentant davantage de valeurs extrêmes qu’une distribution normale. Pour contrôler le poids des queues, la distribution de Student intègre un troisième paramètre : \(\nu\) (nu). Lorsque \(\nu\) tends vers l’infini, la distribution de Student tend vers une distribution normale (figure 8.45).

    +

    Pour rappel, la distribution de Student ressemble à une distribution normale (section sec-024311). Elle est symétrique autour de sa moyenne et a également une forme de cloche. Cependant, elle dispose de queues lourdes, ce qui signifie qu’elle permet de représenter des phénomènes présentant davantage de valeurs extrêmes qu’une distribution normale. Pour contrôler le poids des queues, la distribution de Student intègre un troisième paramètre : \(\nu\) (nu). Lorsque \(\nu\) tends vers l’infini, la distribution de Student tend vers une distribution normale (figure fig-studentdistrib).

    @@ -5973,7 +5976,7 @@

    -

    Comme vous pouvez le constater dans la carte d’identité au tableau 8.31, le modèle GLM de Student est très proche du modèle GLM gaussien. Nous modélisons explicitement la moyenne de la distribution et son paramètre de dispersion (variance) est laissé fixe. Ce GLM est même souvent utilisé comme une version « robuste » du modèle gaussien du fait de sa capacité à intégrer explicitement l’effet des observations extrêmes. En effet, dans un modèle gaussien, les observations extrêmes (aussi appelées observations aberrantes) vont davantage influencer les paramètres du modèle que pour un modèle utilisant une distribution de Student.

    +

    Comme vous pouvez le constater dans la carte d’identité au tableau tbl-studentdentity, le modèle GLM de Student est très proche du modèle GLM gaussien. Nous modélisons explicitement la moyenne de la distribution et son paramètre de dispersion (variance) est laissé fixe. Ce GLM est même souvent utilisé comme une version « robuste » du modèle gaussien du fait de sa capacité à intégrer explicitement l’effet des observations extrêmes. En effet, dans un modèle gaussien, les observations extrêmes (aussi appelées observations aberrantes) vont davantage influencer les paramètres du modèle que pour un modèle utilisant une distribution de Student.

    @@ -6115,7 +6118,7 @@

    -

    Il semble que nous obtenons des résultats similaires à ceux du modèle gaussien: les résidus divergent significativement d’une distribution uniforme (figure 8.48). Le graphique quantile-quantile n’est parfois pas très adapté pour discerner une déviation de la distribution uniforme, nous pouvons dans ce cas afficher un histogramme des résidus pour en avoir le coeur net (figure 8.49).

    +

    Il semble que nous obtenons des résultats similaires à ceux du modèle gaussien: les résidus divergent significativement d’une distribution uniforme (figure fig-studentresid). Le graphique quantile-quantile n’est parfois pas très adapté pour discerner une déviation de la distribution uniforme, nous pouvons dans ce cas afficher un histogramme des résidus pour en avoir le coeur net (figure fig-studentresid2).

    ggplot()+
       geom_histogram(aes(x = residuals(sim_res)), bins = 50, color = "white") + 
    @@ -6154,7 +6157,7 @@ 

    Le second AIC (modèle gaussien) est plus élevé, indiquant que le modèle est moins bien ajusté aux données. Dans le cas présent, il est plus pertinent de retenir le modèle de Student même si les écarts entre ces deux modèles sont minimes. Ce résultat n’est pas surprenant puisque la variable Y (pourcentage de végétation dans les îlots de l’île de Montréal) est relativement compacte et comporte peu / pas de valeurs pouvant être qualifiées de valeurs extrêmes.

    -

    Nous ne détaillons pas ici l’interprétation des coefficients du modèle (présentés au tableau 8.32) puisqu’ils s’interprètent de la même façon qu’un modèle GLM et qu’un modèle de régression linéaire multiple.

    +

    Nous ne détaillons pas ici l’interprétation des coefficients du modèle (présentés au tableau tbl-glmstudentres) puisqu’ils s’interprètent de la même façon qu’un modèle GLM et qu’un modèle de régression linéaire multiple.

    @@ -6248,7 +6251,7 @@

    8.4.3 Modèle GLM avec distribution Gamma

    -

    Pour rappel, la distribution Gamma est strictement positive (\([0;+\infty[\)), asymétrique, et a une variance proportionnelle à sa moyenne (hétéroscedastique). Dans la section sur les distributions, nous avons vu que la distribution Gamma (section 2.4.3.15) est formulée avec deux paramètres : sa forme (\(\alpha\) ou shape) et son échelle (\(b\) ou scale). Ces deux paramètres n’ont pas une interprétation intuitive, mais il est possible avec un peu de jonglage mathématique d’arriver à une reparamétrisation intéressante. Cela est détaillé dans l’encadré ci-dessous; notez toutefois qu’il n’est pas nécessaire de maîtriser le contenu de cet encadré pour lire la suite de cette section sur les modèles GLM avec une distribution Gamma.

    +

    Pour rappel, la distribution Gamma est strictement positive (\([0;+\infty[\)), asymétrique, et a une variance proportionnelle à sa moyenne (hétéroscedastique). Dans la section sur les distributions, nous avons vu que la distribution Gamma (section sec-024315) est formulée avec deux paramètres : sa forme (\(\alpha\) ou shape) et son échelle (\(b\) ou scale). Ces deux paramètres n’ont pas une interprétation intuitive, mais il est possible avec un peu de jonglage mathématique d’arriver à une reparamétrisation intéressante. Cela est détaillé dans l’encadré ci-dessous; notez toutefois qu’il n’est pas nécessaire de maîtriser le contenu de cet encadré pour lire la suite de cette section sur les modèles GLM avec une distribution Gamma.

    @@ -6334,7 +6337,7 @@

    Dans un modèle GLM gaussien, la variance est capturée par un paramètre \(\sigma\) et est constante, produisant la condition d’homoscédasticité des résidus. Dans un modèle Gamma, la variance varie en fonction de l’espérance et du paramètre de forme selon la relation : \(Var(Y) = \frac{E(Y)^2}{\alpha}\). Les résidus sont donc par nature hétéroscédastiques dans un modèle Gamma et doivent suivre cette relation.

    8.4.3.3 Exemple appliqué dans R

    -

    Pour cet exemple, nous nous intéressons à la durée de déplacement en milieu urbain. Ce type d’analyse permet notamment de mieux comprendre les habitudes de déplacement de la population et d’orienter les politiques de transport. Plusieurs travaux concluent que les durées de déplacement en milieu urbain varient en fonction du motif du déplacement, du mode de transport utilisé, des caractéristiques socio-économiques de l’individu et des caractéristiques du trajet lui-même (Anastasopoulos et al. 2012; Frank et al. 2008). Nous modélisons ici la durée en minute d’un ensemble de déplacements effectués par des Montréalais en 2017 et enregistrés avec l’application MTL Trajet proposée par la Ville de Montréal. Ces données sont disponibles sur le site web des données ouvertes de Montréal et sont anonymisées. Nous ne disposons donc d’aucune information individuelle. Compte tenu du très grand nombre d’observations (plus de 185 000), nous avons dû effectuer quelques opérations de tri et nous avons ainsi supprimé:

    +

    Pour cet exemple, nous nous intéressons à la durée de déplacement en milieu urbain. Ce type d’analyse permet notamment de mieux comprendre les habitudes de déplacement de la population et d’orienter les politiques de transport. Plusieurs travaux concluent que les durées de déplacement en milieu urbain varient en fonction du motif du déplacement, du mode de transport utilisé, des caractéristiques socio-économiques de l’individu et des caractéristiques du trajet lui-même (Anastasopoulos et al. 2012; Frank et al. 2008). Nous modélisons ici la durée en minute d’un ensemble de déplacements effectués par des Montréalais en 2017 et enregistrés avec l’application MTL Trajet proposée par la Ville de Montréal. Ces données sont disponibles sur le site web des données ouvertes de Montréal et sont anonymisées. Nous ne disposons donc d’aucune information individuelle. Compte tenu du très grand nombre d’observations (plus de 185 000), nous avons dû effectuer quelques opérations de tri et nous avons ainsi supprimé:

    • les trajets utilisant de multiples modes de transport (sauf en combinaison avec la marche, par exemple, un trajet effectué à pied et en transport en commun a été recatégorisé comme un trajet en transport en commun uniquement). Les déplacements multimodaux se distinguent largement des déplacements unimodaux dans la littérature scientifique;

    • les trajets de nuit (seuls les trajets démarrant dans l’intervalle de 7 h à 21 h ont été conservés);

    • @@ -6342,7 +6345,7 @@

      les trajets de plus de deux heures (cas rares, considérés comme des données aberrantes);

    • les trajets dont le point de départ est à moins de 100 mètres du point d’arrivée (formant des boucles plutôt que des déplacements).

    -

    Nous arrivons ainsi à un total de 24 969 observations. Pour modéliser ces durées de déplacement, nous utilisons les variables indépendantes présentées dans le tableau 8.34.

    +

    Nous arrivons ainsi à un total de 24 969 observations. Pour modéliser ces durées de déplacement, nous utilisons les variables indépendantes présentées dans le tableau tbl-variablegamma.

    @@ -6445,7 +6448,7 @@

    -

    La figure 8.51 permet de constater l’asymétrie de la distribution des temps de trajet et qu’un modèle Gamma (ligne rouge) a plus de chance d’être adapté aux données qu’un modèle gaussien (ligne bleue).

    +

    La figure fig-gammadatadistrib permet de constater l’asymétrie de la distribution des temps de trajet et qu’un modèle Gamma (ligne rouge) a plus de chance d’être adapté aux données qu’un modèle gaussien (ligne bleue).

    Vérification des conditions d’application

    Comme pour les modèles précédents, nous commençons par la vérification de l’absence de multicolinéarité.

    @@ -6494,7 +6497,7 @@

    -

    Puisque nous disposons d’un (très) grand nombre d’observations, nous pouvons nous permettre de retirer les quelques observations fortement influentes (distance de Cook > 0,003 dans notre cas) qui apparaissent dans la figure 8.52. Nous retirons ainsi 28 observations et réajustons le modèle.

    +

    Puisque nous disposons d’un (très) grand nombre d’observations, nous pouvons nous permettre de retirer les quelques observations fortement influentes (distance de Cook > 0,003 dans notre cas) qui apparaissent dans la figure fig-cookdistgamma. Nous retirons ainsi 28 observations et réajustons le modèle.

    # Retirer les valeurs influentes
     dataset2 <- subset(dataset, cooksd<0.003)
    @@ -6504,7 +6507,7 @@ 

    data = dataset2, family = gamma2(lmu = "loglink"))

    -

    Nous constatons ainsi que dans la nouvelle version du modèle (figure 8.53), aucune valeur particulièrement influente ne semble être présente.

    +

    Nous constatons ainsi que dans la nouvelle version du modèle (figure fig-cookdistgamma2), aucune valeur particulièrement influente ne semble être présente.

    # Calcul des distances de Cook
     hats <- hatvaluesvlm(modele)[,1]
    @@ -6556,7 +6559,7 @@ 

    -

    Avant de calculer les résidus simulés, nous comparons la distribution originale des données et des simulations issues du modèle. La figure 8.54 permet de constater que le modèle semble bien capturer l’essentiel de la forme de la variable Y originale. Nous notons un léger décalage entre la pointe des deux distributions, laissant penser que les valeurs prédites par le modèle tendent à être légèrement plus grandes que les valeurs réelles. Pour mieux appréhender ce constat, nous passons à l’analyse des résidus simulés.

    +

    Avant de calculer les résidus simulés, nous comparons la distribution originale des données et des simulations issues du modèle. La figure fig-simdistribgamma permet de constater que le modèle semble bien capturer l’essentiel de la forme de la variable Y originale. Nous notons un léger décalage entre la pointe des deux distributions, laissant penser que les valeurs prédites par le modèle tendent à être légèrement plus grandes que les valeurs réelles. Pour mieux appréhender ce constat, nous passons à l’analyse des résidus simulés.

    # DHarma tests
     sim_res <- createDHARMa(simulatedResponse = mat_sims, 
    @@ -6574,7 +6577,7 @@ 

    -

    Nul besoin d’un test statistique pour constater que ces résidus (figure 8.55) ne suivent pas une distribution uniforme. Nous observons une nette surreprésentation de résidus à 1 et une nette sous-représentation de résidus à 0. Il y a donc de nombreuses observations dans notre modèle pour lesquelles les simulations sont systématiquement trop fortes et il n’y en a pas assez pour lesquelles les simulations seraient systématiquement trop faibles.

    +

    Nul besoin d’un test statistique pour constater que ces résidus (figure fig-gammaresids) ne suivent pas une distribution uniforme. Nous observons une nette surreprésentation de résidus à 1 et une nette sous-représentation de résidus à 0. Il y a donc de nombreuses observations dans notre modèle pour lesquelles les simulations sont systématiquement trop fortes et il n’y en a pas assez pour lesquelles les simulations seraient systématiquement trop faibles.

    plot(sim_res)
    @@ -6584,7 +6587,7 @@

    -

    La figure 8.56 indique que le modèle souffre à la fois d’un problème de dispersion (la relation espérance-variance n’est donc pas respectée) et est affecté par des valeurs aberrantes. Considérant que nous avons encore un très grand nombre d’observations, nous faisons le choix de retirer celles pour lesquelles la méthode des résidus simulés estime qu’elles sont des valeurs aberrantes dans au moins 1 % des simulations, soit environ 620 observations.

    +

    La figure fig-gammaresids2 indique que le modèle souffre à la fois d’un problème de dispersion (la relation espérance-variance n’est donc pas respectée) et est affecté par des valeurs aberrantes. Considérant que nous avons encore un très grand nombre d’observations, nous faisons le choix de retirer celles pour lesquelles la méthode des résidus simulés estime qu’elles sont des valeurs aberrantes dans au moins 1 % des simulations, soit environ 620 observations.

    # Sélection des valeurs aberrantes au seuil 0.01
     sim_outliers <- outliers(sim_res, 
    @@ -6595,7 +6598,7 @@ 

    sim_outliers
     FALSE  TRUE 
    -22923   623 
    +22912 634

    # Retirer ces observations des données
     dataset3 <- subset(dataset2, sim_outliers == FALSE)
    @@ -6634,8 +6637,8 @@ 

    -

    La figure 8.57 indique que les résidus simulés ne suivent toujours pas une distribution uniforme et qu’il existe une relation prononcée (panneau de droite) entre les résidus et les valeurs prédites. Cette dernière laisse penser que des variables indépendantes importantes ont été omises dans le modèle, ce qui n’est pas surprenant compte tenu du fait que nous ne disposons d’aucune donnée socioéconomique sur les individus ayant réalisé les trajets. Nos données sont également potentiellement affectées par la présence de dépendance spatiale.

    -

    Nous pouvons comparer graphiquement la variance observée dans les données et la variance attendue par le modèle. La figure 8.58 montre clairement que la variance des données tend à être plus grande qu’attendu quand les temps de trajet sont courts, mais diminue trop vite quand les temps de trajet augmentent. D’autres distributions pourraient être envisagées pour ajuster notre modèle : Lognormal, Weibull, etc.

    +

    La figure fig-gammaresids3 indique que les résidus simulés ne suivent toujours pas une distribution uniforme et qu’il existe une relation prononcée (panneau de droite) entre les résidus et les valeurs prédites. Cette dernière laisse penser que des variables indépendantes importantes ont été omises dans le modèle, ce qui n’est pas surprenant compte tenu du fait que nous ne disposons d’aucune donnée socioéconomique sur les individus ayant réalisé les trajets. Nos données sont également potentiellement affectées par la présence de dépendance spatiale.

    +

    Nous pouvons comparer graphiquement la variance observée dans les données et la variance attendue par le modèle. La figure fig-dispgamma montre clairement que la variance des données tend à être plus grande qu’attendu quand les temps de trajet sont courts, mais diminue trop vite quand les temps de trajet augmentent. D’autres distributions pourraient être envisagées pour ajuster notre modèle : Lognormal, Weibull, etc.

    # Extraction des prédictions du modèle
     mus <- predict(modele, type = "response")[,1]
    @@ -6689,22 +6692,22 @@ 

    )

    $`deviance expliquee`
    -[1] 0.05082616
    +[1] 0.05081071
     
     $`McFadden ajuste`
    -[1] 0.05037842
    +[1] 0.05036256
     
     $`Cox and Snell`
    -[1] 0.3337405
    +[1] 0.3335397
     
     $Nagelkerke
    -[1] 0.3338537
    +[1] 0.3336532
    # Calcul du RMSE
     preds <- predict(modele, type = "response")[,1]
     sqrt(mean((preds - dataset3$Duree)**2))
    -
    [1] 13.36587
    +
    [1] 13.32661

    Le modèle n’explique que 5 % de la déviance et obtient des valeurs de R2 ajusté de McFadden, de Cox et Snell et de Nagelkerke de respectivement 0,05, 0,33 et 0,33. La moyenne de l’erreur quadratique est de seulement 13,4 indiquant que le modèle se trompe en moyenne de seulement 13,4 minutes. La capacité de prédiction du modèle est donc limitée sans être catastrophique.

    @@ -6769,7 +6772,7 @@

    -

    La figure 8.59 permet de constater que les arrondissements Ville-Marie et Plateau-Mont-Royal se distinguent avec des trajets plus courts (environ 20 % plus courts en moyenne que les trajets partant d’Ahuntsic-Cartierville). À l’inverse, Lachine est de loin l’arrondissement avec les trajets les plus longs (25 % plus longs en moyenne que les trajets partant d’Ahuntsic-Cartierville).

    +

    La figure fig-arrondgamma permet de constater que les arrondissements Ville-Marie et Plateau-Mont-Royal se distinguent avec des trajets plus courts (environ 20 % plus courts en moyenne que les trajets partant d’Ahuntsic-Cartierville). À l’inverse, Lachine est de loin l’arrondissement avec les trajets les plus longs (25 % plus longs en moyenne que les trajets partant d’Ahuntsic-Cartierville).

    Nous appliquons la même méthode de visualisation à la variable Heure de départ des trajets.

    # Extraction des valeurs pour les heures de départ
    @@ -6794,8 +6797,8 @@ 

    -

    Nous pouvons ainsi observer, à la figure 8.60, que les trajets effectués à 10 h, 11 h et 12 h sont les plus longs de la journée, entre 30 et 40 % plus longs que ceux effectués à 7 h et 8 h qui constituent les trajets les plus courts.

    -

    Le reste des coefficients (ainsi que le paramètre de forme) sont affichés dans le tableau 8.35. Comparativement à un trajet effectué à pied, un trajet en transport en commun dure en moyenne 52 % plus longtemps (1,53 fois plus long), alors que les déplacements en véhicule individuel et en vélo sont respectivement 28 % et 23 % moins longs. Aucune différence n’est observable entre les déplacements effectués en semaine ou pendant la fin de semaine.

    +

    Nous pouvons ainsi observer, à la figure fig-heuresgamma, que les trajets effectués à 10 h, 11 h et 12 h sont les plus longs de la journée, entre 30 et 40 % plus longs que ceux effectués à 7 h et 8 h qui constituent les trajets les plus courts.

    +

    Le reste des coefficients (ainsi que le paramètre de forme) sont affichés dans le tableau tbl-coeffsgamma. Comparativement à un trajet effectué à pied, un trajet en transport en commun dure en moyenne 52 % plus longtemps (1,53 fois plus long), alors que les déplacements en véhicule individuel et en vélo sont respectivement 28 % et 23 % moins longs. Aucune différence n’est observable entre les déplacements effectués en semaine ou pendant la fin de semaine.

    @@ -6822,10 +6825,10 @@

    Constante -2,926 -18,661 +2,927 +18,672 0,000 -14,939 +14,954 23,313 *** @@ -6849,29 +6852,29 @@

    transport collectif -0,424 -1,529 +0,428 +1,534 0,000 -1,490 -1,568 +1,495 +1,573 *** vehicule individuel --0,319 -0,727 +-0,312 +0,732 0,000 -0,709 -0,746 +0,713 +0,751 *** velo --0,257 -0,773 +-0,254 +0,776 0,000 -0,754 -0,793 +0,757 +0,795 *** @@ -6894,38 +6897,38 @@

    loisir --0,013 -0,987 -0,451 -0,954 -1,021 +-0,015 +0,985 +0,381 +0,952 +1,019 magasinage --0,109 -0,897 +-0,118 +0,888 0,000 -0,867 -0,928 +0,858 +0,919 *** travail --0,067 -0,936 +-0,068 +0,934 0,000 -0,908 -0,965 +0,907 +0,963 *** LogDist -0,335 -1,398 +0,331 +1,392 0,000 -1,383 -1,413 +1,377 +1,406 *** @@ -6948,11 +6951,11 @@

    Meme --0,036 -0,964 -0,001 -0,944 -0,985 +-0,040 +0,961 +0,000 +0,940 +0,981 *** @@ -6975,11 +6978,11 @@

    samedi et dimanche -0,003 -1,003 -0,779 -0,982 -1,024 +0,002 +1,002 +0,844 +0,981 +1,023 @@ -6993,11 +6996,11 @@

    shape -1,147 -3,150 +1,149 +3,156 0,000 -3,096 -3,206 +3,102 +3,212 *** @@ -7005,7 +7008,7 @@

    -

    Les déplacements ayant comme motif le magasinage et le travail ont tendance à être en moyenne plus courts de 11 % et 6 % respectivement, comparativement aux déplacements effectués pour l’éducation ou le loisir (différence non significative entre loisir et éducation). Sans surprise, la distance entre le point de départ et d’arrivée du trajet (LogDist) affecte sa durée de façon positive. Considérant qu’il est difficile d’interpréter des log de kilomètre (dû à une transformation de la variable originale), nous représentons l’effet de cette variable avec la prédiction du modèle à la figure. Nous utilisons pour cela le cas suivant: déplacement à pied à 7 h en semaine, ayant pour motif éducation, dont le point de départ se situe dans l’arrondissement Ahuntsic et donc le point d’arrivée est dans un autre arrondissement. Seule la distance du trajet varie de 1 à 40 km. À titre de comparaison, nous représentons aussi, pour les mêmes conditions, le cas d’une personne à vélo (en vert) et d’une personne utilisant le transport en commun (en bleu). Les lignes en pointillés représentent les intervalles de confiance à 95 % des prédictions (figure 8.61).

    +

    Les déplacements ayant comme motif le magasinage et le travail ont tendance à être en moyenne plus courts de 11 % et 6 % respectivement, comparativement aux déplacements effectués pour l’éducation ou le loisir (différence non significative entre loisir et éducation). Sans surprise, la distance entre le point de départ et d’arrivée du trajet (LogDist) affecte sa durée de façon positive. Considérant qu’il est difficile d’interpréter des log de kilomètre (dû à une transformation de la variable originale), nous représentons l’effet de cette variable avec la prédiction du modèle à la figure. Nous utilisons pour cela le cas suivant: déplacement à pied à 7 h en semaine, ayant pour motif éducation, dont le point de départ se situe dans l’arrondissement Ahuntsic et donc le point d’arrivée est dans un autre arrondissement. Seule la distance du trajet varie de 1 à 40 km. À titre de comparaison, nous représentons aussi, pour les mêmes conditions, le cas d’une personne à vélo (en vert) et d’une personne utilisant le transport en commun (en bleu). Les lignes en pointillés représentent les intervalles de confiance à 95 % des prédictions (figure fig-distancegamma).

    # Création d'un DataFrame fictif pour la prédiction
     dfpred <- expand.grid(
    @@ -7046,7 +7049,7 @@ 

    8.4.4 Modèle GLM avec une distribution bêta

    -

    Pour rappel, la distribution bêta est une distribution définie sur l’intervalle \([0,1]\), elle est donc particulièrement utile pour décrire des proportions, des pourcentages ou des probabilités. Dans la section 2.4.3.16 sur les distributions, nous avons présenté la paramétrisation classique de la distribution avec les paramètres \(a\) et \(b\) étant tous les deux des paramètres de forme. Ces deux paramètres n’ont pas d’interprétation pratique, mais il est possible (comme pour la distribution Gamma) de reparamétrer la distribution bêta avec un paramètre de centralité (espérance) et de dispersion.

    +

    Pour rappel, la distribution bêta est une distribution définie sur l’intervalle \([0,1]\), elle est donc particulièrement utile pour décrire des proportions, des pourcentages ou des probabilités. Dans la section sec-024316 sur les distributions, nous avons présenté la paramétrisation classique de la distribution avec les paramètres \(a\) et \(b\) étant tous les deux des paramètres de forme. Ces deux paramètres n’ont pas d’interprétation pratique, mais il est possible (comme pour la distribution Gamma) de reparamétrer la distribution bêta avec un paramètre de centralité (espérance) et de dispersion.

    Notez également que si la distribution bêta autorise la présence de 0 et de 1, le modèle GLM utilisant cette distribution doit les exclure des valeurs possibles s’il utilise la fonction de lien logistique. En effet, cette fonction à la forme suivante :

    \[ logit(x) = log(\frac{x}{1-x})\\ @@ -7056,7 +7059,7 @@

  • Si les observations à 0 ou 1 sont très peu nombreuses, il est envisageable de les retirer des données.
  • Si la variable mesurée le permet, il est possible de remplacer les 0 et les 1 par des valeurs très proches (0,0001 et 0,9999 par exemple) sans dénaturer excessivement les données initiales.
  • -
  • Plutôt que d’utiliser une valeur arbitraire, Smithson et Verkuilen (2006) recommandent de recalculer la variable \(Y \in [0;1]\) avec la formule équation 8.25;
  • +
  • Plutôt que d’utiliser une valeur arbitraire, Smithson et Verkuilen (2006) recommandent de recalculer la variable \(Y \in [0;1]\) avec la formule équation eq-correctbeta;
  • Employer un modèle Hurdle à trois équations, la première prédisant la probabilité d’observer \(Y > 0\), la seconde, la probabilité d’observer \(Y = 1\) et la dernière prédisant les valeurs de Y pour \(0>Y>1\).
  • \[ @@ -7089,7 +7092,7 @@

    De cette manière, il est possible d’exprimer la distribution bêta en fonction de son espérance (sa valeur attendue, ce qui s’interprète approximativement comme une moyenne) et d’un paramètre \(\phi\) intervenant dans le calcul de sa variance. Vous noterez d’ailleurs que la variance de cette distribution dépend de sa moyenne, impliquant à nouveau une hétéroscédasticité intrinsèque.

    -

    Pour résumer, nous nous retrouvons donc avec un modèle qui prédit l’espérance d’une distribution bêta avec une fonction de lien logistique. La variance de cette distribution est fonction de cette moyenne et d’un second paramètre \(\phi\). Ces informations sont résumées dans la fiche d’identité du modèle (tableau 8.36).

    +

    Pour résumer, nous nous retrouvons donc avec un modèle qui prédit l’espérance d’une distribution bêta avec une fonction de lien logistique. La variance de cette distribution est fonction de cette moyenne et d’un second paramètre \(\phi\). Ces informations sont résumées dans la fiche d’identité du modèle (tableau tbl-betaentity).

    @@ -7143,11 +7146,11 @@

    Comme pour un modèle Gamma, la seule condition d’application spécifique à un modèle avec distribution bêta est que la variance des résidus suit la forme attendue par la distribution bêta.

    8.4.4.2 Interprétation des coefficients

    -

    Puisque le modèle utilise la fonction de lien logistique, les exponentiels des coefficients \(\beta\) du modèle peuvent être interprétés comme des rapports de cotes (voir la section 8.2.1 sur le modèle GLM binomial). Admettons ainsi que nous avons obtenu pour une variable indépendante \(X_1\) le coefficient \(\beta_1\) de 0,12. Puisque le coefficient est positif, cela signifie qu’une augmentation de \(X_1\) conduit à une augmentation de l’espérance de Y. L’exponentiel de 0,12 est 1,13, ce qui signifie qu’une augmentation d’une unité de \(X_1\) multiplie par 1,13 (augmente de 13 %) les chances d’une augmentation de Y. Pour ce type de modèle, il est particulièrement important de calculer ses prédictions afin d’en faciliter l’interprétation.

    +

    Puisque le modèle utilise la fonction de lien logistique, les exponentiels des coefficients \(\beta\) du modèle peuvent être interprétés comme des rapports de cotes (voir la section sec-0821 sur le modèle GLM binomial). Admettons ainsi que nous avons obtenu pour une variable indépendante \(X_1\) le coefficient \(\beta_1\) de 0,12. Puisque le coefficient est positif, cela signifie qu’une augmentation de \(X_1\) conduit à une augmentation de l’espérance de Y. L’exponentiel de 0,12 est 1,13, ce qui signifie qu’une augmentation d’une unité de \(X_1\) multiplie par 1,13 (augmente de 13 %) les chances d’une augmentation de Y. Pour ce type de modèle, il est particulièrement important de calculer ses prédictions afin d’en faciliter l’interprétation.

    8.4.4.3 Exemple appliqué dans R

    Afin de présenter le modèle GLM avec une distribution bêta, nous utilisons un jeu de données que nous avons construit pour l’île de Montréal. Nous nous intéressons à la question des îlots de chaleur urbains au niveau des aires de diffusion (AD – entités spatiales du recensement canadien comprenant entre 400 et 700 habitants). Pour cela, nous avons calculé dans chaque AD le pourcentage de sa surface classifiée comme îlot de chaleur dans la carte des îlots de chaleur/fraicheur réalisée par l’INSPQ et le CERFO.

    -

    La question que nous nous posons est la suivante : les populations vulnérables socioéconomiquement et/ou physiologiquement sont-elles systématiquement plus exposées à la nuisance que représentent les îlots de chaleur? Cette question se rattache donc au champ de la recherche sur l’équité environnementale. Plusieurs études se sont d’ailleurs déjà penchées sur la question des îlots de chaleur abordée sous l’angle de l’équité environnementale (Harlan et al. 2007; Sanchez et Reames 2019; Huang, Zhou et Cadenasso 2011). Nous modélisons donc pour chaque AD (n = 3 158) de l’île de Montréal la proportion de sa surface couverte par des îlots de chaleur. Nos variables indépendantes sont divisées en deux catégories : variables environnementales et variables socio-économiques. Les premières sont des variables de contrôle, il s’agit de la densité de végétation dans l’AD (ajoutée avec une polynomiale d’ordre deux) et de l’arrondissement dans lequel elle se situe. Ces deux paramètres affectent directement les chances d’observer des îlots de chaleur, mais nous souhaitons isoler leurs effets (toutes choses étant égales par ailleurs) de ceux des variables socio-économiques. Ces dernières ont pour objectif de cibler les populations vulnérables sur le plan physiologique (personnes âgées et enfants de moins de 14 ans) ou socio-économique (minorités visibles et faible revenu). L’ensemble de ces variables sont présentées dans le tableau 8.37. Notez que, puisque le modèle avec distribution bêta ne peut pas prendre en compte des valeurs exactes de 1 ou 0, nous les avons remplacées respectivement par 0,99 et 0,01. Cette légère modification n’altère que marginalement les données, surtout si nous considérons qu’elles sont agrégées au niveau des AD et proviennent originalement d’imagerie satellitaire.

    +

    La question que nous nous posons est la suivante : les populations vulnérables socioéconomiquement et/ou physiologiquement sont-elles systématiquement plus exposées à la nuisance que représentent les îlots de chaleur? Cette question se rattache donc au champ de la recherche sur l’équité environnementale. Plusieurs études se sont d’ailleurs déjà penchées sur la question des îlots de chaleur abordée sous l’angle de l’équité environnementale (Harlan et al. 2007; Sanchez et Reames 2019; Huang, Zhou et Cadenasso 2011). Nous modélisons donc pour chaque AD (n = 3 158) de l’île de Montréal la proportion de sa surface couverte par des îlots de chaleur. Nos variables indépendantes sont divisées en deux catégories : variables environnementales et variables socio-économiques. Les premières sont des variables de contrôle, il s’agit de la densité de végétation dans l’AD (ajoutée avec une polynomiale d’ordre deux) et de l’arrondissement dans lequel elle se situe. Ces deux paramètres affectent directement les chances d’observer des îlots de chaleur, mais nous souhaitons isoler leurs effets (toutes choses étant égales par ailleurs) de ceux des variables socio-économiques. Ces dernières ont pour objectif de cibler les populations vulnérables sur le plan physiologique (personnes âgées et enfants de moins de 14 ans) ou socio-économique (minorités visibles et faible revenu). L’ensemble de ces variables sont présentées dans le tableau tbl-variablebeta. Notez que, puisque le modèle avec distribution bêta ne peut pas prendre en compte des valeurs exactes de 1 ou 0, nous les avons remplacées respectivement par 0,99 et 0,01. Cette légère modification n’altère que marginalement les données, surtout si nous considérons qu’elles sont agrégées au niveau des AD et proviennent originalement d’imagerie satellitaire.

    @@ -7227,7 +7230,7 @@

    -

    La seule variable semblant poser un problème de multicolinéarité est la variable Arrond. Cependant, du fait de sa nature multinomiale, elle regroupe en réalité 32 coefficients (voir la colonne Df). Il faut donc utiliser la règle habituelle de 5 sur le carré de la troisième colonne (GVIF^(1/(2*Df))) du tableau (Fox et Monette 1992), soit 1,032820^2 = 1,066717, ce qui est bien inférieur à la limite de 5. Nous n’avons donc pas de problème de multicolinéarité excessive. Nous pouvons passer au calcul des distances de Cook. Pour ajuster notre modèle, nous utilisons le package mgcv et la fonction gam avec le paramètre family = betar(link = "logit").

    +

    La seule variable semblant poser un problème de multicolinéarité est la variable Arrond. Cependant, du fait de sa nature multinomiale, elle regroupe en réalité 32 coefficients (voir la colonne Df). Il faut donc utiliser la règle habituelle de 5 sur le carré de la troisième colonne (GVIF^(1/(2*Df))) du tableau (Fox et Monette 1992), soit 1,032820^2 = 1,066717, ce qui est bien inférieur à la limite de 5. Nous n’avons donc pas de problème de multicolinéarité excessive. Nous pouvons passer au calcul des distances de Cook. Pour ajuster notre modèle, nous utilisons le package mgcv et la fonction gam avec le paramètre family = betar(link = "logit").

    # Ajustement d'une première version du modèle
     modele <- gam(hot ~
    @@ -7251,7 +7254,7 @@ 

    -

    Nous pouvons observer à la figure 8.62 que seulement deux observations se distinguent très nettement des autres. Nous les isolons donc dans un premier temps.

    +

    Nous pouvons observer à la figure fig-cookdistbeta que seulement deux observations se distinguent très nettement des autres. Nous les isolons donc dans un premier temps.

    cas_etranges <- subset(dataset, df$cooksd >= 0.01)
     print(cas_etranges[,23:ncol(cas_etranges)])
    @@ -7289,7 +7292,7 @@

    -

    Après réajustement, nous constatons à nouveau qu’une observation est extrêmement éloignée des autres (figure 8.63). Nous la retirons également, car cette différence est si forte qu’elle risque de polluer le modèle.

    +

    Après réajustement, nous constatons à nouveau qu’une observation est extrêmement éloignée des autres (figure fig-cookdistbeta2). Nous la retirons également, car cette différence est si forte qu’elle risque de polluer le modèle.

    # Suppression de l'observation très étonnante
     dataset3 <- subset(dataset2, df2$cooksd<max(df2$cooksd))
    @@ -7315,7 +7318,7 @@ 

    -

    Tout semble aller pour le mieux après ce second passage (figure 8.64). Si nous avions continué à observer des valeurs aussi influentes, nous aurions dû commencer à sérieusement questionner nos données ou notre modèle. La prochaine étape du diagnostic est donc l’analyse des résidus simulés.

    +

    Tout semble aller pour le mieux après ce second passage (figure fig-cookdistbeta3). Si nous avions continué à observer des valeurs aussi influentes, nous aurions dû commencer à sérieusement questionner nos données ou notre modèle. La prochaine étape du diagnostic est donc l’analyse des résidus simulés.

    # Extraction de phi
     modele3$family$family
    @@ -7347,7 +7350,7 @@

    -

    La figure 8.65 indique que les résidus suivent bien une distribution uniforme. Le test des valeurs aberrantes n’est pas significatif au seuil de 0,01 (nous retenons ce seuil considérant le grand nombre de simulations et d’observations de notre jeu de données), nous décidons donc de ne pas supprimer davantage d’observations. Le panneau de droite indique une relation non linéaire instable, mais essentiellement centrée sur la ligne droite attendue. Pour plus de détails, nous calculons ces résidus simulés avec chacune des variables indépendantes.

    +

    La figure fig-residsimbeta indique que les résidus suivent bien une distribution uniforme. Le test des valeurs aberrantes n’est pas significatif au seuil de 0,01 (nous retenons ce seuil considérant le grand nombre de simulations et d’observations de notre jeu de données), nous décidons donc de ne pas supprimer davantage d’observations. Le panneau de droite indique une relation non linéaire instable, mais essentiellement centrée sur la ligne droite attendue. Pour plus de détails, nous calculons ces résidus simulés avec chacune des variables indépendantes.

    # Préparons un plot multiple
     par(mfrow=c(2,3))
    @@ -7365,7 +7368,7 @@ 

    -

    La figure 8.66 indique des relations marginales et négligeables entre nos variables indépendantes et nos résidus simulés. Concernant la variable Arrond (figure 8.67), nous observons une situation plus particulière. Pour quelques arrondissements, les résidus simulés sont nettement plus forts ou plus faibles. Notre hypothèse est que cet effet est provoqué par l’introduction de cette variable dans notre modèle comme un effet fixe alors que sa nature devrait nous inciter à l’introduire comme un effet aléatoire. Nous n’avons pas encore présenté ces concepts ici, mais nous le ferons dans le chapitre 9. En attendant, nous conservons le modèle tel quel et passons à l’analyse de sa qualité d’ajustement.

    +

    La figure fig-residsimbeta2 indique des relations marginales et négligeables entre nos variables indépendantes et nos résidus simulés. Concernant la variable Arrond (figure fig-residsimbeta3), nous observons une situation plus particulière. Pour quelques arrondissements, les résidus simulés sont nettement plus forts ou plus faibles. Notre hypothèse est que cet effet est provoqué par l’introduction de cette variable dans notre modèle comme un effet fixe alors que sa nature devrait nous inciter à l’introduire comme un effet aléatoire. Nous n’avons pas encore présenté ces concepts ici, mais nous le ferons dans le chapitre sec-chap09. En attendant, nous conservons le modèle tel quel et passons à l’analyse de sa qualité d’ajustement.

    df <- data.frame(
       resid = residuals(sim_res),
    @@ -7403,7 +7406,7 @@ 

    -

    Nous constatons à la figure 8.68 que le modèle est parvenu à reproduire la forme générale de la distribution originale : un plus grand nombre de valeurs proches de zéro, suivies d’une répartition presque homogène dans les valeurs comprises entre 0,15 et 0,8, suivies par un plus faible nombre de valeurs quand Y est supérieur à 0,8. Il semble en revanche manquer un certain nombre de valeurs extrêmes proches de 0 (absence d’îlot de chaleur) et proches de 1 (couverture à 100 % par des îlots de chaleur).

    +

    Nous constatons à la figure fig-residsimbeta4 que le modèle est parvenu à reproduire la forme générale de la distribution originale : un plus grand nombre de valeurs proches de zéro, suivies d’une répartition presque homogène dans les valeurs comprises entre 0,15 et 0,8, suivies par un plus faible nombre de valeurs quand Y est supérieur à 0,8. Il semble en revanche manquer un certain nombre de valeurs extrêmes proches de 0 (absence d’îlot de chaleur) et proches de 1 (couverture à 100 % par des îlots de chaleur).

    # Calcul des pseudo R2
     rsqs(loglike.full = modele3$deviance/-2,
    @@ -7467,8 +7470,8 @@ 

    -

    Nous constatons ainsi que seuls quelques arrondissements ont une différence d’exposition aux îlots de chaleur significative au seuil de 0,05 comparativement à Ahuntsic-Cartierville (figure 8.69). Pour l’essentiel, il s’agit d’arrondissements pour lesquels nous observons des rapports de cotes supérieurs à 1. Verdun, Lasalle et le Plateau-Mont-Royal sont les arrondissements les plus touchés avec des chances d’observer des niveaux supérieurs de densité d’îlots de chaleur multipliés par 3,19, 2,89 et 2,74. Le reste des coefficients sont affichés dans le tableau 8.38.

    -

    Nous notons ainsi que le seul groupe associé avec une augmentation significative des chances d’observer une augmentation de la densité d’îlot de chaleur est le groupe des personnes à faible revenu (1,4 % de chance supplémentaire à chaque augmentation d’un point de pourcentage de la variable indépendante). Pour mieux cerner la taille de cet effet, nous représentons l’effet marginal de ce coefficient en maintenant toutes les autres variables à leur moyenne. Nous calculons également ces effets marginaux pour trois arrondissements différents : Verdun (RC le plus fort), Ahuntsic-Cartierville (la référence) et Dollard-des-Ormeaux (RC le plus faible). Nous réalisons également un second graphique pour visualiser l’effet non linéaire de la variable pourcentage de végétation. La figure 8.70 nous indique ainsi que le rôle de l’arrondissement est plus important que celui du pourcentage de personnes à faible revenu. Cependant, nous constatons que passer de 0 % de personnes à faible revenu dans une AD à 75 % est associé avec une multiplication de la surface couverte par des îlots de chaleur par environ 1,5 (toutes choses égales par ailleurs). Le rôle de la végétation dans la réduction de la surface des îlots de chaleur est très net et non linéaire. L’essentiel de la réduction est observé entre 0 et 50 % de végétation dans une AD, au-delà de ce seuil, la réduction des îlots de chaleur par la végétation est moins flagrante. Il semblerait donc exister à Montréal une forme d’iniquité systématique pour les populations à faible revenu, qui seraient davantage exposées aux îlots de chaleur. Cependant, compte tenu de la dépendance spatiale et de l’hétéroscésadicité observées plus haut, des ajustements devraient être apportés au modèle pour confirmer ou infirmer ce résultat.

    +

    Nous constatons ainsi que seuls quelques arrondissements ont une différence d’exposition aux îlots de chaleur significative au seuil de 0,05 comparativement à Ahuntsic-Cartierville (figure fig-betaArrond). Pour l’essentiel, il s’agit d’arrondissements pour lesquels nous observons des rapports de cotes supérieurs à 1. Verdun, Lasalle et le Plateau-Mont-Royal sont les arrondissements les plus touchés avec des chances d’observer des niveaux supérieurs de densité d’îlots de chaleur multipliés par 3,19, 2,89 et 2,74. Le reste des coefficients sont affichés dans le tableau tbl-coeffsbeta.

    +

    Nous notons ainsi que le seul groupe associé avec une augmentation significative des chances d’observer une augmentation de la densité d’îlot de chaleur est le groupe des personnes à faible revenu (1,4 % de chance supplémentaire à chaque augmentation d’un point de pourcentage de la variable indépendante). Pour mieux cerner la taille de cet effet, nous représentons l’effet marginal de ce coefficient en maintenant toutes les autres variables à leur moyenne. Nous calculons également ces effets marginaux pour trois arrondissements différents : Verdun (RC le plus fort), Ahuntsic-Cartierville (la référence) et Dollard-des-Ormeaux (RC le plus faible). Nous réalisons également un second graphique pour visualiser l’effet non linéaire de la variable pourcentage de végétation. La figure fig-betaFR nous indique ainsi que le rôle de l’arrondissement est plus important que celui du pourcentage de personnes à faible revenu. Cependant, nous constatons que passer de 0 % de personnes à faible revenu dans une AD à 75 % est associé avec une multiplication de la surface couverte par des îlots de chaleur par environ 1,5 (toutes choses égales par ailleurs). Le rôle de la végétation dans la réduction de la surface des îlots de chaleur est très net et non linéaire. L’essentiel de la réduction est observé entre 0 et 50 % de végétation dans une AD, au-delà de ce seuil, la réduction des îlots de chaleur par la végétation est moins flagrante. Il semblerait donc exister à Montréal une forme d’iniquité systématique pour les populations à faible revenu, qui seraient davantage exposées aux îlots de chaleur. Cependant, compte tenu de la dépendance spatiale et de l’hétéroscésadicité observées plus haut, des ajustements devraient être apportés au modèle pour confirmer ou infirmer ce résultat.

    @@ -7602,7 +7605,7 @@

    8.5 Conclusion sur les modèles linéaires généralisés

    Comme vous avez dû le remarquer, les modèles linéaires généralisés constituent un monde à part entière et tout un livre pourrait être rédigé à leur sujet. Leur grande flexibilité les rend extrêmement utiles dans de nombreux contextes, mais complique leur mise en œuvre, chaque modèle ayant ses propres spécificités théoriques. Ils partagent cependant tous une base commune : le choix d’une distribution et d’une fonction de lien. L’ensemble de leurs spécificités découle directement de ces deux choix.

    -

    La figure 8.71 résume les choix de modèles présentés au cours de ce chapitre pour des variables qualitatives, de comptage et continues. Notez bien qu’il ne s’agit que de la partie émergée de l’iceberg, car il existe de nombreuses autres distributions plus ou moins complexes (skew-normale, log-normal, beta-binomiale, Box-Cox, Gumbel etc.). D’autres pistes pourraient aussi être explorées pour aller plus loin avec les GLM, notamment les modèles Hurdle (combinant un modèle binomial et un modèle avec une distribution continue), les modèles tronqués ou censurés (tenant compte d’une limite nette dans la variable dépendante) ou encore les modèles distributionnels ajustant une équation de régression pour chaque paramètre de la distribution utilisée.

    +

    La figure fig-GLMfinal résume les choix de modèles présentés au cours de ce chapitre pour des variables qualitatives, de comptage et continues. Notez bien qu’il ne s’agit que de la partie émergée de l’iceberg, car il existe de nombreuses autres distributions plus ou moins complexes (skew-normale, log-normal, beta-binomiale, Box-Cox, Gumbel etc.). D’autres pistes pourraient aussi être explorées pour aller plus loin avec les GLM, notamment les modèles Hurdle (combinant un modèle binomial et un modèle avec une distribution continue), les modèles tronqués ou censurés (tenant compte d’une limite nette dans la variable dépendante) ou encore les modèles distributionnels ajustant une équation de régression pour chaque paramètre de la distribution utilisée.

    Figure 8.71: Résumé graphique des principaux GLM abordés
    @@ -7666,7 +7669,7 @@

    -Relisez au besoin la section 8.1. +Relisez au besoin la section sec-081.
    @@ -7719,7 +7722,7 @@

    -Relisez au besoin la section 8.1.2 +Relisez au besoin la section sec-0812
    @@ -7764,7 +7767,7 @@

    -Relisez au besoin la section 8.1.1. +Relisez au besoin la section sec-0811.
    @@ -7793,7 +7796,7 @@

    -Relisez au besoin la section 11.3. +Relisez au besoin la section sec-113.
    @@ -7838,7 +7841,7 @@

    -Relisez au besoin la section 8.1.4. +Relisez au besoin la section sec-0814.
    @@ -7883,7 +7886,7 @@

    -Relisez au besoin la section 8.1.5. +Relisez au besoin la section sec-0815.
    @@ -7936,7 +7939,7 @@

    -Relisez au besoin la section 8.2.1. +Relisez au besoin la section sec-0821.
    @@ -7981,7 +7984,7 @@

    -Relisez au besoin la section 8.2.1. +Relisez au besoin la section sec-0821.
    @@ -8026,7 +8029,7 @@

    -Relisez au besoin la section 8.6. +Relisez au besoin la section sec-086.
    @@ -8075,7 +8078,7 @@

    -

    9.4 Inférence dans les modèles GLMM

    -

    Une des questions importantes à se poser lorsque nous construisons un modèle est toujours : est-ce que les différents effets présents dans le modèle ont un effet significativement différent de zéro sur la variable dépendante? Cette étape d’inférence est plus compliquée pour les modèles GLMM que dans les modèles GLM à cause de la présence d’effets aléatoires. Ces derniers brouillent le comptage du nombre de paramètres et, par extension, du nombre de degrés de liberté des modèles. Pour un effet aléatoire, il est possible de déterminer que le nombre de degrés de liberté est de 1 puisque nous ajustons un seul paramètre supplémentaire (la variance de cet effet aléatoire). Selon un autre point de vue, il serait possible d’affirmer que le nombre de degrés de liberté est de \(k - 1\) (avec k le nombre de groupes dans cet effet aléatoire), ce que nous utilisons habituellement pour un effet fixe. La vraie valeur du nombre de degrés de liberté se situe quelque part entre ces deux extrêmes. L’enjeu du nombre de degrés de liberté est crucial, car il influence directement l’estimation des valeurs de p pour l’ensemble des coefficients du modèle. Avec un nombre de degrés de liberté plus petit, les valeurs de p sont plus faibles et les effets plus significatifs. Le sujet est d’ailleurs l’objet d’une telle controverse que les auteurs de certains packages comme lme4 (un des packages les plus utilisés pour ajuster des GLMM) ont fait le choix de ne renvoyer aucune valeur de p dans les résultats des modèles. L’article de Bolker et al. (2009) propose une explication détaillée et relativement accessible du problème (en plus d’une excellente introduction aux GLMM) : en se basant sur leurs recommandations, il est possible de séparer le problème de l’inférence dans les GLMM en trois sous problèmes :

    +

    Une des questions importantes à se poser lorsque nous construisons un modèle est toujours : est-ce que les différents effets présents dans le modèle ont un effet significativement différent de zéro sur la variable dépendante? Cette étape d’inférence est plus compliquée pour les modèles GLMM que dans les modèles GLM à cause de la présence d’effets aléatoires. Ces derniers brouillent le comptage du nombre de paramètres et, par extension, du nombre de degrés de liberté des modèles. Pour un effet aléatoire, il est possible de déterminer que le nombre de degrés de liberté est de 1 puisque nous ajustons un seul paramètre supplémentaire (la variance de cet effet aléatoire). Selon un autre point de vue, il serait possible d’affirmer que le nombre de degrés de liberté est de \(k - 1\) (avec k le nombre de groupes dans cet effet aléatoire), ce que nous utilisons habituellement pour un effet fixe. La vraie valeur du nombre de degrés de liberté se situe quelque part entre ces deux extrêmes. L’enjeu du nombre de degrés de liberté est crucial, car il influence directement l’estimation des valeurs de p pour l’ensemble des coefficients du modèle. Avec un nombre de degrés de liberté plus petit, les valeurs de p sont plus faibles et les effets plus significatifs. Le sujet est d’ailleurs l’objet d’une telle controverse que les auteurs de certains packages comme lme4 (un des packages les plus utilisés pour ajuster des GLMM) ont fait le choix de ne renvoyer aucune valeur de p dans les résultats des modèles. L’article de Bolker et al. (2009) propose une explication détaillée et relativement accessible du problème (en plus d’une excellente introduction aux GLMM) : en se basant sur leurs recommandations, il est possible de séparer le problème de l’inférence dans les GLMM en trois sous problèmes :

    • Quel est le degré de significativité des effets fixes?
    • Quel est le degré de significativité de l’effet aléatoire dans le modèle?
    • @@ -781,7 +781,7 @@

      Nous avons vu, pour les modèles LM et GLM, que les valeurs de p sont calculées à partir de scores obtenus en divisant les coefficients par leurs erreurs standards. Une approche similaire peut être utilisée pour les modèles GLMM. Cependant, la question du nombre de degrés de liberté à utiliser reste un problème. L’approche la plus flexible est certainement l’approximation par la méthode Satterthwaite proposant une estimation de ce nombre de degrés de liberté et, par extension, des valeurs de p.

    9.4.1.2 Rapports de vraisemblance

    -

    Si le modèle comprend suffisamment d’observations (par suffisamment, comprenez au moins une centaine d’observations par paramètre), il est également possible d’utiliser une série de tests de rapports de vraisemblance pour vérifier si l’apport de chaque variable indépendante contribue à améliorer significativement le modèle. Cette approche correspond à une analyse de type 3, comme nous l’avons mentionné dans la section 8.2.4 pour le modèle logistique multinomial.

    +

    Si le modèle comprend suffisamment d’observations (par suffisamment, comprenez au moins une centaine d’observations par paramètre), il est également possible d’utiliser une série de tests de rapports de vraisemblance pour vérifier si l’apport de chaque variable indépendante contribue à améliorer significativement le modèle. Cette approche correspond à une analyse de type 3, comme nous l’avons mentionné dans la section sec-0824 pour le modèle logistique multinomial.

    9.4.1.3 Bootstrapping

    L’approche par bootstrapping (parametric-bootstrap ou semi-parametric-bootstrap) permet de calculer, pour les différents paramètres d’un modèle, un intervalle de confiance. L’idée étant de réajuster un grand nombre de fois le modèle sur des sous-échantillons de données pour saisir la variabilité des différents paramètres du modèle. Si les intervalles de confiance ainsi construits ne comprennent pas de zéro, il est possible de dire que cet effet est significatif. À nouveau, cette méthode n’est valide que si le jeu de données comporte suffisamment d’observations. L’intérêt de cette approche est qu’elle ne postule pas d’hypothèse sur la distribution des paramètres qui ont la fâcheuse tendance à ne pas suivre une distribution normale dans le cas des GLMM. Elle est d’ailleurs considérée comme la plus robuste, bien que coûteuse en termes de temps de calcul.

    @@ -797,12 +797,12 @@

    Les GLMM sont donc une extension des GLM offrant une grande flexibilité de modélisation (variabilité des pentes et des constantes en fonction de groupes) et nous permettant d’analyser la partition de la variance entre plusieurs niveaux de nos données. Cependant, cette flexibilité implique des modèles plus complexes avec un travail de diagnostic et d’interprétation plus long et potentiellement plus ardu.

    9.6 Mise en œuvre des GLMM dans R

    -

    Pour cet exemple de GLMM, nous proposons d’analyser à nouveau les données présentées dans la section 6.2.1.1 sur le modèle logistique binomial. Pour rappel, nous modélisions la probabilité qu’un individu utilise le vélo comme mode de transport pour son trajet le plus fréquent en utilisant une enquête réalisée auprès d’environ 26 000 Européens. Initialement, nous avons intégré les pays comme un effet fixe. Or, nous savons à présent qu’il serait plus judicieux de les traiter comme un effet aléatoire. Nous comparons deux modèles, un pour lequel seulement la constante varie par pays et un second dans lequel la pente pour l’âge varie également par pays. L’hypothèse étant que l’effet de l’âge sur l’utilisation du vélo pourrait être réduit dans certains pays où la culture du vélo est plus présente. Cette hypothèse implique également la présence potentielle d’une corrélation inverse entre la constante et la pente de chaque pays : dans un pays où la probabilité de base d’utiliser le vélo est plus élevée, l’effet de l’âge est probablement réduit.

    -

    Pour ajuster ces modèles, nous utilisons le package lme4, permettant d’ajuster des modèles GLMM avec des distributions gaussienne, Gamma, de Poisson et binomial. Lorsque d’autres distributions sont nécessaires, il est possible de se tourner vers le package gamlss. Notez cependant que les effets aléatoires de gamlss sont estimés avec une méthode appelée PQL très flexible, mais qui peut produire des résultats erronés dans certains cas (Bolker et al. 2009).

    +

    Pour cet exemple de GLMM, nous proposons d’analyser à nouveau les données présentées dans la section sec-06211 sur le modèle logistique binomial. Pour rappel, nous modélisions la probabilité qu’un individu utilise le vélo comme mode de transport pour son trajet le plus fréquent en utilisant une enquête réalisée auprès d’environ 26 000 Européens. Initialement, nous avons intégré les pays comme un effet fixe. Or, nous savons à présent qu’il serait plus judicieux de les traiter comme un effet aléatoire. Nous comparons deux modèles, un pour lequel seulement la constante varie par pays et un second dans lequel la pente pour l’âge varie également par pays. L’hypothèse étant que l’effet de l’âge sur l’utilisation du vélo pourrait être réduit dans certains pays où la culture du vélo est plus présente. Cette hypothèse implique également la présence potentielle d’une corrélation inverse entre la constante et la pente de chaque pays : dans un pays où la probabilité de base d’utiliser le vélo est plus élevée, l’effet de l’âge est probablement réduit.

    +

    Pour ajuster ces modèles, nous utilisons le package lme4, permettant d’ajuster des modèles GLMM avec des distributions gaussienne, Gamma, de Poisson et binomial. Lorsque d’autres distributions sont nécessaires, il est possible de se tourner vers le package gamlss. Notez cependant que les effets aléatoires de gamlss sont estimés avec une méthode appelée PQL très flexible, mais qui peut produire des résultats erronés dans certains cas (Bolker et al. 2009).

    Afin de limiter les répétitions, nous ne recalculons pas ici le VIF et nous excluons d’emblée les observations aberrantes (provenant de Malte ou de Chypre ou avec des temps de trajets supérieurs à 400 minutes).

    9.6.1 Ajustement du modèle avec uniquement une constante aléatoire

    -

    Nous commençons donc par ajuster un premier modèle avec une constante aléatoire en fonction du pays. Dans la plupart des packages intégrant des effets aléatoires, la syntaxe suivante est utilisée pour stipuler une constante aléatoire : + (1|Pays). Concrètement, nous tentons d’ajuster le modèle décrit par l’équation 9.11.

    +

    Nous commençons donc par ajuster un premier modèle avec une constante aléatoire en fonction du pays. Dans la plupart des packages intégrant des effets aléatoires, la syntaxe suivante est utilisée pour stipuler une constante aléatoire : + (1|Pays). Concrètement, nous tentons d’ajuster le modèle décrit par l’équation eq-glmmbinom1.

    \[ \begin{aligned} &Y \sim Binomial(p)\\ @@ -960,7 +960,7 @@

    # Sauvegarde des résultats save(valeurs, file = 'data/glmm/boot_binom.rda') -

    Nous pouvons à présent analyser l’incertitude de ces différents paramètres. Pour cela, nous devons commencer par observer graphiquement leurs distributions obtenues par bootstrap avec la figure 9.17.

    +

    Nous pouvons à présent analyser l’incertitude de ces différents paramètres. Pour cela, nous devons commencer par observer graphiquement leurs distributions obtenues par bootstrap avec la figure fig-bottdistrib.

    # Chargement de nos valeurs préalablement enregistrées
     load('data/glmm/boot_binom.rda')
    @@ -1056,7 +1056,7 @@ 

    -

    La figure 9.18 permet de repérer en un coup d’oeil les pays pour lesquels la probabilité d’utiliser le vélo comme moyen de transport pour le trajet le plus fréquent est la plus élevée ou la plus faible. Notez cependant que les valeurs représentées sont pour l’instant des logarithmes de rapport de cotes. Nous devons donc les convertir en rapports de cotes avec la fonction exponentielle pour faciliter leur interprétation.

    +

    La figure fig-randomconstantes1 permet de repérer en un coup d’oeil les pays pour lesquels la probabilité d’utiliser le vélo comme moyen de transport pour le trajet le plus fréquent est la plus élevée ou la plus faible. Notez cependant que les valeurs représentées sont pour l’instant des logarithmes de rapport de cotes. Nous devons donc les convertir en rapports de cotes avec la fonction exponentielle pour faciliter leur interprétation.

    # Conversion en rapports de cote (et arrondissement à trois décimales)
     mat <- round(exp(simsRE[c("mean" , "lower" , "upper")]),3)
    @@ -1114,7 +1114,7 @@ 

    # Sauvegarder des résultats! save(valeurs, file = 'data/glmm/boot_binom2.rda')

    -

    Puisque nous disposons des distributions bootstrapées des différents effets aléatoires, nous pouvons directement les représenter dans un graphique (figure 9.19). Les résultats sont très similaires à ceux de la figure 9.18, ce qui s’explique par le grand nombre d’observations et de groupes. Avec moins d’observations, il est recommandé de privilégier l’approche par bootstrap.

    +

    Puisque nous disposons des distributions bootstrapées des différents effets aléatoires, nous pouvons directement les représenter dans un graphique (figure fig-randomconstantes2). Les résultats sont très similaires à ceux de la figure fig-randomconstantes1, ce qui s’explique par le grand nombre d’observations et de groupes. Avec moins d’observations, il est recommandé de privilégier l’approche par bootstrap.

    # Chargement de nos valeurs bootstrapées
     load('data/glmm/boot_binom2.rda')
    @@ -1242,7 +1242,7 @@ 

    -

    À nouveau, nous nous intéressons ici principalement à la section Random Effect, puisque les effets fixes s’interprètent exactement comme dans les modèles présentés dans le chapitre 6. Les constantes ont une variance de 0,595 et les pentes de 0,007. La corrélation entre les deux effets est de -0,22. Cette corrélation est négative et relativement faible, ce qui signifie que les pays dans lesquels la constante est forte tendent à avoir un coefficient plus petit pour l’âge, et donc une réduction accrue de la probabilité d’utiliser le vélo avec l’âge. Nous devons cependant encore nous assurer qu’elle est significativement différente de 0. Pour cela, nous devons calculer l’intervalle de confiance des trois paramètres de variance du modèle. Nous utilisons à nouveau une approche par bootstrap et nous enregistrons les résultats.

    +

    À nouveau, nous nous intéressons ici principalement à la section Random Effect, puisque les effets fixes s’interprètent exactement comme dans les modèles présentés dans le chapitre sec-chap06. Les constantes ont une variance de 0,595 et les pentes de 0,007. La corrélation entre les deux effets est de -0,22. Cette corrélation est négative et relativement faible, ce qui signifie que les pays dans lesquels la constante est forte tendent à avoir un coefficient plus petit pour l’âge, et donc une réduction accrue de la probabilité d’utiliser le vélo avec l’âge. Nous devons cependant encore nous assurer qu’elle est significativement différente de 0. Pour cela, nous devons calculer l’intervalle de confiance des trois paramètres de variance du modèle. Nous utilisons à nouveau une approche par bootstrap et nous enregistrons les résultats.

    # Fonction d'extraction des trois paramètres de variance
     extractor3 <- function(mod){
    @@ -1314,7 +1314,7 @@ 

    -

    Nous constatons ainsi, à la figure 9.20, que la variance des constantes aléatoires est significativement différente de zéro (cette valeur n’est pas dans l’intervalle de confiance à 95 % représenté par les lignes verticales bleues) et une médiane de 0,56 (ligne verticale rouge). Pour les pentes, zéro est également à la limite de l’intervalle de confiance, et la distribution asymétrique et étalée nous indique que ce paramètre est fortement incertain dans le modèle. Enfin, la corrélation entre les pentes et les constantes est de loin le paramètre le plus incertain et son intervalle de confiance est franchement à cheval sur zéro, ce qui devrait nous amener à privilégier un modèle sans ce paramètre.

    +

    Nous constatons ainsi, à la figure fig-glmmvarboot, que la variance des constantes aléatoires est significativement différente de zéro (cette valeur n’est pas dans l’intervalle de confiance à 95 % représenté par les lignes verticales bleues) et une médiane de 0,56 (ligne verticale rouge). Pour les pentes, zéro est également à la limite de l’intervalle de confiance, et la distribution asymétrique et étalée nous indique que ce paramètre est fortement incertain dans le modèle. Enfin, la corrélation entre les pentes et les constantes est de loin le paramètre le plus incertain et son intervalle de confiance est franchement à cheval sur zéro, ce qui devrait nous amener à privilégier un modèle sans ce paramètre.

    Pour terminer, nous pouvons calculer les R2 marginal et conditionnel du modèle afin de mieux cerner le rôle joué par les effets fixes et les effets aléatoires.

    r.squaredGLMM(modele3)
    @@ -1368,7 +1368,7 @@

    -

    La figure 9.21 nous permet ainsi de constater que l’effet des pays sur les pentes est presque toujours non significatif, sauf pour le Danemark. Son effet négatif (-0,136) indique un renforcement de l’effet général, lui-même négatif (-0,088). Une interprétation possible est qu’au Danemark, l’utilisation du vélo est proportionnellement plus courante par les jeunes que dans le reste des pays de l’Europe.

    +

    La figure fig-randomconstantes2b nous permet ainsi de constater que l’effet des pays sur les pentes est presque toujours non significatif, sauf pour le Danemark. Son effet négatif (-0,136) indique un renforcement de l’effet général, lui-même négatif (-0,088). Une interprétation possible est qu’au Danemark, l’utilisation du vélo est proportionnellement plus courante par les jeunes que dans le reste des pays de l’Europe.

    Pour l’interprétation finale, il est nécessaire d’afficher les valeurs exactes de ces différents paramètres et, dans notre cas, de les convertir en rapports de cotes avec la fonction exponentielle. Pour les pentes aléatoires, il peut être plus facile d’interpréter la somme de l’effet fixe et de l’effet aléatoire.

    # Extraction des effets aléatoires obtenus par simulation
    @@ -1421,7 +1421,7 @@ 

    En revanche, les chances pour un individu d’utiliser le vélo comme mode de transport pour son trajet le plus fréquent sont 4 fois supérieures à la moyenne européenne, contre seulement 1,3 fois en Autriche. Notez à nouveau que les intervalles de confiance pour ces pentes et ces constantes pourraient être estimés plus fiablement par bootstrap.

    9.6.2.3 Diagnostic des effets aléatoires

    -

    Pour rappel, dans un modèle GLMM, les effets aléatoires sont modélisés comme provenant de distributions normales. Nous devons donc vérifier qu’ils respectent cette condition d’application. La figure 9.22 (graphique quantile-quantile) nous permet de constater que les constantes suivent bien une distribution normale, ce qui ne semble pas vraiment être le cas pour les pentes. Considérant que leurs effets sont petits, il serait plus pertinent ici de les retirer du modèle.

    +

    Pour rappel, dans un modèle GLMM, les effets aléatoires sont modélisés comme provenant de distributions normales. Nous devons donc vérifier qu’ils respectent cette condition d’application. La figure fig-diagbinomglmm1 (graphique quantile-quantile) nous permet de constater que les constantes suivent bien une distribution normale, ce qui ne semble pas vraiment être le cas pour les pentes. Considérant que leurs effets sont petits, il serait plus pertinent ici de les retirer du modèle.

    @@ -1430,7 +1430,7 @@

    -

    Considérant que ce modèle inclut une corrélation entre les constantes et les pentes aléatoires, il est également nécessaire de vérifier si elles suivent conjointement une distribution normale bivariée. La figure 9.23 semble indiquer que c’est le cas.

    +

    Considérant que ce modèle inclut une corrélation entre les constantes et les pentes aléatoires, il est également nécessaire de vérifier si elles suivent conjointement une distribution normale bivariée. La figure fig-diagbinomglmm2 semble indiquer que c’est le cas.

    cor_mat <- VarCorr(modele3)[[1]]
     re_effects <- data.frame(ranef(modele3)$Pays)
    @@ -1551,7 +1551,7 @@ 

    -Relisez au besoin la section 9.1.2. +Relisez au besoin la section sec-0912.
    @@ -1596,7 +1596,7 @@

    -Relisez au besoin la section 9.1.1. +Relisez au besoin la section sec-0911.
    @@ -1641,7 +1641,7 @@

    -Relisez au besoin la section 9.1.2. +Relisez au besoin la section sec-0912.
    @@ -1686,7 +1686,7 @@

    -Relisez au besoin la section 9.2. +Relisez au besoin la section sec-092.
    @@ -1723,7 +1723,7 @@

    -Relisez au besoin la section 9.2.1.3. +Relisez au besoin la section sec-09223.
    @@ -1776,7 +1776,7 @@

    -Relisez au besoin la section 9.1.2. +Relisez au besoin la section sec-0912.
    @@ -1805,7 +1805,7 @@

    -Relisez au besoin la section 9.2.1. +Relisez au besoin la section sec-0921.
    @@ -1854,7 +1854,7 @@

    -