使用 gather 时保留许多列
Preserving many columns when using gather
我有一个非常宽的 df(85 列),我想使用 gather
将其转换为长格式。我没有使用 -c(all the columns I do not want to gather)
语法来保留列,而是创建了列名的对象并得到了错误。
Error in -c(KeepThese) : invalid argument to unary operator
例如,使用 iris
和一些额外的字段
require(tidyr)
iris$Season <- sample(c("AAA", "BBB"), nrow(iris), replace = T)
iris$Var <- sample(c("CCC", "DDD"), nrow(iris), replace = T)
> head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Season Var
1 5.1 3.5 1.4 0.2 setosa AAA DDD
2 4.9 3.0 1.4 0.2 setosa AAA CCC
3 4.7 3.2 1.3 0.2 setosa BBB CCC
4 4.6 3.1 1.5 0.2 setosa BBB CCC
5 5.0 3.6 1.4 0.2 setosa BBB DDD
6 5.4 3.9 1.7 0.4 setosa AAA DDD
我想收集除5:7以外的所有列,在下面做成一个对象。
KeepThese <- colnames(iris)[5:7]
现在,我想 gather
除 5:7 之外的所有列并调用 ID 列 Part 和数字字段 Value 并使用以下代码并得到错误。
dat <- iris %>% gather(Part, Value, -c(KeepThese))
Error in -c(KeepNames) : invalid argument to unary operator
如果不在 tidyr
中逐一写出,如何指定一堆我不想收集的列?
ADDITION 为什么我的代码不起作用?
您可以使用 match
(或首先将列号传递给 gather
):
dat <- iris %>% gather(Part, Value, -(match(KeepThese, colnames(.))))
head(dat)
## Species Season Var Part Value
## 1 setosa BBB DDD Sepal.Length 5.1
## 2 setosa AAA CCC Sepal.Length 4.9
## 3 setosa BBB CCC Sepal.Length 4.7
## 4 setosa AAA CCC Sepal.Length 4.6
## 5 setosa BBB DDD Sepal.Length 5.0
## 6 setosa BBB CCC Sepal.Length 5.4
更新答案: 正如 Hadley 在评论中指出的那样,one_of()
就是您想要的。
dat <- iris %>% gather(Part, Value, -one_of(KeepThese))
原答案:
另一种选择是使用 as.name()
。我们可以根据要保留的列名创建一个名称分类对象列表。然后用do.call(c, ...)
插入到gather()
.
dat <- iris %>% gather(Part, Value, -do.call("c", lapply(KeepThese, as.name)))
head(dat)
# Species Season Var Part Value
# 1 setosa AAA CCC Sepal.Length 5.1
# 2 setosa AAA CCC Sepal.Length 4.9
# 3 setosa AAA DDD Sepal.Length 4.7
# 4 setosa AAA CCC Sepal.Length 4.6
# 5 setosa AAA CCC Sepal.Length 5.0
# 6 setosa AAA DDD Sepal.Length 5.4
或者,一个简单的 %in%
和 which()
也可以做到这一点(与 jbaums 的回答非常相似)。
iris %>% gather(Part, Value, -which(names(.) %in% KeepThese))
指定列 -matches
和一个好的正则表达式工作
dat <- iris %>% gather(Part, Value, -matches(paste(KeepThese, collapse="|")))
我有一个非常宽的 df(85 列),我想使用 gather
将其转换为长格式。我没有使用 -c(all the columns I do not want to gather)
语法来保留列,而是创建了列名的对象并得到了错误。
Error in -c(KeepThese) : invalid argument to unary operator
例如,使用 iris
和一些额外的字段
require(tidyr)
iris$Season <- sample(c("AAA", "BBB"), nrow(iris), replace = T)
iris$Var <- sample(c("CCC", "DDD"), nrow(iris), replace = T)
> head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species Season Var
1 5.1 3.5 1.4 0.2 setosa AAA DDD
2 4.9 3.0 1.4 0.2 setosa AAA CCC
3 4.7 3.2 1.3 0.2 setosa BBB CCC
4 4.6 3.1 1.5 0.2 setosa BBB CCC
5 5.0 3.6 1.4 0.2 setosa BBB DDD
6 5.4 3.9 1.7 0.4 setosa AAA DDD
我想收集除5:7以外的所有列,在下面做成一个对象。
KeepThese <- colnames(iris)[5:7]
现在,我想 gather
除 5:7 之外的所有列并调用 ID 列 Part 和数字字段 Value 并使用以下代码并得到错误。
dat <- iris %>% gather(Part, Value, -c(KeepThese))
Error in -c(KeepNames) : invalid argument to unary operator
如果不在 tidyr
中逐一写出,如何指定一堆我不想收集的列?
ADDITION 为什么我的代码不起作用?
您可以使用 match
(或首先将列号传递给 gather
):
dat <- iris %>% gather(Part, Value, -(match(KeepThese, colnames(.))))
head(dat)
## Species Season Var Part Value
## 1 setosa BBB DDD Sepal.Length 5.1
## 2 setosa AAA CCC Sepal.Length 4.9
## 3 setosa BBB CCC Sepal.Length 4.7
## 4 setosa AAA CCC Sepal.Length 4.6
## 5 setosa BBB DDD Sepal.Length 5.0
## 6 setosa BBB CCC Sepal.Length 5.4
更新答案: 正如 Hadley 在评论中指出的那样,one_of()
就是您想要的。
dat <- iris %>% gather(Part, Value, -one_of(KeepThese))
原答案:
另一种选择是使用 as.name()
。我们可以根据要保留的列名创建一个名称分类对象列表。然后用do.call(c, ...)
插入到gather()
.
dat <- iris %>% gather(Part, Value, -do.call("c", lapply(KeepThese, as.name)))
head(dat)
# Species Season Var Part Value
# 1 setosa AAA CCC Sepal.Length 5.1
# 2 setosa AAA CCC Sepal.Length 4.9
# 3 setosa AAA DDD Sepal.Length 4.7
# 4 setosa AAA CCC Sepal.Length 4.6
# 5 setosa AAA CCC Sepal.Length 5.0
# 6 setosa AAA DDD Sepal.Length 5.4
或者,一个简单的 %in%
和 which()
也可以做到这一点(与 jbaums 的回答非常相似)。
iris %>% gather(Part, Value, -which(names(.) %in% KeepThese))
指定列 -matches
和一个好的正则表达式工作
dat <- iris %>% gather(Part, Value, -matches(paste(KeepThese, collapse="|")))