【问题标题】:dplyr mutate: Recursive indexing faileddplyr mutate:递归索引失败
【发布时间】:2019-03-13 14:56:15
【问题描述】:

我对 mutate 和自写函数有疑问。我的数据基本如下:

license_sets <- list(x = c("A", "B"), y = c("C", "D", "E"))
license_data <- data.frame(license = c("A","B","C","D","E"), bidder = c("x","x","y","y","y"))
source_data <- expand.grid(license_i = c("A","B","C","D","E"), license_j = c("A","B","C","D","E"))
source_data$value <- c(1:25)

我要应用的函数如下:

compute_set <- function(i, J){  tmp <- source_data %>% 
filter(license_i == i, license_j %in% J)
return(sum(tmp$value))
}

我现在想通过 mutate 应用函数:

license_data %>% mutate(z = compute_set(license, license_sets[[bidder]]))

我收到以下错误和警告消息:

Error in mutate_impl(.data, dots) : 
  Evaluation error: Evaluation error: recursive indexing failed at level 2
..
In addition: Warning messages:
1: In is.na(e1) | is.na(e2) :
  longer object length is not a multiple of shorter object length
2: In `==.default`(license_i, i) :
  longer object length is not a multiple of shorter object length

如果我用一个简单的 for 循环运行相同的函数,它完全可以正常工作。有谁知道这里有什么问题?它必须与变异有关,对吧?我也已经尝试过 as.character(bidder) 和我在这里找到的其他东西,但到目前为止没有任何效果。 我应该补充一点,我正在处理的数据框比我在这里显示的数据框大得多,所以 for 循环是不可行的......(因此我也感谢函数的简化提示;))

【问题讨论】:

  • 您的函数未矢量化。这就是为什么它可以在 for 循环中正常工作,但它不会神奇地在 dplyr mutate-statement 中进行矢量化。
  • 添加rowwise()

标签: r dplyr


【解决方案1】:

问题在于,在mutate 中,参数始终作为整个向量传递,如您在此处看到的:

license_data %>% mutate(z = {print(list(bidder, license));
                             compute_set(license, license_sets[[bidder]])})
# [[1]]
# [1] x x y y y
# Levels: x y
# [[2]]
# [1] A B C D E
# Levels: A B C D E
# Error in license_sets[[bidder]] : recursive indexing failed at level 2

以这种方式索引列表不起作用:

license_sets[[license_data$bidder]]
# Error in license_sets[[license_data$bidder]] : 
#   recursive indexing failed at level 2

所以你想通过向量 map 代替:

license_data %>% 
  mutate(z = map2(bidder, license, ~ compute_set(.y, license_sets[[.x]])))

矢量化

正如@[docendo discimus] 所指出的,您的函数的问题在于它没有矢量化,即它仅处理(在i 的情况下)一个标量。您可以矢量化您的函数以使用它作为预期:

compute_set_v <- Vectorize(compute_set)
license_data %>% 
   ## add the list content directly to the data frame 
   mutate(bidder_set = map(bidder, ~ license_sets[[.]]),
          z          = compute_set_v(license, bidder_set))

注意

data.frame 习惯将字符串视为因素,因此您可能需要在 data.frame 构造中添加 stringsAsFactors = FALSE

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    • 1970-01-01
    • 2022-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多