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 una 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 soltar cada columna una por una.
df#drop(var_name)
, y en su lugar, tenemos que hacer estas soluciones complicadas?Respuestas:
Puede usar una lista simple de nombres:
O, alternativamente, puede hacer una lista de los que desea conservar y hacer referencia a ellos por su nombre:
EDITAR: Para aquellos que aún no están familiarizados con el
drop
argumento de la función de indexación, si desea mantener una columna como marco de datos, debe:drop=TRUE
(o no mencionarlo) eliminará dimensiones innecesarias y, por lo tanto, devolverá un vector con los valores de la columnay
.fuente
DF[,keeps]
lugar deDF[keeps]
?También está el
subset
comando, útil si sabe qué columnas desea:ACTUALIZADO después del comentario de @hadley: Para colocar las columnas a, c, podría hacer:
fuente
subset
función R tuviera una opción como "allbut = FALSE", que "invierte" la selección cuando se establece en TRUE, es decir, conserva todas las columnas excepto las de laselect
lista.df[c("a", "c")]
subset
orden en el que no hay que poner comillas alrededor de los nombres de columna - supongo que no me importa escribir algunos caracteres adicionales sólo para evitar citar nombres :)subset
dentro de otras funciones.es probablemente la más fácil, o para múltiples variables:
O si está tratando con
data.table
s (según ¿Cómo elimina una columna por nombre en data.table? ):o para múltiples variables
fuente
within(df, rm(x))
Es, con mucho, la solución más limpia. Dado que esta es una posibilidad, cualquier otra respuesta parece innecesariamente complicada por un orden de magnitud.within(df, rm(x))
se no funciona si hay columnas duplicadas nombradasx
endf
.df <- data.frame(x = 1, y = 2); names(df) <- c("x", "x"); within(df, rm(x))
devolucionesdata.frame(x = 2, x = 2)
.within()
que es poderosa pero que también usa NSE. La nota en la página de ayuda establece claramente que para la programación se debe tener cuidado suficiente.Podrías usar
%in%
así:fuente
DF[ , !(names(DF) %in% drops)]
identical(post_time_1, post_time_2) [1] TRUE
= Dlist (NULL) también funciona:
fuente
Si desea eliminar las columnas por referencia y evitar la copia interna asociada con
data.frames
, puede usar eldata.table
paquete y la función:=
Puede pasar los nombres de un vector de caracteres al lado izquierdo del
:=
operador, yNULL
como el RHS.Si desea predefinir los nombres como vector de caracteres fuera de la llamada a
[
, ajuste el nombre del objeto en()
o{}
forzar la evaluación del LHS en el alcance de la llamada, no como un nombre dentro del alcance deDT
.También puede usar
set
, lo que evita la sobrecarga de[.data.table
, y también funciona paradata.frames
!fuente
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 yo en uno de mi conjunto de datos, algunas variables que terminan en ".A" y otras que terminan en ".B" y solo desea las que terminan en ".A" (junto con todas las variables que no coinciden con ninguno de los patrones, haga esto:
Para el caso en cuestión, utilizando el ejemplo de Joris Meys, podría no ser tan compacto, pero sería:
fuente
drops
en primer lugar comopaste0("^", drop_cols, "$")
, esto se vuelve mucho más agradable (leer: más compacto) consapply
:DF[ , -sapply(drops, grep, names(DF))]
Otra
dplyr
respuesta Si sus variables tienen alguna estructura de nombres común, puede intentarlostarts_with()
. Por ejemploSi desea soltar una secuencia de variables en el marco de datos, puede usar
:
. Por ejemplo, si quisiera eliminarvar2
,var3
y todas las variables intermedias, simplemente le quedaríavar1
:fuente
select()
, comocontains()
omatches()
, que también acepta expresiones regulares.Otra posibilidad:
o
fuente
setdiff
es el óptimo, especialmente en el caso de una gran cantidad de columnas.df <- df[ , -which(grepl('a|c', names(df)))]
Salida:
Salida:
fuente
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 una
dplyr
cadena que usoone_of()
en laselect
cláusula:Aquí hay un ejemplo simple y reproducible:
La documentación se puede encontrar ejecutando
?one_of
o aquí:http://genomicsclass.github.io/book/pages/dplyr_tutorial.html
fuente
Por interés, esto señala una de las extrañas inconsistencias de sintaxis múltiple de R. Por ejemplo, dado un marco de datos de dos columnas:
Esto da un marco de datos
pero esto da un vector
Todo esto se explica
?[
pero no es exactamente el comportamiento esperado. Bueno, al menos no para mí ...fuente
Aquí hay una
dplyr
manera de hacerlo:Me gusta esto porque es intuitivo para leer y comprender sin anotaciones y robusto para que las columnas cambien de posición dentro del marco de datos. También sigue el idioma vectorizado que se usa
-
para eliminar elementos.fuente
%<>%
operador para reemplazar el objeto de entrada que podría simplificarsedf %<>% select(-col.to.drop.1, -col.to.drop.2, ..., -col.to.drop.6)
dplyr
podría ser más fácil agruparlas y poner solo un menos:df.cut <- df %>% select(-c(col.to.drop.1, col.to.drop.2, ..., col.to.drop.n))
Sigo pensando que debe haber un idioma mejor, pero para restar columnas por nombre, tiendo a hacer lo siguiente:
fuente
df[,-match(c("e","f"),names(df))]
-
?Hay una función llamada
dropNamed()
en elBBmisc
paquete de Bernd Bischl que hace exactamente esto.La ventaja es que evita repetir el argumento del marco de datos y, por lo tanto, es adecuado para conectar
magrittr
(al igual que losdplyr
enfoques):fuente
Otra solución si no desea utilizar @ hadley's arriba: si "COLUMN_NAME" es el nombre de la columna que desea colocar:
fuente
COLUMN_NAME
no está endf
(compruebe usted mismo:)df<-data.frame(a=1,b=2)
. (3)df[,names(df) != "COLUMN_NAME"]
es más simple y no sufre de (2)Más allá de lo
select(-one_of(drop_col_names))
demostrado en respuestas anteriores, hay un par de otrasdplyr
opciones para colocar columnasselect()
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 los nombres de columna):Si necesita descartar una columna que puede o no existir en el marco de datos, aquí hay un pequeño giro
select_if()
que, a diferencia del usoone_of()
, no arrojará unaUnknown columns:
advertencia si el nombre de la columna no existe. En este ejemplo, 'bad_column' no es una columna en el marco de datos:fuente
Proporcione el marco de datos y una cadena de nombres separados por comas para eliminar:
Uso :
fuente
Encuentre el índice de las columnas que desea soltar usando
which
. Dé a estos índices un signo negativo (*-1
). Luego subconjunto en esos valores, lo que los eliminará del marco de datos. Esto es un ejemplo.fuente
Si tiene una
data.frame
memoria grande y tiene poco uso de memoria[
. . . . orm
ywithin
para eliminar columnas de unadata.frame
, comosubset
es actualmente (R 3.6.2) usando más memoria - al lado de la pista del manual para utilizarsubset
de forma interactiva .fuente