auto loss cost trends q4 2017 - society of actuaries...montana property damage severity 3000 3500...
TRANSCRIPT
November 2017 | Auto Loss Cost Trends Report | #
Auto Loss Cost Trends: Q4 2017 August 2018
Q4 2017 Trend Analysis
ContentsARIMA Models 1
Bodily Injury . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Property Damage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9Comprehensive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16Collision . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23Personal Injury Protection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
Code 33
ARIMA Models
Using FAST TRACK PLUS data, we analyzed how auto insurance claims change over time. In this report,we identify which state-level claims are unexpectedly extreme. Using an ARIMA model, we forecast the 4thquarter 2017 value for each state, metric (frequency, severity and loss cost), and coverage (bodily injury,property damage, comprehensive, collision, and personal injury protection). ARIMA models allow us toaccount for both the quarter-to-quarter trends and any trends across years (for example if all the 3Q valuesare higher than any other quarters in the year). The state maps show the accuracy of the 4th quarterprediction. Blue states indicate that the true 4Q metric was significantly less than expected, and red statesindicate that the true 4Q metric was significantly greater than expected.
Below each state map, full time series plots are displayed for the states that had a 4th quarter metric falloutside of the 10%-90% prediction interval. The green dot represents the true 4th quarter value. The bluedot represents the point forecast with a surrounding grey area representing the 10%-90% prediction interval.
Some states and metrics experienced an extreme or abnormal observation due to weather or other events;these outliers decreased the accuracy of the ARIMA model. The time series with outliers were smoothed asto improve the 4th quarter prediction accuracy. These smoothed outliers are marked with an orange squareon the time series plots.
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 1
Bodily Injury
>99%
95%−99%
90%−95%
10%−90%
1%−5%
<1%
Bodily Injury Frequency
Florida Bodily InjuryFrequency
0.0090
0.0095
0.0100
0.0105
0.0110
'12 '13 '14 '15 '16 '17
Idaho Bodily InjuryFrequency
0.0060
0.0065
0.0070
0.0075
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 2
Missouri Bodily InjuryFrequency
0.00680.00700.00720.00740.00760.00780.0080
'12 '13 '14 '15 '16 '17
North Dakota Bodily InjuryFrequency
0.00100.00120.00140.00160.0018
'12 '13 '14 '15 '16 '17
New Jersey Bodily InjuryFrequency
0.0030
0.0035
0.0040
0.0045
0.0050
'12 '13 '14 '15 '16 '17
Ohio Bodily InjuryFrequency
0.0070
0.0075
0.0080
0.0085
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 3
>99%
95%−99%
90%−95%
10%−90%
5%−10%
1%−5%
<1%
Bodily Injury Severity
California Bodily InjurySeverity
11000120001300014000150001600017000
'12 '13 '14 '15 '16 '17
Colorado Bodily InjurySeverity
15000
20000
25000
30000
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 4
Connecticut Bodily InjurySeverity
22000
24000
26000
28000
'12 '13 '14 '15 '16 '17
Delaware Bodily InjurySeverity
14000150001600017000180001900020000
'12 '13 '14 '15 '16 '17
Idaho Bodily InjurySeverity
12000
14000
16000
18000
'12 '13 '14 '15 '16 '17
Michigan Bodily InjurySeverity
4200044000460004800050000
'12 '13 '14 '15 '16 '17
Missouri Bodily InjurySeverity
120001400016000180002000022000
'12 '13 '14 '15 '16 '17
Nebraska Bodily InjurySeverity
14000
16000
18000
20000
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 5
Oklahoma Bodily InjurySeverity
1000011000120001300014000
'12 '13 '14 '15 '16 '17
South CarolinaBodily Injury
Severity
1100012000130001400015000
'12 '13 '14 '15 '16 '17
Utah Bodily InjurySeverity
120001400016000180002000022000
'12 '13 '14 '15 '16 '17
Wyoming Bodily InjurySeverity
15000200002500030000
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 6
>99%
95%−99%
10%−90%
1%−5%
Bodily Injury Loss Cost
California Bodily Injury Loss Cost
100110120130140150160
'12 '13 '14 '15 '16 '17
Connecticut Bodily Injury Loss Cost
200
220
240
260
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 7
Tennessee Bodily Injury Loss Cost
100
110
120
130
'12 '13 '14 '15 '16 '17
Utah Bodily Injury Loss Cost
90100110120130140150
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 8
Property Damage
95%−99%
10%−90%
5%−10%
<1%
Property Damage Frequency
Florida Property DamageFrequency
0.034
0.036
0.038
0.040
'12 '13 '14 '15 '16 '17
Hawaii Property DamageFrequency
0.0350.0360.0370.0380.039
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 9
Iowa Property DamageFrequency
0.024
0.026
0.028
0.030
'12 '13 '14 '15 '16 '17
Louisiana Property DamageFrequency
0.036
0.038
0.040
0.042
0.044
'12 '13 '14 '15 '16 '17
Washington Property DamageFrequency
0.0320.0330.0340.0350.0360.0370.0380.039
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 10
>99%
95%−99%
90%−95%
10%−90%
5%−10%
1%−5%
Property Damage Severity
Iowa Property DamageSeverity
260028003000320034003600
'12 '13 '14 '15 '16 '17
Kentucky Property DamageSeverity
28003000320034003600380040004200
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 11
Montana Property DamageSeverity
3000
3500
4000
4500
'12 '13 '14 '15 '16 '17
North CarolinaProperty Damage
Severity
2600280030003200340036003800
'12 '13 '14 '15 '16 '17
North DakotaProperty Damage
Severity
260028003000320034003600
'12 '13 '14 '15 '16 '17
Oregon Property DamageSeverity
2600280030003200340036003800
'12 '13 '14 '15 '16 '17
South CarolinaProperty Damage
Severity
2600280030003200340036003800
'12 '13 '14 '15 '16 '17
Vermont Property DamageSeverity
240026002800300032003400
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 12
>99%
95%−99%
90%−95%
10%−90%
5%−10%
<1%
Property Damage Loss Cost
Florida Property Damage Loss Cost
100110120130140150
'12 '13 '14 '15 '16 '17
Iowa Property Damage Loss Cost
70
80
90
100
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 13
Illinois Property Damage Loss Cost
90100110120130140
'12 '13 '14 '15 '16 '17
Indiana Property Damage Loss Cost
8090
100110
120
'12 '13 '14 '15 '16 '17
Michigan Property Damage Loss Cost
8
9
10
11
'12 '13 '14 '15 '16 '17
Ohio Property Damage Loss Cost
8090
100110120
'12 '13 '14 '15 '16 '17
Rhode IslandProperty Damage
Loss Cost
140
160
180
200
220
'12 '13 '14 '15 '16 '17
South CarolinaProperty Damage
Loss Cost
90100110120130
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 14
Texas Property Damage Loss Cost
130140150160170180
'12 '13 '14 '15 '16 '17
Vermont Property Damage Loss Cost
65707580859095
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 15
Comprehensive
Several states’ comprehensive metrics seemed to be correlated with severe weather events. In Iowa, there wasmuch less storm damage than usual, possibly leading to a small observed frequency metric. In Connecticut,storm damage was much higher than expected, thus the severity and loss cost metrics were high as well. NewHampshire had flash floods that caused significant damage and the severity and loss cost metrics were bothextremely high. Oregon had a much lower damage amount than usual, thus our severity metric was alsosmaller than usual.
10%−90%
1%−5%
Comprehensive Frequency
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 16
Iowa ComprehensiveFrequency
0.000.020.040.060.080.100.12
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 17
>99%
90%−95%
10%−90%
5%−10%
1%−5%
Comprehensive Severity
California ComprehensiveSeverity
100012001400160018002000
'12 '13 '14 '15 '16 '17
Connecticut ComprehensiveSeverity
8001000120014001600
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 18
Florida ComprehensiveSeverity
600800
10001200140016001800
'12 '13 '14 '15 '16 '17
Maine ComprehensiveSeverity
600800
10001200140016001800
'12 '13 '14 '15 '16 '17
New Hampshire ComprehensiveSeverity
600
800
1000
1200
1400
'12 '13 '14 '15 '16 '17
New Jersey ComprehensiveSeverity
0
2000
4000
6000
8000
'12 '13 '14 '15 '16 '17
Nevada ComprehensiveSeverity
700800900
100011001200
'12 '13 '14 '15 '16 '17
Oregon ComprehensiveSeverity
600
800
1000
1200
1400
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 19
Pennsylvania ComprehensiveSeverity
1000
1500
2000
2500
'12 '13 '14 '15 '16 '17
Wisconsin ComprehensiveSeverity
1500
2000
2500
'12 '13 '14 '15 '16 '17
Wyoming ComprehensiveSeverity
100015002000250030003500
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 20
>99%
95%−99%
90%−95%
10%−90%
<1%
Comprehensive Loss Cost
California Comprehensive Loss Cost
5055606570758085
'12 '13 '14 '15 '16 '17
Connecticut Comprehensive Loss Cost
40
60
80
100
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 21
Maine Comprehensive Loss Cost
2030405060708090
'12 '13 '14 '15 '16 '17
New Hampshire Comprehensive Loss Cost
304050607080
'12 '13 '14 '15 '16 '17
Rhode Island Comprehensive Loss Cost
40
60
80
100
'12 '13 '14 '15 '16 '17
Tennessee Comprehensive Loss Cost
0
50
100
150
'12 '13 '14 '15 '16 '17
Texas Comprehensive Loss Cost
0200400600800
1000
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 22
Collision
Several states’ collision metrics often have an inverse relationship with severe weather damage amounts. Ourguess is that due to severe weather, less vehicles are on the road and less collision claims are made. In Florida,there was very little weather damage this quarter, and our frequency, severity, and loss coss metrics wereextremely high in this quarter. Georgia often experiences a variety of severe weather events in the fourthquarter of each year, but in 2017 those metrics were very low; this could have possibly lead to the high losscost and severity metrics.
>99%
10%−90%
5%−10%
1%−5%
Collision Frequency
District of ColumbiaCollision
Frequency
0.09
0.10
0.11
0.12
0.13
'12 '13 '14 '15 '16 '17
Florida CollisionFrequency
0.0500.0520.0540.0560.0580.060
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 23
Oklahoma CollisionFrequency
0.0460.0480.0500.0520.0540.056
'12 '13 '14 '15 '16 '17
Oregon CollisionFrequency
0.040
0.045
0.050
0.055
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 24
>99%
95%−99%
90%−95%
10%−90%
5%−10%
1%−5%
Collision Severity
Alabama CollisionSeverity
3000320034003600380040004200
'12 '13 '14 '15 '16 '17
Florida CollisionSeverity
280030003200340036003800
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 25
Georgia CollisionSeverity
300032003400360038004000
'12 '13 '14 '15 '16 '17
Hawaii CollisionSeverity
260028003000320034003600
'12 '13 '14 '15 '16 '17
Mississippi CollisionSeverity
3200
3400
3600
3800
'12 '13 '14 '15 '16 '17
New Mexico CollisionSeverity
300032003400360038004000
'12 '13 '14 '15 '16 '17
Rhode Island CollisionSeverity
3500
4000
4500
'12 '13 '14 '15 '16 '17
Tennessee CollisionSeverity
300032003400360038004000
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 26
Texas CollisionSeverity
320034003600380040004200
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 27
>99%
95%−99%
10%−90%
Collision Loss Cost
Alabama Collision Loss Cost
170180190200210220
'12 '13 '14 '15 '16 '17
Florida Collision Loss Cost
140160180200220240
'12 '13 '14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 28
Georgia Collision Loss Cost
160180200220240
'12 '13 '14 '15 '16 '17
Hawaii Collision Loss Cost
160
180
200
220
'12 '13 '14 '15 '16 '17
South Carolina Collision Loss Cost
140
160
180
200
'12 '13 '14 '15 '16 '17
Texas Collision Loss Cost
200220240260280
'12 '13 '14 '15 '16 '17
Washington Collision Loss Cost
120140160180200220
'12 '13 '14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 29
Personal Injury Protection
The PIP data are different than the other insurance coverages. The amount of PIP data we have varies foreach state; specifically, when the data begin and end is not consistent. The plot below gives us informationabout the start and end dates for each state we have data on.
WY
WV
WI
WA
VT
VA
UT
TX
TN
SD
SC
RI
PA
OR
OK
OH
NY
NJ
ND
NC
MN
MI
MD
MA
KY
KS
HI
FL
DE
AK
2012 2014 2016 2018
Sta
te
When the PIP Data Begin and End
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 30
ARIMA model on PIP data
The same ARIMA model was used to forecast the 2017 4Q values on the PIP data. However, only 18 stateshad PIP data through quarter 4 of 2017; these were the states included in the model.
Of the 54 metrics forecasted, only 6 4Q metrics fell outside of the 10%-90% prediction interval. These plotsare shown below.
KentuckyPersonal Injury Protection
Loss Cost
60
65
70
75
'14 '15 '16 '17
North DakotaPersonal Injury Protection
Severity
02000400060008000
10000
'12 '13 '14 '15 '16 '17
New JerseyPersonal Injury Protection
Frequency
0.0105
0.0110
0.0115
0.0120
'14 '15 '16 '17
New JerseyPersonal Injury Protection
Loss Cost
170175180185190195
'14 '15 '16 '17
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 31
New YorkPersonal Injury Protection
Severity
80009000
10000110001200013000
'14 '15 '16 '17
New YorkPersonal Injury Protection
Loss Cost
120130140150160170
'14 '15 '16 '17
Time Series Legend
Point Forecast True Value Prediction Interval Removed Outlier
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 32
Code
All the code used to create this document:# libraries needed for the analysislibrary(readxl)library(data.table)library(dplyr)library(ggplot2)library(maps)library(tseries)library(tsoutliers)library(forecast)library(zoo)library(gridExtra)library(devtools)# install_github('sinhrks/ggfortify')library(ggfortify)
# Reading in the raw Q3 and Q4 data:setwd("~/Google Drive/AutoLossCosts")ts4 <- read_excel("AutoLossCostv20_2017Q4.xlsm",
sheet = "TSData") %>% data.table()ts3 <- read_excel("AutoLossCostv20_2017Q3_TJ-EH.xlsm",
sheet = "TSData") %>% data.table()
# Joining the 2 data fileskey1 <- paste0(ts3$State, ts3$Coverage, ts3$Metric)key2 <- paste0(ts4$State, ts4$Coverage, ts4$Metric)ts_data <- ts3 %>% select(State:`2012 Q4`) %>% cbind(ts4 %>%
select(`2013 Q1`:`2017 Q4`))
# outlier analysis and removal Smoothing just# these series with outliersoutlier.metrics <- c("PA, Comp, SeverityMI, Comp, SeverityAR, Comp, SeverityID, Coll, FrequencyLA, Comp, SeverityMT, BI, SeverityNC, Comp, SeveritySD, BI, SeverityTX, Comp, SeverityVA, Comp, SeverityCT, Comp, SeverityCO, Comp, SeverityNY, Comp, SeverityNJ, Comp, Severity")remove <- x <- strsplit(outlier.metrics, "\n") %>%
unlist()remove <- gsub(pattern = " ", replacement = "",
gsub(pattern = "\\,", replacement = "", remove))boolVec <- paste0(ts_data$State, ts_data$Coverage,
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 33
ts_data$Metric) %in% remove# making sure I detected each rowsum(boolVec) == length(x)# the outliers b4 they're smoothedoutliers <- ts_data[boolVec, ]
# cleaning these time series by replacing# outlierscleanTS <- function(x, critical = NULL) {
outliers[x, ] %>% select(`2012 Q1`:`2017 Q4`) %>%t() %>% ts(start = c(2012, 1), end = c(2017,4), frequency = 4) %>% tso(type = "AO",cval = critical)
}
smoothedValues <- rbind(c(cleanTS(1)$yadj), c(cleanTS(2)$yadj),c(cleanTS(3, 5)$yadj), c(cleanTS(4)$yadj), c(cleanTS(5,
4.1)$yadj), c(cleanTS(6, 5)$yadj), c(cleanTS(7)$yadj),c(cleanTS(8)$yadj), c(cleanTS(9)$yadj), c(cleanTS(10)$yadj),c(cleanTS(11)$yadj), c(cleanTS(12)$yadj), c(cleanTS(13,
5)$yadj), c(cleanTS(14, 5)$yadj))smoothedValuesDF <- cbind(outliers[, 1:3], smoothedValues)names(smoothedValuesDF) <- names(outliers)
# data frame w/ outliers smoothedtsAdj <- ts_data[!boolVec, ]tsAdj <- tsAdj %>% rbind(smoothedValuesDF) %>% arrange(Coverage,
State, Metric)
# loop through each 612 values and predict the# 4Q data valuedf.1 <- data.frame(Point.Forecast = c(1), Lo.90 = c(1),
Hi.90 = c(1), Lo.95 = c(1), Hi.95 = c(1), Lo.99 = c(1),Hi.99 = c(1))
for (i in 1:nrow(tsAdj)) {ar.fit <- tsAdj[i, ] %>% select(`2012 Q1`:`2017 Q3`) %>%
t() %>% ts(start = c(2012, 1), end = c(2017,3), frequency = 4) %>% auto.arima()
pred <- forecast(ar.fit, h = 1, level = c(90,95, 99)) %>% data.frame()
df.1[i, ] <- pred}
pred.df <- tsAdj %>% select(State, Coverage, Metric,`2017 Q4`) %>% cbind(df.1) %>% data.table()
pred.df$true <- pred.df$`2017 Q4`pred.df[, `:=`(pi, ifelse(true < Lo.99, "<1%", ifelse(true <
Lo.95, "1%-5%", ifelse(true < Lo.90, "5%-10%",ifelse(true < Hi.90, "10%-90%", ifelse(true <
Hi.95, "90%-95%", ifelse(true < Hi.99, "95%-99%",">99%")))))))]
pred.df <- pred.df %>% select(State:Metric, true,
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 34
Point.Forecast, pi)
# Saved the results, and re-read in the datapred.df1 <- read_excel("AutoLossCostv20_2017Q4-TJ.xlsm",
sheet = "Q4Forecast") %>% data.table()state.mappings <- read_excel("AutoLossCostv20_2017Q3_TJ-EH.xlsm",
sheet = "Sheet1")[, 6:8] %>% data.table()ts_adj <- read_excel("AutoLossCostv20_2017Q4-TJ.xlsm",
sheet = "TS_adjusted") %>% data.table()map.data <- pred.df1 %>% left_join(state.mappings,
by = c(State = "Abbreviation")) %>% right_join(map_data("state"),by = c(LCState = "region")) %>% data.table()
# data cleaningpi.levels <- c("<1%", "1%-5%", "5%-10%", "10%-90%",
"90%-95%", "95%-99%", ">99%")map.data[, `:=`(my.col, ifelse(pi == pi.levels[1],
1, ifelse(pi == pi.levels[2], 2, ifelse(pi ==pi.levels[3], 3, ifelse(pi == pi.levels[4],4, ifelse(pi == pi.levels[5], 5, ifelse(pi ==
pi.levels[6], 6, 7)))))))]map.data$pi <- factor(map.data$pi, levels = pi.levels)coverage.df <- data.frame(abrev = c("BI", "Coll",
"Comp", "PD", "PIP"), full = c("Bodily Injury","Collision", "Comprehensive", "Property Damage","Personal Injury Protection"))
# making functions to make maps and ARIMA plotsmake.map <- function(coverage = "PD", metric = "Severity") {
map.dat <- filter(map.data, Coverage == coverage,Metric == metric)
labs <- sort(unique(map.dat$pi))brks <- sort(unique(map.dat$my.col))
if (metric == "LossCost") {plt.title <- paste0(coverage.df$full[coverage.df$abrev ==
coverage], " Loss Cost")} else {
plt.title <- paste0(coverage.df$full[coverage.df$abrev ==coverage], " ", metric)
}
ggplot(data = map.dat) + geom_polygon(aes(x = long,y = lat, fill = my.col, group = group),color = "white") + coord_fixed(1.3) + labs(x = NULL,y = NULL, title = plt.title) + theme_bw() +theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),panel.border = element_blank(), axis.ticks = element_blank(),axis.text = element_blank()) + theme(legend.title = element_blank()) +
guides(fill = guide_legend(reverse = TRUE)) +scale_fill_gradient2(midpoint = 4, low = "blue",
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 35
mid = "grey", high = "red", breaks = brks,labels = labs)
}
arima.plot <- function(state = "AL", coverage = "Comp",metric = "Severity", pi = 90) {dat <- ts_adj %>% filter(State == state, Coverage ==
coverage, Metric == metric)orig <- ts_data %>% filter(State == state, Coverage ==
coverage, Metric == metric) %>% select(`2012 Q1`:`2017 Q4`)true.val <- dat$`2017 Q4`ar.fit <- dat %>% select(`2012 Q1`:`2017 Q3`) %>%
t() %>% ts(start = c(2012, 1), end = c(2017,3), frequency = 4) %>% auto.arima()
params <- arimaorder(ar.fit)pred <- forecast(ar.fit, h = 1, level = pi)upr <- max(select(dat, `2012 Q1`:`2017 Q4`),
pred$upper, orig)lwr <- min(select(dat, `2012 Q1`:`2017 Q4`),
pred$lower, orig)range <- upr - lwrcov.full <- coverage.df$full[coverage.df$abrev ==
coverage]state.full <- state.mappings$State[state.mappings$Abbreviation ==
state]
main.l <- nchar(paste0(state.full, " ", cov.full))
if (metric == "LossCost") {if (main.l >= 28) {
main.title <- paste0(state.full, "\n",cov.full, "\n", " Loss Cost")
} else {main.title <- paste0(state.full, " ",
cov.full, "\n", " Loss Cost")}
} else {if (main.l >= 28) {
main.title <- paste0(state.full, "\n",cov.full, "\n", metric)
} else {main.title <- paste0(state.full, " ",
cov.full, "\n", metric)}
}
plot(pred, ylim = c(lwr - 0.1 * range, upr +0.1 * range), las = 1, main = main.title,xaxt = "n")
lines(c(2017.5, 2017.75), c(dat$`2017 Q3`, dat$`2017 Q4`),col = "black")
points(2017.75, true.val, col = "darkgreen",pch = 19)
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 36
axis(1, at = c(2012:2017), labels = c("'12","'13", "'14", "'15", "'16", "'17"))
Hmisc::minor.tick(nx = 4)
out <- tryCatch(removedBoolean %>% filter(State ==state, Coverage == coverage, Metric == metric) ==FALSE, error = function(x) x)
if (!(any(class(out) == "error"))) {ind <- removedBoolean %>% filter(State ==
state, Coverage == coverage, Metric ==metric) == FALSE
y. <- filter(outliers, State == state, Coverage ==coverage, Metric == metric)[ind] %>%as.numeric()
x. <- names(ts_adj)[ind] %>% as.yearqtr() %>%as.numeric()
points(x., y., col = "orange2", pch = 15)}
}arima.plots <- function(cov, met, loops = "all",
pi = 90) {x <- pred.df1 %>% filter(pi != "10%-90%", Coverage ==
cov, Metric == met) %>% select(State, Coverage,Metric)
if (loops == "all") {for (i in 1:nrow(x)) {
arima.plot(x[i, 1], x[i, 2], x[i, 3],pi)
}} else {
for (i in 1:loops) {arima.plot(x[i, 1], x[i, 2], x[i, 3],
pi)}
}}
# Printing all the maps and plots
## BImake.map("BI", "Frequency")par(mfrow = c(1, 2))arima.plots("BI", "Frequency")l.names <- c("Point Forecast", "True Value", "Prediction Interval",
"Removed Outlier")l.cols <- c("blue", "darkgreen", "grey", "orange2")legend.plt <- function() {
par(mfrow = c(1, 1))par(mar = c(0, 0, 0, 0))plot.new()legend(x = "top", inset = 0, title = "Time Series Legend",
legend = l.names, fill = l.cols, cex = 0.9,
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 37
horiz = TRUE, bty = "n")}
legend.plt()
make.map("BI", "Severity")par(mfrow = c(1, 2))arima.plots("BI", "Severity")legend.plt()
make.map("BI", "LossCost")par(mfrow = c(1, 2))arima.plots("BI", "LossCost")legend.plt()
## Property Damagemake.map("PD", "Frequency")par(mfrow = c(1, 2))arima.plots("PD", "Frequency")legend.plt()
make.map("PD", "Severity")par(mfrow = c(1, 2))arima.plots("PD", "Severity")legend.plt()
make.map("PD", "LossCost")par(mfrow = c(1, 2))arima.plots("PD", "LossCost")legend.plt()
## Comprehensivemake.map("Comp", "Frequency")par(mfrow = c(1, 2))arima.plots("Comp", "Frequency")legend.plt()
make.map("Comp", "Severity")par(mfrow = c(1, 2))arima.plots("Comp", "Severity")legend.plt()
make.map("Comp", "LossCost")par(mfrow = c(1, 2))arima.plots("Comp", "LossCost")legend.plt()
## Collisionmake.map("Coll", "Frequency")par(mfrow = c(1, 2))
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 38
arima.plots("Coll", "Frequency")legend.plt()
make.map("Coll", "Severity")par(mfrow = c(1, 2))arima.plots("Coll", "Severity")legend.plt()
make.map("Coll", "LossCost")par(mfrow = c(1, 2))arima.plots("Coll", "LossCost")legend.plt()
# the PIP analysispip <- read_excel("AutoLossCostv20_2017Q4-TJ.xlsm",
sheet = "PIPdata") %>% select(StateName, Year,Quarter, Frequency__1, Severity__1, LossCost__1) %>%data.table()
names(pip) <- c("State", "year", "quarter", "Frequency","Severity", "LossCost")
pip$time <- paste0(pip$year, " Q", pip$quarter)pip <- pip[!is.na(State), ] %>% select(-year, -quarter)pip <- melt.data.table(pip, id.vars = c("State",
"time"), variable.name = "Metric", value.name = "value")pip <- dcast.data.table(pip, State + Metric ~ time,
fun.aggregate = sum)# removing CW and DCpip <- pip[!(pip$State %in% c("CW", "DC")), ]
missing.df <- data.frame(State = "0", Start = 0,End = 0, Data.Missing = 0)
statez <- unique(pip$State)
missing.fun <- function(state) {temp <- pip %>% filter(State == state, Metric ==
"Frequency") %>% data.table()temp <- melt.data.table(temp, id.vars = c("State",
"Metric"), variable.name = "time")temp$time <- as.yearqtr(temp$time, format = "%Y Q%q")times <- temp[temp$value != 0, ]$timefirst <- times[1]last <- times[length(times)]numMis.inbetween <- sum(temp$value[inds <- temp$time >
first & temp$time < last] == 0)data.frame(State = state, Start = first, End = last,
Data.Missing = numMis.inbetween)}
for (i in 1:length(statez)) {missing.df <- rbind(missing.df, missing.fun(statez[i]))
}state.df <- missing.df[-1, ]
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 39
state.df$Data.Missing <- NULLstate.df$End <- as.yearqtr(state.df$End, format = "%Y Q%q")state.df$Start <- as.yearqtr(state.df$Start, format = "%Y Q%q")row.names(state.df) <- NULL
# Put on ggplotstate.df3 <- state.df %>% data.table()state.df3$Start <- state.df3$Start %>% as.numeric()state.df3$End <- state.df3$End %>% as.numeric()state.df3 <- melt.data.table(state.df3, id.vars = "State",
variable.name = "When", value.name = "Times")state.df3 <- state.df3 %>% arrange(desc(State))ggplot(state.df3, aes(x = State, y = Times, group = State)) +
geom_point(color = "steelblue") + geom_line(color = "steelblue") +coord_flip() + labs(title = "When the PIP Data Begin and End",y = NULL) + theme(legend.position = "none") +theme_bw() + theme(panel.border = element_blank()) +scale_x_discrete(limits = rev(levels(state.df3$State)[-1]))
missing.df <- data.frame(State = "0", Start = 0,End = 0, Data.Missing = 0)
missing.fun <- function(state) {temp <- pip %>% filter(State == state, Metric ==
"Frequency") %>% data.table()temp <- melt.data.table(temp, id.vars = c("State",
"Metric"), variable.name = "time")temp$time <- as.yearqtr(temp$time, format = "%Y Q%q")times <- temp[temp$value != 0, ]$timefirst <- times[1]last <- times[length(times)]numMis.inbetween <- sum(temp$value[inds <- temp$time >
first & temp$time < last] == 0)data.frame(State = state, Start = first, End = last,
Data.Missing = numMis.inbetween)}
for (i in 1:length(statez)) {missing.df <- rbind(missing.df, missing.fun(statez[i]))
}state.df <- missing.df[-1, ]state.df$Data.Missing <- NULLstate.df$End <- as.yearqtr(state.df$End, format = "%Y Q%q")state.df$Start <- as.yearqtr(state.df$Start, format = "%Y Q%q")row.names(state.df) <- NULL
tsdat <- pip[pip$`2017 Q4` != 0, ]pip.pred.plot <- function(st, met, PI = 90) {
start.date <- state.df %>% filter(State == st) %>%select(Start)
loop.dat <- tsdat %>% filter(State == st, Metric ==met) %>% select(-State, -Metric) %>% t()
inds <- row.names(loop.dat) %>% as.yearqtr() >=start.date
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 40
loop.dat <- loop.dat[inds, ]true <- loop.dat[length(loop.dat)]loop.dat <- loop.dat[-length(loop.dat)]loop.ts <- ts(loop.dat, start = c(as.numeric(substr(start.date,
0, 4)), as.numeric(substr(start.date, 4,5))), end = c(2017, 3), frequency = 4)
fit <- auto.arima(loop.ts)fc <- forecast(fit, h = 1, level = PI)min. <- min(loop.dat, true, fc$lower)max. <- max(loop.dat, true, fc$upper)params <- arimaorder(fit)cov.full <- coverage.df$full[coverage.df$abrev ==
"PIP"]state.full <- state.mappings$State[state.mappings$Abbreviation ==
st]
if (met == "LossCost") {main.title <- paste0(state.full, "\n", cov.full,
"\n", "Loss Cost")} else {
main.title <- paste0(state.full, "\n", cov.full,"\n", met)
}
plot(fc, ylim = c(min. - 0.1 * (max. - min.),max. + 0.1 * (max. - min.)), main = main.title,las = 1, axt = "n")
lines(c(2017.5, 2017.75), c(loop.ts[length(loop.ts)],true), col = "black")
points(2017.75, true, col = "darkgreen", pch = 19)axis(1, at = c(2012:2017), labels = c("'12",
"'13", "'14", "'15", "'16", "'17"))Hmisc::minor.tick(nx = 4)
}
par(mfrow = c(1, 2))pip.pred.plot("KY", "LossCost", 90)pip.pred.plot("ND", "Severity", 90)pip.pred.plot("NJ", "Frequency", 90)pip.pred.plot("NJ", "LossCost", 90)pip.pred.plot("NY", "Severity", 90)pip.pred.plot("NY", "LossCost", 90)legend.plt()
August 2018 | Auto Loss Cost Trends : Q4 2017 | © CAS, PCI, and SOA | 41