I have a plot that is similar to this:
w=rnorm(9)
z=rnorm(9)
A=as.factor(c(rep(c("A1","A2","A3"),3)))
B=as.factor(c(rep("B1",3),rep("B2",3),rep("B3",3)))
C=as.factor(c("C1","C1","C2","C2","C3","C3","C1","C2","C3"))
xyplot(w~z,type="p",cex=1.4,
panel=function(x, y, ...) {
panel.xyplot(x=z[1], y=w[1],pch=15,col="red",...);
panel.xyplot(x=z[2], y=w[2],pch=15,col="green",...);
panel.xyplot(x=z[3], y=w[3],pch=15,col="blue",...);
panel.xyplot(x=z[4], y=w[4],pch=16,col="red",...);
panel.xyplot(x=z[5], y=w[5],pch=16,col="green",...);
panel.xyplot(x=z[6], y=w[6],pch=16,col="blue",...);
panel.xyplot(x=z[7], y=w[7],pch=17,col="red",...);
panel.xyplot(x=z[8], y=w[8],pch=17,col="green",...);
panel.xyplot(x=z[9], y=w[9],pch=17,col="blue",...);
ltext(x=x, y=y+0.1, labels=C)
})
And now I have been trying a lot without success to get a key like this:
I tried with key function, with legend function, trying to create more than one key in the same graph… I’m lost!!
I know you are doing this in lattice, but ggplot makes this kind of thing pretty easy.
my.data<-data.frame(w,z,A,B,C)
ggplot(my.data,aes(x=w,y=z,colour=A,shape=B,label=C)) +
geom_point(size=3) +
geom_text(hjust=-0.2,vjust=-0.2)
I had a hard time figuring out how to get a guide for the labels. But then I realized that if you have the labels, why do you need a guide?
Related
I have a plotWidget (self.widget0) from pyqtgraph on the pyqt GUI. I want to add 200 plots at this widget. What I can do is add each plot one by one:
self.plot0 = self.widget0.plot(xx0, yy0)
self.plot1 = self.widget0.plot(xx1, yy1)
...
self.plot199 = self.widget0.plot(xx199, yy199)
Where xx0, xx1,... and yyo, yy1... are all 1D numpy arrays of the plot.
For this case, I can update the specified plots later but keep all others, for example if I want to update the 100th plot:
self.widget0.removeItem(self.plot99)
self.plot99 = self.widget0.plot(xx99_new, yy99_new)
My question is adding those 200 lines in to self.plot0, self.plot1, self.plot2, self.plot3, ... are so inefficient and difficult. Can anyone advise a way to code this using loop or dictionary?
A dict of plots would suffice, you want a dict so that when an element is removed, the order isn't lost:
self.plots = {}
for plot_num in range(200):
self.plots[plot_num] = self.widget0.plot(xx[plot_num], yy[plot_num])
self.widget0.removeItem(self.plots[99])
self.plots[99] = self.widget0.plot(xx99_new, yy99_new)
I trying to plot vectors of electric field in scilab. But it always error :
champ: Wrong size for input arguments: Incompatible sizes.
the code:
epsilon0=1e-9/(36*%pi);
q=3e-9;
p=[-1,0,0];
x=-2:0.2:2;
y=-2:0.2:2;
[px,py]=meshgrid(x,y);
for m=1:length(x),
for n=1:length(y),
xp=px(m,n);
yp=py(m,n);
vektorr1x=xp-p(1);
vektorr1y=yp-p(3);
r1=sqrt(vektorr1x^2+vektorr1z^2);
if r1~=0 then
ar1x=vektorr1x/r1;
ar1y=vektorr1y/r1;
E1x=q*ar1x/(4*%pi*epsilon0*r1^2);
E1y=q*ar1y/(4*%pi*epsilon0*r1^2);
else
E1x=0;
E1y=0;
end,
end,
end,
pl=champ(px,py,E1x,E1y,[-2,-1,2,-1]);
You don't have to use loops, the following script does what you want:
epsilon0=1e-9/(36*%pi);
q=3e-9;
p=[-1,0,0];
x=-2:0.2:2;
y=-2:0.2:2;
[px,py]=ndgrid(x,y);
vektorr1x=px-p(1);
vektorr1y=py-p(3);
r1=sqrt(vektorr1x.^2+vektorr1y.^2);
ar1x=vektorr1x./r1;
ar1y=vektorr1y./r1;
E1x=q*ar1x./(4*%pi*epsilon0*r1.^2);
E1y=q*ar1y./(4*%pi*epsilon0*r1.^2);
E1x(r1==0)=0;
E1y(r1==0)=0;
clf
champ(x,y,E1x,E1y,[-2,-1,2,-1]);
To plot fields don't use meshgrid to sample the domain use ngrid instead. Moreover, don't forget to use dot-prefixed operators.
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!)
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.
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: