【问题标题】:Dynamically sorting columns in dplyr via passing ordered vector with column names to select通过传递带有列名的有序向量来动态排序 dplyr 中的列以进行选择
【发布时间】:2016-03-08 03:12:15
【问题描述】:

我正在使用下面的代码来生成一个简单的汇总表:

# Data
data("mtcars")
# Lib
require(dplyr)
# Summary
mt_sum <- mtcars %>%
  group_by(am) %>%
  summarise_each(funs(min, mean, median, max), mpg, cyl) %>%
  mutate(am = as.character(am)) %>%
  left_join(y = as.data.frame(table(mtcars$am),
                              stringsAsFactors = FALSE),
            by = c("am" = "Var1")) 

代码产生预期的结果:

> head(mt_sum)
Source: local data frame [2 x 10]

     am mpg_min cyl_min mpg_mean cyl_mean mpg_median cyl_median mpg_max cyl_max  Freq
  (chr)   (dbl)   (dbl)    (dbl)    (dbl)      (dbl)      (dbl)   (dbl)   (dbl) (int)
1     0    10.4       4 17.14737 6.947368       17.3          8    24.4       8    19
2     1    15.0       4 24.39231 5.076923       22.8          4    33.9       8    13

但是,我对列的排序方式不满意。特别是,我想:

  1. 按名称对列进行排序

  2. 通过select() in dplyr 实现这一目标

想要的顺序

所需的顺序如下所示:

> names(mt_sum)[order(names(mt_sum))]
 [1] "am"         "cyl_max"    "cyl_mean"   "cyl_median" "cyl_min"    "Freq"       "mpg_max"   
 [8] "mpg_mean"   "mpg_median" "mpg_min" 

尝试

理想情况下,我想通过names(mt_sum)[order(names(mt_sum))]select() 中的列进行排序。但是代码:

mt_sum <- mtcars %>%
  group_by(am) %>%
  summarise_each(funs(min, mean, median, max), mpg, cyl) %>%
  mutate(am = as.character(am)) %>%
  left_join(y = as.data.frame(table(mtcars$am),
                              stringsAsFactors = FALSE),
            by = c("am" = "Var1")) %>%
  select(names(.)[order(names(.))])

将返回预期的错误:

Error: All select() inputs must resolve to integer column positions.
The following do not:
*  names(.)[order(names(.))]

在我的真实数据中,我生成了大量的汇总列。因此,我的问题是,如何将已排序的列名动态传递给 dplyr 中的 select(),以便它能够理解并应用于手头的 data.frame


我的重点是找出一种将动态生成的列名传递给select() 的方法。我知道我可以对base 中的列或通过键入名称进行排序,如here 所讨论的那样。

【问题讨论】:

    标签: r sorting dataframe dplyr


    【解决方案1】:

    你绝对是在正确的道路上。

    mt_sum <- mtcars %>%
      group_by(am) %>%
      summarise_each(funs(min, mean, median, max), mpg, cyl) %>%
      mutate(am = as.character(am)) %>%
      left_join(y = as.data.frame(table(mtcars$am),
                                  stringsAsFactors = FALSE),
                by = c("am" = "Var1")) %>%
      .[, names(.)[order(names(.))]]
    

    【讨论】:

    • 太棒了!所以整个事情都没有select(),就是这样!
    【解决方案2】:

    您只需要:

    mt_sum %>% select(order(names(.)))
    #Source: local data frame [2 x 10]
    #
    #     am cyl_max cyl_mean cyl_median cyl_min  Freq mpg_max mpg_mean mpg_median mpg_min
    #  (chr)   (dbl)    (dbl)      (dbl)   (dbl) (int)   (dbl)    (dbl)      (dbl)   (dbl)
    #1     0       8 6.947368          8       4    19    24.4 17.14737       17.3    10.4
    #2     1       8 5.076923          4       4    13    33.9 24.39231       22.8    15.0
    

    它可以工作,因为order 返回整数列位置,正如select 所要求的那样。

    【讨论】:

    • 非常感谢,简洁的解决方案,效果非常好。
    • 如果您正在计算分组变量的汇总,您可以从排序中删除这些并在开头添加它们。喜欢select(group_var, order(names(.)[-1]))
    猜你喜欢
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 2014-10-07
    • 2017-10-24
    • 2017-10-05
    • 2017-06-08
    • 1970-01-01
    • 2017-05-07
    相关资源
    最近更新 更多