J'ai les données et le code suivants pour arrondir les colonnes sélectionnées de ce data.table:
> 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
Existe-t-il une meilleure méthode (code plus court)? Merci de votre aide.
Si cela ne vous dérange pas de remplacer votre mydf
originale:
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
Utiliser dplyr
Si vous souhaitez arrondir plusieurs colonnes à la fois:
mydf %>% mutate_at(vars(vnum1, vnum2), funs(round(., 1)))
Ou, si vous souhaitez modifier toutes les colonnes sauf "vch1":
mydf %>% mutate_at(vars(-vch1), funs(round(., 1)))
Ou, si vous souhaitez modifier toutes les colonnes commençant par "vnum":
mydf %>% mutate_at(vars(starts_with("vnum")), funs(round(., 1)))
Ou, si vous souhaitez modifier uniquement les colonnes numériques:
mydf %>% mutate_if(is.numeric, ~round(., 1))
Vous recevez:
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
require (data.table)
Solution courte et claire:
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
Idem, mais avec des détails descriptifs:
mydf[, lapply(.SD, round, digits = 1), by = vch1]
Si j'ai plusieurs colonnes, dites: (vnum1, vnum2, vch1, vch2, vbin1, vbin2, vbin3) et je veux arrondir uniquement vnum1 et vnum2?
Dans ce cas, vous pouvez utiliser l'opérateur :=
et l'argument .SDcols =
pour spécifier les colonnes à arrondir:
mydf[, 1:2 := lapply(.SD, round, digits = 1), by = vch1]
Si vous devez arrondir certaines colonnes et en exclure d’autres de la sortie, vous pouvez utiliser uniquement l’argument .SDcols =
pour les exécuter simultanément:
mydf[, lapply(.SD, round, digits = 1), by = vch1, .SDcols = "vnum1"]
.SDcols =
peut être fourni avec le nom de la colonne ou son numéro,
en une seule colonne par nom .SDcols = "vnum1"
ou par numéro .SDcols = 1
en multi colonnes par noms .SDcols = c("vnum2", "vnum1")
ou par nombres .SDcols = c(2, 1)
sous forme de colonnes par noms .SDcols = vnum1:vnum2
ou par nombres.SDcols = 1:2
Le plus court de loin:
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
Méthode intéressante. Mais si j'ai plusieurs colonnes, dites: (vnum1, vnum2, vch1, vch2, vbin1, vbin2, vbin3) et si je veux arrondir uniquement vnum1 et vnum2? De plus, quelques explications sur son fonctionnement seront très utiles
Il regroupe des colonnes arrondies en utilisant "by =" de data.table.
Voici l'exemple basé sur cette méthode pour résoudre votre tâche de second niveau.
Jeu de données intégré:
>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
Solution courte:
> 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
Ordre initial des colonnes:
> 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
Je pense que parmi les solutions proposées, celle de Steven Baupre utilisant dplyr
est la plus élégante et la plus applicable de manière sélective dans différentes colonnes d’un cadre de données, en particulier en physique informatique.
library(dplyr)
gasCriticals %>%
mutate_each(funs(round(., 0)), depth, pres, temp) %>%
mutate_each(funs(round(., 2)), pres.pr, temp.pr, temp.r) %>%
mutate_each(funs(round(., 1)), pres.pc, temp.pc)
Comme vous pouvez le constater, la pression et la température seront arrondies à 0 décimale; pression pseudo-réduite et température jusqu'à 2 déc; et enfin, pression pseudo-critique et température à 1 décimale.