Ajouter des modalités dans une colonne

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Kévin Dubois
Messages : 97
Enregistré le : 25 Mar 2019, 12:07

Ajouter des modalités dans une colonne

Messagepar Kévin Dubois » 20 Nov 2020, 18:45

Bonjour,

Je dispose d'un dataframe qui représente :
- un identifiant de carreau
- une année (2006 ou 2012)
- une colonne de facteurs (A, B, ou C)
- une valeur numérique

Voici un code reproductible qui génère un dataframe semblable au miens :

Code : Tout sélectionner

df = data.frame(id_carreau = c("car1", "car1", "car1", "car1", "car2", "car2"), annee = c("2006", "2006", "2012", "2006", "2012", "2012"), facteur = c("A", "B", "A", "C", "A", "C"))


Ce dernier se présente de cette forme :
https://zupimages.net/viewer.php?id=20/47/wv3w.png

On remarque que les modalités de la colonne "facteur" sont répartis de manière aléatoire dans les années de mes carreaux. Certaines années dans certains carreaux, les 3 facteurs n'apparaissent pas. Je voudrais trouver un moyen d'afficher systématiquement tous les facteurs pour chaque année, et pour chaque carreau. L'idée, c'est d'arriver à cette forme :
https://zupimages.net/viewer.php?id=20/47/9pkk.png

Evidement, les valeurs non renseignées deviennent des NA.

Est-il possible de faire ceci dans R ?

Un grand merci.

Serge Rapenne
Messages : 1426
Enregistré le : 20 Aoû 2007, 15:17
Contact :

Re: Ajouter des modalités dans une colonne

Messagepar Serge Rapenne » 20 Nov 2020, 20:50

Bonjour,

il y a vraisemblablement plus simple mai ceci fonctionne :

Code : Tout sélectionner

df = data.frame(id_carreau = c("car1", "car1", "car1", "car1", "car2", "car2"), annee = c("2006", "2006", "2012", "2006", "2012", "2012"), facteur = c("A", "B", "A", "C", "A", "C"))
df2<-expand.grid(unique(df$id_carreau),unique(df$annee),unique(df$facteur),stringsAsFactors = F) # on génère un df contenant tous les croisements entre id_carreau, annee et facteur
colnames(df2)<-colnames(df)

#on construit des chaines constitués de la concaténation de chaque lignes de 2 df
tmp<-apply(df,1,paste,collapse="_")
tmp2<-apply(df2,1,paste,collapse="_")

#si la chaine tmp2 existe dans tmp c'est que cette serie de valeurs existe dans df et on garde la valeur sinon on met NA
df2$facteur<-ifelse(tmp2 %in% tmp,df2$facteur,NA)
df2
   id_carreau annee facteur
1        car1  2006       A
2        car2  2006    <NA>
3        car1  2012       A
4        car2  2012       A
5        car1  2006       B
6        car2  2006    <NA>
7        car1  2012    <NA>
8        car2  2012    <NA>
9        car1  2006       C
10       car2  2006    <NA>
11       car1  2012    <NA>
12       car2  2012       C


Serge

Pierre-Yves Berrard
Messages : 1029
Enregistré le : 12 Jan 2016, 23:30

Re: Ajouter des modalités dans une colonne

Messagepar Pierre-Yves Berrard » 20 Nov 2020, 21:20

Serge Rapenne a écrit :il y a vraisemblablement plus simple

Challenge accepted :

Code : Tout sélectionner

tidyr::complete(
  df,
  annee, id_carreau, facteur
)
PY

Serge Rapenne
Messages : 1426
Enregistré le : 20 Aoû 2007, 15:17
Contact :

Re: Ajouter des modalités dans une colonne

Messagepar Serge Rapenne » 20 Nov 2020, 21:26

Ah bin oui, il avait effectivement plus simple bien joué PY

Code : Tout sélectionner

?tidyr::complete
This is a wrapper around expand(), dplyr::left_join() and replace_na() that's useful for completing missing combinations of data.

c'est bizarre, le coup de la jointure avait été ma 1ere idée et puis j'ai pensé à la comparaisons de chaine, et c'est ça que j'ai fait, ceci prouve bien que je ne suis pas Hadley Wickham :-)

Serge

Kévin Dubois
Messages : 97
Enregistré le : 25 Mar 2019, 12:07

Re: Ajouter des modalités dans une colonne

Messagepar Kévin Dubois » 22 Nov 2020, 14:51

Un grand merci à vous pour vos réponses.

Après application de ces méthodes dans un dataframe similaire mais bien plus volumineux (450 000 entrées), je remarque que ?tidyr::complete ne fonctionne pas. Après 8 min de calcul, il me retourne une copie simple du dataframe de base.... bizarre, car cela marche sur le dataframe généré dans l'exemple (celui à quelques lignes).

En revanche, merci à Serge car sa méthode fonctionne dans mon cas (en plus d'être plus rapide d'exécution que ?tidyr::complete !).

Pierre-Yves Berrard
Messages : 1029
Enregistré le : 12 Jan 2016, 23:30

Re: Ajouter des modalités dans une colonne

Messagepar Pierre-Yves Berrard » 22 Nov 2020, 16:30

Serge 1, Hadley 0
PY

Serge Rapenne
Messages : 1426
Enregistré le : 20 Aoû 2007, 15:17
Contact :

Re: Ajouter des modalités dans une colonne

Messagepar Serge Rapenne » 22 Nov 2020, 22:20

:-), je devrais peut être postuler chez Rstudio.

Serge

jean lobry
Messages : 733
Enregistré le : 17 Jan 2008, 20:00
Contact :

Re: Ajouter des modalités dans une colonne

Messagepar jean lobry » 23 Nov 2020, 17:55

Bonjour,

personellement j'aurais fait comme Serge : générer toutes les combinaisons possibles puis croiser avec l'existant mais en faisant une jointure à gauche :

Code : Tout sélectionner

df <- data.frame(
  id_carreau = c("car1", "car1", "car1", "car1", "car2", "car2"),
  annee = c("2006", "2006", "2012", "2006", "2012", "2012"),
  facteur = c("A", "B", "A", "C", "A", "C"))

# On génère un df2 contenant tous les croisements entre id_carreau/annee/facteur
df2 <- with(df, expand.grid(unique(id_carreau), unique(annee), unique(facteur)))
colnames(df2) <- colnames(df)
# On génère une clef carreau/année/facteur dans les deux tables
df$id <- with(df, paste(id_carreau, annee, facteur))
df2$id <- with(df2, paste(id_carreau, annee, facteur))
# On fait une jointure pour récupérer ceux qui existent pour de vrai
res <- merge(df2[ , -which(colnames(df) == "facteur")], df[ , c("id", "facteur")],
        by.x = "id", by.y = "id", all.x = TRUE)
res[ , -1] # on vire l'id temporaire de la première colonne

   id_carreau annee facteur
1        car1  2006       A
2        car1  2006       B
3        car1  2006       C
4        car1  2012       A
5        car1  2012    <NA>
6        car1  2012    <NA>
7        car2  2006    <NA>
8        car2  2006    <NA>
9        car2  2006    <NA>
10       car2  2012       A
11       car2  2012    <NA>
12       car2  2012       C


Je ne sais pas si c'est plus simple ni plus efficace. Vouloir expliciter l'inexistant c'est à coup sûr se heurter au mur de l'explosion combinatoire avec des données réelles un peu volumineuses.

Bien amicalement,

jean

Bastien Gamboa
Messages : 151
Enregistré le : 13 Jan 2011, 21:31

Re: Ajouter des modalités dans une colonne

Messagepar Bastien Gamboa » 26 Nov 2020, 08:20

Bonjour,

Pour apporter ma pierre à l'édifice, je partirais également sur les approches de Serge et Jean, mais en laissant tout faire à merge().
L'idée est de créer le monde des possible avec expand.grid(), puis de merger les datas à celui-ci :

Code : Tout sélectionner

tutu <- data.frame(id_carreau=c("car1", "car1", "car1", "car1", "car2", "car2"),
                   annee     =c("2006", "2006", "2012", "2006", "2012", "2012"),
                   facteur   =c("A", "B", "A", "C", "A", "C"))
World <- expand.grid(id_carreau=unique(tutu$id_carreau), annee=unique(tutu$annee), facteur=unique(tutu$facteur))
tutu$RealFacteur <- tutu$facteur
merge(World, tutu, by=colnames(World), all=TRUE)
   id_carreau annee facteur RealFacteur
1        car1  2006       A           A
2        car1  2006       B           B
3        car1  2006       C           C
4        car1  2012       A           A
5        car1  2012       B        <NA>
6        car1  2012       C        <NA>
7        car2  2006       A        <NA>
8        car2  2006       B        <NA>
9        car2  2006       C        <NA>
10       car2  2012       A           A
11       car2  2012       B        <NA>
12       car2  2012       C           C

HTH,
Bastien

Edit : En fait c'est la même approche que Jean, sans la création des identifiants, cette étape étant réalisée par merge()

jean lobry
Messages : 733
Enregistré le : 17 Jan 2008, 20:00
Contact :

Re: Ajouter des modalités dans une colonne

Messagepar jean lobry » 26 Nov 2020, 17:14

Bonjour Bastien,

j'aime bien ta solution :-)

Amicalement,

jean lobry


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité