R- expand.grid 给出了 data.frame 的参数名称和序列定义

R- expand.grid given a data.frame of parameter names and sequence definitions

我有一个data.frame可以任意定义参数名称和序列边界:

dfParameterValues <- data.frame(ParameterName = character(), seqFrom = integer(), seqTo = integer(), seqBy = integer())
row1 <- data.frame(ParameterName = "parameterA", seqFrom = 1, seqTo = 2, seqBy = 1)
row2 <- data.frame(ParameterName = "parameterB", seqFrom = 5, seqTo = 7, seqBy = 1)
row3 <- data.frame(ParameterName = "parameterC", seqFrom = 10, seqTo = 11, seqBy = 1)
dfParameterValues <- rbind(dfParameterValues, row1)
dfParameterValues <- rbind(dfParameterValues, row2)
dfParameterValues <- rbind(dfParameterValues, row3)

我想使用这种方法根据唯一 ParameterName 的数量创建 c 参数列的网格,其中包含 seqFrom 给出的所有可能序列组合的 r 行、seqToseqBy。因此,结果看起来有点像这样或者应该具有如下内容:

ParameterA ParameterB ParameterC
1          5          10
1          5          11
1          6          10
1          6          11
1          7          10
1          7          11
2          5          10
2          5          11
2          6          10
2          6          11
2          7          10
2          7          11

编辑:请注意,参数名称及其编号是事先不知道的。 data.frame 来自其他地方,所以我不能使用标准的静态 expand.grid 方法,需要类似灵活的函数之类的东西,它基于具有列 ParameterName、seqFrom、seqTo、seqBy 的任何数据框创建扩展网格。

我一直在研究 for 循环(开始时很糟糕),但它并没有使我产生任何优雅的想法。我似乎也无法找到一种方法来通过使用 tidyr 来得出结果,而无需先单独构建序列。你有什么优雅的方法吗?

将其扩展到不仅包括数字序列,还包括 vectors/sets 个字符/其他因素的额外荣誉。

非常感谢!

脱离 CPak 的答案,你可以使用

my_table <- expand.grid(apply(dfParameterValues, 1, function(x) seq(as.numeric(x['seqFrom']), as.numeric(x['seqTo']), as.numeric(x['seqBy']))))
names(my_table) <- c("ParameterA", "ParameterB", "ParameterC")
my_table <- my_table[order(my_table$ParameterA, my_table$ParameterB), ]

@smanski 的回答在技术上是正确的(并且可以说应该被接受,因为它激发了这一点),但它也是一个很好的例子,说明在将 applydata.frame 一起使用时何时要小心。在这种情况下,该框架至少包含一列是character,因此所有列都被转换,导致需要使用as.numeric。更安全的选择是只拉取所需的列,例如:

expand.grid(apply(dfParameterValues[,-1], 1,
            function(x) seq(x['seqFrom'], x['seqTo'], x['seqBy']) ))
expand.grid(apply(dfParameterValues[,c("seqFrom","seqTo","seqBy")], 1,
            function(x) seq(x['seqFrom'], x['seqTo'], x['seqBy']) ))

我更喜欢第二种,因为它只提取它需要的东西,因此 "knows" 应该是数字。 (我发现 explicit 通常更安全。)

发生这种情况的原因是 apply 默默地将数据转换为 matrix,因此要查看效果,请尝试:

str(as.matrix(dfParameterValues))
#  chr [1:3, 1:4] "parameterA" "parameterB" "parameterC" " 1" " 5" ...
#  - attr(*, "dimnames")=List of 2
#   ..$ : chr [1:3] "1" "2" "3"
#   ..$ : chr [1:4] "ParameterName" "seqFrom" "seqTo" "seqBy"
str(as.matrix(dfParameterValues[c("seqFrom","seqTo","seqBy")]))
#  num [1:3, 1:3] 1 5 10 2 7 11 1 1 1
#  - attr(*, "dimnames")=List of 2
#   ..$ : chr [1:3] "1" "2" "3"
#   ..$ : chr [1:3] "seqFrom" "seqTo" "seqBy"

(注意第一个的 chr 和第二个的 num。)

两者都没有保留参数名称。为此,只需将调用与 setNames:

夹在中间
setNames(
  expand.grid(apply(dfParameterValues[,c("seqFrom","seqTo","seqBy")], 1,
              function(x) seq(x['seqFrom'], x['seqTo'], x['seqBy']) )),
  dfParameterValues$ParameterName)