it-swarm.com.de

Löschen Sie Datenrahmenspalten nach Namen

Ich habe eine Reihe von Spalten, die ich aus einem Datenrahmen entfernen möchte. Ich weiß, dass wir sie einzeln löschen können mit etwas wie:

df$x <- NULL

Aber ich hatte gehofft, dies mit weniger Befehlen zu tun.

Außerdem weiß ich, dass ich Spalten mit der folgenden Ganzzahlindizierung löschen könnte:

df <- df[ -c(1, 3:6, 12) ]

Ich bin jedoch besorgt, dass sich die relative Position meiner Variablen ändern könnte.

Angesichts der Stärke von R habe ich mir gedacht, dass es einen besseren Weg gibt, als jede Spalte einzeln abzulegen.

782
Btibert3

Sie können eine einfache Liste von Namen verwenden:

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)]

Alternativ können Sie eine Liste der zu speichernden Elemente erstellen und nach Namen sortieren:

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

BEARBEITEN: Für diejenigen, die noch nicht mit dem Argument drop der Indexierungsfunktion vertraut sind, tun Sie Folgendes, wenn Sie eine Spalte als Datenrahmen beibehalten möchten:

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

drop=TRUE (oder nicht erwähnt) löscht unnötige Dimensionen und gibt daher einen Vektor mit den Werten der Spalte y zurück.

829
Joris Meys

Es gibt auch den Befehl subset, der nützlich ist, wenn Sie wissen, welche Spalten Sie möchten:

df <- data.frame(a = 1:10, b = 2:11, c = 3:12)
df <- subset(df, select = c(a, c))

UPDATED nach Kommentar von @hadley: To drop Spalten a, c können Sie tun:

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

ist wahrscheinlich am einfachsten oder für mehrere Variablen:

within(df, rm(x, y))

Oder wenn es sich um data.tables (per Wie löscht man eine Spalte nach Namen in data.table? ) handelt:

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

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

oder für mehrere Variablen

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

dt[, !c("x", "y")]
164
Max Ghenis

Sie könnten %in% wie folgt verwenden:

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

list (NULL) funktioniert auch:

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"
45
Vincent

Es gibt eine potenziell leistungsfähigere Strategie, die auf der Tatsache basiert, dass grep () einen numerischen Vektor zurückgibt. Wenn Sie eine lange Liste von Variablen haben, wie ich sie in einem meiner Datensätze habe, einige Variablen mit der Endung ".A" und andere mit der Endung ".B", und Sie möchten nur die Variablen mit der Endung ".A" (zusammen mit Führen Sie mit allen Variablen, die keinem der Muster entsprechen, Folgendes aus:

dfrm2 <- dfrm[ , -grep("\\.B$", names(dfrm)) ]

Für den vorliegenden Fall wäre es am Beispiel von Joris Meys vielleicht nicht so kompakt, aber es wäre:

DF <- DF[, -grep( paste("^",drops,"$", sep="", collapse="|"), names(DF) )]
37
42-

Wenn Sie die Spalten nach Verweis entfernen und das interne Kopieren von data.frames vermeiden möchten, können Sie das Paket data.table und die Funktion := verwenden.

Sie können Zeichenvektornamen an die linke Seite des Operators := und NULL als RHS übergeben.

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]

Wenn Sie die Namen außerhalb des Aufrufs von [ als Zeichenvektor vordefinieren möchten, setzen Sie den Namen des Objekts in () oder {}, um die Auswertung der LHS im aufrufenden Bereich zu erzwingen nicht als Name im Geltungsbereich von 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.   

Sie können auch set verwenden, wodurch der Overhead von [.data.table vermieden wird und auch für data.frames funktioniert!

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)
37
mnel

Eine andere dplyr Antwort. Wenn Ihre Variablen eine gemeinsame Namensstruktur haben, können Sie starts_with() versuchen. Zum Beispiel

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

Wenn Sie eine Folge von Variablen im Datenrahmen ablegen möchten, können Sie : verwenden. Wenn Sie beispielsweise var2, var3 und alle Variablen dazwischen löschen möchten, bleibt nur var1 übrig:

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

Ausgabe:

    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)

Ausgabe:

        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
21
Kun Ren

Aus Interesse weist dies auf eine der seltsamen Inkonsistenzen in der Mehrfachsyntax von R hin. Beispiel für einen zweispaltigen Datenrahmen:

df <- data.frame(x=1, y=2)

Dies ergibt einen Datenrahmen

subset(df, select=-y)

aber das ergibt einen Vektor

df[,-2]

Dies alles wird in ?[ erklärt, aber es ist nicht genau das erwartete Verhalten. Na jedenfalls nicht für mich ...

20
jkeirstead

Andere Möglichkeit:

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

oder

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

Dplyr-Lösung

Ich bezweifle, dass dies hier unten viel Aufmerksamkeit erregen wird, aber wenn Sie eine Liste von Spalten haben, die Sie entfernen möchten, und Sie dies in einer dplyr Kette tun möchten, verwende ich one_of() in select Klausel:

Hier ist ein einfaches, reproduzierbares Beispiel:

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

mtcars <- mtcars %>%
  select(-one_of(undesired))

Dokumentation kann durch Ausführen von ?one_of oder hier gefunden werden:

http://genomicsclass.github.io/book/pages/dplyr_tutorial.html

18
User632716

Hier ist eine dplyr Vorgehensweise:

#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()

Ich mag das, weil es intuitiv zu lesen und zu verstehen ist, ohne Anmerkungen zu machen, und robust gegenüber Spalten, die ihre Position innerhalb des Datenrahmens ändern. Es folgt auch der vektorisierten Redewendung mit -, um Elemente zu entfernen.

17
c.gutierrez

Ich denke immer, dass es eine bessere Redewendung geben muss, aber für die Subtraktion von Spalten nach Namen neige ich dazu, Folgendes zu tun:

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
13
JD Long

In Bernd Bischls Paket BBmisc gibt es eine Funktion namens dropNamed(), die genau dies tut.

BBmisc::dropNamed(df, "x")

Der Vorteil besteht darin, dass das Wiederholen des Datenrahmenarguments vermieden wird und daher für die Weiterleitung in magrittr geeignet ist (genau wie bei den Ansätzen dplyr):

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

Abgesehen von select(-one_of(drop_col_names)), das in früheren Antworten gezeigt wurde, gibt es einige andere dplyr -Optionen zum Löschen von Spalten mithilfe von select(), bei denen nicht alle spezifischen Spaltennamen definiert werden (mithilfe der Beispieldaten von dplyr starwars für eine Vielzahl von Spaltennamen):

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

Eine andere Lösung, wenn Sie @ hadleys oben nicht verwenden möchten: Wenn "COLUMN_NAME" der Name der Spalte ist, die Sie löschen möchten:

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

Geben Sie den Datenrahmen und eine Zeichenfolge von durch Kommas getrennten Namen an, um Folgendes zu entfernen:

remove_features <- function(df, features) {
  rem_vec <- unlist(strsplit(features, ', '))
  res <- df[,!(names(df) %in% rem_vec)]
  return(res)
}

Verwendung :

remove_features(iris, "Sepal.Length, Petal.Width")

enter image description here

3
Cybernetic

Suchen Sie mit which den Index der Spalten, die Sie löschen möchten. Geben Sie diesen Indizes ein negatives Vorzeichen (*-1). Setzen Sie dann diese Werte auf eine Teilmenge, um sie aus dem Datenrahmen zu entfernen. Dies ist ein Beispiel.

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
1
milan