379.CAN SAS DELIVER END-TO-END TLF (TABLES, LISTINGS, AND FIGURES) FOR INSURANCE CLAIMS ANALYSIS?

CAN SAS DELIVER END-TO-END TLF (TABLES, LISTINGS, AND FIGURES) FOR INSURANCE CLAIMS ANALYSIS?


HERE IN THIS PROJECT WE USED THESE SAS STATEMENTS —
DATA STEP | PROC SQL | PROC REPORT | PROC PRINT | PROC SGPLOT | MACROS | TABLES | LISTINGS | FIGURES

1. What is TLF in Insurance Analytics?

In clinical trials, TLF means:

Tables
Listings
Figures

In insurance analytics, TLF means:

Clinical Trials

Insurance Analytics

Tables

Claim summaries, fraud exposure

Listings

Claim-level audit reports

Figures

Risk distribution charts

Insurance companies must submit:

• Fraud exposure reports
• Claim approval summaries
• High-risk case listings
• Settlement turnaround reports


2. Where TLF fits in the Insurance Claim Lifecycle

Real insurance workflow:

1.     Claims submitted

2.     Risk calculated

3.     Fraud flagged

4.     Claims settled

5.     Regulatory reporting

Auditors, regulators, and management never see raw SAS datasets — they see:

• Tables
• Listings
• Figures


3. Insurance ADaM-like Analysis Dataset

Just like clinical ADaM, we use claims_flagged as the analysis dataset.

It contains:

• Claim_ID
• Policy_Type
• Claim_Amount
• Approval_Time
• Days_To_Submit
• Risk_Score
• Fraud_Category
• Settlement_Status


4. TLF Plan (Just like SAP in Clinical Trials)

Before writing code, professionals write a TLF Plan.

No

Output Type

Purpose

T1

Fraud Summary Table

Management risk view

T2

Settlement Summary Table

Operations efficiency

L1

High-Risk Claims Listing

Investigator review

L2

Pending Claims Listing

Operations team

F1

Risk Distribution Figure

Fraud modeling

F2

Claim Amount vs Risk

Financial exposure



5. Creating Raw Insurance Claims Dataset

data claims_raw;

    format Claim_Date Submission_Date date9.;

    input Claim_ID $ Policy_Type $ Claim_Amount Approval_Time Fraud_Flag$ Settlement_Status $ 

          Claim_Date:date9. Submission_Date:date9.;

    datalines;

C001 Health 120000 5 N Approved 01JAN2024 28DEC2023

C002 Motor 450000 12 Y Pending 05JAN2024 20DEC2023

C003 Travel 60000 3 N Approved 10JAN2024 08JAN2024

C004 Property 950000 25 Y Rejected 12JAN2024 01JAN2024

C005 Health 180000 7 N Approved 15JAN2024 10JAN2024

C006 Motor 320000 15 Y Pending 18JAN2024 02JAN2024

C007 Health 75000 4 N Approved 20JAN2024 17JAN2024

C008 Property 1500000 30 Y Rejected 25JAN2024 05JAN2024

C009 Travel 45000 2 N Approved 28JAN2024 27JAN2024

C010 Motor 280000 10 N Approved 30JAN2024 20JAN2024

C011 Health 220000 9 N Approved 02FEB2024 25JAN2024

C012 Property 680000 18 Y Pending 05FEB2024 15JAN2024

C013 Travel 55000 3 N Approved 07FEB2024 06FEB2024

C014 Motor 410000 14 Y Pending 10FEB2024 28JAN2024

C015 Health 195000 8 N Approved 12FEB2024 05FEB2024

;

run;

proc print data=claims_raw;

run;

OUTPUT:

ObsClaim_DateSubmission_DateClaim_IDPolicy_TypeClaim_AmountApproval_TimeFraud_FlagSettlement_Status
101JAN202428DEC2023C001Health1200005NApproved
205JAN202420DEC2023C002Motor45000012YPending
310JAN202408JAN2024C003Travel600003NApproved
412JAN202401JAN2024C004Property95000025YRejected
515JAN202410JAN2024C005Health1800007NApproved
618JAN202402JAN2024C006Motor32000015YPending
720JAN202417JAN2024C007Health750004NApproved
825JAN202405JAN2024C008Property150000030YRejected
928JAN202427JAN2024C009Travel450002NApproved
1030JAN202420JAN2024C010Motor28000010NApproved
1102FEB202425JAN2024C011Health2200009NApproved
1205FEB202415JAN2024C012Property68000018YPending
1307FEB202406FEB2024C013Travel550003NApproved
1410FEB202428JAN2024C014Motor41000014YPending
1512FEB202405FEB2024C015Health1950008NApproved


6. Date Calculations using INTCK

data claims_dates;

    set claims_raw;

    Days_To_Submit = intck('day', Submission_Date, Claim_Date);

run;

proc print data=claims_dates;

var Claim_ID  Policy_Type Days_To_Submit;

run;

OUTPUT:

ObsClaim_IDPolicy_TypeDays_To_Submit
1C001Health4
2C002Motor16
3C003Travel2
4C004Property11
5C005Health5
6C006Motor16
7C007Health3
8C008Property20
9C009Travel1
10C010Motor10
11C011Health8
12C012Property21
13C013Travel1
14C014Motor13
15C015Health7


7. Risk Score Calculation

data claims_risk;

    set claims_dates;

    Risk_Score = (Claim_Amount/10000) + Approval_Time + (Days_To_Submit*2);

run;

proc print data=claims_risk;

 var Claim_ID  Policy_Type Days_To_Submit Risk_Score;

run;

OUTPUT:

ObsClaim_IDPolicy_TypeDays_To_SubmitRisk_Score
1C001Health425.0
2C002Motor1689.0
3C003Travel213.0
4C004Property11142.0
5C005Health535.0
6C006Motor1679.0
7C007Health317.5
8C008Property20220.0
9C009Travel18.5
10C010Motor1058.0
11C011Health847.0
12C012Property21128.0
13C013Travel110.5
14C014Motor1381.0
15C015Health741.5


8. Character Cleaning

data claims_clean;

    set claims_risk;

    Policy_Type = propcase(strip(Policy_Type));

    Settlement_Status = upcase(trim(Settlement_Status));

run;

proc print data=claims_clean;

 var Claim_ID  Policy_Type Days_To_Submit Risk_Score Policy_Type Settlement_Status;

run;

OUTPUT:

ObsClaim_IDPolicy_TypeDays_To_SubmitRisk_ScorePolicy_TypeSettlement_Status
1C001Health425.0HealthAPPROVED
2C002Motor1689.0MotorPENDING
3C003Travel213.0TravelAPPROVED
4C004Property11142.0PropertyREJECTED
5C005Health535.0HealthAPPROVED
6C006Motor1679.0MotorPENDING
7C007Health317.5HealthAPPROVED
8C008Property20220.0PropertyREJECTED
9C009Travel18.5TravelAPPROVED
10C010Motor1058.0MotorAPPROVED
11C011Health847.0HealthAPPROVED
12C012Property21128.0PropertyPENDING
13C013Travel110.5TravelAPPROVED
14C014Motor1381.0MotorPENDING
15C015Health741.5HealthAPPROVED


9. Fraud Detection Macro

%macro fraud_flag(input=, output=);

data &output;

    set &input;

    length Fraud_Category $12;

    if Risk_Score > 80 then Fraud_Category = "HIGH";

    else if Risk_Score > 50 then Fraud_Category = "MEDIUM";

    else Fraud_Category = "LOW";

run;

proc print data=&output;

run;

%mend;


%fraud_flag(input=claims_clean, output=claims_flagged);

OUTPUT:

ObsClaim_DateSubmission_DateClaim_IDPolicy_TypeClaim_AmountApproval_TimeFraud_FlagSettlement_StatusDays_To_SubmitRisk_ScoreFraud_Category
101JAN202428DEC2023C001Health1200005NAPPROVED425.0LOW
205JAN202420DEC2023C002Motor45000012YPENDING1689.0HIGH
310JAN202408JAN2024C003Travel600003NAPPROVED213.0LOW
412JAN202401JAN2024C004Property95000025YREJECTED11142.0HIGH
515JAN202410JAN2024C005Health1800007NAPPROVED535.0LOW
618JAN202402JAN2024C006Motor32000015YPENDING1679.0MEDIUM
720JAN202417JAN2024C007Health750004NAPPROVED317.5LOW
825JAN202405JAN2024C008Property150000030YREJECTED20220.0HIGH
928JAN202427JAN2024C009Travel450002NAPPROVED18.5LOW
1030JAN202420JAN2024C010Motor28000010NAPPROVED1058.0MEDIUM
1102FEB202425JAN2024C011Health2200009NAPPROVED847.0LOW
1205FEB202415JAN2024C012Property68000018YPENDING21128.0HIGH
1307FEB202406FEB2024C013Travel550003NAPPROVED110.5LOW
1410FEB202428JAN2024C014Motor41000014YPENDING1381.0HIGH
1512FEB202405FEB2024C015Health1950008NAPPROVED741.5LOW


10. TABLE 1 – Fraud Exposure Summary

Business Question

How much money is exposed to fraud?

proc sql;

create table tlf_fraud_summary as

select 

    Fraud_Category,

    count(*) as Total_Claims,

    sum(Claim_Amount) as Total_Exposure,

    mean(Risk_Score) as Avg_Risk

from claims_flagged

group by Fraud_Category;

quit;

proc print data=tlf_fraud_summary;

run;

OUTPUT:

ObsFraud_CategoryTotal_ClaimsTotal_ExposureAvg_Risk
1HIGH53990000132.00
2LOW895000024.75
3MEDIUM260000068.50

Why this Table Matters

• Regulators want fraud exposure
• Finance wants loss estimates
• Risk teams want severity


11. Display Table 1

proc report data=tlf_fraud_summary nowd;

columns Fraud_Category Total_Claims Total_Exposure Avg_Risk;

define Fraud_Category / "Fraud Level";

define Total_Claims / "Number of Claims";

define Total_Exposure / "Exposure Amount";

define Avg_Risk / "Average Risk Score";

run;

OUTPUT:

Fraud LevelNumber of ClaimsExposure AmountAverage Risk Score
HIGH53990000132
LOW895000024.75
MEDIUM260000068.5

12. TABLE 2 – Settlement Efficiency Table

Business Question

Are risky claims taking longer to close?

proc sql;

create table tlf_settlement as

select 

    Fraud_Category,

    Settlement_Status,

    count(*) as Claims,

    mean(Approval_Time) as Avg_Days

from claims_flagged

group by Fraud_Category, Settlement_Status;

quit;

proc print data=tlf_settlement;

run;

OUTPUT:

ObsFraud_CategorySettlement_StatusClaimsAvg_Days
1HIGHPENDING314.6667
2HIGHREJECTED227.5000
3LOWAPPROVED85.1250
4MEDIUMAPPROVED110.0000
5MEDIUMPENDING115.0000

This is used by:

• Claims operations
• SLA monitoring
• Audit teams


13. Display Settlement Table

proc report data=tlf_settlement nowd;

columns Fraud_Category Settlement_Status Claims Avg_Days;

define Fraud_Category / "Fraud Level";

define Settlement_Status / "Settlement";

define Claims / "Count";

define Avg_Days / "Average Approval Days";

run;

OUTPUT:

Fraud LevelSettlementCountAverage Approval Days
HIGHPENDING314.666667
HIGHREJECTED227.5
LOWAPPROVED85.125
MEDIUMAPPROVED110
MEDIUMPENDING115

14. LISTING 1 – High-Risk Claim Listing

Business Question

Which specific claims must be investigated?

proc sql;

create table listing_highrisk as

 select Claim_ID,Policy_Type,Claim_Amount,Days_To_Submit,Risk_Score,Settlement_Status

 from claims_flagged

 where Fraud_Category="HIGH"

 order by Risk_Score desc;

quit;

proc print data=listing_highrisk;

run;

OUTPUT:

ObsClaim_IDPolicy_TypeClaim_AmountDays_To_SubmitRisk_ScoreSettlement_Status
1C008Property150000020220REJECTED
2C004Property95000011142REJECTED
3C012Property68000021128PENDING
4C002Motor4500001689PENDING
5C014Motor4100001381PENDING

15. Print High-Risk Listing

proc print data=listing_highrisk label noobs;

label Claim_ID="Claim ID"

      Policy_Type="Policy"

      Claim_Amount="Amount"

      Days_To_Submit="Delay Days"

      Risk_Score="Risk Score"

      Settlement_Status="Status";

run;

OUTPUT:

Claim IDPolicyAmountDelay DaysRisk ScoreStatus
C008Property150000020220REJECTED
C004Property95000011142REJECTED
C012Property68000021128PENDING
C002Motor4500001689PENDING
C014Motor4100001381PENDING

This is sent to:

• Fraud investigators
• Internal audit
• Regulators


16. LISTING 2 – Pending Claims

proc sql;

create table listing_pending as

 select Claim_ID,Policy_Type,Claim_Amount,Fraud_Category,Approval_Time

 from claims_flagged

 where Settlement_Status="PENDING";

quit;

proc print data=listing_pending;

run;

OUTPUT:

ObsClaim_IDPolicy_TypeClaim_AmountFraud_CategoryApproval_Time
1C002Motor450000HIGH12
2C006Motor320000MEDIUM15
3C012Property680000HIGH18
4C014Motor410000HIGH14

17. FIGURE 1 – Risk Score Distribution

proc sgplot data=claims_flagged;

 histogram Risk_Score;

 density Risk_Score;

 title "Distribution of Insurance Claim Risk Scores";

run;

OUTPUT:

The SGPlot Procedure

Used for:

• Fraud modeling
• Risk calibration
• Model validation


18. FIGURE 2 – Claim Amount vs Risk

proc sgplot data=claims_flagged;

 scatter x=Risk_Score y=Claim_Amount;

 title "Claim Amount vs Fraud Risk";

run;

OUTPUT:

The SGPlot Procedure

Used by:

• Finance
• Fraud analytics
• Loss modeling


14. Why TLF is Mandatory in Insurance

Insurance is regulated by:

• IRDAI (India)
• NAIC (USA)
• EIOPA (Europe)

They do not accept datasets — they accept:

• Tables
• Listings
• Figures


15. How This Matches Clinical Trial TLF

Clinical Trials

Insurance

AE Summary Table

Fraud Exposure Table

Patient Listing

Claim Listing

Safety Plots

Risk Plots


This is why SAS clinical programmers easily move into insurance analytics.


16. Interview Value

If you explain this TLF:

You can answer:

• Regulatory reporting
• Risk modeling
• Audit compliance
• Data transparency
• End-to-end SAS pipelines


FINAL CONCLUSION

This project shows how raw insurance claim data is transformed into regulatory-grade Tables, Listings, and Figures using SAS.
The same workflow used in clinical trials was applied to fraud detection, risk scoring, and claim settlement analysis.
By building TLFs, we converted raw transactional data into audit-ready, management-ready, and regulator-ready outputs.
This is how real insurance companies operate their SAS analytics platforms.


INTERVIEW QUESTIONS FOR YOU

1.How to use MDY in SAS date handling?
2.How does PROC Copy work and when is it used?
3.What is the role of PROC DATASETS compared to deleting datasets using a DATA step?

About the Author:

SAS Learning Hub is a data analytics and SAS programming platform focused on clinical, financial, and real-world data analysis. The content is created by professionals with academic training in Pharmaceutics and hands-on experience in Base SAS, PROC SQL, Macros, SDTM, and ADaM, providing practical and industry-relevant SAS learning resources.


Disclaimer:

The datasets and analysis in this article are created for educational and demonstration purposes only. They do not represent Insurance Fraud TLF data.


Our Mission:

This blog provides industry-focused SAS programming tutorials and analytics projects covering finance, healthcare, and technology.


This project is suitable for:

SAS Programmer Interviews

SAS Programmer Job Seekers

SAS Analysts


Follow Us On : 


 


--->Follow our blog for more SAS-based analytics projects and industry data models.

To deepen your understanding of SAS analytics, please refer to our other data science and industry-focused projects listed below:








Comments

Popular posts from this blog

412.Can We Build And Clean A University Course Analytics & Fraud Detection System In Sas Using Only Macros While Intentionally Creating And Fixing Errors?

420.Can We Detect Errors, Prevent Fraud, And Optimize Biometric Access System Security Using Advanced SAS Programming?

418.Can We Design, Debug, Detect Fraud, And Optimize A Smart Parking System Using Advanced SAS Programming Techniques?