For Actuarial Analysts ·
What you'll accomplish
Many analysts write scripts that nobody reads before peer review. A first read from Claude can point at risky lines, such as a join that duplicates rows or a random step with no seed, and suggest a small test case for each. You run every test on invented data, fix what is real, and send the script through your team's normal review. The AI's read does not replace the reviewer.
What you'll need
Data caution. A script written against company tables can reveal table names, column names and logic. Whether you may upload it depends on your company's AI policy and on whether Claude is an approved tool for code. Check your plan's settings for whether chats and uploads are used for training and how long they are kept. This guide uses a script written for synthetic data, so it works under any policy. Before uploading any script, remove connection strings, server names, file paths to real data and credentials. Never upload real data files. If your policy does not allow company code, rewrite the logic on invented columns.
Save the invented script below as check_expected.py. It reads two invented files, joins them and computes an expected count per unit. It is meant to contain two problems.
import pandas as pd
import numpy as np
exposure = pd.read_csv("synthetic_exposure.csv")
rates = pd.read_csv("synthetic_rates.csv")
merged = exposure.merge(rates, on="cell_code", how="left")
merged["expected_claims"] = merged["earned_units"] * merged["rate"]
print("Rows after join:", len(merged))
print("Units after join:", merged["earned_units"].sum())
sample = merged.sample(frac=0.5)
total_expected = sample["expected_claims"].sum()
total_units = sample["earned_units"].sum()
summary = sample.groupby("cell_code")["expected_claims"].sum()
print(summary)
print("Expected per unit:", total_expected / total_units)
What you should see: About 20 lines of Python. Line 7 is the merge. Line 13 is the sample. Troubleshooting: If you prefer R, ask Claude to translate the invented script first, then review the translation yourself before using it.
The two planted issues:
cell_code, the left join returns an exposure row for each, so units and expected claims are counted twice.Other points may also be raised, such as unmatched codes giving missing rates after the join. That is a fair point, not a planted one.
What you should see: Your own notes naming the two lines. Troubleshooting: If you want the review to be a fair test, write the answers down before you upload.
Claude's upload page lists PDF, DOCX, CSV, TXT, HTML, ODT, RTF, EPUB, JSON and XLSX as supported document types. A script file with a .py or .R extension is not on that list, so save a copy as check_expected.txt before uploading, or paste the code into the chat.
What you should see: The file shown as an attachment in the message box. Troubleshooting: If the upload is refused, check the file type and use the TXT copy.
Paste this prompt.
Review the attached script, which uses synthetic data. List risks under these headings: hard-coded paths, unhandled missing values, silent type coercion, joins that duplicate rows, and random steps with no seed. For each risk, name the line number, explain what could go wrong in one or two sentences, and give a small invented test case I can run to see it. If a heading has no risk, say so. Do not rewrite the whole script.
What you should see: A list under each heading, with line numbers. The merge on line 7 and the sample on line 13 should appear, and the hard-coded file names on lines 4 and 5 may appear too. Troubleshooting: If line numbers look off, ask Claude to quote the line. Different editors count blank lines differently, so check against your file.
Take the test case for the join risk. A small invented version is below.
Exposure file (3 rows):
| cell_code | earned_units |
|---|---|
| Cell 1 | 100 |
| Cell 2 | 200 |
| Cell 3 | 300 |
Rates file (4 rows, with Cell 3 repeated):
| cell_code | rate |
|---|---|
| Cell 1 | 0.02 |
| Cell 2 | 0.03 |
| Cell 3 | 0.04 |
| Cell 3 | 0.05 |
Run the script on these files. The join produces 4 rows, not 3, and the units after the join are 900, not 600 (100 plus 200 plus 300 plus 300). That confirms the duplication.
For the seed risk, run the script twice and compare the printed summary. Without a seed the sample, and so the summary, can differ between runs.
What you should see: "Rows after join: 4" and "Units after join: 900". Troubleshooting: If your output differs, check that the CSV headers match the column names in the script.
random_state value in the sample call.What you should see: "Rows after join: 3" and "Units after join: 600". Troubleshooting: If you ask Claude for a fix, test it on the invented files first. Never accept a fix because it looks right.
Claude's list is a first read. The reviewer signs off on model code through your team's normal process.
Explain before reviewing
Explain in plain language what each block of the attached script does, so I can confirm it matches my intent. Do not suggest changes yet.
Missing value check
Which columns in the script could contain missing values after the join, and what does each later line do with them?
Test case for one line
Give me a four-row invented data set that would expose a problem on line [number], with the output I should see.
Review summary for the reviewer
Draft a short note listing the checks I ran on this script and the results I got. Use only the results I give you: [paste results]