2011-04-01 5 views
2

Je suis aux prises avec un peu de code. Je peux le faire fonctionner très inefficacement, mais je pensais qu'il devait y avoir une meilleure façon de le réparer. J'essaie de compiler une variable à partir de plusieurs variables différentes. Dans les variables codées, un "saut" est codé comme un nombre spécifique (pour l'exemple ci-dessous "99"). J'essaie de créer une variable de coût total basée sur 10 de ces variables.Amélioration du codage R avec l'aide Sapply

De cette façon, je fait le code inefficace qui fonctionne par:

var1 <- ifelse(data$v1<99, data$v1, 0) 
var2 <- ifelse(data$v2<99, data$v2, 0) 
... 
var10 <- ifelse(data$v1<99, data$v10, 0) 
sumvar <- var1 + var2 + var3 + var4 + var5 + var6 + var7 + var8 + var9 + var10 

J'ai essayé d'utiliser la commande sapply pour en faire un peu plus élégant et il n'a pas fonctionné. J'essayais juste de voir si quelqu'un pouvait me donner des indices ou aider à comprendre pourquoi mon code échouait. Je l'ai mis dans un environnement de liste (ce que je pense est correct après avoir essayé d'autres comme cbind) et essayer de faire un appel spécifique, mais obtenir une erreur. Comme exemple de code, je mis en place les éléments suivants:

set.seed(1234) 
data <- data.frame(x=rnorm(30), y=rnorm(30), z=rnorm(30)) 
data$x <- ifelse(data$x > 1, 99, data$x) 
data$y <- ifelse(data$y > 1, 99, data$y) 
data$z <- ifelse(data$z > 1, 99, data$z) 

t.list <- list(data$x, data$y, data$z) 

sumvar1 <- sapply(1:length(t.list), function(i){ 
    tempvar <- ifelse(t.list[i] !=99, t.list[i], 0) 
    sumvar1 <- sumvar1 + tempvar 
}) 

Le problème est que quand je fais de mon code réel (ou code), je reçois:

Error in storage.mode(test) <- "logical" : 
    (list) object cannot be coerced to type 'double' 
Calls: sapply -> lapply -> FUN -> ifelse 

Il est évident que je fais quelque chose mal, mais je ne suis pas sûr de ce que c'est. J'ai regardé le fichier d'aide pour ifelse, mais je ne comprends pas le message d'erreur qui est sorti. J'ai eu le code pour fonctionner de manière inefficace, mais j'aimerais vraiment avoir des commentaires et des connaissances sur la façon d'améliorer mon futur codage dans R.

Merci!

Répondre

4

Si c'est la même valeur (99) pour toutes les variables de votre data.frame, il suffit d'opérer sur l'ensemble du data.frame en même temps.

> sum(data*(data < 99)) 
[1] -39.68282 

Si vous voulez la ligne résume

rowSums(data*(data < 99)) # faster than apply(data*(data < 99), 1, sum) 

si vous voulez résume colonne

colSums(data*(data < 99)) # faster than apply(data*(data < 99), 2, sum) 
+0

+1 Excellente réponse;) Je ne savais pas si Tony voulait la somme totale ou la somme des lignes. – csgillespie

+0

@csgillespie: Je pense que tu as raison; il veut les sommes de la rangée. –

+0

Merci pour l'aide! Je vais regarder ça. Le seul problème que j'ai, c'est que ces valeurs que je résume ne sont qu'une partie d'un ensemble de données beaucoup plus grand. Je pense que, si rien d'autre, c'est une façon de simplifier mon code en les codant dans un data.frame plus petit et en faisant les applications comme vous l'avez suggéré. Merci encore – Tony

4

Si je comprends votre problème correctement, je pense que tout ce que vous devez faire est:

## Set any skip values to be equal to zero 
data[data == 99] = 0 
## Work out the row means 
apply(data, 1, sum) 

Un commentaire t. Vous pensez à utiliser l'objet valeur manquante de R NA au lieu de régler 99 à 0.

+2

OP: notez que si vous réglez '99' sur' NA' vous aurez besoin de 'apply (data, 1, sum, na.rm = TRUE)' –