sous-groupes

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

Mathilde RIBET
Messages : 15
Enregistré le : 15 Mai 2017, 11:26

sous-groupes

Messagepar Mathilde RIBET » 27 Mai 2017, 14:56

Bonjour !

Voici un aperçu de ma base de données :

Code : Tout sélectionner

      TT1     TT2       TT3     TT4              
1     B        A         D        B            
2     C        B         B        A       
3     B        C         A        A
4     C        A         C        B


Les TT1, TT2... correspondent à des type de traitements donnés dans le temps.
Je voudrais faire 2 groupes :
- groupe A : tous les individus qui ont eu le traitement A avant le B (peu importe ce qu'il s'est passé avant)
- groupe B : tous les individus qui ont eu le traitement B avant le A (peu importe ce qu'il s'est passé avant)

Ici cela me donnerait
- groupe A : ligne 4
- groupe B : lignes 1, 2 et 3

J'aimerais éviter de passer par une boucle mais je ne vois pas comment ?

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

Re: sous-groupes

Messagepar Serge Rapenne » 27 Mai 2017, 19:43

Bonjour,

une solution possible si A et B sont forcement présent dans chaque ligne

Code : Tout sélectionner

dta
  TT1 TT2 TT3 TT4
1   B   A   D   B
2   C   B   B   A
3   B   C   A   A
4   C   A   C   B

dta$grp<-apply(dta,1,function(x) ifelse(min(which(x=="A"))<min(which(x=="B")),"Grp1","Grp2"))
dta
  TT1 TT2 TT3 TT4  grp
1   B   A   D   B Grp2
2   C   B   B   A Grp2
3   B   C   A   A Grp2
4   C   A   C   B Grp1


Serge

Mathilde RIBET
Messages : 15
Enregistré le : 15 Mai 2017, 11:26

Re: sous-groupes

Messagepar Mathilde RIBET » 27 Mai 2017, 21:02

Merci Serge.

Je n'ai pas fait attention mais mon exemple est mauvais car il y a en effet des lignes contenant uniquement A (ou uniquement B), voire aucun des deux (mais je peux facilement extraire un sous-groupe contenant au moins un des deux traitement)

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

Re: sous-groupes

Messagepar Serge Rapenne » 28 Mai 2017, 18:05

dans ce cas tu peux changer le apply comme ça :

Code : Tout sélectionner

dta$grp<-apply(dta,1,function(x) ifelse("A" %in% x && "B" %in% x && min(which(x=="A"))<min(which(x=="B")),"Grp1","Grp2"))

avec ce code si "A" ou "B" sont absents, c'est le Grp2 qui est sélectionné. Attention à bien doubler les & pour arrêter l'évaluation dés qu'une conditions est à FALSE, sans cela le code va retourner un warning pour les lignes sans "A" ou "B"

Serge

Edit : il est possible d’alléger le test comme ça :

Code : Tout sélectionner

dta$grp<-apply(dta,1,function(x) ifelse( all(c("A","B") %in% x) && min(which(x=="A"))<min(which(x=="B")),"Grp1","Grp2"))

Mathilde RIBET
Messages : 15
Enregistré le : 15 Mai 2017, 11:26

Re: sous-groupes

Messagepar Mathilde RIBET » 28 Mai 2017, 21:11

Super merci beaucoup !

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: sous-groupes

Messagepar Logez Maxime » 29 Mai 2017, 14:00

Bonjour,

une solution alternative :

Code : Tout sélectionner

auxi <- do.call(paste0, dta)
gr <- rep(2, length(auxi))
gr[grep("^[^B]*A.*B", auxi)] <- 1
Cordialement,
Maxime

Mathilde RIBET
Messages : 15
Enregistré le : 15 Mai 2017, 11:26

Re: sous-groupes

Messagepar Mathilde RIBET » 30 Mai 2017, 22:06

Merci à tous les deux.

J'ai encore 'autres questions du même type.
Je débute avec R, je me rends compte que je n'ai pas compris comment fonctionne le apply.
Je veux maintenant comparer 2 dates

Code : Tout sélectionner

TT1      date_1     TT2       date_2      TT3    date_3
A      10/01/2001    B     02/09/2005     C    21/05/2006
C      12/04/2011    A     02/07/2010     C    24/03/2004
C      08/01/2001    B     05/10/2005     A    13/05/2006


Je veux récupérer la date qui suit le premier "B" (il s'agit forcément d'une date) trouvé dans chaque ligne et la comparer à une autre date que je connais (appelons la date_ref). Selon le résultat (inférieur ou supérieur) je fais deux groupes.
Voici mon code

Code : Tout sélectionner

data$gr<-apply(data,1,function(x) ifelse x[min(which(x=="B"))+1]>date_ref,"GR1","GR2")


Visiblement ce n'est pas la bonne manière de faire, j'aimerais comprendre ce qui ne va pas.

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

Re: sous-groupes

Messagepar Pierre-Yves Berrard » 31 Mai 2017, 06:17

Bonjour,

Il semble manquer des parenthèses dans l'écriture de ifelse().

Ceci dit, ça ne donnera sûrement pas le résultat attendu après cette correction. En effet, apply() attend une matrice (données homogènes) en premier argument. Donc, la première chose qu'il va faire est convertir toutes les colonnes en caractères (type le plus flexible), y compris les dates.
Du coup, il va essayer de comparer non pas des dates mais des chaînes de caractères.
PY

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: sous-groupes

Messagepar Logez Maxime » 31 Mai 2017, 07:43

Bonjour,

Une solution :

Code : Tout sélectionner

# récupération de la colonne des dates qui suivent le 1er B
auxi <- do.call(paste0, tab[grep("^TT", colnames(tab))])
auxi <- regexpr("B", auxi)
auxi <- auxi * 2
auxi[auxi < 0] <- NA

# les dates suivant le 1er B
d1 <- tab[cbind(seq_along(auxi), auxi)]
# si ce ne sont pas des dates il faut les transformer au format Date
d1 <- as.Date(d1, format = "%d/%m/%Y")

# pour l'exemple date_ref 30/09/2005
date_ref <- as.Date("2005-09-30")

# la définition des groupes
gr <- rep("GR2", nrow(tab))
gr[d1 > date_ref] <- "GR1"
gr[is.na(d1)] <- NA
Pour ce qui est de l'explication du apply donnée par Pierre-Yves, elle n'est pas tout à fait exacte. Apply peut prendre pour premier argument un data.frame ou une matrice, mais comme la soulignée Pierre-Yves cette fonction ne va travailler que sur des données homogènes. Elle va convertir le data.frame en array (matrice si que deux dimensions). Comme les arrays ne supportent qu'un seul type de valeurs elles vont être harmonisées. Les dates si elles sont stockées sous ce format vont être transformées en chaîne de caractères.

Cordialement,
Maxime

Mathilde RIBET
Messages : 15
Enregistré le : 15 Mai 2017, 11:26

Re: sous-groupes

Messagepar Mathilde RIBET » 31 Mai 2017, 16:14

Bonjour,

Merci de vos réponses.
Maxime, cette solution ne marche pas sur mes données (du moins pas toujours, 2 fois sur 3 la date renvoyée n'est pas la bonne date... voire même le code me renvoie le nom d'un traitement et pas une date).

Cela fait seulement quelques jours que je me suis mise à R, je trouve cela un peu compliqué!
Du coup, j'ai essayé de convertir mes colonnes en chaînes de caractères :

Code : Tout sélectionner

dta<-apply(dta,2,function(x) as.character(x))


Mais ensuite je ne vois pas comment faire pour qu'il compare numériquement deux chaînes de caractères ?

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Re: sous-groupes

Messagepar Logez Maxime » 01 Juin 2017, 07:19

Bonjour,

Il est difficile de donner un code qui s'adapte à toutes les situations. Le code que je t'ai donné fonctionne sur l'exemple que tu as donné. Si ton tableau est structuré différemment alors ça peut poser problème. Voici un code qui devrait être plus générique :

Code : Tout sélectionner

auxi <- do.call(paste0, tab[grep("^TT", colnames(tab))])
auxi <- regexpr("B", auxi)
auxi[auxi < 0] <- NA
auxi <- grep("^date_", colnames(tab))[auxi]

d1 <- tab[cbind(seq_along(auxi), auxi)]
# si ce ne sont pas des dates il faut les transformer au format Date
d1 <- as.Date(d1, format = "%d/%m/%Y")

# pour l'exemple date_ref 30/09/2005
date_ref <- as.Date("2005-09-30")

# la définition des groupes
gr <- rep("GR2", nrow(tab))
gr[d1 > date_ref] <- "GR1"
gr[is.na(d1)] <- NA
Pour ce qui est de la comparaison de chaîne de caractères ça doit pouvoir se faire mais il te faut réorganiser tes dates dans un format AAAAMMJJ sinon tu auras de mauvaises surprises.

Cordialement,
Maxime


Retourner vers « Questions en cours »

Qui est en ligne

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