web-dev-qa-db-fra.com

Boucle sur des lignes de la fonction d'application de trame de données avec l'instruction if

Je suis nouveau dans R et j'essaie de résumer 2 colonnes d'une trame de données donnée, si les deux éléments à additionner remplissent une condition donnée. Pour clarifier les choses, ce que je veux faire, c'est:

> t.d<-as.data.frame(matrix(1:9,ncol=3))
> t.d
  V1 V2 V3
  1  4  7  
  2  5  8  
  3  6  9  

> t.d$V4<-rep(0,nrow(t.d))

> for (i in 1:nrow(t.d)){
+   if (t.d$V1[i]>1 && t.d$V3[i]<9){
+     t.d$V4[i]<-t.d$V1[i]+t.d$V3[i]}
+     }

> t.d    
  V1 V2 V3 V4
  1  4  7  0
  2  5  8 10
  3  6  9  0

J'ai besoin d'un code efficace, car mon véritable dataframe a environ 150000 lignes et 200 colonnes. Cela donne une erreur:

t.d$V4<-t.d$V1[t.d$V1>1]+ t.d$V3[t.d$V3>9] 

"Appliquer" est-il une option? J'ai essayé ceci:

t.d<-as.data.frame(matrix(1:9,ncol=3))
t.d$V4<-rep(0,nrow(t.d))

my.fun<-function(x,y){
  if(x>1 && y<9){
    x+y}
}

t.d$V4<-apply(X=t.d,MAR=1,FUN=my.fun,x=t.d$V1,y=t.d$V3)

mais cela donne aussi une erreur. Merci beaucoup pour votre aide.

32
Elinka

Cette opération ne nécessite pas de boucles, d'appliquer des instructions ou d'instructions if. Des opérations vectorisées et un sous-ensemble suffisent:

t.d <- within(t.d, V4 <- V1 + V3)
t.d[!(t.d$V1>1 & t.d$V3<9), "V4"] <- 0
t.d

  V1 V2 V3 V4
1  1  4  7  0
2  2  5  8 10
3  3  6  9  0

Pourquoi ça marche?

Dans la première étape, je crée une nouvelle colonne qui est la somme directe des colonnes V1 et V4. J'utilise within comme un moyen pratique de se référer aux colonnes de d.f sans avoir à écrire d.f$V tout le temps.

Dans la deuxième étape, je sous-ensemble toutes les lignes qui ne remplissent pas vos conditions et définissez V4 pour celles-ci sur 0.

41
Andrie

ifelse est votre ami ici:

t.d$V4<-ifelse((t.d$V1>1)&(t.d$V3<9), t.d$V1+ t.d$V3, 0)
25
Nick Sabbe

Je prendrai part et fournirai encore une autre version. Puisque vous voulez zéro si la condition ne fonctionne pas, et TRUE/FALSE sont des versions glorifiées de 1/0, la simple multiplication par la condition fonctionne également:

t.d<-as.data.frame(matrix(1:9,ncol=3))
t.d <- within(t.d, V4 <- (V1+V3)*(V1>1 & V3<9))

... et il se trouve que c'est plus rapide que les autres solutions ;-)

t.d <- data.frame(V1=runif(2e7, 1, 2), V2=1:2e7, V3=runif(2e7, 5, 10))
system.time( within(t.d, V4 <- (V1+V3)*(V1>1 & V3<9)) )         # 3.06 seconds
system.time( ifelse((t.d$V1>1)&(t.d$V3<9), t.d$V1+ t.d$V3, 0) ) # 5.08 seconds
system.time( { t.d <- within(t.d, V4 <- V1 + V3); 
               t.d[!(t.d$V1>1 & t.d$V3<9), "V4"] <- 0 } )       # 4.50 seconds
10
Tommy