├── .gitignore ├── CodeVizWorkshopI.R ├── ElectionMap ├── Additions ├── stateHTMLTables.js ├── stateMap.svg └── stateTableEx.html ├── FollowOnNotes ├── GNUmakefile ├── GraphicsPartI.pdf ├── Interactivity.html ├── Interactivity.xml ├── JSEg ├── 0_a1e99_9dabddb2_L.jpg ├── 260px-Okapi2.jpg ├── 440px-Lowland_Streaked_Tenrec,_Mantadia,_Madagascar.jpg ├── Data.js ├── Eg.js ├── eg.css ├── jsAutoEg.html └── jsEg.html ├── Networks ├── ggvisCalls.R ├── ggvisFunctionNetwork.R ├── twoCols.R └── utilFuns.R ├── OmegaTech.css ├── Packages.html ├── SVGAnnotation ├── housing.R ├── housingFrequencies.rda ├── housingMatplot.svg ├── live_matplot.svg ├── live_scatterplot.svg ├── matplot.R ├── matplot.svg ├── scatterPlot.svg └── tooltips.R ├── Topics.html ├── ggvis └── tooltips.R ├── googleVis ├── eg.html ├── eg1.R ├── eg1.html ├── eg2.R ├── eg2.html ├── getMSEvents.R ├── googleVis.R ├── ldf.R └── ldf.rda ├── html.css ├── index.html ├── rCharts ├── barChart.R ├── egSmall.R ├── maps.R └── rCharts.R ├── shiny.html ├── server.R └── www │ └── index.html ├── shiny0 ├── server.R └── ui.R ├── shiny1 ├── 260px-Okapi2.jpg ├── htmlContent.html ├── server.R └── ui.R └── shinyHousePrices ├── README └── housing.rda /.gitignore: -------------------------------------------------------------------------------- 1 | googleVis_pkg 2 | .Rhistory 3 | -------------------------------------------------------------------------------- /CodeVizWorkshopI.R: -------------------------------------------------------------------------------- 1 | ### Infant Health 2 | load(url("http://www.stat.berkeley.edu/users/nolan/data/KaiserBabies.rda")) 3 | 4 | hist(infants$bwt , freq = FALSE, 5 | xlab = "Birth Weight (oz)", 6 | main = "Male Babies, Oakland Kaiser 1960s") 7 | 8 | hist(infants$bwt , freq = FALSE, breaks = 30, 9 | xlab = "Birth Weight (oz)", 10 | main = "Male Babies, Oakland Kaiser 1960s") 11 | 12 | hist(infants$bwt , freq = FALSE, 13 | breaks = c(55, 70, 80, 90, seq(95,150, by = 5), 14 | 160, 170, 180), 15 | xlab = "Birth Weight (oz)", main="") 16 | 17 | 18 | plot(density(infants$bwt, bw = 1), 19 | xlab = "Birth Weight (oz)", 20 | main = "Male Babies") 21 | 22 | boxplot(infants$bwt, 23 | xlab="Birth Weight (oz)") 24 | 25 | plot(table(infants$parity), 26 | type ="h", lwd = 4, 27 | ylab ="Proportion", col="darkgrey") 28 | 29 | barplot(table(infants$parity)) 30 | 31 | tParity = table(infants$parity) 32 | 33 | dotchart(x = as.numeric(tParity), 34 | labels = names(tParity), 35 | xlab = "Parity", 36 | pch = 19, bg= "darkgrey") 37 | 38 | library(vioplot) 39 | vioplot(infants$bwt) 40 | 41 | sinfants = subset(infants, smoke != "Unknown" & ed != "Unknown") 42 | levels(sinfants$ed) = c("No HS", "Some HS", "High School", "Trade", 43 | "Some College","College", "Unknown") 44 | levels(sinfants$smoke) = c("Never", "Now", "Until", "Once", "Unknown") 45 | with(sinfants, mosaicplot(table(droplevels(ed), 46 | droplevels(smoke)), 47 | main = "")) 48 | 49 | 50 | tableEdSmoke = with(sinfants, table(droplevels(ed), 51 | droplevels(smoke))) 52 | 53 | tableSmokeEd = with(sinfants, table(droplevels(smoke), 54 | droplevels(ed))) 55 | barplot(tableEdSmoke) 56 | barplot(tableEdSmoke, beside = TRUE) 57 | barplot(tableSmokeEd, beside = TRUE) 58 | 59 | matplot(x = 1:6, y = tableEdSmoke, type ="l", 60 | lwd = 3, axes = FALSE, xlab = "", ylab = "Count") 61 | axis(1, labels = c("No HS", "Some HS", "HS", "Trade", 62 | "Some College","College"), 63 | at = 1:6) 64 | axis(2) 65 | 66 | 67 | ######## SF Housing 68 | 69 | load(url("http://www.stat.berkeley.edu/users/nolan/data/smallHousing.rda")) 70 | 71 | boxplot(shousing$price ~ shousing$city, las = 2) 72 | 73 | citymedian = tapply(shousing$price, shousing$city, median, na.rm=TRUE) 74 | cityOrder = order(citymedian) 75 | shousing$cityO = factor(shousing$city, 76 | levels = levels(shousing$city)[cityOrder], 77 | ordered = TRUE) 78 | boxplot(shousing$price ~ shousing$cityO, las = 2) 79 | 80 | shousing$ppsf = shousing$price/shousing$bsqft 81 | 82 | plot(ppsf ~ shousing$bsqft, 83 | pch=19, cex = 0.2, 84 | subset = shousing$city == "Berkeley", 85 | main="Berkeley", 86 | xlab="Area (ft^2)", 87 | ylab = "Price/ft^2") 88 | 89 | 90 | pdf("smoothScatterSFHousing.pdf", width = 8, height = 5) 91 | 92 | with(shousing, smoothScatter(ppsf ~ bsqft, 93 | ylim = c(0, 1250), xlim = c(400, 6000), 94 | xlab="Area (ft^2)", ylab = "Price/ft^2")) 95 | 96 | h.obj = with(shousing, loess(ppsf ~ bsqft)) 97 | 98 | h.obj.pr = predict(h.obj, 99 | newdata = data.frame( bsqft = 700:6000)) 100 | lines(x = 700:6000, y = h.obj.pr, col = "#4daf4a", lwd = 2) 101 | 102 | library(lattice) 103 | xyplot(ppsf ~ log(bsqft)| city, data = shousing, group = br, 104 | ylim = c(0, 1500),) 105 | 106 | library(ggplot2) 107 | p = ggplot(shousing) 108 | 109 | p + geom_point(aes(x = bsqft, y = ppsf, color = factor(br))) + 110 | scale_x_continuous(trans = "log") + 111 | scale_y_continuous(limits = c(0, 1500)) + 112 | facet_wrap(~ city) 113 | 114 | p = ggplot(shousing, aes(factor(city), ppsf)) 115 | p + geom_violin(trim = FALSE) + 116 | scale_y_continuous(limits = c(0, 2000)) 117 | 118 | library("RColorBrewer") 119 | library("plotrix") 120 | 121 | 122 | ############ CIA Factbook 123 | 124 | load(url("http://www.stat.berkeley.edu/users/nolan/data/factbook.rda")) 125 | 126 | pairs(fbDF) 127 | 128 | myColors = brewer.pal(9, "YlOrRd")[c(9, 7, 6, 4, 2, 1)] 129 | 130 | fbDF$cutLE = cut(fbDF$lifeExpect, 131 | breaks = c(48, 55, 60, 65, 70, 75, 90)) 132 | popOrder = order(fbDF$pop, decreasing = TRUE) 133 | fbDF = fbDF[popOrder, ] 134 | 135 | 136 | 137 | plot(x = fbDF$gini, y = fbDF$im, type = "n", 138 | log = "y", 139 | xlab = "Gini Index", 140 | ylab = "Infant Mortality Rate (log scale)", 141 | main = "World Trends" ) 142 | 143 | symbols(x = fbDF$gini, y = fbDF$imRates, 144 | bg = myColors[fbDF$cutLE], add = TRUE, 145 | circles = pmax(sqrt(fbDF$pop)/8000, 0.2), 146 | inches = FALSE) 147 | 148 | lifeLabels = c("< 55", "55 - 65", "65 - 70", 149 | "70-75", "75 - 80", ">85" 150 | 151 | legend("bottomright", title = "Life Expectancy", 152 | legend = lifeLabels, 153 | bty = "n", fill = myColors) 154 | 155 | 156 | 157 | 158 | fbDF$popS = pmax(sqrt(fbDF$pop)/8000, 1) 159 | 160 | 161 | p = ggplot(fbDF) 162 | 163 | p + 164 | geom_point(aes(x = gini, y = imRates, 165 | color = cutLE, size = popS)) + 166 | scale_y_continuous(trans = "log", 167 | name = "Infant Mortality Rate (log scale)") + 168 | scale_x_continuous(name = "Gini Index") + 169 | scale_color_manual(values = myColors, 170 | name = "Life Expectancy") + 171 | scale_size(name = "Population") + 172 | ggtitle("World Trends") 173 | 174 | 175 | -------------------------------------------------------------------------------- /ElectionMap/Additions: -------------------------------------------------------------------------------- 1 | When we click on a state, show the counties of that state color-coded. -------------------------------------------------------------------------------- /ElectionMap/stateMap.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | map("state", fill = TRUE, col = c("red", "blue")[obama.won[stateNames] + 5 | 1]) 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | alabama 17 | 18 | 19 | 20 | 21 | arizona 22 | 23 | 24 | 25 | 26 | arkansas 27 | 28 | 29 | 30 | 31 | california 32 | 33 | 34 | 35 | 36 | colorado 37 | 38 | 39 | 40 | 41 | connecticut 42 | 43 | 44 | 45 | 46 | delaware 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | florida 55 | 56 | 57 | 58 | 59 | georgia 60 | 61 | 62 | 63 | 64 | idaho 65 | 66 | 67 | 68 | 69 | illinois 70 | 71 | 72 | 73 | 74 | indiana 75 | 76 | 77 | 78 | 79 | iowa 80 | 81 | 82 | 83 | 84 | kansas 85 | 86 | 87 | 88 | 89 | kentucky 90 | 91 | 92 | 93 | 94 | louisiana 95 | 96 | 97 | 98 | 99 | maine 100 | 101 | 102 | 103 | 104 | maryland 105 | 106 | 107 | 108 | 109 | massachusetts 110 | 111 | 112 | 113 | 114 | massachusetts 115 | 116 | 117 | 118 | 119 | massachusetts 120 | 121 | 122 | 123 | 124 | michigan 125 | 126 | 127 | 128 | 129 | michigan 130 | 131 | 132 | 133 | 134 | minnesota 135 | 136 | 137 | 138 | 139 | mississippi 140 | 141 | 142 | 143 | 144 | missouri 145 | 146 | 147 | 148 | 149 | montana 150 | 151 | 152 | 153 | 154 | nebraska 155 | 156 | 157 | 158 | 159 | nevada 160 | 161 | 162 | 163 | 164 | new hampshire 165 | 166 | 167 | 168 | 169 | new jersey 170 | 171 | 172 | 173 | 174 | new mexico 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | new york 183 | 184 | 185 | 186 | 187 | new york 188 | 189 | 190 | 191 | 192 | new york 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | north carolina 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | north dakota 209 | 210 | 211 | 212 | 213 | ohio 214 | 215 | 216 | 217 | 218 | oklahoma 219 | 220 | 221 | 222 | 223 | oregon 224 | 225 | 226 | 227 | 228 | pennsylvania 229 | 230 | 231 | 232 | 233 | rhode island 234 | 235 | 236 | 237 | 238 | south carolina 239 | 240 | 241 | 242 | 243 | south dakota 244 | 245 | 246 | 247 | 248 | tennessee 249 | 250 | 251 | 252 | 253 | texas 254 | 255 | 256 | 257 | 258 | utah 259 | 260 | 261 | 262 | 263 | vermont 264 | 265 | 266 | 267 | 268 | virginia 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | virginia 277 | 278 | 279 | 280 | 281 | washington 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | washington 290 | 291 | 292 | 293 | 294 | washington 295 | 296 | 297 | 298 | 299 | washington 300 | 301 | 302 | 303 | 304 | west virginia 305 | 306 | 307 | 308 | 309 | wisconsin 310 | 311 | 312 | 313 | 314 | wyoming 315 | 316 | 317 | 318 | 319 | district of columbia 320 | 321 | 322 | 323 | 324 | new york 325 | 326 | 327 | 328 | 329 | north carolina 330 | 331 | 332 | 333 | 334 | north carolina 335 | 336 | 337 | 338 | 339 | virginia 340 | 341 | 342 | 343 | 344 | washington 345 | 346 | 347 | 348 | 349 | 350 | -------------------------------------------------------------------------------- /ElectionMap/stateTableEx.html: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 52 | 53 | 70 | 71 | 82 | 83 | 84 | 85 | 104 | 105 | 106 | 107 | 108 | 109 |
110 |

Presidential Election 2008

111 | 112 |

113 | The map is interactive in that you can click on 114 | anywhere within a state to see more detailed 115 | results about the voting in that state. 116 |

117 |
118 | 119 |
120 | 121 |
122 | 123 |
124 | 125 |
126 | 127 | 128 |
129 |
130 | 131 |
132 | + Click to see county results 133 | 137 |
138 |
139 | 140 | 141 |
142 |
143 |
Duncan Temple Lang 144 | <duncan@wald.ucdavis.edu>
145 | 146 | Last modified: Thu Dec 24 10:31:14 PST 2009 147 | 148 |
149 | 150 | -------------------------------------------------------------------------------- /FollowOnNotes: -------------------------------------------------------------------------------- 1 | Plots aren't supposed to be quick to understand. 2 | 3 | And they shouldn't be simple to create. 4 | 5 | Turn tables into plots. -------------------------------------------------------------------------------- /GNUmakefile: -------------------------------------------------------------------------------- 1 | ifndef DYN_DOCS 2 | DYN_DOCS=$(HOME)/Classes/StatComputing/XDynDocs/inst 3 | endif 4 | 5 | include $(DYN_DOCS)/Make/Makefile 6 | -------------------------------------------------------------------------------- /GraphicsPartI.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsidavis/Visualization/7b595a9f8b2671504ead46db32f103520f9b0d44/GraphicsPartI.pdf -------------------------------------------------------------------------------- /Interactivity.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | High-level Concepts of Interactive and Web Graphics

High-level Concepts of Interactive and Web Graphics

Duncan Temple Lang

University of California at Davis

Department of Statistics


4 | Goals of the session are 5 |

  1. to introduce you to a variety of tools that you can use immediately to create interesting displays, dashboards, etc.

  2. to explain the architecture involved so that you can go further than simple use of the tools

6 |

7 | These tools provide "instant" gratification (once you learn the basics). 8 | However, it is very important that you focus on using the tools to present the data clearly 9 | and offer insight for the viewer. It is easy to produce bad displays, and to focus on the "glossy", "moving" 10 | things. 11 |

12 | Interactive displays are very different from static plots. 13 | When we create a static plot, we make decisions about what is in the plot 14 | or not, what to emphasize. We are in charge of what the viewer sees. 15 | For an interactive plot, we still get to make many decisions 16 | that limit what the viewer can see. However, when the viewer 17 | sees the display, she can change it via the user controls we provide. 18 | We are providing the viewer with a process for exploring the information 19 | in the plot in her own way. 20 |

21 | Interactive plots are verging on software, and many are full-fledged 22 | pieces of software. Therefore, we need to incorporate best practices 23 | and considerations for both user interface (UI) and user experience 24 | (UX). We have seen best practices and considerations for static 25 | plots. These also (generally) apply to interactive plots, and we also 26 | have to consider dynamic, interactive best practices. 27 |

28 | We need to 29 |

  1. consider what the viewer may want to do,

  2. handle errors

  3. provide feedback and suggestions

  4. use clear interfaces with documentation. Often they will not be intuitive to everyone.

30 |

31 | There are many ways to create interactive plots. It is somewhat of a 32 | wild-west out there. Things are converging and approaches are being 33 | integrated. There are still a lot of tradeoffs. While many of you 34 | will want to quickly create standard plots, others will want to create 35 | non-standard plots and will have to work harder as there may not be 36 | existing functions to create those plots. Regardless, it is helpful, 37 | if not very important, to understand the fundamentals of the 38 | mechanisms that make all of this possible and to be able to go below 39 | the high-level interfaces. 40 |

<aside> 41 | I'm a big believer in minimizing the discontinuity in programming when dealing with problems. 42 | In other words, I don't want to have a situation where it is easy 43 | to do one thing, but a slight variation in that means an entirely different approach and 44 | having to learn a new software system or computational model. 45 | For this reason, I like to know how things work and be able to use the primitives 46 | when we need to do something slightly outside of the norm. 47 | </aside>

48 | There are (at least) three differerent styles of interactive plots: 49 | 1) stand-alone displays that contain all the information for their own interactivity (e.g. tooltips, animation in SVG) 50 | 2) displays that have client-side (JavaScript) code which updates the plot at viewing time 51 | 3) displays that need computations to be done at viewing time that can't be done in the client's browser, e.g. need to come back to R. 52 |

53 | When we are on our own machine, we don't need to care much about these distinctions. 54 | When we publish displays for other people to view, we have to consider some issues. 55 |

56 | If we are displaying data that cannot be explicitly shared in totality with viewers (for confidentiality reason or simply size of the 57 | data), but we can show summary plots, then we have to have any computations that update the display done on a server, not in each client's browser. 58 | 59 |

60 | The server does not run arbitrary code, but there are security issues that we need to be aware of. 61 | Running R on a server requires some care to ensure that people cannot inject code to expose information 62 | on the server, or delete files, or simply keeps the server busy so that other requests cannot be processed. 63 | If you build something popular, the demands on the server may be many. 64 | For personal use, or internally within an institution, this is probably not an issue. 65 |

66 | The more we can do in the client's browser, the lower the latency/delay waiting for results. 67 | Perhaps, the initial display of the page is delayed however. 68 | Ideally, display the initial page rapidly and asynchronously download additional elements 69 | we need (e.g. data for further plots). 70 |

71 | We're going to look under the hood so that you can learn how 72 | you can go further than the basics. 73 |

74 | Different Architectures for Interactive Plots 75 |

  1. Use an R graphics device with locator() or setGraphicsEventHandlers()

  2. PNG/JPEG files and image maps (very old)

  3. Create plots in R to, e.g., SVG, with annotations to provide event handlers, animations. 76 |

    1. RSVGTipsDevice

    2. svg() graphics device and then post-process the SVG content to add tooltips, animations, event handlers - SVGAnnotation

    3. Add SVG content to R objects in grid plot and generate SVG - gridSVG

    77 |

  4. Within R, create JavaScript, HTML code that will create the plot in the Web browser when loaded

  5. Create HTML document whose sub-contents will be updated at

78 |

79 | Creating object-based pots where the elements in the plot is quite different 80 | from the R style of graphics. 81 | We can change the characteristics of an element and it will be immediately updated. 82 |

83 | Object-based displays are problematic as the number of elements grows. 84 | This is true of vectorized plots also. 85 | Instead of having a fixed number of pixels based on the dimensions 86 | of the raster image, object-based plots have as many elements as 87 | there are observations (or more). 88 |

89 | If you know R, it may be easier to create HTML, JavaScript code, etc. in R. 90 | Programmatically generating content is a good idea when it removes repetition 91 | (e.g. creating checkboxes for 100 senators) or we want to reproduce this in different ways. 92 | However, it adds an additional layer between the output we create and the input that creates it. 93 | This can make it difficult to create the final document we actually want. 94 | Furthermore, it often complicates debugging both the page generation and also 95 | the run-time behavior of the page. This is because we have to fully understand 96 | how and what the layer is generating. 97 |

98 | Client-server code is hard to debug since there are two agents involved. 99 | We can run the R shiny server interactively and catch errors. 100 |

101 |

102 | http://timelyportfolio.github.io/gridSVG_intro/
103 | 
104 | 
105 | Linked plots
106 | Brushing
107 | 
108 | 
109 | animation 
110 |   Simple sequence of images
111 |   Object-based animation.
112 | 
113 | 
114 | 
115 | Basics of Stand-alone
116 |   tooltips
117 |   highlight (e.g. a point, a line)
118 | 
119 | 
120 | Off-The-Shelf Approaches
121 | 
122 | googleVis
123 | https://developers.google.com/chart/
124 | 
125 | 
126 | 
127 | 
128 | Maps
129 |   chloropleth maps. Good choice of colors vital.
130 | 
131 |   Google Earth
132 |     allows the viewer to add/remove other elements/layers, control time window, 
133 | 
134 | RgoogleMaps
135 | ggmap
136 | 
137 | rworldmap, rworldxtra
138 | 
139 |  par(mar = c(0, 0, 0, 0))
140 |  plot(getMap("li"))
141 | 
142 | 
143 | plotKML package
144 | 
145 | 
146 | Linked maps
147 |   file:///Users/duncan/Projects/NSFWorkshops/Visualization/maps/DistributionsMap.html
148 | 
149 | 
150 | 
151 | 
152 | 
153 | HTML, CSS, JavaScript
154 |  www.w3schools.com
155 | 
156 | 
157 | 
158 | ExcitedRW:  Click on a boxplot of timings, show code corresponding to that implementation.
159 | 
160 | 
161 | 
162 | 
163 | 
164 | 
165 | 
166 | D3
167 | /Users/duncan/Projects/Visualization
168 | 

169 |

170 | -------------------------------------------------------------------------------- /Interactivity.xml: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | High-level Concepts of Interactive and Web Graphics 5 | 6 | DuncanTemple Lang 7 | University of California at Davis 8 | Department of Statistics 9 | 10 | 11 | 12 | 13 | 14 | 15 | Goals of the session are 16 |
    17 |
  1. to introduce you to a variety of tools that you can use immediately to create interesting displays, dashboards, etc.
  2. 18 |
  3. to explain the architecture involved so that you can go further than simple use of the tools
  4. 19 |
20 |
21 | 22 | 23 | These tools provide "instant" gratification (once you learn the basics). 24 | However, it is very important that you focus on using the tools to present the data clearly 25 | and offer insight for the viewer. It is easy to produce bad displays, and to focus on the "glossy", "moving" 26 | things. 27 | 28 | 29 | 30 | Interactive displays are very different from static plots. 31 | When we create a static plot, we make decisions about what is in the plot 32 | or not, what to emphasize. We are in charge of what the viewer sees. 33 | For an interactive plot, we still get to make many decisions 34 | that limit what the viewer can see. However, when the viewer 35 | sees the display, she can change it via the user controls we provide. 36 | We are providing the viewer with a process for exploring the information 37 | in the plot in her own way. 38 | 39 | 40 | 41 | Interactive plots are verging on software, and many are full-fledged 42 | pieces of software. Therefore, we need to incorporate best practices 43 | and considerations for both user interface (UI) and user experience 44 | (UX). We have seen best practices and considerations for static 45 | plots. These also (generally) apply to interactive plots, and we also 46 | have to consider dynamic, interactive best practices. 47 | 48 | 49 | We need to 50 |
    51 |
  1. consider what the viewer may want to do,
  2. 52 |
  3. handle errors
  4. 53 |
  5. provide feedback and suggestions
  6. 54 |
  7. use clear interfaces with documentation. Often they will not be intuitive to everyone.
  8. 55 |
56 |
57 | 58 | 59 | There are many ways to create interactive plots. It is somewhat of a 60 | wild-west out there. Things are converging and approaches are being 61 | integrated. There are still a lot of tradeoffs. While many of you 62 | will want to quickly create standard plots, others will want to create 63 | non-standard plots and will have to work harder as there may not be 64 | existing functions to create those plots. Regardless, it is helpful, 65 | if not very important, to understand the fundamentals of the 66 | mechanisms that make all of this possible and to be able to go below 67 | the high-level interfaces. 68 | 69 | 70 | 78 | 79 | 80 | 81 | There are (at least) three differerent styles of interactive plots: 82 | 1) stand-alone displays that contain all the information for their own interactivity (e.g. tooltips, animation in SVG) 83 | 2) displays that have client-side (JavaScript) code which updates the plot at viewing time 84 | 3) displays that need computations to be done at viewing time that can't be done in the client's browser, e.g. need to come back to R. 85 | 86 | 87 | 88 | When we are on our own machine, we don't need to care much about these distinctions. 89 | When we publish displays for other people to view, we have to consider some issues. 90 | 91 | 92 | 93 | If we are displaying data that cannot be explicitly shared in totality with viewers (for confidentiality reason or simply size of the 94 | data), but we can show summary plots, then we have to have any computations that update the display done on a server, not in each client's browser. 95 | make this clearer about which computations need to be done on the server 96 | 97 | 98 | 99 | The server does not run arbitrary code, but there are security issues that we need to be aware of. 100 | Running R on a server requires some care to ensure that people cannot inject code to expose information 101 | on the server, or delete files, or simply keeps the server busy so that other requests cannot be processed. 102 | If you build something popular, the demands on the server may be many. 103 | For personal use, or internally within an institution, this is probably not an issue. 104 | 105 | 106 | 107 | The more we can do in the client's browser, the lower the latency/delay waiting for results. 108 | Perhaps, the initial display of the page is delayed however. 109 | Ideally, display the initial page rapidly and asynchronously download additional elements 110 | we need (e.g. data for further plots). 111 | 112 | 113 | 114 | We're going to look under the hood so that you can learn how 115 | you can go further than the basics. 116 | 117 | 118 | 119 | 120 | Different Architectures for Interactive Plots 121 |
    122 |
  1. Use an R graphics device with locator() or setGraphicsEventHandlers()
  2. 123 |
  3. PNG/JPEG files and image maps (very old)
  4. 124 |
  5. Create plots in R to, e.g., SVG, with annotations to provide event handlers, animations. 125 |
      126 |
    1. RSVGTipsDevice
    2. 127 |
    3. svg() graphics device and then post-process the SVG content to add tooltips, animations, event handlers - SVGAnnotation
    4. 128 |
    5. Add SVG content to R objects in grid plot and generate SVG - gridSVG
    6. 129 |
    130 |
  6. 131 | 132 |
  7. Within R, create JavaScript, HTML code that will create the plot in the Web browser when loaded
  8. 133 | 134 |
  9. Create HTML document whose sub-contents will be updated at
  10. 135 |
136 |
137 | 138 | 139 | Creating object-based pots where the elements in the plot is quite different 140 | from the R style of graphics. 141 | We can change the characteristics of an element and it will be immediately updated. 142 | 143 | 144 | 145 | Object-based displays are problematic as the number of elements grows. 146 | This is true of vectorized plots also. 147 | Instead of having a fixed number of pixels based on the dimensions 148 | of the raster image, object-based plots have as many elements as 149 | there are observations (or more). 150 | 151 | 152 | 153 | 154 | 155 | 156 | If you know R, it may be easier to create HTML, JavaScript code, etc. in R. 157 | Programmatically generating content is a good idea when it removes repetition 158 | (e.g. creating checkboxes for 100 senators) or we want to reproduce this in different ways. 159 | However, it adds an additional layer between the output we create and the input that creates it. 160 | This can make it difficult to create the final document we actually want. 161 | Furthermore, it often complicates debugging both the page generation and also 162 | the run-time behavior of the page. This is because we have to fully understand 163 | how and what the layer is generating. 164 | 165 | 166 | 167 | Client-server code is hard to debug since there are two agents involved. 168 | We can run the R shiny server interactively and catch errors. 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | http://timelyportfolio.github.io/gridSVG_intro/ 177 | 178 | 179 | Linked plots 180 | Brushing 181 | 182 | 183 | animation 184 | Simple sequence of images 185 | Object-based animation. 186 | 187 | 188 | 189 | Basics of Stand-alone 190 | tooltips 191 | highlight (e.g. a point, a line) 192 | 193 | 194 | Off-The-Shelf Approaches 195 | 196 | googleVis 197 | https://developers.google.com/chart/ 198 | 199 | 200 | 201 | 202 | Maps 203 | chloropleth maps. Good choice of colors vital. 204 | 205 | Google Earth 206 | allows the viewer to add/remove other elements/layers, control time window, 207 | 208 | RgoogleMaps 209 | ggmap 210 | 211 | rworldmap, rworldxtra 212 | 213 | par(mar = c(0, 0, 0, 0)) 214 | plot(getMap("li")) 215 | 216 | 217 | plotKML package 218 | 219 | 220 | Linked maps 221 | file:///Users/duncan/Projects/NSFWorkshops/Visualization/maps/DistributionsMap.html 222 | 223 | 224 | 225 | 226 | 227 | HTML, CSS, JavaScript 228 | www.w3schools.com 229 | 230 | 231 | 232 | ExcitedRW: Click on a boxplot of timings, show code corresponding to that implementation. 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | D3 241 | /Users/duncan/Projects/Visualization 242 | 243 | 244 |
245 | -------------------------------------------------------------------------------- /JSEg/0_a1e99_9dabddb2_L.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsidavis/Visualization/7b595a9f8b2671504ead46db32f103520f9b0d44/JSEg/0_a1e99_9dabddb2_L.jpg -------------------------------------------------------------------------------- /JSEg/260px-Okapi2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsidavis/Visualization/7b595a9f8b2671504ead46db32f103520f9b0d44/JSEg/260px-Okapi2.jpg -------------------------------------------------------------------------------- /JSEg/440px-Lowland_Streaked_Tenrec,_Mantadia,_Madagascar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsidavis/Visualization/7b595a9f8b2671504ead46db32f103520f9b0d44/JSEg/440px-Lowland_Streaked_Tenrec,_Mantadia,_Madagascar.jpg -------------------------------------------------------------------------------- /JSEg/Data.js: -------------------------------------------------------------------------------- 1 | var data = { 2 | "Hummingbird Moth": [ 'http://newsimg.bbc.co.uk/media/images/47868000/jpg/_47868651_001547179-1.jpg', "The hummingbird moth ...."], 3 | "Okapi" : [ "260px-Okapi2.jpg", "An Okapi is a type of" ], 4 | "Tenrec": ["440px-Lowland_Streaked_Tenrec,_Mantadia,_Madagascar.jpg", "Tenrecs are Wikipedia."] 5 | }; -------------------------------------------------------------------------------- /JSEg/Eg.js: -------------------------------------------------------------------------------- 1 | function toggleRightImage(obj) 2 | { 3 | toggleElement(document.getElementById('img2')); 4 | } 5 | 6 | function toggleElement(img) 7 | { 8 | console.log(img + " " + img.style); 9 | var style = img.style; 10 | if(style.length == 0 || style.display == 'inline') 11 | img.style.display = 'none'; 12 | else 13 | img.style.display = 'inline'; 14 | } 15 | 16 | 17 | function changeImage(obj) 18 | { 19 | var img = document.getElementById('img1'); 20 | img.src = obj.value; 21 | 22 | if(data) { 23 | showAnimalText(obj.value); 24 | } 25 | } 26 | 27 | function showAnimalText(img) 28 | { 29 | var p = document.getElementById('announce') 30 | for(var key in data) { 31 | var obj = data[key]; 32 | if(obj[0] == img) { 33 | alert('key ' + key + " " + obj[1]); 34 | p.innerHTML = obj[1]; 35 | break; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /JSEg/eg.css: -------------------------------------------------------------------------------- 1 | .body { 2 | background: #FFF; 3 | margin-left: 3em; 4 | margin-right: 3em; 5 | font-family: Verdana, Arial, Helvetica, sans-serif; 6 | } 7 | 8 | div.note { 9 | border: black 1pt solid; 10 | background: lightgray; 11 | margin: 30px 30px 30px 30px; 12 | } 13 | 14 | .hidden { 15 | visibility: hidden; 16 | } -------------------------------------------------------------------------------- /JSEg/jsAutoEg.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Example of JavaScript in HTML 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Illustraing JavaScript Code in HTML

12 |
13 |

14 | This is very similar to the display in jsEg.html, 15 | but there are important differences. 16 |

21 | 22 | 23 |

24 |

25 | We put information about each animal and its image into an "associative array" 26 | or named-element container in JavaScript. 27 | We have done this in an unintuitive manner with the text displayed in the optin as the key and then 28 | the information about the image and the text to show describing that animal. 29 | We should probably have used the file name/URL for the image as the key. 30 |

31 |

32 | When the animal changes, there is a relayout that resizes the two images and the layout of the page. 33 | This is a little jarring as the user interface controls move up or down. 34 | Similarly, this happens when we hide/show the right image. 35 | How can we fix this? 37 |

38 | 47 |

48 |

49 | The JavaScript code is stored in a separate file named Eg.js 50 |

51 |
52 | 53 |
54 | 55 |

56 |

57 | 58 | 59 | 61 | 62 |
63 | 64 |
65 | Change left image: 66 | 67 | 68 |
69 | Hide right image 70 |
71 | 72 | 81 | 82 | 83 |
84 |
Duncan Temple Lang 85 | <duncan@r-project.org>
86 | Last modified: Sat Apr 25 05:06:59 PDT 2015 87 | 88 | -------------------------------------------------------------------------------- /JSEg/jsEg.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Example of JavaScript in HTML 4 | 5 | 6 | 7 | 8 | 9 |

Illustraing JavaScript Code in HTML

10 |
11 |

12 | We create a simple HTML document that displays 13 | two images. 14 | The viewer can change the image on the left using a pull-down menu. 15 | She can hide and display the image on the right by toggling the checkbox. 16 |

17 |

18 | We create the HTML with a text editor. 19 | We'll display the two images in a table, but we could use CSS with float: left and float: right. 20 | The user-interface elements are within a form element, but this is not essential as we use 21 | JavaScript event handlers on each element. 22 | The two form elements are SELECT and an INPUT. 23 | We specify JavaScript a command(s) for the onchange attribute on each of these. 24 | The select element has several OPTION elements giving the items in the pull down menu. 25 | The value attribute of each OPTION gives the URL for the image, either a regular URL or a local 26 | file name. We use these as the value for the corresponding IMG element's src attribute. 27 |

28 |

29 | The JavaScript code is stored in a separate file named Eg.js 30 |

31 |

32 | The CSS file for this HTML document is in eg.css. 33 |

34 |
35 | 36 |
37 | 38 |

39 |

40 | 41 | 42 | 43 | 44 |
45 | 46 |
47 | Change left image: 48 | 53 |
54 | Hide right image 56 |
57 | 58 | 59 |
60 | See http://www.boredpanda.com/unusual-animals/ 61 | 62 |
63 |
Duncan Temple Lang 64 | <duncan@r-project.org>
65 | Last modified: Sat Apr 25 14:24:01 PDT 2015 66 | 67 | -------------------------------------------------------------------------------- /Networks/ggvisCalls.R: -------------------------------------------------------------------------------- 1 | source("utilFuns.R") 2 | 3 | library(ggvis) 4 | g = getFunctionNetwork("ggvis") 5 | 6 | # Which functions call which others 7 | # Two columns and lines from the left function to those on the right that it calls the right function 8 | 9 | 10 | -------------------------------------------------------------------------------- /Networks/ggvisFunctionNetwork.R: -------------------------------------------------------------------------------- 1 | source("utilFuns.R") 2 | 3 | 4 | g = getFunctionNetwork("ggvis") 5 | 6 | library(graph) 7 | library(igraph) 8 | 9 | gr = graphNEL(names(g), g, "directed") 10 | 11 | igr = igraph.from.graphNEL(gr) 12 | plot(igr) 13 | 14 | plot(igr, vertex.size = .75, edge.arrow.size = .2) 15 | # vertex.label = NA 16 | # See layout and igraph.plotting for more information. 17 | # http://igraph.org/r/doc/layout.html 18 | 19 | 20 | # Let's pare the graph down to remove some of the isolated nodes. 21 | # There are functions that are not called by anyother functions. 22 | 23 | notCalled = setdiff(names(g), unlist(g)) 24 | # Still have isolated nodes, e.g. add_data. 25 | # This is not exported and so not in the names of g. 26 | # But ggvis which is the only function that calls it gets excluded since no function calls it. 27 | notCalled = setdiff(notCalled, c("ggvis", "mark", grep("^(layer_|knit_print)", names(g), value = TRUE))) 28 | cg = g[ - match(notCalled, names(g))] 29 | cgr = graphNEL(names(cg), cg, "directed") 30 | 31 | 32 | icgr = igraph.from.graphNEL(cgr) 33 | pos = plot(icgr, vertex.size = .75, edge.arrow.size = .4, layout = layout.kamada.kawai, vertex.label.dist = .25) 34 | 35 | 36 | # Perhaps display the not-called functions on the sides of the plot. 37 | # can use par()$usr to get coordinates. 38 | 39 | # Exercise: How do we igraph to plot these for us? 40 | 41 | # Rgraphviz 42 | 43 | -------------------------------------------------------------------------------- /Networks/twoCols.R: -------------------------------------------------------------------------------- 1 | # Rearrange the information 2 | target = unlist(lapply(g, function(x) if(length(x)) x else NA)) 3 | src = unlist(mapply(function(id, x) rep(id, max(1, length(x))), names(g), g)) 4 | 5 | stopifnot(length(target) == length(src)) 6 | 7 | all = na.omit(unique(c(target, src))) 8 | 9 | d = data.frame(src = factor(src, levels = all), target = factor(target, levels = all)) 10 | 11 | m = do.call(cbind, lapply(d, as.integer)) 12 | library(MASS) 13 | parcoord(m) 14 | -------------------------------------------------------------------------------- /Networks/utilFuns.R: -------------------------------------------------------------------------------- 1 | library(codetools) 2 | 3 | # Allow to collect functions from other packages and then color code them based on where they come from. 4 | 5 | # Color the edges based on the number of calls. 6 | 7 | # Make this in D3 or with SVG annotations. 8 | 9 | getFunctionNetwork = 10 | function(pkg, within = TRUE) 11 | { 12 | if(!grepl(":", pkg)) 13 | pkg = paste("package", pkg, sep = ":") 14 | 15 | funs = getPackageFunctions(pkg) 16 | calls = lapply(funs, getCalledFuns, names(funs)) 17 | 18 | if(within) 19 | lapply(calls, intersect, names(funs)) 20 | else 21 | calls 22 | } 23 | 24 | getCalledFuns = 25 | function(f, knownFuns = character()) 26 | { 27 | vars = findGlobals(f, FALSE) 28 | # unique( c(vars$functions, intersect(vars$variables, knownFuns)) ) 29 | intersect(c(vars$functions, vars$variables), knownFuns) 30 | } 31 | 32 | getPackageFunctions = 33 | function(pkg) 34 | { 35 | ids = ls(pkg) 36 | isFun = sapply(ids, function(v) is.function(get(v, pkg))) 37 | 38 | ns = getNamespace(gsub(".*:", "", pkg)) 39 | funs = mget(ids[isFun], ns, ifnotfound = list(NULL)) # or inherits = TRUE 40 | funs[ ! sapply(funs, is.null) ] 41 | } 42 | -------------------------------------------------------------------------------- /OmegaTech.css: -------------------------------------------------------------------------------- 1 | @import "html.css"; 2 | 3 | BODY { 4 | background: #FFF; 5 | margin-left: 3em; /* # 1%; */ 6 | margin-right: 3em; /* #10%; */ 7 | font-family: Verdana, Arial, Helvetica, sans-serif; 8 | } 9 | 10 | H1 { 11 | color: red; 12 | } 13 | 14 | h2 { 15 | color: blue; 16 | } 17 | H3 { 18 | color: green; 19 | font-style: italic 20 | } 21 | 22 | .link { 23 | text-decoration: underline; 24 | } 25 | 26 | 27 | B.S, B.R, B.rvar { color: green; } 28 | B.object { color: red; } 29 | 30 | CODE { color: brown; font-family: Courier; } 31 | 32 | CODE.rstr, CODE.rint, CODE.rnum, CODE.rlog { color: black; font-family: Courier; } 33 | 34 | CODE.comment { color: red; } 35 | CODE.codeComment { color: red; } 36 | CODE.object { color: green; } 37 | CODE.keyword { color: darkgreen; font-style: italic; } 38 | 39 | CODE.sfunction { color: darkblue; } 40 | CODE.rfunction { background-color: #f0ffff; 41 | color: red; 42 | font-family: Courier; } 43 | 44 | CODE.s3class { background-color: #f0ffff; 45 | color: gray; 46 | } 47 | 48 | 49 | 50 | CODE.envvar { color: brown; } 51 | CODE.dir { color: blue; } 52 | 53 | CODE.file {color: green ; font-style: italic} 54 | CODE.shellScript, code.executable {color: blue ; font-style: italic} 55 | 56 | CODE.shellCmd {color: red} 57 | 58 | CODE.jclass { color: brown ; } 59 | 60 | CODE.class { color: red ; } 61 | 62 | CODE.method { color: red ; font-family: courier } 63 | 64 | CODE.JavaProperty { color: brown ; font-style: italic} 65 | 66 | CODE.makeVar { color: magenta ; font-style: italic } 67 | 68 | CODE.xsl-param { color: gray ; font-style: italic } 69 | 70 | PRE.xml { background-color: lightgray ; font-style: italic } 71 | 72 | 73 | DIV.rfunction { background-color: #f0ffff; color: red; } 74 | 75 | A.within-doc-rfunction { color: green; } 76 | 77 | DIV.literallayout { color: purple ; } 78 | 79 | PRE { color: brown ; padding: .5em;} 80 | PRE.Scode { color: red ; } 81 | PRE.S, PRE.rcode, PRE.exampleCode, div.r-commands { 82 | color: green; 83 | border: 1pt black; 84 | background-color: #f0ffff; 85 | padding: .5em 0; 86 | margin: .5em .5em .5em .5em; 87 | overflow: auto ; 88 | } 89 | PRE.C { color: #b22222 ; background-color: #e6e6fa; padding: .5em;} 90 | PRE.soutput, PRE.routput { 91 | color: blue ; 92 | clear: both; 93 | } 94 | PRE.cpp { color: #b22222 ; background-color: #e6e6fa; padding: .5em; } 95 | 96 | PRE.rerror { color: red ; 97 | background-color: #f0ffff; 98 | padding: .5em; 99 | } 100 | 101 | PRE.rwarning, PRE.swarning { color: blue ; background-color: #dcdcdc} 102 | 103 | B.cnull { color: grey; 104 | font-family: courier; 105 | } 106 | 107 | FONT.JavaPackage { font-family: sans-serif ; color: brown} 108 | FONT.JavaClass { font-family: sans-serif ; color: red} 109 | FONT.JavaInterface{ font-family: sans-serif ; color: olive} 110 | FONT.JavaMethod { font-family: sans-serif ; color: blue} 111 | FONT.JavaField { font-family: sans-serif ; color: orange} 112 | 113 | FONT.OmegaPackage { font-family: courier; font-size: larger ; color: brown} 114 | FONT.OmegaClass { font-family: courier; font-size: larger ; color: red} 115 | FONT.OmegaInterface{ font-family: courier; font-size: larger ; color: olive} 116 | FONT.OmegaMethod { font-family: courier; font-size: larger ; color: blue} 117 | FONT.OmegaField { font-family: courier; font-size: larger ; color: orange} 118 | 119 | FONT.file { font-family: courier ; color: navy} 120 | FONT.dir { font-family: courier ; color: blue} 121 | 122 | FONT.OMega { font-weight: bold; color: red} 123 | FONT.Omegahat { font-weight: bold; color: red} 124 | FONT.Java { font-weight: bold; color: red} 125 | FONT.CORBA { font-weight: bold; color: red} 126 | 127 | FONT.perlSub { font-weight: bold; color: blue} 128 | 129 | DIV.done { margin-left: 5%; 130 | padding-left: 30px; 131 | padding-right: 30px; 132 | } 133 | 134 | I.rslot { color: blue; font-family: courier;} 135 | I.relement { color: darkblue; font-family: courier;} 136 | 137 | code.arg { 138 | font-style: italic; 139 | } 140 | 141 | 142 | code.shellCommand { font-family: courier ; color: green;} 143 | 144 | I.note { color: red; 145 | background-color: lightgrey;} 146 | 147 | I.question { font-size: larger ; color: brown } 148 | 149 | 150 | TH { font-family: Verdana, Arial, Helvetica, sans-serif; } 151 | 152 | P.note { 153 | padding: 10pt; 154 | margin-left: -70pt; 155 | color: red; 156 | font-family: sans-serif; 157 | border: 1pt solid green; 158 | } 159 | 160 | 161 | PRE.shell { 162 | padding: 3pt; 163 | color: green; 164 | background-color: lightgray; 165 | } 166 | 167 | PRE.perl { 168 | padding: 3pt; 169 | color: #2f4f4f; 170 | background-color: #afeeee; 171 | font-family: courier sans-serif; 172 | } 173 | 174 | 175 | /* 176 | For displaying the name and a link to 177 | a function in an R XML document for a 178 | parameter that is specific to one of the functions 179 | being documented. 180 | */ 181 | A.funcArgRef { 182 | color: red; 183 | font-size: 75% 184 | } 185 | 186 | A.exampleIdentifier { 187 | color: green 188 | } 189 | 190 | 191 | DIV.r-code-chunk-refs-box { 192 | text-align: right; 193 | } 194 | 195 | A.r-code-chunk-name { 196 | color: darkgreen; 197 | } 198 | 199 | tr.trColNames > td { 200 | color: red; 201 | } 202 | 203 | tr.trColNames { 204 | color: red; 205 | } 206 | 207 | hr.rtopRule { 208 | color: blue; 209 | height: 0pt; 210 | } 211 | 212 | 213 | th.thRowName { 214 | color: blue; 215 | text-align: right; 216 | } 217 | 218 | iframe { 219 | border-width: 0; 220 | } 221 | 222 | 223 | font.xmlAttribute { 224 | color: red; 225 | font-style: italic; 226 | } 227 | 228 | 229 | code.pseudocode { 230 | color: blue; 231 | font-style: italic; 232 | font-weight: bold; 233 | font-family: courier; 234 | } 235 | 236 | 237 | div.data { 238 | background-color: lightgrey; 239 | } 240 | 241 | pre.data { 242 | font-family: courier; 243 | color: darkgrey; 244 | } 245 | 246 | 247 | /* space after an img in an incorrect admonition. */ 248 | div.admonImage img { 249 | padding-right: 5pt; 250 | } 251 | 252 | div.dynFigure { 253 | border-style: solid; 254 | border-color: grey; 255 | border-width: 2pt; 256 | padding: 3pt; 257 | } 258 | 259 | 260 | 261 | code.jsKeyword { 262 | 263 | } 264 | 265 | code.xpath-func { 266 | 267 | } 268 | 269 | code.xpath { 270 | 271 | } 272 | 273 | 274 | PRE.shCode { 275 | background: lightgray; 276 | border: 1pt solid black; 277 | border-radius: 10px; 278 | } 279 | 280 | PRE.shOutput { 281 | background: #B9D3EE; 282 | color: darkgreen; 283 | border: 1pt solid black; 284 | border-radius: 10px; 285 | } -------------------------------------------------------------------------------- /Packages.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

9 | 10 | 11 | 12 |
  • SVGAnnotation
  • 13 | 14 |
  • RKML
  • 15 |
  • plotKML
  • 16 | 17 |
  • ggvis
  • 18 | 19 |
  • networkD3
  • 20 |
  • htmlWidgets
  • 21 |
  • dygraph
  • 22 | 23 | 24 | 25 | 26 | 27 | 28 |
    29 |
    Duncan Temple Lang 30 | <duncan@r-project.org>
    31 | Last modified: Fri Apr 24 16:28:20 PDT 2015 32 | 33 | -------------------------------------------------------------------------------- /SVGAnnotation/housing.R: -------------------------------------------------------------------------------- 1 | load("housingFrequencies.rda") 2 | 3 | 4 | svg("housingMatplot.svg", width = 9) 5 | library(RColorBrewer) 6 | cols = brewer.pal(nrow(housingFrequencies), "Set1") 7 | matplot(t(housingFrequencies), type = "l", col = cols, lty = 1, xlab = "Bedrooms", ylab = "Number of houses", 8 | main = "House sales by number of bedrooms and county") 9 | legend("topright", legend = rownames(housingFrequencies), col = cols, lty = 1, lwd = 3) 10 | dev.off() 11 | -------------------------------------------------------------------------------- /SVGAnnotation/housingFrequencies.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsidavis/Visualization/7b595a9f8b2671504ead46db32f103520f9b0d44/SVGAnnotation/housingFrequencies.rda -------------------------------------------------------------------------------- /SVGAnnotation/live_scatterplot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | ABCDEFGHIJ 4 | -------------------------------------------------------------------------------- /SVGAnnotation/matplot.R: -------------------------------------------------------------------------------- 1 | library(SVGAnnotation) 2 | library(XML) 3 | 4 | load("housingFrequencies.rda") 5 | 6 | labels = rownames(housingFrequencies) 7 | 8 | doc = xmlParse("housingMatplot.svg") 9 | 10 | highlightMatplot(doc, NULL, 8, ids = paste0("series", seq(along = labels))) 11 | 12 | series = getMatplotSeries(doc) 13 | 14 | invisible(mapply(addToolTips, 15 | series, sprintf("%s %d", labels, rowSums(housingFrequencies)), 16 | MoreArgs = list(addArea = FALSE))) 17 | 18 | #XXX Not quite working. Doesn't recognize C and groups it with B. 19 | if(TRUE) { 20 | radioShowHide(doc, labels = labels, within = NA, checkboxCallback = "toggle") 21 | # Should be hidden. 22 | if(FALSE) 23 | invisible(mapply(function(node, id) 24 | addAttributes(node, id = id), series, sprintf("series%d", seq(along = series)))) 25 | } 26 | 27 | saveXML(doc, "live_matplot.svg") 28 | 29 | -------------------------------------------------------------------------------- /SVGAnnotation/matplot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /SVGAnnotation/scatterPlot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /SVGAnnotation/tooltips.R: -------------------------------------------------------------------------------- 1 | library(XML) 2 | library(SVGAnnotation) 3 | 4 | doc = xmlParse("scatterPlot.svg") 5 | addToolTips(doc, LETTERS[1:10]) 6 | saveXML(doc, "live_scatterplot.svg") 7 | 8 | -------------------------------------------------------------------------------- /Topics.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 12 | 13 |

    14 | 15 |
    16 |
    17 |
  • Networks/Graphs - nodes and edges
  • 18 |
    19 |
  • igraph 20 | 23 |
  • 24 | 25 | 29 | 30 |
  • Rgraphviz
  • 31 | 32 | 33 |
    34 |
  • Maps
  • 35 |
    36 | Two approaches. C 37 |
  • maps
  • 38 |
  • rworldmap
  • 39 |
  • RgoogleMaps
  • 40 |
  • ggmap
  • 41 |
  • OpenStreetMap
  • 42 | 43 |
  • leafletR
  • 44 | 58 |
    59 | 60 | 61 |

    Interaction and Animation

    62 | 63 |
    64 |
    65 |
  • Simple Animation
  • 66 |
    67 | 70 | 71 | 72 | 73 |
    74 |
  • Basics of HTML, CSS, JavaScript
  • 75 |
    76 | 90 | 91 |
    92 |
  • Rich interactive, object-based displays
  • 93 |
    94 | 97 | 98 | 99 |
    100 |
  • Google Charts API and the googleVis package
  • 101 |
    102 |
    103 | 108 |
    109 | 110 |
    111 |
  • rCharts
  • 112 |
    113 | 118 |
    119 | 120 | 121 |
    122 |
  • Making Interactive Plots using R Graphics
  • 123 |
    124 | 135 | 136 | 137 |
    138 |
  • ggvis
  • 139 |
    140 | 143 | 144 | 145 |
    146 |
  • Shiny and Dashboards
  • 147 |
    148 | 154 | 155 | 156 |
    157 |
  • D3 - Data Driven Documents
  • 158 |
    159 | 162 |
    163 | 164 | 165 | 166 |
    167 |
    Duncan Temple Lang 168 | <duncan@r-project.org>
    169 | Last modified: Sat Apr 25 07:47:06 PDT 2015 170 | 171 | -------------------------------------------------------------------------------- /ggvis/tooltips.R: -------------------------------------------------------------------------------- 1 | load("../shinyHousePrices/housing.rda") 2 | 3 | # prepare the data. We'll just look at Marin. 4 | marin = subset(housing, county == "Marin County", drop = TRUE) 5 | marin$city = droplevels(marin$city) 6 | 7 | 8 | library(lattice) 9 | xyplot(price/1000 ~ bsqft, marin, groups = city, auto.key = list(space = "right", column = 1, cex.text = .4), xlab = "Building Square Feet", ylab = "Price ($1000)") 10 | 11 | library(ggplot2) 12 | p = ggplot(marin, aes(bsqft/1000, price, color = city)) + geom_point() + labs(x = "Building Square Feet", y = "Price ($1000)") 13 | 14 | # 15 | library(ggvis) 16 | p = layer_points(ggvis(marin, ~ bsqft, ~ price/1000, fill = ~ city)) 17 | p = add_tooltip(p, function(d) paste(d$city, d$br, d$year, sep = ", ")) 18 | p 19 | 20 | 21 | # the function we pass to add_tooltip is only passed the columns in the plot!! 22 | # So we need to get a key variable passed in and then use this to subset the non-local variable marin 23 | # to get the additional columns. Mmmmmm. 24 | # Note the := when defining key. 25 | marin$id = 1:nrow(marin) 26 | p = layer_points(ggvis(marin), ~ bsqft, ~ price/1000, fill = ~ city, key := ~id) 27 | p = add_tooltip(p, function(d) { with(marin[d$id, ], paste(d$id, city, br, year, lsqft, sep = ", "))}) 28 | p 29 | 30 | # What about the outlier with a price of $15 million. 31 | # Lot square feet 32 | # 33 | # 8 acres. 34 | # Lucas valley road. 35 | # Lookup address on zillow. Could do it via the API from our Web Scraping 36 | 37 | 38 | # How can we then put this on a Web page for others to explore? 39 | # Compare to gridSVG/SVGAnnotation and using JS libraries to create the plots. 40 | -------------------------------------------------------------------------------- /googleVis/eg1.R: -------------------------------------------------------------------------------- 1 | library(googleVis) 2 | 3 | load("ldf.rda") 4 | 5 | # Documentation: 6 | # https://developers.google.com/chart/interactive/docs/gallery/annotationchart 7 | 8 | #obj = gvisAnnotationChart(ldf, "Date", "price", "company", options = list(width = "1000px" , height = "600px", gvis.listener.jscode = c(rangechange = "alert('got event');"))) 9 | 10 | 11 | obj = gvisAnnotationChart(ldf, "Date", "price", "company", 12 | options = list(width = 1000 , height = 600, 13 | gvis.listener.jscode = c(rangechange = "function(ev) { alert('got event: ' + ev['start'] + ' ' + event['end']); return(true);}"))) 14 | print(obj, file = "eg1.html") 15 | 16 | plot(obj) 17 | 18 | # In the event 19 | # call getVisibleChartRange() on the chart object to get the start and end or get it from the event itself. 20 | 21 | -------------------------------------------------------------------------------- /googleVis/eg2.R: -------------------------------------------------------------------------------- 1 | library(googleVis) 2 | # Same as eg1.R but show the annotations. 3 | load("ldf.rda") 4 | 5 | # Documentation: 6 | # https://developers.google.com/chart/interactive/docs/gallery/annotationchart 7 | 8 | #obj = gvisAnnotationChart(ldf, "Date", "price", "company", options = list(width = "1000px" , height = "600px", gvis.listener.jscode = c(rangechange = "alert('got event');"))) 9 | 10 | source("getMSEvents.R") 11 | 12 | # We had width = "1000px". This caused the plot to be very narrow. 13 | # The debugging tools in the browser identified this problem as unparseable. 14 | obj = gvisAnnotatedTimeLine(ldf, "Date", "price", "company", annotationvar = "ann", 15 | options = list(width = 1000 , height = 600, displayAnnotations = TRUE, annotationsWidth = 15, 16 | gvis.listener.jscode = c(rangechange = "function(ev) { alert('got event: ' + ev['start'] + ' to ' + ev['end']); return(true);}"))) 17 | 18 | 19 | print(obj, file = "eg2.html") 20 | 21 | #plot(obj) 22 | 23 | 24 | -------------------------------------------------------------------------------- /googleVis/getMSEvents.R: -------------------------------------------------------------------------------- 1 | library(XML) 2 | tt = readHTMLTable("http://en.wikipedia.org/wiki/Timeline_of_Microsoft_Windows", which = 2, stringsAsFactors = FALSE) 3 | ev.date = as.Date(tt$Date, "%d %B %Y") 4 | 5 | ldf$ann = rep(as.character(NA), nrow(ldf)) 6 | i = match(ev.date, ldf$Date, 0) 7 | ldf$ann[i] = tt[[2]][i != 0] 8 | 9 | -------------------------------------------------------------------------------- /googleVis/googleVis.R: -------------------------------------------------------------------------------- 1 | library("googleVis") 2 | 3 | source("ldf.R") 4 | 5 | plot( gvisAnnotatedTimeLine(ldf, "Date", "price", "company", options = list(width = "1000px" , height = "600px"))) 6 | 7 | 8 | obj = gvisAnnotatedTimeLine(ldf, "Date", "price", "company", options = list(width = "1000px" , height = "600px", gvis.listener.jscode = "alert('got event');")) 9 | plot(obj) 10 | 11 | print(obj, file = "eg.html") 12 | 13 | 14 | obj = gvisAnnotationChart(ldf, "Date", "price", "company", options = list(width = "1000px" , height = "600px", gvis.listener.jscode = c(rangechange = "alert('got event');"))) 15 | print(obj, file = "eg.html") 16 | 17 | 18 | # Many available options. 19 | # https://developers.google.com/chart/interactive/docs/gallery/annotatedtimeline#Configuration_Options 20 | 21 | # How do we set the dimensions? 22 | plot( gvisAnnotatedTimeLine(ldf, "Date", "price", "company", options = list(width = "1000px" , height = "600px"))) 23 | 24 | # known dates with events 25 | # Annotation variable 26 | # annotationvar 27 | # has to be a column in the data frame - to match the dates. 28 | # So we give the name of the variable, not the annotations themselves. 29 | # 30 | 31 | plot( gvisAnnotatedTimeLine(ldf, "Date", "price", "company", annotationvar = "ann", options = list(width = "1000px" , height = "600px", displayAnnotations = TRUE))) 32 | #XXX Issue with size of the display now. 33 | 34 | # 35 | # add general JS events 36 | jscode <- "window.open('http://en.wikipedia.org/wiki/' 37 | + data.getValue(chart.getSelection()[0].row,0)); " 38 | #gvis.listener.jscode=jscode 39 | options=list(gvis.listener.jscode = jscode) 40 | plot(obj) 41 | 42 | 43 | ################ 44 | if(FALSE) { 45 | library(googleVis) 46 | demo(WorldBank) 47 | } 48 | 49 | 50 | ################### 51 | if(FALSE) { 52 | fargo <- read.csv("fargoTemps2014.csv", colClasses = c("Date", "integer", "integer")) 53 | mychart <- gvisLineChart(fargo, options=list(gvis.editor="Edit this chart", width=1000, height=600)) 54 | plot(mychart) 55 | } 56 | -------------------------------------------------------------------------------- /googleVis/ldf.R: -------------------------------------------------------------------------------- 1 | # http://finance.yahoo.com/q/hp?s=GOOG+Historical+Prices 2 | 3 | data = lapply(c(google = "google.csv", yahoo = "yahoo.csv", microsoft = "microsoft.csv"), read.csv, stringsAsFactors = FALSE) 4 | 5 | data = lapply(data, function(x) { x$Date = as.Date(x$Date, "%Y-%m-%d"); x}) 6 | 7 | #max(sapply(data, function(x) min(x$Date))) 8 | n = max(sapply(data, nrow)) 9 | close = lapply(data, function(d, n) c( d$Close, rep(NA, n - nrow(d))), n) 10 | 11 | df = as.data.frame(close) 12 | df$Date = data[[ which.max(sapply(data, nrow)) ]] $Date 13 | df = as.data.frame(df)[, c(4, 1:3)] 14 | plot( gvisLineChart(df) ) 15 | 16 | 17 | 18 | # 19 | ldf = data.frame(Date = rep(df$Date, 3), 20 | price = unlist(df[, c("microsoft", "google", "yahoo")]), 21 | company = rep(c("microsoft", "google", "yahoo"), each = nrow(df))) 22 | -------------------------------------------------------------------------------- /googleVis/ldf.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsidavis/Visualization/7b595a9f8b2671504ead46db32f103520f9b0d44/googleVis/ldf.rda -------------------------------------------------------------------------------- /html.css: -------------------------------------------------------------------------------- 1 | FONT.htmlTag { color: red ; font-style: italic } 2 | 3 | FONT.htmlAttribute { font-weight: bold } 4 | 5 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

    Data Visualization Workshop

    9 |

    April 25th, UC Davis

    10 | 11 |

    12 | Git Repository: git clone https://github.com/dsidavis/Visualization.git 13 |

    14 |

    15 | Or individual files from links on this and sub-pages. 16 |

    17 | 18 |

    19 | Videos of the workshop 20 |

    21 | 22 | 32 | 33 | 34 |

    35 | Instructors: Deborah Nolan (UC Berkeley) and Duncan Temple Lang (UC Davis) 36 | 37 |


    38 | Sponsored by: 39 | 46 | 47 | 48 |
    49 |
    Duncan Temple Lang 50 | <duncan@r-project.org>
    51 | Last modified: Tue Aug 25 14:54:22 PDT 2015 52 | 53 | -------------------------------------------------------------------------------- /rCharts/barChart.R: -------------------------------------------------------------------------------- 1 | library(rCharts) 2 | print(load("../shinyHousePrices/housing.rda")) 3 | 4 | housingFrequencies = table(housing$county, housing$br) 5 | d = data.frame( county = rep(rownames(housingFrequencies), ncol(housingFrequencies)), 6 | bedroom = factor(as.character( rep(colnames(housingFrequencies), each = nrow(housingFrequencies)))), 7 | counts = as.integer(housingFrequencies)) 8 | 9 | p <- nPlot(counts ~ county, group = "bedroom", data = d, type = "multiBarChart") 10 | print(p) 11 | p$print("chart3") 12 | 13 | save(housingFrequencies, file = "../SVGAnnotation/housingFrequencies.rda") 14 | # What about an alternative representation 15 | # dotplot/matplot in SVGAnnotation/housing.R 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /rCharts/egSmall.R: -------------------------------------------------------------------------------- 1 | # Stock prices from Google, Microsoft and Yahoo 2 | load("../googleVis/ldf.rda") 3 | 4 | # Get the data from the start of the most recent time series to now. 5 | start = max(with(ldf, by(ldf, company, function(x) min(x$Date[ !is.na(x$price)])))) 6 | class(start) = "Date" 7 | 8 | ldf.all = ldf[ldf$Date >= start, ] 9 | 10 | 11 | library(rCharts) 12 | ldf.all$Date_str = as.character(ldf.all$Date) 13 | m1 <- mPlot(x = "Date_str", y = c("microsoft", "yahoo", "google"), type = "Line", data = ldf) 14 | -------------------------------------------------------------------------------- /rCharts/maps.R: -------------------------------------------------------------------------------- 1 | library(rCharts) 2 | 3 | 4 | load("../shinyHousePrices/housing.rda") 5 | 6 | map <- Leaflet$new() 7 | map$setView(c(37.8717, -122.27), zoom = 8) 8 | countyCoords = 9 | list(Sonoma = c(38.288, -122.4589), 10 | Napa = c(38.3047, -122.2989), 11 | Alameda = c(37.7561, -122.2744), 12 | "Contra Costa" = c(37.9300, -121.9500), 13 | "San Mateo" = c(37.5542, -122.3131), 14 | "Marin" = c(38.0400, -122.7400), 15 | "San Francisco" = c(37.7833, -122.4167), 16 | Solano = c(38.270, -121.9400), 17 | "Santa Clara" = c(37.3600, -121.9700)) 18 | 19 | invisible(mapply(function(id, coords, pricePerSqft) 20 | map$marker(coords, bindPopup = sprintf("

    %s: price/square foott = %d

    ", id, pricePerSqft)), 21 | names(countyCoords), countyCoords, 22 | as.integer(by(housing, housing$county, function(d) median(d$price/d$bsqft, na.rm = TRUE))))) 23 | 24 | #map$print("chart7") # for generate the file 25 | print(map) # need to explicitly print it in case we source() this file. 26 | -------------------------------------------------------------------------------- /rCharts/rCharts.R: -------------------------------------------------------------------------------- 1 | library(rCharts) 2 | data(economics, package = "ggplot2") 3 | econ <- transform(economics, date = as.character(date)) 4 | m1 <- mPlot(x = "date", y = c("psavert", "uempmed"), type = "Line", data = econ) 5 | m1$set(pointSize = 0, lineWidth = 1) 6 | m1$print("chart2") 7 | 8 | 9 | 10 | # df from googleVis.R - stock prices 11 | df$Date_str = as.character(df$Date) 12 | m1 <- mPlot(x = "Date_str", y = c("microsoft", "yahoo", "google"), type = "Line", data = df) 13 | 14 | 15 | -------------------------------------------------------------------------------- /shiny.html/server.R: -------------------------------------------------------------------------------- 1 | data(mtcars) 2 | 3 | shinyServer(function(input, output) { 4 | 5 | output$out <- renderText(paste("check:", input$on, "; radio", input$which)) 6 | 7 | # This should check if the variable exists 8 | i = reactive({ if(length(input$var) && input$var != "") pmatch(input$var, names(mtcars)) }) 9 | 10 | # if(!is.na(i())) 11 | output$plot <- renderPlot({ if(length(i() == 1)) { 12 | plot(density(mtcars[[ i() ]] )) 13 | if(length(input$on) && input$on != "off") 14 | rug(mtcars[[ i() ]]) 15 | }}) 16 | 17 | output$scatterplot <- renderPlot({ if(length(i() == 1)) { 18 | plot(mtcars[[ i() ]], mtcars$mpg, xlab = names(mtcars)[i()], ylab = "Miles Per Gallon") 19 | if(length(input$on) && input$on != "off") { 20 | rug(mtcars[[ i() ]]) 21 | rug(mtcars[[ "mpg" ]], side = 2) 22 | } 23 | }}) 24 | 25 | }) 26 | -------------------------------------------------------------------------------- /shiny.html/www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | My HTML 5 | 6 | 7 | 8 | 9 | 10 | 11 |

    My Own HTML Shiny Interface

    12 | 13 |

    14 | On/Off: 15 |
    16 | A 17 |
    18 | B 19 |

    20 | 21 |

    22 | Variable name: 23 |

    24 | 25 |
    26 | 
    27 | 28 |
    29 |
    30 |
    31 | 32 |
    33 |
    34 | 35 |
    36 |
    Duncan Temple Lang 37 | <duncan@r-project.org>
    38 | Last modified: Fri Apr 24 22:18:18 PDT 2015 39 | 40 | -------------------------------------------------------------------------------- /shiny0/server.R: -------------------------------------------------------------------------------- 1 | shinyServer(function(input, output) { 2 | 3 | output$text1 <- renderText({ 4 | paste("You have selected this", input$var, input$range[1]) 5 | }) 6 | 7 | } 8 | ) 9 | -------------------------------------------------------------------------------- /shiny0/ui.R: -------------------------------------------------------------------------------- 1 | shinyUI(fluidPage( 2 | titlePanel("censusVis"), 3 | 4 | sidebarLayout( 5 | sidebarPanel( 6 | helpText("Create demographic maps with 7 | information from the 2010 US Census."), 8 | 9 | selectInput("var", 10 | label = "Choose a variable to display", 11 | choices = c("Percent White", "Percent Black", 12 | "Percent Hispanic", "Percent Asian"), 13 | selected = "Percent White"), 14 | 15 | sliderInput("range", 16 | label = "Range of interest:", 17 | min = 0, max = 100, value = c(0, 100)) 18 | ), 19 | 20 | mainPanel( 21 | textOutput("text1") 22 | ) 23 | ) 24 | )) 25 | 26 | -------------------------------------------------------------------------------- /shiny1/260px-Okapi2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsidavis/Visualization/7b595a9f8b2671504ead46db32f103520f9b0d44/shiny1/260px-Okapi2.jpg -------------------------------------------------------------------------------- /shiny1/htmlContent.html: -------------------------------------------------------------------------------- 1 |

    2 | This is content that we write in a separate file. 3 | It is regular HTML 4 | with links and images . 5 |

    6 | 7 |

    8 | We can have tables and other elements: 9 |

    10 | 11 | 12 | 13 |
    ABCDEF
    12
    14 | 15 | 16 |
    17 |
    Duncan Temple Lang 18 | <duncan@r-project.org>
    19 | Last modified: Fri Apr 24 21:23:04 PDT 2015 20 | 21 | -------------------------------------------------------------------------------- /shiny1/server.R: -------------------------------------------------------------------------------- 1 | shinyServer(function(input, output) { 2 | 3 | output$out <- renderText(paste("starting at", input$date_start, "; ending at", input$date_end, list.files("../")[1])) 4 | 5 | }) 6 | -------------------------------------------------------------------------------- /shiny1/ui.R: -------------------------------------------------------------------------------- 1 | shinyUI(fluidPage( 2 | titlePanel("Getting Started - testing the forms"), 3 | 4 | sidebarLayout( 5 | sidebarPanel( 6 | dateInput("date_start", label = "Start", value = "2015-01-01"), 7 | dateInput("date_end", label = "Finish", value = "2015-01-02") 8 | # submitButton("go")# , label = "Go") 9 | ), 10 | mainPanel( 11 | h2("Output"), 12 | textOutput("out"), 13 | hr(), 14 | img(src = "260px-Okapi2.jpg"), # images don't seem to make it across to the Web server? 15 | hr(), 16 | includeHTML("htmlContent.html") 17 | 18 | ) 19 | ) 20 | )) 21 | -------------------------------------------------------------------------------- /shinyHousePrices/README: -------------------------------------------------------------------------------- 1 | What do we want to have for the viewer to explore? 2 | Without worrying excessively about design, we'll create a 3 | reasonably rich page/dashboard for the viewer to explore 4 | the SF Bay housing price data. 5 | 6 | UI 7 | 8 | plot of the map of the bay area with counties. 9 | Color code by price or number of houses sold. 10 | Ideally get the boundaries for the cities and use those rather than counties. 11 | Allow the viewer to change what we color by - median price or number of houses sold. 12 | 13 | Display density plots for price by city 14 | 15 | Display number of houses by week by county or city 16 | Allow the viewer to change the start and end dates. 17 | 18 | Plot of price by sqft for the included points. 19 | Tooltips 20 | 21 | Click on a point in a plot and see the corresponding entry from Zillow. 22 | 23 | Two scatter plots - click/mouse over point in one, see the points in the other. 24 | 25 | Checkboxes to add/remove counties/cities from the plots 26 | 27 | 28 | 29 | 30 | 31 | 32 | server 33 | load the data 34 | 35 | 36 | -------------------------------------------------------------------------------- /shinyHousePrices/housing.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dsidavis/Visualization/7b595a9f8b2671504ead46db32f103520f9b0d44/shinyHousePrices/housing.rda --------------------------------------------------------------------------------