data - dcast r
Redondeo de columnas seleccionadas de data.table en R (6)
Creo que a partir de las soluciones, la de Steven Baupre que usa dplyr
es la más elegante y aplicable de forma selectiva en diferentes columnas en un marco de datos, especialmente en física computacional.
> whatever <- setcolorder(dt_round, names(dt))
> whatever
# names general picture blocks maze reading vocab
#1: general 24.641 5.991 33.5 6.0 20.755 29.701
#2: picture 5.991 6.700 18.1 1.8 4.936 7.204
#3: blocks 33.520 18.137 149.8 19.4 31.430 50.753
#4: maze 6.023 1.782 19.4 12.7 4.757 9.075
#5: reading 20.755 4.936 31.4 4.8 52.604 66.762
#6: vocab 29.701 7.204 50.8 9.1 66.762 135.292
Como puede ver, la presión y la temperatura se redondearán a 0 decimales; Presión y temperatura pseudo-reducidas a 2 decs. y finalmente, presión y temperatura pseudo-críticas hasta 1 decimales.
Tengo los siguientes datos y código para redondear las columnas seleccionadas de estos datos.
> dput(mydf)
structure(list(vnum1 = c(0.590165705411504, -1.39939534199836,
0.720226053660755, -0.253198380120377, -0.783366825121657), vnum2 = c(0.706508400384337,
0.526770398486406, 0.863136084517464, 0.838245498016477, 0.556775856064633
), vch1 = structure(c(2L, 4L, 1L, 3L, 3L), .Label = c("A", "B",
"C", "E"), class = "factor")), .Names = c("vnum1", "vnum2", "vch1"
), row.names = c(NA, -5L), class = c("data.table", "data.frame"
))
> mydf[,round(.SD,1),]
Error in Math.data.frame(list(vnum1 = c(0.590165705411504, -1.39939534199836, :
non-numeric variable in data frame: vch1
> cbind(mydf[,3,with=F], mydf[,1:2,with=F][,round(.SD,1),])
vch1 vnum1 vnum2
1: B 0.6 0.7
2: E -1.4 0.5
3: A 0.7 0.9
4: C -0.3 0.8
5: C -0.8 0.6
¿Hay un método mejor (código más corto)? Gracias por tu ayuda.
Dado que dplyr::mutate_each
ha quedado en desuso, use mutate_if
con el beneficio adicional de redondear una columna solo si es numérico
mydf %>% mutate_if(is.numeric, round, 1)
Más corto por mucho:
mydf[, lapply(.SD, round, digits = 1), by = vch1, .SDcols = "vnum1"]
Método interesante. Pero, ¿qué pasa si tengo muchas columnas, por ejemplo: (vnum1, vnum2, vch1, vch2, vbin1, vbin2, vbin3) y quiero redondear solo vnum1 y vnum2? Además, alguna explicación sobre cómo está funcionando será muy útil.
Es agrupar por columnas redondeadas utilizando "by =" de data.table.
Este es el ejemplo basado en este método para resolver su tarea de segundo nivel.
Conjunto de datos incorporado:
mydf[, vch1, round(mydf[, 1:2], 1)]
# vnum1 vnum2 vch1
#1: 0.6 0.7 B
#2: -1.4 0.5 E
#3: 0.7 0.9 A
#4: -0.3 0.8 C
#5: -0.8 0.6 C
Solución corta:
>dt <- data.table(names = rownames(datasets::ability.cov$cov), datasets::ability.cov$cov)
>dt
# names general picture blocks maze reading vocab
#1: general 24.641 5.991 33.520 6.023 20.755 29.701
#2: picture 5.991 6.700 18.137 1.782 4.936 7.204
#3: blocks 33.520 18.137 149.831 19.424 31.430 50.753
#4: maze 6.023 1.782 19.424 12.711 4.757 9.075
#5: reading 20.755 4.936 31.430 4.757 52.604 66.762
#6: vocab 29.701 7.204 50.753 9.075 66.762 135.292
Orden inicial de las columnas:
> dt_round <- dt[, .SD, by = round(dt[, blocks:maze], 1)]
> dt_round
# blocks maze names general picture reading vocab
#1: 33.5 6.0 general 24.641 5.991 20.755 29.701
#2: 18.1 1.8 picture 5.991 6.700 4.936 7.204
#3: 149.8 19.4 blocks 33.520 18.137 31.430 50.753
#4: 19.4 12.7 maze 6.023 1.782 4.757 9.075
#5: 31.4 4.8 reading 20.755 4.936 52.604 66.762
#6: 50.8 9.1 vocab 29.701 7.204 66.762 135.292
Si no te importa sobreescribir tu mydf
original:
cols <- names(mydf)[1:2]
mydf[,(cols) := round(.SD,1), .SDcols=cols]
mydf
# vnum1 vnum2 vch1
#1: 0.6 0.7 B
#2: -1.4 0.5 E
#3: 0.7 0.9 A
#4: -0.3 0.8 C
#5: -0.8 0.6 C
Utilizando dplyr
Si quieres redondear varias columnas a la vez:
mydf %>% mutate(vnum1 = round(vnum1, 1), vnum2 = round(vnum2, 1))
O, si desea cambiar todas las columnas excepto "vch1":
mydf %>% mutate_each(funs(round(.,1)), vnum1, vnum2)
O, si desea cambiar todas las columnas que comienzan con "vnum":
mydf %>% mutate_each(funs(round(.,1)), -vch1)
O, si quieres cambiar solo las columnas numéricas:
cols <- names(mydf)[1:2]
mydf %>% mutate_each_(funs(round(.,1)), cols)
Usted obtiene:
mydf %>% mutate_each(funs(round(.,1)), starts_with("vnum"))
requiere (data.table)
Solución corta y clara:
vnum1 vnum2 vch1
1 0.6 0.7 B
2 -1.4 0.5 E
3 0.7 0.9 A
4 -0.3 0.8 C
5 -0.8 0.6 C
Lo mismo, pero con detalles descriptivos:
mydf[, lapply(.SD, round, 1), vch1]
# vch1 vnum1 vnum2
#1: B 0.6 0.7
#2: E -1.4 0.5
#3: A 0.7 0.9
#4: C -0.3 0.8
#5: C -0.8 0.6
Si tengo muchas columnas, diga: (vnum1, vnum2, vch1, vch2, vbin1, vbin2, vbin3) y quiero redondear solo vnum1 y vnum2?
En este caso, puede usar :=
operator y .SDcols =
argumento para especificar columnas para redondear:
mydf[, lapply(.SD, round, digits = 1), by = vch1]
En caso de que necesite redondear ciertas columnas y excluir otras de la salida, puede usar solo el argumento .SDcols =
para hacer ambas cosas a la vez:
mydf[, 1:2 := lapply(.SD, round, digits = 1), by = vch1]
.SDcols =
puede suministrarse con el nombre de la columna o su número,
como una sola columna por nombre .SDcols = "vnum1"
o por número .SDcols = 1
como varias columnas por nombres .SDcols = c("vnum2", "vnum1")
o por números .SDcols = c(2, 1)
como un rango de columnas por nombres .SDcols = vnum1:vnum2
o por números .SDcols = 1:2