columnas - colnames r
Eliminar columnas de marco de datos por nombre (19)
Aquí hay una manera de hacerlo:
#df[ -c(1,3:6, 12) ] # original
df.cut <- df %>% select(-col.to.drop.1, -col.to.drop.2, ..., -col.to.drop.6) # with dplyr::select()
Me gusta esto porque es intuitivo para leer y entender sin anotaciones y robusto a las columnas que cambian de posición dentro del marco de datos. También sigue el lenguaje vectorizado usando -
para eliminar elementos.
Tengo una serie de columnas que me gustaría eliminar de un marco de datos. Sé que podemos eliminarlos individualmente usando algo como:
df$x <- NULL
Pero esperaba hacer esto con menos comandos.
Además, sé que podría eliminar columnas utilizando la indexación de enteros como esta:
df <- df[ -c(1, 3:6, 12) ]
Pero me preocupa que la posición relativa de mis variables pueda cambiar.
Dado lo poderosa que es la R, pensé que podría haber una mejor manera de eliminar cada columna una por una.
Encuentre el índice de las columnas que desea eliminar usando. Dale a estos índices un signo negativo ( *-1
). A continuación, subcontrate esos valores, que los eliminarán del marco de datos. Esto es un ejemplo.
DF <- data.frame(one=c(''a'',''b''), two=c(''c'', ''d''), three=c(''e'', ''f''), four=c(''g'', ''h''))
DF
# one two three four
#1 a d f i
#2 b e g j
DF[which(names(DF) %in% c(''two'',''three'')) *-1]
# one four
#1 a g
#2 b h
Existe una estrategia potencialmente más poderosa basada en el hecho de que grep () devolverá un vector numérico. Si tiene una larga lista de variables como lo hago en uno de mis conjuntos de datos, algunas variables terminan en ".A" y otras que terminan en ".B" y solo desea las que terminan en ".A" (junto con con todas las variables que no coinciden con ninguno de los patrones, haga esto:
dfrm2 <- dfrm[ , -grep("//.B$", names(dfrm)) ]
Para el caso que nos ocupa, usando el ejemplo de Joris Meys, podría no ser tan compacto, pero sería:
DF <- DF[, -grep( paste("^",drops,"$", sep="", collapse="|"), names(DF) )]
Hay una función llamada dropNamed()
en el paquete BBmisc
Bernd BBmisc
que hace exactamente esto.
BBmisc::dropNamed(df, "x")
La ventaja es que evita repetir el argumento del marco de datos y, por lo tanto, es adecuado para la canalización en magrittr
(al igual que se dplyr
el dplyr
):
df %>% BBmisc::dropNamed("x")
La lista (NULL) también funciona:
dat <- mtcars
colnames(dat)
# [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear"
# [11] "carb"
dat[,c("mpg","cyl","wt")] <- list(NULL)
colnames(dat)
# [1] "disp" "hp" "drat" "qsec" "vs" "am" "gear" "carb"
Más allá de select(-one_of(drop_col_names))
demostrado en respuestas anteriores, hay un par de otras opciones de dplyr
para dplyr
columnas usando select()
que no implican la definición de todos los nombres de columna específicos (usando los datos de muestra dplyr starwars para alguna variedad en la columna nombres):
library(dplyr)
starwars %>%
select(-(name:mass)) %>% # the range of columns from ''name'' to ''mass''
select(-contains(''color'')) %>% # any column name that contains ''color''
select(-starts_with(''bi'')) %>% # any column name that starts with ''bi''
select(-ends_with(''er'')) %>% # any column name that ends with ''er''
select(-matches(''^f.+s$'')) %>% # any column name matching the regex pattern
select_if(~!is.list(.)) %>% # not by column name but by data type
head(2)
# A tibble: 2 x 2
homeworld species
<chr> <chr>
1 Tatooine Human
2 Tatooine Droid
Otra posibilidad:
df <- df[, setdiff(names(df), c("a", "c"))]
o
df <- df[, grep(''^(a|c)$'', names(df), invert=TRUE)]
Otra respuesta dplyr
. Si sus variables tienen alguna estructura de denominación común, puede probar starts_with()
. Por ejemplo
library(dplyr)
df <- data.frame(var1 = rnorm(5), var2 = rnorm(5), var3 = rnorm (5),
var4 = rnorm(5), char1 = rnorm(5), char2 = rnorm(5))
df
# var2 char1 var4 var3 char2 var1
#1 -0.4629512 -0.3595079 -0.04763169 0.6398194 0.70996579 0.75879754
#2 0.5489027 0.1572841 -1.65313658 -1.3228020 -1.42785427 0.31168919
#3 -0.1707694 -0.9036500 0.47583030 -0.6636173 0.02116066 0.03983268
df1 <- df %>% select(-starts_with("char"))
df1
# var2 var4 var3 var1
#1 -0.4629512 -0.04763169 0.6398194 0.75879754
#2 0.5489027 -1.65313658 -1.3228020 0.31168919
#3 -0.1707694 0.47583030 -0.6636173 0.03983268
Si desea eliminar una secuencia de variables en el marco de datos, puede utilizar :
Por ejemplo, si desea eliminar var2
, var3
y todas las variables intermedias, simplemente se quedará con var1
:
df2 <- df1 %>% select(-c(var2:var3) )
df2
# var1
#1 0.75879754
#2 0.31168919
#3 0.03983268
Otra solución si no quiere usar @ hadley''s arriba: Si "COLUMN_NAME" es el nombre de la columna que desea eliminar:
df[,-which(names(df) == "COLUMN_NAME")]
Podrías usar %in%
así:
df[, !(colnames(df) %in% c("x","bar","foo"))]
Puedes usar una simple lista de nombres:
DF <- data.frame(
x=1:10,
y=10:1,
z=rep(5,10),
a=11:20
)
drops <- c("x","z")
DF[ , !(names(DF) %in% drops)]
O, alternativamente, puede hacer una lista de aquellos para guardar y referirse a ellos por su nombre:
keeps <- c("y", "a")
DF[keeps]
EDITAR: para aquellos que aún no conocen el argumento de la función de indexación, si desea mantener una columna como marco de datos, haga lo siguiente:
keeps <- "y"
DF[ , keeps, drop = FALSE]
drop=TRUE
(o no mencionarlo) eliminará dimensiones innecesarias y, por lo tanto, devolverá un vector con los valores de la columna y
.
Si desea eliminar las columnas por referencia y evitar la copia interna asociada con data.frames
, puede usar el paquete data.table
y la función :=
Puede pasar los nombres de un vector de caracteres al lado izquierdo del operador :=
, y NULL
como RHS.
library(data.table)
df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10)
DT <- data.table(df)
# or more simply DT <- data.table(a=1:10, b=1:10, c=1:10, d=1:10) #
DT[, c(''a'',''b'') := NULL]
Si desea predefinir los nombres como vector de caracteres fuera de la llamada a [
, ajuste el nombre del objeto en ()
o {}
para forzar que el LHS se evalúe en el alcance de la llamada, no como un nombre dentro del alcance de DT
.
del <- c(''a'',''b'')
DT <- data.table(a=1:10, b=1:10, c=1:10, d=1:10)
DT[, (del) := NULL]
DT <- <- data.table(a=1:10, b=1:10, c=1:10, d=1:10)
DT[, {del} := NULL]
# force or `c` would also work.
También puede usar set
, que evita la sobrecarga de [.data.table
, y también funciona para data.frames
!
df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10)
DT <- data.table(df)
# drop `a` from df (no copying involved)
set(df, j = ''a'', value = NULL)
# drop `b` from DT (no copying involved)
set(DT, j = ''b'', value = NULL)
Sigo pensando que debe haber un mejor idioma, pero para restar las columnas por nombre, tiendo a hacer lo siguiente:
df <- data.frame(a=1:10, b=1:10, c=1:10, d=1:10)
# return everything except a and c
df <- df[,-match(c("a","c"),names(df))]
df
Sin interés, esto marca una de las extrañas inconsistencias de sintaxis múltiples de R. Por ejemplo, dado un marco de datos de dos columnas:
df <- data.frame(x=1, y=2)
Esto da un marco de datos
subset(df, select=-y)
pero esto da un vector
df[,-2]
Todo esto se explica en ?[
Pero no es exactamente el comportamiento esperado. Bueno, al menos no para mí ...
También está el comando de subset
, útil si sabe qué columnas desea:
df <- data.frame(a = 1:10, b = 2:11, c = 3:12)
df <- subset(df, select = c(a, c))
ACTUALIZADO después del comentario de @hadley: Para eliminar las columnas a, c, podría hacer:
df <- subset(df, select = -c(a, c))
Solución Dplyr
Dudo que esto le preste mucha atención aquí abajo, pero si tiene una lista de columnas que desea eliminar, y desea hacerlo en una cadena dplyr
, uso one_of()
en la cláusula de select
:
Aquí hay un ejemplo simple, reproducible:
undesired <- c(''mpg'', ''cyl'', ''hp'')
mtcars %>%
select(-one_of(undesired))
La documentación se puede encontrar ejecutando ?one_of
o aquí:
http://genomicsclass.github.io/book/pages/dplyr_tutorial.html
DF <- data.frame(
x=1:10,
y=10:1,
z=rep(5,10),
a=11:20
)
DF
Salida:
x y z a
1 1 10 5 11
2 2 9 5 12
3 3 8 5 13
4 4 7 5 14
5 5 6 5 15
6 6 5 5 16
7 7 4 5 17
8 8 3 5 18
9 9 2 5 19
10 10 1 5 20
DF[c("a","x")] <- list(NULL)
Salida:
y z
1 10 5
2 9 5
3 8 5
4 7 5
5 6 5
6 5 5
7 4 5
8 3 5
9 2 5
10 1 5
within(df, rm(x))
Probablemente sea más fácil, o para múltiples variables:
within(df, rm(x, y))
O si está tratando con data.table
s (por ¿Cómo borra una columna por nombre en data.table? ):
dt[, x := NULL] # deletes column x by reference instantly
dt[, !"x", with=FALSE] # selects all but x into a new data.table
o para múltiples variables
dt[, c("x","y") := NULL]
dt[, !c("x", "y"), with=FALSE]
En la versión de desarrollo de data.table
( instrucciones de instalación ), with = FALSE
ya no es necesario:
dt[ , !"x"]
dt[ , !c("x", "y")]