{"id":"code-work-fin-pandas-reconcile-unmatched","audience":"finance","category":"coding","track":"coding","technique":"context","title":"Find unmatched bank and ledger lines with pandas","free":false,"task":"Write a pandas script that compares bank.csv and ledger.csv and writes unmatched.csv with only the lines that appear in one file but not the other. Match on both date and amount, with amounts rounded to 2 decimals first because the ledger stores values like 310.4500001. Add a column named side whose values are exactly bank only or ledger only, and don't write the index. One code block, at most 14 lines, then under 25 words outside the code.","materialLabel":"Both files, first rows (attached to your prompt automatically)","material":"bank.csv (from the bank portal)\ndate,amount,description\n2026-10-01,-1250.00,CARD KOPA OFFICE\n2026-10-02,4200.00,BACS LAKEVIEW DENTAL\n2026-10-04,-310.45,DD FLEETLINE INS\n2026-10-09,-15.00,BANK CHARGE\n\nledger.csv (from Ledgerly)\ndate,amount,memo\n2026-10-01,-1250.0,Office supplies - Kopa\n2026-10-02,4200,Inv 3301 Lakeview\n2026-10-04,-310.4500001,Insurance Oct\n2026-10-12,6000,Inv 3322 Okafor\n\nNotes from Ama:\n- The bank charge usually isn't booked until we reconcile.\n- Okafor's deposit was booked on the 12th but hit the bank on the 13th, which is in next week's export.\n- Descriptions never match between the two systems, so don't use them.\n- Both files have a header row.\n- Each month has about 300 lines.","rules":[{"type":"codeBlocks","count":1},{"type":"maxCodeLines","max":14},{"type":"maxProseWords","max":25}],"mistakes":[{"title":"Not mentioning float noise","why":"The AI compares raw amounts, so -310.45 and -310.4500001 look different.","fix":"Add: \"Round amounts to 2 decimals before matching.\"","checks":["r0"]},{"title":"Leaving the match key open","why":"The AI matches on amount alone or tries the descriptions, which never agree.","fix":"Add: \"Match on date and amount only.\"","checks":["r1"]},{"title":"Leaving the output open","why":"The AI prints both lists or keeps pandas' own left_only and right_only labels.","fix":"Add: \"One file, a side column saying bank only or ledger only, index=False.\"","checks":["r2"]},{"title":"Getting a menu of options","why":"The AI likes to offer two or three versions of the script, so you're left to pick and test them yourself.","fix":"Add: \"Give one script only, in one code block, no alternatives.\"","checks":["codeBlocks","maxCodeLines"]},{"title":"Getting a tutorial","why":"By default the AI explains every part of the code at length, which you then have to scroll past.","fix":"Add: \"After the code, one line under 12 words. Nothing else.\"","checks":["maxProseWords"]}],"promptHints":[{"label":"Rounds the amounts","patterns":["round","2 decimals","float"]},{"label":"Sets the match key","patterns":["date and amount","\\[.?date.?, ?.?amount","on date"]},{"label":"Names the side labels","patterns":["bank only","ledger only","side"]},{"label":"Sets the output","patterns":["unmatched\\.csv","index=false","no index"]},{"label":"Asks for one answer only","patterns":["\\b(one|single|1)\\s+(script|code block|block|version)","only one","no (alternatives|options|other versions)"]}],"hint":"Look at the insurance line in both files. Tell the AI how to make those match, what to match on, and how the result should be labeled.","rubricLabels":["Rounds amount to 2 decimals in both files (round(2)) before matching","Matches on both date and amount (for example merge on [\"date\", \"amount\"] with how=\"outer\" and indicator=True), not on description","Writes unmatched.csv with only the unmatched rows, a side column whose values are exactly bank only and ledger only, and index=False"]}