Considérez un df comme celui-ci:
df <- data.frame(colA = 1:10, colB = 50:59, colC = 100:109, colD = letters[1:10])
Je veux transformer la variable "colA" puis calculer une somme en ligne de variables que je choisis par select () code > à l'intérieur de mutate () . Je fais ceci:
df %>% mutate(colA = colA * 60) %>% mutate(sum = rowSums(select(., colA, colB, colC))) colA colB colC colD sum 1 60 50 100 a 210 2 120 51 101 b 272 3 180 52 102 c 334 4 240 53 103 d 396 5 300 54 104 e 458 6 360 55 105 f 520 7 420 56 106 g 582 8 480 57 107 h 644 9 540 58 108 i 706 10 600 59 109 j 768
qui me donne un résultat incorrect:
df %>%
mutate(colA_mod = colA * 60,
sum = rowSums(select(., colA_mod, colB, colC)))
Si je crée une toute nouvelle variable :
colA colB colC colD sum 1 60 50 100 a 151 2 120 51 101 b 154 3 180 52 102 c 157 4 240 53 103 d 160 5 300 54 104 e 163 6 360 55 105 f 166 7 420 56 106 g 169 8 480 57 107 h 172 9 540 58 108 i 175 10 600 59 109 j 178
J'obtiens:
Erreur: erreur d'évaluation: la position doit être comprise entre 0 et n.
Cependant, lorsque j'utilise deux mutate () s séparés, j'obtiens les bons résultats:
df %>%
mutate(colA = colA * 60,
sum = rowSums(select(., colA, colB, colC)))
Donc la question est, comment puis-je transformer une variable / créer une nouvelle variable et la sélectionner dans un mutate () ?
Exemple de données :
colA colB colC colD 1 1 50 100 a 2 2 51 101 b 3 3 52 102 c 4 4 53 103 d 5 5 54 104 e 6 6 55 105 f 7 7 56 106 g 8 8 57 107 h 9 9 58 108 i 10 10 59 109 j
3 Réponses :
Une option consiste à ajouter colA séparément
rowSums(select(., colA_mod, colB, colC))
Lorsque vous utilisez select (., colA, colB, colC) , . est la trame de données d'origine et les colonnes sélectionnées proviennent également de la trame de données d'origine. Par conséquent, il ne dispose pas d'informations sur les valeurs mises à jour de colA . C'est la même raison pour laquelle vous obtenez l'erreur lors de votre deuxième tentative
library(dplyr)
df %>%
mutate(colA = colA * 60,
sum = rowSums(select(., colB, colC)) + colA)
# colA colB colC colD sum
#1 60 50 100 a 210
#2 120 51 101 b 272
#3 180 52 102 c 334
#4 240 53 103 d 396
#5 300 54 104 e 458
#6 360 55 105 f 520
#7 420 56 106 g 582
#8 480 57 107 h 644
#9 540 58 108 i 706
#10 600 59 109 j 768
car la colonne colA_mod ne fait pas partie du dataframe d'origine ( df ).
Possibilité très élégante! Cependant, je suis toujours curieux de savoir s'il existe un moyen de mettre à jour le df original référencé par . dans select () .
Le fait de changer rowSums et select fera le travail:
colA colB colC colD sum 1 1 50 100 a 210 2 2 NA 101 b 221 3 3 52 102 c 334 4 4 53 103 d 396 5 5 54 104 e 458 6 6 55 105 f 520 7 7 56 106 g 582 8 8 57 107 h 644 9 9 58 108 i 706 10 10 59 109 j 768
Si vous avez des NA, mettez-les d'abord à zéro. se comporte comme et na.rm:
df %>%
mutate(sum = rowSums(select(., colA:colC) *
matrix(rep(c(60,1,1), times = 10), byrow = T, ncol = 3), na.rm = T))
Sinon, voici une solution qui autorise rowSums et une mutation:
df %>%
replace(is.na(.), 0) %>%
mutate(colA = colA * 60,
sum = colA + colB + colC)
Cela pourrait être une possibilité, cependant, dans mes données réelles, j'ai aussi des NA. Il est beaucoup plus pratique d'ajouter na.rm = TRUE dans rowSums () .
@tmfmnk a trouvé une solution qui permet aux rowSums
Le . est un espace réservé pour ce qui a été envoyé dans le tube. Dans ce cas, votre mutation de colA ne met pas à jour ce qui est dans le pipeline dans l'appel mutate .
Vous pouvez ajouter un autre tube:
df %>% mutate(colA = colA * 60)%>% mutate(sum = rowSums(select(., colA, colB, colC)))
Merci, cependant, j'ai également inclus cette possibilité dans ma question :) De plus, je veux vraiment le faire en un seul mutate () .
Oops. En gros, cependant, vous ne pouvez pas faire ce que vous voulez. Le . ne sera pas mis à jour avant le prochain tube avant %>% .