Multiple plots at the same time

1 view
Skip to first unread message

Mark Knecht

unread,
Jun 29, 2009, 3:17:31 PM6/29/09
to hel...@googlegroups.com
Hi,
Thanks to the lords of Bar Area R Users for creating an environment
where we can have a higher volume of traffic about using R without
getting in the way of managing the current list the way folks are used
to. I for one will really appreciate it as I have held off asking
questions on the other list.

I'm *investigating* R as a means of *NOT* writing a dedicated GUI
app. I am not and don't want to be a Linux or Windows programmer. One
of my requirements is the ability to display multiple plots at the
same time. Think of a small matrix of charts, maybe 3x3, so 9 charts
displayed at the same time. Is there a way to do this in R, or with an
R add-on package?

Possibly Lattice is the right answer? Is it as difficult to use as
I seem to read from other newbies? I'm not against digging in but
don't want to waste time on a package that simply cannot do what I
need. If not Lattice then what are the other options?

So far I see nothing in ?plot that clues me in on how to do a
second plot and every experiment I run simply draws over the top of
the old plot so I suspect maybe it's not there.

Any examples of how to pull up multiple charts at the same time
would be greatly appreciated. I promise to post back some results as I
go.

Cheers,
Mark

Daniel Levine

unread,
Jun 29, 2009, 4:11:04 PM6/29/09
to Mark Knecht, hel...@googlegroups.com
I'm not exactly positive on what you want. But you can definitely display multiple plots at once and with a number of different layouts. Look at ?par and check out mfcol and mfrow, they allow you to create space for plots to go in a certain order. Use par(mfrow(3,3)) to create a window with room for 9 plots that enters them in by row. Then when you call a plot() it will automatically fill the next open space.

Good luck.

Mark Knecht

unread,
Jun 29, 2009, 4:42:13 PM6/29/09
to Michael E. Driscoll, Bay Area R Helpers
Michael & Daniel,
Thanks for your responses.

This is certainly one way to do it. I suppose if I manage the order
in which I call the plot commands and make sure the matrix matches up
against my visual requirements it could work very well.

Small PDF attached. Something isn't right about the upper right
corner plot but I'm sure that's either me or my data.

Cheers,
Mark

On Mon, Jun 29, 2009 at 1:30 PM, Michael E.
Driscoll<m.e.dr...@gmail.com> wrote:
> Mark -
>
> The most straightforward way to do this is set a graphical parameter
> called 'mfrow'.
>
>  par(mfrow=c(2,2))
>
> Will split up your graphical display into a 2x2 matrix.
>
> I'd also recommend taking a look at a survey to R Graphics that I
> recently posted which talks about R's base graphics, the lattice
> package, and ggplot2.
>
>  http://dataspora.com/archive/2009/seminar/Survey_of_R_Graphics_by_Driscoll_Dataspora_Jun2009.pdf
>
> Mike
>
>
>
>
> On Mon, Jun 29, 2009 at 12:17 PM, Mark Knecht<markk...@gmail.com> wrote:
>>
> --
> p: 415.860.4347
> b: www.dataspora.com/blog
> t: www.twitter.com/dataspora
>
3x3.pdf

Mark Knecht

unread,
Jun 29, 2009, 6:31:37 PM6/29/09
to Bay Area R Helpers
On Mon, Jun 29, 2009 at 1:42 PM, Mark Knecht<markk...@gmail.com> wrote:
> Michael & Daniel,
>   Thanks for your responses.
>
>   This is certainly one way to do it. I suppose if I manage the order
> in which I call the plot commands and make sure the matrix matches up
> against my visual requirements it could work very well.
>
>   Small PDF attached. Something isn't right about the upper right
> corner plot but I'm sure that's either me or my data.
>
> Cheers,
> Mark
>

Finally I noticed that the chart in the upper right which has the
shadow and the strange curve is actually the only data series with
over 1000 points. (1300+ actually) All the others are smaller -
350-800. Is there a limit to how many points the plot command can
handle? I don't see anything in ?plot so probably it's some sort of
overall limit, like 2^10 or something like that?

The problem is worse than that though. The other thing that happened
with this plot only was that R decided to rearrange the trade numbers
on the X axis. Instead of incrementing 1:1300 they have been reordered
with everything above 1000 between 1 and 2!

the code I used to generate this plot is shown here:

> Gallatin <- read.csv("C:\\MSA-Files\\Excel Rollup\\Gallatin.csv", header = TRUE, sep = ",", quote="\"", dec=".",fill = TRUE, comment.char="", skip=1,check.names=FALSE)
> Gallatin$EQUITY <- as.numeric(sub('[",]', '', Gallatin$EQUITY))
> plot(EQUITY ~ TRADE, Gallatin,type="l" )

It's the same code for each of the 9 charts with only the name of the
trading system changed. Again, the only difference that I can see is
this one system has more than 1000 trades...

Thanks,
Mark

Ted Dunning

unread,
Jun 29, 2009, 7:11:19 PM6/29/09
to Bay Area R Helpers
partial answers inline. I can't answer the big questions without more
context.

On Jun 29, 3:31 pm, Mark Knecht <markkne...@gmail.com> wrote:
> .... Is there a limit to how many points the plot command can
> handle?

Only practical limits. I have plotted >100,000 points with no more
penalty than a delay in seeing the plot.

> I don't see anything in ?plot so probably it's some sort of
> overall limit, like 2^10 or something like that?

No way is the limit that small.

> The problem is worse than that though. The other thing that happened
> with this plot only was that R decided to rearrange the trade numbers
> on the X axis. Instead of incrementing 1:1300 they have been reordered
> with everything above 1000 between 1 and 2!

This smells like strings. I think that what has happened here is that
something has caused R to treat your X values for this plot as
strings.

Think back ... you also just noted that this is the only plot with
more than 1000 items.

I think that you need to get rid of commas in this value and convert
to numeric.

Ted Dunning

unread,
Jun 29, 2009, 7:12:22 PM6/29/09
to Bay Area R Helpers

Ahhh... and the shadow is simply a huge number of tick marks.

The problem is almost certainly string treatment of your data. Think
of it as a feature!

On Jun 29, 3:31 pm, Mark Knecht <markkne...@gmail.com> wrote:

Mark Knecht

unread,
Jun 29, 2009, 7:40:41 PM6/29/09
to Ted Dunning, Bay Area R Helpers
LOL! No wI know how to get a shadow. ;-)

I suspect you are right about the strings. It didn't dawn on me until
you said it that once I get above 999 even the trade numbers which are
just incrementing by 1 have commas, ala 998 999 1,001 1,002 and so
on. That then raises the point that actually individual trade gains
bigger than $1K have commas. It looks like the substitution thing that
I got on the other list and applied to the equity value actually has
to be applied to almost everything in the table.

OK, off to do the work to prove it but I suspect you've solved this one.

Thanks!

- Mark

Ted Dunning

unread,
Jun 29, 2009, 7:51:41 PM6/29/09
to Mark Knecht, Bay Area R Helpers

https://stat.ethz.ch/pipermail/r-help/2007-April/130912.html

Might be of some help.  In particular, this allows you to define a class for conversion of the data.  These lines:

library(methods)
setClass("num.with.comma")
setAs("character", "num.with.comma", function(from) as.numeric(gsub(",", "", from)))

define a class known as num.with.comma

Then you can use this class for reading data:

### test ###

Input <- "A B
1,000 1
2,000 2
3,000 3
"
DF <- read.table(textConnection(Input), header = TRUE,
colClasses = c("num.with.comma", "numeric"))
str(DF)
My only addition here, btw, was doing a google search and changing the name of the class.  The search I used was [r thousands separator, input] and it landed me pretty much dead on the right answer.
--
Ted Dunning, CTO
DeepDyve

111 West Evelyn Ave. Ste. 202
Sunnyvale, CA 94086
http://www.deepdyve.com
858-414-0013 (m)
408-773-0220 (fax)

Mark Knecht

unread,
Jun 29, 2009, 8:12:03 PM6/29/09
to Ted Dunning, Bay Area R Helpers
On Mon, Jun 29, 2009 at 4:51 PM, Ted Dunning<ted.d...@gmail.com> wrote:
>
> https://stat.ethz.ch/pipermail/r-help/2007-April/130912.html
>
> Might be of some help.  In particular, this allows you to define a class for
> conversion of the data.  These lines:
>
> library(methods)
> setClass("num.with.comma")
> setAs("character", "num.with.comma", function(from) as.numeric(gsub(",", "",
> from)))
>
> define a class known as num.with.comma
>
> Then you can use this class for reading data:
>
> ### test ###
>
> Input <- "A B
>
>
>
> 1,000 1
> 2,000 2
> 3,000 3
> "
> DF <- read.table(textConnection(Input), header = TRUE,
> colClasses = c("num.with.comma", "numeric"))
> str(DF)
>
> My only addition here, btw, was doing a google search and changing the name
> of the class.  The search I used was [r thousands separator, input] and it
> landed me pretty much dead on the right answer.
>

Humm....OK - with it sitting there in front of me it almost looks like
I might understand it, but in truth I'm sure I don't. (Only my 2nd day
using R) I'll have to play with your code to really get it.
textConnection is new to me. library(methods) I don't recognize yet.
str is new.

Now, I think I've got the code in a script file and I ran it one line
at a time. No error messages but I don't understand the str output. It
seems to have changed 1,000 to X1.000.

I need to study this a bit more.

Thanks!

Mark

> library(methods)
> setClass("num.with.comma")
[1] "num.with.comma"


> setAs("character", "num.with.comma", function(from) as.numeric(gsub(",", "",from)))

> Input <- "A B 1,000 1 2,000 2 3,000 3"

> DF <- read.table(textConnection(Input), header = TRUE,colClasses = c("num.with.comma", "numeric"))
> str(DF)
'data.frame': 0 obs. of 8 variables:
$ A : num
$ B : num
$ X1.000: num
$ X1 : num
$ X2.000: num
$ X2 : num
$ X3.000: num
$ X3 : num
>
> DF
[1] A B X1.000 X1 X2.000 X2 X3.000 X3
<0 rows> (or 0-length row.names)
>

Earl

unread,
Jun 29, 2009, 8:19:58 PM6/29/09
to Bay Area R Helpers
I think the problem is you put everything on one line. Note Ted's
Input string has 4 lines while yours has 1.

I think it's easier to just read the text file, assuming any numbers
with commas are quote enclosed, and clean up afterwards.

eg:
mydata is your data frame, then write a function clean which turns
your dirty character strings into numerics, then do:

mydata[] <- sapply(mydata, clean)


Earl



On Jun 29, 5:12 pm, Mark Knecht <markkne...@gmail.com> wrote:

Ted Dunning

unread,
Jun 29, 2009, 9:03:08 PM6/29/09
to Mark Knecht, Bay Area R Helpers

textConnection is just a way to read a string as if it were a file.  That makes the test case simpler to read.

library(methods) is included to allow the definition of a new class.

str just prints out the DF data frame in a lower level format.  Try just displaying by typing DF alone on a line.

The X1.000 is a row header, I think, not a number.  Not sure where you got that from since here is the output I get:

> str(DF)
'data.frame':    3 obs. of  2 variables:
 $ A: num  1000 2000 3000
 $ B: num  1 2 3
>
> DF
     A B
1 1000 1
2 2000 2
3 3000 3


On Mon, Jun 29, 2009 at 5:12 PM, Mark Knecht <markk...@gmail.com> wrote:
Humm....OK - with it sitting there in front of me it almost looks like
I might understand it, but in truth I'm sure I don't. (Only my 2nd day
using R)  I'll have to play with your code to really get it.
textConnection is new to me. library(methods) I don't recognize yet.
str is new.

...


Ted Dunning

unread,
Jun 29, 2009, 9:04:11 PM6/29/09
to Earl, Bay Area R Helpers

Even better to write a function to fix certain columns of a data.frame.

Mark Knecht

unread,
Jun 29, 2009, 9:12:52 PM6/29/09
to Ted Dunning, Bay Area R Helpers
On Mon, Jun 29, 2009 at 6:04 PM, Ted Dunning<ted.d...@gmail.com> wrote:
>
> Even better to write a function to fix certain columns of a data.frame.
>

This is what I'm thinking but first I have to write a function to fix
the column headers which currently have their own set of problems.
Either that or dump the headers completely and just process everything
by column number, but I think using the headers might be better in the
long run in case my apps start putting things out in a different
order.

This feels like a lot of work but I'm still convinced this is probably
way better in the long run vs my original idea of doing a GUI app from
scratch. With my experience level this is going to take awhile.

Thanks so much for your help, and also to the others who have responded.

Cheers,
Mark

Mark Knecht

unread,
Jun 30, 2009, 12:21:12 PM6/30/09
to Bay Area R Helpers

I'm sure that experienced R users can probably do this in a line or
two but I'm making good headway. Wrote my first function. Almost got
it right the first time, but it took a couple passes. Cleaned up all
the data that I need to clean up right now so that I can take the
second step which is creating all the indicator data to evaluate my
system. (Stuff I have in TradeStation and/or Excel as equations and
will move to R as functions.)

My simple code is:

readMSA = function (MyFile) {
x <- read.csv(MyFile, header = TRUE, sep = ",", quote="\"",


dec=".",fill = TRUE, comment.char="", skip=1,check.names=FALSE)

names(x)[1] <- "Trade"
names(x)[2] <- "SysNumber"
names(x)[3] <- "Date"
names(x)[4] <- "PL_Size"
names(x)[5] <- "PS_Method"
names(x)[6] <- "Size"
names(x)[7] <- "Pos_PL"
names(x)[8] <- "DDDollars"
names(x)[9] <- "DDPercent"
names(x)[10]<- "Equity"
x$Trade <- as.numeric(sub('[",]', '', x$Trade))
x$PL_Size <- as.numeric(sub('[",]', '', x$PL_Size))
x$Pos_PL <- as.numeric(sub('[",]', '', x$Pos_PL))
x$DDDollars <- as.numeric(sub('[",]', '', x$DDDollars))
x$DDPercent <- as.numeric(sub('[",]', '', x$DDPercent))
x$Equity <- as.numeric(sub('[",]', '', x$Equity))
readMSA <-x
}

require(TTR)
Bobcat1 <- readMSA("C:\\MSA-Files\\Excel Rollup\\Bobcat1.csv")
DDF <- readMSA("C:\\MSA-Files\\Excel Rollup\\DDF.csv")
Gallatin <- readMSA("C:\\MSA-Files\\Excel Rollup\\Gallatin.csv")
Kaweah <- readMSA("C:\\MSA-Files\\Excel Rollup\\Kaweah.csv")
KaweahNewOpt <- readMSA("C:\\MSA-Files\\Excel Rollup\\Kaweah-NewOpt.csv")
Klamath <- readMSA("C:\\MSA-Files\\Excel Rollup\\Klamath.csv")
MDDF <- readMSA("C:\\MSA-Files\\Excel Rollup\\MDDF.csv")
MDDFNewOpt <- readMSA("C:\\MSA-Files\\Excel Rollup\\MDDF-NewOpt.csv")
PFA_VWAP <- readMSA("C:\\MSA-Files\\Excel Rollup\\PFA_VWAP.csv")

par(mfrow=c(3,3))

plot(Equity ~ Trade, Bobcat1,type="l" )
plot(Equity ~ Trade, DDF,type="l" )
plot(Equity ~ Trade, Gallatin,type="l" )
plot(Equity ~ Trade, Kaweah,type="l" )
plot(Equity ~ Trade, KaweahNewOpt,type="l" )
plot(Equity ~ Trade, Klamath,type="l" )
plot(Equity ~ Trade, MDDF,type="l" )
plot(Equity ~ Trade, MDDFNewOpt,type="l" )
plot(Equity ~ Trade, PFA_VWAP,type="l" )

which generates a nice little 3x3 plot of the 9 system's equity curves
in under 2 seconds. Similar results in Excel take 1-2 minutes on this
same machine.

Kewl!

I'm sure there are probably better ways to manage the list of system
names/file path names. I'll get to that later.

Thanks to all for the help. More questions coming soon! ;-)

Cheers,
Mark

3x3.pdf

Ted Dunning

unread,
Jun 30, 2009, 5:18:29 PM6/30/09
to Mark Knecht, Bay Area R Helpers

Speaking of one liners, this code:

On Tue, Jun 30, 2009 at 9:21 AM, Mark Knecht <markk...@gmail.com> wrote:
       names(x)[1] <- "Trade"
       names(x)[2] <- "SysNumber"
       names(x)[3] <- "Date"
       names(x)[4] <- "PL_Size"
       names(x)[5] <- "PS_Method"
       names(x)[6] <- "Size"
       names(x)[7] <- "Pos_PL"
       names(x)[8] <- "DDDollars"
       names(x)[9] <- "DDPercent"
       names(x)[10]<- "Equity"

can be written as:

     names(x) <- c("Trade", "SysNumber", "Date" ... and so on ... "Equity)

Also, it may help your fingers to know that = is a synonym for <-

Using = will make your code very unstylish among the hip R crowd, but you may prefer it.
 
I'm sure there are probably better ways to manage the list of system
names/file path names. I'll get to that later.

When you do get to that, paste will be your friend:

> paste("a", "b")
[1] "a b"
> paste("a", "b", sep="/")
[1] "a/b"
> paste(c("a", "b"), sep="/")
[1] "a" "b"
> paste(c("a", "b"), "foo", sep="/")
[1] "a/foo" "b/foo"
> paste(c("a", "b"), c("foo", "bar"), "baz", sep="/")
[1] "a/foo/baz" "b/bar/baz"
> paste(c("a", "b"), c("foo", "bar"), "baz", sep="/", collapse=":")
[1] "a/foo/baz:b/bar/baz"

Earl

unread,
Jun 30, 2009, 8:43:48 PM6/30/09
to Bay Area R Helpers
Also:

> # list.files() shows you the files in your current working directory
> # getwd() / setwd() set the working directory

-- this code should allow you to look in a directory and turn every
filename there into a dataframe named as the file

> setwd( '~/myworkingdirectory' )
> files <- list.files()
> names <- gsub(pattern='\\.csv$', '', files, ignore.case=T)
>
> for( i in 1:length(names)){
+ a <- paste(names[i], ' <- read.csv( file=\'', files[i], '\',
header=T, sep=\',\')', sep='')
+ # print( a )
+ eval(parse( text=a ))
+ }
>



On Jun 30, 9:21 am, Mark Knecht <markkne...@gmail.com> wrote:
> On Mon, Jun 29, 2009 at 6:12 PM, Mark Knecht<markkne...@gmail.com> wrote:
>  3x3.pdf
> 54KViewDownload
Reply all
Reply to author
Forward
0 new messages