我有許多列想從數據框中刪除。我知道我們可以刪除他們單獨使用類似的東西:按名稱刪除數據框列
df$x <- NULL
但我希望用更少的命令做到這一點。
另外,我知道我可以使用索引的整數這樣的刪除列:
df <- df[ -c(1, 3:6, 12) ]
但我關心的是我的變量的相對位置可能會改變。
給定的R多麼強大,我想有可能是比一個下探每列一個更好的辦法。
我有許多列想從數據框中刪除。我知道我們可以刪除他們單獨使用類似的東西:按名稱刪除數據框列
df$x <- NULL
但我希望用更少的命令做到這一點。
另外,我知道我可以使用索引的整數這樣的刪除列:
df <- df[ -c(1, 3:6, 12) ]
但我關心的是我的變量的相對位置可能會改變。
給定的R多麼強大,我想有可能是比一個下探每列一個更好的辦法。
您可以使用名稱的簡單列表:
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)]
,或者,你可以讓這些列表,以保持並通過名稱引用它們:
keeps <- c("y", "a")
DF[keeps]
編輯: 對於那些還不熟悉索引功能參數drop
的人,如果你想保留一列作爲數據幀,你需要:
keeps <- "y"
DF[ , keeps, drop = FALSE]
drop=TRUE
(或不提它)將下降不必要的尺寸,並因此返回一個向量與y
列的值。
您可以使用%in%
這樣的:
df[, !(colnames(df) %in% c("x","bar","foo"))]
我是否錯過了某些東西,或者這與Joris的答案的第一部分是否有效地相同? 'DF [,!(名稱(DF)%以%爲單位)]' – 2016-04-28 05:46:37
@DanielFletcher:這是一樣的。看看答案的時間戳。我們同時回答... 5年前。 :) – 2016-04-28 13:01:18
堅果。 '相同(post_time_1,post_time_2)[1] TRUE' = D – 2016-04-30 02:47:32
另外還有subset
命令,有用的,如果你知道你想要的列:
df <- data.frame(a = 1:10, b = 2:11, c = 3:12)
df <- subset(df, select = c(a,c))
通過@hadley後評論更新:要下降列a,c你可以這樣做:
df <- subset(df, select = -c(a,c))
我真的希望R'子集'函數有一個選項,如「allbut = FALSE」,「反轉」選項設置爲TRUE時,即保留所有列*,除了* select列表中的列。 – 2011-01-05 14:56:20
@prasad,請參閱下面的@joris答案。沒有任何子集標準的子集有點矯枉過正。試試看:'df [c(「a」,「c」)]' – 2011-01-05 15:16:33
@JD我知道這一點,但我喜歡'subset'命令的語法方便性,因爲你不需要在列名 - 我想我不介意輸入一些額外的字符,以避免引用名稱:) – 2011-01-05 15:18:46
我一直在想,必須有一個更好的成語,但對於名字列的減法,我傾向於做到以下幾點:
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
否定匹配不是一個好主意 - ''df [, - match(c (「e」,「f」),names(df))]' – hadley 2011-01-05 18:33:24
有根據的事實是grep的一個潛在的更強大的戰略()將返回一個數字向量。如果你有一長串變量,就像我在其中一個數據集中做的那樣,一些變量以「.A」結尾,而其他變量以「.B」結尾,而你只需要以「.B」結尾的變量。A」(所有的變量一起不要麼模式匹配,這樣做:
dfrm2 <- dfrm[ , -grep("\\.B$", names(dfrm)) ]
手頭的情況下,使用里斯Meys例如,它可能不會像緊湊,但它是:
DF <- DF[, -grep(paste("^",drops,"$", sep="", collapse="|"), names(DF))]
如果我們首先將'drops'定義爲'paste0(「^」,drop_cols,「$」)',這會變得好多了:更緊湊)使用'sapply':'DF [,-sapply(drops,grep,names(DF))]' – MichaelChirico 2016-04-13 20:31:19
如果您想通過引用刪除列,並避免與data.frames
相關聯,那麼你可以使用data.table
包和功能:=
您可以通過一個特徵向量的名字到:=
運營商的左側的內部複製,和NULL
作爲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]
如果您想預定義的名字作爲作爲調用[
外面特徵向量,在()
或{}
包裹對象的名稱,迫使LHS在呼叫範圍來評價並不像內的名字範圍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.
您還可以使用set
,這避免了[.data.table
,開銷,也適用於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)
出於興趣,這標誌着R的奇怪的多個語法不一致之一。例如,給定一個具有兩列的數據幀:
df <- data.frame(x=1, y=2)
這給出了一個數據幀
subset(df, select=-y)
但是這給一個矢量
df[,-2]
這全部在?[
說明,但它不是準確的預期行爲。至少不對我來說...
within(df, rm(x))
是可能比較容易,或多個變量:
within(df, rm(x, y))
或者,如果你正在處理data.table
S(每How do you delete a column by name in data.table?):
dt[, x := NULL] # deletes column x by reference instantly
dt[, !"x", with=FALSE] # selects all but x into a new data.table
或多個變量
dt[, c("x","y") := NULL]
dt[, !c("x", "y"), with=FALSE]
在data.table
(installation instructions)的開發版本,with = FALSE
不再是必要的:
dt[ , !"x"]
dt[ , !c("x", "y")]
'最乾淨的解決方案。鑑於這是一種可能性,所有其他答案似乎都不必要地複雜一個數量級。 – 2015-10-02 01:00:10
請注意,如果在'df'中存在名爲'x'的重複列,'within(df,rm(x))'將不工作。 – MichaelChirico 2016-07-15 19:51:54
@MichaelChirico澄清,它既不刪除,但似乎改變數據的價值觀。如果出現這種情況,則會遇到更大的問題,但這裏有一個例子:'df < - data.frame(x = 1,y = 2);名稱(df)< - c(「x」,「x」);在(df,rm(x))內返回'data.frame(x = 2,x = 2)'。 – 2017-03-10 22:23:11
列表(NULL)也適用:
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"
太棒了!這將NULL分配以一種自然的方式擴展到單個列,並且(看似)避免了複製(雖然我不知道底層會發生什麼,所以它在內存使用方面可能沒有效率......但在我看來很清楚語法上更有效率。) – 2014-05-20 16:15:48
您不需要列表(NULL),NULL就足夠了。例如:dat [,4] = NULL – CousinCocaine 2014-07-07 08:29:07
OP的問題是如何刪除多列。 dat [,4:5] < - NULL將不起作用。這就是list(NULL)進來的地方。它適用於1列或更多列。 – Vincent 2014-09-16 00:01:45
DF <- data.frame(
x=1:10,
y=10:1,
z=rep(5,10),
a=11:20
)
DF
輸出:
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)
輸出:
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
這裏是去做一個dplyr
方式:
#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()
我喜歡這個,因爲它直觀的閱讀&理解沒有註釋和對列在數據框架內的位置變化具有魯棒性。它也遵循矢量化慣用法,使用-
刪除元素。
此外,(1)用戶想要替換原來的df(2)magrittr具有用於替換輸入對象的'%<>%'操作符,它可以簡化爲'df%<>%select select(-col.to.drop.1 ,-col.to.drop.2,...,-col.to.drop.6)' – Marek 2016-11-23 11:39:48
如果你有一長串列要刪除,使用'dplyr',可能會更容易將它們分組並放入只有一個減:'df.cut <- df %>%select(-c(col.to.drop.1,col.to.drop.2,...,col.to.drop.n))' – 2017-05-04 06:32:12
另一個dplyr
答案。如果你的變量有一些共同的命名結構,你可以試試starts_with()
。例如
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
如果你想在數據幀丟棄的變量序列,您可以使用:
。例如,如果你想砸var2
,var3
,並所有變量之間,你只是會留下var1
:
df2 <- df1 %>% select(-c(var2:var3))
df2
# var1
#1 0.75879754
#2 0.31168919
#3 0.03983268
有一個在貝恩德Bischl的BBmisc
呼包dropNamed()
一個函數,它正是這樣做的。
BBmisc::dropNamed(df, "x")
的優點在於,它避免了重複數據幀的參數,因此適合於在管路magrittr
(就像dplyr
方法):
df %>% BBmisc::dropNamed("x")
另一種解決方案,如果你不希望使用@哈德利的上面:如果「COLUMN_NAME」是列的名稱要刪除:
df[,-which(names(df) == "COLUMN_NAME")]
(1)問題是一次刪除多個列。 (2)如果'COLUMN_NAME'不在'df'中(檢查你自己:'df <-data.frame(a = 1,b = 2)'),它將不起作用。 (3)'df [,names(df)!=「COLUMN_NAME」]'更簡單,不會受到(2) – Marek 2016-11-23 11:34:10
您能提供更多關於此答案的信息嗎? – 2018-01-17 13:04:46
我懷疑這會得到多少關注到這裏,但如果你甲肝
下面是一個簡單的,可再現的例子:
undesired <- c('mpg', 'cyl', 'hp')
mtcars %>%
select(-one_of(undesired))
文檔可以是您要刪除,並希望做一個dplyr
鏈我用one_of()
的select
子句中的列EA名單
http://genomicsclass.github.io/book/pages/dplyr_tutorial.html
子集功能效果更好,因爲它不會轉換成數據幀有一列到一個載體 – mut1na 2013-06-28 09:06:09
@ mut1na檢查:通過運行
?one_of
或在這裏找到參數drop =索引函數的FALSE。 – 2013-06-28 10:10:19不應該是'DF [,保持]'而不是'DF [保持]'嗎? – lindelof 2014-10-28 13:53:32