如何在数据框中按名称删除列
我有一个大的数据集,我想阅读特定的列或删除所有其他的。
data <- read.dta("file.dta")
我选择了我不感兴趣的列:
var.out <- names(data)[!names(data) %in% c("iden", "name", "x_serv", "m_serv")]
并且比我想要做的事情如:
for(i in 1:length(var.out)) {
paste("data$", var.out[i], sep="") <- NULL
}
删除所有不需要的列。 这是最佳解决方案吗?
您应该使用索引或subset
函数。 例如 :
R> df <- data.frame(x=1:5, y=2:6, z=3:7, u=4:8)
R> df
x y z u
1 1 2 3 4
2 2 3 4 5
3 3 4 5 6
4 4 5 6 7
5 5 6 7 8
然后你可以在列索引中使用which
函数和-
操作符:
R> df[ , -which(names(df) %in% c("z","u"))]
x y
1 1 2
2 2 3
3 3 4
4 4 5
5 5 6
或者,更简单的是,使用subset
函数的select
参数:然后可以直接在列名称向量上使用-
运算符,并且甚至可以省略名称周围的引号!
R> subset(df, select=-c(z,u))
x y
1 1 2
2 2 3
3 3 4
4 4 5
5 5 6
请注意,您也可以选择您想要的列而不是删除其他列:
R> df[ , c("x","y")]
x y
1 1 2
2 2 3
3 3 4
4 4 5
5 5 6
R> subset(df, select=c(x,y))
x y
1 1 2
2 2 3
3 3 4
4 4 5
5 5 6
不要使用-which()
,这是非常危险的。 考虑:
dat <- data.frame(x=1:5, y=2:6, z=3:7, u=4:8)
dat[ , -which(names(dat) %in% c("z","u"))] ## works as expected
dat[ , -which(names(dat) %in% c("foo","bar"))] ## deletes all columns! Probably not what you wanted...
而是使用子集或!
功能:
dat[ , !names(dat) %in% c("z","u")] ## works as expected
dat[ , !names(dat) %in% c("foo","bar")] ## returns the un-altered data.frame. Probably what you want
我从痛苦的经历中学到了这一点。 不要过度使用which()
!
首先 ,如果您使用相同的数据框,则可以使用直接索引(使用布尔值向量)而不是重新访问列名; 如Ista指出的那样更安全,并且更快写入和执行。 所以你只需要:
var.out.bool <- !names(data) %in% c("iden", "name", "x_serv", "m_serv")
然后,只需重新分配数据:
data <- data[,var.out.bool] # or...
data <- data[,var.out.bool, drop = FALSE] # You will need this option to avoid the conversion to an atomic vector if there is only one column left
其次 ,编写速度更快,您可以直接将NULL分配给要删除的列:
data[c("iden", "name", "x_serv", "m_serv")] <- list(NULL) # You need list() to respect the target structure.
最后 ,您可以使用subset(),但它不能真正用于代码中(即使帮助文件也会警告)。 具体来说,对我来说一个问题是,如果你想直接使用susbset()的拖放功能,则需要在不带引号的情况下写入与列名相对应的表达式:
subset( data, select = -c("iden", "name", "x_serv", "m_serv") ) # WILL NOT WORK
subset( data, select = -c(iden, name, x_serv, m_serv) ) # WILL
作为奖励 ,这里是不同选项的小基准,清楚地表明子集是较慢的,并且第一个重新分配方法是较快的:
re_assign(dtest, drop_vec) 46.719 52.5655 54.6460 59.0400 1347.331
null_assign(dtest, drop_vec) 74.593 83.0585 86.2025 94.0035 1476.150
subset(dtest, select = !names(dtest) %in% drop_vec) 106.280 115.4810 120.3435 131.4665 65133.780
subset(dtest, select = names(dtest)[!names(dtest) %in% drop_vec]) 108.611 119.4830 124.0865 135.4270 1599.577
subset(dtest, select = -c(x, y)) 102.026 111.2680 115.7035 126.2320 1484.174
代码如下:
dtest <- data.frame(x=1:5, y=2:6, z = 3:7)
drop_vec <- c("x", "y")
null_assign <- function(df, names) {
df[names] <- list(NULL)
df
}
re_assign <- function(df, drop) {
df <- df [, ! names(df) %in% drop, drop = FALSE]
df
}
res <- microbenchmark(
re_assign(dtest,drop_vec),
null_assign(dtest,drop_vec),
subset(dtest, select = ! names(dtest) %in% drop_vec),
subset(dtest, select = names(dtest)[! names(dtest) %in% drop_vec]),
subset(dtest, select = -c(x, y) ),
times=5000)
plt <- ggplot2::qplot(y=time, data=res[res$time < 1000000,], colour=expr)
plt <- plt + ggplot2::scale_y_log10() +
ggplot2::labs(colour = "expression") +
ggplot2::scale_color_discrete(labels = c("re_assign", "null_assign", "subset_bool", "subset_names", "subset_drop")) +
ggplot2::theme_bw(base_size=16)
print(plt)
链接地址: http://www.djcxy.com/p/70907.html