【问题标题】:arrange() doesn't recognize column name parameter安排()不识别列名参数
【发布时间】:2018-04-13 20:14:32
【问题描述】:

在 R 中,我使用dplyr,更具体地说是arrange()。 不知何故,arrange 函数无法按预期工作。

在下面的示例中,我首先存储列的名称,然后将此变量作为参数传递给名为“my_function”的自定义函数。

target_column = 'mean_age'

# below the function
my_function <- function(target_column, number){
    df <- read.csv('file.csv', stringsAsFactors=FALSE)
    df <- df[, c(1,4,10)]
    names(df) <-  c('place','state','mean_age')
    df1 <- df %>% group_by(state) %>% arrange(target_column) 
    df1 %>% summarise(rank = nth(target_column, number))        
}

由于arrange()的输入而调用'my_function'时R返回错误:

“arrange_impl(.data, dots) 中的错误: 位置 1 的尺寸 (1) 不正确,预期为:4000"

当列名直接放入arrange(),而不是引用字符串的变量(如上例)时,它确实接受参数。

df %>% group_by(state) %>% arrange(mean_age) 

如何以更好的方式将列名的参数传递给“my_function”,以便arrange() 能够识别它?

【问题讨论】:

  • 在一个简单的情况下,您在函数中使用arrange 并希望将变量作为字符串传递,您可以使用arrange_at 代替arrange。你的情况对我来说看起来更复杂,nthsummarise,所以使用 unquoting/quosures 进行编程可能更有意义。

标签: r dplyr


【解决方案1】:

您需要先将字符串参数解析为 quosure,然后使用 !! 取消引用:

library(dplyr)
library(rlang)

target_column = 'mean_age'

my_function <- function(target_column, number){
    target_quo = parse_quosure(target_column)

    df <- read.csv('file.csv', stringsAsFactors=FALSE)
    df <- df[, c(1,4,10)]
    names(df) <-  c('place','state','mean_age')
    df1 <- df %>% group_by(state) %>% arrange(!!target_quo) 
    df1 %>% summarise(rank = nth(target_column, number))        
}

my_function('mean_age', 10)

如果您希望能够提供 target_column 作为不带引号的列名,您可以改用 enquo

my_function <- function(target_column, number){
    target_quo = enquo(target_column)

    df <- read.csv('file.csv', stringsAsFactors=FALSE)
    df <- df[, c(1,4,10)]
    names(df) <-  c('place','state','mean_age')
    df1 <- df %>% group_by(state) %>% arrange(!!target_quo) 
    df1 %>% summarise(rank = nth(target_column, number))        
}

my_function(mean_age, 10)

注意:

通常,enquo 也适用于字符串参数,但 arrange 本身不允许这样做,因此以下示例不适用于第二个示例:

my_function('mean_age', 10)

下面是一个玩具示例来说明我的意思,因为 OP 的问题不可重现:

library(dplyr)
library(rlang)

test_func = function(var){
    var_quo = parse_quosure(var)
    mtcars %>%
      select(!!var_quo) %>%
      arrange(!!var_quo)
}

test_func2 = function(var){
  var_quo = enquo(var)
  mtcars %>%
    select(!!var_quo) %>%
    arrange(!!var_quo)
}

结果:

> test_func("mpg") %>%
+   head()
   mpg
1 10.4
2 10.4
3 13.3
4 14.3
5 14.7
6 15.0

> test_func2(mpg) %>%
+   head()
   mpg
1 10.4
2 10.4
3 13.3
4 14.3
5 14.7
6 15.0

> test_func2("mpg") %>%
+   head()

arrange_impl(.data, dots) 中的错误: 位置 1 的尺寸 (1) 不正确,预期为:32

【讨论】:

  • 或者他可以用arrange_代替arrange
  • @Moody_Mudskipper 你如何让它同时适用于my_function('mean_age', 10)my_function(mean_age, 10)?此外,arrange_ 已弃用
  • 感谢您的努力。这暂时解决了这个问题。加载库的顺序也有所不同。
  • 对于简单的情况,arrange_at 可以在带有字符串输入的函数中工作。
【解决方案2】:

@avid_user 的好答案需要更新,因为现在不推荐使用 'rlang::parse_quosure'。

要简短回答如何让 'dplyr::arrange' 接受包含字符串的字符串或变量以供列名进行排序,您可以这样做:

target_column = rlang::sym('mean_age')
df %>% group_by(state) %>% arrange(!!target_column)

或作为单线(如果您只需要使用一次):

df %>% group_by(state) %>% arrange(!!rlang::sym(target_column))

【讨论】:

    猜你喜欢
    • 2019-05-29
    • 1970-01-01
    • 2016-08-20
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    • 2015-03-24
    • 2013-07-23
    • 1970-01-01
    相关资源
    最近更新 更多