mtcars - Reemplazo condicional de valores en un data.frame
r data frame mtcars (6)
Aquí está mi solución con otra versión para resolver mi problema con if y max en row-wise.
my.assign <- function(col1, col2, col3){
if(col2==0) {col3 <- col1} else {
col3 <- 0
}
}
my.max <- function(col1, col2, col3){
if(col1 >= 10 ) {max_r <- max(col2, col3, na.rm=TRUE)}
else { max_r <- col2 }
}
df$est <- with(df,mapply(my.assign,col1=a, col2=b, col3=est))
df$max_row <- with(df,mapply(my.max,col1=a, col2=b, col3=est))
> df
a b est max_row
1 11.77000 2 0.000 2.00
2 10.90000 3 0.000 3.00
3 10.32000 2 0.000 2.00
4 10.96000 0 10.960 10.96
5 9.90600 0 9.906 0.00
6 10.70000 0 10.700 10.70
7 11.43000 1 0.000 1.00
8 11.41000 2 0.000 2.00
9 10.48512 4 0.000 4.00
10 11.19000 0 11.190 11.19
Estoy tratando de entender cómo reemplazar valores condicionales en un marco de datos sin usar un bucle. Mi marco de datos está estructurado de la siguiente manera:
> df
a b est
1 11.77000 2 0
2 10.90000 3 0
3 10.32000 2 0
4 10.96000 0 0
5 9.90600 0 0
6 10.70000 0 0
7 11.43000 1 0
8 11.41000 2 0
9 10.48512 4 0
10 11.19000 0 0
y la salida de dput
es esta:
structure(list(a = c(11.77, 10.9, 10.32, 10.96, 9.906, 10.7,
11.43, 11.41, 10.48512, 11.19), b = c(2, 3, 2, 0, 0, 0, 1, 2,
4, 0), est = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)), .Names = c("a",
"b", "est"), row.names = c(NA, -10L), class = "data.frame")
Lo que quiero hacer es verificar el valor de b
. Si b
es 0, quiero establecer est
en un valor de a
. Entiendo que df$est[df$b == 0] <- 23
establecerá todos los valores de est
en 23, cuando b==0
. Lo que no entiendo es cómo establecer est
en un valor de a
cuando esa condición es verdadera. Por ejemplo:
df$est[df$b == 0] <- (df$a - 5)/2.533
da la siguiente advertencia:
Warning message:
In df$est[df$b == 0] <- (df$a - 5)/2.533 :
number of items to replace is not a multiple of replacement length
¿Hay alguna manera de que pueda pasar la celda relevante, en lugar de vector?
Aquí hay un enfoque. ifelse
está vectorizado y comprueba todas las filas para valores cero de b
y reemplaza est
con (a - 5)/2.53
si ese es el caso.
df <- transform(df, est = ifelse(b == 0, (a - 5)/2.53, est))
Como está indexando condicionalmente df$est
, también necesita indexar condicionalmente el vector de reemplazo df$a
:
index <- df$b == 0
df$est[index] <- (df$a[index] - 5)/2.533
Por supuesto, el index
variable es solo temporal, y lo uso para que el código sea más legible. Puedes escribirlo en un solo paso:
df$est[df$b == 0] <- (df$a[df$b == 0] - 5)/2.533
Para una mejor lectura, puede usar within
:
df <- within(df, est[b==0] <- (a[b==0]-5)/2.533)
Los resultados, independientemente del método que elija:
df
a b est
1 11.77000 2 0.000000
2 10.90000 3 0.000000
3 10.32000 2 0.000000
4 10.96000 0 2.352941
5 9.90600 0 1.936834
6 10.70000 0 2.250296
7 11.43000 1 0.000000
8 11.41000 2 0.000000
9 10.48512 4 0.000000
10 11.19000 0 2.443743
Como otros han señalado, una solución alternativa en su ejemplo es usar ifelse
.
El R-inferno o la documentación R básica explicarán por qué utilizar df $ * no es el mejor enfoque aquí. Desde la página de ayuda para "[":
"La indexación por [es similar a los vectores atómicos y selecciona una lista de los elementos especificados. Ambos [[y $ seleccionan un solo elemento de la lista. La principal diferencia es que $ no permite índices computados, mientras que [[hace . x $ name es equivalente a x [["nombre", exacto = FALSO]]. Además, el comportamiento de coincidencia parcial de [puede controlarse usando el argumento exacto.
Recomiendo usar la notación [row,col]
lugar. Ejemplo:
Rgames: foo
x y z
[1,] 1e+00 1 0
[2,] 2e+00 2 0
[3,] 3e+00 1 0
[4,] 4e+00 2 0
[5,] 5e+00 1 0
[6,] 6e+00 2 0
[7,] 7e+00 1 0
[8,] 8e+00 2 0
[9,] 9e+00 1 0
[10,] 1e+01 2 0
Rgames: foo<-as.data.frame(foo)
Rgames: foo[foo$y==2,3]<-foo[foo$y==2,1]
Rgames: foo
x y z
1 1e+00 1 0e+00
2 2e+00 2 2e+00
3 3e+00 1 0e+00
4 4e+00 2 4e+00
5 5e+00 1 0e+00
6 6e+00 2 6e+00
7 7e+00 1 0e+00
8 8e+00 2 8e+00
9 9e+00 1 0e+00
10 1e+01 2 1e+01
Otra opción sería usar case_when
require(dplyr)
transform(df, est = case_when(
b == 0 ~ (a - 5)/2.53,
TRUE ~ est
))
Esta solución se vuelve aún más útil si se deben distinguir más de 2 casos, ya que permite evitar construcciones if_else
anidadas.
Prueba data.table ''s :=
operator:
DT = as.data.table(df)
DT[b==0, est := (a-5)/2.533]
Es rápido y corto. Consulte estas preguntas vinculadas para obtener más información sobre :=
:
Por qué se ha definido data.table :=
Cuándo debería usar el operador :=
en data.table