#Load Necessary Libraries
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(dplyr)
library(readr)
library(MASS)
##
## Attaching package: 'MASS'
##
## The following object is masked from 'package:dplyr':
##
## select
library(ggplot2)
library(GGally)
## Warning: package 'GGally' was built under R version 4.4.3
## Registered S3 method overwritten by 'GGally':
## method from
## +.gg ggplot2
Firstly we take important Libraries so we can perform our next task
insurance_data = read_csv("C:/Users/LENOVO/Downloads/insurance.zip")
## Rows: 10000 Columns: 27
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (6): Marital_Status, Prior_Insurance, Claims_Severity, Policy_Type, Sou...
## dbl (21): Age, Is_Senior, Married_Premium_Discount, Prior_Insurance_Premium_...
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
View(insurance_data)
We started by loading the insurance dataset using read_csv() and viewed it with View() to familiarize ourselves with the data.
#Look the structure & Summarization of dataset
glimpse(insurance_data)
## Rows: 10,000
## Columns: 27
## $ Age <dbl> 47, 37, 49, 62, 36, 36, 63, 51, 32,…
## $ Is_Senior <dbl> 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0,…
## $ Marital_Status <chr> "Married", "Married", "Married", "M…
## $ Married_Premium_Discount <dbl> 86, 86, 86, 86, 0, 86, 86, 0, 86, 0…
## $ Prior_Insurance <chr> "1-5 years", "1-5 years", "1-5 year…
## $ Prior_Insurance_Premium_Adjustment <dbl> 50, 50, 50, 0, 0, 0, 50, 100, 0, 0,…
## $ Claims_Frequency <dbl> 0, 0, 1, 1, 2, 0, 0, 0, 0, 1, 1, 1,…
## $ Claims_Severity <chr> "Low", "Low", "Low", "Low", "Low", …
## $ Claims_Adjustment <dbl> 0, 0, 50, 50, 100, 0, 0, 0, 0, 200,…
## $ Policy_Type <chr> "Full Coverage", "Full Coverage", "…
## $ Policy_Adjustment <dbl> 0, 0, 0, 0, 0, -200, 0, 0, -200, 0,…
## $ Premium_Amount <dbl> 2286, 2336, 2386, 2336, 2350, 1936,…
## $ Safe_Driver_Discount <dbl> 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,…
## $ Multi_Policy_Discount <dbl> 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0,…
## $ Bundling_Discount <dbl> 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,…
## $ Total_Discounts <dbl> 0, 0, 0, 0, 0, 50, 50, 50, 50, 50, …
## $ Source_of_Lead <chr> "Agent", "Online", "Online", "Onlin…
## $ Time_Since_First_Contact <dbl> 10, 22, 28, 4, 14, 13, 2, 1, 16, 27…
## $ Conversion_Status <dbl> 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1,…
## $ Website_Visits <dbl> 5, 5, 4, 6, 8, 4, 5, 3, 5, 5, 3, 3,…
## $ Inquiries <dbl> 1, 1, 4, 2, 4, 1, 1, 0, 1, 3, 2, 1,…
## $ Quotes_Requested <dbl> 2, 2, 1, 2, 2, 1, 2, 2, 3, 2, 1, 3,…
## $ Time_to_Conversion <dbl> 99, 99, 99, 2, 10, 7, 1, 99, 3, 99,…
## $ Credit_Score <dbl> 704, 726, 772, 809, 662, 729, 795, …
## $ Premium_Adjustment_Credit <dbl> -50, -50, -50, -50, 50, -50, -50, 5…
## $ Region <chr> "Suburban", "Urban", "Urban", "Urba…
## $ Premium_Adjustment_Region <dbl> 50, 100, 100, 100, 50, 0, 100, 50, …
summary(insurance_data)
## Age Is_Senior Marital_Status Married_Premium_Discount
## Min. :18.00 Min. :0.0000 Length:10000 Min. : 0.00
## 1st Qu.:29.00 1st Qu.:0.0000 Class :character 1st Qu.: 0.00
## Median :39.00 Median :0.0000 Mode :character Median : 0.00
## Mean :39.99 Mean :0.1593 Mean :42.13
## 3rd Qu.:50.00 3rd Qu.:0.0000 3rd Qu.:86.00
## Max. :90.00 Max. :1.0000 Max. :86.00
## Prior_Insurance Prior_Insurance_Premium_Adjustment Claims_Frequency
## Length:10000 Min. : 0.00 Min. :0.0000
## Class :character 1st Qu.: 0.00 1st Qu.:0.0000
## Mode :character Median : 50.00 Median :0.0000
## Mean : 47.62 Mean :0.4972
## 3rd Qu.: 50.00 3rd Qu.:1.0000
## Max. :100.00 Max. :5.0000
## Claims_Severity Claims_Adjustment Policy_Type Policy_Adjustment
## Length:10000 Min. : 0.00 Length:10000 Min. :-200.00
## Class :character 1st Qu.: 0.00 Class :character 1st Qu.:-200.00
## Mode :character Median : 0.00 Mode :character Median : 0.00
## Mean : 36.78 Mean : -79.86
## 3rd Qu.: 50.00 3rd Qu.: 0.00
## Max. :800.00 Max. : 0.00
## Premium_Amount Safe_Driver_Discount Multi_Policy_Discount Bundling_Discount
## Min. :1800 Min. :0.0000 Min. :0.0000 Min. :0.0000
## 1st Qu.:2100 1st Qu.:0.0000 1st Qu.:0.0000 1st Qu.:0.0000
## Median :2236 Median :0.0000 Median :0.0000 Median :0.0000
## Mean :2220 Mean :0.1999 Mean :0.3051 Mean :0.0972
## 3rd Qu.:2336 3rd Qu.:0.0000 3rd Qu.:1.0000 3rd Qu.:0.0000
## Max. :2936 Max. :1.0000 Max. :1.0000 Max. :1.0000
## Total_Discounts Source_of_Lead Time_Since_First_Contact Conversion_Status
## Min. : 0.00 Length:10000 Min. : 1.00 Min. :0.0000
## 1st Qu.: 0.00 Class :character 1st Qu.: 8.00 1st Qu.:0.0000
## Median : 50.00 Mode :character Median :16.00 Median :1.0000
## Mean : 30.11 Mean :15.48 Mean :0.5767
## 3rd Qu.: 50.00 3rd Qu.:23.00 3rd Qu.:1.0000
## Max. :150.00 Max. :30.00 Max. :1.0000
## Website_Visits Inquiries Quotes_Requested Time_to_Conversion
## Min. : 0.000 Min. :0.000 Min. :1.000 Min. : 1.00
## 1st Qu.: 3.000 1st Qu.:1.000 1st Qu.:1.000 1st Qu.: 6.00
## Median : 5.000 Median :2.000 Median :2.000 Median :12.00
## Mean : 5.023 Mean :1.997 Mean :1.997 Mean :46.07
## 3rd Qu.: 6.000 3rd Qu.:3.000 3rd Qu.:3.000 3rd Qu.:99.00
## Max. :16.000 Max. :9.000 Max. :3.000 Max. :99.00
## Credit_Score Premium_Adjustment_Credit Region
## Min. :530.0 Min. :-50.00 Length:10000
## 1st Qu.:681.0 1st Qu.:-50.00 Class :character
## Median :715.0 Median :-50.00 Mode :character
## Mean :714.3 Mean :-11.32
## 3rd Qu.:748.0 3rd Qu.: 50.00
## Max. :850.0 Max. : 50.00
## Premium_Adjustment_Region
## Min. : 0.00
## 1st Qu.: 50.00
## Median : 50.00
## Mean : 64.33
## 3rd Qu.:100.00
## Max. :100.00
We then used glimpse() to get a quick overview of the dataset’s structure and summary() to understand the statistical properties of each variable.
sum(is.na(insurance_data))
## [1] 0
We checked for any missing values using sum(is.na()) and found whether our data was complete.
#Remove Duplicate Records
insurance_data = distinct(insurance_data)
distinct(insurance_data)
## # A tibble: 10,000 × 27
## Age Is_Senior Marital_Status Married_Premium_Discount Prior_Insurance
## <dbl> <dbl> <chr> <dbl> <chr>
## 1 47 0 Married 86 1-5 years
## 2 37 0 Married 86 1-5 years
## 3 49 0 Married 86 1-5 years
## 4 62 1 Married 86 >5 years
## 5 36 0 Single 0 >5 years
## 6 36 0 Married 86 >5 years
## 7 63 1 Married 86 1-5 years
## 8 51 0 Single 0 <1 year
## 9 32 0 Married 86 >5 years
## 10 48 0 Single 0 >5 years
## # ℹ 9,990 more rows
## # ℹ 22 more variables: Prior_Insurance_Premium_Adjustment <dbl>,
## # Claims_Frequency <dbl>, Claims_Severity <chr>, Claims_Adjustment <dbl>,
## # Policy_Type <chr>, Policy_Adjustment <dbl>, Premium_Amount <dbl>,
## # Safe_Driver_Discount <dbl>, Multi_Policy_Discount <dbl>,
## # Bundling_Discount <dbl>, Total_Discounts <dbl>, Source_of_Lead <chr>,
## # Time_Since_First_Contact <dbl>, Conversion_Status <dbl>, …
We removed any duplicate records by applying distinct(), ensuring that our dataset only contains unique observations.
average_age = mean(insurance_data$Age)
print(paste("Average Age:", average_age))
## [1] "Average Age: 39.9917"
We calculated the average age of the policyholders to understand the typical customer profile.
#Proportion of senior citizens
proportion_senior = mean(insurance_data$Is_Senior)
print(paste("Proportion of Senior Citizens:", proportion_senior))
## [1] "Proportion of Senior Citizens: 0.1593"
We found the proportion of senior citizens by taking the mean of the Is_Senior column.
#Distribution of marital status
marital_status_dist = insurance_data %>%
group_by(Marital_Status) %>%
summarise(count = n())
print(marital_status_dist)
## # A tibble: 4 × 2
## Marital_Status count
## <chr> <int>
## 1 Divorced 920
## 2 Married 4899
## 3 Single 3259
## 4 Widowed 922
We examined the distribution of marital status by grouping and counting the number of policyholders in each category.
#Average premium amount
average_premium = mean(insurance_data$Premium_Amount)
print(paste("Average Premium Amount:", average_premium))
## [1] "Average Premium Amount: 2219.5714"
We computed the average premium amount to get a sense of the typical insurance cost.
#Average premium amount for each region
average_premium_region = insurance_data %>%
group_by(Region) %>%
summarise(average_premium = mean(Premium_Amount))
print(average_premium_region)
## # A tibble: 3 × 2
## Region average_premium
## <chr> <dbl>
## 1 Rural 2157.
## 2 Suburban 2202.
## 3 Urban 2256.
We analyzed the average premium amount across different regions to see if there were any geographical differences.
#Distribution of claims frequency
claims_frequency_dist = insurance_data %>%
group_by(Claims_Frequency) %>%
summarise(count = n())
print(claims_frequency_dist)
## # A tibble: 6 × 2
## Claims_Frequency count
## <dbl> <int>
## 1 0 6126
## 2 1 2965
## 3 2 745
## 4 3 141
## 5 4 21
## 6 5 2
We explored the distribution of claims frequency by counting occurrences in category.
#Distribution of claims severity
claims_severity_dist = insurance_data %>%
group_by(Claims_Severity) %>%
summarise(count = n())
print(claims_severity_dist)
## # A tibble: 3 × 2
## Claims_Severity count
## <chr> <int>
## 1 High 959
## 2 Low 7003
## 3 Medium 2038
We explored the distribution of claims severity by counting occurrences in category.
#Average age by marital status
average_age_marital_status = insurance_data %>%
group_by(Marital_Status) %>%
summarise(average_age = mean(Age))
print(average_age_marital_status)
## # A tibble: 4 × 2
## Marital_Status average_age
## <chr> <dbl>
## 1 Divorced 42.3
## 2 Married 39.8
## 3 Single 39.1
## 4 Widowed 41.8
We calculated the average age by marital status to check if age varies between different marital statuses.
#Most common claims severity
common_claims_severity = insurance_data %>%
group_by(Claims_Severity) %>%
summarise(count = n()) %>%
arrange(desc(count)) %>%
slice(1)
print(common_claims_severity)
## # A tibble: 1 × 2
## Claims_Severity count
## <chr> <int>
## 1 Low 7003
We identified the most common claims severity level among the policyholders.
#Correlation between Age and Premium Amount
correlation_age_premium = cor(insurance_data$Age, insurance_data$Premium_Amount)
print(paste("Correlation between Age and Premium Amount:", correlation_age_premium))
## [1] "Correlation between Age and Premium Amount: -0.0295406633794125"
We calculated the correlation between age and premium amount to understand if age impacts how much premium a person pays.
#Correlation between Prior Insurance Premium Adjustment and Current Premium Amount
correlation_prior_current_premium = cor(
insurance_data$Prior_Insurance_Premium_Adjustment,
insurance_data$Premium_Amount)
print(paste("Correlation between Prior Insurance Premium Adjustment and Current Premium Amount:", correlation_prior_current_premium))
## [1] "Correlation between Prior Insurance Premium Adjustment and Current Premium Amount: 0.234540830168632"
We measured the correlation between prior insurance premium adjustments and current premium amounts to see if there was any relationship.
#Effect of Prior Insurance on Claims Frequency and Severity
prior_insurance_effect = insurance_data %>%
group_by(Prior_Insurance) %>%
summarise(
average_claims_frequency = mean(Claims_Frequency),
average_claims_severity = mean(as.numeric(Claims_Severity))
)
## Warning: There were 3 warnings in `summarise()`.
## The first warning was:
## ℹ In argument: `average_claims_severity = mean(as.numeric(Claims_Severity))`.
## ℹ In group 1: `Prior_Insurance = "1-5 years"`.
## Caused by warning in `mean()`:
## ! NAs introduced by coercion
## ℹ Run `dplyr::last_dplyr_warnings()` to see the 2 remaining warnings.
print(prior_insurance_effect)
## # A tibble: 3 × 3
## Prior_Insurance average_claims_frequency average_claims_severity
## <chr> <dbl> <dbl>
## 1 1-5 years 0.492 NA
## 2 <1 year 0.493 NA
## 3 >5 years 0.512 NA
We analyzed how prior insurance affects claims frequency and severity by grouping and summarizing the data.
#Relationship between Policy Type and Premium Amount
policy_type_premium = insurance_data %>%
group_by(Policy_Type) %>%
summarise(average_premium = mean(Premium_Amount))
print(policy_type_premium)
## # A tibble: 2 × 2
## Policy_Type average_premium
## <chr> <dbl>
## 1 Full Coverage 2300.
## 2 Liability-Only 2099.
We checked how the type of policy affects the average premium by grouping data by Policy_Type.
#Categorizing Credit Score Ranges
insurance_data = insurance_data %>%
mutate(Credit_Score_Range = case_when(
Credit_Score >= 750 ~ "Excellent (750+)",
Credit_Score >= 700 & Credit_Score < 750 ~ "Good (700-749)",
Credit_Score >= 650 & Credit_Score < 700 ~ "Fair (650-699)",
Credit_Score < 650 ~ "Poor (<650)"
))
We categorized credit scores into meaningful ranges (Excellent, Good, Fair, Poor) to better segment the customers. Its create One another Column in dataset
#Average premium amount by Credit Score Range
average_premium_credit_score = insurance_data %>%
group_by(Credit_Score_Range) %>%
summarise(average_premium = mean(Premium_Amount))
print(average_premium_credit_score)
## # A tibble: 4 × 2
## Credit_Score_Range average_premium
## <chr> <dbl>
## 1 Excellent (750+) 2184.
## 2 Fair (650-699) 2279.
## 3 Good (700-749) 2182.
## 4 Poor (<650) 2284.
We calculated the average premium amount for each credit score range to see if creditworthiness affects premiums.
#Premium differences by Marital Status
premium_marital_status = insurance_data %>%
group_by(Marital_Status) %>%
summarise(average_premium = mean(Premium_Amount))
print(premium_marital_status)
## # A tibble: 4 × 2
## Marital_Status average_premium
## <chr> <dbl>
## 1 Divorced 2173.
## 2 Married 2264.
## 3 Single 2179.
## 4 Widowed 2175.
We compared premium differences across different marital statuses.
#Claims Frequency differences by Policy Type
claims_frequency_policy = insurance_data %>%
group_by(Policy_Type) %>%
summarise(average_claims_frequency = mean(Claims_Frequency))
print(claims_frequency_policy)
## # A tibble: 2 × 2
## Policy_Type average_claims_frequency
## <chr> <dbl>
## 1 Full Coverage 0.497
## 2 Liability-Only 0.497
We examined how claims frequency varies across different policy types.
#Claims Adjustment by Policy Type
claims_adjustment_policy = insurance_data %>%
group_by(Policy_Type) %>%
summarise(average_claims_adjustment = mean(Claims_Adjustment))
print(claims_adjustment_policy)
## # A tibble: 2 × 2
## Policy_Type average_claims_adjustment
## <chr> <dbl>
## 1 Full Coverage 36.4
## 2 Liability-Only 37.3
We studied how claims adjustment differs between various policy types.
#Effect of Prior Insurance Premium Adjustment on Current Premium Amount
effect_prior_insurance = insurance_data %>%
group_by(Prior_Insurance_Premium_Adjustment) %>%
summarise(average_current_premium = mean(Premium_Amount))
print(effect_prior_insurance)
## # A tibble: 3 × 2
## Prior_Insurance_Premium_Adjustment average_current_premium
## <dbl> <dbl>
## 1 0 2174.
## 2 50 2220.
## 3 100 2276.
We studied how claims adjustment differs between various policy types.
#Effect of Claims Adjustment on Premium Amount
effect_claims_adjustment = insurance_data %>%
group_by(Claims_Adjustment) %>%
summarise(average_premium_amount = mean(Premium_Amount))
print(effect_claims_adjustment)
## # A tibble: 10 × 2
## Claims_Adjustment average_premium_amount
## <dbl> <dbl>
## 1 0 2183.
## 2 50 2229.
## 3 100 2289.
## 4 150 2334.
## 5 200 2379.
## 6 250 2443
## 7 300 2484.
## 8 400 2560.
## 9 600 2802.
## 10 800 2900
We also explored how claims adjustment levels are related to premium amounts.
#Predict Premium Amount based on Age and Credit Score
Predict_Premium_Amount = lm(Premium_Amount ~ Age + Credit_Score, data = insurance_data)
summary(Predict_Premium_Amount)
##
## Call:
## lm(formula = Premium_Amount ~ Age + Credit_Score, data = insurance_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -426.41 -105.61 8.95 102.44 758.00
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 2767.44236 21.07567 131.310 <2e-16 ***
## Age -0.30694 0.10229 -3.001 0.0027 **
## Credit_Score -0.74987 0.02889 -25.958 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 143.7 on 9997 degrees of freedom
## Multiple R-squared: 0.06396, Adjusted R-squared: 0.06378
## F-statistic: 341.6 on 2 and 9997 DF, p-value: < 2.2e-16
We built a linear regression model to predict premium amount based on age and credit score.This helped us understand the impact of these factors on the premium. summary() tells you how well the model fits, coefficients, R-squared, etc.
#Predict Claims Frequency based on Age, Credit Score, and Prior Insurance
Predict_Claims_Frequency = lm(Claims_Frequency ~ Age + Credit_Score + Prior_Insurance, data = insurance_data)
summary(Predict_Claims_Frequency)
##
## Call:
## lm(formula = Claims_Frequency ~ Age + Credit_Score + Prior_Insurance,
## data = insurance_data)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.5240 -0.4973 -0.4882 0.5041 4.5204
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.855e-01 1.059e-01 4.586 4.57e-06 ***
## Age -3.698e-04 5.137e-04 -0.720 0.472
## Credit_Score 3.103e-05 1.440e-04 0.216 0.829
## Prior_Insurance>5 years 1.991e-02 2.103e-02 0.947 0.344
## Prior_Insurance1-5 years -1.628e-03 1.839e-02 -0.089 0.929
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.7162 on 9995 degrees of freedom
## Multiple R-squared: 0.000202, Adjusted R-squared: -0.0001981
## F-statistic: 0.5049 on 4 and 9995 DF, p-value: 0.7322
We developed another linear regression model to predict claims frequency using age, credit score, and prior insurance status. This model allowed us to study the factors affecting how often customers make claims.
#Premium Amount difference across Marital Status
Premium_Amount_Across_Marital_Status = aov(Premium_Amount ~ Marital_Status, data = insurance_data)
summary(Premium_Amount_Across_Marital_Status)
## Df Sum Sq Mean Sq F value Pr(>F)
## Marital_Status 3 18779068 6259689 310.1 <2e-16 ***
## Residuals 9996 201784139 20186
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
We performed a one-way ANOVA to determine whether the average Premium Amount differs significantly across different Marital Status groups (Single, Married, Divorced, etc.).
Null Hypothesis (H₀): There is no difference in Premium Amount between marital status groups. Alternative Hypothesis (H₁): At least one group has a different mean Premium Amount If the p-value is less than 0.05, we reject the null hypothesis, meaning that marital status does impact the Premium Amount. Conclusion Example: If p-value = 0.002 → “There is a significant difference in Premium Amount between marital status groups.”
#Claims Frequency difference across Policy Type
Claims_Frequency_across_Policy_Type = aov(Claims_Frequency ~ Policy_Type, data = insurance_data)
summary(Claims_Frequency_across_Policy_Type)
## Df Sum Sq Mean Sq F value Pr(>F)
## Policy_Type 1 0 0.0000 0 0.993
## Residuals 9998 5128 0.5129
We conducted a one-way ANOVA to check if the Claims Frequency significantly varies across different Policy Types. Null Hypothesis (H₀): The mean Claims Frequency is the same for all Policy Types. Alternative Hypothesis (H₁): At least one Policy Type has a different mean Claims Frequency. If the p-value is less than 0.05, we conclude that Policy Type affects how frequently claims are made. Conclusion Example: If p-value = 0.01 → “There is a significant difference in Claims Frequency between Policy Types, indicating that certain policy types are riskier.”
#Premium Amount difference across Regions
Premium_Amount_difference_across_Regions = aov(Premium_Amount ~ Region, data = insurance_data)
summary(Premium_Amount_difference_across_Regions)
## Df Sum Sq Mean Sq F value Pr(>F)
## Region 2 15632513 7816257 381.3 <2e-16 ***
## Residuals 9997 204930694 20499
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
We performed a one-way ANOVA to investigate whether the Premium Amount significantly differs across different Regions. Null Hypothesis (H₀): The mean Premium Amount is the same across all regions. Alternative Hypothesis (H₁): At least one region has a different mean Premium Amount. A p-value less than 0.05 would suggest that the Premium Amount varies significantly by Region. Conclusion Example: If p-value = 0.04 → “Premiums differ significantly across regions, suggesting that geographic factors influence pricing.”
#Website Visits vs Premium Amount
ggplot(insurance_data, aes(x = Website_Visits, y = Premium_Amount)) +
geom_point(alpha = 0.5, color = "purple") +
geom_smooth(method = "lm", color = "red", se = TRUE) +
labs(title = "Relationship Between Website Visits and Premium Amount",
x = "Website Visits", y = "Premium Amount") +
theme_minimal()
## `geom_smooth()` using formula = 'y ~ x'
We visualized the relationship between website visits and premium
amount using a scatter plot with a linear trend line.
#Boxplot of Age by Marital Status
ggplot(insurance_data, aes(x = Marital_Status, y = Age, fill = Marital_Status)) +
geom_boxplot(outlier.color = "red", notch = TRUE) +
labs(title = "Boxplot of Age by Marital Status", x = "Marital Status", y = "Age") +
theme_minimal()
We created a boxplot to compare the age distributions across
different marital statuses.
#Histogram of Credit Score
ggplot(insurance_data, aes(x = Credit_Score)) +
geom_histogram(binwidth = 5, fill = "green", color = "black") +
labs(title = "Histogram of Credit Score", x = "Credit Score") +
theme_minimal()
We plotted a histogram to explore the distribution of credit scores
among policyholders.
#Customer Distribution across Regions
insurance_data %>%
group_by(Region) %>%
summarise(Count = n()) %>%
ggplot(aes(x = "", y = Count, fill = Region)) +
geom_col(width = 1) +
coord_polar(theta = "y") +
labs(title = "Distribution of Customers Across Regions") +
theme_void()
We displayed the customer distribution across different regions
using a pie chart to understand regional variations.
#Claims Severity Distribution
insurance_data %>%
group_by(Claims_Severity) %>%
summarise(Count = n()) %>%
ggplot(aes(x = "", y = Count, fill = Claims_Severity)) +
geom_col(width = 1) +
coord_polar(theta = "y") +
labs(title = "Distribution of Claims Severity") +
theme_void()
We visualized the distribution of claims severity levels using both
a pie chart and a bar chart.
#Premium Amount by Credit Score Range
insurance_data %>%
group_by(Credit_Score_Range) %>%
summarise(Average_Premium = mean(Premium_Amount, na.rm = TRUE)) %>%
ggplot(aes(x = Credit_Score_Range, y = Average_Premium, fill = Credit_Score_Range)) +
geom_col() +
labs(title = "Average Premium by Credit Score Range", x = "Credit Score Range", y = "Average Premium") +
theme_minimal()
We showed how average premium amounts vary across different credit
score ranges with a bar chart.
#Senior vs Non-Senior Citizens Distribution
insurance_data %>%
mutate(Senior_Status = ifelse(Is_Senior == 1, "Senior Citizen", "Non-Senior")) %>%
group_by(Senior_Status) %>%
summarise(Count = n()) %>%
ggplot(aes(x = "", y = Count, fill = Senior_Status)) +
geom_col(width = 1) +
coord_polar(theta = "y") +
labs(title = "Senior Citizens vs Non-Senior Citizens") +
theme_void()
We compared the number of senior and non-senior citizens using a pie
chart to understand the senior citizen customer base.
#Claims Severity Distribution
insurance_data %>%
group_by(Claims_Severity) %>%
summarise(Count = n()) %>%
ggplot(aes(x = Claims_Severity, y = Count, fill = Claims_Severity)) +
geom_col() +
labs(title = "Distribution of Claims Severity", x = "Claims Severity Level", y = "Number of Policyholders") +
theme_minimal()
We visualized claims severity distribution again through a bar chart
for a different perspective.
#How does the Average Premium Amount change with increasing Age?
age_premium_trend <- insurance_data %>%
group_by(Age) %>%
summarise(Average_Premium = mean(Premium_Amount, na.rm = TRUE))
ggplot(age_premium_trend, aes(x = Age, y = Average_Premium)) +
geom_line(color = "blue", size = 1) +
geom_point(color = "red", size = 1.5) +
labs(title = "Trend of Average Premium Amount with Age",
x = "Age of Policyholders",
y = "Average Premium Amount") +
theme_minimal()
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
The line chart shows how the average premium amount changes as the
age of policyholders increases. A rising trend would suggest
that older customers generally pay higher premiums, possibly due to
increased insurance risks. Any dips might suggest discounts or
different premium structures for certain age groups.
#Pairplot of Selected Features
insurance_subset <- insurance_data[, c("Premium_Amount", "Total_Discounts", "Credit_Score", "Region")]
ggpairs(insurance_subset,
columns = 1:4,
aes(color = Region),
title = "Pairplot of Selected Features from Insurance Dataset")
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Finally, we created a pairplot of selected features — Premium
Amount, Total Discounts, Credit Score, and Region — to study the
relationships between these important variables.