cheatsheet - dplyr:: mutate(asignar na.rm=TRUE)
sum by group in r (3)
Tengo un data.frame que tiene 100 variables. Quiero obtener la suma de tres variables solo usando mutate
(no summarise
).
Si hay NA en cualquiera de las 3 variables, aún quiero obtener la sum
. Para hacer esto usando mutate
, reemplacé todos los valores de NA
con 0
usando ifelse
luego obtuve la sum
.
library(dplyr)
df %>% mutate(mod_var1 = ifelse(is.na(var1), 0, var1),
mod_var2 = ifelse(is.na(var2), 0, var2),
mod_var3 = ifelse(is.na(var3), 0, var3),
sum = (mod_var1+mod_var2+mod_var3))
¿Hay alguna forma mejor (más corta) de hacer esto?
DATOS
df <- read.table(text = c("
var1 var2 var3
4 5 NA
2 NA 3
1 2 4
NA 3 5
3 NA 2
1 1 5"), header =T)
Donde mejor = tidyr
:
df %>%
mutate(rn = row_number()) %>%
gather(var, varNum, var1:var3) %>%
group_by(rn) %>%
mutate(sum = sum(varNum, na.rm = TRUE)) %>%
spread(var, varNum)
En caso de que su conjunto de datos esté a punto de crecer ...
Podemos usar Reduce
con +
df %>%
mutate_each(funs(replace(., is.na(.), 0)), var1:var3) %>%
mutate(Sum = Reduce(`+`, .))
# var1 var2 var3 Sum
#1 4 5 0 9
#2 2 0 3 5
#3 1 2 4 7
#4 0 3 5 8
#5 3 0 2 5
#6 1 1 5 7
O con rowSums
df %>%
mutate(Sum = rowSums(.[names(.)[1:3]], na.rm = TRUE))
# var1 var2 var3 Sum
#1 4 5 NA 9
#2 2 NA 3 5
#3 1 2 4 7
#4 NA 3 5 8
#5 3 NA 2 5
#6 1 1 5 7
Puntos de referencia
set.seed(24)
df1 <- as.data.frame(matrix(sample(c(NA, 1:5), 1e6 *3, replace=TRUE),
dimnames = list(NULL, paste0("var", 1:3)), ncol=3))
system.time({
df1 %>% rowwise() %>% mutate(Sum = sum(c(var1, var2, var3), na.rm = TRUE))
})
# user system elapsed
# 21.50 0.03 21.66
system.time({
df1 %>%
mutate(rn = row_number()) %>%
gather(var, varNum, var1:var3) %>%
group_by(rn) %>%
mutate(sum = sum(varNum, na.rm = TRUE)) %>%
spread(var, varNum)})
# user system elapsed
# 5.96 0.39 6.37
system.time({
replace(df1, is.na(df1), 0) %>% mutate(sum = var1 + var2 + var3)
})
# user system elapsed
# 0.17 0.01 0.19
system.time({
df1 %>%
mutate_each(funs(replace(., is.na(.), 0)), var1:var3) %>%
mutate(Sum = Reduce(`+`, .))
})
# user system elapsed
# 0.10 0.02 0.11
system.time({
df1 %>%
mutate(Sum = rowSums(.[names(.)[1:3]], na.rm = TRUE))
})
# user system elapsed
# 0.04 0.00 0.03
rowwise()
es mi función de rowwise()
. Es como group_by()
pero trata cada fila como un grupo individual.
df %>% rowwise() %>% mutate(Sum = sum(c(var1, var2, var3), na.rm = TRUE))