R Advanced Usage
library(ggplot2) |
Types
In R, we have:
| mode ~= class | typeof == storage.mode |
|---|---|
| numeric | double integer |
| character | character |
| logic | logical |
character(2) # "" "" numeric(2) double(2) integer(2) # 0 0 logical(2) # [1] FALSE FALSE !logical(2) # [1] TRUE TRUE |
sapply(list(1:2,c(1:2),c(1,2),"hi",TRUE,1,1.5,2L), mode) # "numeric" "numeric" "numeric" "character" "logical" "numeric" "numeric" "numeric" sapply(list(1:2,c(1:2),c(1,2),"hi",TRUE,1,1.5,2L), class) # "integer" "integer" "numeric" "character" "logical" "numeric" "numeric" "integer" sapply(list(1:2,c(1:2),c(1,2),"hi",TRUE,1,1.5,2L), typeof) # "integer" "integer" "double" "character" "logical" "double" "double" "integer" sapply(list(1:2,c(1:2),c(1,2),"hi",TRUE,1,1.5,2L), storage.mode) # "integer" "integer" "double" "character" "logical" "double" "double" "integer" ## So, class is a weied method, double <--> numeric ## We can check it with sapply(list(numeric(2),double(2),integer(2),logical(2),character(2)),class) # "numeric" "numeric" "integer" "logical" "character" |
sapply(list(c(), vector(), factor(), list(), matrix(), data.frame(), NULL, NA),base::mode) # [1] "NULL" "logical" "numeric" "list" "logical" "list" # [7] "NULL" "logical" sapply(list(c(), vector(), factor(), list(), matrix(), data.frame(), NULL, NA),class) # [1] "NULL" "logical" "factor" "list" "matrix" "data.frame" # [7] "NULL" "logical" sapply(list(c(), vector(), factor(), list(), matrix(), data.frame(), NULL, NA),typeof) # [1] "NULL" "logical" "integer" "list" "logical" "list" # [7] "NULL" "logical" sapply(list(c(), vector(), factor(), list(), matrix(), data.frame(), NULL, NA),storage.mode) # [1] "NULL" "logical" "integer" "list" "logical" "list" # [7] "NULL" "logical" |
sapply(list("123","hi",TRUE,2L,1.5),as.character) # "123" "hi" "TRUE" "2" "1.5" sapply(list("123","hi",TRUE,2L,1.5),as.double) ## NAs introduced by coercion # 123.0 NA 1.0 2.0 1.5 sapply(list("123","hi",TRUE,2L,1.5),as.integer) ## NAs introduced by coercion # 123 NA 1 2 1 sapply(list("123","hi",TRUE,2L,1.5),as.logical) # NA NA TRUE TRUE TRUE |
is.atomic:TRUE if x is of an atomic type (or NULL)
is.recursive:TRUE if x has a recursive (list-like) structure
sapply(list(c(), vector(), factor(), list(), matrix(), data.frame(), NULL, NA),is.atomic) # TRUE TRUE TRUE FALSE TRUE FALSE TRUE TRUE sapply(list(c(), vector(), factor(), list(), matrix(), data.frame(), NULL, NA),is.list) # FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE sapply(list(c(), vector(), factor(), list(), matrix(), data.frame(), NULL, NA),is.recursive) # FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE |
Environment
e1<-new.env(hash=T) e1$a<-10 ls(e1) # [1] "a" ## operator $ or [[ e1$a e1[["a"]] # [1] 10 # e1[1] !Error attr(e1,"foo")<-10 attr(e1,"bar")<-20 e1 # <environment: 0x000000001fcd5898> # attr(,"foo") # [1] 10 # attr(,"bar") # [1] 20 f<-function(n, env){ b<-get("a", envir = env); assign("a", b + n, envir = env)} f(10,e1) e1$a # [1] 20 f(10,e1) e1$a # [1] 30 f1<-function( n ){ n + a} environment(f1)<-e1 f1(10) # [1] 40 f1(20) # [1] 50 e1$a<-100 f1(20) # 120 e1$b<-20 e1$c<-"c" mget(c("a","b","c","d"),envir= e1,ifnotfound=NA) # $a # [1] 100 # $b # [1] 20 # $c # [1] "c" # $d # [1] NA |
findArgs <- function(env, pattern) { nms <- ls(envir = as.environment(env)) nms <- nms[is.na(match(nms, c("F","T")))] ## remove F && T aa <- sapply(nms, function(.) { o <- get(.) if(is.function(o)) names(formals(o)) }) ## indeed, all true iw <- sapply(aa, function(a) any(grepl(pattern, a, ignore.case=TRUE))) aa[iw] } |
body(findArgs) # { # nms <- ls(envir = as.environment(env)) # nms <- nms[is.na(match(nms, c("F", "T")))] # aa <- sapply(nms, function(.) { # o <- get(.) # if (is.function(o)) # names(formals(o)) # }) # iw <- sapply(aa, function(a) any(grepl(pattern, a, ignore.case = TRUE))) # aa[iw] # } formals(findArgs) # $env # $pattern names(formals(findArgs)) # "env" "pattern" environment(findArgs) # <environment: R_GlobalEnv> attributes(findArgs) # $srcref # function(env, pattern) { # nms <- ls(envir = as.environment(env)) # nms <- nms[is.na(match(nms, c("F","T")))] ## remove F && T # aa <- sapply(nms, function(.) { o <- get(.) # if(is.function(o)) names(formals(o)) }) ## indeed, all true # iw <- sapply(aa, function(a) any(grepl(pattern, a, ignore.case=TRUE))) # aa[iw] # } env = "package:ggplot2" as.environment(env) # <environment: package:ggplot2> # attr(,"name") # [1] "package:ggplot2" # attr(,"path") # [1] "D:/Program Files/R-3.4.4/library/ggplot2" all(ls(envir = as.environment(env)) == ls(env)) # TRUE ls(env)[82:125] # [1] "geom_abline" "geom_area" "geom_bar" # [4] "geom_bin2d" "geom_blank" "geom_boxplot" # [7] "geom_col" "geom_contour" "geom_count" # [10] "geom_crossbar" "geom_curve" "geom_density" # [13] "geom_density_2d" "geom_density2d" "geom_dotplot" # [16] "geom_errorbar" "geom_errorbarh" "geom_freqpoly" # [19] "geom_hex" "geom_histogram" "geom_hline" # [22] "geom_jitter" "geom_label" "geom_line" # [25] "geom_linerange" "geom_map" "geom_path" # [28] "geom_point" "geom_pointrange" "geom_polygon" # [31] "geom_qq" "geom_quantile" "geom_raster" # [34] "geom_rect" "geom_ribbon" "geom_rug" # [37] "geom_segment" "geom_smooth" "geom_spoke" # [40] "geom_step" "geom_text" "geom_tile" # [43] "geom_violin" "geom_vline" formals(get(ls(env)[84])) # $mapping # NULL # $data # NULL # $stat # [1] "count" # $position # [1] "stack" # $... # # $width # NULL # $binwidth # NULL # $na.rm # [1] FALSE # $show.legend # [1] NA # $inherit.aes # [1] TRUE |
findArgs("package:ggplot2","colours") # $scale_color_gradientn # [1] "..." "colours" "values" "space" "na.value" "guide" # [7] "colors" # # $scale_colour_gradientn # [1] "..." "colours" "values" "space" "na.value" "guide" # [7] "colors" # # $scale_fill_gradientn # [1] "..." "colours" "values" "space" "na.value" "guide" # [7] "colors" |
Assignment
v1 <- v2 <- 5 -> v3 identical(v1,v2,v3) # TRUE |
Assign a value to a name in an environment
for(i in 1:5){ nam <- paste("var", i, sep = "") assign(nam, 1:i) } ls(pattern = "^var.$") # "var1" "var2" "var3" "var4" "var5" get(paste("var", 5, sep = "")) # 1 2 3 4 5 deparse(var5) # "1:5" substitute(var5) # var5 assign("var5[5]", 1) var5[5] # 5 `var5[5]` get("var5[5]") # 1 |
In R, We have <- VS = assignment operators, the main difference is the scope
rm(x) |
## Warning in rm(x): 找不到对象'x' |
mean(x=1:10) # x ## Error: object 'x' not found mean(x <- 1:10) x # [1] 1 2 3 4 5 6 7 8 9 10 |
Functions
a <- 1 f <- function(a) return(a <- a + 1) f2 <- f(a <- a + 5) a # 6 f2 # 7 a = 1 f <- function(a) return(a <- a + 1 ) f2 <- f(a = a + 5) a # 1 f2 # 7 a <- 1 f <- function(a) return(a <<- a + 1) f2 <- f(a = a + 5) a # 7 f2 # 7 |
Scheme Perl Python Common Lisp (all languages converge to Lisp) Lexical scope
make.power <- function(n) { pow <- function(x) { x^n } pow } cube <- make.power(3) square <- make.power(2) cube(4) square(3) # 64 # 9 ls(environment(cube)) # "n" "pow" get("n", environment(cube)) # 3 ls(environment(square)) # "n" "pow" get("n", environment(square)) # 2 |
n <- function(x) x * 2 foo <- function() { n <- 5 n(n) } foo() |
fun <- function(param1, param2 = c("SEL1", "SEL2", "SEL3"), ...) { if (missing(param1)) { stop("param1 is required.") } if (!inherits(param1, c("numeric", "integer", "double"))) { stop("param1 must be an object of numeric") } param2 <- match.arg(param2) if (!missing(...)) { dots <- substitute(list(...))[-1] names <- unlist(sapply(dots, deparse)) return(names) } else { return(invisible(quantile(param1))) } } fun(param1 = 1:10, param2 = "SEL2") res <- fun(param1 = 1:10, param2 = "SEL2") res # 0% 25% 50% 75% 100% # 1.00 3.25 5.50 7.75 10.00 fun(param1 = 1:10, param2 = "SEL3", otherParam = "It returned!!!") # otherParam # "\"It returned!!!\"" |
Dubug
Insert this into your code at the place where you want to start debugging:
browser() |
When the R interpreter reaches that line, it will pause your code and you will be able to look at and change variables.
In the browser, typing these letters will do things:
| c | Continue |
| n (or Return) | Next step |
| Q | quit |
| Ctrl-C | go to top level |
To pause and start a browser for every line in your function:
# debug(myfunction) # myfunction(x) |
By default, every time you press Enter at the browser prompt, it runs the next step. This is equivalent to pressing n and then Enter. This can be annoying. To disable it use:
options(browserNLdisabled=TRUE) getOption("defaultPackages") |
To start debugging whenever an error is thrown, run this before your function which throws an error:
options(error=recover) |
If you want these options to be set every time you start R, you can put them in your ~/.Rprofile file.



