I'm sure this is simple, but I cannot find a solution ...
I would like to use a variable containing a character string as argument for a function.
x <- c(1:10)
myoptions <- "trim=0, na.rm=FALSE"
Now, something like
foo <- mean(x, myoptions)
should be the same as
foo <- mean(x, trim=0, na.rm=FALSE)
Thanks in advance!
You can use eval and parse:
foo <- eval(parse(text = paste("mean(x,", myoptions, ")")))
A more natural way to do what you want is to use do.call. For example,
R> l[["trim"]] = 0
R> l[["na.rm"]] = FALSE
R> l[["x"]] = 1:10
##Or l <- list(trim = 0, na.rm = FALSE, x = 1:10)
R> do.call(mean, l)
[1] 5.5
If for some reason you really want to use a myoptions string, you could always use strsplit to coarce it into a list form. For example,
R> y = "trim=0, na.rm=FALSE"
R> strsplit(y, ", ")
[[1]]
[1] "trim=0" "na.rm=FALSE"
R> strsplit(y, ", ")[[1]][1]
[1] "trim=0"
Here's a third answer that both uses parse, alist and do.call. My motivation for this new answer, is in the case where arguments are passed interactively from a client-side as chars. Then I guess, there is no good way around not using parse. Suggested solution with strsplit, cannot understand the context whether a comma , means next argument or next argument within an argument. strsplit does not understand context as strsplit is not a parser.
here arguments can be passed as "a=c(2,4), b=3,5" or list("c(a=(2,4)","b=3","5")
#' convert and evaluate a list of char args to a list of arguments
#'
#' #param listOfCharArgs a list of chars
#'
#' #return
#' #export
#'
#' #examples
#' myCharArgs = list('x=c(1:3,NA)',"trim=0","TRUE")
#' myArgs = callMeMaybe(myCharArgs)
#' do.call(mean,myArgs)
callMeMaybe2 = function(listOfCharArgs) {
CharArgs = unlist(listOfCharArgs)
if(is.null(CharArgs)) return(alist())
.out = eval(parse(text = paste0("alist(",
paste(parse(text=CharArgs),collapse = ","),")")))
}
myCharArgs = list('x=c(1:3,NA)',"trim=0","TRUE")
myArgs = callMeMaybe2(myCharArgs)
do.call(mean,myArgs)
[1] 2
Using all of do.call, eval and parse (combining kohske's and csgillespie's answers, and also WoDoSc's answer to 'Pass a comma separated string as a list'):
x <- c(1:10)
myoptions <- "trim = 0, na.rm = FALSE"
do.call(
what = mean,
args = append(list(x = x), eval(parse(text = paste0("list(", myoptions, ")"))))
)
This solution can be quite resilient in a more complex case, such as shown below.
myfn <- function(x, y = 0, z = 0, ...) {
print(paste("x:", x))
print(paste("y:", y))
print(paste("z:", z))
if (length(list(...)) > 0) {
print("other:")
print(list(...))
}
}
myextraargs <- paste(
"y = c(11, 14), z = 47,",
"t = data.frame(p = c('apple', 'plum'), j = c(7, 2), k = c(3, 21))"
)
do.call(
what = myfn,
args = append(
list(x = 7),
eval(parse(text = paste0("list(", myextraargs, ")")))
)
)
results in:
[1] "x: 7"
[1] "y: 11" "y: 14"
[1] "z: 47"
[1] "other:"
$t
p j k
1 apple 7 3
2 plum 2 21
...and...
myextraargs <- NULL
do.call(
what = myfn,
args = append(
list(x = 7),
eval(parse(text = paste0("list(", myextraargs, ")")))
)
)
results in
[1] "x: 7"
[1] "y: 0"
[1] "z: 0"
Related
The following example is for anyone who is building a Cox Proportional Hazards models and trying to produce prediction error curves, but get an error stating:
Error in coxModelFrame.coxph(object) : invalid object
set x=TRUE in the call to coxph.
Here is the code to reproduce the error:
LIBRARIES
library(survival)
library(survminer)
library(pec)
library(Hmisc)
library(rms)
library(riskRegression)
#install.packages("doMC", repos="http://R-Forge.R-project.org")
library(doMC)
The Data
#Load and store the data
lcOrig <- read.csv("cancer.csv")
#Replace all the 1's with 0's (censored)
lcOrig$status <- gsub(pattern = "1", replacement = "0", x = lcOrig$status, fixed = TRUE)
#Replace all the 2's with 1's (death)
lcOrig$status <- gsub (pattern = "2", replacement = "1", x = lcOrig$status, fixed = TRUE)
#Do the same thing for sex (0 = Males, 1 = Females)
lcOrig$sex <- gsub(pattern = "1", replacement = "0", x = lcOrig$sex, fixed = TRUE)
lcOrig$sex <- gsub(pattern = "2", replacement = "1", x = lcOrig$sex, fixed = TRUE)
#Change the class of these variables to integer.
lcOrig$status <- as.integer(lcOrig$status)
lcOrig$sex <- as.integer(lcOrig$sex)
lcOrig$ph.ecog <- as.integer(lcOrig$ph.ecog)
#Remove missing values and column with over 20% missing data.
apply(lcOrig, 2, function(x) sum(is.na(x))/length(x))
lcOrig <- lcOrig[, c(1:9, 11)]
lc <- lcOrig[complete.cases(lcOrig), ]
Cox Proportional Hazards
fitform1 <- Surv(time, status) ~ inst + age + sex + ph.ecog + ph.karno + pat.karno + wt.loss
cox1 <- coxph(fitform1, data = lc)
PREDICTION ERROR CURVES
extends <- function(...) TRUE
library("doMC")
registerDoMC()
set.seed(0692)
fitpec1 <- pec(list("CPH" = cox1), data = lc, formula = fitform1, splitMethod = "cv10", B = 5, keep.index = TRUE, keep.matrix = TRUE)
The last line of code results in the following error:
Error in coxModelFrame.coxph(object) : invalid object
set x=TRUE in the call to coxph
SOLUTION
Change:
cox1 <- coxph(fitform1, data = lc)
To:
cox1 <- coxph(fitform1, data = lc, x = TRUE)
This did not use to be a requirement 2 years ago, but is now. I hope this helps save you some time!
I need to concatenate a String and Int as below:
let myVariable: Int = 8
return "first " + myVariable
But it does not compile, with the error:
Binary operator '+' cannot be applied to operands of type 'String' and 'Int'
What is the proper way to concatenate a String + Int?
If you want to put a number inside a string, you can just use String Interpolation:
return "first \(myVariable)"
You have TWO options;
return "first " + String(myVariable)
or
return "first \(myVariable)"
To add an Int to a String you can do:
return "first \(myVariable)"
If you're doing a lot of it, consider an operator to make it more readable:
func concat<T1, T2>(a: T1, b: T2) -> String {
return "\(a)" + "\(b)"
}
let c = concat("Horse ", "cart") // "Horse cart"
let d = concat("Horse ", 17) // "Horse 17"
let e = concat(19.2345, " horses") // "19.2345 horses"
let f = concat([1, 2, 4], " horses") // "[1, 2, 4] horses"
operator infix +++ {}
#infix func +++ <T1, T2>(a: T1, b: T2) -> String {
return concat(a, b)
}
let c1 = "Horse " +++ "cart"
let d1 = "Horse " +++ 17
let e1 = 19.2345 +++ " horses"
let f1 = [1, 2, 4] +++ " horses"
You can, of course, use any valid infix operator, not just +++.
Optional keyword would appear when you have marked variable as optional with ! during declaration.
To avoid Optional keyword in the print output, you have two options:
Mark the optional variable as non-optional. For this, you will have
to give default value.
Use force unwrap (!) symbol, next to variable
In your case, this would work just fine
return "first \(myVariable!)"
var a = 2
var b = "Hello W"
print("\(a) " + b)
will print 2 Hello W
Here is documentation about String and characters
var variableString = "Horse"
variableString += " and carriage"
// variableString is now "Horse and carriage"
Is there an easy way to split a string like this:
M34a79 or M2ab943 or M4c4
into
M,34,a,79 or M,2,ab,943 or M,4,c,4
without any separators?
You can do it with a pair of gsub calls:
x = "M34a79 or M2ab943 or M4c4"
x, _ = x:gsub( "(%d)(%a)", "%1,%2" )
x, _ = x:gsub( "(%a)(%d)", "%1,%2" )
print( x )
M,34,a,79 or M,2,ab,943 or M,4,c,4
Might not work in all cases, but does work on your example.
If you don’t mind using the LPEG
library:
local lpeg = require "lpeg"
local C, Ct, P, R = lpeg.C, lpeg.Ct, lpeg.P, lpeg.R
local lpegmatch = lpeg.match
local extract
do
local digit = R"09"
local lower = R"az"
local comma = P","
local space = P" "
local schema = Ct( C(P"M")
* (digit^1 / tonumber)
* C(lower^1)
* (digit^1 / tonumber))
local extractor = Ct((schema + 1)^0)
extract = function (str)
return lpegmatch (extractor, str)
end
end
This will match all sequences of characters of the input
that consist of (in that order)
the letter M,
a sequence of 1 or more decimal digits,
a sequence of 1 or more lowercase characters, and
another sequence of 1 or more decimal digits.
When processing the input each match is put in a subtable,
the digits are converted to Lua numbers on the fly.
Since the question requested it, the leading M is included
in the entries.
Usage example:
local data = extract [[M34a79 or M2ab943 or M4c4]]
for i = 1, #data do
local elm = data[i]
print (string.format ("[%d] = { [1] = %q, [2] = %d, [3] = %q, [4] = %d },",
i, table.unpack (elm)))
end
Output:
[1] = { [1] = "M", [2] = 34, [3] = "a", [4] = 79 },
[2] = { [1] = "M", [2] = 2, [3] = "ab", [4] = 943 },
[3] = { [1] = "M", [2] = 4, [3] = "c", [4] = 4 },
Solution:
http://www.coronalabs.com/blog/2013/04/16/lua-string-magic/
function string:split( inSplitPattern, outResults )
...
end
function val(x)
x = x:gsub( "(%d)(%a)", "%1,%2" )
x = x:gsub( "(%a)(%d)", "%1,%2" )
Table = string.split(x,",")
for i = 1, #Table do
print( Table[i] )
end
end
val("M3a5")
returns M 3 a 5
I have many formula strings similar to this:
str <- "( (( A ) * J ) - (( J ) * G ) ) / Z "
There are many parentheses which don't need to be there, (A*J - J*G)/Z is sufficient. Is there a function or package in R that can take care of this?
I tried functions for R expressions and as well as.formula but did not find what I need.
We can use R parser to do the job. The trick is that R knows when parentheses are needed based on the parse tree, so we can simply remove them from the tree:
See this:
simplify <- function(e)
{
if( mode(e) %in% c("name","numeric") ) return(e)
op <- as.character(e[[1]])
if( op == "(" ) return(simplify(e[[2]]))
if( op %in% c("+","-","*","/","^") ) return(call(op, simplify(e[[2]]), simplify(e[[3]])))
}
simplifytext <- function(s) deparse(simplify(parse(text=s)[[1]]))
Inputs:
str <- "( (( A ) * J ) - (( J ) * G ) ) / Z "
str2 <- gsub("-", "/", gsub("*", "+", str, fixed=TRUE))
Results:
> str2
[1] "( (( A ) + J ) / (( J ) + G ) ) / Z "
> simplifytext(str)
[1] "(A * J - J * G)/Z"
> simplifytext(str2)
[1] "(A + J)/(J + G)/Z"
Here are a couple of approaches:
R parsing
rmParen <- function(e) {
if (length(e) > 1) {
if (identical(e[[1]], as.symbol("("))) e <- e[[2]]
if (length(e) > 1) for (i in 1:length(e)) e[[i]] <- Recall(e[[i]])
}
e
}
s <- "( (( A ) * J ) - (( J ) * G ) ) / Z "
rmParen(parse(text = s)[[1]])
The last line returns:
(A * J - J * G)/Z
This works in all cases I tried but you might want to test it out a bit more.
If you want a character string as the return value then use deparse as in deparse(rmParen(parse(text = s)[[1]])). Note that deparse has a width.cutoff argument which is set to 60 by default but can be set to be larger if the actual expressions exceed that length.
Ryacas
library(Ryacas)
s <- "( (( A ) * J ) - (( J ) * G ) ) / Z "
Simplify(s)
The last line returns:
expression((A - G) * J/Z)
Note that its actually the print method that invokes the computation so if you want to save it then try yacas(Simplify(s))$text or as.character(yacas(Simplify(s))) .
ADDED: Ryacas solution.
Hey guys so this is a strange little error I'm getting and I'm not understand why it's giving it to me.
It says Parse Error in input 'appendString' yet I see nothing wrong with it...
I call it from an if,then else statement as follows:
createShow currentIndex (Grid {delta = d, middle = (x,y), points = g}) dir counter =
if currentIndex ==0 || dir == 2
then (appendString d (x,y) g currentIndex) ++ (createShow currentIndex+1 (Grid {delta = d, middle = (x,y), points = g}) 2 (counter+1))
else if counter == (2*d+1)
then (appendString d (x,y) g currentIndex) ++ (appendX x)
else if dir == 1
then (appendString d (x,y) g currentIndex) ++ (createShow currentIndex-1 (Grid {delta = d, middle = (x,y), points = g}) 1 (counter+1))
where createShow returns a string and so does appendString
appendString gives the error in the constructor:
appendString d (x,y) g currentIndex =
(if currentIndex == y
then "y "
else
" " ) ++ (show currentIndex) ++(rowFunction g x d 0 (x+d) 1)++ "\n"
do you see where I could have gone wrong with it?
Edit: Added entire area
Haskell if's are not like other if's in say Java or python. The biggest difference is that they are expressions unlike java or python where they are statements.
They are much closer to the condition ? res1 : res2 from C.
The correct way to write nested if's is like this:
if condition
then foo
else if condition2
then bar
else ...
You'll notice that this is horribly ugly.
That's why haskell has guards:
foo args | condition = foo
| condition2= bar
| otherwise = meh
Here we declare a function foo and if condition is true then we execute foo otherwise we proceed to condition2 and otherwise is always true. For you
createShow currentIndex (Grid {delta = d, middle = (x,y), points = g}) dir counter
| currentIndex == 0 || dir == 2 = appendString d ....
| counter == (2 * d + 1) = appendString d ....
| dir == 1 = appendString d ....
which looks much more readable.
Here's a refactoring::
createShow currentIndex grid#(Grid {delta = d, middle = (x,y), points = g}) dir counter =
prefix ++ show currentIndex ++ row ++ "\n" ++ nextLine
where
prefix = if currentIndex == y then "y " else " "
row = rowFunction g x d 0 (x+d) 1
nextLine | currentIndex == 0 || dir == 2 = createShow (currentIndex+1) grid 2 (counter+1)
nextLine | counter == (2*d+1) = appendX x
nextLine | dir == 1 = createShow (currentIndex-1) grid 1 (counter+1)
appendX x = ...
Things to notice:
Using a where clause often lets you avoid repeating parameters
The common call to appendString has been factored out, and moved to the top, and then in-lined, since it is only called once.
Use of guards in nextLine to handle a cascaded if more clearly.
The guards and form of nextLine make it clear it isn't a total function. What happens when it falls off the end?
The use of grid# to name a pattern. This way you don't need to "reconstruct" the Grid value when making the recursive calls.
One can go further. Noticing that Grid {...} and dir never change throughout the function suggests factoring those out:
createShow currentIndex (Grid {delta = d, middle = (x,y), points = g}) dir counter =
line currentIndex counter
where
line currentIndex counter =
prefix ++ show currentIndex ++ row ++ "\n" ++ nextLine currentIndex counter
prefix = if currentIndex == y then "y " else " "
row = rowFunction g x d 0 (x+d) 1
nextLine currentIndex counter
| currentIndex == 0 || dir == 2 = line (currentIndex+1) (counter+1)
| counter == (2*d+1) = appendX x
| dir == 1 = line (currentIndex-1) (counter+1)
appendX x = ...
Here, line plays the part of "carrying" around the only values that differ as the function recurses. It would be a common idiom to place those arguments at the end of what createShow takes, and thus even factor them out:
createShow :: Grid -> Int -> Int -> Int -> String
createShow (Grid {delta = d, middle = (x,y), points = g}) dir = line
where
line currentIndex counter =
prefix ++ show currentIndex ++ row ++ "\n" ++ nextLine currentIndex counter
prefix = if currentIndex == y then "y " else " "
row = rowFunction g x d 0 (x+d) 1
nextLine currentIndex counter
| currentIndex == 0 || dir == 2 = line (currentIndex+1) (counter+1)
| counter == (2*d+1) = appendX x
| dir == 1 = line (currentIndex-1) (counter+1)
appendX x = ...