Skip to content

Commit b435b53

Browse files
adding code from the Software Carpentries
1 parent 8fbc793 commit b435b53

1 file changed

Lines changed: 152 additions & 38 deletions

File tree

posts/2025-07-06-CSEE-intro-shiny/index.qmd

Lines changed: 152 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -30,107 +30,221 @@ There are many reasons to consider using Shiny for a project:
3030

3131
# Lists, functions & plotting in R
3232

33-
To ease into things, we will familiarize ourselves with the data that we will use to create a Shiny app together. At the same time, we will practice indexing **lists**, understanding **functions**, and **plotting**. By the end of this section, we will have made a plot that we will add interactivity to using Shiny.
33+
To ease into things, we will familiarize ourselves with the data that we will use to create a Shiny app together. At the same time, we will practice indexing **lists**, **plotting**, and making **functions**. By the end of this section, we will have made a plot that we will add interactivity to using Shiny.
3434

3535
## The data
36-
Today, we will be using a dataset on **networks of scientific collaboration** within the ecology and evolution departments of 25 Canadian universities. For each university, we have a count of the number of co-authored publications between each pair of ecology and evolution professors.
36+
We will be using a dataset on **networks of scientific collaboration** within the ecology and evolution departments of 25 Canadian universities. For each university, we have a count of the number of co-authored publications between each pair of ecology and evolution professors.
3737

3838
Lucas Eckert has kindly provided us with this data, and will be giving a talk on patterns of collaboration on Wednesday July 9th at 4:00pm (don't miss it!).
3939

40-
Let's explore the data a little:
40+
Let's explore the data:
4141

4242
```{r eval = FALSE}
4343
4444
## read in the data
45-
data <- readRDS("intra-list_clean.RDS")
45+
data <- readRDS("~/Documents/research-networks/intra-list_clean.RDS")
4646
4747
## what type of object are the data are stored in?
4848
class(data)
4949
50-
## how many elements are there?
51-
length(data)
50+
```
5251

53-
## are the elements named?
54-
names(data)
52+
As you can see, the data are stored in a **list** object.
53+
54+
In R lists act as containers. Unlike atomic vectors, the contents of a list are not restricted to a single mode and can encompass any mixture of data types. Lists are sometimes called generic vectors, because the elements of a list can by of any type of R object, even lists containing further lists. This property makes them fundamentally different from atomic vectors.
55+
56+
A list is a special type of vector. Each element can be a different type.
57+
58+
Create lists using ```list()```:
59+
60+
```{r eval = FALSE}
61+
62+
x <- list(5, "a", TRUE)
63+
x
5564
5665
```
5766

58-
As you can see, the data are stored in a **list** object. Each **element** of the list holds the data on collaboration within one university, and the names of the list tell us which university. Let's look at an element:
67+
The content of elements of a list can be retrieved by using double square brackets.
5968

6069
```{r eval = FALSE}
6170
62-
## index the list by element number:
63-
data[[1]]
71+
x[[1]]
72+
73+
```
74+
75+
Elements of a list can be named (i.e. lists can have the names attribute).
76+
77+
```{r eval = FALSE}
6478
65-
## or by element name:
66-
data[['McGill University']]
79+
names(x) <- c("number", "string", "boolean")
80+
names(x)
6781
68-
## store element in another object:
82+
```
83+
84+
And elements can be accessed by their names:
85+
86+
```{r eval = FALSE}
87+
88+
x[["string"]]
89+
x$string
90+
91+
```
92+
93+
In our ```data``` list, each **element** of the list stores the collaboration network within one university, and the **names** attribute tells which university.
94+
95+
96+
*Practice: try indexing ```data``` to get the collaboration network for McGill University*
97+
98+
```{r eval = FALSE}
99+
#| code-fold: true
100+
101+
## get the names of elements on our list
102+
names(data)
103+
104+
## access element containing data for McGill University
69105
network = data[['McGill University']]
70106
71-
## view:
107+
```
108+
109+
110+
Let's look at the format of the list elements:
111+
112+
```{r eval = FALSE}
113+
114+
## view the data:
72115
View(network)
73116
74117
```
75118

76-
The data for each university collaboration network are represented by a 2D matrix (similar to one used to represent species interactions) where rows and columns represent researchers and nodes contain the number of shared publications between two researchers.
119+
Each university collaboration network is represented by a 2D matrix (similar to one used to represent species interaction networks) where rows and columns represent researchers and cells contain the number of shared publications between two researchers.
120+
121+
## Plotting intra-university collaboration networks
122+
123+
Now that we understand the data's structure, we can begin making the plot for our Shiny app.
77124

125+
We are going to be using **functions** from the ```ggplot2``` package to create visualizations of data. Functions are predefined bits of code that automate more complicated actions. R itself has many built-in functions, but we can access many more by loading other packages of functions and data into R.
126+
127+
If you don't yet have this package installed, run this line of code:
128+
```{r eval = FALSE}
129+
130+
install.packages("ggplot2")
131+
132+
```
133+
134+
And load the package using the ```library()``` function:
78135
```{r eval = FALSE}
79136
137+
# load package
138+
library(ggplot2)
139+
140+
```
141+
Let's also load a dataset to practice making a plot with:
80142

143+
```{r eval = FALSE}
81144
145+
data("iris")
146+
82147
```
83148

84-
*maybe: indexing vectors?*
149+
ggplot2 is a powerful package that allows you to create complex plots from tabular data (data in a table format with rows and columns). The gg in ggplot2 stands for “grammar of graphics”, and the package uses consistent vocabulary to create plots of widely varying types. Therefore, we only need small changes to our code if the underlying data changes or we decide to make a box plot instead of a scatter plot. This approach helps you create publication-quality plots with minimal adjusting and tweaking.
85150

151+
ggplot plots are built step by step by adding new layers, which allows for extensive flexibility and customization of plots.
86152

87-
## Plotting intra-university collaboration networks
153+
We use the ```ggplot()``` function to create a plot. In order to tell it what data to use, we need to specify the data argument. An argument is an input that a function takes, and you set arguments using the ```=``` sign.
88154

89-
Now that we understand the data's structure, we can begin making a plot for our Shiny app.
155+
```{r eval = FALSE}
156+
ggplot(data = iris)
157+
158+
```
90159

91-
*maybe Jake's draw what you want to put in your shiny' thing here?*
160+
We get a blank plot because we haven’t told ```ggplot()``` which variables we want to correspond to parts of the plot. We do this using the ```mapping``` argument. We can specify the “mapping” of variables to plot elements, such as x/y coordinates, size, or shape, by using the ```aes()``` function.
92161

93-
We want our app to display the collaboration network for a university that the user selects. Let's make a plot using **ggplot2** and **????**.
94162

95163
```{r eval = FALSE}
96-
# load packages
97-
library(ggplot)
98-
library(???)
164+
165+
ggplot(data = iris, mapping = aes(x = Petal.Length, y = Petal.Width))
166+
167+
```
168+
Now we’ve got a plot with x and y axes corresponding to variables from the iris data. However, we haven’t specified how we want the data to be displayed. We do this using ```geom_``` functions, which specify the type of geometry we want, such as points, lines, or bars. We can add a ```geom_point()``` layer to our plot by using the + sign. We indent onto a new line to make it easier to read, and we have to end the first line with the ```+``` sign.
169+
170+
```{r eval = FALSE}
171+
172+
ggplot(data = iris, mapping = aes(x = Petal.Length, y = Petal.Width)) +
173+
geom_point()
174+
175+
```
176+
177+
We want our app to display the collaboration network for a university that the user of our Shiny app will select, so let's start by making a plot of the collaboration network for McGill University.
178+
179+
ggplot likes ```tidy``` data, where each row of the data is an observation and each column represents different variables describing that observation. Because our network data are not in this format, we need the help of another package called ```package``` to plot them. Let's install and load it:
180+
181+
```{r eval = FALSE}
182+
183+
install.packages("package")
184+
library(package)
99185
100186
## build a network plot
101-
ggplot(data = network,
102-
aes())
103-
#~~~~# INSERT ANDREW'S PLOT CODE HERE #~~~~#
187+
ggplot(data = network,
188+
aes())
189+
#~~~~# INSERT ANDREW'S PLOT CODE HERE #~~~~#
190+
191+
```
104192

105-
# While teaching:
106-
# -explain how ggplot works, build up network plot from Lucas's data
193+
If we only had one university's network to plot, we could stop here... but we have 24 others to plot. Let's wrap our code in a **function** so that we can repeat several operations with a single command.
194+
195+
You can write your own functions in order to make repetitive operations using a single command. Let’s start by defining our function ```plot_network``` and the input parameter(s) that the user will feed to the function. Afterwards you will define the operation that you desire to program in the body of the function within curly braces ```{ }```. Finally, you need to assign the result (or output) of your function in the ```return()``` statement.
196+
197+
```{r eval = FALSE}
198+
199+
plot_network = function(university, network_list) {
200+
201+
# ~~~~ operations to make our plot ~~~~~ #
107202
203+
return()
204+
}
205+
108206
```
109207

110-
Because we want to be able to create this plot for *every* university, let's wrap our code in a **function**.
208+
Our function will take two arguments: ```university``` (a string defining the name of the university to plot) and ```network_list``` (the list of collaboration networks). In the body of the function, we will index the ```network_list``` for the matrix data for the ```university```:
111209

112210
```{r eval = FALSE}
113211
114212
plot_network = function(university, network_list) {
213+
115214
## index the network list for the selected university
116215
matrix = network_list[[university]]
216+
217+
return()
218+
}
219+
220+
```
221+
222+
And the we will use that data to make our network plot, and return it using the return statement:
223+
224+
```{r eval = FALSE}
225+
226+
plot_network = function(university, network_list) {
227+
228+
## index the network list for the selected university
229+
matrix = network_list[[university]]
117230
118231
## build a network plot
119-
ggplot(data = network,
232+
plot = ggplot(data = network,
120233
aes())
121234
#~~~~# INSERT ANDREW'S PLOT CODE HERE #~~~~#
122235
123-
## return the plot
124236
return(plot)
125237
}
126238
127-
## call the function
128-
my_plot <- plot_network(university = "McGill University", network_list = data)
239+
```
240+
241+
*Practice: We can now call our function ```plot_network```. Using what you know about the arguments it needs, calling the function to make a plot of Trent University's collaboration network.*
129242

130-
# While teaching:
131-
# - explain what a function is, when they are useful, and how it is useful in this particular case (because we want to remake the same plot for each university)
132-
# - explain what arguments are - ours will be the name of the university
133-
# - show how to call function
243+
```{r eval = FALSE}
244+
#| code-fold: true
245+
246+
## call the function
247+
plot_network(university = "Trent University", network_list = data)
134248
135249
```
136250

0 commit comments

Comments
 (0)