【问题标题】:R move column to last using dplyrR使用dplyr将列移动到最后
【发布时间】:2017-10-09 10:03:32
【问题描述】:

对于具有 n 列的 data.frame,我希望能够从任何 1-(n-1) 位置移动一列,以第 n 列(即非最后一列成为最后一列)。我也想用dplyr 来做。我想这样做而不是简单地输入所有列的名称。

例如:

data<-data.frame(a=1:5, b=6:10, c=11:15)

这可行,但不是dplyr 方式:

data[,c(colnames(data)[colnames(data)!='b'],'b')]

这是dplyr首先创建列b的方式:

data%>%select(b, everything())

但这并不能让b 成为最后一个:

data%>%select(everything(), b)

这可行,但需要我输入所有列:

data%>%select(a,c,b)

那么有没有一种优雅的 dplyr 方法可以做到这一点?

相关问题:

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    更新:

    dplyr::relocate 是 dplyr 1.0.0 中引入的一个新动词,现在是我的首选解决方案,因为它明确说明了你在做什么,你可以继续使用 tidyselect 助手选择变量,你可以准确地指定将带有.before.after 的列放在哪里

    data %&gt;% relocate(b, .after = last_col()) (同dule arnaux的更新)

    原答案

    data%>%select(-b,everything())
    

    将变量 b 移动到末尾。

    这是因为 select 的第一个位置的负变量会引发 select() 的特殊行为,即插入所有变量。然后它会删除 b,然后将它与everything() 部分一起添加回来。

    由哈德利本人解释:https://github.com/tidyverse/dplyr/issues/2838

    有关如何将某些列移至末尾和将其他列移至开头的其他示例,另请参阅此其他答案: How does dplyr's select helper function everything() differ from copying?

    【讨论】:

    • 如果您将几列移到后面,这比 dule arnaux 的答案更干净。
    • 请注意,此答案不尊重变量的顺序,以防您传递多个名称,例如 -c(a,b,c) 而不仅仅是 -b。使用此解决方案,变量的顺序将反映它们已经在数据框中的顺序。因此,如果列顺序为a, c, b, d, e, f,则此答案将返回d, e, f, a, c, b。 Dule arnaux 的回答将返回d, e, f, a, b, c
    【解决方案2】:

    经过一些修改,以下内容可以正常工作,并且只需要很少的输入。

    data %&gt;% select(-b,b)


    更新:dplyr 1.0.0

    dplyr 1.0.0 介绍了relocate 动词:

    data %&gt;% relocate(b, .after = last_col())

    我还是更喜欢旧的“hacky”方式。

    【讨论】:

    • 非常感谢这种简单易行的方法。欣赏杜乐。
    • Dule,您可以将接受的答案更改为 this 或 Arthur Yip 的答案,因为它们绝对比 Arkun 的更干净、更“优雅”(尽管效果很好。)
    • 其他答案教我更多关于 dplyr 的知识,但这个答案是所有答案中最短的!所以我认为这是一个折腾。
    【解决方案3】:
    df <- df[, c(which(colnames(df) != "YourColumnName"), which(colnames(df) == "YourColumnName"))]
    

    【讨论】:

    • 问题的最后两个词是:using dplyr。这个答案不使用 dplyr。
    【解决方案4】:

    由于在 dplyr 中没有现成的解决方案,您可以定义自己的小函数来为您完成:

    move_last <- function(DF, last_col) {
        match(c(setdiff(names(DF), last_col), last_col), names(DF))
    }
    

    然后您可以在普通的select 呼叫中轻松使用它:

    mtcars %>% select(move_last(., "mpg")) %>% head()
    

    您还可以将多列移到末尾:

    mtcars %>% select(move_last(., c("mpg", "cyl"))) %>% head()
    

    您仍然可以提供其他参数来选择,例如删除一列:

    mtcars %>% select(move_last(., "mpg"), -carb) %>% head()
    

    【讨论】:

    • 为什么说dplyr没有现成的解决方案? Akrun 的解决方案示例似乎就是其中之一。
    • 没错,dplyr 确实允许这样做,但 Hadley 指出,移动/重新排序变量“通常不是那么重要,所以你现在需要与 select() 一起混淆。” github.com/tidyverse/dplyr/issues/2838
    【解决方案5】:

    我们可以使用

    data %>%
        select(-one_of('b'), one_of('b'))
    #  a  c  b
    #1 1 11  6
    #2 2 12  7
    #3 3 13  8
    #4 4 14  9
    #5 5 15 10
    

    或者

    data %>%
        select(matches("[^b]"), matches("b"))
    

    或使用select_

    data %>% 
        select_(.dots = c(setdiff(names(.), 'b'), 'b'))
    #  a  c  b
    #1 1 11  6
    #2 2 12  7
    #3 3 13  8
    #4 4 14  9
    #5 5 15 10
    

    【讨论】:

    • 总是很好的答案, one_of 是做什么的? ,与其他选项不同,它实际上是否选择引号中的名称?谢谢
    • @Bankelal 谢谢。您可以在one_of 中有一个字符串名称的向量来匹配并选择它
    • +1 用于使用 one_of 作为对缺失列的保护。结合 Arthur Yip 对 data %&gt;% select(-one_of('b'), everything()) 的回答,这会将删除的列放回末尾,并调用 Everything()。
    • 我认为matches("[^b]"), matches("b") 非常聪明,在其他情况下可能非常有用。
    猜你喜欢
    • 1970-01-01
    • 2022-06-28
    • 1970-01-01
    • 1970-01-01
    • 2017-12-04
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    相关资源
    最近更新 更多