web-dev-qa-db-fra.com

ifelse ne fait rien en R

Je suis un programmeur R très novice et j'essaie de convertir l'ancien code SAS en R. Je dois remplacer les valeurs en fonction d'une condition, et si la condition est fausse, laissez-les seules. J'ai googlé cela et essayé plusieurs des solutions affichées, mais en vain. La raison pour laquelle je fais cela est de classer la première instance d'un événement (dans ce cas, les médecins rédigent une ordonnance). si le premier mois où ils ont écrit une ordonnance était le mois de mai de l'année dernière, leur mois de début (rédacteur) était de 5. Si c'était en juin, puis de 6 ans, etc. débutant (newwriter) si une ordonnance antérieure est trouvée. Si aucune ordonnance antérieure n'est trouvée, je veux laisser le numéro seul. C'est le code que j'utilise:

newwriters$newwriter=ifelse(newwriters$MTRx_06_30_2017>0,18,NULL)
newwriters$newwriter=ifelse(newwriters$MTRx_05_31_2017>0,17,NULL)
newwriters$newwriter=ifelse(newwriters$MTRx_04_30_2017>0,16,NULL)
newwriters$newwriter=ifelse(newwriters$MTRx_03_31_2017>0,15,NULL)
newwriters$newwriter=ifelse(newwriters$MTRx_02_28_2017>0,14,NULL)
newwriters$newwriter=ifelse(newwriters$MTRx_01_31_2017>0,13,NULL)
newwriters$newwriter=ifelse(newwriters$MTRx_12_31_2016>0,12,NULL)
newwriters$newwriter=ifelse(newwriters$MTRx_11_30_2016>0,11,NULL)
newwriters$newwriter=ifelse(newwriters$MTRx_10_31_2016>0,10,NULL)

Le problème est qu’il continue de changer les valeurs les plus élevées en 0 s’il ne trouve pas de prescription ce mois-ci. Je veux juste laisser les valeurs seules. J'ai également essayé toutes les solutions suivantes sans succès:

newwriters$newwriter=ifelse(newwriters$MTRx_06_30_2017>0,18,newwriters$newwriter)
newwriters$newwriter=ifelse(newwriters$MTRx_06_30_2017>0,18,newwriters[,16])
newwriters$newwriter=ifelse(newwriters$MTRx_06_30_2017>0,18,)

Comme je l'ai mentionné, je suis novice en écriture de code R. Je suis sûr qu'il existe un moyen meilleur/plus rapide/plus efficace de le faire, mais je ne sais pas quoi essayer d'autre. Merci d'avance pour votre aide!

5
Kevin.C

Si vous souhaitez modifier conditionnellement une colonne (ou un vecteur) et laisser les entrées inchangées lorsque la condition n'est pas remplie, vous pouvez probablement aussi vous passer de ifelse.

Considérons les deux vecteurs suivants:

a = c(1,2,3,4,5)
b = c(1,1,1,1,1)

Maintenant, supposons que nous voulions remplacer les valeurs dans b par 2, si la valeur dans a est supérieure à 3. Voici deux façons de réaliser ce que vous voulez:

b[a>2] = 2
b = ifelse(a>3,2,b)

Ils aboutiront tous deux à b étant 1 1 2 2 2. Cependant, remplaçons maintenant l'une des valeurs dans a, par NA, disons;

a = c(1,2,NA,4,5)

Maintenant, comparez les résultats des deux extraits suivants:

b = c(1,1,1,1,1)
b[a>2] = 2
# 1 1 1 2 2

et

b = c(1,1,1,1,1)
b = ifelse(a>3,2,b)
# 1  1 NA  2  2

La raison intuitive en est que NA>3 ne renvoie pas TRUE ou FALSE, mais NA, donc ifelse ne sait pas lequel des deux champs doit être renvoyé. Lorsque b[a>2] est utilisé, nous ne remplaçons que les valeurs où a>2 est TRUE, et puisque NA n'est pas TRUE, la valeur de la troisième entrée n'est tout simplement pas modifiée.


Donc, dans votre cas particulier,

writers$newwriter=ifelse(newwriters$MTRx_06_30_2017>0,18,newwriters$newwriter)

ne fonctionne probablement pas comme prévu car il y a des valeurs NULL ou NA dans ces colonnes. Si vous voulez utiliser ifelse, vous pouvez faire quelque chose comme:

writers$newwriter=ifelse(newwriters$MTRx_06_30_2017>0 & !is.na(newwriters$MTRx_06_30_2017),18,newwriters$newwriter)

mais vous pourriez aussi envisager de faire

writers$newwriter[newwriters$MTRx_06_30_2017>0] = 18

J'espère que cela t'aides!

4
Florian

Mieux vaut utiliser if_else du paquet dplyr . Il a un traitement explicite pour NAs qui le rend plus robuste et il est aussi légèrement plus rapide.

Exemple rapide:

> library(tidyverse)
> iris2 = iris %>% as_data_frame()
> 
> #add some NA's
> iris2$Sepal.Length[c(1, 5, 8)] = NA
> 
> #print
> iris2
# A tibble: 150 x 5
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          <dbl>       <dbl>        <dbl>       <dbl> <fct>  
 1        NA           3.50         1.40       0.200 setosa 
 2         4.90        3.00         1.40       0.200 setosa 
 3         4.70        3.20         1.30       0.200 setosa 
 4         4.60        3.10         1.50       0.200 setosa 
 5        NA           3.60         1.40       0.200 setosa 
 6         5.40        3.90         1.70       0.400 setosa 
 7         4.60        3.40         1.40       0.300 setosa 
 8        NA           3.40         1.50       0.200 setosa 
 9         4.40        2.90         1.40       0.200 setosa 
10         4.90        3.10         1.50       0.100 setosa 
# ... with 140 more rows
> 
> #conditionally change
> iris2$new_var = if_else(iris2$Sepal.Length > 5, true = 100, false = 0, missing = -100)
> 
> iris2$new_var
  [1] -100    0    0    0 -100  100    0 -100    0    0  100    0    0    0  100  100  100  100  100  100  100  100    0  100    0    0    0
 [28]  100  100    0    0  100  100  100    0    0  100    0    0  100    0    0    0    0  100    0  100    0  100    0  100  100  100  100
 [55]  100  100  100    0  100  100    0  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100
 [82]  100  100  100  100  100  100  100  100  100  100  100  100    0  100  100  100  100  100  100  100  100  100  100  100  100    0  100
[109]  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100
[136]  100  100  100  100  100  100  100  100  100  100  100  100  100  100  100

Nous avons donc créé une nouvelle variable où les valeurs supérieures à 5 sont passées à 100, inférieures à 5 à 0 et NA à -100.

0
Deleet