Data analyst, London

Kautum Krishnan Panjalaraja

Data analystSQL, Python, and a habit of checking

I work out what the data actually says, including the times that turns out to be less flattering than what everyone hoped it would say.

Available

On course completion

Right to work

Graduate Route, no sponsorship needed

Studying

MSc Data Science, King's College London

Who I am, and how I work

Analyst on the application. Scientist and engineer in practice.

Data analyst is the role I am applying for, and I want it: the job is working out what a number really says and being able to defend the answer to someone who did not do the analysis. What I bring on top of it is how I got here. I came into this through machine learning and building AI systems, so I tend to ask what would have to be true for a result to hold, and then go and check.

1.86M rows

Every Land Registry sale for 2024 and 2025, analysed in SQL. Joins, chained CTEs, window functions, and a script that re-checks every number in the write-up.

0.90 → 0.61

The macro-F1 once attacker machines the model had never seen replace random splits, and the ranking of models reverses with it.

3 for 3

LLMs tested as classifier, synthetic data generator and next-packet predictor. Lost all three roles, reported all three.

1 week, solo

Read a job posting as a content problem instead of a chatbot one, then built and shipped the product it actually described.

The method, not just the tool

The habit underneath all of this is the same one an analyst needs: know where every number came from before anyone acts on it. Before a model touches anything, I build it a structured knowledge base: what is true, where each fact came from, and which file to open when it is not sure. I keep one for my dissertation, one for my job search, and one for this site, and each one gets read before the model writes a line.

In practice that means Claude Code with a plugin set I have tuned myself, MCP servers for the tools I reach for often, and a written brief committed alongside the code, so that anyone joining the project, human or machine, starts from an accurate picture instead of guessing from whichever file they opened first.

Writing the code is rarely the slow part. Deciding what to build, checking whether the result is actually true, and being able to show your working are the slow parts.

What that looks like when it is not a dashboard

MSc dissertation, submitted 6 August

An evaluation flaw that flips the leaderboard

Random train/test splits let intrusion-detection models fingerprint the attacker's machine instead of the attack, which is why the field's usual near-98% detection scores look so convincing. Testing on attacker machines the model had never seen drops the easy macro-F1 of 0.9002 to an honest pooled 0.6059, and reverses which model wins. I tested large language models in three separate roles, as classifier, as synthetic data generator and as next-packet predictor, and they lost all three. I reported that as a finding rather than leaving it out.

1.86 million rows, written in SQL

Asking the UK housing market six questions

Every Land Registry sale for 2024 and 2025, plus the official House Price Index, in a DuckDB star schema. Six questions, and every analytical step is a query rather than a dataframe. The one I would show first splits England from Wales, because the stamp duty thresholds that changed in April 2025 apply in England and Wales charges a different tax. If the March spike were the tax deadline and not the season, it should appear in one column and not the other. It did: England rose 92.1% then fell 74.2%, Wales moved 19.4% then 18.4%.

A job application, one week, solo

Built the product the posting was actually describing

A haircare brand advertised for a junior AI developer and described AI woven into paid content and product ranges. Everyone applying was going to build a chatbot; the brand already ran one. I built the campaign generator instead, and it is still live.

A codebase I had never opened

Read an unfamiliar codebase, then fixed what was broken

Forked a research tool built at King's, got it running from a clean clone, and wrote the documentation it was missing. The most serious defect I found and fixed was an authentication bypass: the framework registered every callback globally, so anyone who knew the component IDs could run the whole pipeline without logging in.

None of this makes me a senior data scientist. It is why analyst is the role I am applying for, and why the questions I ask once I am in the door will not stop at the dashboard.

Chapter one

Chennai to London, in six steps.

Five years of computer science and internships in Chennai, then a year in London doing a masters. The six steps run sideways. Scroll on, or swipe them.

2021

Started a BTech in computer science at VIT in Chennai, on the AI and robotics track. Finished on 8.21 out of 10.

2023

Two traineeships at Celcom, back to back. The first was Java and SQL. The second was the one that stuck: comparing regression, trees and neural networks on real metrics.

Jan 2025

A month at Finstein, benchmarking deep learning architectures for a fintech product team and cleaning up their structured financial data.

Mar to Jul 2025

Back at Celcom for five months. Built the reporting chatbot that ended up saving the team most of a working day each week.

Sep 2025

Moved to London for the MSc in Data Science at King's. First time living outside India.

Aug 2026

Handed in the dissertation on 6 August. Everything after this point is what I did with the year.

Chapter two

Things I made because I wanted to know something.

In each of these the interesting part was deciding what the actual question was, which is the part of analysis nobody sets as an exercise.

Thirteen datasets, one story

What a fish dinner costs, beyond the price on the label

My individual coursework for the data visualisation and storytelling module at King's, written up as an IEEE-format paper. Thirteen datasets from the FAO, Our World in Data, the Global Slavery Index and the US Department of Labor, pulled into one cleaned pipeline and built into a six-stage narrative: demand, then how the fish is caught, then what that does to the sea, then who gets hurt, then who pays for it, then what else we could eat. Two figures from the middle of that argument are redrawn here, live, from the same data.

Share of world fish stocks inside biologically sustainable limits

90% down to 62%, in one working lifeTen per cent of stocks were being fished beyond safe limits in 1974. By 2021 it was thirty-eight. FAO assessments, and the first stage of the story where the cost stops being abstract.

Share of global discards by fishing gear, 2014

bycatch is a design choice, not an accidentDiscards are fish caught and thrown back dead. Nearly half of them come from one gear type. That makes bycatch a structural property of how the fishing is done, rather than bad luck on a given trip.

The whole thing is built for a reader seeing the data for the first time, not for someone marking a methods section. I used Munzner's why, what and how framework and Segel and Heer's martini glass model on purpose: lead the reader through the argument on a fixed path first, then hand over control so they can explore the same data themselves. That discipline showed up most in what I turned down. A Sankey diagram for the gear flows looked the most striking option by far, but it hid the absolute scale of the numbers, so it went. A choropleth map for labour abuses would have painted every country with no data the same reassuring colour as a country with none of the problem, so that went too. Every palette that did make the cut was checked against ColorBrewer for colour blind safety. The paper also carries a section on what the data cannot show, since FAO statistics exclude most illegal catch and labour figures count only documented cases.

Python, pandas, NumPy, Matplotlib, Tableau

Group coursework, same module

Do London's parks actually make it more livable?

Four datasets merged across all 33 boroughs, then plotted in five dimensions at once: park access on one axis, flood risk on the other, obesity in the size of each marker and air pollution in its colour, with a composite livability index fitted over the top.

33 London boroughs. Flood risk against park access, sized by obesity, coloured by air pollution

Cleaner air More polluted Livability trend

parks help. the river decides.Bigger circles are more obese boroughs. The composite livability index does rise with park access, but only modestly, at an r squared of about 0.42. Flood exposure is set by the Thames: Hammersmith and Fulham has average park access and 89 per cent of properties in the floodplain, while Harrow has the fewest parks in London and almost no flood risk at all.

The honest answer is a qualified yes. Livability does improve with park access, but the fit is modest and the headline relationship people expect is not there at all: flood risk tracks the river, not the parks. Central boroughs with the best green access still carry the worst air. It would have been a tidier group write-up to just say parks help. Saying instead that the effect is real but small, and that flood risk has nothing to do with green space, was the less comfortable finding and the one we actually handed in.

Python, pandas, Matplotlib, ColorBrewer palettes

1.86 million sales, all of it in SQL

What UK house prices actually did, asked in SQL

the question
Every other project here is Python. SQL is the first thing an analyst gets tested on, so it needed a piece of work of its own.
what I did
Loaded every Land Registry Price Paid sale for 2024 and 2025, 1.86 million of them, plus the official House Price Index, into a DuckDB star schema. Six questions, and every analytical step is a query: joins, chained CTEs, window functions, moving averages, medians. Python only downloads the files and runs the SQL.
what came out
New builds carry a 25.3% premium. March 2025 saw 123,129 sales before the stamp duty change, then April collapsed to 33,803, and splitting England from Wales shows the tax caused it, since Wales sets its own thresholds. The tidy assumption that cash buyers cluster at the top does not survive contact with the data: the correlation is -0.092, which is nothing.
the less fun part
A limitations section, and a script that re-checks all 76 numbers in the README against the query output. It caught two of my own errors.
The query behind the stamp duty finding
WITH monthly AS (
  SELECT
    date_trunc('month', t.date_of_transfer)       AS sale_month,
    count(*)                                      AS sales,
    count(*) FILTER (WHERE a.area_code LIKE 'E%') AS england_sales,
    count(*) FILTER (WHERE a.area_code LIKE 'W%') AS wales_sales
  FROM transactions     t
  JOIN dim_ppd_category c ON c.code = t.ppd_category
  JOIN dim_area         a ON a.ppd_district = t.district
  WHERE c.is_full_market_value
  GROUP BY 1
)
SELECT
  sale_month,
  round(100.0 * sales / avg(sales) OVER (), 1)    AS volume_index,
  lag(sales, 12) OVER (ORDER BY sale_month)       AS same_month_last_year
FROM monthly
ORDER BY sale_month;

DuckDB, SQL, Python, open government data

A case study for a research analyst role

What happens to a stock when an index quietly drops it

the question
Index funds have to hold whatever the index says they hold. So when the index changes, they all have to trade, at the same time, whether they want to or not. How much money is that, and can the market absorb it?
what I did
Modelled the passive fund flows around a hundred stock US index from its constituent list: price, shares outstanding and free float per name. Worked out the assets tracking the index, the weight of individual names, then walked through the events that force a rebalance. A free float expansion. A stock split. A deletion from the index entirely.
what came out
Around 940 billion dollars of passive money sits against that index and has to move mechanically when the rules change. Unwinding a deleted name would take roughly fourteen times its average daily volume, so it cannot be done on the day without moving the price. Splits change nothing, because market cap does not move.
the less fun part
A limitations section. The model treats the tracking percentage as fixed and ignores that different funds rebalance on different schedules.

Python, pandas, Jupyter, February 2026

The job application that built itself

They already had a chatbot, so I built the thing they actually asked for

the question
A haircare brand advertised for a junior AI developer. The posting talked about AI woven into paid content and product ranges recreated in generated environments. Everyone applying was going to build a chatbot. The brand already ran one.
what I did
Read it as a content problem and built a campaign generator, solo, in under a week. Point it at one of their twelve real products and it writes the copy in their voice, generates a lifestyle scene from the same campaign idea, and composites the product in at true relative scale, so a fifteen pound spray does not come out the size of a hairdryer.
decisions I would defend
Copy is generated before the image prompt, not in parallel, so words and picture come from one concept. Scene generation kept collapsing into bathrooms and spas, so I added nine style categories, a banned word check and a targeted retry. Image to image APIs were too expensive, so compositing runs in the browser. I picked gpt-oss-120b over Llama 3.3 70B after comparing their copy side by side.
The md creative generator running: a Social Content Generator heading, a product picker, and the mdlondon range laid out as cards.
md-creative.vercel.app, running now

Next.js, TypeScript, Groq, Vercel, all on free tiers

A codebase I had never seen before

Reading someone else's research tool properly

the question
Janus is an app analysis tool built at King's by the DIGISILK project, by a rotating cast of students rather than a standing engineering team. I applied for the developer role on it. What is the useful thing to do when you do not know the team's roadmap?
what I did
Read the code, got it running, and wrote the guide it was missing: what the project is, how a request moves through it, how to set it up if you do not consider yourself a programmer, and every defect I found with file references. I spent more time on the documentation than on the code.
what came out
It boots from a clean clone now, and the defects I found are fixed. The serious one was authentication. Checking login when the page renders looks like access control but is not: the framework registers every callback globally, so anyone who knew the component IDs, which the framework itself lists, could run the analysis pipeline and the file upload without ever logging in. I put the guard on the single endpoint every callback passes through, so one added next year is covered too. Also a path traversal in the upload handler, a race in session tracking that broke the site for everyone, and a worker pool that leaked on a malformed file. It had no production users at the time, so nothing was actually exposed by it, but the flaw itself was the kind that matters badly once real users show up. Upstream's branch is untouched so the two can be diffed, and I committed a brief at the root that coding assistants read automatically.

Python, Dash, Androguard, Apache 2.0, same as upstream

Three more, briefly

Agents, retrieval and a camera that talks

a2a banking agents
Two agents handling banking customer service over Google's A2A protocol, built in a day at their hackathon. Search runs keyword first across 698 documents and only pays for the embedding call when keywords come up short.
rag model comparison
The same pipeline three times, everything constant except the language model. LLaMA stayed closest to the retrieved text. SmolLM2 did well for its size but drifted on harder questions.
vision to voice
My undergraduate capstone. A camera describes what it sees out loud, in English and Tamil, for people who cannot see it. Written up as an IEEE format paper with my supervisor.
Throw it sideways for the rest

Chapter three

I spent a year finding out my field was marking its own homework.

My dissertation started with a question that sounds dull and turned out not to be. Papers on detecting attacks in network traffic report accuracy somewhere around 0.90. Should anyone believe that?

Here is the problem. These datasets are recorded in a lab, where a handful of machines play the attacker. If you shuffle all the traffic and split it at random, flows from the same attacking machine land on both sides of the split. The model never has to learn what an attack looks like. It only has to learn what that particular machine looks like, and it will happily do the easier thing.

So I rebuilt the test. I took the ToN_IoT captures, extracted 109,203 flows across nine classes and 68 hosts, and held out every flow from an entire attacking machine rather than shuffling.

The score dropped by a third. Worse for anyone choosing a model, the ranking flipped: the detector that won under the easy split came last under the fair one. If you had picked your model the usual way, you would have picked the wrong one and never known.

Detector ranking, easy split versus honest holdout

the winner changes when the test gets honestUnder a random split, pooled macro-F1 reaches 0.9002 and LightGBM comes out on top. Once whole attacker machines are held out of training rather than just individual flows, pooled macro-F1 drops to 0.6059 and RandomForest comes out on top instead. The ranking reverses. RandomForest is the detector that was locked in.

I also went looking for a fix. Large language models were the obvious candidate, so I tried them in three separate jobs: classifying the traffic directly, generating extra training data, and predicting what packet comes next. Ten model families went into the comparison. DistilBERT finished last of the ten. The generation experiments, run with Qwen2.5, SmolLM2 and GLM-Edge, came back negative every time. The core experiment, predicting future packets and then classifying them, lost to simply classifying what you can already see in 18 of 21 configurations.

None of that is the result I wanted. All of it is in the report. There is a verification notebook that reloads the saved models, retrains the baseline live and reproduces the headline figure to four decimal places, because a claim like this one should be checkable by someone who does not trust me.

Two things did work. Aggregating the flow level verdicts up to whole devices caught eight of the nine attacking machines with no false alarms across 59 clean hosts. And a small Markov and LSTM forecaster predicted the next event well on real botnet captures, then failed on a different malware family, which is a limit worth reporting rather than a result worth hiding.

The report, the notebooks and all seventeen result files

Chapter four

Three jobs, and one afternoon I gave back to a team.

At Celcom the employee monitoring reports were put together by hand, every single time. Someone would open the RFID logs, pull out what mattered and write it up. I built a retrieval chatbot in n8n that assembled them instead. The team reading those reports had no way to check my working, so before anyone was allowed to rely on it, I checked its answers myself against several different document formats, because a reporting tool that is right most of the time is worse than no tool at all. The team took it on afterwards and it cut their reporting time by 60%.

Mar to Jul 2025

AI Intern

Celcom Solutions, Chennai

  • Built a retrieval augmented chatbot in n8n that automated the RFID based employee monitoring reports.
  • Cut the manual reporting time by 60% once the team took it on.
  • Tested the output against several document types before it went anywhere near production.
  • Worked in a small intern team under a project manager, handling the prompt design and the retrieval setup.
Jan 2025

AI Intern

Finstein Advizory Service, Chennai

  • Benchmarked deep learning architectures with FastAI for a fintech product team.
  • Did the exploratory analysis and feature engineering on their structured financial datasets, start to finish.
Nov to Dec 2023

Trainee, AI and ML programme

Celcom Solutions, Chennai

  • Researched and wrote up a machine learning proof of concept for software development decisions.
  • Compared regression, decision trees and neural networks on RMSE, R squared, precision, recall and F1.
  • Preceded by a separate two month traineeship on the software engineering track, covering Java, collections, JDBC and SQL.

Chapter five

What I reach for.

Everything here has been used on something that shipped or got marked. If a tool is missing it is because I have not used it properly yet, and I would rather say so at the start than halfway through an interview.

  • PythonPython
  • SQLSQL
  • TypeScriptTypeScript
  • pandaspandas
  • NumPyNumPy
  • JupyterJupyter
  • scikit-learnscikit-learn
  • PyTorchPyTorch
  • Hugging FaceHugging Face
  • LangChainLangChain
  • GitGit
  • GitHubGitHub
  • DockerDocker
  • LinuxLinux
  • Next.jsNext.js
  • ReactReact
  • VercelVercel
  • FastAPIFastAPI
  • n8nn8n

Querying and languages

  • SQL
  • Python
  • Java
  • TypeScript

Analysis and statistics

  • Exploratory analysis
  • Feature engineering
  • Statistical modelling
  • pandas
  • NumPy
  • Data wrangling

Showing people the answer

  • Tableau
  • Matplotlib
  • Seaborn
  • Plotly
  • Narrative visualisation

Machine learning

  • scikit-learn
  • PyTorch
  • FastAI
  • HuggingFace
  • Fine tuning
  • Computer vision

Language models and agents

  • RAG pipelines
  • LangChain
  • Prompt engineering
  • Embeddings
  • Hybrid retrieval
  • Google ADK

The rest of the toolbox

  • Git
  • Jupyter
  • Linux
  • Docker
  • FastAPI
  • n8n
  • Bloomberg Terminal

Chapter six

Where I was taught.

2025 to 2026, London

MSc Data Science

King's College London. Machine learning, deep learning and neural networks, big data technologies, data mining, database management, and statistics for finance, where the coursework ran on data extracted from Bloomberg Terminal, plus the data visualisation and storytelling module that produced the seafood project. Dissertation handed in August 2026.

2021 to 2025, Chennai

BTech, Computer Science

Vellore Institute of Technology, on the AI and robotics track. CGPA 8.21 out of 10, a first class honours equivalent. Along the way: cryptography and network security, compiler design, probability and statistics, and game theory.

Coursera

On my own time

Courses and languages

Andrew Ng's Machine Learning Specialization and the fast.ai course on practical deep learning. IELTS Academic 8.0 overall, with 9.0 in both listening and reading. English fluent, Tamil native.

The end, sort of

If any of this sounds useful, say hello.

I am looking for data analyst roles in London, available on course completion. I have Graduate Route right to work in the UK, so no sponsorship is needed.