分析Excel公式

如果这是一个长期的啰嗦,提前道歉。 我需要模仿一组特定电子表格的function。 这需要在R完成。获取数据等是相对简单的。 我现在需要在给定的工作表中实现公式。 像XLConnect这样的XLConnect能够以string格式提取公式。 对于特定的工作表,数据如下所示:

 exForm <- structure(list(r = c("A2", "B2", "A3", "B3", "A4", "B4", "A5", "B5", "A6", "B6", "A7", "B7"), formulae2 = c("1", "A2", "A2+1", "SUM(A$2:A3)", "A3+1", "SUM(A$2:A4)", "A4+1", "SUM(A$2:A5)", "A5+1", "SUM(A$2:A6)", "A6+1", "SUM(A$2:A7)"), x = c("2", "2", "3", "3", "4", "4", "5", "5", "6", "6", "7", "7"), y = c("1", "2", "1", "2", "1", "2", "1", "2", "1", "2", "1", "2")), .Names = c("r", "formulae2", "x", "y"), class = "data.frame", row.names = c(NA, -12L)) #> exForm # r formulae2 xy #1 A2 1 2 1 #2 B2 A2 2 2 #3 A3 A2+1 3 1 #4 B3 SUM(A$2:A3) 3 2 #5 A4 A3+1 4 1 #6 B4 SUM(A$2:A4) 4 2 #7 A5 A4+1 5 1 #8 B5 SUM(A$2:A5) 5 2 #9 A6 A5+1 6 1 #10 B6 SUM(A$2:A6) 6 2 #11 A7 A6+1 7 1 #12 B7 SUM(A$2:A7) 7 2 

有一个整齐的Python代码在这里实现了一个原始的JavaScript代码片段。 我已经使用rPython将我的数据传递给了这组函数。

 library(rPython) excelURL <- "http://www.ewbi.com/ewbi.develop/samples/jsport_nonEAT.py" download.file(excelURL, "excel.py") python.exec("execfile('excel.py')") python.assign("test", exForm$formulae2) python.exec('t=[] for i in range(len(test)): \t p.parse(test[i]) \t t.append(p.prettyprint()) ') parseForm <- python.get('t') 

如果人们没有使用rPython来传递parseForm的输出

 c("1 <operand> <number>\n", "A2 <operand> <range>\n", "A2 <operand> <range>\n+ <operator-infix> <math>\n1 <operand> <number>\n", "SUM <function> <start>\n A$2:A3 <operand> <range>\n <function> <stop>\n", "A3 <operand> <range>\n+ <operator-infix> <math>\n1 <operand> <number>\n", "SUM <function> <start>\n A$2:A4 <operand> <range>\n <function> <stop>\n", "A4 <operand> <range>\n+ <operator-infix> <math>\n1 <operand> <number>\n", "SUM <function> <start>\n A$2:A5 <operand> <range>\n <function> <stop>\n", "A5 <operand> <range>\n+ <operator-infix> <math>\n1 <operand> <number>\n", "SUM <function> <start>\n A$2:A6 <operand> <range>\n <function> <stop>\n", "A6 <operand> <range>\n+ <operator-infix> <math>\n1 <operand> <number>\n", "SUM <function> <start>\n A$2:A7 <operand> <range>\n <function> <stop>\n" ) 

所以我现在收集parseForm包含原始公式的标记版本。 为了在R中使用,我将parseForm的表单渲染为Rexpression式?

 > ex1 <- expression(1 + A1) > A1 <- 10 > eval(ex1) [1] 11 

有没有人有类似的经验,或有人指出我在正确的方向。 对于额外的信息,我有工作表中的数据表示为一个数据框,例如上面提到的sheet1 ,这是指:

 wData <- structure(c(NA, 1, 2, 3, 4, 5, 6, NA, 1, 3, 6, 10, 15, 21), .Dim = c(7L, 2L)) 

我认为这个想法是input是exForm ,输出应该是wData

以下内容可以进一步推广,但对于问题中的示例来说,它足够了。 请注意,它假定exForm中的任何单元格仅指它上面的单元格(在这里是这种情况,在大多数情况下可能是这种情况),以便我们可以线性进行exForm的行。

ss删除给出x1美元符号,然后将诸如A2:A4string转换为wData[2:4, "A"]给出x2 ,然后将embedded的A2等string转换为embedded的wData[2, "A"]等等。 剩下的可以parsing为R,我们这样做。 for循环遍历exForm从顶层应用ssexForm定义的每个单元。 没有插件包是必要的。

 SUM <- sum ss <- function(x) { x1 <- gsub("$", "", x, fixed = TRUE) x2 <- gsub("([[:alpha:]]+)([[:digit:]]+):\\1([[:digit:]]+)", "wData[\\2:\\3, '\\1']", x1, perl = TRUE) x3 <- gsub("([[:alpha:]]+)([[:digit:]]+)", "wData[\\2, '\\1']", x2) eval.parent(parse(text = x3)) } wData <- matrix(NA, nr = max(as.numeric(exForm$x)), nc = max(as.numeric(exForm$y))) colnames(wData) <- LETTERS[1:ncol(wData)] for(i in 1:nrow(exForm)) { x <- as.numeric(exForm$x[i]) y <- as.numeric(exForm$y[i]) wData[x, y] <- ss(exForm$formulae2[i]) } 

赠送:

 > wData AB [1,] NA NA [2,] 1 1 [3,] 2 3 [4,] 3 6 [5,] 4 10 [6,] 5 15 [7,] 6 21 

修订了许多更正和简化。