Comment réorganiser des Données agglomérées avec une colonne par année

En langage R

L'essentiel de cette page

Les bonnes pratiques exigent que, dans l'analyse de données, l'on mette une seule colonne par variable. Pourtant, bien souvent, celui qui prépare ses données trouvera pratique d'assembler ses valeurs en ajoutant une colonne par année (ex : poids2024, poids2025, poids2026) alors qu'il faudra une seule colonne pour cette variable et une pour l'année.

Voici un code qui permet de redonner une forme exploitable à un jeu de données mal organisé de cette façon.

Partons d'un exemple...

Des données pour l'exemple

Ce code permet par un simple copier-coller de générer un jeu de données où le poids de 4 personnes a été collectées de 2024 à 2026. Leurs taille n'a été relevée que sur 2024 et 2026 (pas 2025). Une tentative d'analyse a été menée en comparant les poids de 2026 et 2024 dans une colonne Poids2026-2024.

On notera tout de suite des erreurs à ne pas.

Le vrai tableau devrait ressembler à cela :

# Code pour générer cet exemple (à copier-coller)

df <- data.frame(Noms=c("Marcel","Julia","Rose","Joseph"),

Poids2024=round(rnorm(4,75,6),0))

df <- cbind(df,Poids2025=round(df$Poids2024*rnorm(4,1,0.1),0))

df <- cbind(df,Poids2026=round(df$Poids2025*rnorm(4,1,0.1),0))

df <- cbind(df,"Poids2026-2024"=df$Poids2026-df$Poids2024)

df <- cbind(df,Tailles2024=round(rnorm(4,170,12),0))

df <- cbind(df,Tailles2026=round(df$Tailles2024*rnorm(4,1,0.01),0))

print(df)

Des données pour l'exemple

# 1. Éliminer les colonnes indésirables

eliminate_patterns <- "(\\D+\\d{2,4}-\\d{2,4})"

cols_to_eliminate <- grep(eliminate_patterns, colnames(df), value = TRUE) # Vérification des colonnes à éliminer print(cols_to_eliminate)

data_filtered <- df[, !colnames(df) %in% cols_to_eliminate]

# Vérification du dataframe filtré

print(data_filtered) 

# 2. Sélectionner les colonnes correspondant aux variables d'intérêt (les colonnes avec des années à la fin)

cols_variable <- grep("\\d{2,4}$", colnames(data_filtered), value = TRUE)

# Extraire les entités (colonnes non correspondant aux variables d'intérêt) - ici une seule colonne, les noms

entities <- data.frame(data_filtered[,1] )

3 # Extraire les années et les noms de variables

years <- as.numeric(sub(".*(\\d{2,4})$", "\\1", colnames(data_filtered[, cols_variable])))

years[years < 100] <- years[years < 100] + 2000 

# Ajuster pour les années à 2 chiffres

variable_names <- sub("\\d{2,4}$", "", colnames(data_filtered[, cols_variable]))

indices_variable <- grep("\\d{2,4}$", colnames(data_filtered)) 

4 # Initialiser data_final avec les colonnes d'entités correctement

data_final <- data.frame(rep(sort(unique(years)),each=nrow(entities)))

colnames(data_final)<-"Année"


for (i in 1:ncol(entities)) {

  data_final[,i+1] <- rep(entities[,i],length(unique(years)))

  colnames(data_final)[ncol(data_final)]<- colnames(entities)[i]

}


# Ajouter les colonnes de variables à data_final

for (i in unique(variable_names)) {

  variable <- c()

  for (j in sort(unique(years))) {

    temp <- data_filtered[, indices_variable[variable_names == i & years == j]]

    if (length(temp) == 0) {

      temp <- rep(NA, nrow(entities))

    }

    variable <- c(variable, temp)

  }

  data_final <- cbind(data_final, variable)

  colnames(data_final)[ncol(data_final)] <- i

}