Apply to my task
arXiv:2511.02219 ★ 81 Nov 4, 2025

TABDSR: Three-Step Table Processing for Accurate Calculations

Key result

The paradox: The more context you give a model, the worse it performs. Feed it the question + a big table at once and the model "forgets" parts of the question. A multi-hop request ("calculate X, then compare with Y") turns into an answer about X only. TabDSR lets you get accurate answers to complex questions about tables, especially when you need several calculation steps and the data is dirty ($3,275, "N/A", notes in parentheses). The method's trick: it splits the process into three independent steps. The decomposer breaks the question into sub-questions (it works ONLY with the question text and ignores the table). The sanitizer cleans the junk out of the table (currency symbols, percent signs, footnotes). The reasoner generates Python code for each sub-question. Each step covers a separate LLM weakness instead of trying to do everything in one prompt.

TABDSR: Three-Step Table Processing for Accurate Calculations

TABDSR: Three-Step Table Processing for Accurate Calculations

02

TL;DR

TABDSR is a three-agent framework for working with tables: first break the question into sub-questions, then clean the junk out of the table, then generate code to do the math. The point is that each step tackles a separate LLM weakness instead of trying to do everything in one prompt.

Models are bad at complex table questions for three reasons: (1) multi-hop questions ("calculate X, then compare it with Y") get lost, and the model answers only part of them; (2) "dirty" cells ("$3,275", "1.24 (approx)") break code or cause calculation errors; (3) LLMs imitate arithmetic rather than actually doing it, so accuracy drops when the numbers change. The GSM-Symbolic study showed it: change the numbers in a problem and the model gets it wrong more often.

The method solves this with a three-step pipeline: the decomposer splits the question into atomic sub-questions (it works ONLY with the question text and ignores the table, so important details don't get lost in a large context), the sanitizer cleans the table (strips currency symbols, percent signs and footnotes, standardizes empty cells), and the reasoner generates Python code for each sub-question and runs it.

Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.

03

Method Blueprint

STEP 1: DECOMPOSITION → list of sub-questions
        (question text only, NO table)

STEP 2: TABLE CLEANUP → clean JSON/DataFrame
        (strip $, %, footnotes; null instead of "N/A", "-", "???")

STEP 3: CODE FOR EACH SUB-QUESTION → execution → final answer
        (Pandas + Python)

The steps run in sequence. Steps 1 and 2 can run in parallel (they're independent). Step 3 uses the output of both.

04

Example in Practice

Task: A CFO receives a quarterly report in Excel. The question: "What's the total revenue for Q2-Q4, and by what percentage is it higher than Q1?"

The table contains cells like: "$12,500K", "N/A", "15.3% (prelim.)".

Prompt (step 1: decomposition):

Analyze the question and break it into sub-questions.
Look for conjunctions (and, or), commas, linking words (then, after that, by how much).

Question: "What's the total revenue for Q2-Q4, and by what percentage is it higher than Q1?"

Output:
1. Number of sub-questions
2. List of sub-questions

Prompt (step 2: cleanup):

Clean the table for machine processing:
1. Remove currency symbols ($, €), percent signs (%), thousands separators
2. Delete notes in parentheses: (prelim.), (approx), (estimate)
3. Replace empty values (N/A, -, ???, None) with null
4. Convert numbers to int or float

Table: [paste table]

Output the cleaned table as JSON.

Prompt (step 3: code):

Write Python code to answer each sub-question.
Use Pandas. The data is already loaded into a DataFrame df.

Sub-questions:
1. What is the sum of revenue for Q2, Q3, Q4?
2. What is the revenue for Q1?
3. By what percentage is (1) greater than (2)?

Output the code and the result.

Result: The model returns three code blocks: filtering and summing Q2-Q4, extracting Q1, and computing the percentage. Each block can be checked on its own. The final answer is an exact number, not a "roughly."

05

Why It Works

Weakness 1: details get lost in long context. When the prompt contains both the question and a big table, the model "forgets" parts of the question. A multi-hop request ("calculate X, compare with Y") turns into an answer about X only. TABDSR's fix: the decomposer works ONLY with the question; the table isn't passed in. The model sees the whole question and doesn't drop details.

Weakness 2: "dirty" data breaks code. The cell "$3,275" doesn't convert to a number, so Python throws an error. The note "(approx)" turns a cell into a string instead of a number. The fix: the sanitizer cleans the table BEFORE code generation. It strips symbols and standardizes empty values. If the first cleanup attempt doesn't parse, the model gets the error and tries again (reflection).

Weakness 3: LLMs imitate arithmetic. Models are trained on examples of calculations but don't "understand" arithmetic. They slip up on new numbers. The fix: code does the calculations, not the model. Python computes exactly. The model only generates the code.

Control knobs:

  • Sanitizer iteration limit (currently 1) → raise it for very messy tables
  • Decomposition granularity → ask for finer-grained sub-questions on hard tasks
  • Cleanup instructions → add rules specific to your domain (e.g., "date format DD.MM.YYYY → YYYY-MM-DD")
06

Prompt Template

Step 1: Question Decomposition

You are analyzing a question to find the sub-questions inside it.

Rules:
1. Look for conjunctions (and, or, as well as), commas, linking words
2. Each sub-question must be atomic: one calculation or one comparison
3. Preserve order: if sub-question 2 depends on sub-question 1, say so

Question: {question}

Output:
- Number of sub-questions: [number]
- Sub-questions:
  1. [sub-question 1]
  2. [sub-question 2]
  ...

Step 2: Table Cleanup

Clean the table for machine processing.

Structure rules:
1. If there are multi-level headers, merge them into a single level
2. If the table is split into sections (blank rows, separators), remove the separators

Content rules:
1. Remove symbols: $, £, €, %, commas in numbers
2. Delete notes in parentheses: (approx), (prelim.), (estimated)
3. Convert empty values to null: N/A, -, ???, None, empty string
4. Numbers → int or float

Table:
{table}

Output the cleaned table as JSON:
{
  "columns": [...],
  "data": [[...], [...]]
}

Step 3: Code Generation

Write Python code to answer the sub-questions.
The data is loaded into a pandas DataFrame named df.

Sub-questions:
{sub_question_list}

For each sub-question:
1. Write the code
2. Show the result
3. If the sub-question depends on a previous one, use its result

At the end, combine the results into a final answer.

Placeholders:

  • {question}: the full text of the user's question
  • {table}: the source table (you can paste it straight from Excel/CSV)
  • {sub_question_list}: the output of step 1

🚀 Quick start: paste into the chat (ChatGPT with Code Interpreter, or Claude):

I have a data table and a complex question.
Help me answer it using the TABDSR method:
1. Break the question into sub-questions (work only with the question text)
2. Clean the junk out of the table (currency symbols, footnotes, empty values)
3. Write Python code for each sub-question

Table: [paste table]
Question: [paste question]

The LLM will ask about the table format and clarify which symbols count as junk, because cleanup rules depend on the domain (finance, logistics, HR).

07

Limitations

⚠️ Requires Code Interpreter: The method generates Python code that has to be executed. In a regular chat without Code Interpreter (ChatGPT) or Computer Use (Claude), it won't work. You need a plan with code execution.

⚠️ Code generation errors: In 15-17% of cases the generated code crashes with errors (ValueError, KeyError, TypeError). The dirtier the source data and the harder the question, the higher the risk.

⚠️ Not for simple questions: If the question is "What was Q1 revenue?", three steps are overkill. The method is for multi-hop questions with calculations.

⚠️ Model dependence: The quality of decomposition and cleanup depends on the underlying LLM's abilities. On weak models (7B parameters) results are worse.

08

How They Tested It

A team from Wuhan University and the University of North Texas tested TABDSR on three datasets: TAT-QA (financial tables), TableBench (hard questions), and their own CalTab151 (built specifically for multi-hop questions). They compared it with 12 methods: pretrained models (TAPEX, OmniTab), fine-tuned LLMs (TableLlama, TableGPT2), and prompt-based approaches (Chain-of-Table, TabSQLify, MIX-SC).

Why build their own dataset? Existing datasets have "leaked" into LLM training data: the models have seen these examples and post inflated scores. CalTab151 fixes that: they took 151 tables, shifted the numbers by ±3-5%, added noise (currency symbols, footnotes), shuffled rows, and replaced cells with null. The questions are new multi-hop ones, written from scratch and checked by humans.

The results produced three insights: (1) TABDSR delivers +8.79%, +6.08%, +19.87% accuracy on the three datasets, and even a 7B model beats 13B competitors; (2) the sanitizer is critical: without table cleanup accuracy drops by 10-20%; (3) the decomposer helps, but not always: on "clean" tables it sometimes gets in the way (an extra step), but on dirty data it consistently improves results. The method works on GPT-4o and DeepSeek-V3 too, so it's not just a crutch for weak models.

09

Original Prompts from the Paper

Context: The authors published the prompts for each agent in the appendix. Here are the key excerpts.

Query Decomposer Prompt

You are tasked with analyzing a user query to identify the number of sub-questions it contains. Your objectives are to:
1. Identify Sub-Questions: Split complex or compound questions into independent, self-contained sub-questions.
2. Determine the Count: Count the total number of sub-questions identified.

Guidelines:
- Look for conjunctions like "and", "or", or punctuation such as commas that may indicate multiple questions.
- Treat each distinct inquiry or request for information as a separate sub-question.

### Input Format:
**Query**: [User's compound or complex query]

### Output Format:
**Number of Sub-Questions**: [Count]
**Sub-Questions**:
1. [First sub-question]
2. [Second sub-question]
...

### Example:
**Query**: What is the capital of France, and what is its population?
**Number of Sub-Questions**: 2
**Sub-Questions**:
1. What is the capital of France?
2. What is the population of the capital of France?

Table Sanitizer Prompt

You are a table formatting assistant. Your task is to clean up table data and convert it into a format that can be read correctly by the pandas library.

## Requirements:
1. Structural Optimization:
- Reconstruct Nested Tables: Merge multi-level headers based on semantic similarity
- Reconstruct Segmented Tables: Identify and remove separation rows

2. Content Optimization:
- Remove extraneous symbols: %, $, €, commas in numbers
- Remove explanatory notes in parentheses: (approx), (estimated)
- Convert numerical data to int or float
- Standardize blank cells to "null": -, N/A, ???, None, empty string

## Output Format:
{"columns": [...], "data": [[...], [...]]}

PoT-based Reasoner Prompt

Given a table in DataFrame format and a list of sub-questions, generate Python code to answer each sub-question.

Requirements:
1. Load the sanitized table into a Pandas DataFrame
2. For each sub-question:
   - Extract relevant data
   - Generate Python code for calculation
   - Execute and store result
3. Combine results for final answer
4. Use only stable Pandas methods to avoid version inconsistencies
10

Adaptations and Extrapolations

💡 Adaptation: Decomposition WITHOUT the table as a standalone principle

TABDSR's key insight: take the table out of the context while analyzing the question. This works for any task with a long context + a short request.

First, analyze ONLY my question (ignore the document):
- How many sub-tasks does it contain?
- What data does each one need?

Question: {question}

Now that the structure is clear, I'll give you the document.

Applies to: long documents, reports, contracts, anywhere a question can "get lost" in a big context.

🔧 Technique: Reflection for data cleanup

The sanitizer uses reflection: if the cleaned table doesn't parse, the error goes back to the model to fix.

Clean the table: {table}

[model returns the result]

Check: try loading the result as JSON.
If there's an error, show it and fix it.
Maximum 2 attempts.

💡 Adaptation: The "clean data → code" principle without the full framework

If you don't have Code Interpreter, you can apply the principle by hand:

  1. Ask the model to describe which cells are "dirty"
  2. Clean them manually in Excel
  3. Paste the clean table
  4. Ask it to do the math

That's not the full TABDSR, but it uses its main insight: data quality determines answer quality.

11

Resources

Paper: TABDSR: Decompose, Sanitize, and Reason for Complex Numerical Reasoning in Tabular Data

Authors: Changjiang Jiang, Fengchang Yu, Haihua Chen, Wei Lu, Jin Zeng

Institutions: Wuhan University, University of North Texas, Hubei University of Economics

Contact: [email protected]

CalTab151 dataset: available from the authors on request


Research digest

Key result

The paradox: The more context you give a model, the worse it performs. Feed it the question + a big table at once and the model "forgets" parts of the question. A multi-hop request ("calculate X, then compare with Y") turns into an answer about X only. TabDSR lets you get accurate answers to complex questions about tables, especially when you need several calculation steps and the data is dirty ($3,275, "N/A", notes in parentheses). The method's trick: it splits the process into three independent steps. The decomposer breaks the question into sub-questions (it works ONLY with the question text and ignores the table). The sanitizer cleans the junk out of the table (currency symbols, percent signs, footnotes). The reasoner generates Python code for each sub-question. Each step covers a separate LLM weakness instead of trying to do everything in one prompt.

Principle

A pipeline of three agents, each doing its own job: Step 1: Decomposition → a list of atomic sub-questions (one sub-question = one calculation or one comparison). Critical: the agent sees ONLY the question text; the table isn't passed in. That way important details don't get lost in a large context. Step 2: Table cleanup → clean JSON/DataFrame. Strips symbols ($, €, %), deletes notes in parentheses (approx, prelim.), replaces empty values (N/A, -, ???) with null. Step 3: Code generation → a Python script for each sub-question → execution → final answer. Pandas and Python do the math; the model only generates the logic. Steps 1 and 2 can run in parallel (they're independent). Step 3 uses the output of both.

Why it works

The method targets three specific LLM weaknesses: 1. Details get lost in long context. When the prompt has both the question and a big table, the model "forgets" parts of the question. A request like "calculate X, compare with Y" turns into an answer about X only. The fix: the decomposer works WITHOUT the table, so the model sees the whole question. 2. Dirty data breaks code. The cell "$3,275" doesn't convert to a number, so Python throws an error. The note "(approx)" turns a cell into a string instead of a number. The fix: the sanitizer cleans the table BEFORE code generation. If the first attempt doesn't parse, the model gets the error and tries again (reflection). 3. LLMs imitate arithmetic instead of doing it. Models are trained on examples of calculations but don't "understand" arithmetic. They slip up on new numbers. The fix: Python computes exactly. The model only generates code; the interpreter does the calculations.

When to apply

Financial analytics, reporting, logistics → specifically for multi-hop questions about tables ("sum Q2-Q4 and compare with Q1 as a percentage"), especially when the data is dirty (currency symbols, footnotes, different formats for empty values). NOT a fit for simple questions like "What was Q1 revenue?": three steps are overkill and a regular prompt will do. The method is for tasks that need several calculation steps.

Mini recipe

1. Break the question into sub-questions (WITHOUT the table): Prompt: `Analyze the question and break it into atomic sub-questions. Look for conjunctions (and, or), commas, linking words (then, after that). Each sub-question is one calculation or one comparison. Question: [your question]` 2. Clean the junk out of the table: Prompt: `Clean the table for machine processing: (1) remove currency symbols ($, €), percent signs (%), thousands separators; (2) delete notes in parentheses; (3) replace empty values (N/A, -, ???) with null; (4) convert numbers to int/float. Output as JSON. Table: [paste]` 3. Generate Python code for each sub-question: Prompt: `Write Python code to answer the sub-questions. The data is in DataFrame df. Sub-questions: [list from step 1]. For each sub-question: write the code, show the result. At the end, combine into a final answer.` Quick start: Paste into ChatGPT (with Code Interpreter) or Claude: `I have a table and a complex question. Help me with the TabDSR method: (1) break the question into sub-questions (question text only), (2) clean the junk out of the table, (3) write Python code for each sub-question. Table: [...] Question: [...]`

Examples

[BAD]: `What's the total revenue for Q2-Q4, and by what percentage is it higher than Q1?` + a table with cells like "$12,500K", "N/A", "15.3% (prelim.)", all in one prompt. (The model will either forget the percentage comparison or the code will crash on the currency symbols) [GOOD]: Three prompts: 1. `Break down the question: "What's the total revenue for Q2-Q4, and by what percentage is it higher than Q1?"` → you get: (a) Q2-Q4 total, (b) Q1 revenue, (c) growth percentage 2. `Clean the table: remove $, K, replace N/A with null` → clean JSON 3. `Write code for sub-questions (a), (b), (c). The data is in df` → three code blocks, each checkable on its own For a CFO: `Analyze the quarterly report using the TabDSR method. Question: how much higher is Q3 OPEX than the Q1-Q2 average, and which line items grew by more than 20%? Table: [Excel with footnotes and symbols]`: you get exact figures and a list of line items, not the model's guesswork.

In plain words

Language models freeze up when you feed them a giant table and ask for a complex calculation in one go. The problem is that an LLM isn't a calculator; it's more of a well-read English major. When the data and the task conditions are mixed together in one prompt, the model suffers from an attention deficit: it either drops pieces of the question or gets tangled in the numbers. The TabDSR method solves this with a division of labor: instead of making one "employee" do everything at once, the task is split into three clear stages: decomposition, cleanup and reasoning.

Picture walking into a records office for a certificate, and there's one exhausted clerk behind the desk. If you dump a pile of paperwork on him and ask him to "calculate the average tax over five years adjusted for inflation," he'll either lose his mind or hand you nonsense. TabDSR works differently: first one person writes out a clear plan of action, a second throws the junk out of the files, and only the third picks up a calculator and runs the numbers from the ready-made instructions. Technically it's the same work, but the result is many times more accurate, because nobody is trying to boil the ocean.

The key trick here is context isolation. At the first stage, called decomposition, the model sees only the question text, with no table at all. This is critical: that way the AI isn't distracted by numbers and clearly understands it's being asked for "three actions in two steps." Then the sanitizer kicks in and cuts everything unnecessary out of the table, leaving only the columns that matter. Only at the very end does the programmer agent write the code for the calculations. This chain kills the main problem: the model "forgetting" the second half of the question because it got carried away with the first.

Although the method was tested on financial reports, the principle is universal. It's the cure for any situation involving structured data and multi-step logic. Logistics, medical metrics, warehouse inventory: anywhere you need not just to find a row but to "compare A with B and get a percentage," a regular chatbot will start hallucinating. TabDSR turns the model from an unsure bookkeeper into a crisp assembly line where every step is verifiable and transparent.

Bottom line: stop hoping a "smart" model will sort out your Excel chaos on its own. Splitting into sub-tasks and filtering the data is the only way to make AI calculate without mistakes. Cram everything into one prompt and you'll get a confident but completely wrong answer. Want accuracy? Make the model plan first, clean second and calculate only at the very end.

AI lab assistant

Apply this study to your task

Describe what you're working on. AI takes the method and the measured results from this paper and adapts them to your case, or writes a ready prompt built on them.

Based on TABDSR: Three-Step Table Processing for Accurate Calculations arXiv:2511.02219

Sign in to apply this study New accounts get 50 free credits.

Get the week’s best papers by email

One email on Sundays with the highest-rated new techniques. Unsubscribe with one click.