我想从数据框中删除多个列。我知道我们可以使用以下内容单独删除它们:
df$x <- NULL
但我希望用更少的命令来做到这一点。
另外,我知道我可以使用整数索引来删除列,如下所示:
df <- df[ -c(1, 3:6, 12) ]
但我担心我的变量的相对位置可能会改变。
鉴于R有多强大,我认为可能有一种更好的方法,就是逐一删除每一列。
答案 0 :(得分:812)
您可以使用简单的名称列表:
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
列的向量。
答案 1 :(得分:397)
还有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))
答案 2 :(得分:151)
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"] # Selects all but x into a new data.table.
或多个变量
dt[, c("x","y") := NULL]
dt[, !c("x", "y")]
答案 3 :(得分:101)
您可以像这样使用%in%
:
df[, !(colnames(df) %in% c("x","bar","foo"))]
答案 4 :(得分:44)
list(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"
答案 5 :(得分:37)
基于grep()将返回数字向量这一事实,可能有更强大的策略。如果你在我的一个数据集中有一长串变量,那么一些变量以“.A”结尾,而其他变量以“.B”结尾,你只想要那些以“.A”结尾的变量(沿着如果所有变量都不匹配任何模式,请执行以下操作:
dfrm2 <- dfrm[ , -grep("\\.B$", names(dfrm)) ]
对于手头的情况,使用Joris Meys的例子,它可能不那么紧凑,但它会是:
DF <- DF[, -grep( paste("^",drops,"$", sep="", collapse="|"), names(DF) )]
答案 6 :(得分:37)
如果您想通过引用删除列并避免与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)
答案 7 :(得分:22)
另一个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
答案 8 :(得分:20)
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
答案 9 :(得分:20)
出于兴趣,这标志着R的一个奇怪的多语法不一致。例如,给定一个两列数据框:
df <- data.frame(x=1, y=2)
这给出了一个数据框
subset(df, select=-y)
但这会给出一个向量
df[,-2]
这在?[
中都有解释,但并不是完全预期的行为。好吧,至少不是我...
答案 10 :(得分:19)
另一种可能性:
df <- df[, setdiff(names(df), c("a", "c"))]
或
df <- df[, grep('^(a|c)$', names(df), invert=TRUE)]
答案 11 :(得分:18)
这是一种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()
我喜欢这个,因为它直观易读。理解没有注释和鲁棒的列更改数据框内的位置。它还遵循使用-
移除元素的矢量化习语。
答案 12 :(得分:16)
Dplyr解决方案
我怀疑这会引起很多关注,但是如果你有一个要删除的列列表,并且想要在PublicKey publicKey = KeyUtils.readPublicKey(publicKeyPath, "EC");
Cipher cipher = Cipher.getInstance("ECIESwithAES-CBC/NONE/PKCS7Padding", new BouncyCastleProvider());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedData = cipher.doFinal(dataToEncrypt);
链中执行此操作,我会在dplyr
中使用one_of()
select
条款:
这是一个简单,可重复的例子:
undesired <- c('mpg', 'cyl', 'hp')
mtcars <- mtcars %>%
select(-one_of(undesired))
可以通过运行?one_of
或此处
http://genomicsclass.github.io/book/pages/dplyr_tutorial.html
答案 13 :(得分:13)
我一直认为必须有一个更好的习语,但是为了按名称减去列,我倾向于做以下事情:
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
答案 14 :(得分:11)
在Bernd Bischl的dropNamed()
包中有一个名为BBmisc
的函数可以完成这个。
BBmisc::dropNamed(df, "x")
优点是它避免重复数据框参数,因此适用于magrittr
中的管道(就像dplyr
方法一样):
df %>% BBmisc::dropNamed("x")
答案 15 :(得分:7)
如果您不想使用上面的@ hadley,则为另一种解决方案:如果“COLUMN_NAME”是您要删除的列的名称:
df[,-which(names(df) == "COLUMN_NAME")]
答案 16 :(得分:5)
除了早先的答案中展示的select(-one_of(drop_col_names))
以外,还有其他两个dplyr
选项用于使用select()
删除列,这些定义不涉及定义所有特定的列名(使用dplyr starwars示例列名称中的各种数据):
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
答案 17 :(得分:3)
提供数据框和一串以逗号分隔的名称以删除:
remove_features <- function(df, features) {
rem_vec <- unlist(strsplit(features, ', '))
res <- df[,!(names(df) %in% rem_vec)]
return(res)
}
用法:
remove_features(iris, "Sepal.Length, Petal.Width")
答案 18 :(得分:1)
使用which
查找要删除的列的索引。给这些索引加上一个负号(*-1
)。然后是这些值的子集,这会将它们从数据框中删除。这是一个例子。
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
答案 19 :(得分:0)
您也可以这样做:
i<-which( colnames(df)=="COLumn")
df<-df[,-i]
答案 20 :(得分:0)
如果data.frame
大而内存不足,请使用[
. . . .或rm
and within
删除data.frame
的列,因为subset
当前(R 3.6.2)使用更多的内存-在手册的提示中使用{{1 }}互动。
subset