All posts by William Doane

Yes, and…? Inviting People to Take the Next Step

As an educator who advises students working on theses and dissertations, there’s a standard question I ask—I refer to it as “the PhD question”: So what? It’s a shorthand to challenge students to consider the question: If everything you’ve just said is shown to be true, what will that mean for changes in our understanding of the world or how we engage with it?

I found myself using So what? again recently at ICER 2019, a community of education researchers that values openness and community building. I heard myself saying it, and I realized I didn’t like the tone of it at all. So what? is confrontational. It’s a conversation stopper, not a starter. It’s a blockade, not an invitation. Yes, I learned it from my graduate advisors way back when, and I think it’s time to put it to bed.

Continue reading Yes, and…? Inviting People to Take the Next Step

My RStudio Configuration

I help a few of dozen users install RStudio and learn R regularly. Whenever I need to install RStudio on a new machine, I have to think a bit about the configuration options I’ve tweaked. Invariably, I miss a checkbox that leaves me with slightly different RStudio behavior on each system. This post includes screenshots of my currently preferred standard RStudio configuration and custom keyboard shortcuts for RStudio 1.3, MacOS.

If you need an exact copy of your settings, consider the discussion at https://stackoverflow.com/questions/55903423/export-import-rstudio-user-preferences-global-setting-etc/55940249 (h/t: liebrr)

Continue reading My RStudio Configuration

Converting Individual Binary Vectors to a Value Based on Column Names

When processing data downloaded from popular survey engines, it’s not uncommon for multiple choice questions to be represented as one column per possible response coded as 0/1. So, a question with just two responses might be downloaded as part of a CSV with one column for q1_1 and another for q1_2. If the responses are mutually exclusive, then (q1_1 == 0 iff q1_2 == 1) and (q1_1 == 1 iff q1_2 == 0). If the responses are part of a “choose all that apply” question, then it’s possible to have multiple 1s.

How can these individual binary indicator variables be reassembled into a single response variable?

Continue reading Converting Individual Binary Vectors to a Value Based on Column Names

The Shiny Module Design Pattern

Foremost in your mind should be the quintessential reality of R: Everything that happens in R is the result of a function call. Shiny is no exception.

To write a minimal shiny app, you create an object that describes your app’s user interface, write a function describing runtime behaviors, and pass them into a function that spins up the app you’ve described. By convention, these two objects are associated with the variable names ui and server.

library(shiny)
ui <- fluidPage()
server <- function(input, output, session) {}

This is just R code. You can type it into the Console to execute it line by line and inspect what it does.

If you’re working in RStudio, you can type it into a Source file, then press Control-Enter (Windows) or Command-Return (MacOS) to send each line to the Console for execution.

Checking the Environment—or the structure of these two objects with str()—we can see that ui is a list of three objects. If we print ui to the Console, we see only an empty HTML <div> element.

<div class="container-fluid"></div>

The object associated with server is simply a function with no body.

To execute this minimal shiny app, we pass the ui and server objects to the shinyApp() function.

shinyApp(ui, server)

The app will be spun up either in RStudio’s Viewer pane, in a Viewer window, or in your default Web browser, depending on your settings in RStudio.

Don’t be surprised: it will be just a blank window, since all that has been defined thus far is an empty <div> element. The document that opened is an HTML document with some boilerplate CSS and JavaScript. You can inspect it using your Browser’s Developer Tools.

That’s it. That’s shiny. Everything else flows from these core ideas:

  • ui is a list object representing the HTML UI to be constructed.
  • server is a function describing the runtime behavior of your app.
  • shinyApp() takes these two objects and uses them to construct an HTML document that then gets spun up in a browser.
Continue reading The Shiny Module Design Pattern

Writing Research Well

Newcomers to writing nonfiction research—often new PhD students—may find the research process and the formal structure of research documents daunting. Here are a few resources both on research writing and on the writing craft itself that I found useful when I was starting to hone my skill. And, yes, writing is a skill; you can improve your writing through practice.

Above all, seek out and be open to feedback. Anyone who is willing to offer honest feedback on your writing to help you improve it is valuable.

The Craft of Research by Wayne Booth, et al

A Manual for Writers of Research Papers, Theses, and Dissertations by Kate Turabian, et al

On Writing Well by William Zinsser

The Professor is In by Karen Kelsky

Avoid Strunk and White. It’s an interesting historical read, but much of the advice is either incorrect or outdated, by modern standards.

 

 

Writing Pipe-friendly Functions

Pipes have been a fundamental aspect of computer programming for many decades. In short, the semantics of pipes can be thought of as taking the output from the left-hand side and passing it as input to the right-hand side. For example, in a linux shell, you might cat example.txt | sort | uniq to take the contents of a text file, then sort the rows, then take one copy of each distinct value. | is a common, but not universal, pipe operator and on U.S. Qwerty keyboards, is found above the RETURN key along with the backslash: \.

Languages that don’t begin by supporting pipes often eventually implement some version of them. In R, the magrittr package introduced the %>% infix operator as a pipe operator and is most often pronounced as “then”. For example, “take the mtcars data.frame, THEN take the head of it, THEN…” and so on.

Continue reading Writing Pipe-friendly Functions

Science and Communication: Alan Alda in Conversation with Neil deGrasse Tyson

Despite the reality that we use tools and techniques every moment of every day that have been devised and revised through the constant questioning and reflecting process we call science, far too many people don’t believe they understand what science is, don’t consider themselves scientists, and don’t trust the expert opinions of the scientific community. How can that possibly be?

“We’re not really listening, unless we’re willing to be changed by the other person.” ~ Alan Alda

Science and Communication—Alan Alda and Neil deGrasse Tyson at the 92nd Street Y in New York City

Stay Secure

Security is a tricky affair: it’s difficult to establish, to maintain, and to verify. Take all the steps you can to keep your data and devices secure.

  • Backup, keeping a copy in your home and somewhere outside your home that you consider safe and are likely to be able to access in an emergency.
  • Secure, so that only you and those you trust can get access to your information and accounts.
  • Plan for routine recovery, such as when you’re away from your computer, but need to gain access to your information and accounts.
  • Plan for extreme recovery, such as when you are disabled and unable to communicate, or when you pass away.

Continue reading Stay Secure

I’m ‘not in’ right now…

Checking whether an item is in a vector or not in a vector is a common task. The notation in R is a little inelegant when expressing the “not in” condition since the negation operator (!) is separated from the comparison operator (%in%):

5 %in% c(1, 2, 3, 4, 5)  # TRUE
!5 %in% c(1, 2, 3, 4, 5) # FALSE

R is a language where you can easily extend the set of built in operators:

`%!in%` <-
  function(needle, haystack) {
    !(needle %in% haystack)
  }

Now, I can express my intentions reasonably clearly with my new, compact, infix operator %!in%:

5 %in% c(1, 2, 3, 4, 5)  # TRUE
5 %!in% c(1, 2, 3, 4, 5) # FALSE

Moral: bend your tools to your will, not the other way ’round.