Flaring in the Bakken (Oil & Gas Coding Series)

As a continuation of our previous post, Shut-ins in the Bakken, I though I would delve into flaring trends in the Bakken for the Environmentally-Conscious folk.


Follow my blog

Flaring

No bones about it, flaring is a black eye on our industry. While it is harmful to the environment, it is also hugely wasteful. Resources do not last forever, and despite all the gains in alternative energies, we still will be reliant on hydrocarbons for awhile. Burning away part of a depleting resource will leave us exposed.

Of course, maybe I’ll just move to Pittsburgh when the great natural gas wars start up (that city sits right in the thick of the Marcellus and is basically undeveloped).


Data

Data is usually difficult to come by. It often comes down to self-reporting at the state level, so who knows how many folks are less than genuine. However, in North Dakota, we do at least have these values reported from the North Dakota Department of Mineral Resources. I won’t rehash all of what I did in the last insight, but I will show the code. One additional note, I will be adding in the data.table package, which allows me to simplify (and speed up) the code. The other packages should already be installed if you are following my tutorials.

install.packages('data.table')
library(data.table)
library(tidyverse)
library(readxl)

list1 <- merge(seq(1, 12, 1), seq(2015, 2020, 1)) %>%
  select(months = x, years = y) %>% 
  mutate(months = replace(months, 
                          months < 10, 
                          paste0('0', months[months<10])
  )
  ) %>% 
  mutate(url1 = 
           glue::glue('https://www.dmr.nd.gov/oilgas/mpr/{years}_{months}.xlsx')
  )
library(readxl)

options(scipen = 999)

data1 <- lapply(split(list1, list1[,'url1']), function (well) tryCatch({
  
  temp = tempfile(fileext = ".xlsx")
  
  download.file(well$url1, destfile=temp, mode='wb')
  
  readxl::read_excel(temp, sheet =1)
  
},
error = function(e) {
  e
  NULL
}))

df <- data.table::rbindlist(data1)

Now, we should have the production data we need to do an analysis.


Data Cleanup

Once again, I clean up company names and some of the categories, as with last insight. Here is the summary code.

df <- df %>% 
    mutate(Company = gsub('.', '', Company, fixed = TRUE))
df <- df %>% 
    mutate(Company = gsub(',', '', Company, fixed = TRUE))
df$Company <- toupper(df$Company)

df <- df %>% mutate(Company = gsub('LLC', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('CORPORATION', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('CORP', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('LP', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('LTD', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('COMPANY', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('INC', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('ENERGY', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('OPERATING', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('EXPLORATION &amp; PRODUCTION', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('E&amp;P', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('PETROLEUM', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('OIL AND GAS', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('RESOURCES', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('USA', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('MANAGEMENT', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('PRODUCTION', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('NORTH AMERICA', '', Company, fixed = TRUE))
df <- df %>% mutate(Company = gsub('OIL &amp; GAS', '', Company, fixed = TRUE))

df <- df %>% mutate(Company = gsub('\\s+', ' ', Company))
df$Company <- trimws(df$Company, which = 'both')

And that should be it for our dataset.


Analysis

Now that we have the data where we like it, we can start doing analysis. Since we are looking at flaring data, we will just look at operators over time using dplyr (part of the tidyverse).


Operator Total over Time

First one we will look at overall trend, separated by operator (top 10 at least). We also want to add in the lubridate library.

#Identify Top 10 flarers in 2020
tst1 <- df %>% filter(year(Date) == 2020) %>% 
  group_by(Company) %>% summarise(Flared = sum(Flared)) %>% ungroup() %>% arrange(desc(Flared))
tst1 <- tst1$Company[1:10]

library(lubridate)

#Group by Operator and Date and add up flared and total gas volumes
tst2 <- df %>% mutate(Company = replace(Company, !Company %in% tst1, 'OTHER')) %>%
  group_by(Company, Date) %>% summarise(flared = sum(Flared), Gas = sum(Gas)) %>% ungroup() %>%
  mutate(flared = flared/days_in_month(Date), Gas = Gas/days_in_month(Date))

#If you want to just group by all operators uncomment the below block

#tst2 <- df %>% 
#  group_by(Company, Date) %>% summarise(flared = sum(Flared), Gas = sum(Gas)) %>% ungroup() %>%
#  mutate(flared = flared/days_in_month(Date), Gas = Gas/days_in_month(Date))

Let’s plot it up in highcharts as well.

library(highcharter)

highchart() %>% 
  hc_chart(type = "area") %>% 
  hc_title(text = glue::glue("Flaring Volumes - North Dakota"), align='left') %>% 
  hc_subtitle(text = "<i>2016+ from North Dakota DMR</i>", align = 'left') %>% 
  hc_xAxis(type = 'datetime',
           title = list(enabled = FALSE),
           labels = list(style = list(
             color = '#0D1540',
             fontSize = '18px', 
             fontWeight = 'bold'))) %>% 
  hc_yAxis(title = list(text = '<b>Total Reported Flaring<br>MCF/D</b>', style = list(fontSize = '18px')),
           labels = list(style = list(fontSize = '12px', fontWeight = 'bold'))) %>% 
  hc_tooltip(pointFormat = "<span style=\"color:{series.color}\">{series.name}</span>:
             <b> {point.y}</b><br/>",
             shared = FALSE) %>% 
  hc_plotOptions(area = list(
    stacking = "normal",
    lineColor = "#ffffff",
    lineWidth = 1,
    marker = list(
      enabled = FALSE,
      lineWidth = 1,
      lineColor = "#ffffff"
    ))) %>%
  hc_add_series(tst2 %>% filter(year(Date) >= 2016),
                type='area', hcaes(x=Date, y=as.integer(flared), group = Company), 
                showInLegend = TRUE,
                marker= list(enabled=FALSE)) %>%
  hc_credits(enabled = TRUE, text = 'Powered by Highcharts', href = "https://www.highcharts.com/")

If you want to look at specific operators, you can just deselect various ones in the legend below.

Figure 1: Daily North Dakota Flaring by Operator

It does appear that total flared volumes have been dropping for a year now, likely driven by some gas plant work, as well as just overall reduced production volumes brought on by shut-ins.


Total 2020

Let’s look at the top ten by operator in 2020 as well, from a total volume and percent of volume perspective.

tst1 <- df %>% filter(year(Date) == 2020) %>% 
  group_by(Company) %>%
  summarise(Flared = sum(Flared), Gas = sum(Gas)) %>%
  ungroup() %>% arrange(desc(Flared)) %>%
  mutate(Percent = round(100*Flared/Gas,1))
tst1 <- tst1[1:15,]

What I did here is filter the year to be 2020, grouped by each operator, and just summed up the flared and total gas volumes. I also created a percent of total gas column and filtered by the top 15.

#Highcharts Column Plot
highchart() %>%
  hc_add_series(tst1, type = 'column', hcaes(x = Company, y = Flared), name = 'Flared', showInLegend=FALSE)%>%
  hc_credits(enabled = TRUE, text = 'Powered by Highcharts', href = "https://www.highcharts.com/")%>%
  hc_xAxis(categories = tst1$Company) %>%
  hc_yAxis(title = list(text = '<b>Total 2020 Reported Flaring<br>MCF</b>', style = list(fontSize = '18px')),
          labels = list(style = list(fontSize = '12px', fontWeight = 'bold'))) %>%
  hc_title(text = glue::glue("Flaring By Operator - North Dakota"), align='left') %>% 
  hc_subtitle(text = "<i>2020 from North Dakota DMR</i>", align = 'left') 

Figure 2: 2020 Flared Volumes by Operator – Top 15 in North Dakota

And let’s look at total percent in this sample-set.

tst1 <- tst1 %>% arrange(desc(Percent))

Figure 3: 2020 Percent Gas Flared by Operator – Top 15 in North Dakota


Summary

It’s hard not to notice Marathon at the top of both lists. While I believe some of this is gas-plant related, they need to get on this quick. Kayne Anderson probably needs to crack down on this with Kraken if they are serious about being environmental stewards.

Thanks for reading and stay tuned for the next one.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: