使用dplyr不支持使用矩阵错误

时间:2017-03-06 22:04:50

标签: r dplyr

让我有这样的数据框:

    df <- structure(list(subjecttaxnoid = c("22661187010", "10346575807", 
"22439110996", "63510438612", "85267957976", "40178118040", "51246665873", 
"66803849969", "45813719599", "26979059418", "11240408751"), 
    reportyear = c(2014L, 2014L, 2014L, 2008L, 2008L, 2008L, 
    2008L, 2013L, 2013L, 2013L, 2013L), b001 = c(0, 0, 0, 0, 
    0, 0, 0, 0, 0, 0, 0), b002 = c(0, 3.43884233571018e-07, 7.24705810574303e-08, 
    1.41222784374111e-07, 1.62917712565032e-05, 0, 4.53310814208705e-07, 
    7.63856039195011e-06, 0, 0, 0)), .Names = c("subjecttaxnoid", 
"reportyear", "b001", "b002"), row.names = c(1L, 2L, 3L, 200000L, 
200001L, 200002L, 200003L, 40000L, 40001L, 40002L, 40003L), class = "data.frame")

和包含两列df名称的向量:

x <- c("b001", "b002")

我想在dplyr中使用x的组件而不是列名:

my_list <- list()
for (i in 1:length(x)){
  my_list[[1]] <- df %>% group_by(reportyear) %>% top_n(2, wt = x[1])
}

这会返回错误:

 Error in eval(substitute(expr), envir, enclos) : 
  Unsupported use of matrix or array for column indexing

你能帮忙解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

除非您想要更改函数x[1],否则我认为有一种简单的解决方法(例如,将as.name包裹在top_n内)。 @ulfelder在评论中建议的原因是dplyr使用非标准评估,因此在这种情况下它需要一个不带引号的变量名。其他函数具有处理引用参数的版本(例如mutate_rename_等)但在这种情况下不是。

最简单的方法是使用临时分配,例如

df %>% 
    group_by(reportyear) %>% 
    mutate_(tempvar = x[1]) %>% 
    top_n(2, wt = tempvar) %>% 
    select(-tempvar)

(当然你需要确保tempvar不是数据框中已有的变量名,否则它将覆盖现有变量。远离理想状态,您可能已经考虑过并拒绝了它。< / p>

另一种方法是定义自己的top_n_函数,类似于top_n,但需要wt参数中的字符串:

top_n_ <- function (x, n, wt) {
    wt <- as.name(wt)
    stopifnot(is.numeric(n), length(n) == 1)
    if (n > 0) {
        call <- substitute(filter(x, min_rank(desc(wt)) <= n),
            list(n = n, wt = wt))
    }
    else {
        call <- substitute(filter(x, min_rank(wt) <= n), list(n = abs(n),
            wt = wt))
    }
    eval(call)
}

这基本上只是在函数定义的顶部使用top_n并更改wt参数的处理。然后就可以了

df %>% group_by(reportyear) %>% top_n_(2, wt = x[1])

identical(
    df %>% group_by(reportyear) %>% top_n_(2, wt = x[1]),
    df %>% group_by(reportyear) %>% top_n(2, wt = b001),
)
# TRUE
identical(
    df %>% group_by(reportyear) %>% top_n_(2, wt = x[2]),
    df %>% group_by(reportyear) %>% top_n(2, wt = b002),
)
# TRUE