Difficultés réorganisation de base de données

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

Clement Corentin
Messages : 44
Enregistré le : 09 Aoû 2011, 08:55

Difficultés réorganisation de base de données

Messagepar Clement Corentin » 22 Nov 2017, 10:36

Bonjour a tous,

Mon problème me parait assez simple mais je suis complément perdu car je n'ai peu ou pas d’expérience dans la réorganisation de données sous R (jusque ici) je préparais mes tables sous excel.

Je dispose d'une grande base de données que j'ai simplifiée ci-dessous:

head(Lucerne)
id; intersection ;depth.cm; grid.m; ri ;crop.sys
1 ; 4 ; 0 ; 0.49 ; 8; Lucerne
1 ; 9 ; 4 ; 0.59 ;18; Lucerne
1 ; 18 ; 8; 0.49; 37; Lucerne
1 ; 9 ; 13; 0.49; 18; Lucerne
2 ; 7 ;17 ; 0.59 ;14; Lucerne
2 ; 29 ;21; 0.49; 59; Lucerne

J'aimerais obtenir une base de données avec en colonne mes "id" (avec une valeur unique de id par niveau), en ligne des classes de profondeur par tranche de 25 cm (i.e. [0-25[; [25-50[; etc.) et comme valeur la somme des "intersections" (comprises au sein de la classe de profondeur) divisée par la somme des valeurs "grid" (également comprises au sein de la classe de profondeur).

Enfin j'aimerais savoir si c'est possible de faire une boucle qui me permettrait de sortir une table similaire pour chaque groupe de culture (i.e. crop.sys) présent au sein de ma table initial.

D'avance je vous remercie pour votre aide. J'ai du mal à décrire ce que je cherche à faire et tombe sur des tutoriels/forums où il s'agit uniquement de transformation "de forme" et pas "de fond" de base de données.

Corentin.

ps: Si quelqu’un peux m'expliquer comment utiliser la fonction [code] pour insérer proprement mes tables sur le forum je suis preneur.

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

Re: Difficultés réorganisation de base de données

Messagepar Pierre-Yves Berrard » 22 Nov 2017, 14:21

Bonjour,

Pour utiliser les balises code, sélectionner une partie du message et cliquer sur "Code", ce qui donnera :

Code : Tout sélectionner

[code]tr_width <- 25[/code]


Pour le problème en-lui même, une solution "tout en un" à l'aide les packages dplyr et tidyr :

Code : Tout sélectionner

library(dplyr)
library(tidyr)

tr_width <- 25
Lucerne %>%
  mutate(depth.cm_tr = depth.cm %/% tr_width * tr_width) %>%  # crée les classes
  group_by(crop.sys, id, depth.cm_tr) %>%                     # groupes pour instuction suivante
  summarise(valeur = sum(intersection) / sum(grid.m)) %>%     # calcule l'indicateur
  spread(id, valeur, sep = "_")                               # met en colonne l'id

À essayer sur une base contenant tous les crop.sys.
PY

Clement Corentin
Messages : 44
Enregistré le : 09 Aoû 2011, 08:55

Re: Difficultés réorganisation de base de données

Messagepar Clement Corentin » 23 Nov 2017, 09:34

Bonjour,

Je tiens à vous remercier pour votre réponse qui répond bien a ma question.

Je me permet de vous reposer quelques questions.

Premièrement, je ne suis pas familier avec les "tibble" et ne vois pas bien comment je peux les utiliser car quand j'appelle ma data.frame (Lucerne) la représentation des données restent inchangées. Est-ce possible d'exporter la table (tibble) formée sous forme de "dataframe"?

Deuxièmement, la séparation par groupe de culture fonctionne bien, néanmoins j'aurais aimé savoir s'il était possible de sortir une table différente pour chaque groupe de culture?

D'avance merci pour votre réponse.
Corentin.

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

Re: Difficultés réorganisation de base de données

Messagepar Serge Rapenne » 23 Nov 2017, 10:11

Bonjour,

un tibble est juste un data.frame encapsulé dans un objet S3, il s'utilise normalement comme un data.frame mais si tu préfères avoir un data.frame, il suffit d'utiliser la commande as.data.frame.

Pour "splitter" un data.frame en plusieurs data.frame selon un identifiant, tu peut faire comme ça :

Code : Tout sélectionner

dta<-data.frame(ID=sample(LETTERS[1:4],10,replace = T),value=runif(10)) #création d'un jeu de données exemple
dta
   ID      value
1   C 0.03661219
2   D 0.96513021
3   A 0.37145737
4   A 0.48096808
5   B 0.55554429
6   D 0.45765338
7   A 0.63812499
8   B 0.26969086
9   B 0.53474959
10  D 0.14221398

#fonction qui extrait d'un data.frame , les lignes qui ont pour ID==id et lui donne le nom de dta_id
#par ex si id="A" extrait dans dta les lignes avec ID=="A" et le place dans un data.frame du nom de dta_A
sous_df<-function(id,dta){
  assign(paste("dta",id,sep="_"),(dta[dta$ID==id,]),envir = .GlobalEnv)
}

lapply(unique(dta$ID),sous_df,dta) #applique la fonction sous_df à toutes les valeurs de ID pour le data.frame dta

 dta_A
  ID     value
3  A 0.3714574
4  A 0.4809681
7  A 0.6381250

dta_B
  ID     value
5  B 0.5555443
8  B 0.2696909
9  B 0.5347496

...


Serge

Clement Corentin
Messages : 44
Enregistré le : 09 Aoû 2011, 08:55

Re: Difficultés réorganisation de base de données

Messagepar Clement Corentin » 29 Nov 2017, 15:27

Bonjour,

Tous d'abord un grand merci a tous les deux pour vos réponses qui me sont très utiles, j'ai bien avancé sur mon problème en revanche j'aimerais aller un peu plus loin dans l'analyse de mes données de manière "automatiques".

En premier lieu, j'ai bien extrait une base de donnée par type de culture avec le code suivant (inspiré de celui de Serge). Le résultat me sort bien 25 bases de données différentes.

Code : Tout sélectionner

#Load data set
data <- as.data.frame(read.csv("~/UCPH/PLEN/Data/R input/Data/TRON_counting_Take_11_3.csv",sep=";",header=TRUE))

#Select column
Take11<-subset(data,select=c(id,intersection,distance,file.distance,depth.cm,grid.m,crop.sys))

#Suppress negative value
Take11<- subset(Take11, as.character(as.numeric(depth.cm))>=0)

#Create one database per crop type
id<-seq(1,40,1)
sous_df<-function(crop.sys,Take11){
  assign(paste("Take11",crop.sys,sep="_"),(Take11[Take11$crop.sys==crop.sys,]),envir = .GlobalEnv)
}
lapply(unique(Take11$crop.sys),sous_df,Take11) #applique la fonction sous_df à toutes les valeurs de ID pour le data.frame dta


Ensuite sur chaque base de données, j'aimerais faire tourner le code suivant (cf. ci-dessous inspiré de celui Pierre-Yves), qui me permet de calculer l'indicateur voulu (intersection) par catégorie de profondeur et de l’intégrer dans une nouvelle base de donnée. Enfin, à partir de la dataframe que j’obtiens je fais un calcul d’écart type et de moyenne puis je représente mes données sur un graphique.

Code : Tout sélectionner

#Packages needed
library(dplyr)
library(tidyr)
library(plotrix)
library(forcats)

#Create dataframe with depth class and calculate intersection
tr_width <- 25
t<-Take11 %>%
  mutate(depth.cm_tr = -depth.cm %/% tr_width * tr_width) %>%  # crée les classes
  group_by(crop.sys, id,depth.cm_tr) %>%                     # groupes pour instuction suivante
  summarise(valeur = sum(intersection) / sum(grid.m)) %>%     # calcule l'indicateur
  spread(id, valeur, sep = "_")

#Remake a dataframe with correct depth classes
t<-as.data.frame(t)
levels <- 15
labels<-c("[350,375[","[325,350[","[300,325[","[275,300[","[250,275[","[225,250[","[200,225[","[175,200[","[150,175[","[125,150[","[100,125[","[75,100[","[50,75[","[25,50[","[0,25[")
group = cut(t$depth.cm_tr,levels,labels=labels, right=FALSE)
t$DClass =(group)

#Change data frame from wide to long format
data_long <- gather(t,id,measurement,id_2:id_17, factor_key=TRUE)

#Calculate the mean and standard error
summary_crop<-as.data.frame(summarise(group_by(data_long,depth.cm_tr,DClass),
          mean=mean(measurement,na.rm=TRUE), sd=sd(measurement,na.rm=TRUE)))
arrange(summary_crop, -row_number())      #inverse row order

#Plot the results (Mean and St dev)
par(mar=c(2,5,7,5))
a<-plot(summary_crop$mean,summary_crop$depth.cm_tr,type="b",main="",xaxt="n",xlab="",yaxt="n",ylab="Depth(cm)",xlim=c(-10,100))
axis(3,cex.axis=1.5,labels="Mean root intensity for XX", at=45,line=3,tick=FALSE)
axis(3,cex=0.8)
axis(3,labels="Mean root intensity (intersections/cm of gridline)",at=45,tick=FALSE,line=1.5)
axis(2,las=TRUE)

y=summary_crop$depth.cm_tr
avg=summary_crop$mean
sdev=summary_crop$sd
arrows(avg-sdev,y,avg+sdev,y,length=0.03,angle=90,code=3)


Ma question est la suivante comment puis-je faire pour automatiser la lecture de ce code (2nd code) sur chaque data frame qui "sort" de ma base de donnée initiale (1er code)?

Je tiens à préciser que le nombre de modalités (id) varie d'un culture à une autre, ainsi je dois pour chaque data.frame extraire les id présent au sein de cette dernière afin de pouvoir les référencer dans le code suivant

Code : Tout sélectionner

data_long <- gather(t,id,measurement,id_2:id_17, factor_key=TRUE)
.

Enfin, et si cette boucle fonctionne est-il possible d'automatiser la création d'une fenêtre graphique contenant, au minimum, le nombre de base de données distinctes afin d'avoir une représentation globale de mes données avec chaque cultures représentées dans un graphique/portion unique de ma fenêtre graphique.

Comme vous l'aurez compris je cherche à automatiser la lecture d'une base de donnée qui sera mise à jours de manière récurrente afin d’éviter un laborieux travail d'analyse. Si le sujet s’écarte trop du titre de ce poste je peux le reposter si cela pose problème.

Je vous remercie d'avance pour l'aide que vous pourriez m'apporter, c'est la première que j'envisage d'utiliser R de cette manière (boucle automatique) et suis preneur de tous conseils.

Corentin.


Retourner vers « Questions en cours »

Qui est en ligne

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