Reputation: 1235
The task I'm facing is to return some rows from a list of matrices. Rows to return can be entered as a number or as "first" and "last". I've coded that like this:
showrow <- function(row) {
if (class(row) == "numeric") {
getrow <- function(d) {
d[row,]
}
return(getrow)
} else {
if (row =="first") {
getrow <- function(d) {
head(d, 1)
}
return(getrow)
} else {
if (row == "last") {
getrow <- function(d) {
tail(d, 1)
}
return(getrow)
} else {
stop("invalid position")
}
}
}
}
And then it's possible to use it like that:
a <- matrix(rnorm(20), 4)
b <- matrix(rnorm(100), 10)
lst <- list(a, b) ; lst
num <- "last" # Or `num <- "first"`, or `num <- 3`, etc
lapply(lst, function(df) { showrow(num)(df) })
The problem is I think that If
structure still looks clumsy... Is there any workaround to avoid it in this particular scenario?
(And, on a side note, is it possible to return NAs if the subscript would be out of bounds, like num <- 11
, for example?)
Upvotes: 2
Views: 687
Reputation: 52637
You greatly simplify your problem if you change your interface to:
show me the last row if you give me anything but a number, or that row otherwise:
showrow <- function(row) {
if(!is.numeric(row)) return(function(x) tail(x, 1L))
function(x) tryCatch(x[row, ], error=function(e) NA)
}
Usage examples:
showrow("last")(a) # Last row
showrow(4)(a) # 4th row (also last in this case)
showrow(2:3)(a) # 2nd and 3rd
showrow(20)(a) # Returns NA
You don't need to have a special token for "first" since 1
works just fine. Then you can do stuff like this. Obviously showrow("first")(mx)
would still return the last row, which might be confusing. Really the best thing would be something like:
show me a specific row if I specify it, or the last one if I don't.
That's even easier to implement.
Upvotes: 1
Reputation: 19960
Here is a switch
solution.
showrow <- function(row) {
switch(class(row),
numeric = function(d) {
d[row,]
},
character = switch(row,
first = function(d){
head(d,1)
},
last = function(d){
tail(d,1)
},
{stop("Invalid position")}),
{stop("Invalid position")}
)
}
Upvotes: 1
Reputation: 13304
Here is one approach:
showrow <- function(row) {
if (class(row) == "numeric") return(function(d) d[row,])
f <- list(first=head,last=tail)[[row]]
if (is.null(f)) stop("invalid position")
function(d) f(d,1)
}
Upvotes: 1