2

I have the following data and I am trying to construct a for loop across 3 stock symbols;

symbols <- c("HOG", "GE", "GOOG")

I have the following ggplot. I am trying to do two things.

1) Run a ggplot on all three of the symbols in symbols

2) Change the title of each ggplot to incorporate the correct symbols name

An example using GOOG below.

library(ggplot2)
ggplot(subset(NFO_WCAnalysis, Ticker %in% c("GOOG"))) +
  geom_line(aes(Date, NFO, group = Ticker, colour = "Blue")) +
  geom_line(aes(Date, WC, group = Ticker, colour = "Red")) +
  labs(title="NFO and WC plot GOOG", x="Date", y="NFO / WC") +
  scale_color_manual(labels = c("NFO", "WC"), values = c("Blue", "Red")) +
  theme_bw() +
  guides(color=guide_legend("Legend"))

The data. (I can post my attempts at the for loop if necessary) I am also open to just using the base plot functionality instead of ggplot.

structure(list(Ticker = c("GOOG", "GOOG", "GOOG", "GOOG", "GE", 
"GE", "GE", "GE", "HOG", "HOG", "HOG", "HOG"), Date = c(2017, 
2016, 2015, 2014, 2017, 2016, 2015, 2014, 2017, 2016, 2015, 2014
), REC = c(18705, 14232, 13909, 10849, 24438, 24076, 27022, 23237, 
2435.65, 2361.37, 2300.99, 2164.26), INV = c(749, 268, 0, 0, 
21923, 22354, 22515, 17689, 538.2, 499.92, 585.91, 448.87), OtherCurrentAssetsNotCash = c(80, 
596, 628, 852, 0, 0, 0, 0, 223.37, 227.06, 323.59, 370.96), Payables = c(3137, 
2041, 1931, 1715, 15153, 14435, 13680, 12067, 227.6, 235.32, 
235.61, 196.87), SpontaneousFunsIncDeftaxes = c(21476, 14941, 
14343, 13813, 19514, 18867, 17943, 14854, 529.82, 486.65, 471.97, 
449.32), NFO = c(-5079, -1886, -1737, -3827, 11694, 13128, 17914, 
14005, 2439.8, 2366.38, 2502.91, 2337.9), LTD = c(3969, 3935, 
1995, 3228, 110555, 105497, 147742, 190999, 4587.26, 4666.98, 
4832.47, 3761.53), EQ = c(152502, 139036, 120331, 103860, 64264, 
75827, 98273, 128158, 1844.28, 1920.16, 1839.65, 2909.29), OtherLongTermLiabilities = c(16211, 
7544, 5636, 4562, 144423, 119843, 165573, 238451, 382.97, 440.55, 
553.55, 468), FA = c(72987, 62089, 57347, 50531, 377945, 365183, 
493071, 654954, 6087.93, 6036.39, 5995.1, 5580.01), WC = c(99695, 
88426, 70615, 61119, -58703, -64016, -81483, -97346, 726.58, 
991.3, 1230.57, 1558.81), CreditPlusCashMinus = c(-104774, -90312, 
-72352, -64946, 70397, 77144, 99397, 111351, 1713.22, 1375.08, 
1272.34, 779.090000000001)), .Names = c("Ticker", "Date", "REC", 
"INV", "OtherCurrentAssetsNotCash", "Payables", "SpontaneousFunsIncDeftaxes", 
"NFO", "LTD", "EQ", "OtherLongTermLiabilities", "FA", "WC", "CreditPlusCashMinus"
), row.names = c(NA, -12L), class = "data.frame")
Julius Vainora
  • 47,421
  • 9
  • 90
  • 102
user113156
  • 6,761
  • 5
  • 35
  • 81

3 Answers3

2

I think the best approach here is to create a list of ggplot objects, then just replace the text in what you currently have.

This is what I mean:

#This will store all our ggplot objects, not necessary, but this gives us some extra flexibility
plotList <- list()

#This will loop through each of the symbol names
for(symbol in symbols){

    #What you had before, but with minor changes
    plotList[[symbol]] <- ggplot(subset(NFO_WCAnalysis, Ticker %in% symbol)) +
      geom_line(aes(Date, NFO, group = Ticker, colour = "Blue")) +
      geom_line(aes(Date, WC, group = Ticker, colour = "Red")) +
      labs(title=paste0("NFO and WC plot ", symbol), x="Date", y="NFO / WC") +
      scale_color_manual(labels = c("NFO", "WC"), values = c("Blue", "Red")) +
      theme_bw() +
      guides(color=guide_legend("Legend"))

}

Notice all that is different in the plotting command is that the "GOOG" has been replaced with symbol, which is the object it loops through. In the title argument I've just used a paste0 operation to concatenate what symbol name with the other text you want.

With objects stored in plotList[[symbol]] you can now call them however you want by using plotList[["GOOG"]] or whatever the name of the symbol you want is :)

Because it's a list, you can also use it sequentially, e.g. plotList[[1]]. This means you can loop through to print things too if you want to later, or just grab the ones you want.

e.g.

for(i in 1:3){

    print(plotList[[i]])

}

If you just want to plot things immediately in the first place, you can ditch the plotList[[symbol]] <- bit and just wrap all the ggplot instructions within a print command, and that will do the same job.

Good luck!

LachlanO
  • 1,152
  • 8
  • 14
1

Only a couple of changes are needed:

for(symbol in symbols)
  print(ggplot(subset(NFO_WCAnalysis, Ticker %in% symbol)) +
          geom_line(aes(Date, NFO, group = Ticker, colour = "Blue")) +
          geom_line(aes(Date, WC, group = Ticker, colour = "Red")) +
          labs(title= paste("NFO and WC plot", symbol), x = "Date", y = "NFO / WC") +
          scale_color_manual(labels = c("NFO", "WC"), values = c("Blue", "Red")) +
          theme_bw() +
          guides(color = guide_legend("Legend")))
Julius Vainora
  • 47,421
  • 9
  • 90
  • 102
  • Thanks! Certainly learned something new here! I was always starting loops off with `for(i in 1:length(symbols)){....` and running into many problems! Thanks again! – user113156 Mar 06 '18 at 22:26
  • Shows how dynamic `ggplot` can be also, adding simply `symbol`in the `labs(title...` did not think it would be so clean! – user113156 Mar 06 '18 at 22:27
  • 1
    @user113156, that's also a valid approach, in that case you could have written `symbols[i]` where I have `symbol`. But `for(symbol in symbols)` indeed looks somewhat nicer. – Julius Vainora Mar 06 '18 at 22:28
1

I'd start by writing a function. I would also transform the data from wide-long format, which works better with ggplot:

library(tidyverse)

plotSymbol <- function(data, symbol) {
  data %>%
    filter(Ticker == symbol) %>%
    select(Date, NFO, WC) %>%
    gather(variable,value, -Date) %>%
    ggplot(aes(Date, value)) + 
      geom_line(aes(color = variable, group = variable)) +
      labs(title = paste("NFO and WC plot", symbol),
           y = "NFO, WC") +
      scale_color_manual(values = c("blue", "red")) +
      theme_bw()
}

Now you can run, for example:

plotSymbol(NFO_WCAnalysis, "GOOG")

And rather than a loop, you can use lapply to generate a list of ggplot objects, one per symbol:

plots <- lapply(symbols, function(x) plotSymbol(NFO_WCAnalysis, x))

Now you can do whatever you like with the list plots. With a few modifications to the code you could, for example, write to PNG files using the symbol as part of the file name.

neilfws
  • 32,751
  • 5
  • 50
  • 63