Rstudio-Empty ggplot in a function - r
I have a function called plot.medals2 that has an input that includes a variable named start and a variable named finish. Both variables are numbers and I want that in the event that start is bigger than finish the function will stop running and draw an empty ggplot like the one i attached here.
This is the part of the code that is supposed to take care of that:
plot.medals2 <- function(code,start,finish,medalsvec) {
if(start>finish) { #years not make sense return empty drawing
ggplot() + ylab('medals won') + xlab('year') +
ggtitle(paste('Medals by',"",countries.df[countries.df$country_id==code,]$country_name,',',"",finish,'-',start))
return()
}
}
this is what I get when I try to run it:
plot.medals2('USA',1933,1456,c('GOLD'))
NULL
I tried to use the breakpoint option to see what is going on and it seems the
function does enter the if statement meaning it recognizes that the variable start is larger than finish but then for some reason it skips the next 2 rows and does not plot anything. Now when I use this
ggplot() + ylab('medals won') + xlab('year') +
ggtitle(paste('Medals by',"",countries.df[countries.df$country_id==code,]$country_name,',',"",finish,'-',start))
outside of a function it works but not when its a part of a function.
Related
Can the R prompt be a time?
?option says this. ‘prompt’: a non-empty string to be used for R's prompt; should usually end in a blank (‘" "’). Is it possible to make the prompt to include some dynamic stuffs, e.g., the current time?
You should take a look at the taskCallbackManager (https://developer.r-project.org/TaskHandlers.pdf). With prompt you can call the current time and save it. Example: options("prompt"=format(Sys.time(), "%H:%M:%S> ")). But this is fixed with the time it was set. The doc for the function taskCallbackManager has the rest: R> h <- taskCallbackManager() R> h$add(function(expr, value, ok, visible) { + options("prompt"=format(Sys.time(), "%H:%M:%S> ")); + return(TRUE) }, + name = "simpleHandler") [1] "simpleHandler" 07:25:42> a <- 2 07:25:48> This registers a callback that gets evaluated after each command completes.
Using a function to change a variable in R
I am trying to change a variable in a function but even tho the function is producing the right values, when I go to use them in the next sections, R is still using the initial values. I created a function to update my variables NetN and NetC: Reproduction=function(NetN,NetC,cnrep=20){ if(NetC/NetN<=cnrep) { DeltaC=NetC*p; DeltaN=DeltaC/cnrep; Crep=Crep+DeltaC; Nrep=Nrep+DeltaN; Brep=(Nrep*14+Crep*12)*2/1e6; NetN=NetN-DeltaN; #/* Update N, C values */ NetC=NetC*(1-p) print ("'Using C to allocate'") } else { print("Using N to allocate"); DeltaN=NetN*p; DeltaC=DeltaN*cnrep; Nrep=Nrep+DeltaN; Crep=Crep+DeltaC; Brep=(Nrep*14+Crep*12)*2/1e6; NetN=NetN*(1-p); NetC=NetC-DeltaC; } } return(c(NetC=NetC,NetN=NetN,NewB=NewB,Crep=Crep,Nrep=Nrep,Brep=Brep))} When I use my function by say doing: Reproduction(NetN=1.07149,NetC=0.0922349,cnrep=20) I get the desired result printed out which includes: NetC=7.378792e-02 However, when I go to use NetC in the next section of my code, R is still using NetC=0.0922349. Can I make R update NetC without having to define a new variable?
In R, in general, functions shouldn't change things outside of the function. It's possible to do so using <<- or assign(), but this generally makes your function inflexible and very surprising. Instead, functions should return values (which yours does nicely), and if you want to keep those values, you explicitly use <- or = to assign them to objects outside of the function. They way your function is built now, you can do that like this: updates = Reproduction(NetN = 1.07149, NetC = 0.0922349, cnrep = 20) NetC = updates["NetC"] This way, you (a) still have all the other results of the function stored in updates, (b) if you wanted to run Reproduction() with a different set of inputs and compare the results, you can do that. (If NetC updated automatically, you could never see two different values), (c) You can potentially change variable names and still use the same function, (d) You can run the function to experiment/see what happens without saving/updating the values. If you generally want to keep NetN, NetC, and cnrep in sync, I would recommend keeping them together in a named vector or list, and rewriting your function to take that list as input and return that list as output. Something like this: params = list(NetN = 1.07149, NetC = 0.0922349, cnrep = 20) Reproduction=function(param_list){ NetN = param_list$NetN NetC = param_list$NetC cnrep = param_list$cnrep if(NetC/NetN <= cnrep) { DeltaC=NetC*p; DeltaN=DeltaC/cnrep; Crep=Crep+DeltaC; Nrep=Nrep+DeltaN; Brep=(Nrep*14+Crep*12)*2/1e6; NetN=NetN-DeltaN; #/* Update N, C values */ NetC=NetC*(1-p) print ("'Using C to allocate'") } else { print("Using N to allocate"); DeltaN=NetN*p; DeltaC=DeltaN*cnrep; Nrep=Nrep+DeltaN; Crep=Crep+DeltaC; Brep=(Nrep*14+Crep*12)*2/1e6; NetN=NetN*(1-p); NetC=NetC-DeltaC; } ## Removed extra } and ) ?? return(list(NetC=NetC, NetN=NetN, NewB=NewB, Crep=Crep, Nrep=Nrep, Brep=Brep)) } This way, you can use the single line params <- Reproduction(params) to update everything in your list. You can access individual items in the list with either params$Netc or params[["NetC"]].
Scilab - gui - many unknown variables error messages
Still trying to understand the logic of Scilab, I created a small calculation tool for a mechanical element. The main problem I have is finding the right order (or syntax) for the calculation code... I get a lot of "unknown variable" errors and I don't understand why? I tried to change the order of definitions for the functions, declare the variables as global, etc. but nothing seems to help. The code for the calculation is not long and also not complicated, but the gui was built using guibuilder, so the uicontrols definitions are probably much longer than they need to be. Could somebody help me make this code working, as I would learn and understand a lot by this example, althought it contains more than one "problem zones"? Here what I've done: G = 78500; table_titles = ["" "Wire diameter" "Wp" "Tau alwd" "M alwd" "Angle alwd"]; f=figure('figure_position',[910,163],'figure_size', [903,537],'auto_resize','on','background',[33],'figure_name','Graphic window number %d'); ////////// delmenu(f.figure_id,gettext('File')) delmenu(f.figure_id,gettext('?')) delmenu(f.figure_id,gettext('Tools')) toolbar(f.figure_id,'off') handles.dummy = 0; handles.sl_dwire=uicontrol(f,'unit','normalized','BackgroundColor', [-1,-1,-1],'Enable','on','FontAngle','normal','FontName','Tahoma', 'FontSize',[12],'FontUnits','points','FontWeight','normal', 'ForegroundColor',[-1,-1,-1],'HorizontalAlignment','left','ListboxTop', [],'Max',[12],'Min',[0],'Position', [0.0058208,0.77875,0.124375,0.06875],'Relief','default','SliderStep', [0.1,1],'Style','slider','String',"Wire diameter",'Value', [6],'VerticalAlignment','middle','Visible','on','Tag','sl_dwire', 'Callback','sl_dwire_callback(handles)') handles.ed_dwire=uicontrol(f,'unit','normalized','BackgroundColor', [-1,-1,-1],'Enable','off','FontAngle','normal','FontName','Tahoma', 'FontSize',[12],'FontUnits','points','FontWeight','normal', 'ForegroundColor',[-1,-1,-1],'HorizontalAlignment','left','ListboxTop', [],'Max',[1],'Min',[0], 'Position',[0.0058208,0.71875,0.124375,0.06875],'Relief', 'default','SliderStep',[0.01,0.1],'String',"wire diameter: " + msprintf('%2.1f',handles.sl_dwire.Value) + "mm",'Style','text', 'Value',[0],'VerticalAlignment','middle','Visible','on','Tag', 'ed_dwire','Callback','auto') handles.sl_wangle=uicontrol(f,'unit','normalized','BackgroundColor', [-1,-1,-1],'Enable','on','FontAngle','normal','FontName','Tahoma', 'FontSize',[12],'FontUnits','points','FontWeight','normal', 'ForegroundColor',[-1,-1,-1],'HorizontalAlignment','left', 'ListboxTop',[],'Max',[180],'Min',[5],'Position', [0.0090625,0.5191667,0.25625,0.0645833],'Relief','default', 'SliderStep',[0.1,1],'String','Working angle','Style','slider','Value', [50],'VerticalAlignment','middle','Visible','on','Tag','sl_wangle', 'Callback','sl_wangle_callback(handles)') handles.ed_wangle=uicontrol(f,'unit','normalized','BackgroundColor', [-1,-1,-1],'Enable','off','FontAngle','normal','FontName','Tahoma', 'FontSize',[12],'FontUnits','points','FontWeight','normal', 'ForegroundColor',[-1,-1,-1],'HorizontalAlignment','left', 'ListboxTop',[],'Max',[1],'Min',[0],'Position', [0.0090625,0.4591667,0.25625,0.0645833],'Relief','default', 'SliderStep',[0.01,0.1],'String',"Working angle: " + msprintf('%2.1f',handles.sl_wangle.Value) + "°",'Style','text', 'Value',[0],'VerticalAlignment','middle','Visible','on','Tag', 'ed_wangle','Callback','auto') handles.sl_activel=uicontrol(f,'unit','normalized', 'BackgroundColor',[-1,-1,-1],'Enable','on','FontAngle','normal', 'FontName','Tahoma','FontSize',[12],'FontUnits','points','FontWeight', 'normal','ForegroundColor',[-1,-1,-1],'HorizontalAlignment','left', 'ListboxTop',[],'Max',[1000],'Min',[10],'Position', [0.0090625,0.365,0.25625,0.0645833],'Relief','default', 'SliderStep',[0.1,1],'String','Active length' ,'Style','slider', 'Value',[10],'VerticalAlignment','middle','Visible','on','Tag', 'sl_activel','Callback','sl_activel_callback(handles)') handles.ed_activel=uicontrol(f,'unit','normalized', 'BackgroundColor',[-1,-1,-1],'Enable','off','FontAngle','normal', 'FontName','Tahoma','FontSize',[12],'FontUnits','points','FontWeight', 'normal','ForegroundColor',[-1,-1,-1],'HorizontalAlignment','left', 'ListboxTop',[],'Max',[1],'Min',[0],'Position', [0.0090625,0.305,0.25625,0.0645833],'Relief','default', 'SliderStep',[0.01,0.1],'String','Active length: ' + msprintf('%2.1f',handles.sl_activel.Value) + "mm",'Style','text','Value',[0],'VerticalAlignment','middle','Visible', 'on','Tag','ed_activel','Callback','auto') handles.ax_graph= newaxes();handles.ax_graph.margins = [ 0 0 0 0]; handles.ax_graph.axes_bounds = [0.4274266,0.0619266,0.3995485,0.5191743]; handles.tab_param=uicontrol(f,'unit','normalized','BackgroundColor', [-1,-1,-1],'Enable','on','FontAngle','normal','FontName', 'Tahoma','FontSize',[12],'FontUnits','points','FontWeight','normal', 'ForegroundColor',[-1,-1,-1],'HorizontalAlignment','left', 'ListboxTop',[],'Max',[1],'Min',[0], 'Position',[0.4308126,0.1690826,0.3950339,0.2178899],'Relief', 'default','SliderStep',[0.01,0.1],'String',string(table_param),'Style', 'table','Value',[0],'VerticalAlignment','middle','Visible', 'on','Tag','tab_param','Callback','tab_param_callback(handles)') handles.sl_sfactor=uicontrol(f,'unit','normalized', 'BackgroundColor',[-1,-1,-1],'Enable','on','FontAngle','normal', 'FontName','Tahoma','FontSize',[12],'FontUnits','points','FontWeight', 'normal','ForegroundColor',[-1,-1,-1],'HorizontalAlignment','left', 'ListboxTop',[],'Max',[1],'Min',[0], 'Position',[0.0058208,0.6525688,0.124375,0.06875],'Relief','default', 'SliderStep',[0.01,0.1],'String',"Safety factor",'Style', 'slider','Value',[0.58],'VerticalAlignment','middle','Visible','on', 'Tag','ed_sfactor','Callback','sl_sfactor_callback(handles)') handles.ed_sfactor=uicontrol(f,'unit','normalized', 'BackgroundColor',[-1,-1,-1],'Enable','off','FontAngle','normal', 'FontName','Tahoma','FontSize',[12],'FontUnits','points','FontWeight', 'normal','ForegroundColor',[-1,-1,-1],'HorizontalAlignment', 'left','ListboxTop',[],'Max',[1],'Min',[0],'Position', [0.0058208,0.5925688,0.124375,0.06875],'Relief','default', 'SliderStep',[0.01,0.1],'String',"Safety factor : " + msprintf('%2.1f',handles.sl_sfactor.Value),'Style', 'text','Value',[0.58],'VerticalAlignment','middle','Visible','on', 'Tag','ed_dwire','Callback','auto') handles.popm_wtype=uicontrol(f,'unit','normalized', 'BackgroundColor',[-1,-1,-1],'Enable','on','FontAngle','normal', 'FontName','Tahoma','FontSize',[12],'FontUnits','points','FontWeight', 'normal','ForegroundColor',[-1,-1,-1],'HorizontalAlignment','left', 'ListboxTop',[],'Max',[1],'Min',[0],'Position', [0.0058208,0.8618349,0.124375,0.0639450],'Relief','default', 'SliderStep',[0.01,0.1],'String',gettext("SL/DL|SM/DM|SH/DH"),'Style', 'popupmenu','Value',[2],'VerticalAlignment','middle','Visible','on', 'Tag','popm_wtype','Callback','popm_wtype_callback(handles)') ////////// // Callbacks are defined as below. Please do not delete the comments as it will be used in coming version ////////// function sl_sfactor_callback(handles) sf=handles.sl_sfactor.Value; handles.ed_sfactor.String="Safety factor: " + msprintf('%3.2f',sf); endfunction function sl_dwire_callback(handles) wd=handles.sl_dwire.Value; Wp = %pi*wd^3/16; Ip =%pi*wd^4/32; Kt = G*%pi*Ip/(180*L); Talwd = sf * calcform; Malwd = Wp * Talwd; alphaalwd = Malwd / Kt; x=0:0.1:alphaalwd*1.5; plot(x,Kt*x); handles.ed_dwire.String="Wire diameter: " + msprintf('%2.1f',wd) + "mm"; endfunction function popm_wtype_callback(handles) //Write your callback for popm_wtype here if selected == 1 then calcform =(1845 - 700*log10(wd)); elseif selected == 2 then calcform =(2105 - 780*log10(wd)); elseif selected == 3 then calcform = (2220 - 820*log10(wd)); end endfunction function sl_wangle_callback(handles) handles.ed_wangle.String="Working angle: " + msprintf('%2.1f',handles.sl_wangle.Value) + "°"; endfunction function sl_activel_callback(handles) //Write your callback for sl_activel here handles.ed_activel.String="Active length: " + msprintf('%2.1f',handles.sl_activel.Value) + "mm"; L=handles.sl_activel.Value; endfunction function tab_param_callback(handles) //Write your callback for tab_param here table_values = string([ wd Wp Talwd Malwd alphaalwd]); table_param = [table_titles; [table_values]]; endfunction I expect the code to dynamically update the graph and the parameters table according to the positions of input sliders and popup-menu. Again, it would be very helpful if somebody could help me get this code working, as I would get answers for a lot of my questions concerning programming with scilab. Thank you very much in advance!
First of all, your code is not directly executable, caused by the linebreaks. Please add ... after each line of a statement. This improves also the readability. As mentioned by #luispauloml, you try to use variables, which exist just inside of another function. For example you try to reach table_param, which is just alive in tab_param_callback(handles). To get rid of this, you have to define the output for the function: function [table_values, table_param] = tab_param_callback(handles) table_values = string([ wd Wp Talwd Malwd alphaalwd]); table_param = [table_titles; [table_values]]; endfunction Now you can call this function to get the variable: string(tab_param_callback(handles)) I corrected just this case and added the dots as explained. For the other variables, it can be done analogously. Furthermore, I moved the function definition to the beginning of the code. Because if your scrips crashed in the middle, the compiler has no chance to read the function definitions. Please find the code in this file . I hope this helps. Good luck!
Function keeps repeating in Octave
My code is written in a file "plot.m". If I put the following code in "plot.m", when I call plot("20%"), the Octave GUI will keep opening a new window with a new figure indefinitely. function X = plot(folderName) X = 0; data = ([folderName, "\\summary.txt"]); NUM_SURVIVED = data(1); NUM_DATA = size(data)(1)-1; FINAL_WEALTH = data(2 : NUM_DATA); %plot FINAL_WEALTH figure; plot(1:numel(FINAL_WEALTH), FINAL_WEALTH, '-b', 'LineWidth', 2); xlabel('x'); ylabel('FINAL_WEALTH'); end However, if I put the following code in "plot.m" and run it, the program works as intended and will plot data from "summary.txt". data = ("20%\\summary.txt"); NUM_SURVIVED = data(1); NUM_DATA = size(data)(1)-1; FINAL_WEALTH = data(2 : NUM_DATA); %plot FINAL_WEALTH figure; plot(1:numel(FINAL_WEALTH), FINAL_WEALTH, '-b', 'LineWidth', 2); xlabel('x'); ylabel('FINAL_WEALTH'); Any idea what I am doing wrong in the first section of code? I would like to write it as a function so that I can call it multiple times for different folder names.
When you call plot from the function plot, you get endless recursion. Rename your function and its file.
Just adding to Michael's answer, if you really wanted to name your function as "plot" and override the built-in plot function, but still wanted to be able to call the built-in plot function inside it, this is actually possible to do by using the builtin function to call the built-in version of plot. Your code would then look like this: function X = plot (folderName) % same code as before figure; builtin ("plot", 1:numel(FINAL_WEALTH), FINAL_WEALTH, '-b', 'LineWidth', 2); xlabel ('x'); ylabel ('FINAL_WEALTH'); end Obviously, whether it's a good idea to overload such a core function in the first place is an entirely different discussion topic. (Hint: don't!)
R: Running computation while waiting for user input
do you see a way to run a computation in R while waiting for a user input? I'm writing a script that makes differents types of plots which are defined by user input, but in first lot of data has to be loaded and processed. But in fact, user could start defining what he wants already while the processing is running - that's what I would like to do! I think package Rdsn might provide the functionality that I need, but I was not able to figure out how. Thanks!
You didn't give me much context, nor reproducible code, so I will just provide a simple example. I am not familiar with the Rdsn package, so I will use provide a solution I know. # create a function to prompt the user for some input readstuff = function(){ stuff = readline(prompt = "Enter some stuff: ") # Here is where you set the condition for the parameter # Let's say you want it to be an integer stuff = as.integer(stuff) if(is.na(stuff)){ return(readstuff()) } else { return(stuff) } } parameter = readstuff() print(parameter) print(parameter + 10) The key here is to "source" the script instead of "running" it. You can find the "source" button on the top right of RStudio. You can also use source(yourscript) to source it. So for every parameter you want to prompt the user for input, just call readstuff(). You can also tweak it a little to make it more general. For example: # create a function to prompt the user for some input readstuff = function(promptMessage = "stuff", class = "integer"){ stuff = readline(prompt = paste("Enter the", promptMessage, ": ")) # Here is where you set the condition for the parameter # Let's say you want it to be an integer stuff = as(stuff, class) if(is.na(stuff)){ return(readstuff(promptMessage, class)) } else { return(stuff) } } plotColor = readstuff("plot color", "character") size = readstuff("size parameter") xvarName = readstuff("x axis name", "character") df = data.frame(x = 1:100, y = 1:100) library(ggplot2) p = ggplot(df, aes(x = x, y = y, size = size, color = plotColor)) + labs(x = xvarName) + geom_point() print(p) The if(is.na(stuff)) statements won't work if class is character, but I won't get into details on how to fix that, since this question is mainly about how to wait for user input. There are also ways to suppress the warning messages if the user entered something other than what is intended, but again, a bit off topic to talk about it here. One important thing you have to watch out for is that anything you want R to print or plot, you need to wrap it with a print() function. Otherwise sourcing it won't print nor plot anything. Also, when typing in a parameter that is intended to be a string or character, don't add quotes. For example, for plotColor, type red instead of "red" in the prompt. Most of the readline code are referenced from here: