我想从数据帧中删除一些列。我知道我们可以使用如下方法单独删除它们:
df$x <- NULL
但我希望用更少的命令来做到这一点。
另外,我知道我可以像这样使用整数索引删除列:
df <- df[ -c(1, 3:6, 12) ]
但我担心变量的相对位置可能会改变。
考虑到R的强大功能,我认为可能有一种比逐个删除每一列更好的方法。
我想从数据帧中删除一些列。我知道我们可以使用如下方法单独删除它们:
df$x <- NULL
但我希望用更少的命令来做到这一点。
另外,我知道我可以像这样使用整数索引删除列:
df <- df[ -c(1, 3:6, 12) ]
但我担心变量的相对位置可能会改变。
考虑到R的强大功能,我认为可能有一种比逐个删除每一列更好的方法。
当前回答
除了在前面的回答中演示的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
如果您需要删除数据帧中可能存在也可能不存在的列,这里使用select_if()略有变化,与使用one_of()不同,它不会抛出Unknown列:如果列名不存在,则会发出警告。在这个例子中,'bad_column'不是数据帧中的列:
starwars %>%
select_if(!names(.) %in% c('height', 'mass', 'bad_column'))
其他回答
另一个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
我一直在想一定有更好的习语,但对于按名称减法的列,我倾向于这样做:
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[, !(colnames(df) %in% c("x","bar","foo"))]
出于兴趣,这标记了R的一个奇怪的多重语法不一致。例如,给定一个两列数据帧:
df <- data.frame(x=1, y=2)
这就给出了一个数据帧
subset(df, select=-y)
但这给出了一个向量
df[,-2]
这些都在?中得到了解释,但这并不是完全预期的行为。至少对我来说不是……
另一种可能性:
df <- df[, setdiff(names(df), c("a", "c"))]
or
df <- df[, grep('^(a|c)$', names(df), invert=TRUE)]