我想从数据帧中删除一些列。我知道我们可以使用如下方法单独删除它们:
df$x <- NULL
但我希望用更少的命令来做到这一点。
另外,我知道我可以像这样使用整数索引删除列:
df <- df[ -c(1, 3:6, 12) ]
但我担心变量的相对位置可能会改变。
考虑到R的强大功能,我认为可能有一种比逐个删除每一列更好的方法。
我想从数据帧中删除一些列。我知道我们可以使用如下方法单独删除它们:
df$x <- NULL
但我希望用更少的命令来做到这一点。
另外,我知道我可以像这样使用整数索引删除列:
df <- df[ -c(1, 3:6, 12) ]
但我担心变量的相对位置可能会改变。
考虑到R的强大功能,我认为可能有一种比逐个删除每一列更好的方法。
当前回答
你有很多方法可以……
选项1:
df[ , -which(names(df) %in% c("name1","name2"))]
选项2:
df[!names(df) %in% c("name1", "name2")]
选项3:
subset(df, select=-c(name1,name2))
其他回答
你可以像这样在%中使用%:
df[, !(colnames(df) %in% c("x","bar","foo"))]
下面是一个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()
我喜欢这个,因为它是直观的阅读和理解,没有注释和健壮的列在数据框架内改变位置。它还遵循向量化成语使用-来删除元素。
如果你有一个大的data.frame和低内存使用[. . . .或rm和within删除data.frame的列,因为子集目前(R 3.6.2)使用更多的内存-除了手册提示交互式使用子集。
getData <- function() {
n <- 1e7
set.seed(7)
data.frame(a = runif(n), b = runif(n), c = runif(n), d = runif(n))
}
DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF <- DF[setdiff(names(DF), c("a", "c"))] ##
#DF <- DF[!(names(DF) %in% c("a", "c"))] #Alternative
#DF <- DF[-match(c("a","c"),names(DF))] #Alternative
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#0.1 MB are used
DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF <- subset(DF, select = -c(a, c)) ##
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#357 MB are used
DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF <- within(DF, rm(a, c)) ##
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#0.1 MB are used
DF <- getData()
tt <- sum(.Internal(gc(FALSE, TRUE, TRUE))[13:14])
DF[c("a", "c")] <- NULL ##
sum(.Internal(gc(FALSE, FALSE, TRUE))[13:14]) - tt
#0.1 MB are used
如果您希望通过引用删除列并避免与data.frames相关的内部复制,则可以使用数据。表包和函数:=
您可以将字符向量名称传递到:=运算符的左侧,并将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]的开销。表,也适用于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)
df <- data.frame(
+ a=1:5,
+ b=6:10,
+ c=rep(22,5),
+ d=round(runif(5)*100, 2),
+ e=round(runif(5)*100, 2),
+ f=round(runif(5)*100, 2),
+ g=round(runif(5)*100, 2),
+ h=round(runif(5)*100, 2)
+ )
> df
a b c d e f g h
1 1 6 22 76.31 39.96 66.62 72.75 73.14
2 2 7 22 53.41 94.85 96.02 97.31 85.32
3 3 8 22 98.29 38.95 12.61 29.67 88.45
4 4 9 22 20.04 53.53 83.07 77.50 94.99
5 5 10 22 5.67 0.42 15.07 59.75 31.21
> # remove cols: d g h
> newDf <- df[, c(1:3, 5), drop=TRUE]
> newDf
a b c e
1 1 6 22 39.96
2 2 7 22 94.85
3 3 8 22 38.95
4 4 9 22 53.53
5 5 10 22 0.42