Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
2701 views
1
#-*-Fundamental-*-
2
3
4
# Spreadsheet written in S
5
6
# The spreadsheet may be called anything.
7
# References to cells in the spreadsheet must be called "x".
8
9
# Updating is in column order.
10
11
# Version 3 classes and methods technology.
12
13
14
as.spread <- function(x)
15
{
16
if (is.spread(x)) return(x)
17
x <- as.array(x)
18
attr(x,"expr") <- as.expr(x, length=0)
19
attr(x,"macro") <- as.expr(x, length=0)
20
attr(x,"before") <- as.expr(x, length=0)
21
attr(x,"after") <- as.expr(x, length=0)
22
class(x) <- c("spread", class(x))
23
x
24
}
25
26
is.spread <- function(x)
27
inherits(x,"spread")
28
29
30
print.spread <- function(x, ..., quote=F)
31
{
32
if (inherits(x, "data.frame")) print.data.frame(x)
33
else {
34
class(x) <- class(x)[-match("spread",class(x))]
35
print.array(x, ..., quote=quote)
36
}
37
invisible(x)
38
}
39
40
41
42
"[.spread"<-
43
function(x, ..., drop = F)
44
{
45
# Note: We do not retain the spread class!
46
# If we did, the subscripts on the expr() and macros() would be wrong
47
#
48
NextMethod("[", drop=drop)
49
}
50
51
52
"[.expr" <- function(x, ... , drop=F)
53
{
54
# Note: We do retain the expr class.
55
# The primary use is for printing, so we want the original subscripting.
56
57
z <- NextMethod("[", drop=drop)
58
class(z) <- class(x)
59
z
60
}
61
62
63
update.spread <- function(object, ..., force=F)
64
{
65
if (force) object <- eval.spread(object, NULL, force=force)
66
if (length(before(object)))
67
object <- eval.spread(object, before(object))
68
if (length(expr(object)))
69
object <- eval.spread(object, force=force)
70
if (length(after(object)))
71
object <- eval.spread(object, after(object))
72
object
73
}
74
75
eval.spread <- function(object, e, force=F)
76
{
77
x <- object
78
class(x) <- class(x)[-match("spread",class(x))]
79
if (force) {
80
.Options$warn <- -1
81
tmp <- as.numeric(as.matrix(x))
82
if (!any(is.na(tmp))) x <- tmp
83
}
84
if (missing(e)) {
85
if (inherits(x,"data.frame")) {
86
e <- expr(object)
87
if (force)
88
for (j in 1:ncol(x)) for (i in 1:nrow(x))
89
x[[i,j]] <- eval(e[i,j])
90
else
91
for (j in 1:ncol(x)) for (i in 1:nrow(x)) {
92
eij <- e[i,j]
93
if(is.language(eij)) x[[i,j]] <- eval(eij)
94
}
95
}
96
else {
97
i <- 0
98
if (force)
99
for (ei in expr(object))
100
{i <- i+1; x[i] <- eval(ei)}
101
else
102
for (ei in expr(object))
103
{i <- i+1; if(is.language(ei)) x[i] <- eval(ei)}
104
}
105
}
106
else eval(e)
107
class(x) <- class(object)
108
x
109
}
110
111
#usage: x <- macro.eval(x, i)
112
macro.eval <- function(object, i)
113
eval.spread(object, macro(x)[i])
114
115
116
"[[<-.spread" <- function(...) do.call("[<-.spread", list(...))
117
118
"[<-.spread" <- function(object, ..., value)
119
{
120
x <- object
121
expr(x) <- expression()
122
class(x) <- NULL
123
e <- expr(object)
124
l.e <- length(e)
125
i.a.v <- is.atomic(substitute(value))
126
n.cells <- prod(dim(x[..., drop=F]))
127
128
if (l.e == 0) {
129
if (n.cells != 1 || i.a.v )
130
x[...] <- eval(substitute(value))
131
else {
132
e <- as.expr(object)
133
l.e <- length(e)
134
}
135
}
136
if (l.e != 0) {
137
if (n.cells != 1) {
138
e.s.v <- eval(substitute(value, sys.parent()))
139
x[...] <- e.s.v
140
e[...] <- e.s.v
141
}
142
else {
143
e[[...]] <- substitute(value)
144
x[[...]] <- eval(e[[...]])
145
}
146
}
147
attributes(x) <- attributes(object)
148
class(x) <- class(object)
149
expr(x) <- e
150
update.spread(x)
151
}
152
153
154
print.expr <- function(e, ..., replace.string=F) {
155
replace <- as.logical(replace.string)
156
if (length(e) == 0) {
157
if (replace) cat(replace.string, "<- ")
158
print(expression())
159
}
160
else if (is.null(dim(e))) {
161
ne <- names(e)
162
for (i in 1:length(e)) {
163
nei <- index.value(ne, i)
164
if (replace) cat(replace.string)
165
cat(paste("[", nei, "] ", sep=""))
166
if (replace) cat("<- expression(")
167
cat(e[i])
168
if (replace) cat(")")
169
cat("\n")
170
}
171
}
172
else {
173
dn <- dimnames(e)
174
if (is.null(dn)) dn <- list()
175
for (i in 1:length(dim(e))) {
176
if (is.null(dn[[i]])) dn[[i]] <- 1:dim(e)[i]
177
}
178
dnn <- outer(dn[[1]], dn[[2]], paste, sep=",")
179
if (length(dn) > 2)
180
for (i in 3:length(dn))
181
dnn <- outer(dnn, dn[[i]], paste, sep=",")
182
for (i in seq(length=length(e))) {
183
if (replace) cat("x")
184
cat(paste("[", dnn[i], "] ", sep=""))
185
if (replace) cat("<-")
186
cat(paste(" ", e[i], "\n", sep=""))
187
}
188
}
189
invisible(e)
190
}
191
192
as.expr <- function(x, ...) UseMethod("as.expr")
193
194
as.expr.default <- function(x, length.x=prod(dim(x))) {
195
e <- vector(mode="expression", length=length.x)
196
x <- unclass(x)
197
if (length.x > 0) {
198
e <- array(e, dim(x), dimnames(x))
199
e[] <- x[]
200
# for (i in 1:length(e)) e[i] <- x[i]
201
}
202
class(e) <- "expr"
203
e
204
}
205
206
as.expr.data.frame <- function(x, length.x=prod(dim(x))) {
207
e <- vector(mode="expression", length=length.x)
208
if (length.x > 0) {
209
e <- array(e, dim(x), dimnames(x))
210
u.x <- unclass(x)
211
for (j in 1:ncol(x)) {
212
uxj <- as.matrix(u.x[[j]])
213
for (i in 1:nrow(x))
214
e[i,j] <- uxj[i,1]
215
}
216
}
217
class(e) <- "expr"
218
e
219
}
220
221
222
expr <- function(x)
223
attr(x,"expr")
224
225
# "expr<-" is used only when value is a matrix the size of x, or to update
226
# a subscripted piece of x. It is not a user function.
227
# Currently used only in "[<-.spread".
228
"expr<-" <- function(x, value)
229
{
230
attr(x,"expr") <- value
231
x
232
}
233
234
"before<-" <- function(x, value)
235
{
236
attr(x,"before") <- value
237
class(attr(x,"before")) <- "expr"
238
x
239
}
240
241
"macro<-" <- function(x, value)
242
{
243
attr(x,"macro") <- value
244
class(attr(x,"macro")) <- "expr"
245
x
246
}
247
248
"after<-" <- function(x, value)
249
{
250
attr(x,"after") <- value
251
class(attr(x,"after")) <- "expr"
252
x
253
}
254
255
before <- function(x)
256
attr(x,"before")
257
258
259
macro <- function(x)
260
attr(x,"macro")
261
262
263
after <- function(x)
264
attr(x,"after")
265
266
267
expr.rc <- function(x, ...) UseMethod("expr.rc")
268
269
expr.rc.default <- function(x, acpab)
270
{
271
subs <- paste("[", paste(acpab, collapse=","), "]")
272
273
if (length(expr(x))==0) {
274
x.expr <- paste("x.value(x",subs,")",sep="")
275
value <- eval(parse(text=x.expr))
276
}
277
else {
278
e.expr <- paste("expr.value(expr(x)", subs, ", x", subs, ")")
279
value <- eval(parse(text=e.expr))
280
}
281
282
paste("x", subs, " <- ", value, sep="")
283
}
284
285
286
x.value <- function(x) {
287
value <-
288
if (length(x)==1)
289
as.vector(as.matrix(x[[1]]))
290
else if (inherits(x,"data.frame"))
291
lapply(x, function(x) as.vector(as.matrix(x)))
292
else
293
as.vector(x)
294
deparse(value)
295
}
296
297
expr.value <- function(e, x) {
298
if (inherits(x,"data.frame") &&
299
(dim(e)[2]>1 || inherits(x[[1]],"factor")))
300
value <- deparse(lapply(e, function(x) as.vector(as.matrix(x))))
301
else {
302
value <- paste(e, collapse=",")
303
if (length(e) > 1) value <- paste("c(", value, ")", sep="")
304
}
305
value
306
}
307
308
309
index.value <- function(dn, i, deparse.result=T) {
310
if (i==0) {i <- 0; mode(i) <- "missing"}
311
if (is.numeric(i) && i>0 && length(dn)) i <- dn[i]
312
if (deparse.result) deparse(as.vector(i))
313
else as.vector(i)
314
}
315
316
as.numeric.spread <- function(x)
317
{
318
.Options$warn <- -1
319
tmp <- as.numeric(unclass(x))
320
tmp <- ifelse(is.na(tmp), 0, tmp)
321
attributes(tmp) <- attributes(x)
322
tmp
323
}
324
325
all.numeric <- function(x) {
326
.Options$warn <- -1
327
!any(is.na(as.numeric(x)))
328
}
329
330
331