DIY Mosiah Priority with BomDB

We recently created BomDB as a tool for Book of Mormon researchers. This post shows how to use it to replicate some of the analysis that led to the Mosiah Priority hypothesis. This is especially for you if you like to do-it-yourself for the sake of skeptical inquiry.

Brent Metcalfe wrote a seminal chapter of New Approaches to the Book of Mormon in 1993 called The Priority of Mosiah. In it, he convincingly shows that Mosiah was written first, prior to 1st Nephi, and one of the techniques used was a simple wordcount of the occurrences of "wherefore" and "therefore" throughout the Book of Mormon.

We can use BomDB (a command-line tool and Ruby gem that contains several editions of the Book of Mormon) to replicate Metcalfe's work and even further it.

First, let's get some raw data to work with. We'll count up the number of "wherefore" and "therefore" occurrences in each book of the Book of Mormon, and print it out as text:

require 'bomdb' # version 0.6.2  
require 'json'

q = BomDB::Query.new(exclude: 'Bible')

data = q.books.map do |book, content|  
  wordcount = content.scan(/ +/).size
  wh = content.scan(/wherefore/i).size.to_f / wordcount
  th = content.scan(/therefore/i).size.to_f / wordcount
  [book, wh, th]
end

labels, wherefores, therefores = data.transpose  
puts "Labels: #{labels.to_json}"  
puts "Wherefores: #{wherefores.to_json}"  
puts "Therefores: #{wherefores.to_json}"  

Note that the BomDB::Query above handily excludes Biblical chapters and verses from our analysis using exclude: 'Bible-OT'. Next, we iterate over each book and divide the number of times we see 'wherefore' by the total number of words in the book (e.g. 1 Nephi). We do the same for 'therefore'. Finally, transpose takes our array-of-arrays and turns it back in to 3 arrays: the labels, the normalized 'wherefore' counts, and the normalized 'therefore' counts.

Here's what the output looks like:

Labels: ["1 Nephi","2 Nephi","Jacob","Enos",  
  "Jarom","Omni","Words of Mormon","Mosiah",
  "Alma","Helaman","3 Nephi","4 Nephi","Mormon",
  "Ether","Moroni"]
Wherefores: [0.00426,0.00705,0.00581,0.00515,0.00411,0.00429,  
  0.00579,0.0,4.0e-05,0.0,0.00012,0.0,0.0,0.00378,0.00627]
Therefores: [0.00426,0.00705,0.00581,0.00515,0.00411,0.00429,  
  0.00579,0.0,4.0e-05,0.0,0.00012,0.0,0.0,0.00378,0.00627]

It would be easier to understand this data if we could chart it, so let's do that using Highcharts.

Since we'll be doing more than comparing 'wherefore' and 'therefore', let's make a method that compares any number of words and their frequencies. Basically, this is a generalized version of the code above (note, this requires Ruby 2.1 or above):

def compare_frequencies(words:, group_by: :books, range: nil)  
  BomDB::Query.new(range: range, exclude: 'Bible-OT').
  send(group_by).map do |heading, content|
    wordcount = content.scan(/ +/).size
    frequencies = words.map do |word|
      content.scan(/\b#{word}\b/i).size.to_f / wordcount
    end
    [group_by == :chapters ? heading[1] : heading] + frequencies
  end.transpose
end  

Now, we can give it a set of words, and we get the same thing as above:

compare_frequencies(["wherefore", "therefore"])  

Additionally, we need a method that turns our data into a javascript chart using Highcharts:

def make_chart(words:, group_by: :books, range: nil,  
  title: "Chart", subtitle: nil, labels: [], xtitle: nil, ytitle: nil,
  tooltip: ' occurrences per word', placeholder: 'PLACEHOLDER', height: 400)
  labels, *data = compare_frequencies(words: words, group_by: group_by, range: range)

  series = words.zip(data).map do |word, datapoints|
    { name: word, data: datapoints }
  end

  {
    chart: {
        renderTo: placeholder,
        height: height
    },
    title: {
        text: title,
        x: -20
    },
    subtitle: {
        text: subtitle,
        x: -20
    },
    xAxis: {
        categories: labels,
        title: {
            text: xtitle
        }
    },
    yAxis: {
        min: 0,
        title: {
            text: ytitle
        }
    },
    tooltip: {
        valueSuffix: tooltip
    },
    legend: {
        layout: 'vertical',
        align: 'right',
        verticalAlign: 'middle',
        borderWidth: 0
    },
    series: series
  }
end  

Lastly, a helper method to generate the embedded script tags for this blog:

def script_chart(**args)  
  "<script>" +
    "var div = document.createElement('div'), " +
        "script = document.scripts[document.scripts.length - 1]; " +
    "script.parentElement.insertBefore(div, script); " +
    "new Highcharts.Chart(" + 
      make_chart(**args).to_json.gsub('"PLACEHOLDER"', 'div') +
    ");</script>"
end  

When we string this together,

puts script_chart(  
  title: "Wherefores & Therefores Per Word",
  subtitle: "in the Book of Mormon",
  xtitle: "Books in the Book of Mormon",
  ytitle: "Normalized Word Count",
  words: ["wherefore", "therefore"]
)

Here's what we get:

Ether is really interesting. It's the only book that has a substantial number of 'wherefores' and 'therefores'. If the Book of Mormon had two or more authors, perhaps we would expect one author to be favoring 'wherefore', and another author favoring 'therefore', and so we would expect a clean break. On the other hand, if there is one author (i.e. Joseph Smith) whose vocabulary and word preference is changing over time, we'd expect a smooth transition.

Using our compare_frequencies method above, let's generate a chart and zoom in on Ether:

puts script_chart(  
  range: 'Ether 1-15',
  group_by: :chapters,
  title: "Wherefores & Therefores Per Word in Ether",
  subtitle: "in the Book of Mormon",
  xtitle: "Chapters in Ether",
  ytitle: "Normalized Word Count",
  words: ["wherefore", "therefore"]
)

Here's what it looks like:

According to Metcalfe, Ether was dictated in late May 1829. It looks like this was the period of time when Joseph began preferring 'wherefore' over 'therefore'. Indeed, if you look at the Book of Commandments, a similar pattern appears (see Metcalfe's chapter).

What about other words? Metcalfe mentions 'whoso' and 'whosoever'. Let's check these out:

puts script_chart(  
  title: "Whosos & Whosoevers Per Word",
  subtitle: "in the Book of Mormon",
  xtitle: "Books in the Book of Mormon",
  ytitle: "Normalized Word Count",
  words: ["whoso\\b", "whosoever"]
)

And the resulting chart:

Between 3rd Nephi and Mormon, a clear inversion occurs--whereas 'whosoever' was the most common synonym beginning in Mosiah, by Moroni, 'whoso' has completely taken its place, and the trend continues into 1st & 2nd Nephi, as well as Jacob. If we took the hypothesis that 1st Nephi was authored before Mosiah, it would be hard to explain the prevalence of whoso, then its complete absence, then its return.

Let's take a look at 3rd Nephi by "zooming in":

There's no clear trend-line up or down. Many of these verses are taken from the New Testament, where the language of Jesus is borrowed. It's interesting to see that in the Book of Mormon, Jesus uses 'whoso' and 'whosoever' interchangeably:

bomdb show --search 'whoso' '3 Nephi 1-30'  

3 Nephi 9:14 Yea, verily I say unto you: If ye will come unto me, ye shall have eternal life. Behold, mine arm of mercy is extended towards you. And whosoever will come, him will I receive. And blessed are they which cometh unto me.

3 Nephi 9:20 And ye shall offer for a sacrifice unto me a broken heart and a contrite spirit. And whoso cometh unto me with a broken heart and a contrite spirit, him will I baptize with fire and with the Holy Ghost, even as the Lamanites because of their faith in me at the time of their conversion were baptized with fire and with the Holy Ghost--and they knew it not.

...

Note: I will spare you the 29 verses in 3rd Nephi that mention "whoso", but if you'd like to see all references, by all means run the command above.

What about Mormon?

There are 2 'whoso's in chapter 8, and 1 'whoso' and 1 'whosoever' in chapter 9. These occur when Moroni begins speaking.

Here's another interesting one we found. Searching for occurrences of 'House of Israel', the Book of Mormon distributes them in a similar fashion as 'wherefore' and 'whoso':

puts script_chart(  
  title: "'House of Israel' Per Word",
  subtitle: "in the Book of Mormon",
  xtitle: "Books in the Book of Mormon",
  ytitle: "Normalized Word Count",
  words: ["house of israel"]
)

Here again, it looks like the phrase "House of Israel" was first encountered in 3rd Nephi, and then favored through Moroni, 1st and 2nd Nephi, and finally Jacob. Its absence from Enos to Helaman is hard to explain without a dictation order that starts somewhere after Jacob and before 3rd Nephi.

If you have ideas to test, or want to replicate this work, give BomDB a try!

Note 2015-04-18: These charts were including data from verses in 3 Nephi that were borrowed from the New Testament (ch. 12, 13, 14). Those data points have now been fixed.