Pregunta

Tengo varias 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 soltar columnas usando 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 poderoso que es R, pensé que podría haber una mejor manera que dejar cada columna una por una.

¿Fue útil?

Solución

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 ellos para mantener y consultar ellos por su nombre:

keeps <- c("y", "a")
DF[keeps]

Editar: para aquellos que todavía no están familiarizados con el drop Argumento de la función de indexación, si desea mantener una columna como marco de datos, usted hace:

keeps <- "y"
DF[ , keeps, drop = FALSE]

drop=TRUE (o no mencionarlo) arrojará dimensiones innecesarias y, por lo tanto, devolverá un vector con los valores de la columna y.

Otros consejos

También está el subset Comando, ú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: a soltar Columnas A, C que podrías hacer:

df <- subset(df, select = -c(a, c))
within(df, rm(x))

es probablemente más fácil, o para múltiples variables:

within(df, rm(x, y))

O si estás tratando con data.tables (por ¿Cómo se elimina una columna por nombre en data.table?):

dt[, x := NULL]   # Deletes column x by reference instantly.

dt[, !"x"]   # Selects all but x into a new data.table.

o para múltiples variables

dt[, c("x","y") := NULL]

dt[, !c("x", "y")]

Podrías usar %in% como esto:

df[, !(colnames(df) %in% c("x","bar","foo"))]

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"

Si desea eliminar las columnas por referencia y evite la copia interna asociada con data.frames Entonces puedes usar el data.table paquete y la función :=

Puedes pasar un personaje de nombres vectoriales 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 vector de caracteres fuera de la llamada a [, envuelva el nombre del objeto en () o {} para forzar el LHS a ser evaluado en el alcance de llamadas 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 puedes 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)

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 mi conjunto de datos, algunas variables que terminan en ".a" y otras que terminan en ".b" y solo quieres las que terminan en ".a" ( Con todas las variables que no coinciden con ningún patrón, haz 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) )]

Otro dplyr responder. Si sus variables tienen una estructura de nomenclatura común, puede intentar 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 querías caer var2, var3, y todos variables intermedias, solo te quedarías var1:

df2 <- df1 %>% select(-c(var2:var3) )  
df2
#        var1
#1 0.75879754
#2 0.31168919
#3 0.03983268
DF <- data.frame(
  x=1:10,
  y=10:1,
  z=rep(5,10),
  a=11:20
)
DF

Producción:

    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)

Producción:

        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

Por interés, esto marca una de las extrañas inconsistencias de sintaxis múltiple 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 le da un vector

df[,-2]

Todo esto se explica en ?[ Pero no es exactamente el comportamiento esperado. Bueno, al menos no para mí ...

Otra posibilidad:

df <- df[, setdiff(names(df), c("a", "c"))]

o

df <- df[, grep('^(a|c)$', names(df), invert=TRUE)]

Solución dplyr

Dudo que esto reciba mucha atención aquí, pero si tiene una lista de columnas que desea eliminar, y desea hacerlo en un dplyr cadena que uso one_of() en el select cláusula:

Aquí hay un ejemplo simple y reproducible:

undesired <- c('mpg', 'cyl', 'hp')

mtcars <- 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

Aquí hay un 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 comprender sin anotación y robusto a las columnas que cambian de posición dentro del marco de datos. También sigue el idioma vectorizado usando - para eliminar elementos.

Sigo pensando que debe haber un mejor idioma, pero para la resta de 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

Hay una función llamada dropNamed() En Bernd Bischl's BBmisc paquete 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 tuberías en magrittr (como el dplyr enfoques):

df %>% BBmisc::dropNamed("x")

Otra solución si no desea usar el arriba de @Hadley: si "column_name" es el nombre de la columna que desea soltar:

df[,-which(names(df) == "COLUMN_NAME")]

Más allá de select(-one_of(drop_col_names)) demostrado en respuestas anteriores, hay un par otro dplyr Opciones para soltar columnas usando select() que no implican definir todos los nombres de columnas específicos (utilizando los datos de muestra DPLYR StarWars para alguna variedad en nombres de columnas):

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 

Proporcionar la marco de datos y una cadena de nombres separados por coma 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")

enter image description here

Encuentre el índice de las columnas que desea soltar usando which. Dar a estos índices un signo negativo (*-1). Luego subseten esos valores, lo que los eliminará de DataFrame. 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top