R dplyr: eliminar varias columnas


96

Tengo un marco de datos y una lista de columnas en ese marco de datos que me gustaría eliminar. Usemos el irisconjunto de datos como ejemplo. Me gustaría dejar caer Sepal.Lengthy Sepal.Widthy utilizar sólo las columnas restantes. ¿Cómo puedo hacer esto usando selecto select_desde el dplyrpaquete?

Esto es lo que he probado hasta ahora:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
iris %>% select(-drop.cols)

Error en -drop.cols: argumento no válido para el operador unario

iris %>% select_(.dots = -drop.cols)

Error en -drop.cols: argumento no válido para el operador unario

iris %>% select(!drop.cols)

Error en! Drop.cols: tipo de argumento no válido

iris %>% select_(.dots = !drop.cols)

Error en! Drop.cols: tipo de argumento no válido

Siento que me estoy perdiendo algo obvio porque parece una operación bastante útil que ya debería existir. En Github, alguien publicó un problema similar , y Hadley dijo que usara 'indexación negativa'. Eso es lo que (creo) he intentado, pero fue en vano. ¿Alguna sugerencia?

Respuestas:


127

Consulte la ayuda sobre select_vars. Eso le da algunas ideas adicionales sobre cómo trabajar con esto.

En tu caso:

iris %>% select(-one_of(drop.cols))

Gracias. Por alguna razón, esto funciona iris, pero no en mi marco de datos real ( irisfue un ejemplo de juguete). Mi marco de datos contiene 4558 filas y 147 columnas. El mensaje de error que recibí fue Error in eval(x$expr, data, x$env) : variable names are limited to 10000 bytes. ¿Alguna idea de por qué esto podría estar sucediendo?
Navaneethan Santhanam

1
Ah, parece que estaba cometiendo un error. Usé accidentalmente en select_varslugar de select. ¡Ahora funciona perfectamente!
Navaneethan Santhanam

5
¿Dónde se supone que debemos averiguar sobre funciones integradas como one_of? A menos que me falte algo, no aparece en la documentación del paquete ( help(package='dplyr')).
geoteoría

4
@geotheory, en realidad one_of está documentado. ver help(one_of, package = "dplyr"). Al menos está en la versión de paquete 0.5.0. Pero es útil leer los blogs que publica Hadley cuando hay actualizaciones de uno de sus paquetes. Y algunas funciones están documentadas dentro de otras funciones. Desafortunadamente, eso requiere leer toda la documentación, lo que hago principalmente cuando quiero algo que no es inmediatamente obvio o posible con la función.
phiver

10
Gracias. ¿Cómo se entera de estas funciones en primer lugar, en términos de documentación?
geoteoría

67

intenta también

## Notice the lack of quotes
iris %>% select (-c(Sepal.Length, Sepal.Width))

5
¡Excelente! Realmente útil cuando tenemos que eliminar columnas copiando y pegando los nombres de la consola.
Pablo Casas

37

Más allá, select(-one_of(drop.cols))hay un par de otras opciones para eliminar columnas select()que no implican la definición de todos los nombres de columna específicos (usando los datos de muestra dplyr starwars para obtener más variedad en los nombres de columna):

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 

Es select_if(~!is.list(.))equivalente a select_if(is.list(.))?
Jasha

3
En este caso ~es purrr abreviatura para definir una función anónima, no es otro símbolo para no. Por ejemplo, estos dos significan lo mismo function(x) {!is.list(x)}y ~!is.list(.). Piense ~en la abreviatura de function(.).
SlyFox

8

Tenga cuidado con la select()función, porque se usa tanto en los paquetes dplyr como en MASS, por lo que si MASS está cargado, es posible que select () no funcione correctamente. Para saber qué paquetes están cargados, escríbalo sessionInfo()y búsquelo en la sección "otros paquetes adjuntos:". Si está cargado, escriba detach( "package:MASS", unload = TRUE )y su select()función debería funcionar nuevamente.


12
alternativamente, puede acceder a la función directamente en el espacio de nombres del paquete dplyr::select().
Triamus

2
Me he encontrado con este problema con demasiada frecuencia. Ahora suelo definir una nueva función en la parte superior de mi script dselect <- dplyr::select().
filups21

5

Podemos intentar

iris %>% 
      select_(.dots= setdiff(names(.),drop.cols))

Gracias @akrun, esto funcionó perfectamente. Sin embargo, dada la dplyrcapacidad del entorno para hacer que las tareas de análisis básicas sean fáciles de leer y escribir, me decepciona que la solución real parezca una solución alternativa.
Navaneethan Santhanam

@NavaneethanSanthanam En realidad, el one_ofde la otra solución es el camino a seguir. Me habia olvidado de eso.
akrun

3

Otra forma es mutar las columnas no deseadas a NULL, esto evita los paréntesis incrustados:

head(iris,2) %>% mutate_at(drop.cols, ~NULL)
#   Petal.Length Petal.Width Species
# 1          1.4         0.2  setosa
# 2          1.4         0.2  setosa

Esto tampoco da una advertencia si una columna no está allí.
skoz

3

Si usted tiene un carácter especial en los nombres de columna, ya sea selecto select_no funcionen como se esperaba. Esta propiedad dplyrde usar ".". Para hacer referencia al conjunto de datos en la pregunta, se puede utilizar la siguiente línea para resolver este problema:

drop.cols <- c('Sepal.Length', 'Sepal.Width')
  iris %>% .[,setdiff(names(.),drop.cols)]

Se desaconsejan las respuestas de solo código. Proporcione una explicación de cómo funciona la respuesta y en qué se diferencia de las respuestas ya presentes.
Ralf Stubner

¡¡Gracias!! Ninguna de las otras soluciones anteriores funcionó por esta razón exacta.
Marty999

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.