<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Super Statisticienne &#187; Marketing</title>
	<atom:link href="https://superstatisticienne.fr/category/marketing/feed/" rel="self" type="application/rss+xml" />
	<link>https://superstatisticienne.fr</link>
	<description>Statistiques, R et paillettes...</description>
	<lastBuildDate>Sat, 19 Nov 2016 14:52:42 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
	<item>
		<title>Typologie avec R</title>
		<link>https://superstatisticienne.fr/typologie-avec-r/</link>
		<comments>https://superstatisticienne.fr/typologie-avec-r/#comments</comments>
		<pubDate>Thu, 15 Oct 2015 08:43:59 +0000</pubDate>
		<dc:creator><![CDATA[superstatisticienne]]></dc:creator>
				<category><![CDATA[Marketing]]></category>
		<category><![CDATA[R]]></category>
		<category><![CDATA[Statistiques]]></category>
		<category><![CDATA[Classification]]></category>

		<guid isPermaLink="false">http://superstatisticienne.fr/?p=88</guid>
		<description><![CDATA[En marketing, on appelle typologie un traitement de données qui vise à régrouper des individus en fonction de leur proximité/ressemblance sur un ensemble de variables. En terme d&#8217;analyse statistique, on va utiliser une analyse factorielle de type &#171;&#160;ACM&#160;&#187; (= Analyse des Correspondances Multiples) suivie d&#8217;une classification ascendante hiérarchique (&#171;&#160;CAH&#160;&#187;). Nous allons donc voir comment faire [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>En marketing, on appelle <span style="color: #923887;"><strong>typologie</strong></span> un traitement de données qui vise à régrouper des individus en fonction de leur <em>proximité</em>/<em>ressemblance</em> sur un ensemble de variables. En terme d&rsquo;analyse statistique, on va utiliser une analyse factorielle de type &laquo;&nbsp;ACM&nbsp;&raquo; (= <u>A</u>nalyse des <u>C</u>orrespondances <u>M</u>ultiples) suivie d&rsquo;une <strong>classification ascendante hiérarchique</strong> (&laquo;&nbsp;CAH&nbsp;&raquo;). </p>
<p>Nous allons donc voir comment faire cela avec <strong>R</strong>.<br />
&nbsp;<br />
<span id="more-88"></span></p>
<p>+ <u>Chargement des données</u> :</p>
<p></p><pre class="crayon-plain-tag">M <- read.csv("data_typo.csv", header = TRUE, sep = ";")</pre><p>> Type du fichier d&rsquo;exemple : CSV, séparateur &laquo;&nbsp;point-virgule&nbsp;&raquo;, questions de type qualitatif et questions à choix multiples au format dichotomique (1 = &laquo;&nbsp;Cité&nbsp;&raquo; / 0 = &laquo;&nbsp;Non Cité&nbsp;&raquo;)<br />
&nbsp;<br />
+ <u>Visualiser le nom des variables/en-têtes de colonnes</u> :</p>
<p></p><pre class="crayon-plain-tag">colnames(M)</pre><p>&nbsp;<br />
+ <u>Gestion des valeurs manquantes NA</u> :</p>
<p></p><pre class="crayon-plain-tag">vm <- which(is.na(M$q1))  # sélectionner les individus ayant une valeur manquante à la question "q1" par exemple
vm <- which(is.na(M[, 3]))  # autre écriture si, par exemple, la question "q1" est en colonne 3 dans les données

# vm contient la liste des numéros de lignes correspondant aux individus ayant une valeur manquante (NA) pour "q1"

M <- M[-vm, ]  # exclusion des NA de q1 dans le jeu de données global</pre><p>&nbsp;<br />
+ <u>Sélection d&rsquo;individus d&rsquo;après un filtre</u> :</p>
<p></p><pre class="crayon-plain-tag">ut <- which(M$util == 1)  # ex : on ne veut réaliser l'analyse que sur les profils "utilisateurs", i.e. les gens ayant choisi la modalité 1 à la question "util"

# ou
ut <- which(M[, 1] == 1)  # si la question "util" est en 1ère colonne dans les données

# ut contient la liste des numéros de lignes correspondant aux individus "utilisateurs"

M <- M[ut, ]  # selection des profils "utilisateurs" parmis le jeu de données global</pre><p>&nbsp;<br />
+ <u>Sélection des variables typo</u> :</p>
<p>Un certain nombre de variables ont été retenues pour réaliser la typologie. On va donc récupérer les données correspondant à ces variables en particulier.</p>
<p></p><pre class="crayon-plain-tag">list_vars <- c(3:5, 12, 24:27)  # contient les numéros des colonnes correspondant aux variables choisies pour la typo</pre><p>> Au final, &laquo;&nbsp;list_vars&nbsp;&raquo; contient les numéros suivants : 3, 4, 5, 12, 24, 25, 26 et 27</p>
<p></p><pre class="crayon-plain-tag">X <- M[, list_vars]</pre><p>> La matrice &laquo;&nbsp;X&nbsp;&raquo; va contenir uniquement les variables (actives et illustratives) qui serviront dans la typologie (dans notre exemple : 8 variables).<br />
&nbsp;<br />
+ <u>Vecteur de poids</u> :</p>
<p>Dans le cas où il existe une pondération sur les individus, on va avoir besoin d&rsquo;un vecteur contenant ces poids.</p>
<p></p><pre class="crayon-plain-tag">poids <- M$poids</pre><p></p>
<p>&nbsp;</p>
<p><span style="color: #923887;"><strong>- Analyse des Correspondances Multiples -</strong></span><br />
&nbsp;<br />
+ <u>Type des variables = &laquo;&nbsp;factor&nbsp;&raquo;</u> :</p>
<p>Dans R, il va falloir spécifier que les variables utilisées pour notre analyse sont de type &laquo;&nbsp;qualitatif&nbsp;&raquo; (ie. avec un nombre fini de modalités entières) : il s&rsquo;agit de mettre les variables de &laquo;&nbsp;X&nbsp;&raquo; au format &laquo;&nbsp;factor&nbsp;&raquo;.</p>
<p></p><pre class="crayon-plain-tag">X <- apply(X, 2, as.factor)

str(X)  # l'appel à la fonction "str" va nous permettre de vérifier que toutes les variables ont bien le type "factor" souhaité</pre><p>&nbsp;<br />
+ <u>ACM</u> :</p>
<p></p><pre class="crayon-plain-tag">library(FactoMineR)  # va permettre de charger la librairie contenant la fonction permettant de réaliser l'ACM

acm <- MCA(X, ncp = 80, graph = FALSE, quali.sup = c(7, 8), row.w = poids)  # réalisation de l'ACM</pre><p></p>
<p><u>Syntaxe</u> : Arguments de la fonction &laquo;&nbsp;MCA&nbsp;&raquo; </p>
<table>
<tr>
<td>X</td>
<td>matrice des variables actives et illustratives utilisées pour l&rsquo;ACM</td>
</tr>
<tr>
<td>ncp</td>
<td>nombre de composantes retenues au maximum</td>
</tr>
<tr>
<td>graph = FALSE</td>
<td>empêche l&rsquo;affichage de sorties graphiques (TRUE pour l&rsquo;autoriser)</td>
</tr>
<tr>
<td>quali.sup = c(&#8230;)</td>
<td>quali.sup = vecteur des numéros de colonnes dans X qui correspondent aux variables illustratives (existe aussi &laquo;&nbsp;quanti.sup&nbsp;&raquo;)</td>
</tr>
<tr>
<td>row.w = poids</td>
<td>permet de spécifier le vecteur des poids des individus (si pas de pondération, ne pas mettre cet argument)</td>
</tr>
</table>
<p>&nbsp;<br />
+ <u>Sélection des composantes</u> :</p>
<p>On va sélectionner un nombre de composantes permettant d&rsquo;obtenir le maximum d&rsquo;informations (par exemple 80%).</p>
<p></p><pre class="crayon-plain-tag">vp <- acm$eig$eigenvalue  # vecteur des valeurs propres associées aux composantes de l'ACM

100*(cumsum(vp)/sum(vp))  # pourcentage cumulé d'info apportée par les composantes de l'ACM</pre><p>> On va ensuite sauvegarder les composantes retenues (ainsi que les données initiales) dans un fichier csv :</p><pre class="crayon-plain-tag">IC <- acm$ind$coord[, 1:25]  # ici on a retenu 25 composantes

colnames(IC) <- paste0("Dim.", 1:25)

C <- cbind(M, IC)

write.csv(C, file = "data_total_with_acm_coord.csv", row.names = FALSE, quote = FALSE)</pre><p></p>
<p>&nbsp;</p>
<p><span style="color: #923887;"><strong>- Classification -</strong></span><br />
&nbsp;<br />
On va maintenant réaliser une classification sur les composantes de l&rsquo;ACM que nous avons retenues afin de séparer nos individus en plusieurs groupes.</p>
<p>+ <u>Dendrogramme</u> :</p>
<p></p><pre class="crayon-plain-tag">dendro <- hclust(dist(model.matrix(~-1+Dim.1+Dim.2+Dim.3+Dim.4+Dim.5+Dim.6+Dim.7+Dim.8+Dim.9+Dim.10+Dim.11+Dim.12+Dim.13+Dim.14+Dim.15+Dim.16+Dim.17+Dim.18+Dim.19+Dim.20+Dim.21+Dim.22+Dim.23+Dim.24+Dim.25,C)), method = "ward")

plot(dendro)  # représentation de l'arbre de classification

# ou : représentation plus personnalisée de l'arbre de classification (nécessite une connexion internet)

source("http://addictedtor.free.fr/packages/A2R/lastVersion/R/A2R")

pdf("dendro5.pdf")  # va permettre de sauvegarder le dendrogramme au format pdf

A2Rplot(dendro, k = 5, lty.up = 1, lty.down = 1, boxes = FALSE, col.down = c("orange", "blue", "green", "red", "yellow"), lwd.down = 1, col.up = "black", show.labels = FALSE, main = "Dendrogramme")  # ici répartition en 5 groupes

dev.off()</pre><p></p>
<p>> L&rsquo;observation de l&rsquo;arbre va nous permettre de décider d&rsquo;un nombre <em>k</em> de groupes dans lesquels seront répartis les individus de l&rsquo;étude.</p>
<p><u>Exemple de dendrogramme</u> :</p>
<p><a href="http://superstatisticienne.fr/wp-content/uploads/2014/06/dendro5.png"><img src="http://superstatisticienne.fr/wp-content/uploads/2014/06/dendro5.png" alt="dendro5" width="700" height="700" class="aligncenter size-full wp-image-158" /></a></p>
<p>+ <u>Répartition des individus dans les groupes et effectifs</u> :</p>
<p></p><pre class="crayon-plain-tag">group5 <- cutree(dendro, k = 5)  # vecteur contenant le numéro du groupe (ici entre 1 et 5) auquel appartient chaque individu

table(group5)  # va renvoyer le tableau d'effectifs de chacun des 5 groupes</pre><p>> On va ensuite sauvegarder les numéros de groupe des individus (ainsi que les résultats de l&rsquo;ACM et les données initiales) dans un fichier csv :</p><pre class="crayon-plain-tag">T <- cbind(C, group5)

write.csv(T, file = "data_complete_with_groups.csv", row.names = FALSE, quote = FALSE)</pre><p></p>
<p>&nbsp;</p>
<p><span style="color: #923887;"><strong>- Description des groupes -</strong></span><br />
&nbsp;<br />
Maintenant que nous avons une répartition de nos individus en <em>k</em> groupes, ce qui va nous intéresser c&rsquo;est de déterminer quels sont les éléments (variables) qui caractérisent ces différents groupes.<br />
Pour cela, on peut utiliser la fonction : &laquo;&nbsp;<em>catdes.w</em>&laquo;&nbsp;, donc vous trouverez le code ci-dessous :<br />
(<em>il s&rsquo;agit en fait d&rsquo;une version très légèrement modifiée de la fonction &laquo;&nbsp;catdes&nbsp;&raquo; du package &laquo;&nbsp;FactoMineR&nbsp;&raquo;, afin de pouvoir prendre en compte un poids sur les individus</em>)</p>
<div class="omsc-accordion"><br />
<div class="omsc-toggle"><div class="omsc-toggle-title">Afficher code</div><div class="omsc-toggle-inner"><br />
<pre class="crayon-plain-tag">catdes.w<-function (donnee, num.var, proba = 0.05 , weight=NULL) 
{
   lab.sauv <- lab <- colnames(donnee)
   quali = NULL

   for (i in 1:length(lab))
   {
      lab[i] = gsub(" ", ".", lab[i])

      if (is.factor(donnee[, i]))
      {
         if (levels(donnee[, i])[1] == "")
         {	
            levels(donnee[, i])[1] = "NA"
         }

         if (i != num.var)
         {
            quali = c(quali, i)
         }
      }
   }

   quanti = (1:ncol(donnee))[-c(quali, num.var)]

   if (length(quanti) == 0)
   {
      quanti = NULL
   }

   colnames(donnee) = lab
   res = list()
   nb.modalite <- length(levels(donnee[, num.var]))
   nb.quali = length(quali)
   old.warn = options("warn")

   if(length(weight)==0)
   {
      weight<-rep(1,dim(donnee)[1])
   }

   if (nb.quali > 0) 
   {
      options(warn = -1)

      marge.li = xtabs(weight~donnee[, num.var])
      nom = tri = structure(vector(mode = "list", length = nb.modalite), names = levels(donnee[, num.var]))

      for (i in 1:nb.quali) 
      {
         Table <- xtabs(weight~donnee[, num.var] + donnee[, quali[i]])
         marge.col = xtabs(weight~donnee[, quali[i]])

         ML<-rowSums(Table)

         for (j in 1:nlevels(donnee[, num.var]))
         {
            for (k in 1:nlevels(donnee[, quali[i]]))
            {
               aux2 = Table[j, k]/ML[j]

               if(ML[j]==0)
               {
                  aux2 = 0
               }

               aux3 = marge.col[k]/sum(marge.col)

               if (aux2 > aux3) 
               {
                  aux4 = phyper(Table[j, k] - 1, ML[j], sum(ML) - ML[j], marge.col[k], lower.tail = FALSE) * 2
               }
               else 
               {
                  aux4 = phyper(Table[j, k], ML[j], sum(ML) - ML[j], marge.col[k]) * 2
               }

               if (aux4 < proba)
               {
                  aux5 = (1 - 2 * as.integer(aux2 > aux3)) * qnorm(aux4/2)
                  aux1 = Table[j, k]/marge.col[k]

                  tri[[j]] = rbind(tri[[j]], c(aux1 * 100, aux2 * 100, aux3 * 100, aux4, aux5))
                  nom[[j]] = rbind(nom[[j]], c(levels(donnee[,quali[i]])[k], colnames(donnee)[quali[i]]))
               }
            }
         }
      }

      for (j in 1:nb.modalite)
      {
         if (!is.null(tri[[j]]))
         {
            oo = rev(order(tri[[j]][, 5]))
            tri[[j]] = tri[[j]][oo, ]
            nom[[j]] = nom[[j]][oo, ]

            if (nrow(matrix(tri[[j]], ncol = 5)) > 1)
            {
               rownames(tri[[j]]) = paste(nom[[j]][, 2], nom[[j]][,1], sep = "=")
            }
            else
            {
               tri[[j]] = matrix(tri[[j]], ncol = 5)
               rownames(tri[[j]]) = paste(nom[[j]][2], nom[[j]][1], sep = "=")
            }

            colnames(tri[[j]]) = c("Cla/Mod", "Mod/Cla", "Global", "p.value", "v.test")
         }

      }

      res$category = tri
   }

   if (!is.null(quanti))
   {
      nom = result = structure(vector(mode = "list", length = nb.modalite), names = levels(donnee[, num.var]))

      for (i in 1:length(quanti))
      {
         moy.mod = by(donnee[, quanti[i]]*weight, donnee[, num.var], mean, na.rm = TRUE)
         n.mod = summary(donnee[, num.var])

         sd.mod = by(donnee[, quanti[i]]*weight, donnee[, num.var], sd, na.rm = TRUE)
         sd.mod = sd.mod * sqrt((n.mod - rep(1, nb.modalite))/n.mod)

         moy = mean(donnee[, quanti[i]]*weight, na.rm = TRUE)
         et = sd(donnee[, quanti[i]]*weight, na.rm = TRUE) * sqrt(1 - 1/sum(n.mod))

         for (j in 1:nb.modalite)
         {
            v.test = (moy.mod[j] - moy)/et * sqrt(n.mod[j])/sqrt((sum(n.mod) - n.mod[j])/(sum(n.mod) - 1))
            p.value = pnorm(abs(v.test), lower.tail = FALSE) * 2

            if (!is.na(v.test))
            {
               if (abs(v.test) > -qnorm(proba/2))
               {
                  result[[j]] = rbind(result[[j]], c(v.test, moy.mod[j], moy, sd.mod[j], et, p.value))
                  nom[[j]] = c(nom[[j]], colnames(donnee)[quanti[i]])
               }
            }
         }
      }

      for (j in 1:nb.modalite)
      {
         if (!is.null(result[[j]]))
         {
            oo = rev(order(result[[j]][, 1]))
            result[[j]] = result[[j]][oo, ]
            nom[[j]] = nom[[j]][oo]

            if (nrow(matrix(result[[j]], ncol = 6)) > 1)
            {
               rownames(result[[j]]) = nom[[j]]
               colnames(result[[j]]) = c("v.test", "Mean in category", "Overall mean", "sd in category", "Overall sd", "p.value")
            }
            else
            {
               result[[j]] = matrix(result[[j]], ncol = 6)
               rownames(result[[j]]) = nom[[j]]
               colnames(result[[j]]) = c("v.test", "Mean in category", "Overall mean", "sd in category", "Overall sd", "p.value")
            }
         }
      }

      res$quanti = result
   }

   options(old.warn)
   class(res) <- c("catdes", "list ")
   return(res)
}</pre><br />
</div></div><br />
</div>
<p>&nbsp;<br />
<u>Utilisation</u> :</p>
<p></p><pre class="crayon-plain-tag">M <- read.csv("data_complete_with_groups.csv", header = TRUE, sep = ",")

vars <- c(3:5, 12, 24:27, 45)  # liste des numéros de colonnes correspondant aux variables utilisées pour la typo ET à la variable "groupe"

X <- M[, vars]

D <- apply(X, 2, as.factor)

donnees <- as.data.frame(D)

num.var <- 9  # la variable "groupe" est située en 9ème colonne de "donnees"

proba = 0.05  # seuil de significativité = 5%

weight <- M[, 2]  # le poids des individus est en 2ème colonne de M


source("catdes_w.R")  # va permettre d'indiquer à R où trouver le code de la fonction "catdes.w" qu'on aura au préalable sauvegardée dans une fichier nommé "catdes_w.R"

results <- catdes.w(donnees, num.var, proba = 0.05 , weight) 

G1 <- results$category$"1"
G2 <- results$category$"2"
G3 <- results$category$"3"
G4 <- results$category$"4"
G5 <- results$category$"5"

K <- rbind(rep("",5), round(G1,3), rep("",5), rep("",5), round(G2,3), rep("",5), rep("",5), round(G3,3), rep("",5), rep("",5), round(G4,3), rep("",5), rep("",5), round(G5,3), rep("",5))

write.csv(K, file = "Typo1_5groups_weighted.csv", quote = FALSE)  # va sauvegarder la description des groupes typo dans un fichier csv (qu'on pourra mettre en page par la suite, notamment en remplaçant les valeurs de type "q1_1=1" par le libellé correspondant)</pre><p></p>
<p>&nbsp;</p>
<p><span style="color: #923887;"><strong>- Lecture des résultats -</strong></span><br />
&nbsp;<br />
Exemple de description d&rsquo;un groupe :</p>
<div class="monTableau">
<table border="1">
<tr>
<th> </th>
<th>Cla / Mod</th>
<th>Mod / Cla</th>
<th>Global</th>
<th>p.value</th>
<th>v.test</th>
</tr>
<tr>
<td>Q18 &#8211; Satisfaction : Clarté de la présentation = ST Pas satisfait</td>
<td>71.43</td>
<td>78.43</td>
<td>13.93</td>
<td>3.70 10^-20</td>
<td>11.72</td>
</tr>
</table>
</div>
<p>&nbsp;<br />
> <em><strong>Cla / Mod = 71,43</strong></em> : 71,43 % des individus (parmis l&rsquo;ensemble de la population à qui est posée cette question) qui sont &laquo;&nbsp;Non Satisfaits&nbsp;&raquo; par &laquo;&nbsp;la clarté de la présentation des informations&nbsp;&raquo; se retrouvent dans ce groupe.</p>
<p>> <em><strong>Mod / Cla = 78,43</strong></em> et <em><strong>Global = 13,93</strong></em> : dans ce groupe il y a 78,43 % des individus qui sont &laquo;&nbsp;Non Satisfaits&nbsp;&raquo; par &laquo;&nbsp;la clarté de la présentation des informations&nbsp;&raquo; alors que dans la population global il n&rsquo;y en a que 13,93 %, il y a donc une sur-représentation de cette modalité dans le groupe.</p>
<p>> <em><strong>p.value = 3.70 10^-20</strong></em> : La sur-représentation dans ce groupe de la modalité &laquo;&nbsp;Non Satisfaits&nbsp;&raquo; pour &laquo;&nbsp;la clarté de la présentation des informations&nbsp;&raquo; est significative au seuil 3.70&#215;10^-20.</p>
<p>> <em><strong>v.test = 11.72</strong></em> : valeur de la statistique de test permettant de déterminer la significativité des variables de description du groupe (si la valeur est positive, on aura une sur-représentation de la modalité considérée, si elle est négative, une sous-représentation).</p>
<p>C&rsquo;est cette description de chacun des différents groupes qui va permettre ensuite de classer nos répondants dans des catégories bien spécifiques auxquelles on pourra donner des noms en rapport avec la description obtenue (par exemple &laquo;&nbsp;Les insatisfaits&nbsp;&raquo;).</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>https://superstatisticienne.fr/typologie-avec-r/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
