Mam wiele kolumn, które chciałbym usunąć z ramki danych. Wiem, że możemy je usuwać indywidualnie za pomocą:
df$x <- NULL
Miałem jednak nadzieję, że zrobię to z mniejszą liczbą poleceń.
Wiem też, że mogłem upuścić kolumny za pomocą indeksowania liczb całkowitych w następujący sposób:
df <- df[ -c(1, 3:6, 12) ]
Obawiam się jednak, że względne położenie moich zmiennych może ulec zmianie.
Biorąc pod uwagę moc R, pomyślałem, że może być lepszy sposób niż upuszczanie każdej kolumny jedna po drugiej.
df#drop(var_name)
, a zamiast tego musimy wykonać te skomplikowane obejścia?Odpowiedzi:
Możesz użyć prostej listy nazw:
Ewentualnie możesz utworzyć listę tych, którzy będą przechowywać, i odwołać się do nich według nazwy:
EDYCJA: Jeśli nadal nie
drop
znasz argumentu funkcji indeksowania, jeśli chcesz zachować jedną kolumnę jako ramkę danych, wykonaj następujące czynności:drop=TRUE
(lub nie wspominając o nim) upuści niepotrzebne wymiary, a zatem zwróci wektor z wartościami kolumnyy
.źródło
DF[,keeps]
zamiastDF[keeps]
?Jest też
subset
polecenie przydatne, jeśli wiesz, które kolumny chcesz:AKTUALIZACJA po komentarzu @hadley: Aby upuścić kolumny a, c możesz:
źródło
subset
funkcja R miała opcję typu „allbut = FALSE”, która „odwraca” zaznaczenie, gdy jest ustawiona na PRAWDA, tzn. Zachowuje wszystkie kolumny oprócz tych zselect
listy.df[c("a", "c")]
subset
polecenia, w którym nie trzeba umieszczać cudzysłowów wokół nazw kolumn - chyba nie mam nic przeciwko wpisywaniu kilku dodatkowych znaków, aby uniknąć cytowania nazw :)subset
wewnątrz innych funkcji.jest prawdopodobnie najłatwiejszy lub dla wielu zmiennych:
Lub jeśli masz do czynienia z
data.table
s (według Jak usunąć kolumnę według nazwy w data.table? ):lub dla wielu zmiennych
źródło
within(df, rm(x))
jest zdecydowanie najczystszym rozwiązaniem. Biorąc pod uwagę, że jest to możliwe, każda inna odpowiedź wydaje się niepotrzebnie skomplikowana o rząd wielkości.within(df, rm(x))
będzie nie działać, jeśli nie są zduplikowane kolumny nazwanex
wdf
.df <- data.frame(x = 1, y = 2); names(df) <- c("x", "x"); within(df, rm(x))
zwracadata.frame(x = 2, x = 2)
.within()
która jest potężna, ale używa również NSE. Uwaga na stronie pomocy wyraźnie stwierdza, że do programowania należy zachować wystarczającą ostrożność.Możesz użyć
%in%
tego w następujący sposób:źródło
DF[ , !(names(DF) %in% drops)]
identical(post_time_1, post_time_2) [1] TRUE
= Dlista (NULL) działa również:
źródło
Jeśli chcesz usunąć kolumny przez odniesienie i uniknąć powiązanego z nimi wewnętrznego kopiowania
data.frames
, możesz użyćdata.table
pakietu i funkcji:=
Nazwy wektorów znaków możesz przekazać po lewej stronie
:=
operatora iNULL
jako RHS.Jeśli chcesz wstępnie zdefiniować nazwy jako wektor znaków poza wywołaniem
[
, zawiń nazwę obiektu()
lub{}
wymuś, aby LHS był oceniany w zakresie wywołującym, a nie jako nazwa w zakresieDT
.Możesz także użyć
set
, co pozwala uniknąć narzutu[.data.table
, a także działadata.frames
!źródło
Istnieje potencjalnie silniejsza strategia oparta na fakcie, że grep () zwróci wektor liczbowy. Jeśli masz długą listę zmiennych, tak jak ja, w jednym z moich zbiorów danych, niektóre zmienne, które kończą się na „.A” i inne, które kończą się na „.B”, a chcesz tylko te, które kończą się na „.A” (razem ze wszystkimi zmiennymi, które nie pasują do żadnego wzorca, wykonaj następujące czynności:
W omawianym przypadku, na przykładzie Jorisa Meysa, może on nie być tak kompaktowy, ale byłby to:
źródło
drops
przede wszystkim jakopaste0("^", drop_cols, "$")
, stanie się to znacznie ładniejsze (czytaj: bardziej kompaktowe) zsapply
:DF[ , -sapply(drops, grep, names(DF))]
Kolejna
dplyr
odpowiedź. Jeśli twoje zmienne mają jakąś wspólną strukturę nazewnictwa, możesz spróbowaćstarts_with()
. Na przykładJeśli chcesz upuścić sekwencję zmiennych w ramce danych, możesz użyć
:
. Na przykład, jeśli chcesz upuścićvar2
,var3
a wszystkie zmienne pomiędzy, będziesz po prostu zvar1
:źródło
select()
, takich jakcontains()
lubmatches()
, które również akceptują wyrażenie regularne.Inna możliwość:
lub
źródło
setdiff
jest optymalne, szczególnie w przypadku bardzo dużej liczby kolumn.df <- df[ , -which(grepl('a|c', names(df)))]
Wynik:
Wynik:
źródło
Rozwiązanie Dplyr
Wątpię, czy to przyniesie wiele uwagi tutaj, ale jeśli masz listę kolumn, które chcesz usunąć i chcesz to zrobić w
dplyr
łańcuchu, którego używamone_of()
wselect
klauzuli:Oto prosty, odtwarzalny przykład:
Dokumentację można znaleźć, uruchamiając
?one_of
lub tutaj:http://genomicsclass.github.io/book/pages/dplyr_tutorial.html
źródło
Z braku zainteresowania oznacza to jedną z dziwnych wielokrotnych niespójności składniowych R. Na przykład biorąc pod uwagę dwukolumnową ramkę danych:
Daje to ramkę danych
ale to daje wektor
Wszystko to wyjaśniono w,
?[
ale nie jest to dokładnie oczekiwane zachowanie. Cóż, przynajmniej nie dla mnie ...źródło
Oto
dplyr
jak to zrobić:Podoba mi się to, ponieważ jest intuicyjny w czytaniu i zrozumieniu bez adnotacji i niezawodny dla kolumn zmieniających położenie w ramce danych. Podąża również za wektoryzowanym idiomem używanym
-
do usuwania elementów.źródło
%<>%
operator do zastąpienia obiektu wejściowego, do którego można by to uprościćdf %<>% select(-col.to.drop.1, -col.to.drop.2, ..., -col.to.drop.6)
dplyr
łatwiej może być pogrupować je i umieścić tylko jeden minus:df.cut <- df %>% select(-c(col.to.drop.1, col.to.drop.2, ..., col.to.drop.n))
Ciągle myślę, że musi istnieć lepszy idiom, ale do odejmowania kolumn według nazwy mam tendencję do wykonywania następujących czynności:
źródło
df[,-match(c("e","f"),names(df))]
-
?W pakiecie
dropNamed()
Bernda Bischla znajduje się funkcja,BBmisc
która właśnie to robi.Zaletą jest to, że unika się powtarzania argumentu ramki danych, a zatem nadaje się do przesyłania strumieniowego
magrittr
(podobnie jakdplyr
podejścia):źródło
Inne rozwiązanie, jeśli nie chcesz używać powyższych @ hadley: Jeśli „COLUMN_NAME” to nazwa kolumny, którą chcesz upuścić:
źródło
COLUMN_NAME
nie madf
(sprawdź sam:)df<-data.frame(a=1,b=2)
. (3)df[,names(df) != "COLUMN_NAME"]
jest prostszy i nie cierpi na (2)Oprócz
select(-one_of(drop_col_names))
wcześniejszych odpowiedzi, istnieje kilka innychdplyr
opcji usuwania kolumnselect()
, które nie wymagają zdefiniowania wszystkich konkretnych nazw kolumn (użycie przykładowych danych Dplyr Starwars dla różnych odmian nazw kolumn):Jeśli chcesz upuścić kolumnę, która może istnieć w ramce danych, możesz ją nieco zmienić
select_if()
, w przeciwieństwie do użyciaone_of()
, nie rzuciUnknown columns:
ostrzeżenia, jeśli nazwa kolumny nie istnieje. W tym przykładzie „bad_column” nie jest kolumną w ramce danych:źródło
Podaj ramkę danych i ciąg nazw oddzielonych przecinkami, aby usunąć:
Zastosowanie :
źródło
Znajdź indeks kolumn, które chcesz upuścić
which
. Nadaj tym indeksom znak ujemny (*-1
). Następnie podzestaw na te wartości, które usuną je z ramki danych. To jest przykład.źródło
Jeśli masz duży
data.frame
i masz mało pamięci[
. . . . lubrm
iwithin
aby usunąć kolumny zdata.frame
, jaksubset
jest obecnie (R 3.6.2), wykorzystując więcej pamięci - oprócz wskazówek zawartych w instrukcji, aby używaćsubset
interaktywnie .źródło