Le code suivant renomme la première colonne de l'ensemble de données:
require(dplyr)
mtcars %>%
setNames(c("RenamedColumn", names(.)[2:length(names(.))]))
Résultats souhaités:
RenamedColumn cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
Serait-il possible d'arriver au même résultat en utilisant rename
et index de colonne?
Cette:
mtcars %>%
rename(1 = "ChangedNameAgain")
échouera:
Error in source("~/.active-rstudio-document", echo = TRUE) :
~/.active-rstudio-document:7:14: unexpected '='
6: mtcars %>%
7: rename(1 =
^
De même, essayez d'utiliser rename_
ou .[[1]]
comme référence de colonne renverra une erreur.
À partir de dplyr
0.7.5
, rlang
0.2.1
, tidyselect
0.2.4
, Cela fonctionne simplement:
library(dplyr)
rename(mtcars, ChangedNameAgain = 1)
# ChangedNameAgain cyl disp hp drat wt qsec vs am gear carb
# Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
# Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
# Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
# Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
# Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
# ...
La réponse d'origine et les modifications sont désormais obsolètes:
La logique de rename()
est new_name = old_name
, Donc ChangedNameAgain = 1
Aurait plus de sens que 1 = ChangedNameAgain
.
Je voudrais suggerer:
mtcars %>% rename_(ChangedNameAgain = names(.)[1])
# ChangedNameAgain cyl disp hp drat wt qsec vs am gear carb
# Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
# Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
# Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
# Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
# Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
# Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1
Modifier
Je n'ai pas encore fait le tour du nouveau système de programmation dplyr
basé sur rlang
, depuis les versions 0.6/0.7 de dplyr
.
La version avec suffixe de soulignement de rename
utilisée dans ma réponse initiale est maintenant obsolète, et selon le commentaire de @ jzadra, elle ne fonctionnait pas de toute façon avec des noms syntaxiquement problématiques comme "foo bar"
.
Voici ma tentative avec le nouveau système d'évaluation non standard basé sur rlang
. N'hésitez pas à me dire ce que j'ai fait de mal, dans les commentaires:
df <- tibble("foo" = 1:2, "bar baz" = letters[1:2])
# # A tibble: 2 x 2
# foo `bar baz`
# <int> <chr>
# 1 1 a
# 2 2 b
J'essaie d'abord directement avec rename()
mais malheureusement j'ai une erreur. Il semble être un FIXME
(ou est-ce que ce FIXME n'est pas lié?) Dans le code source (j'utilise dplyr
0.7.4), donc cela pourrait fonctionner A l'avenir:
df %>% rename(qux = !! quo(names(.)[[2]]))
# Error: Expressions are currently not supported in `rename()`
(Edit: le message d'erreur maintenant (dplyr 0.7.5) lit Error in UseMethod("rename_") : no applicable method for 'rename_' applied to an object of class "function"
)
(Mise à jour 2018-06-14: df %>% rename(qux = !! quo(names(.)[[2]]))
semble maintenant fonctionner, toujours avec dplyr 0.7.5, je ne sais pas si un paquet sous-jacent a changé).
Voici une solution de contournement avec select
qui fonctionne. Cependant, il ne conserve pas l'ordre des colonnes comme rename
:
df %>% select(qux = !! quo(names(.)[[2]]), everything())
# # A tibble: 2 x 2
# qux foo
# <chr> <int>
# 1 a 1
# 2 b 2
Et si nous voulons le mettre dans une fonction, nous devons le modifier légèrement avec :=
Pour permettre le retrait des guillemets sur le côté gauche. Si nous voulons être robustes aux entrées comme les chaînes et les noms de variables nues, nous devons utiliser la "magie noire" (ou c'est ce que dit la vignette ) de la fonction enquo()
et quo_name()
(honnêtement, je ne comprends pas bien ce que ça fait):
rename_col_by_position <- function(df, position, new_name) {
new_name <- enquo(new_name)
new_name <- quo_name(new_name)
select(df, !! new_name := !! quo(names(df)[[position]]), everything())
}
Cela fonctionne avec un nouveau nom sous forme de chaîne:
rename_col_by_position(df, 2, "qux")
# # A tibble: 2 x 2
# qux foo
# <chr> <int>
# 1 a 1
# 2 b 2
Cela fonctionne avec un nouveau nom comme une suspension:
rename_col_by_position(df, 2, quo(qux))
# # A tibble: 2 x 2
# qux foo
# <chr> <int>
# 1 a 1
# 2 b 2
Cela fonctionne avec un nouveau nom comme nom nu:
rename_col_by_position(df, 2, qux)
# # A tibble: 2 x 2
# qux foo
# <chr> <int>
# 1 a 1
# 2 b 2
Et même cela fonctionne:
rename_col_by_position(df, 2, `qux quux`)
# # A tibble: 2 x 2
# `qux quux` foo
# <chr> <int>
# 1 a 1
# 2 b 2
Voici quelques solutions alternatives qui sont sans doute plus faciles à lire car elles ne se concentrent pas sur la référence .
. select
comprend les indices de colonne, donc si vous renommez la première colonne, vous pouvez simplement faire
mtcars %>% select( RenamedColumn = 1, everything() )
Cependant, le problème avec l'utilisation de select
est qu'il réorganisera les colonnes si vous renommez une colonne au milieu. Pour contourner le problème, vous devez présélectionner les colonnes à gauche de celle que vous renommez:
## This will rename the 7th column without changing column order
mtcars %>% select( 1:6, RenamedColumn = 7, everything() )
Une autre option consiste à utiliser le nouveau rename_at
, Qui comprend également les indices de colonne:
## This will also rename the 7th column without changing the order
## Credit for simplifying the second argument: Moody_Mudskipper
mtcars %>% rename_at( 7, ~"RenamedColumn" )
~
Est nécessaire car rename_at
Est assez flexible et peut accepter des fonctions comme deuxième argument. Par exemple, mtcars %>% rename_at( c(2,4), toupper )
mettra les noms des deuxième et quatrième colonnes en majuscules.
Imho rlang
comme suggéré par @Aurele est trop ici.
Solution 1: utilisez un contexte de tuyau de tuyau à accolades:
bcMatrix %>% {colnames(.)[1] = "foo"; .}
Solution 2: Ou (ab) utilisez l'opérateur tee %>%
à partir du package magrittr
(installé de toute façon si dplyr
est utilisé) pour effectuer le changement de nom en tant qu'effet secondaire:
bcMatrix %T>% {colnames(.)[1] = "foo"}
Solution 3: à l'aide d'une fonction d'assistance simple:
rename_by_pos = function(df, index, new_name){
colnames(df)[index] = new_name
df
}
iris %>% rename_by_pos(2,"foo")