Is there a way to extract current value from a slider control in manipulate package? For example:
library(manipulate)
xx <- seq(-pi, pi, pi/20)
manipulate(
plot(xx, sin(par.a*xx)),
par.a = slider(-3, 3, step=0.01, initial = 1))
After playing with the slider I would like to get the value of par.a for further calculations without having to look at the control and write it by hand each time.
Figured it out myself.
It is possible to do with global variables
manipulate(
{plot(xx, sin(par.a*xx))
a <<- par.a},
par.a = slider(-3, 3, step=0.01, initial = 1))
Maybe it will be of assistance to somebody.
Related
I am trying to turn off the display of plot in R.
I read Disable GUI, graphics devices in R but the only solution given is to write the plot to a file.
What if I don't want to pollute the workspace and what if I don't have write permission ?
I tried options(device=NULL) but it didn't work.
The context is the package NbClust : I want what NbClust() returns but I do not want to display the plot it does.
Thanks in advance !
edit : Here is a reproducible example using data from the rattle package :)
data(wine, package="rattle")
df <- scale (wine[-1])
library(NbClust)
# This produces a graph output which I don't want
nc <- NbClust(df, min.nc=2, max.nc=15, method="kmeans")
# This is the plot I want ;)
barplot(table(nc$Best.n[1,]),
xlab="Numer of Clusters", ylab="Number of Criteria",
main="Number of Clusters Chosen by 26 Criteria")
You can wrap the call in
pdf(file = NULL)
and
dev.off()
This sends all the output to a null file which effectively hides it.
Luckily it seems that NbClust is one giant messy function with some other functions in it and lots of icky looking code. The plotting is done in one of two places.
Create a copy of NbClust:
> MyNbClust = NbClust
and then edit this function. Change the header to:
MyNbClust <-
function (data, diss = "NULL", distance = "euclidean", min.nc = 2,
max.nc = 15, method = "ward", index = "all", alphaBeale = 0.1, plotetc=FALSE)
{
and then wrap the plotting code in if blocks. Around line 1588:
if(plotetc){
par(mfrow = c(1, 2))
[etc]
cat(paste(...
}
and similarly around line 1610. Save. Now use:
nc = MyNbClust(...etc....)
and you see no plots unless you add plotetc=TRUE.
Then ask the devs to include your patch.
I'm fairly new to R-programming and have been struggling to understand how certain objects seem to pass variables to functions, but don't seem to return these variables overtly. Have a look at this example:
install.packages("cluster")
library(cluster)
x <- rbind(cbind(rnorm(10, 0, 0.5), rnorm(10, 0, 0.5)),
cbind(rnorm(15, 5, 0.5), rnorm(15, 5, 0.5)),
cbind(rnorm( 3,3.2,0.5), rnorm( 3,3.2,0.5)))
fannyx <- cluster::fanny(x, 2)
p <- cluster::clusplot(fannyx)
When examining the plot, the following information is provided:
These two components explain 100 % of the point variability
I simply don't understand where how this information is passed! The variability explained is not returned by the fannyx-object.
I've encountered this issue before when other functions have provided more information by summary() than by using print().
How can this be explained?
If we expand the clusplot function
cluster:::clusplot.default
We can see the line of code:
sub = paste("These two components explain",
round(100 * var.dec, digits = 2), "% of the point variability.")
So in this case this particular metric is calculated internally within the function, and then added to the plot.
Edit:
And we can see that cluster:::mkCheckX returns var.dec, which is called in clusplot
I'm trying to write a function that takes a few lines of code and allows me to input a single variable. I've got the code below that creates an object using the Surv function (Survival package). The second line takes the variable in question, in this case a column listed as Variable_X, and outputs data that can then be visualized using ggsurvplot. The output is a Kaplan-Meier survival curve. What I'd like to do is have a function such that i can type f(Variable_X) and have the output KM curve visualized for whichever column I choose from the data. I want f(y) to output the KM as if I had put y where the ~Variable_X currently is. I'm new to R and very new to how functions work, I've tried the below code but it obviously doesn't work. I'm working through datacamp and reading posts but I'm having a hard time with it, appreciate any help.
surv_object <- Surv(time = KMeier_DF$Followup_Duration, event = KMeier_DF$Death_Indicator)
fitX <- survfit(surv_object ~ Variable_X, data = KMeier_DF)
ggsurvplot(fitX, data = KMeier_DF, pval = TRUE)
f<- function(x) {
dat<-read.csv("T:/datafile.csv")
KMeier_DF < - dat
surv_object <- Surv(time = KMeier_DF$Followup_Duration, event =
KMeier_DF$Death_Indicator)
fitX<-survfit(surv_object ~ x, data = KMeier_DF)
PlotX<- ggsurvplot(fitX, data = KMeier_DF, pval = TRUE)
return(PlotX)
}
The crux of the problem you have is actually a tough stumbling block to figure out initially: how to pass variable or dataframe column names into a function. I created some example data. In the example below I supply a function four variables, one of which is your data. You can see two ways I call on the columns, using [[]], and [,], which you can think of as being equivalent to using $. Outside of functions, they are, but not inside. The print functions are there to just show you the data along the way. If those objects exist in your global environment, remove them one by one, rm(surv_object), or clear them all rm(list = ls()).
duration <- c(1, 3, 4, 3, 3, 4, 2)
di <- c(1, 1, 0, 0, 0, 0, 1)
color <- c(1, 1, 2, 2, 3, 3, 4)
KMdf <- data.frame(duration, di, color)
testfun <- function(df, varb1, varb2, varb3) {
surv_object <- Surv(time = df[[varb1]], event = df[ , varb2])
print(surv_object)
fitX <- survfit(surv_object ~ df[[varb3]], data = df)
print(fitX)
# plotx <- ggsurvplot(fitX, data = df, pval = TRUE) # this gives an error that surv_object is not found
# return(plotx)
}
testfun(KMdf, "duration", "di", "color") # notice the use of quotes here, if not you'll get an error about object not found.
And even better, you have an even tougher stumbling block: how r handles variables and where it looks for them. From what I can tell, you're running into that because there is possibly a bug in ggsurvplot and looking at the global environment for variables, and not inside the function. They closed the issue, but as far as I can tell, it's still there. When you try to run the ggsurvplot line, you'll get an error that you would get if you didn't supply a variable:
Error in eval(inp, data, env) : object 'surv_object' not found.
Hopefully that helps. I'd submit a bug report if I were you.
edit
I was hoping this solution would help, but it doesn't.
testfun <- function(df, varb1, varb2, varb3) {
surv_object <- Surv(time = df[[varb1]], event = df[,varb2])
print(surv_object)
fitX <- survfit(surv_object ~ df[[varb3]], data = df)
print(fitX)
attr(fitX[['strata']], "names") <- c("color = 1", "color = 2", "color = 3", "color = 4")
plotx <- ggsurvplot(fitX, data = df, pval = TRUE) # this gives an error that surv_object is not found
return(plotx)
}
Error in eval(inp, data, env) : object 'surv_object' not found
This is homework, right?
First, you need to try to run the code before you provide it as an example. Your example has several fatal errors. ggsurvplot() needs either a library call to survminer or to be summoned as follows: survminer::ggsurvplot().
You have defined a function f, but you never used it. In the function definition, you have a wayward space < -. It never would have worked.
I suggest you start by defining a function that calculates the sum of two numbers, or concatenates two strings. Start here or here. Then, you can return to the Kaplan-Meier stuff.
Second, in another class or two, you will need to know the three parts of a function. You will need to understand the scope of a function. You might as well dig into the basics before you start copy-and-pasting.
Third, before you post another question, please read How to make a great R reproducible example?.
Best of luck.
We can plot candle stick chart using chart series function chartSeries(Cl(PSEC)) I have created some custom values (I1,I2 and I3) which I want to plot together(overlay) outside the candle stick pattern. I have used addTA() for this purpose
chartSeries(Cl(PSEC)), TA="addTA(I1,col=2);addTA(I2,col=3);addTA(I3,col=4)")
The problem is that it plots four plots for Cl(PSEC),I1,I2 and I3 separately instead of two plots which I want Cl(PSEC) and (I1,I2,I3)
EDITED
For clarity I am giving a sample code with I1, I2 and I3 variable created for this purpose
library(quantmod)
PSEC=getSymbols("PSEC",auto.assign=F)
price=Cl(PSEC)
I1=SMA(price,3)
I2=SMA(price,10)
I3=SMA(price,15)
chartSeries(price, TA="addTA(I1,col=2);addTA(I2,col=3);addTA(I3,col=4)")
Here is an option which preserves largely your original code.
You can obtain the desired result using the option on=2 for each TA after the first:
library(quantmod)
getSymbols("PSEC")
price <- Cl(PSEC)
I1 <- SMA(price,3)
I2 <- SMA(price,10)
I3 <- SMA(price,15)
chartSeries(price, TA=list("addTA(I1, col=2)", "addTA(I2, col=4, on=2)",
"addTA(I3, col=5, on=2)"), subset = "last 6 months")
If you want to overlay the price and the SMAs in one chart, you can use the option on=1 for each TA.
Thanks to #hvollmeier who made me realize with his answer that I had misunderstood your question in the previous version of my answer.
PS: Note that several options are described in ?addSMA(), including with.col which can be used to select a specific column of the time series (Cl is the default column).
If I understand you correctly you want the 3 SMAs in a SUBPLOT and NOT in your main chart window.You can do the following using newTA.
Using your data:
PSEC=getSymbols("PSEC",auto.assign=F)
price=Cl(PSEC)
Now plotting a 10,30,50 day SMA in a window below the main window:
chartSeries(price['2016'])
newSMA <- newTA(SMA, Cl, on=NA)
newSMA(10)
newSMA(30,on=2)
newSMA(50,on=2)
The key is the argument on. Use on = NA in defining your new TA function, because the default value foron is 1, which is the main window. on = NA plots in a new window. Then plot the remaining SMAs to the same window as the first SMA. Style the colours etc.to your liking :-).
You may want to consider solving this task using plotting with the newer quantmod charts in the quantmod package (chart_Series as opposed to chartSeries).
Pros:
-The plots look cleaner and better (?)
-have more flexibility via editing the pars and themes options to chart_Series (see other examples here on SO for the basics of things you can do with pars and themes)
Cons:
-Not well documented.
PSEC=getSymbols("PSEC",auto.assign=F)
price=Cl(PSEC)
chart_Series(price, subset = '2016')
add_TA(SMA(price, 10))
add_TA(SMA(price, 30), on = 2, col = "green")
add_TA(SMA(price, 50), on = 2, col = "red")
# Make plot all at once (this approach is useful in shiny applications):
print(chart_Series(price, subset = '2016', TA = 'add_TA(SMA(price, 10), yaxis = list(0, 10));
add_TA(SMA(price, 30), on = 2, col = "purple"); add_TA(SMA(price, 50), on = 2, col = "red")'))
I'm not sure how to pose this question with the right lingo and the related questions weren't about the same thing. I wanted to plot a function and noticed that R wasn't udpating the plot with my change in a coefficient.
a <- 2
x <- seq(-1, 1, by=0.1)
y <- 1/(1+exp(-a*x))
plot(x,y)
a <- 4
plot(x,y) # no change
y <- 1/(1+exp(-a*x)) # redefine function
plot(x,y) # now it updates
Just in case I didn't know what I was doing, I followed the syntax on this R basic plotting tutorial. The only difference was the use of = instead of <- for assignment of y = 1/(1+exp(-a*x)). The result was the same.
I've actually never just plotted a function with R, so this was the first time I experienced this. It makes me wonder if I've seen bad results in other areas if re-defined variables aren't propagated to functions or objects initialized with the initial value.
1) Am I doing something wrong and there is a way to have variables sort of dynamically assigned so that functions take into account the current value vs. the value it had when they were created?
2) If not, is there a common way R programmers work around this when tweaking variable assignments and making sure everything else is properly updated?
You are not, in fact, plotting a function. Instead, you are plotting two vectors. Since you haven't updated the values of the vector before calling the next plot, you get two identical plots.
To plot a function directly, you need to use the curve() function:
f <- function(x, a)1/(1+exp(-a*x))
Plot:
curve(f(x, 1), -1, 1, 100)
curve(f(x, 4), -1, 1, 100)
R is not Excel, or MathCAD, or any other application that might lead you to believe that changing an object's value might update other vectors that might have have used that value at some time in the past. When you did this
a <- 4
plot(x,y) # no change
There was no change in 'x' or 'y'.
Try this:
curve( 1/(1+exp(-a*x)) )
a <- 10
curve( 1/(1+exp(-a*x)) )