34

使用以下示例数据框:

a <-  c(1:5)
b <- c("Cat", "Dog", "Rabbit", "Cat", "Dog")
c <- c("Dog", "Rabbit", "Cat", "Dog", "Dog")
d <- c("Rabbit", "Cat", "Dog", "Dog", "Rabbit")
e <- c("Cat", "Dog", "Dog", "Rabbit", "Cat")
f <- c("Cat", "Dog", "Dog", "Rabbit", "Cat")

df <- data.frame(a,b,c,d,e,f)

我想研究如何重新排序列而不必输入所有列名,即df[,c("a","d","e","f","b","c")]

我怎么会说我想要在 f 列之后的 b 列和 c 列?(仅引用我要移动的列或列范围?)。

非常感谢您的帮助。

4

8 回答 8

46

要将特定列移动到 data.frame 的开头或结尾,请使用selectdplyr及其everything()函数。在这个例子中,我们发送到最后:

library(dplyr)
df %>%
  select(-b, -c, everything())

  a      d      e      f      b      c
1 1 Rabbit    Cat    Cat    Cat    Dog
2 2    Cat    Dog    Dog    Dog Rabbit
3 3    Dog    Dog    Dog Rabbit    Cat
4 4    Dog Rabbit Rabbit    Cat    Dog
5 5 Rabbit    Cat    Cat    Dog    Dog

如果没有否定,这些列将被发送到前面。

于 2015-05-27T02:37:10.360 回答
37

如果您只是将某些列移动到最后,您可以创建一个小辅助函数,如下所示:

movetolast <- function(data, move) {
  data[c(setdiff(names(data), move), move)]
}

movetolast(df, c("b", "c"))
#   a      d      e      f      b      c
# 1 1 Rabbit    Cat    Cat    Cat    Dog
# 2 2    Cat    Dog    Dog    Dog Rabbit
# 3 3    Dog    Dog    Dog Rabbit    Cat
# 4 4    Dog Rabbit Rabbit    Cat    Dog
# 5 5 Rabbit    Cat    Cat    Dog    Dog

建议养成使用列位置的习惯,尤其是从程序的角度来看,因为这些位置可能会改变。


“为了好玩”更新

这是对上述函数的扩展解释。它允许您将列移动到第一个或最后一个位置,或者在另一列之前或之后。

moveMe <- function(data, tomove, where = "last", ba = NULL) {
  temp <- setdiff(names(data), tomove)
  x <- switch(
    where,
    first = data[c(tomove, temp)],
    last = data[c(temp, tomove)],
    before = {
      if (is.null(ba)) stop("must specify ba column")
      if (length(ba) > 1) stop("ba must be a single character string")
      data[append(temp, values = tomove, after = (match(ba, temp)-1))]
    },
    after = {
      if (is.null(ba)) stop("must specify ba column")
      if (length(ba) > 1) stop("ba must be a single character string")
      data[append(temp, values = tomove, after = (match(ba, temp)))]
    })
  x
}

试试下面的。

moveMe(df, c("b", "c"))
moveMe(df, c("b", "c"), "first")
moveMe(df, c("b", "c"), "before", "e")
moveMe(df, c("b", "c"), "after", "e")

您需要对其进行调整以进行一些错误检查——例如,如果您尝试将列“b”和“c”移动到“c 之前”,您将(显然)得到一个错误。

于 2013-08-20T15:50:34.453 回答
15

您可以按位置引用列。例如

df <- df[ ,c(1,4:6,2:3)]
> df
  a      d      e      f      b      c
1 1 Rabbit    Cat    Cat    Cat    Dog
2 2    Cat    Dog    Dog    Dog Rabbit
3 3    Dog    Dog    Dog Rabbit    Cat
4 4    Dog Rabbit Rabbit    Cat    Dog
5 5 Rabbit    Cat    Cat    Dog    Dog
于 2013-08-20T15:46:24.347 回答
5

packagedplyr和 functiondplyr::relocate是 中引入的一个新动词dplyr 1.0.0,它通过高度可读的语法完全符合您的要求。

df %>% dplyr::relocate(b, c, .after = f)

于 2020-04-20T07:02:15.767 回答
3

要以任何顺序概括列的重新洗牌dplyr,例如使用重新洗牌:

df <- data.frame(a,b,c,d,e,f)

df[,c("a","d","e","f","b","c")]

df %>% select(a, d:f, b:c)
于 2017-05-20T20:51:52.783 回答
2

使用子集函数:

> df <- data.frame(a,b,c,d,e,f)
> df <- subset(df, select = c(a, d:f, b:c))
> df
  a      d      e      f      b      c
1 1 Rabbit    Cat    Cat    Cat    Dog
2 2    Cat    Dog    Dog    Dog Rabbit
3 3    Dog    Dog    Dog Rabbit    Cat
4 4    Dog Rabbit Rabbit    Cat    Dog
5 5 Rabbit    Cat    Cat    Dog    Dog
于 2019-11-27T08:15:43.410 回答
2

我将之前的函数更改为将它用于 data.table 使用包 data.table 的函数 setcolorder。

moveMeDataTable <-function(data, tomove, where = "last", ba = NULL) {
  temp <- setdiff(names(data), tomove)
  x <- switch(
    where,
    first = setcolorder(data,c(tomove, temp)),
    last = setcolorder(data,c(temp, tomove)),
    before = {
      if (is.null(ba)) stop("must specify ba column")
      if (length(ba) > 1) stop("ba must be a single character string")
      order = append(temp, values = tomove, after = (match(ba, temp)-1))
      setcolorder(data,order)

    },
    after = {
      if (is.null(ba)) stop("must specify ba column")
      if (length(ba) > 1) stop("ba must be a single character string")
      order = append(temp, values = tomove, after = (match(ba, temp)))
      setcolorder(data,order)
    })
  x
}

DT <- data.table(A=sample(3, 10, TRUE),
                B=sample(letters[1:3], 10, TRUE), C=sample(10))
DT <- moveMeDataTable(DT, "C", "after", "A")
于 2016-02-24T11:03:20.443 回答
0

这是另一种选择:

df <- cbind( df[, -(2:3)], df[, 2:3] )
于 2013-08-20T16:25:46.760 回答