问题:
我有一个函数,该函数使用参数来索引内部data.frame
,但返回一个整数。但是,当我在dplyr::mutate
中运行该函数以基于data.frame
中的另一个变量创建一个新变量时,出现错误:
Error in mutate_impl(.data, dots) : Evaluation error: duplicate subscripts for columns.
这似乎是由于使用变量的索引位置而不是其值对数据帧进行内部索引所致。
我该如何解决?
示例:
在此函数中,我需要索引到内部data.frame
并将其用于计算结果。 :连接和数据:
toyfun <- function(thing1){
thing2 <- data.frame(a = 0, b = 0, c = 0, d = 0)
thing2[, thing1] <- 1
thing3 <- sum(thing2[1,]) + thing1
return(thing3)
}
toydat <- tibble(thing1 = c(4, 3, 2, 1, 1, 2))
函数按预期运行:
toyfun(thing1 = toydat$thing1[1])
#[1] 5
但是,如果我想使用tibble
用data.frame
或mutate
中的变量的每个元素来计算函数,它将失败:
toydat %>%
mutate(thing4 = toyfun(thing1 = thing1))
# Error in mutate_impl(.data, dots) :
# Evaluation error: duplicate subscripts for columns.
如果我们仅使用toydat
的前4行(或更少),请注意,data.frame
中的内部toyfun
的宽度为4列,效果很好
toydat[1:4,] %>%
mutate(thing4 = toyfun(thing1 = thing1))
# # A tibble: 4 x 2
# thing1 thing4
# <dbl> <dbl>
# 1 4 5
# 2 3 4
# 3 2 3
# 4 1 2
但是,如果再次使用5行,那么遍历内部data.frame
的索引值,就会再次失败:
toydat[1:5,] %>%
mutate(thing4 = toyfun(thing1 = thing1))
# Error in mutate_impl(.data, dots) :
# Evaluation error: duplicate subscripts for columns.
问题的根源
该结果似乎表明问题在于使用thing1
的索引值而不是其实际值进行内部索引。这很奇怪,因为如上面的4行示例中所使用的那样,我们可以看到Thing4中的返回值与应使用thing1
的值计算结果时的值相同。
注意:sapply
不会发生相同的问题:
sapply(toydat$thing1, toyfun)
# [1] 5 4 3 2 2 3
在dplyr
类型框架中是否有解决此问题的想法,以便我可以保持工作流程的一致性?
答案 0 :(得分:1)
问题是因为mutate
将整个列一起发送到该函数。
让我们调试功能
toyfun <- function(thing1){
browser()
thing2 <- data.frame(a = 0, b = 0, c = 0, d = 0)
thing2[,thing1] <- 1
thing3 <- thing1 + 1
return(thing3)
}
现在我们运行mutate
命令
toydat %>%
mutate(thing4 = toyfun(thing1 = thing1))
#Called from: toyfun(thing1 = thing1)
#Browse[1]> thing1
#[1] 4 3 2 1 1 2
由于第1列有重复的条目,因此会出现错误。
与
相同df <- mtcars
df[, c(5, 5)] <- 1
[<-.data.frame
(*tmp*
,,c(1,1),value = 1)中的错误: 列的下标重复
现在让我们来看一下sapply
通话
sapply(toydat$thing1, toyfun)
#Called from: FUN(X[[i]], ...)
#Browse[1]> thing1
#[1] 4
sapply
一次传递值,因此没有错误。
与
相同df <- mtcars
df[, 5] <- 1
df[, 5] <- 1
没有任何错误。
要解决该错误,我们可以使用unique
仅获得unique
的{{1}}个条目
thing1
,这也将继续与toyfun <- function(thing1){
thing2 <- data.frame(a = 0, b = 0, c = 0, d = 0)
thing2[,unique(thing1)] <- 1
thing3 <- thing1 + 1
return(thing3)
}
toydat %>%
mutate(thing4 = toyfun(thing1 = thing1))
# A tibble: 6 x 2
# thing1 thing4
# <dbl> <dbl>
#1 4 5
#2 3 4
#3 2 3
#4 1 2
#5 1 2
#6 2 3
sapply
如果您不想更改功能,另一种选择是使用sapply(toydat$thing1, toyfun)
#[1] 5 4 3 2 2 3
,其作用与rowwise
相同,并将每个单独的值一个接一个地发送给功能
sapply
希望这很清楚而且很有帮助。