关于如何将列移动到第一个或最后一个位置有很多问题和答案.
使用dplyr最佳答案分别类似于:
iris2 <- iris %>% head(2)
iris2 %>% select( Sepal.Width, everything()) # move Sepal.Width to first
# Sepal.Width Sepal.Length Petal.Length Petal.Width Species
# 1 3.5 5.1 1.4 0.2 setosa
# 2 3.0 4.9 1.4 0.2 setosa
iris2 %>% select(-Sepal.Width, Sepal.Width) # move Sepal.Width to last
# Sepal.Length Petal.Length Petal.Width Species Sepal.Width
# 1 5.1 1.4 0.2 setosa 3.5
# 2 4.9 1.4 0.2 setosa 3.0
Run Code Online (Sandbox Code Playgroud)
但是,我没有找到任何简单的方法在给定的一个之后或之前移动一个列.
我在下面发布了一个粗略的解决方案但是:
dplyr函数的灵活性来使用数字索引,名称,字符串等......我相信使用dplyr我们也可以移动列的列表,或者在名称等中显示模式的一组列...但我对dplyr样式编程还不是很熟悉.
所以我挑战你做得更好/更聪明,或者指出我错过的明显解决方案.
预期产量:
iris2 %>% move_at(Species, Sepal.Width, side = "before")
# Sepal.Length Species Sepal.Width Petal.Length Petal.Width
# 1 5.1 setosa 3.5 1.4 0.2
# 2 4.9 setosa 3.0 1.4 0.2
iris2 %>% move_at(Species, Sepal.Width, side = "after")
# Sepal.Length Sepal.Width Species Petal.Length Petal.Width
# 1 5.1 3.5 setosa 1.4 0.2
# 2 4.9 3.0 setosa 1.4 0.2
Run Code Online (Sandbox Code Playgroud)
Moo*_*per 13
更新:使用rlang::enquo我可以做得更好,然后使用@ Zsombor的答案,我可以使它更短,更优雅.答案结束时的旧解决方案(在基础R中)
#' Move column or selection of columns
#'
#' Column(s) described by \code{cols} are moved before (default) or after the reference
#' column described by \code{ref}
#'
#' @param data A \code{data.frame}
#' @param cols unquoted column name or numeric or selection of columns using a select helper
#' @param ref unquoted column name
#' @param side \code{"before"} or \code{"after"}
#'
#' @return A data.frame with reordered columns
#' @export
#'
#' @examples
#' iris2 <- head(iris,2)
#' move(iris2, Species, Sepal.Width)
#' move(iris2, Species, Sepal.Width, "after")
#' move(iris2, 5, 2)
#' move(iris2, 4:5, 2)
#' move(iris2, one_of("Sepal.Width","Species"), Sepal.Width)
#' move(iris2, starts_with("Petal"), Sepal.Width)
move <- function(data, cols, ref, side = c("before","after")){
if(! requireNamespace("dplyr"))
stop("Make sure package 'dplyr' is installed to use function 'move'")
side <- match.arg(side)
cols <- rlang::enquo(cols)
ref <- rlang::enquo(ref)
if(side == "before")
dplyr::select(data,1:!!ref,-!!ref,-!!cols,!!cols,dplyr::everything())
else
dplyr::select(data,1:!!ref,-!!cols,!!cols,dplyr::everything())
}
Run Code Online (Sandbox Code Playgroud)
例子:
iris2 %>% move(Species, Sepal.Width)
# Sepal.Length Species Sepal.Width Petal.Length Petal.Width
# 1 5.1 setosa 3.5 1.4 0.2
# 2 4.9 setosa 3.0 1.4 0.2
iris2 %>% move(Species, Sepal.Width, "after")
# Sepal.Length Sepal.Width Species Petal.Length Petal.Width
# 1 5.1 3.5 setosa 1.4 0.2
# 2 4.9 3.0 setosa 1.4 0.2
iris2 %>% move(5, 2)
# Sepal.Length Species Sepal.Width Petal.Length Petal.Width
# 1 5.1 setosa 3.5 1.4 0.2
# 2 4.9 setosa 3.0 1.4 0.2
iris2 %>% move(4:5, 2)
# Sepal.Length Petal.Width Species Sepal.Width Petal.Length
# 1 5.1 0.2 setosa 3.5 1.4
# 2 4.9 0.2 setosa 3.0 1.4
iris2 %>% move(one_of("Sepal.Width","Species"), Sepal.Width)
# Sepal.Length Sepal.Width Species Petal.Length Petal.Width
# 1 5.1 3.5 setosa 1.4 0.2
# 2 4.9 3.0 setosa 1.4 0.2
iris2 %>% move(starts_with("Petal"), Sepal.Width)
# Sepal.Length Petal.Length Petal.Width Sepal.Width Species
# 1 5.1 1.4 0.2 3.5 setosa
# 2 4.9 1.4 0.2 3.0 setosa
Run Code Online (Sandbox Code Playgroud)
有问题的旧解决方案
这是一个只使用基本R编程的简单解决方案:
move_at <- function(data, col, ref, side = c("before","after")){
side = match.arg(side)
col_pos <- match(as.character(substitute(col)),names(data))
ref_pos <- match(as.character(substitute(ref)),names(data))
sorted_pos <- c(col_pos,ref_pos)
if(side =="after") sorted_pos <- rev(sorted_pos)
data[c(setdiff(seq_len(ref_pos-1),col_pos),
sorted_pos,
setdiff(seq_along(data),c(seq_len(ref_pos),col_pos)))]
}
iris2 %>% move_at(Species, Sepal.Width)
# Sepal.Length Species Sepal.Width Petal.Length Petal.Width
# 1 5.1 setosa 3.5 1.4 0.2
# 2 4.9 setosa 3.0 1.4 0.2
iris2 %>% move_at(Species, Sepal.Width, "after")
# Sepal.Length Sepal.Width Species Petal.Length Petal.Width
# 1 5.1 3.5 setosa 1.4 0.2
# 2 4.9 3.0 setosa 1.4 0.2
Run Code Online (Sandbox Code Playgroud)
无论原始列顺序如何,这似乎都有效(感谢对@Moody_Mudskipper的评论):
iris %>% select(1:Sepal.Width, -Species, Species, everything()) %>% head(2)
#> Sepal.Length Sepal.Width Species Petal.Length Petal.Width
#> 1 5.1 3.5 setosa 1.4 0.2
#> 2 4.9 3.0 setosa 1.4 0.2
iris %>% select(1:Sepal.Width, -Sepal.Width, -Species, Species, everything()) %>% head(2)
#> Sepal.Length Species Sepal.Width Petal.Length Petal.Width
#> 1 5.1 setosa 3.5 1.4 0.2
#> 2 4.9 setosa 3.0 1.4 0.2
Run Code Online (Sandbox Code Playgroud)
为了完成答案,有一个名为relocate()since的函数dplyr 1.0.0:
library(dplyr)
iris %>%
head(n = 2) %>%
relocate(Species, .before = Sepal.Width)
#> Sepal.Length Species Sepal.Width Petal.Length Petal.Width
#> 1 5.1 setosa 3.5 1.4 0.2
#> 2 4.9 setosa 3.0 1.4 0.2
Run Code Online (Sandbox Code Playgroud)
创建于 2022 年 10 月 18 日,使用reprex v2.0.2