Soltar columnas del marco de datos por nombre
Tengo un número 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 órdenes.
También, sé que podría soltar columnas usando 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 poderoso que es R, pensé que podría haber una mejor manera de dejar caer cada columna por una.
19 answers
Puede usar una lista simple 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 los que mantener y referirse a ellos por su nombre:
keeps <- c("y", "a")
DF[keeps]
EDITAR :
Para aquellos que aún no están familiarizados con el argumento drop
de la función de indexación, si desea mantener una columna como un marco de datos, haga lo siguiente:
keeps <- "y"
DF[ , keeps, drop = FALSE]
drop=TRUE
(o no mencionarlo) soltará dimensiones innecesarias, y por lo tanto devolverá un vector con los valores de la columna y
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-26 20:57:39
También está el comando subset
, útil si sabes qué columnas quieres:
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 soltar columnas a, c se puede hacer:
df <- subset(df, select = -c(a, c))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-08 01:02:57
within(df, rm(x))
Es probablemente más fácil, o para múltiples variables:
within(df, rm(x, y))
O si se trata de data.table
s (per Cómo se elimina una columna por nombre en los datos.¿mesa?):
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")]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:26
Podrías usar %in%
así:
df[, !(colnames(df) %in% c("x","bar","foo"))]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-05 14:40:26
List (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"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-13 20:24:24
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 el 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 como vector de caracteres fuera de la llamada a [
, envuelva el nombre del objeto en ()
o {}
para forzar que el LHS se evalúe en el ámbito de llamada no como un nombre en el ámbito de aplicación 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
, lo 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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-21 01:17:06
Hay 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 yo en uno de mis conjuntos de datos, algunas variables que terminan en".Un" y otros que terminan en ".B "y solo quieres los que terminan en".A " (junto con todas las variables que no coinciden con ninguno de los patrones, haga esto:
dfrm2 <- dfrm[ , -grep("\\.B$", names(dfrm)) ]
Para el caso en cuestión, usando el ejemplo de Joris Meys, podría no ser tan compacto, pero sería:
DF <- DF[, -grep( paste("^",drops,"$", sep="", collapse="|"), names(DF) )]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-24 16:45:59
Por 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í...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-02 18:42:27
Otra dplyr
respuesta. Si sus variables tienen alguna estructura de nomenclatura 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 soltar una secuencia de variables en el marco de datos, puede usar :
. Por ejemplo, si quieres dejar var2
, var3
, y todas las variables en el medio, te quedarías con var1
:
df2 <- df1 %>% select(-c(var2:var3) )
df2
# var1
#1 0.75879754
#2 0.31168919
#3 0.03983268
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-22 20:37:02
Otra posibilidad:
df <- df[, setdiff(names(df), c("a", "c"))]
O
df <- df[, grep('^(a|c)$', names(df), invert=TRUE)]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-11 19:07:36
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-12 07:37:32
Aquí hay una dplyr
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 leer y entender sin anotación y robusto para columnas que cambian de posición dentro del marco de datos. También sigue el modismo vectorizado usando -
para eliminar elementos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-23 19:16:00
Sigo pensando que debe haber un mejor modismo, pero para restar 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-05 17:21:58
Hay una función llamada dropNamed()
en el paquete BBmisc
de Bernd Bischl que hace exactamente esto.
BBmisc::dropNamed(df, "x")
La ventaja es que evita repetir el argumento data frame y por lo tanto es adecuado para canalizar en magrittr
(al igual que los enfoques dplyr
):
df %>% BBmisc::dropNamed("x")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-04 14:06:22
Solución de Dplyr
Dudo que esto reciba mucha atención aquí abajo, pero si tienes una lista de columnas que quieres eliminar, y quieres hacerlo en una cadena dplyr
utilizo one_of()
en la cláusula select
:
Aquí hay un ejemplo simple y 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-02 14:02:14
Otra solución si no desea utilizar @hadley de arriba: Si "COLUMN_NAME" es el nombre de la columna que desea soltar:
df[,-which(names(df) == "COLUMN_NAME")]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-25 22:57:20
Más allá de select(-one_of(drop_col_names))
demostrado en respuestas anteriores, hay un par de otras dplyr
opciones para soltar columnas usando select()
que no implican definir todos los nombres de columna específicos (utilizando los datos de muestra de dplyr starwars para alguna variedad de nombres de columna):
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-03 02:11:25
Proporcione el marco de datos y una cadena de nombres separados por comas para eliminar:
remove_features <- function(df, features) {
rem_vec <- unlist(strsplit(features, ', '))
res <- df[,!(names(df) %in% rem_vec)]
return(res)
}
Uso :
remove_features(iris, "Sepal.Length, Petal.Width")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-15 16:51:02
Encuentre el índice de las columnas que desea soltar usando which
. Dé a estos índices un signo negativo (*-1
). Luego subconjunto en esos valores, que los eliminará del dataframe. Este 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-17 11:42:03