The diamond model is not only a conceptual model of the common flow of participatory decisionmaking dynamics – it is also a tool you can use to design good group processes.
Have you ever been in a meeting that generated tons of ideas, but left you wondering whether any of it was going to go anywhere? That group process neglected to engage in convergent thinking. Or have you experienced a leader who hands down dictates with little discussion and expects everyone to just agree? They are missing out on the value of divergent and emergent thinking to generate creativity and buy-in.
A good group process will move through the diamond model and include all three types of thinking. Your process design, whether it’s for a single meeting, a multi-day workshop, or a longer collaborative process, should start by asking yourself, where are we now? What resources, people, and information do we have as our starting point? And where do we want to get to? What is our target end state – the deliverable or outcome we are trying to achieve?
Between those two points - your initial state and your target state - you can use one or multiple diamond shaped activities to productively move your group along. Each microstructure or game you use to engage the group can help to generate new ideas, explore them together, and converge on new insights or decisions. Those insights or decisions can then become the input for the next diamond, until you eventually reach your goal.
Those diamonds can vary in scale from mini-exercises that only take a few minutes to multi-day or longer processes. Once you start to recognize it, you’ll see the diamond model everywhere (or miss it when it’s lacking!).
NoteActivity: Small Group Exercise #1 - Where are we in the diamond?
Purpose: Identify where your group is in the diamond model right now and what stage you need to move through next.
Part 1 - Individual Reflection
Where would you say your group is right now in the diamond model?
Have you been leveraging the relevant thinking for the stage you are in (divergent, emergent, or convergent)?
Think about the next group work or decisionmaking task that lies ahead:
What stage(s) of the diamond will that work take you through and what kind of thinking will be needed?
Part 2 - Project Team Discussion
Identify a reporter, notetaker, and facilitator/timekeeper
Go around and share your answers to the prompt (1 min each)
Discuss and try to reach consensus about which stage(s) of the diamond model best match the next chunk of work you have ahead of you.
Set up stations with experts or innovators who can present information and engage discussion; group members circulate to learn, ask questions, or provide feedback
Keep the overall session short so that it’s not too fatiguing for presenters who will have to repeat their spiel many times
Draw out and contrast different perspectives from experts or interested parties
Experts with direct experience of the challenge at hand are invited to engage each other in conversation at the center of a circle; the rest of the group are audience to their conversation; audience and facilitator can suggest things for them to discuss
Avoid falling back on traditional formats where panelists talk to the audience rather than each other - the power of the fishbowl is the deep way in which the experts can engage each other
Horizon scanning / futures thinking
DE
Detect emerging trends, issues, or research opportunities
Define your scope; consult outside sources of data and expertise or brainstorm within the group to identify emerging trends, events, and weak signals of future change that may affect the question / topic you have defined
Set a timeframe that’s far enough out to encompass important uncertainties but not so far that forecasting becomes overly speculative
Engage everyone in making sense of profound challenges
Ask for a volunteer to host each table; use a talking object; Go-around 1: share what you are thinking, feeling, or doing about the theme or topic; Go-around 2: share your thoughts and feelings after having listened to others; Open conversation; Go-around 4: “takeaways”
Start with a clear question or prompt for discussion; Share the agreements and ask hosts to gently facilitate adherence
Make sense of past progress or experiences and decide on future actions
What - As a group, compile the facts and observations relevant to the context; So What - Reflect on the facts and their implications, identify patterns, generate hypotheses; Now What - Draw conclusions - What actions make sense?
Be firm in calling out opinions being passed off as facts in the What stage. Stick to what is observable.
Polling
EC
Rank alternatives
Decide how many votes per person; In person - use sticky dots; Virtually - use +1s in a google doc or a digital polling tool (e.g., Zoom, Mural, slido)
Before you start - clarify how you will use the results - are you gathering information or taking a vote to make a decision?
Feasibility x impact matrix
C
Compare alternatives
Discuss and agree on definitions for two criteria for evaluating ideas: feasibility of implementation and impact potential; Rate each idea against these two axes and map onto 2x2 grid
How you define the axes must be clear and agreed upon by everyone before you start
Use when ready to close a discussion or make a decision; Invite participants to rate their level of agreement with a proposal on a scale of 0-5; Five fingers means “absolute, total agreement or support” and a fist means “complete opposition”
If you have some 1s and 2s, more discussion is needed - ask them to explain their concerns or questions
Open discussion
DEC
Group inquiry, sensemaking, and/or decision-making
Clearly define the scope; set agreements for inclusive discussion; invite discussion about the topic at hand; capture ideas and questions; listen for when the group is ready to converge
Keep track of side topics (e.g. in a “bike rack”) and make time to come back to them, but don’t let them derail
Breakout groups
DEC
Engage everyone deeply; avoid groupthink
Define the scope and intended outcomes; set a time limit; assign roles (facilitator, notetaker, reporter); model what you want in the report out
Consider whether all groups should work with the same prompts or different aspects of the problem
Chart writing or whiteboarding
DEC
Reflect participant’s viewpoints back to the group
On a virtual or physical chart or whiteboard, capture key points in the discussion so everyone can see them
Use speakers’ own words; if the comment is long or complex, ask the speaker to give you a headline you can capture
Engage everyone in generating questions, ideas, and suggestions
Individual reflection; Pair share; Two pairs combine and share as a group of 4; Small groups share highlights with whole group
Emphasize novel ideas and distinctions for divergence; common themes and emerging insights for emergence and convergence
Round robin / go around
DEC
Hear from everyone; get starting positions on the table
Everyone answers the same prompt. Alternatives to going in order: each speaker calls on someone else after they have shared; popcorn-style - people share in the order that they feel moved to speak
Do not allow discussion until everyone has responded to the initial prompt
NoteActivity: Small Group Exercise #2 - Emergent thinking practice
Part 1 - Team Discussion & Co-Production
Assign a facilitator, notetaker and reporter
Read through the list of options and begin with the step that seems most useful for your team’s current needs. Work your way through as many of the steps as you can during the allotted time.
Create or refine a conceptual figure that captures how you are thinking about the system you are investigating
Once you are satisfied with your conceptual figure:
Outline your key questions
Map your planned analyses to them
How are you going to answer each question with data?
If you were working with the tools we suggested last time to start outlining your analysis, this should build from there
What are the ~3 key figures that would best illustrate your results?
Part 2 - Report Out
Share what you developed with the whole group!
After all groups have shared, offer suggestions to other groups and/or ask questions about the module.
Conditionals
Rather than finding and replacing content, you may want to create a new column based on the contents of a different column. In plain language you might phrase this as ‘if column X has [some values] then column Y should have [other values]’. These operations are called conditionals and are an important part of data wrangling.
If you only want your conditional to support two outcomes (as in an either/or statement) there are useful functions that support this. Let’s return to our Plum Island Ecosystems crab dataset for an example.
# Load tidyverselibrary(tidyverse)# Make a new colum with an either/or conditionalpie_crab_v2 <- pie_crab %>% dplyr::mutate(size_category =ifelse(test = (size >=15),yes ="big",no ="small"),.after = size) # Count the number of crabs in each categorypie_crab_v2 %>% dplyr::group_by(size_category) %>% dplyr::summarize(crab_ct = dplyr::n())
1
mutate makes a new column, ifelse is actually doing the conditional
# A tibble: 2 × 2
size_category crab_ct
<chr> <int>
1 big 179
2 small 213
If you have multiple different conditions you can just stack these either/or conditionals together but this gets cumbersome quickly. It is preferable to instead use a function that supports as many alternates as you want!
# Make a new column with several conditionalspie_crab_v2 <- pie_crab %>% dplyr::mutate(size_category = dplyr::case_when( size <=10~"tiny", size >10& size <=15~"small", size >15& size <=20~"big", size >20~"huge",TRUE~"uncategorized"),.after = size)# Count the number of crabs in each categorypie_crab_v2 %>% dplyr::group_by(size_category) %>% dplyr::summarize(crab_ct = dplyr::n())
1
Syntax is ‘test ~ what to do when true’
2
This line is a catch-all for any rows that don’t meet previous conditions
# A tibble: 4 × 2
size_category crab_ct
<chr> <int>
1 big 150
2 huge 28
3 small 178
4 tiny 36
Note that you can use functions like this one when you do have an either/or conditional if you prefer this format.
NoteActivity: Conditionals
In a script, attempt the following with the PIE crab data:
Create a column indicating when air temperature is above or below 13° Fahrenheit
Create a column indicating whether water temperature is lower than the first quartile, between the first quartile and the median water temp, between the median and the third quartile or greater than the third quartile
Hint
Consult the summary function output!
Uniting or Separating Columns
Sometimes one column has multiple pieces of information that you’d like to consider separately. A date column is a common example of this because particular months are always in a given season regardless of the specific day or year. So, it can be useful to break a complete date (i.e., year/month/day) into its component bits to be better able to access those pieces of information.
# Split date into each piece of temporal infopie_crab_v3 <- pie_crab_v2 %>% tidyr::separate_wider_delim(cols = date, delim ="-",names =c("year", "month", "day"),cols_remove =TRUE)# Check that outstr(pie_crab_v3)
1
‘delim’ is short for “delimiter” which we covered in the Reproducibility module
2
This argument specifies whether to remove the original column when making the new columns
While breaking apart a column’s contents can be useful, it can also be helpful to combine the contents of several columns!
# Re-combine data information back into datepie_crab_v4 <- pie_crab_v3 %>% tidyr::unite(col ="date",sep ="/", year:day, remove =FALSE)# Structure checkstr(pie_crab_v4)
1
This is equivalent to the ‘delim’ argument in the previous function
2
Comparable to the ‘cols_remove’ argument in the previous function
Note in this output how despite re-combining data information the column is listed as a character column! Simply combining or separating data is not always enough so you need to really lean into frequent data structure checks to be sure that your data are structured in the way that you want.
Joining Data
Often the early steps of a synthesis project involve combining the data tables horizontally. You might imagine that you have two groups’ data on sea star abundance and–once you’ve synonymized the column names–you can simply ‘stack’ the tables on top of one another. Slightly trickier but no less common is combining tables by the contents of a shared column (or columns). Cases like this include wanting to combine your sea star table with ocean temperature data from the region of each group’s research. You can’t simply attach the columns because that assumes that the row order is identical between the two data tables (and indeed, that there are the same number of rows in both to begin with!). In this case, if both data tables shared some columns (perhaps “site” and coordinate columns) you can use joins to let your computer match these key columns and make sure that only appropriate rows are combined.
Because joins are completely dependent upon the value in both columns being an exact match, it is a good idea to carefully check the contents of those columns before attempting a join to make sure that the join will be successful.
# Create a fish taxonomy dataframe that corresponds with the earlier fish dataframefish_tax <-data.frame("species"=c("salmon", "bass", "halibut", "eel"),"family"=c("Salmonidae", "Serranidae", "Pleuronectidae", "Muraenidae"))# Check to make sure that the 'species' column matches between both tablessupportR::diff_check(old = fish_ct$species, new = fish_tax$species)
# Use text replacement methods to fix that mistake in one tablefish_tax_v2 <- fish_tax %>% dplyr::mutate(species =gsub(pattern ="^eel$",replacement ="moray eel", x = species))# Re-check to make sure that fixed itsupportR::diff_check(old = fish_ct$species, new = fish_tax_v2$species)
1
The symbols around “eel” mean that we’re only finding/replacing exact matches. It doesn’t matter in this context but often replacing a partial match would result in more problems. For example, replacing “eel” with “moray eel” could make “electric eel” into “electric moray eel”.
Now that the shared column matches between the two two dataframes we can use a join to combine them! There are four types of join:
left/right join
full join (a.k.a. outer join)
inner join
anti join
You can learn more about the types of join here or here but the quick explanation is that the name of the join indicates whether the rows of the “left” and/or the “right” table are retained in the combined table. In synthesis work a left join or full join is most common (where you have your primary data in the left position and some ancillary/supplementary dataset in the right position).
# Let's combine the fish count and fish taxonomy informationfish_df <- fish_ct %>%# Actual join step dplyr::left_join(y = fish_tax_v2, by ="species") %>%# Move 'family' column to the left of all other columns dplyr::relocate(family, .before = dplyr::everything())# Look at the result of thatfish_df
1
The ‘by’ argument accepts a vector of column names found in both data tables
NoteActivity: Joining Data
In a script, attempt the following with the PIE crab data:
Create a data frame where you bin months into seasons (i.e., winter, spring, summer, fall)
Use your judgement on which month(s) should fall into each given PIE’s latitude/location
Join your season table to the PIE crab data based on month
Calculate the average size of crabs in each season in order to identify which season correlates with the largest crabs
Hint
You may need to modify the PIE dataset to ensure both data tables share at least one column upon which they can be joined
Leveraging Data Shape
You may already be familiar with data shape but fewer people recognize how playing with the shape of data can make certain operations dramatically more efficient. If you haven’t encountered it before, any data table can be said to have one of two ‘shapes’: either long or wide. Wide data have all measured variables from a single observation in one row (typically resulting in more columns than rows or “wider” data tables). Long data usually have one observation split into many rows (typically resulting in more rows than columns or “longer” data tables).
Data shape is often important for statistical analysis or visualization but it has an under-appreciated role to play in quality control efforts as well. If many columns have the shared criteria for what constitutes “tidy”, you can reshape the data to get all of those values into a single column (i.e., reshape longer), perform any needed wrangling, then–when you’re finished–reshape back into the original data shape (i.e., reshape wider). As opposed to applying the same operations repeatedly to each column individually.
Let’s consider an example to help clarify this. We’ll simulate a butterfly dataset where both the number of different species and their sex were recorded in the same column. This makes the column not technically numeric and therefore unusable in analysis or visualization.
# Generate a butterfly dataframebfly_v1 <-data.frame("pasture"=c("PNW", "PNW", "RCS", "RCS"),"monarch"=c("14m", "10f", "7m", "16f"),"melissa_blue"=c("32m", "2f", "6m", "0f"),"swallowtail"=c("1m", "3f", "0m", "5f"))# First we'll reshape this into long formatbfly_v2 <- bfly_v1 %>% tidyr::pivot_longer(cols =-pasture, names_to ="butterfly_sp", values_to ="count_sex")# Check what that leaves us withhead(bfly_v2, n =4)
# Let's separate count from sex to be more usable laterbfly_v3 <- bfly_v2 %>% tidyr::separate_wider_regex(cols = count_sex, c(count ="[[:digit:]]+", sex ="[[:alpha:]]")) %>%# Make the 'count' column a real number now dplyr::mutate(count =as.numeric(count))# Re-check outputhead(bfly_v3, n =4)
# A tibble: 4 × 4
pasture butterfly_sp count sex
<chr> <chr> <dbl> <chr>
1 PNW monarch 14 m
2 PNW melissa_blue 32 m
3 PNW swallowtail 1 m
4 PNW monarch 10 f
# Reshape back into wide-ish formatbfly_v4 <- bfly_v3 %>% tidyr::pivot_wider(names_from ="butterfly_sp", values_from = count)# Re-re-check outputhead(bfly_v4)
# A tibble: 4 × 5
pasture sex monarch melissa_blue swallowtail
<chr> <chr> <dbl> <dbl> <dbl>
1 PNW m 14 32 1
2 PNW f 10 2 3
3 RCS m 7 6 0
4 RCS f 16 0 5
While we absolutely could have used the same function to break apart count and butterfly sex data it would have involved copy/pasting the same information repeatedly. By pivoting to long format first, we can greatly streamline our code. This can also be advantageous for unit conversions, applying data transformations, or checking text column contents among many other possible applications.
Loops
Another way of simplifying repetitive operations is to use a “for loop” (often called simply “loops”). Loops allow you to iterate across a piece of code for a set number of times. Loops require you to define an “index” object that will change itself at the end of each iteration of the loop before beginning the next iteration. This index object’s identity will be determined by whatever set of values you define at the top of the loop.
Here’s a very bare bones example to demonstrate the fundamentals.
# Loop across each number between 2 and 4for(k in2:4){# Square the number result <- k^2# Message that outside of the loopmessage(k, " squared is ", result)}
1
‘k’ is our index object in this loop
2
Note that the operations to iterate across are wrapped in curly braces ({...})
2 squared is 4
3 squared is 9
4 squared is 16
Once you get the hang of loops, they can be a nice way of simplifying your code in a relatively human-readable way! Let’s return to our Plum Island Ecosystems crab dataset for a more nuanced example.
# Create an empty listcrab_list <-list()# Let's loop across size categories of crabfor(focal_size inunique(pie_crab_v4$size_category)){# Subset the data to just this size category focal_df <- pie_crab_v4 %>% dplyr::filter(size_category == focal_size)# Calculate average and standard deviation of size within this category size_avg <-mean(focal_df$size, na.rm = T) size_dev <-sd(focal_df$size, na.rm = T) # Assemble this into a data table and add to our list crab_list[[focal_size]] <-data.frame("size_category"= focal_size,"size_mean"= size_avg,"size_sd"= size_dev)} # Close loop# Unlist the outputs into a dataframecrab_df <- purrr::list_rbind(x = crab_list)# Check out the resulting data tablecrab_df
1
Note that this is not the most efficient way of doing group-wise summarization but is–hopefully–a nice demonstration of loops!
2
When all elements of your list have the same column names, list_rbind efficiently stacks those elements into one longer data table.