anchor.diff:    .option("header", "true")      // <3>
     .option("inferSchema", "true") // <4>
     .load(inputPath)               // <5>
  ----
  +----
   <1> We want to read (as opposed to write) our dataset from disk.
   <2> Our dataset in the CSV format.
   <3> There will be headers to read.
  
positive.code: 
  .Printing the schema of our data
  [source,scala]
  ---
  events.printSchema()
  ---
  
  You should get something along the lines of:
  
  .The schema of our events
  [source,scala]
  ---
  root
   |-- actor: struct (nullable = true)
   |    |-- avatar_url: string (nullable = true)
   |    |-- gravatar_id: string (nullable = true)
   |    |-- id: long (nullable = true)
   |    |-- login: string (nullable = true)
  etc
  ---
  
  The fields which interest us in this chapter are the _actor_, the _type_ of
  event as well as a few fields in the _payload_.
  
negative.code: it is actually referring to someone starring a repository and not watching it.
  Refer to https://developer.github.com/v3/activity/events/types/#watchevent[the
  documentation for this type] to know more.
  <8> If the event type is not an aggregation of sub-events, we leave it alone.
  
  Once we have defined our function, we can actually turn it into a UDF:
  
  .Turning our function into a UDF
  [source,scala]
  ----
  import org.apache.spark.sql.functions.udf
  val splitEventUDF = udf(splitEvent)
  ----
  
  Note that a UDF is a black box as far as Spark SQL is concerned and it won't try
  to optimize what's being done. Consequently, UDF should be used sparingly for
  