forked from tidyverse/ggplot2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscale-.r
120 lines (89 loc) · 2.99 KB
/
scale-.r
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# Domain: raw, transformed, user (limits)
# Range: raw, transformed
Scale <- proto(TopLevel, expr={
.input <- ""
.output <- ""
common <- NULL
legend <- TRUE
limits <- NULL
doc <- TRUE
class <- function(.) "scale"
new <- function(., name="Unknown") {
.$proto(name=name)
}
clone <- function(.) {
as.proto(.$as.list(all.names=TRUE), parent=.)
}
trained <- function(.) {
!is.null(.$input_set())
}
find <- function(., output, only.documented = FALSE) {
scales <- Scales$find_all()
select <- sapply(scales, function(x) any(output %in% c(x$output(), get("common", x))))
if (only.documented) select <- select & sapply(scales, function(x) get("doc", x))
unique(scales[select])
}
# Input --------------------------------------------------------------------
breaks <- NULL
input <- function(.) .$.input
input_set <- function(.) {
nulldefault(.$limits, .$.domain)
}
# Return names of all aesthetics in df that should be operated on
# by this scale - this is currently used for x and y scales, which also
# need to operate of {x,y}{min,max,end}.
input_aesthetics <- function(., df) {
input <- .$input()
matches <- aes_to_scale(names(df)) == input
names(df)[matches]
}
# Output -------------------------------------------------------------------
output <- function(.) .$.output
output_breaks <- function(.) .$map(.$input_breaks())
output_expand <- function(.) {
expand_range(.$output_set(), .$.expand[1], .$.expand[2])
}
# Train scale from a data frame
train_df <- function(., df, drop = FALSE) {
if (empty(df)) return()
# Don't train if limits have already been set
if (!is.null(.$limits)) return()
input <- .$input_aesthetics(df)
l_ply(input, function(var) .$train(df[[var]], drop))
}
# Map values from a data.frame. Returns data.frame
map_df <- function(., df) {
output <- .$input_aesthetics(df)
mapped <- llply(output, function(var) .$map(df[[var]]))
if (length(mapped) == 0) {
return(data.frame(matrix(nrow = nrow(df), ncol=0)))
}
output_df <- do.call("data.frame", mapped)
names(output_df) <- output
output_df
}
pprint <- function(., newline=TRUE) {
clist <- function(x) paste(x, collapse=",")
cat("scale_", .$objname, ": ", clist(.$input()), " -> ", clist(.$output()), sep="")
if (!is.null(.$input_set())) {
cat(" (", clist(.$input_set()), " -> ", clist(.$output_set()), ")", sep="")
}
if (newline) cat("\n")
}
html_returns <- function(.) {
ps(
"<h2>Returns</h2>\n",
"<p>This function returns a scale object.</p>"
)
}
my_names <- function(.) {
ps(.$class(), .$common, .$objname, sep="_", collapse=NULL)
}
my_full_name <- function(.) {
ps(.$class(), .$input(), .$objname, sep="_", collapse=NULL)
}
parameters <- function(.) {
params <- formals(get("new", .))
params[setdiff(names(params), c(".","variable"))]
}
})