Skip to content

Read comma groups of three in currency columns as thousands separators #12224

Closed

Description

@MarkusNeusinger

Goal

A currency column whose commas sit in groups of exactly three digits holds thousands separators, not decimal commas: a money amount has at most two decimals, so $1,200 is 1200, never 1.2. Today the parser reads $1,200 as 1.2 and $12,500 as 12.5. Its warning even says "remove them first if they separate thousands", but after the paste nothing can recover 1200. Pasted values must keep their exact value, or every change must be announced. Here the value changes by a factor of 1,000.

Revised 2026-10-22 after Gemini's report-back. The first version asked to take dot decimals in another column (4.5) as evidence. That contradicts the second opinion of 2026-10-15: a dot number elsewhere is no evidence, because 12.30 may be a time and a rating of 4.5 says nothing about a price of 1,250. test_a_dot_decimal_elsewhere_keeps_the_ambiguous_decimal_comma pins that, and the owner keeps it. The evidence here lives in the column itself: its currency.

Context

Reproducer (current main):

from agents.anyplot.data.parse import parse_dataset
p = parse_dataset('price\n"$1,200"\n"$950"\n"$12,500"\n')
print(p.csv)       # price ($) / 1.2 / 950 / 12.5   <- wrong
print(p.warnings)  # "... commas read as decimal commas; remove them first if they separate thousands"

The same happens with a second column such as rating (4.5, 3.8, 4.9), and for "1,200 USD".

Relevant code in agents/anyplot/data/parse.py:

  • _CURRENCY (around line 361), the currency signs and codes the parser already knows (€ $ £ CHF EUR USD GBP);
  • _split_units / _split_unit (around line 2814), which move a unit from the cells into the column name (price ($));
  • _type_column (around line 2619), the rules that type a column; rule 5 reads comma numbers;
  • AMBIGUOUS_COMMAS (around line 2697), today's warning;
  • _commas_as_thousands (around line 2778) and its call site (around line 3289): the existing rule that settles an ambiguous comma column from the file's other columns. Its docstring records the 2026-10-15 boundary. The new rule is a sibling or a new first bullet there, settled by the column's own currency.

Tests live in tests/unit/agents/data/test_parse.py, class TestThousandsGroups (around line 1780).

Steps

  • Step 1: add failing tests for the cases under Acceptance.
  • Step 2: implement the rule. A column that is typed as decimal commas with AMBIGUOUS_COMMAS, whose unit is a currency (_CURRENCY), and whose comma cells all match _COMMA_GROUP (every group exactly three digits) reads as whole numbers with comma thousands, with a note. Any cell with a one- or two-digit fraction after a comma keeps the whole column on decimal commas.
  • Step 3: describe the rule where the parser's comma rules are described (docs/concepts/agent-network.md, around line 272, and the _commas_as_thousands docstring); changelog fragment (### Fixed); gates.

Constraints

  • Change only the parser, its tests, the doc lines above, and the changelog fragment. Do not touch agents/anyplot/data/prepare.py (set_type).
  • A dot number in another column stays no evidence (2026-10-15). Every existing test in tests/unit/agents/data/ must still pass unchanged.
  • Decimal-comma files must behave exactly as today.
  • A column named as an id, a code, or a version (_id_like) is never retyped.
  • Integers beyond int64 keep every digit (see how _retype_thousands_dots falls back to text with BIG_INTEGERS).
  • Every change to a pasted value is announced in a warning; no silent changes.

Acceptance

All of these pass:

PYTHON_DOTENV_DISABLED=1 uv run pytest tests/unit/agents/data -n auto
PYTHON_DOTENV_DISABLED=1 uv run ruff check . && uv run ruff format --check .
PYTHON_DOTENV_DISABLED=1 uv run --extra typecheck mypy api core --pretty
PYTHON_DOTENV_DISABLED=1 uv run python -m tools.changelog check --base origin/main

New tests cover:

  1. price alone with "$1,200", "$950", "$12,500": the CSV holds 1200, 950, 12500. A warning says the commas were read as thousands separators, and AMBIGUOUS_COMMAS is gone for that column.
  2. The same beside rating with 4.5, 3.8, 4.9, and the same with "1,200 USD", "€ 1,200" and "CHF 12,500".
  3. Bare "1,200" without a currency, beside 4.5: unchanged, still decimal commas with AMBIGUOUS_COMMAS (the existing parametrized test keeps passing).
  4. "$1,25", "$3,50": stays decimal comma (1.25, 3.5).
  5. "$1,200" and "$3,50" in one column: no thousands reading.
  6. A group that is not three digits long ("$1,2000"): no thousands reading.
  7. A semicolon file with decimal commas (Preis;Menge\n3,50;1.200\n): unchanged.

Decide yourself / report back

  • Decide and document in the hand-over: the exact warning wording (mirror "commas read as thousands separators, as in the file's other columns", but name the currency as the reason), the helper's name and whether it extends _commas_as_thousands or sits beside it.
  • Report back instead of guessing:
    • if the rule breaks an existing test,
    • if the column no longer knows its unit at the point where the rule has to run,
    • if you find the same bug in another code path (JSON input, prepare.py).

Activity

  1. added
    geminiTask for Gemini in the owner's interactive agy session (gemini-task skill)
    on Oct 21, 2026
  2. changed the title [-]Read comma groups of three as thousands separators in dot-decimal pastes[/-] [+]Read comma groups of three in currency columns as thousands separators[/+] on Oct 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    geminiTask for Gemini in the owner's interactive agy session (gemini-task skill)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions