Upuść kolumny ramki danych według nazwy

Mam kilka kolumn, które chciałbym usunąć z ramki danych. Wiem, że możemy je usuwać pojedynczo używając czegoś takiego:

df$x <- NULL

Ale miałem nadzieję zrobić to z mniejszą ilością komend.

Również Wiem, że mógłbym upuścić kolumny używając indeksowania liczb całkowitych w ten sposób:

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

Ale obawiam się, że względna pozycja moich zmiennych może się zmienić.

Biorąc pod uwagę, jak potężne jest R, pomyślałem, że może być lepszy sposób niż opuszczanie każdej kolumny po jednej przez jeden.

Author: Henrik, 2011-01-05

19 answers

Możesz użyć prostej listy nazw:

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

Lub, alternatywnie, możesz zrobić listę tych, które należy zachować i odnieść się do nich po nazwie:

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

Edytuj : Dla tych, którzy nadal nie znają argumentu drop funkcji indeksowania, jeśli chcesz zachować jedną kolumnę jako ramkę danych, wykonaj:

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

drop=TRUE (lub nie wspominając o tym) zrzuci niepotrzebne wymiary, a tym samym zwróci wektor o wartościach kolumny y.

 753
Author: Joris Meys,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-26 20:57:39

Istnieje również polecenie subset, przydatne, jeśli wiesz, które kolumny chcesz:

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

Zaktualizowano po komentarzu przez @ hadley: to drop kolumny A, c można zrobić:

df <- subset(df, select = -c(a, c))
 369
Author: Prasad Chalasani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-08 01:02:57
within(df, rm(x))

Jest prawdopodobnie najłatwiejszy, lub dla wielu zmiennych:

within(df, rm(x, y))

Lub jeśli masz do czynienia z data.table s (per Jak usunąć kolumnę po nazwie w danych.stolik?):

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

dt[, !"x", with=FALSE]   # selects all but x into a new data.table

Lub dla wielu zmiennych

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

dt[, !c("x", "y"), with=FALSE]

W wersji rozwojowej data.table (Instrukcje Instalacji), with = FALSE nie jest już konieczne:

dt[ , !"x"]
dt[ , !c("x", "y")]
 124
Author: Max Ghenis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:26

Możesz użyć %in% w ten sposób:

df[, !(colnames(df) %in% c("x","bar","foo"))]
 93
Author: Joshua Ulrich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-05 14:40:26

List (NULL) działa również:

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"
 40
Author: Vincent,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-13 20:24:24

Jeśli chcesz usunąć kolumny przez odniesienie i uniknąć wewnętrznego kopiowania związanego z data.frames, możesz użyć pakietu data.table i funkcji :=

Można przekazać nazwy wektorów znaków po lewej stronie operatora := i NULL jako 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]

Jeśli chcesz predefiniować nazwy jako wektor znaków poza wywołaniem do [, zawiń nazwę obiektu w () lub {}, aby wymusić obliczanie LHS w zakresie wywołania, a nie jako nazwa w zakresie 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.   

Można również użyć set, co pozwala uniknąć napowietrznych [.data.table, a także działa dla 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)
 36
Author: mnel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-21 01:17:06

Istnieje potencjalnie potężniejsza strategia oparta na fakcie, że grep() zwróci wektor liczbowy. Jeśli masz długą listę zmiennych, tak jak ja w jednym z moich zestawów danych, niektóre zmienne, które kończą się".A "i inne, które się kończą".B "i chcesz tylko te, które się kończą".A" (wraz ze wszystkimi zmiennymi, które nie pasują do żadnego wzorca, zrób to:

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

W omawianym przypadku, używając przykładu Jorisa Meysa, może nie być tak zwarty, ale byłby:

DF <- DF[, -grep( paste("^",drops,"$", sep="", collapse="|"), names(DF) )]
 35
Author: 42-,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-24 16:45:59

Z ciekawości, oznacza to jedną z dziwnych, wielokrotnych niespójności składniowych R. Na przykład podano dwukolumnową ramkę danych:

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

To daje ramkę danych

subset(df, select=-y)

Ale to daje wektor

df[,-2]
To wszystko jest wyjaśnione w ?[, ale nie jest to dokładnie oczekiwane zachowanie. Przynajmniej nie dla mnie...
 19
Author: jkeirstead,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-02 18:42:27

Kolejna dplyr odpowiedź. Jeśli Twoje zmienne mają wspólną strukturę nazewnictwa, możesz spróbować starts_with(). Na przykład

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

Jeśli chcesz upuścić sekwencję zmiennych do ramki danych, możesz użyć :. Na przykład, jeśli chcesz upuścić var2, var3, i wszystkie zmienne pomiędzy, zostałbyś z var1:

df2 <- df1 %>% select(-c(var2:var3) )  
df2
#        var1
#1 0.75879754
#2 0.31168919
#3 0.03983268
 19
Author: Pat W.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-22 20:37:02

Inna możliwość:

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

Lub

df <- df[, grep('^(a|c)$', names(df), invert=TRUE)]
 18
Author: scentoni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-11 19:07:36
DF <- data.frame(
  x=1:10,
  y=10:1,
  z=rep(5,10),
  a=11:20
)
DF

Wyjście:

    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)

Wyjście:

        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
 18
Author: Kun Ren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-12 07:37:32

Oto dplyr sposób na to:

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

Podoba mi się to, ponieważ jest intuicyjny do czytania i rozumienia bez adnotacji i wytrzymały do kolumn zmieniających pozycję w ramce danych. Jest on również zgodny z idiomem vectorized używającym - do usuwania elementów.

 16
Author: c.gutierrez,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-23 19:16:00

Ciągle myślę, że musi być lepszy idiom, ale dla odejmowania kolumn po nazwie, zwykle robię co następuje:

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
 10
Author: JD Long,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-05 17:21:58

W pakiecie Bernda Bischla BBmisc istnieje funkcja o nazwie dropNamed(), która robi dokładnie to samo.

BBmisc::dropNamed(df, "x")

Zaletą jest to, że unika się powtarzania argumentu ramki danych i dlatego nadaje się do orurowania w magrittr (podobnie jak podejście dplyr):

df %>% BBmisc::dropNamed("x")
 10
Author: krlmlr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-04 14:06:22

Dplyr Solution

Wątpię, żeby to przyciągnęło tu uwagę, ale jeśli masz listę kolumn, które chcesz usunąć, i chcesz to zrobić w dplyr łańcuchu używam one_of() w select klauzuli:

Oto prosty, powtarzalny przykład:

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

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

Dokumentację można znaleźć uruchamiając ?one_of lub tutaj:

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

 9
Author: User632716,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-02 14:02:14

Inne rozwiązanie, jeśli nie chcesz używać @hadley ' s powyżej: jeśli "COLUMN_NAME" jest nazwą kolumny, którą chcesz upuścić:

df[,-which(names(df) == "COLUMN_NAME")]
 6
Author: Nick Keramaris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-25 22:57:20

Poza select(-one_of(drop_col_names)) wykazanymi we wcześniejszych odpowiedziach, istnieje kilka innych opcji dplyr do upuszczania kolumn za pomocą select(), które nie wymagają definiowania wszystkich konkretnych nazw kolumn (używając przykładowych danych dplyr starwars dla pewnej odmiany nazw kolumn):

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 
 2
Author: sbha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-03 02:11:25

Podaj ramkę danych oraz ciąg nazw rozdzielonych przecinkami do usunięcia:

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

Użycie :

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

Tutaj wpisz opis obrazka

 0
Author: Cybernetic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-15 16:51:02

Znajdź indeks kolumn, które chcesz upuścić za pomocą which. Nadaj indeksom znak ujemny (*-1). Następnie podgrupuj te wartości, co usunie je z ramki danych. To jest przykład.

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
 0
Author: milan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-17 11:42:03