When I use the package 'progress' like so:
library(progress)
pb <- progress_bar$new(total = 100)
for(i in 1:10){
pb$tick()
}
I get a repeated output like so:
[==>----------------------------------------------------------------------------------------------] 3%[===>---------------------------------------------------------------------------------------------] 4%[====>--------------------------------------------------------------------------------------------] 5%[=====>-------------------------------------------------------------------------------------------] 6%[======>------------------------------------------------------------------------------------------] 7%[=======>-----------------------------------------------------------------------------------------] 8%[========>----------------------------------------------------------------------------------------] 9%[=========>---------------------------------------------------------------------------------------] 10%[==========>--------------------------------------------------------------------------------------] 11%[===========>-------------------------------------------------------------------------------------] 12%...
I would prefer it to delete the old bar after the new one is called. Is there a setting in R studio that I need to change to use that? I'm using a mac if that matters.
Related
I'm using the R package gWidgets.
I want to add a point on a picture (.jpg).
My code is:
require(jpeg)
require(gWidgets)
options(guiToolkit="RGtk2")
w <- gwindow("test")
gimage("yourpath.jpg",dirname="", container = w,toolkit=guiToolkit("RGtk2"))
da <- w#widget#widget
callbackID <- gSignalConnect(da,"button-release-event", function
(w,e,...) {
# allocation <- w$GetAllocation()
addHandlerClicked(da, handler = function(h,...) {
})
xclick <- e$GetX()
yclick <- e$GetY()
print(xclick)
print(yclick)
points(xclick, yclick)
pressed <<- FALSE
return(TRUE)
})
warning:
plot.new has not been called yet
Could someone help me?
Thanks
warning:
plot.new has not been called yet
Well, that's true isn't it ? In the code above, nowhere is a plot created (using plot() or similar).
Also in your code I cannot see where you create "yourpath.jpg" -- presumably, it is the plot you're trying to draw.
In fact you are trying, it seems, to mix an image and a plot. If you want to include an R plot, what you need is a ggraphics.
Something like that should do what you seem to try and achieve:
library(gWidgets2)
options(guiToolkit="RGtk2")
# Generate some data
xdata<-rnorm(n=5)
ydata<-rnorm(n=5)
gTest<-function(){
#Plotting function
plotf<-function(...){
plot(xdata,ydata)
}
# Function to add points
.addPoint<-function(h,...){
points(h$x,h$y,col="red")
}
win <- gwindow("Test")
theplot<-ggraphics(cont=win)
addHandlerClicked(theplot,handler=.addPoint)
Sys.sleep(0.1) # Prevents error with "figure margins too large"
plotf()
}
gTest()
Note that as written, new points are plotted (with points()) but not actually saved. You would need to do, for instance
.addPoint<-function(h,...){
points(h$x,h$y,col="red")
xdata<<-c(xdata,h$x)
ydata<<-c(ydata,h$y)
}
Here with a global assignment, that may or may not be what you need; mostly <<- and global variables are regarded as bad practice, but sometimes it's good enough!
My problem is very basic (I am a beginner user in R). I am trying to collect the value selected from a gradio widget (gwidgets2 package for R).
I am using a similar script as this simplified one :
U=vector(mode="character")
DF=function() {
Win=gbasicdialog(handler=function(h,...) {
T=svalue(A)
print(T)
# I can print but not assign the value using : assign (U,T, .GlobalEnv)
})
A<-gradio(c("1","2","3"), selected=1,container=Win,)
out <- visible(Win)
}
DF()
Using this script, I am able to print the value selected in the gradio widget, but when I try to assign this value to another variable passed to the global environment, I get an error.
It is strange as this structure of script works fine to collect values from other widgets (like gtable). What am I doing wrong ?
Thanks for the help.
I am not sure what goes wrong, but was able to run your code with a small change:
DF <- function() {
Win <- gbasicdialog(
handler = function(h, ...) {
.GlobalEnv$varT = svalue(A)
print(varT)
}
)
A <- gradio(c("1", "2", "3"), selected = 1, container = Win)
out <- visible(Win)
}
DF()
A small advice: avoid using the single letters T or F, as in your code T might be interpreted as TRUE and not object T.
I'm struggling to assign a namespace variable inside of a function. Consider this example using the CRAN package "qcc": qcc() generates a plot, but
the display options of that plot are controlled by qcc.options().
When working in global, everything is fine:
library(qcc)
qcc.options(bg.margin="red") # sets margin background colour, i.e.
# qcc:::.qcc.options$bg.margin is "red"
qcc(rnorm(100), type = "xbar.one") # generates a plot with red margin
But when working in the local environment of a function, qcc and qcc.options seem to use the namespace differently:
foo <- function(x){
qcc.options(bg.margin=x)
qcc(rnorm(100), type = "xbar.one")
}
foo("green") # generates a default plot with grey margins
Here is an ugly hack:
foo <- function(x){
old.qcc.options <- get(".qcc.options", asNamespace("qcc"))
assign(".qcc.options", qcc.options(bg.margin=x), asNamespace("qcc"))
res <- qcc(rnorm(100), type = "xbar.one")
assign(".qcc.options", old.qcc.options, asNamespace("qcc"))
invisible(res)
}
foo("green")
Of course, the scoping issues would be better solved by changing qcc.options. You should contact the package maintainer about that.
This is because of where qcc.options stores its .qcc.options variable. Working in global, this is qcc:::.qcc.options, but when you're inside a function, it is storing it in a local variable just called .qcc.options, thus when you try to use plot.qcc (called by qcc) it retrieves options from the global (non-exported) qcc:::.qcc.options rather than the local .qcc.options.
Here's a function that shows what's happening with the options:
bar <- function(x){
pre <- qcc:::.qcc.options
pre.marg <- qcc.options("bg.margin")
qcc.options(bg.margin=x)
post1 <- qcc:::.qcc.options
post2 <- .qcc.options
post.marg <- qcc.options("bg.margin")
qcc(rnorm(100), type = "xbar.one")
list(pre,post1,post2,pre.marg,post.marg)
}
bar('green')
If you look at the results, you'll see that qcc.options creates the local variable and changes its value of bg.margin to "green" but this isn't the object that's subsequently referenced by plot.qcc.
Seems like you should request some code modifications from the package maintainer because this is probably not the best setup.
EDIT: A workaround is to use assignInNamespace to use the local variable to overwrite the global one. (Obviously, this then changes the parameter globally and would affect all subsequent plots unless the parameter is updated.)
foo <- function(x){
qcc.options(bg.margin=x)
assignInNamespace('.qcc.options',.qcc.options,ns='qcc')
qcc(rnorm(100), type = "xbar.one")
}
foo('green')
I created a function which produces a matrix as a result, but I can't figure out how to make the output of this function usable outside of the function environment, so that I could for instance save it in csv file.
My code for function is the following:
created function which takes url's from specific site and returns page title:
getTitle <- function(url) {
webpage <- readLines(url)
first.row <- webpage[1]
start <- regexpr("<title>", first.row)
end <- regexpr("</title>", first.row)
title <- substr(first.row,start+7,end-1)
return(title)
}
created function which takes vector of urls and returns n*2 matrix with urls and page titles:
getTitles <- function(pages) {
my.matrix <- matrix(NA, ncol=2, nrow=nrow(pages))
for (i in seq_along(1:nrow(pages))) {
my.matrix[i,1] <- as.character(pages[i,])
my.matrix[i,2] <- getTitle(as.character(pages[i,])) }
return(my.matrix)
print(my.matrix)}
After running this functions on a sample file from here http://goo.gl/D9lLZ which I import with read.csv function and name "mypages" I get the following output:
getTitles(mypages)
[,1] [,2]
[1,] "http://support.google.com/adwords/answer/1704395" "Create your first ad campaign - AdWords Help"
[2,] "http://support.google.com/adwords/answer/1704424" "How costs are calculated in AdWords - AdWords Help"
[3,] "http://support.google.com/adwords/answer/2375470" "Organizing your account for success - AdWords Help"
This is exactly what I need, but I'd love to be able to export this output to csv file or reuse for further manipulations. However, when I try to print(my.matrix), I am getting an error saying "Error: object 'my.matrix' not found"
I feel like it's quite basic gap in my knowledge, but have not been working with R for a while and could not solve that.
Thanks!
Sergey
That's easy: use <<- for assignment to a global.
But then again, global assignment is evil and not functional. Maybe you'd rather return
a list with several results from your function? Looking at your code, it seems that your second function may confuse the return and print. Make sure you return the correct data structure.
A little about functional programming. First of all, when you define your function:
getTitles <- function(pages) {
[...]
return(my.matrix)
print(my.matrix)
}
know that when the function is called it will never reach the print statement. Instead, it will exit right before, with return. So you can remove that print statement, it is useless.
Now the more important stuff. Inside your function, you define and return my.matrix. The object only exists within the scope of the function: as the function exits, what is returned is an unnamed object (and my.matrix is lost.)
In your session, when you call
getTitles(mypages)
the result is printed because you did not assign it. Instead, you should do:
out.matrix <- getTitles(mypages)
Now the result won't be printed but you can definitely do so by typing print(out.matrix) or just out.matrix on a single line. And because you have stored the result in an object, you can now reuse it for further manipulations.
If it help you grasp the concept, this is all the same as calling the c() function from the command line:
c(1, 5, 2) # will return and print a vector
x <- c(1, 5, 2) # will return and assign a vector (not printed.)
Bonus: Really, I don't think you need to define getTitles, but you can use one of the *apply functions. I would try this:
url <- as.character(mypages)
title <- sapply(url, getTitle)
report <- data.frame(url, title)
write.csv(report, file = "report.csv", row.names = FALSE)
Can't you just use <<- to assign it the object to the workspace? The following code works for me and saves the amort_value object.
amortization <- function(cost, downpayment, interest, term) {
amort_value <<- (cost)*(1-downpayment/100)*(interest/1200)*((1+interest/1200)^(term*12))/((1+interest/1200)^(term*12)-1)
sprintf("$%.2f", amort_value)
}
amortization(445000,20,3,15)
amort_value
At the end of the function, you can return the result.
First define the function:
getRangeOf <- function (v) {
numRange <- max(v) - min(v)
return(numRange)
}
Then call it and assign the output to a variable:
scores <- c(60, 65, 70, 92, 99)
scoreRange <- getRangeOf(scores)
From here on use scoreRange in the environment. Any variables or nested functions within your defined function is not accessible to the outside, unless of course, you use <<- to assign a global variable. So in this example, you can't see what numRange is from the outside unless you make it global.
Usually, try to avoid global variables at an early stage. Variables are "encapsulated" so we know which one is used within the current context ("environment"). Global variables are harder to tame.
How do you create your status line at the bottom of your window? An inactive entry does not look very nice. What other options are there?
Is possible to integrate a progress bar which is visible only on demand?
(I am using tk and ttk from within R.)
EDIT: Now here is my second version, which works fine for me, but I would like to display the whole status bar on demand only (similar to what the status bar in the Chrome browser does). How can I do that? Calling tklower(f) does not help...
library(tcltk)
library(tcltk2)
tkdestroy(root)
root <- tktoplevel()
status <- tclVar("")
progress <- tclVar("0")
b <- tk2button(root, text="fake doing something!")
tkpack(b, padx=40, pady=10)
o <- tk2checkbutton(root, text="show progress", variable=progress)
tkpack(o, pady=10)
f <- tk2frame(root, relief="sunken")
l <- tk2label(f, textvariable=status)
tkpack(l, side="left", pady=2, padx=5, expand=0, fill="x")
tkpack(f, side="left", expand=1, fill="x", anchor="s")
sg <- ttksizegrip(root)
tkpack(sg, side="left", expand=0, anchor="se")
doit <- function() {
tclvalue(status) <- "working (hard) ..."
tcl("update")
do.pb <- tclvalue(progress)=="1"
if(do.pb) {
pb <- tk2progress(f, length=60, mode="determinate")
tkpack(pb, side="right", expand=0, padx=3, pady=2)
tkconfigure(pb, maximum=100, value=0)
}
for(i in 1:100) {
if(do.pb) {
tkconfigure(pb, value=i)
tcl("update")
}
Sys.sleep(0.03)
}
if(do.pb) tkdestroy(pb)
tclvalue(status) <- "Ready."
}
tkconfigure(b, command=doit)
tclvalue(status) <- "Ready."
I use a ttk::frame widget. In that I'll place one or more ttk::label widgets, and a ttk::sizegrip widget on the far right.
As for the progress bar -- just add it as usual. If you use grid, you can use grid remove to remove it from the statusbar but grid will remember its settings so you can add it right back. Or, you can user lower and raise to remove it from view and bring it back again.
Your question about the sizegrip widget is unclear. What about it doesn't work for you on windows?
By status line do you mean like the status bar you find at the bottom of most browser windows? If so, I usually use a label with its textvariable linked to a variable containing the status string.