funcion - Mutaciones condicionales del marco de datos en R con magrittr y dplyr
funcion filter en r (3)
Podrías hacerlo usando mutate_each
y replace
:
df %>% mutate_each(funs(replace(., a==5, nth(., which(b==7)))), x, y)
Salida:
a b x y
1 1 6 11 16
2 2 7 12 17
3 3 8 13 18
4 4 9 14 19
5 5 10 12 17
O según el comentario de @docendodiscimus, se puede acortar aún más (y probablemente [
también es mejor que which
):
df %>% mutate_each(funs(replace(., a==5, .[b==7])), x, y)
Me gustaría usar el sucinto de magrittr y dplyr para copiar valores individuales entre filas en un subconjunto de columnas basadas en los valores de otras columnas. Este es un ejemplo simple; Quiero aplicar esta idea a muchas columnas de un gran conjunto de datos con múltiples condiciones dentro de un largo canal de comandos.
Tome el marco de datos df <- data.frame(a = 1:5, b = 6:10, x = 11:15, y = 16:20)
:
a b x y
1 6 11 16
2 7 12 17
3 8 13 18
4 9 14 19
5 10 15 20
Para la fila donde a = 5
, me gustaría reemplazar los valores de x
e y
con aquellos en la fila donde b = 7
, para dar:
a b x y
1 6 11 16
2 7 12 17
3 8 13 18
4 9 14 19
5 10 12 17
Este intento falla:
foo <- function(x){ifelse(df$a == 5, df[df$b == 7, .(df$x)], x)}
df %<>% mutate_each(funs(foo), x, y)
Lo más cercano que puedo conseguir es:
bar <- function(x){ifelse(df$a == 5, df[df$b == 7, "x"], x)}
df %<>% mutate_each(funs(bar), x, y)
pero esto es incorrecto ya que reemplaza ambos valores con el valor de x
, en lugar de x
e y
respectivamente.
Gracias por el consejo.
Si su principal requisito es aplicar la función dentro de un dplyr-pipe más largo, podría hacer algo como el siguiente ejemplo:
foo <- function(df, cols = c("x", "y")) {
df[df$a == 5, cols] <- df[df$b == 7, cols]
df
}
df %>% ... %>% foo(c("x", "y")) %>% ...
# a b x y
#1 1 6 11 16
#2 2 7 12 17
#3 3 8 13 18
#4 4 9 14 19
#5 5 10 12 17
Solo por mencionar la solución data.table
sería:
require(data.table)
setDT(df)[a == 5, c("x", "y") := df[b == 7, .SD, .SDcols = c("x", "y")]]
> df
a b x y
1: 1 6 11 16
2: 2 7 12 17
3: 3 8 13 18
4: 4 9 14 19
5: 5 10 12 17
Alternativamente, también puedes usar:
cols <- c("x", "y")
setDT(df)[a == 5, (cols) := df[b == 7, .SD, .SDcols = cols]]
# or
cols <- c("x", "y")
setDT(df)[a == 5, (cols) := df[b == 7, cols, with = FALSE]]