Soustraction par groupe

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

Stéphane Pelletier
Messages : 16
Enregistré le : 04 Déc 2017, 06:28

Soustraction par groupe

Messagepar Stéphane Pelletier » 04 Déc 2017, 10:34

Bonjour,

Voila mon problème : J'ai trois vecteurs organisé comme suit:

data<-c(3,2,1,4,1,5,2,4,7,3,5,2,3,6,2)
fluo<-c(1,1,0,0,NA,1,1,0,0,NA,1,1,0,0,NA)
chan<-c("chan_1","chan_1","chan_1","chan_1","chan_1","chan_2","chan_2","chan_2","chan_2","chan_2","chan_3","chan_3","chan_3","chan_3","chan_3").

Je souhaiterais soustraire la valeur "data" qui a pour "fluo" NA aux autres valeurs de data et par "chan".

Pour cela j'ai créer la fonction suivante, puis j'applique la fonction tapply

Code : Tout sélectionner

sous<-function(x){
reslt=x-x[is.na(fluo)==T]
return(reslt)
}
tapply(data,chan,sous)


Et voila ce que me renvoie R

Code : Tout sélectionner

$chan_1
[1]  2 NA NA  3 NA

$chan_2
[1]  2 NA NA  4 NA

$chan_3
[1]  3 NA NA  4 NA

Warning messages:
1: In x - x[is.na(fluo) == T] :
  la taille d'un objet plus long n'est pas multiple de la taille d'un objet plus court
2: In x - x[is.na(fluo) == T] :
  la taille d'un objet plus long n'est pas multiple de la taille d'un objet plus court
3: In x - x[is.na(fluo) == T] :
  la taille d'un objet plus long n'est pas multiple de la taille d'un objet plus court
>


En fait, ça semble bon, juste que je ne comprend pas pourquoi pour certaine valeur, il me renvoie des NA.

Par avance, merci.

Stéphane

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

Re: Soustraction par groupe

Messagepar Pierre-Yves Berrard » 04 Déc 2017, 10:53

Bonjour,

L'explication de l'erreur :

Quand tapply appelle "sous", x est différent pour chaque "chan", mais "fluo" est l'ensemble du vecteur (15 valeurs). Donc il trouve plusieurs NA et refuse de soustraire car les longueurs ne correspondent pas.
PY

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

Re: Soustraction par groupe

Messagepar Serge Rapenne » 04 Déc 2017, 11:10

Bonjour,

Je n'aurais pas mieux dit que Pierre-Yves.

Une solution pour faire ce que tu veux avec le package dplyr

Code : Tout sélectionner

library(dplyr)
data<-c(3,2,1,4,1,5,2,4,7,3,5,2,3,6,2)
fluo<-c(1,1,0,0,NA,1,1,0,0,NA,1,1,0,0,NA)
chan<-c("chan_1","chan_1","chan_1","chan_1","chan_1","chan_2","chan_2","chan_2","chan_2","chan_2","chan_3","chan_3","chan_3","chan_3","chan_3")
df<-data.frame(data,fluo,chan)

df<-df %>% group_by(chan) %>% mutate(data_sub=data-data[is.na(fluo)])
df

# A tibble: 15 x 4
# Groups:   chan [3]
    data  fluo   chan data_sub
   <dbl> <dbl>  <chr>    <dbl>
 1     3     1 chan_1        2
 2     2     1 chan_1        1
 3     1     0 chan_1        0
 4     4     0 chan_1        3
 5     1    NA chan_1        0
 6     5     1 chan_2        2
 7     2     1 chan_2       -1
 8     4     0 chan_2        1
 9     7     0 chan_2        4
10     3    NA chan_2        0
11     5     1 chan_3        3
12     2     1 chan_3        0
13     3     0 chan_3        1
14     6     0 chan_3        4
15     2    NA chan_3        0


Serge

Stéphane Pelletier
Messages : 16
Enregistré le : 04 Déc 2017, 06:28

Re: Soustraction par groupe

Messagepar Stéphane Pelletier » 04 Déc 2017, 13:27

Merci Pierre-Yves et Serge.

En fait, mon code initial était :

Code : Tout sélectionner

new_data<-function(data){
vector_table_chan=as.vector(table(chan))
bg_fluo=data[is.na(fluo)==T]
vector_bg_fluo=rep(bg_fluo,vector_table_chan)
reslt_fluo_net<-c(data-vector_bg_fluo)
return(reslt_fluo_net)
}


Il marche parfaitement bien. Je suis juste obliger de m'assurer que les data sont dans le bon ordre (mais ça reste un détail). Seulement, je le trouve un peu "lourd"
J'avais espérer qu'avec le code plus simple que je vous ai présenté avant, ça marche.
Je vais voir du coté du packages "dplyr".

En tout cas, merci de vos réponses.

Bonne journée.

Stéphane

Gabriel Terraz
Messages : 591
Enregistré le : 26 Sep 2011, 15:11

Re: Soustraction par groupe

Messagepar Gabriel Terraz » 04 Déc 2017, 14:15

Salut,

Pour rester avec la distri de base, tu peux faire une approche avec split qui revient à faire un tapply (dans la démarche) :

Code : Tout sélectionner

df <- data.frame(data, fluo, chan)
sp <- split(df, chan)
difference <- lapply(sp, function(x) x$data - x$data[is.na(x$fluo)])
data.frame(df, unlist(difference))

Stéphane Pelletier
Messages : 16
Enregistré le : 04 Déc 2017, 06:28

Re: Soustraction par groupe

Messagepar Stéphane Pelletier » 04 Déc 2017, 17:13

Merci Gabriel, ton code marche super bien ;) .

Merci à tous pour votre aide.

Stéphane


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Google [Bot] et 1 invité