[{"data":1,"prerenderedAt":2610},["ShallowReactive",2],{"doc:\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Ffix-the-capitalisation-of-names-with-exceptions-in-pandas":3,"surround:\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Ffix-the-capitalisation-of-names-with-exceptions-in-pandas":2576,"ancestors:\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Ffix-the-capitalisation-of-names-with-exceptions-in-pandas":2585,"children:\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Ffix-the-capitalisation-of-names-with-exceptions-in-pandas":2590,"related:\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Ffix-the-capitalisation-of-names-with-exceptions-in-pandas":2591},{"id":4,"title":5,"body":6,"dateModified":2541,"datePublished":2541,"description":2542,"extension":2543,"faq":2544,"keyword":2553,"kind":2554,"meta":2555,"navigation":145,"path":2565,"seo":2566,"slug":2569,"stem":2570,"topics":2571,"type":2574,"__hash__":2575},"docs\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Ffix-the-capitalisation-of-names-with-exceptions-in-pandas\u002Findex.md","Fix the Capitalisation of Names with Exceptions in pandas",{"type":7,"value":8,"toc":2528},"minimark",[9,74,79,107,113,117,219,250,360,364,367,510,534,538,548,1263,1300,1427,1431,1436,1576,1582,1586,1589,1922,1943,1947,1950,2283,2290,2412,2416,2453,2457,2463,2467,2473,2479,2485,2491,2495,2524],[10,11,12,13,17,18,21,22,25,26,29,30,33,34,37,38,40,41,44,45,17,48,44,51,17,54,44,57,60,61,44,64,67,68,73],"p",{},"Customer lists collect names in every possible case. One system exports everything in capitals — ",[14,15,16],"code",{},"MARY O'BRIEN",", ",[14,19,20],{},"JOHN MCDONALD"," — a web form keeps whatever people typed — ",[14,23,24],{},"anna-lena schmidt"," — and the CRM holds the correctly written ",[14,27,28],{},"Ludwig van Beethoven",". Mail merges and reports need consistent, correct capitalisation, and pandas' obvious tool, ",[14,31,32],{},"str.title()",", gets the hard cases wrong: it produces ",[14,35,36],{},"O'Brien"," as ",[14,39,36],{}," only by luck, turns ",[14,42,43],{},"McDonald"," into ",[14,46,47],{},"Mcdonald",[14,49,50],{},"van",[14,52,53],{},"Van",[14,55,56],{},"III",[14,58,59],{},"Iii"," and ",[14,62,63],{},"ACME UK LLC",[14,65,66],{},"Acme Uk Llc",". This page writes a small name-casing function with explicit rules for these cases, applies it only to values that are clearly in the wrong case, and produces a list of every change for a person to skim before the data is used. It belongs to ",[69,70,72],"a",{"href":71},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002F","Cleaning Excel Data with pandas",".",[75,76,78],"h2",{"id":77},"prerequisites","Prerequisites",[80,81,86],"pre",{"className":82,"code":83,"language":84,"meta":85,"style":85},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl\n","bash","",[14,87,88],{"__ignoreMap":85},[89,90,93,97,101,104],"span",{"class":91,"line":92},"line",1,[89,94,96],{"class":95},"sMTad","pip",[89,98,100],{"class":99},"srMev"," install",[89,102,103],{"class":99}," pandas",[89,105,106],{"class":99}," openpyxl\n",[10,108,109,112],{},[14,110,111],{},"contacts.xlsx"," lists twelve contacts with a person's name and a company name, in a mix of capitals, lower case and correct mixed case, including names with apostrophes, Mc and Mac prefixes, hyphens, particles, a generational suffix, accented letters and one \"Surname, Forename\" entry.",[75,114,116],{"id":115},"step-1-see-what-strtitle-gets-wrong","Step 1 — See what str.title gets wrong",[80,118,122],{"className":119,"code":120,"language":121,"meta":85,"style":85},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\n\ndf = pd.read_excel(\"contacts.xlsx\")\ndf[\"title()\"] = df[\"Name\"].str.title()\nprint(df[[\"Name\", \"title()\"]].to_string(index=False))\n","python",[14,123,124,140,147,165,188],{"__ignoreMap":85},[89,125,126,130,134,137],{"class":91,"line":92},[89,127,129],{"class":128},"s-kum","import",[89,131,133],{"class":132},"skGVy"," pandas ",[89,135,136],{"class":128},"as",[89,138,139],{"class":132}," pd\n",[89,141,143],{"class":91,"line":142},2,[89,144,146],{"emptyLinePlaceholder":145},true,"\n",[89,148,150,153,156,159,162],{"class":91,"line":149},3,[89,151,152],{"class":132},"df ",[89,154,155],{"class":128},"=",[89,157,158],{"class":132}," pd.read_excel(",[89,160,161],{"class":99},"\"contacts.xlsx\"",[89,163,164],{"class":132},")\n",[89,166,168,171,174,177,179,182,185],{"class":91,"line":167},4,[89,169,170],{"class":132},"df[",[89,172,173],{"class":99},"\"title()\"",[89,175,176],{"class":132},"] ",[89,178,155],{"class":128},[89,180,181],{"class":132}," df[",[89,183,184],{"class":99},"\"Name\"",[89,186,187],{"class":132},"].str.title()\n",[89,189,191,195,198,200,202,204,207,211,213,216],{"class":91,"line":190},5,[89,192,194],{"class":193},"sP0c6","print",[89,196,197],{"class":132},"(df[[",[89,199,184],{"class":99},[89,201,17],{"class":132},[89,203,173],{"class":99},[89,205,206],{"class":132},"]].to_string(",[89,208,210],{"class":209},"sa561","index",[89,212,155],{"class":128},[89,214,215],{"class":193},"False",[89,217,218],{"class":132},"))\n",[10,220,221,223,224,226,227,230,231,233,234,237,238,242,243,245,246,249],{},[14,222,32],{}," capitalises the first letter after every non-letter, which is right for most names and wrong in predictable ways: ",[14,225,47],{}," instead of McDonald, ",[14,228,229],{},"Van Gogh"," where Dutch usage writes \"van Gogh\", ",[14,232,59],{}," for the Roman numeral, and ",[14,235,236],{},"D'Arcy"," correct only because the apostrophe happens to start a new \"word\". Worse, it ",[239,240,241],"em",{},"damages"," names that were already right: ",[14,244,28],{}," becomes ",[14,247,248],{},"Ludwig Van Beethoven",". Any fix must therefore do two things — apply better rules, and leave correctly cased names alone.",[251,252,260,261,260,265,260,269,260,277,260,287,260,298,260,304,260,310,260,315,260,319,260,323,260,327,260,332,260,339,260,344,260,348,260,351,260,354,260,357],"svg",{"viewBox":253,"role":254,"ariaLabelledBy":255,"xmlns":258,"style":259},"4 0 752 233","img",[256,257],"cap-title-t","cap-title-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[262,263,264],"title",{"id":256},"str.title() versus casing rules",[266,267,268],"desc",{"id":257},"str.title gives Mcdonald, Van Gogh, Iii and changes the correctly written Ludwig van Beethoven to Ludwig Van Beethoven. Explicit rules applied only to all-caps or all-lower values give McDonald, van Gogh, III and leave Beethoven unchanged.",[270,271],"rect",{"x":272,"y":273,"width":274,"height":275,"fill":276},"4","0","752","233","#ffffff",[270,278],{"x":279,"y":280,"width":281,"height":282,"rx":283,"fill":284,"stroke":285,"style":286},"20.0","16.0","351.0","201.0","14","#fce9e9","var(--danger,#dc2626)","stroke-width:2px",[288,289,291],"g",{"transform":290},"translate(182.5,29.0) scale(1.083)",[292,293],"path",{"d":294,"fill":295,"stroke":296,"style":297},"M6 6l12 12 M18 6L6 18","none","var(--accent-ink,#be185d)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[299,300,32],"text",{"x":301,"y":302,"style":303},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle",[91,305],{"x1":306,"y1":307,"x2":308,"y2":307,"stroke":285,"style":309},"36.0","91.0","355.0","stroke-width:1px",[299,311,314],{"x":301,"y":312,"style":313},"111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","John Mcdonald",[299,316,318],{"x":301,"y":317,"style":313},"137.0","Vincent Van Gogh",[299,320,322],{"x":301,"y":321,"style":313},"163.0","Henry Ford Iii",[299,324,326],{"x":301,"y":325,"style":313},"189.0","Ludwig Van Beethoven (damaged)",[270,328],{"x":329,"y":280,"width":281,"height":282,"rx":283,"fill":330,"stroke":331,"style":286},"389.0","#d9f4f1","var(--teal,#0f9488)",[288,333,335],{"transform":334},"translate(551.5,29.0) scale(1.083)",[292,336],{"d":337,"fill":295,"stroke":338,"style":297},"M5 12.5l4.5 4.5L19 7","var(--teal-ink,#0b6157)",[299,340,343],{"x":341,"y":302,"style":342},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","rules, wrong-case values only",[91,345],{"x1":346,"y1":307,"x2":347,"y2":307,"stroke":331,"style":309},"405.0","724.0",[299,349,350],{"x":341,"y":312,"style":313},"John McDonald",[299,352,353],{"x":341,"y":317,"style":313},"Vincent van Gogh",[299,355,356],{"x":341,"y":321,"style":313},"Henry Ford III",[299,358,359],{"x":341,"y":325,"style":313},"Ludwig van Beethoven (untouched)",[75,361,363],{"id":362},"step-2-decide-which-values-to-touch","Step 2 — Decide which values to touch",[10,365,366],{},"A name written in mixed case — some capitals, some lower case — was almost certainly typed deliberately, and the person knows how their name is spelt. Only values that are entirely upper case or entirely lower case are candidates for fixing:",[80,368,370],{"className":119,"code":369,"language":121,"meta":85,"style":85},"def needs_fixing(text):\n    letters = [ch for ch in str(text) if ch.isalpha()]\n    return bool(letters) and (all(ch.isupper() for ch in letters) or all(ch.islower() for ch in letters))\n\ndf[\"fix?\"] = df[\"Name\"].map(needs_fixing)\nprint(df[[\"Name\", \"fix?\"]].to_string(index=False))\n",[14,371,372,384,415,465,469,487],{"__ignoreMap":85},[89,373,374,377,381],{"class":91,"line":92},[89,375,376],{"class":128},"def",[89,378,380],{"class":379},"s_Opv"," needs_fixing",[89,382,383],{"class":132},"(text):\n",[89,385,386,389,391,394,397,400,403,406,409,412],{"class":91,"line":142},[89,387,388],{"class":132},"    letters ",[89,390,155],{"class":128},[89,392,393],{"class":132}," [ch ",[89,395,396],{"class":128},"for",[89,398,399],{"class":132}," ch ",[89,401,402],{"class":128},"in",[89,404,405],{"class":193}," str",[89,407,408],{"class":132},"(text) ",[89,410,411],{"class":128},"if",[89,413,414],{"class":132}," ch.isalpha()]\n",[89,416,417,420,423,426,429,432,435,438,440,442,444,447,450,453,456,458,460,462],{"class":91,"line":149},[89,418,419],{"class":128},"    return",[89,421,422],{"class":193}," bool",[89,424,425],{"class":132},"(letters) ",[89,427,428],{"class":128},"and",[89,430,431],{"class":132}," (",[89,433,434],{"class":193},"all",[89,436,437],{"class":132},"(ch.isupper() ",[89,439,396],{"class":128},[89,441,399],{"class":132},[89,443,402],{"class":128},[89,445,446],{"class":132}," letters) ",[89,448,449],{"class":128},"or",[89,451,452],{"class":193}," all",[89,454,455],{"class":132},"(ch.islower() ",[89,457,396],{"class":128},[89,459,399],{"class":132},[89,461,402],{"class":128},[89,463,464],{"class":132}," letters))\n",[89,466,467],{"class":91,"line":167},[89,468,146],{"emptyLinePlaceholder":145},[89,470,471,473,476,478,480,482,484],{"class":91,"line":190},[89,472,170],{"class":132},[89,474,475],{"class":99},"\"fix?\"",[89,477,176],{"class":132},[89,479,155],{"class":128},[89,481,181],{"class":132},[89,483,184],{"class":99},[89,485,486],{"class":132},"].map(needs_fixing)\n",[89,488,490,492,494,496,498,500,502,504,506,508],{"class":91,"line":489},6,[89,491,194],{"class":193},[89,493,197],{"class":132},[89,495,184],{"class":99},[89,497,17],{"class":132},[89,499,475],{"class":99},[89,501,206],{"class":132},[89,503,210],{"class":209},[89,505,155],{"class":128},[89,507,215],{"class":193},[89,509,218],{"class":132},[10,511,512,514,515,518,519,60,522,525,526,529,530,533],{},[14,513,28],{}," is mixed case and is left exactly as it is. ",[14,516,517],{},"José ÁLVAREZ"," is mixed too — the first name is fine, the surname is shouting — so the whole-value test leaves it alone; Step 4 shows a per-word refinement for such cases. Testing letters only, with ",[14,520,521],{},"str.isupper",[14,523,524],{},"str.islower",", means punctuation, digits and accented letters are handled correctly: ",[14,527,528],{},"Á"," is upper case, ",[14,531,532],{},"é"," lower case.",[75,535,537],{"id":536},"step-3-a-casing-function-with-explicit-rules","Step 3 — A casing function with explicit rules",[10,539,540,541,60,544,547],{},"Lower-case the value, then rebuild each word with rules for the known exceptions. Words are split on spaces, and each word is further split on hyphens and apostrophes so ",[14,542,543],{},"anna-lena",[14,545,546],{},"o'brien"," are handled piece by piece:",[80,549,551],{"className":119,"code":550,"language":121,"meta":85,"style":85},"import re\n\nPARTICLES = {\"van\", \"von\", \"der\", \"den\", \"de\", \"la\", \"le\", \"da\", \"di\", \"du\", \"del\", \"dos\", \"das\", \"ter\"}\nSUFFIXES = {\"ii\": \"II\", \"iii\": \"III\", \"iv\": \"IV\", \"jr\": \"Jr\", \"sr\": \"Sr\"}\nNOT_MAC = {\"mack\", \"macy\", \"mace\", \"machin\", \"macho\"}\n\ndef case_piece(piece):\n    if not piece:\n        return piece\n    low = piece.lower()\n    if low.startswith(\"mc\") and len(low) > 2:\n        return \"Mc\" + low[2].upper() + low[3:]\n    if low.startswith(\"mac\") and len(low) > 4 and low not in NOT_MAC:\n        return \"Mac\" + low[3].upper() + low[4:]\n    return low[0].upper() + low[1:]\n\ndef case_name(text):\n    words = str(text).lower().split()\n    out = []\n    for i, w in enumerate(words):\n        core = w.rstrip(\",.\")\n        tail = w[len(core):]\n        if core in SUFFIXES:\n            out.append(SUFFIXES[core] + tail)\n        elif core in PARTICLES and 0 \u003C i \u003C len(words) - 1:\n            out.append(core + tail)\n        else:\n            parts = re.split(r\"([-'’])\", core)\n            out.append(\"\".join(case_piece(p) if p not in \"-'’\" else p for p in parts) + tail)\n    return \" \".join(out)\n\ndf[\"Name fixed\"] = [case_name(n) if needs_fixing(n) else n for n in df[\"Name\"]]\nprint(df[[\"Name\", \"Name fixed\"]].to_string(index=False))\n",[14,552,553,560,564,646,706,740,744,755,767,776,787,818,849,889,913,933,938,948,961,972,989,1005,1022,1038,1054,1094,1104,1112,1144,1185,1196,1201,1240],{"__ignoreMap":85},[89,554,555,557],{"class":91,"line":92},[89,556,129],{"class":128},[89,558,559],{"class":132}," re\n",[89,561,562],{"class":91,"line":142},[89,563,146],{"emptyLinePlaceholder":145},[89,565,566,569,572,575,578,580,583,585,588,590,593,595,598,600,603,605,608,610,613,615,618,620,623,625,628,630,633,635,638,640,643],{"class":91,"line":149},[89,567,568],{"class":193},"PARTICLES",[89,570,571],{"class":128}," =",[89,573,574],{"class":132}," {",[89,576,577],{"class":99},"\"van\"",[89,579,17],{"class":132},[89,581,582],{"class":99},"\"von\"",[89,584,17],{"class":132},[89,586,587],{"class":99},"\"der\"",[89,589,17],{"class":132},[89,591,592],{"class":99},"\"den\"",[89,594,17],{"class":132},[89,596,597],{"class":99},"\"de\"",[89,599,17],{"class":132},[89,601,602],{"class":99},"\"la\"",[89,604,17],{"class":132},[89,606,607],{"class":99},"\"le\"",[89,609,17],{"class":132},[89,611,612],{"class":99},"\"da\"",[89,614,17],{"class":132},[89,616,617],{"class":99},"\"di\"",[89,619,17],{"class":132},[89,621,622],{"class":99},"\"du\"",[89,624,17],{"class":132},[89,626,627],{"class":99},"\"del\"",[89,629,17],{"class":132},[89,631,632],{"class":99},"\"dos\"",[89,634,17],{"class":132},[89,636,637],{"class":99},"\"das\"",[89,639,17],{"class":132},[89,641,642],{"class":99},"\"ter\"",[89,644,645],{"class":132},"}\n",[89,647,648,651,653,655,658,661,664,666,669,671,674,676,679,681,684,686,689,691,694,696,699,701,704],{"class":91,"line":167},[89,649,650],{"class":193},"SUFFIXES",[89,652,571],{"class":128},[89,654,574],{"class":132},[89,656,657],{"class":99},"\"ii\"",[89,659,660],{"class":132},": ",[89,662,663],{"class":99},"\"II\"",[89,665,17],{"class":132},[89,667,668],{"class":99},"\"iii\"",[89,670,660],{"class":132},[89,672,673],{"class":99},"\"III\"",[89,675,17],{"class":132},[89,677,678],{"class":99},"\"iv\"",[89,680,660],{"class":132},[89,682,683],{"class":99},"\"IV\"",[89,685,17],{"class":132},[89,687,688],{"class":99},"\"jr\"",[89,690,660],{"class":132},[89,692,693],{"class":99},"\"Jr\"",[89,695,17],{"class":132},[89,697,698],{"class":99},"\"sr\"",[89,700,660],{"class":132},[89,702,703],{"class":99},"\"Sr\"",[89,705,645],{"class":132},[89,707,708,711,713,715,718,720,723,725,728,730,733,735,738],{"class":91,"line":190},[89,709,710],{"class":193},"NOT_MAC",[89,712,571],{"class":128},[89,714,574],{"class":132},[89,716,717],{"class":99},"\"mack\"",[89,719,17],{"class":132},[89,721,722],{"class":99},"\"macy\"",[89,724,17],{"class":132},[89,726,727],{"class":99},"\"mace\"",[89,729,17],{"class":132},[89,731,732],{"class":99},"\"machin\"",[89,734,17],{"class":132},[89,736,737],{"class":99},"\"macho\"",[89,739,645],{"class":132},[89,741,742],{"class":91,"line":489},[89,743,146],{"emptyLinePlaceholder":145},[89,745,747,749,752],{"class":91,"line":746},7,[89,748,376],{"class":128},[89,750,751],{"class":379}," case_piece",[89,753,754],{"class":132},"(piece):\n",[89,756,758,761,764],{"class":91,"line":757},8,[89,759,760],{"class":128},"    if",[89,762,763],{"class":128}," not",[89,765,766],{"class":132}," piece:\n",[89,768,770,773],{"class":91,"line":769},9,[89,771,772],{"class":128},"        return",[89,774,775],{"class":132}," piece\n",[89,777,779,782,784],{"class":91,"line":778},10,[89,780,781],{"class":132},"    low ",[89,783,155],{"class":128},[89,785,786],{"class":132}," piece.lower()\n",[89,788,790,792,795,798,801,803,806,809,812,815],{"class":91,"line":789},11,[89,791,760],{"class":128},[89,793,794],{"class":132}," low.startswith(",[89,796,797],{"class":99},"\"mc\"",[89,799,800],{"class":132},") ",[89,802,428],{"class":128},[89,804,805],{"class":193}," len",[89,807,808],{"class":132},"(low) ",[89,810,811],{"class":128},">",[89,813,814],{"class":193}," 2",[89,816,817],{"class":132},":\n",[89,819,821,823,826,829,832,835,838,841,843,846],{"class":91,"line":820},12,[89,822,772],{"class":128},[89,824,825],{"class":99}," \"Mc\"",[89,827,828],{"class":128}," +",[89,830,831],{"class":132}," low[",[89,833,834],{"class":193},"2",[89,836,837],{"class":132},"].upper() ",[89,839,840],{"class":128},"+",[89,842,831],{"class":132},[89,844,845],{"class":193},"3",[89,847,848],{"class":132},":]\n",[89,850,852,854,856,859,861,863,865,867,869,872,875,878,881,884,887],{"class":91,"line":851},13,[89,853,760],{"class":128},[89,855,794],{"class":132},[89,857,858],{"class":99},"\"mac\"",[89,860,800],{"class":132},[89,862,428],{"class":128},[89,864,805],{"class":193},[89,866,808],{"class":132},[89,868,811],{"class":128},[89,870,871],{"class":193}," 4",[89,873,874],{"class":128}," and",[89,876,877],{"class":132}," low ",[89,879,880],{"class":128},"not",[89,882,883],{"class":128}," in",[89,885,886],{"class":193}," NOT_MAC",[89,888,817],{"class":132},[89,890,892,894,897,899,901,903,905,907,909,911],{"class":91,"line":891},14,[89,893,772],{"class":128},[89,895,896],{"class":99}," \"Mac\"",[89,898,828],{"class":128},[89,900,831],{"class":132},[89,902,845],{"class":193},[89,904,837],{"class":132},[89,906,840],{"class":128},[89,908,831],{"class":132},[89,910,272],{"class":193},[89,912,848],{"class":132},[89,914,916,918,920,922,924,926,928,931],{"class":91,"line":915},15,[89,917,419],{"class":128},[89,919,831],{"class":132},[89,921,273],{"class":193},[89,923,837],{"class":132},[89,925,840],{"class":128},[89,927,831],{"class":132},[89,929,930],{"class":193},"1",[89,932,848],{"class":132},[89,934,936],{"class":91,"line":935},16,[89,937,146],{"emptyLinePlaceholder":145},[89,939,941,943,946],{"class":91,"line":940},17,[89,942,376],{"class":128},[89,944,945],{"class":379}," case_name",[89,947,383],{"class":132},[89,949,951,954,956,958],{"class":91,"line":950},18,[89,952,953],{"class":132},"    words ",[89,955,155],{"class":128},[89,957,405],{"class":193},[89,959,960],{"class":132},"(text).lower().split()\n",[89,962,964,967,969],{"class":91,"line":963},19,[89,965,966],{"class":132},"    out ",[89,968,155],{"class":128},[89,970,971],{"class":132}," []\n",[89,973,975,978,981,983,986],{"class":91,"line":974},20,[89,976,977],{"class":128},"    for",[89,979,980],{"class":132}," i, w ",[89,982,402],{"class":128},[89,984,985],{"class":193}," enumerate",[89,987,988],{"class":132},"(words):\n",[89,990,992,995,997,1000,1003],{"class":91,"line":991},21,[89,993,994],{"class":132},"        core ",[89,996,155],{"class":128},[89,998,999],{"class":132}," w.rstrip(",[89,1001,1002],{"class":99},"\",.\"",[89,1004,164],{"class":132},[89,1006,1008,1011,1013,1016,1019],{"class":91,"line":1007},22,[89,1009,1010],{"class":132},"        tail ",[89,1012,155],{"class":128},[89,1014,1015],{"class":132}," w[",[89,1017,1018],{"class":193},"len",[89,1020,1021],{"class":132},"(core):]\n",[89,1023,1025,1028,1031,1033,1036],{"class":91,"line":1024},23,[89,1026,1027],{"class":128},"        if",[89,1029,1030],{"class":132}," core ",[89,1032,402],{"class":128},[89,1034,1035],{"class":193}," SUFFIXES",[89,1037,817],{"class":132},[89,1039,1041,1044,1046,1049,1051],{"class":91,"line":1040},24,[89,1042,1043],{"class":132},"            out.append(",[89,1045,650],{"class":193},[89,1047,1048],{"class":132},"[core] ",[89,1050,840],{"class":128},[89,1052,1053],{"class":132}," tail)\n",[89,1055,1057,1060,1062,1064,1067,1069,1072,1075,1078,1081,1083,1086,1089,1092],{"class":91,"line":1056},25,[89,1058,1059],{"class":128},"        elif",[89,1061,1030],{"class":132},[89,1063,402],{"class":128},[89,1065,1066],{"class":193}," PARTICLES",[89,1068,874],{"class":128},[89,1070,1071],{"class":193}," 0",[89,1073,1074],{"class":128}," \u003C",[89,1076,1077],{"class":132}," i ",[89,1079,1080],{"class":128},"\u003C",[89,1082,805],{"class":193},[89,1084,1085],{"class":132},"(words) ",[89,1087,1088],{"class":128},"-",[89,1090,1091],{"class":193}," 1",[89,1093,817],{"class":132},[89,1095,1097,1100,1102],{"class":91,"line":1096},26,[89,1098,1099],{"class":132},"            out.append(core ",[89,1101,840],{"class":128},[89,1103,1053],{"class":132},[89,1105,1107,1110],{"class":91,"line":1106},27,[89,1108,1109],{"class":128},"        else",[89,1111,817],{"class":132},[89,1113,1115,1118,1120,1123,1126,1129,1132,1136,1139,1141],{"class":91,"line":1114},28,[89,1116,1117],{"class":132},"            parts ",[89,1119,155],{"class":128},[89,1121,1122],{"class":132}," re.split(",[89,1124,1125],{"class":128},"r",[89,1127,1128],{"class":99},"\"",[89,1130,1131],{"class":193},"([",[89,1133,1135],{"class":1134},"sSjpA","-'’",[89,1137,1138],{"class":193},"])",[89,1140,1128],{"class":99},[89,1142,1143],{"class":132},", core)\n",[89,1145,1147,1149,1152,1155,1157,1160,1162,1164,1167,1170,1172,1174,1176,1178,1181,1183],{"class":91,"line":1146},29,[89,1148,1043],{"class":132},[89,1150,1151],{"class":99},"\"\"",[89,1153,1154],{"class":132},".join(case_piece(p) ",[89,1156,411],{"class":128},[89,1158,1159],{"class":132}," p ",[89,1161,880],{"class":128},[89,1163,883],{"class":128},[89,1165,1166],{"class":99}," \"-'’\"",[89,1168,1169],{"class":128}," else",[89,1171,1159],{"class":132},[89,1173,396],{"class":128},[89,1175,1159],{"class":132},[89,1177,402],{"class":128},[89,1179,1180],{"class":132}," parts) ",[89,1182,840],{"class":128},[89,1184,1053],{"class":132},[89,1186,1188,1190,1193],{"class":91,"line":1187},30,[89,1189,419],{"class":128},[89,1191,1192],{"class":99}," \" \"",[89,1194,1195],{"class":132},".join(out)\n",[89,1197,1199],{"class":91,"line":1198},31,[89,1200,146],{"emptyLinePlaceholder":145},[89,1202,1204,1206,1209,1211,1213,1216,1218,1221,1224,1227,1229,1231,1233,1235,1237],{"class":91,"line":1203},32,[89,1205,170],{"class":132},[89,1207,1208],{"class":99},"\"Name fixed\"",[89,1210,176],{"class":132},[89,1212,155],{"class":128},[89,1214,1215],{"class":132}," [case_name(n) ",[89,1217,411],{"class":128},[89,1219,1220],{"class":132}," needs_fixing(n) ",[89,1222,1223],{"class":128},"else",[89,1225,1226],{"class":132}," n ",[89,1228,396],{"class":128},[89,1230,1226],{"class":132},[89,1232,402],{"class":128},[89,1234,181],{"class":132},[89,1236,184],{"class":99},[89,1238,1239],{"class":132},"]]\n",[89,1241,1243,1245,1247,1249,1251,1253,1255,1257,1259,1261],{"class":91,"line":1242},33,[89,1244,194],{"class":193},[89,1246,197],{"class":132},[89,1248,184],{"class":99},[89,1250,17],{"class":132},[89,1252,1208],{"class":99},[89,1254,206],{"class":132},[89,1256,210],{"class":209},[89,1258,155],{"class":128},[89,1260,215],{"class":193},[89,1262,218],{"class":132},[10,1264,1265,1267,1268,1271,1272,1275,1276,1279,1280,1283,1284,1287,1288,1291,1292,1295,1296,1299],{},[14,1266,16],{}," becomes Mary O'Brien, ",[14,1269,1270],{},"john mcdonald"," John McDonald, ",[14,1273,1274],{},"ANNA-LENA SCHMIDT"," Anna-Lena Schmidt, and ",[14,1277,1278],{},"HENRY FORD III"," Henry Ford III. Particles stay lower case ",[239,1281,1282],{},"between"," other words — ",[14,1285,1286],{},"VINCENT VAN GOGH"," becomes Vincent van Gogh, ",[14,1289,1290],{},"maria de la cruz"," Maria de la Cruz — but are capitalised at the start, so ",[14,1293,1294],{},"DE SOUZA, PAULO"," becomes De Souza, Paulo. The Mac rule is deliberately cautious: Sarah MacIntyre is cased as Mac + capital, but ",[14,1297,1298],{},"DEREK MACK"," stays Mack, because \"mack\" is on the exception list. No rule set is perfect — some families write MacIntyre, others Macintyre — which is why the next step lists every change for review.",[251,1301,260,1306,260,1309,260,1312,260,1315,260,1320,260,1327,260,1333,260,1336,260,1340,260,1345,260,1350,260,1352,260,1356,260,1358,260,1361,260,1364,260,1368,260,1370,260,1372,260,1374,260,1377,260,1380,260,1384,260,1386,260,1390,260,1392,260,1395,260,1398,260,1402,260,1404,260,1407,260,1409,260,1411,260,1414,260,1418,260,1420,260,1423,260,1425],{"viewBox":1302,"role":254,"ariaLabelledBy":1303,"xmlns":258,"style":259},"4 0 752 242",[1304,1305],"cap-rules-t","cap-rules-d",[262,1307,1308],{"id":1304},"The casing rules and what they produce",[266,1310,1311],{"id":1305},"Apostrophes and hyphens start a new capital, as in O'Brien and Anna-Lena. Mc is followed by a capital, as in McDonald. Mac is followed by a capital except for words like Mack. Particles such as van and de stay lower case between other words. Generational suffixes become II, III, Jr.",[270,1313],{"x":272,"y":273,"width":274,"height":1314,"fill":276},"242",[270,1316],{"x":279,"y":280,"width":1317,"height":1318,"rx":273,"fill":276,"stroke":1319,"style":309},"101.7","40.0","var(--line,#cdd5e6)",[270,1321],{"x":1322,"y":280,"width":1323,"height":1318,"rx":273,"fill":1324,"stroke":1325,"style":1326},"121.7","309.1","#f0f4ff","var(--brand,#5b5cf0)","stroke-width:1.2px",[299,1328,1332],{"x":1329,"y":1330,"style":1331},"276.3","41.0","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","input",[270,1334],{"x":1335,"y":280,"width":1323,"height":1318,"rx":273,"fill":1324,"stroke":1325,"style":1326},"430.9",[299,1337,1339],{"x":1338,"y":1330,"style":1331},"585.4","output",[270,1341],{"x":279,"y":1342,"width":1317,"height":1343,"rx":273,"fill":1344,"stroke":1319,"style":309},"56.0","34.0","#e7ebef",[299,1346,1349],{"x":1347,"y":302,"style":1348},"32.0","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:start","apostrophe",[270,1351],{"x":1322,"y":1342,"width":1323,"height":1343,"rx":273,"fill":276,"stroke":1319,"style":309},[299,1353,16],{"x":1329,"y":1354,"style":1355},"77.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle",[270,1357],{"x":1335,"y":1342,"width":1323,"height":1343,"rx":273,"fill":276,"stroke":1319,"style":309},[299,1359,1360],{"x":1338,"y":1354,"style":1355},"Mary O'Brien",[270,1362],{"x":279,"y":1363,"width":1317,"height":1343,"rx":273,"fill":1344,"stroke":1319,"style":309},"90.0",[299,1365,1367],{"x":1347,"y":1366,"style":1348},"112.0","hyphen",[270,1369],{"x":1322,"y":1363,"width":1323,"height":1343,"rx":273,"fill":276,"stroke":1319,"style":309},[299,1371,1274],{"x":1329,"y":312,"style":1355},[270,1373],{"x":1335,"y":1363,"width":1323,"height":1343,"rx":273,"fill":276,"stroke":1319,"style":309},[299,1375,1376],{"x":1338,"y":312,"style":1355},"Anna-Lena Schmidt",[270,1378],{"x":279,"y":1379,"width":1317,"height":1343,"rx":273,"fill":1344,"stroke":1319,"style":309},"124.0",[299,1381,1383],{"x":1347,"y":1382,"style":1348},"146.0","Mc \u002F Mac",[270,1385],{"x":1322,"y":1379,"width":1323,"height":1343,"rx":273,"fill":276,"stroke":1319,"style":309},[299,1387,1389],{"x":1329,"y":1388,"style":1355},"145.0","john mcdonald · DEREK MACK",[270,1391],{"x":1335,"y":1379,"width":1323,"height":1343,"rx":273,"fill":276,"stroke":1319,"style":309},[299,1393,1394],{"x":1338,"y":1388,"style":1355},"John McDonald · Derek Mack",[270,1396],{"x":279,"y":1397,"width":1317,"height":1343,"rx":273,"fill":1344,"stroke":1319,"style":309},"158.0",[299,1399,1401],{"x":1347,"y":1400,"style":1348},"180.0","particles",[270,1403],{"x":1322,"y":1397,"width":1323,"height":1343,"rx":273,"fill":276,"stroke":1319,"style":309},[299,1405,1286],{"x":1329,"y":1406,"style":1355},"179.0",[270,1408],{"x":1335,"y":1397,"width":1323,"height":1343,"rx":273,"fill":276,"stroke":1319,"style":309},[299,1410,353],{"x":1338,"y":1406,"style":1355},[270,1412],{"x":279,"y":1413,"width":1317,"height":1343,"rx":273,"fill":1344,"stroke":1319,"style":309},"192.0",[299,1415,1417],{"x":1347,"y":1416,"style":1348},"214.0","suffix",[270,1419],{"x":1322,"y":1413,"width":1323,"height":1343,"rx":273,"fill":276,"stroke":1319,"style":309},[299,1421,1278],{"x":1329,"y":1422,"style":1355},"213.0",[270,1424],{"x":1335,"y":1413,"width":1323,"height":1343,"rx":273,"fill":276,"stroke":1319,"style":309},[299,1426,356],{"x":1338,"y":1422,"style":1355},[75,1428,1430],{"id":1429},"step-4-per-word-repair-for-half-shouted-names","Step 4 — Per-word repair for half-shouted names",[10,1432,1433,1435],{},[14,1434,517],{}," is mixed case overall but has one shouting word. Applying the test per word fixes only the offending part:",[80,1437,1439],{"className":119,"code":1438,"language":121,"meta":85,"style":85},"def case_name_per_word(text):\n    words = str(text).split()\n    return \" \".join(case_name(w) if needs_fixing(w) and len(w) > 1 and w.isupper() else w for w in words)\n\ndf[\"Name fixed\"] = [case_name(n) if needs_fixing(n) else case_name_per_word(n) for n in df[\"Name\"]]\nprint(df.loc[df[\"Name\"].str.contains(\"José\"), [\"Name\", \"Name fixed\"]].to_string(index=False))\n",[14,1440,1441,1450,1461,1505,1509,1542],{"__ignoreMap":85},[89,1442,1443,1445,1448],{"class":91,"line":92},[89,1444,376],{"class":128},[89,1446,1447],{"class":379}," case_name_per_word",[89,1449,383],{"class":132},[89,1451,1452,1454,1456,1458],{"class":91,"line":142},[89,1453,953],{"class":132},[89,1455,155],{"class":128},[89,1457,405],{"class":193},[89,1459,1460],{"class":132},"(text).split()\n",[89,1462,1463,1465,1467,1470,1472,1475,1477,1479,1482,1484,1486,1488,1491,1493,1496,1498,1500,1502],{"class":91,"line":149},[89,1464,419],{"class":128},[89,1466,1192],{"class":99},[89,1468,1469],{"class":132},".join(case_name(w) ",[89,1471,411],{"class":128},[89,1473,1474],{"class":132}," needs_fixing(w) ",[89,1476,428],{"class":128},[89,1478,805],{"class":193},[89,1480,1481],{"class":132},"(w) ",[89,1483,811],{"class":128},[89,1485,1091],{"class":193},[89,1487,874],{"class":128},[89,1489,1490],{"class":132}," w.isupper() ",[89,1492,1223],{"class":128},[89,1494,1495],{"class":132}," w ",[89,1497,396],{"class":128},[89,1499,1495],{"class":132},[89,1501,402],{"class":128},[89,1503,1504],{"class":132}," words)\n",[89,1506,1507],{"class":91,"line":167},[89,1508,146],{"emptyLinePlaceholder":145},[89,1510,1511,1513,1515,1517,1519,1521,1523,1525,1527,1530,1532,1534,1536,1538,1540],{"class":91,"line":190},[89,1512,170],{"class":132},[89,1514,1208],{"class":99},[89,1516,176],{"class":132},[89,1518,155],{"class":128},[89,1520,1215],{"class":132},[89,1522,411],{"class":128},[89,1524,1220],{"class":132},[89,1526,1223],{"class":128},[89,1528,1529],{"class":132}," case_name_per_word(n) ",[89,1531,396],{"class":128},[89,1533,1226],{"class":132},[89,1535,402],{"class":128},[89,1537,181],{"class":132},[89,1539,184],{"class":99},[89,1541,1239],{"class":132},[89,1543,1544,1546,1549,1551,1554,1557,1560,1562,1564,1566,1568,1570,1572,1574],{"class":91,"line":489},[89,1545,194],{"class":193},[89,1547,1548],{"class":132},"(df.loc[df[",[89,1550,184],{"class":99},[89,1552,1553],{"class":132},"].str.contains(",[89,1555,1556],{"class":99},"\"José\"",[89,1558,1559],{"class":132},"), [",[89,1561,184],{"class":99},[89,1563,17],{"class":132},[89,1565,1208],{"class":99},[89,1567,206],{"class":132},[89,1569,210],{"class":209},[89,1571,155],{"class":128},[89,1573,215],{"class":193},[89,1575,218],{"class":132},[10,1577,1578,1579,1581],{},"Only words written entirely in capitals inside an otherwise mixed-case value are recased, so José Álvarez is repaired while ",[14,1580,28],{}," remains untouched — its words are already mixed or lower case. Single capital letters such as middle initials are left alone. This refinement is optional; it suits sources where people tend to type their surname in capitals, a common habit on forms.",[75,1583,1585],{"id":1584},"step-5-companies-suffixes-and-acronyms","Step 5 — Companies: suffixes and acronyms",[10,1587,1588],{},"Company names add legal forms and acronyms that must stay in capitals — LLC, UK, GmbH, PLC — and connector words that are conventionally lower case:",[80,1590,1592],{"className":119,"code":1591,"language":121,"meta":85,"style":85},"UPPER = {\"llc\", \"uk\", \"us\", \"plc\", \"it\", \"bv\", \"sa\", \"sl\", \"ag\", \"nv\"}\nFIXED = {\"gmbh\": \"GmbH\", \"ltd\": \"Ltd\", \"co\": \"Co\", \"inc\": \"Inc\"}\nLOWER = {\"and\", \"of\", \"the\", \"&\"}\n\ndef case_company(text):\n    words = str(text).lower().split()\n    out = []\n    for i, w in enumerate(words):\n        if w in UPPER:\n            out.append(w.upper())\n        elif w in FIXED:\n            out.append(FIXED[w])\n        elif w in LOWER and i > 0:\n            out.append(w)\n        else:\n            out.append(case_name(w))\n    return \" \".join(out)\n\ndf[\"Company fixed\"] = [case_company(c) if needs_fixing(c) else c for c in df[\"Company\"]]\nprint(df[[\"Company\", \"Company fixed\"]].to_string(index=False))\n",[14,1593,1594,1653,1702,1731,1735,1744,1754,1762,1774,1787,1792,1805,1814,1835,1840,1846,1851,1859,1863,1900],{"__ignoreMap":85},[89,1595,1596,1599,1601,1603,1606,1608,1611,1613,1616,1618,1621,1623,1626,1628,1631,1633,1636,1638,1641,1643,1646,1648,1651],{"class":91,"line":92},[89,1597,1598],{"class":193},"UPPER",[89,1600,571],{"class":128},[89,1602,574],{"class":132},[89,1604,1605],{"class":99},"\"llc\"",[89,1607,17],{"class":132},[89,1609,1610],{"class":99},"\"uk\"",[89,1612,17],{"class":132},[89,1614,1615],{"class":99},"\"us\"",[89,1617,17],{"class":132},[89,1619,1620],{"class":99},"\"plc\"",[89,1622,17],{"class":132},[89,1624,1625],{"class":99},"\"it\"",[89,1627,17],{"class":132},[89,1629,1630],{"class":99},"\"bv\"",[89,1632,17],{"class":132},[89,1634,1635],{"class":99},"\"sa\"",[89,1637,17],{"class":132},[89,1639,1640],{"class":99},"\"sl\"",[89,1642,17],{"class":132},[89,1644,1645],{"class":99},"\"ag\"",[89,1647,17],{"class":132},[89,1649,1650],{"class":99},"\"nv\"",[89,1652,645],{"class":132},[89,1654,1655,1658,1660,1662,1665,1667,1670,1672,1675,1677,1680,1682,1685,1687,1690,1692,1695,1697,1700],{"class":91,"line":142},[89,1656,1657],{"class":193},"FIXED",[89,1659,571],{"class":128},[89,1661,574],{"class":132},[89,1663,1664],{"class":99},"\"gmbh\"",[89,1666,660],{"class":132},[89,1668,1669],{"class":99},"\"GmbH\"",[89,1671,17],{"class":132},[89,1673,1674],{"class":99},"\"ltd\"",[89,1676,660],{"class":132},[89,1678,1679],{"class":99},"\"Ltd\"",[89,1681,17],{"class":132},[89,1683,1684],{"class":99},"\"co\"",[89,1686,660],{"class":132},[89,1688,1689],{"class":99},"\"Co\"",[89,1691,17],{"class":132},[89,1693,1694],{"class":99},"\"inc\"",[89,1696,660],{"class":132},[89,1698,1699],{"class":99},"\"Inc\"",[89,1701,645],{"class":132},[89,1703,1704,1707,1709,1711,1714,1716,1719,1721,1724,1726,1729],{"class":91,"line":149},[89,1705,1706],{"class":193},"LOWER",[89,1708,571],{"class":128},[89,1710,574],{"class":132},[89,1712,1713],{"class":99},"\"and\"",[89,1715,17],{"class":132},[89,1717,1718],{"class":99},"\"of\"",[89,1720,17],{"class":132},[89,1722,1723],{"class":99},"\"the\"",[89,1725,17],{"class":132},[89,1727,1728],{"class":99},"\"&\"",[89,1730,645],{"class":132},[89,1732,1733],{"class":91,"line":167},[89,1734,146],{"emptyLinePlaceholder":145},[89,1736,1737,1739,1742],{"class":91,"line":190},[89,1738,376],{"class":128},[89,1740,1741],{"class":379}," case_company",[89,1743,383],{"class":132},[89,1745,1746,1748,1750,1752],{"class":91,"line":489},[89,1747,953],{"class":132},[89,1749,155],{"class":128},[89,1751,405],{"class":193},[89,1753,960],{"class":132},[89,1755,1756,1758,1760],{"class":91,"line":746},[89,1757,966],{"class":132},[89,1759,155],{"class":128},[89,1761,971],{"class":132},[89,1763,1764,1766,1768,1770,1772],{"class":91,"line":757},[89,1765,977],{"class":128},[89,1767,980],{"class":132},[89,1769,402],{"class":128},[89,1771,985],{"class":193},[89,1773,988],{"class":132},[89,1775,1776,1778,1780,1782,1785],{"class":91,"line":769},[89,1777,1027],{"class":128},[89,1779,1495],{"class":132},[89,1781,402],{"class":128},[89,1783,1784],{"class":193}," UPPER",[89,1786,817],{"class":132},[89,1788,1789],{"class":91,"line":778},[89,1790,1791],{"class":132},"            out.append(w.upper())\n",[89,1793,1794,1796,1798,1800,1803],{"class":91,"line":789},[89,1795,1059],{"class":128},[89,1797,1495],{"class":132},[89,1799,402],{"class":128},[89,1801,1802],{"class":193}," FIXED",[89,1804,817],{"class":132},[89,1806,1807,1809,1811],{"class":91,"line":820},[89,1808,1043],{"class":132},[89,1810,1657],{"class":193},[89,1812,1813],{"class":132},"[w])\n",[89,1815,1816,1818,1820,1822,1825,1827,1829,1831,1833],{"class":91,"line":851},[89,1817,1059],{"class":128},[89,1819,1495],{"class":132},[89,1821,402],{"class":128},[89,1823,1824],{"class":193}," LOWER",[89,1826,874],{"class":128},[89,1828,1077],{"class":132},[89,1830,811],{"class":128},[89,1832,1071],{"class":193},[89,1834,817],{"class":132},[89,1836,1837],{"class":91,"line":891},[89,1838,1839],{"class":132},"            out.append(w)\n",[89,1841,1842,1844],{"class":91,"line":915},[89,1843,1109],{"class":128},[89,1845,817],{"class":132},[89,1847,1848],{"class":91,"line":935},[89,1849,1850],{"class":132},"            out.append(case_name(w))\n",[89,1852,1853,1855,1857],{"class":91,"line":940},[89,1854,419],{"class":128},[89,1856,1192],{"class":99},[89,1858,1195],{"class":132},[89,1860,1861],{"class":91,"line":950},[89,1862,146],{"emptyLinePlaceholder":145},[89,1864,1865,1867,1870,1872,1874,1877,1879,1882,1884,1887,1889,1891,1893,1895,1898],{"class":91,"line":963},[89,1866,170],{"class":132},[89,1868,1869],{"class":99},"\"Company fixed\"",[89,1871,176],{"class":132},[89,1873,155],{"class":128},[89,1875,1876],{"class":132}," [case_company(c) ",[89,1878,411],{"class":128},[89,1880,1881],{"class":132}," needs_fixing(c) ",[89,1883,1223],{"class":128},[89,1885,1886],{"class":132}," c ",[89,1888,396],{"class":128},[89,1890,1886],{"class":132},[89,1892,402],{"class":128},[89,1894,181],{"class":132},[89,1896,1897],{"class":99},"\"Company\"",[89,1899,1239],{"class":132},[89,1901,1902,1904,1906,1908,1910,1912,1914,1916,1918,1920],{"class":91,"line":974},[89,1903,194],{"class":193},[89,1905,197],{"class":132},[89,1907,1897],{"class":99},[89,1909,17],{"class":132},[89,1911,1869],{"class":99},[89,1913,206],{"class":132},[89,1915,210],{"class":209},[89,1917,155],{"class":128},[89,1919,215],{"class":193},[89,1921,218],{"class":132},[10,1923,1924,1926,1927,1930,1931,1934,1935,1938,1939,1942],{},[14,1925,63],{}," becomes Acme UK LLC, ",[14,1928,1929],{},"SCHMIDT GMBH"," Schmidt GmbH, ",[14,1932,1933],{},"mcdonald & sons ltd"," McDonald & Sons Ltd, and ",[14,1936,1937],{},"VAN GOGH AND CO"," Van Gogh and Co — the company name starts with \"Van\" because it is the first word, and \"and\" stays lower case. Reusing ",[14,1940,1941],{},"case_name"," for ordinary words means McDonald and D'Arcy get the same treatment in company names as in personal names. The acronym list will need entries for your own data — sector abbreviations, country codes — and is the part of the code to extend over time.",[75,1944,1946],{"id":1945},"step-6-review-the-changes-and-write-them-out","Step 6 — Review the changes and write them out",[10,1948,1949],{},"Never overwrite names silently. Write the original and the suggestion side by side, highlight changed rows, and let someone skim the list:",[80,1951,1953],{"className":119,"code":1952,"language":121,"meta":85,"style":85},"from openpyxl.styles import PatternFill\n\nchanges = df[(df[\"Name\"] != df[\"Name fixed\"]) | (df[\"Company\"] != df[\"Company fixed\"])]\nwith pd.ExcelWriter(\"contacts_cased.xlsx\", engine=\"openpyxl\") as xw:\n    df[[\"Name\", \"Name fixed\", \"Company\", \"Company fixed\"]].to_excel(xw, sheet_name=\"Contacts\", index=False)\n    ws = xw.sheets[\"Contacts\"]\n    for r, changed in enumerate(df.index.isin(changes.index), start=2):\n        if changed:\n            for c in (\"B\", \"D\"):\n                ws[f\"{c}{r}\"].fill = PatternFill(\"solid\", fgColor=\"FFF2CC\")\n    for col in \"ABCD\":\n        ws.column_dimensions[col].width = 26\nprint(f\"{len(changes)} of {len(df)} rows changed; unchanged: {list(df.loc[~df.index.isin(changes.index), 'Name'])}\")\n",[14,1954,1955,1968,1972,2015,2043,2083,2098,2122,2129,2150,2199,2213,2223],{"__ignoreMap":85},[89,1956,1957,1960,1963,1965],{"class":91,"line":92},[89,1958,1959],{"class":128},"from",[89,1961,1962],{"class":132}," openpyxl.styles ",[89,1964,129],{"class":128},[89,1966,1967],{"class":132}," PatternFill\n",[89,1969,1970],{"class":91,"line":142},[89,1971,146],{"emptyLinePlaceholder":145},[89,1973,1974,1977,1979,1982,1984,1986,1989,1991,1993,1996,1999,2002,2004,2006,2008,2010,2012],{"class":91,"line":149},[89,1975,1976],{"class":132},"changes ",[89,1978,155],{"class":128},[89,1980,1981],{"class":132}," df[(df[",[89,1983,184],{"class":99},[89,1985,176],{"class":132},[89,1987,1988],{"class":128},"!=",[89,1990,181],{"class":132},[89,1992,1208],{"class":99},[89,1994,1995],{"class":132},"]) ",[89,1997,1998],{"class":128},"|",[89,2000,2001],{"class":132}," (df[",[89,2003,1897],{"class":99},[89,2005,176],{"class":132},[89,2007,1988],{"class":128},[89,2009,181],{"class":132},[89,2011,1869],{"class":99},[89,2013,2014],{"class":132},"])]\n",[89,2016,2017,2020,2023,2026,2028,2031,2033,2036,2038,2040],{"class":91,"line":167},[89,2018,2019],{"class":128},"with",[89,2021,2022],{"class":132}," pd.ExcelWriter(",[89,2024,2025],{"class":99},"\"contacts_cased.xlsx\"",[89,2027,17],{"class":132},[89,2029,2030],{"class":209},"engine",[89,2032,155],{"class":128},[89,2034,2035],{"class":99},"\"openpyxl\"",[89,2037,800],{"class":132},[89,2039,136],{"class":128},[89,2041,2042],{"class":132}," xw:\n",[89,2044,2045,2048,2050,2052,2054,2056,2058,2060,2062,2065,2068,2070,2073,2075,2077,2079,2081],{"class":91,"line":190},[89,2046,2047],{"class":132},"    df[[",[89,2049,184],{"class":99},[89,2051,17],{"class":132},[89,2053,1208],{"class":99},[89,2055,17],{"class":132},[89,2057,1897],{"class":99},[89,2059,17],{"class":132},[89,2061,1869],{"class":99},[89,2063,2064],{"class":132},"]].to_excel(xw, ",[89,2066,2067],{"class":209},"sheet_name",[89,2069,155],{"class":128},[89,2071,2072],{"class":99},"\"Contacts\"",[89,2074,17],{"class":132},[89,2076,210],{"class":209},[89,2078,155],{"class":128},[89,2080,215],{"class":193},[89,2082,164],{"class":132},[89,2084,2085,2088,2090,2093,2095],{"class":91,"line":489},[89,2086,2087],{"class":132},"    ws ",[89,2089,155],{"class":128},[89,2091,2092],{"class":132}," xw.sheets[",[89,2094,2072],{"class":99},[89,2096,2097],{"class":132},"]\n",[89,2099,2100,2102,2105,2107,2109,2112,2115,2117,2119],{"class":91,"line":746},[89,2101,977],{"class":128},[89,2103,2104],{"class":132}," r, changed ",[89,2106,402],{"class":128},[89,2108,985],{"class":193},[89,2110,2111],{"class":132},"(df.index.isin(changes.index), ",[89,2113,2114],{"class":209},"start",[89,2116,155],{"class":128},[89,2118,834],{"class":193},[89,2120,2121],{"class":132},"):\n",[89,2123,2124,2126],{"class":91,"line":757},[89,2125,1027],{"class":128},[89,2127,2128],{"class":132}," changed:\n",[89,2130,2131,2134,2136,2138,2140,2143,2145,2148],{"class":91,"line":769},[89,2132,2133],{"class":128},"            for",[89,2135,1886],{"class":132},[89,2137,402],{"class":128},[89,2139,431],{"class":132},[89,2141,2142],{"class":99},"\"B\"",[89,2144,17],{"class":132},[89,2146,2147],{"class":99},"\"D\"",[89,2149,2121],{"class":132},[89,2151,2152,2155,2158,2160,2163,2166,2169,2171,2174,2176,2179,2181,2184,2187,2189,2192,2194,2197],{"class":91,"line":778},[89,2153,2154],{"class":132},"                ws[",[89,2156,2157],{"class":128},"f",[89,2159,1128],{"class":99},[89,2161,2162],{"class":1134},"{",[89,2164,2165],{"class":132},"c",[89,2167,2168],{"class":1134},"}{",[89,2170,1125],{"class":132},[89,2172,2173],{"class":1134},"}",[89,2175,1128],{"class":99},[89,2177,2178],{"class":132},"].fill ",[89,2180,155],{"class":128},[89,2182,2183],{"class":132}," PatternFill(",[89,2185,2186],{"class":99},"\"solid\"",[89,2188,17],{"class":132},[89,2190,2191],{"class":209},"fgColor",[89,2193,155],{"class":128},[89,2195,2196],{"class":99},"\"FFF2CC\"",[89,2198,164],{"class":132},[89,2200,2201,2203,2206,2208,2211],{"class":91,"line":789},[89,2202,977],{"class":128},[89,2204,2205],{"class":132}," col ",[89,2207,402],{"class":128},[89,2209,2210],{"class":99}," \"ABCD\"",[89,2212,817],{"class":132},[89,2214,2215,2218,2220],{"class":91,"line":820},[89,2216,2217],{"class":132},"        ws.column_dimensions[col].width ",[89,2219,155],{"class":128},[89,2221,2222],{"class":193}," 26\n",[89,2224,2225,2227,2230,2232,2234,2236,2238,2241,2243,2246,2248,2250,2253,2255,2258,2260,2263,2266,2269,2272,2275,2277,2279,2281],{"class":91,"line":851},[89,2226,194],{"class":193},[89,2228,2229],{"class":132},"(",[89,2231,2157],{"class":128},[89,2233,1128],{"class":99},[89,2235,2162],{"class":1134},[89,2237,1018],{"class":193},[89,2239,2240],{"class":132},"(changes)",[89,2242,2173],{"class":1134},[89,2244,2245],{"class":99}," of ",[89,2247,2162],{"class":1134},[89,2249,1018],{"class":193},[89,2251,2252],{"class":132},"(df)",[89,2254,2173],{"class":1134},[89,2256,2257],{"class":99}," rows changed; unchanged: ",[89,2259,2162],{"class":1134},[89,2261,2262],{"class":193},"list",[89,2264,2265],{"class":132},"(df.loc[",[89,2267,2268],{"class":128},"~",[89,2270,2271],{"class":132},"df.index.isin(changes.index), ",[89,2273,2274],{"class":99},"'Name'",[89,2276,1138],{"class":132},[89,2278,2173],{"class":1134},[89,2280,1128],{"class":99},[89,2282,164],{"class":132},[10,2284,2285,2286,73],{},"Changed rows are highlighted in the suggestion columns; only the correctly written Beethoven row is untouched. A reviewer can overwrite any suggestion they disagree with — a family that really is \"Macintyre\" — before the fixed columns replace the originals. Keeping the original columns also preserves the evidence of what the source system sent. Whitespace and other text clean-up that usually comes first is covered in ",[69,2287,2289],{"href":2288},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstrip-whitespace-and-normalise-text-columns-with-pandas\u002F","Strip Whitespace and Normalise Text Columns with pandas",[251,2291,260,2296,260,2299,260,2302,260,2305,260,2310,260,2318,260,2324,260,2328,260,2333,260,2338,260,2341,260,2348,260,2354,260,2358,260,2362,260,2365,260,2368,260,2371,260,2377,260,2382,260,2385,260,2389,260,2392,260,2397,260,2404,260,2409],{"viewBox":2292,"role":254,"ariaLabelledBy":2293,"xmlns":258,"style":259},"4 0 752 142",[2294,2295],"cap-flow-t","cap-flow-d",[262,2297,2298],{"id":2294},"Fixing name case safely",[266,2300,2301],{"id":2295},"Test whether each value is entirely upper or lower case, recase those values with explicit rules for apostrophes, hyphens, Mc and Mac, particles and suffixes, repair shouting words inside mixed values, apply company acronym rules, and write originals and suggestions side by side for review.",[270,2303],{"x":272,"y":273,"width":274,"height":2304,"fill":276},"142",[270,2306],{"x":279,"y":280,"width":2307,"height":2308,"rx":2309,"fill":1344,"stroke":1319,"style":286},"153.0","110.5","12",[288,2311,2313],{"transform":2312},"translate(84.5,37.8) scale(1.000)",[292,2314],{"d":2315,"fill":295,"stroke":2316,"style":2317},"M11 4a7 7 0 1 0 .01 0z M16 16l5 5","var(--text,#172033)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[299,2319,2323],{"x":2320,"y":2321,"style":2322},"96.5","84.2","font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Needs fixing?",[299,2325,2327],{"x":2320,"y":2326,"style":1355},"103.8","all caps or all lower",[91,2329],{"x1":2330,"y1":2331,"x2":2332,"y2":2331,"stroke":1325,"style":286},"178.0","71.2","200.0",[2334,2335],"polygon",{"points":2336,"fill":2337},"204.0,71.2 195.0,76.2 195.0,66.2","#5b5cf0",[270,2339],{"x":2340,"y":280,"width":2307,"height":2308,"rx":2309,"fill":1324,"stroke":1325,"style":286},"209.0",[288,2342,2344],{"transform":2343},"translate(273.5,29.0) scale(1.000)",[292,2345],{"d":2346,"fill":295,"stroke":2347,"style":2317},"M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8z M4 21c0-4 3.6-7 8-7s8 3 8 7","var(--brand-strong,#4338ca)",[299,2349,2353],{"x":2350,"y":2351,"style":2352},"285.5","75.5","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Name rules",[299,2355,2357],{"x":2350,"y":2356,"style":1355},"95.0","O'Brien, McDonald,",[299,2359,2361],{"x":2350,"y":2360,"style":1355},"112.5","van, III",[91,2363],{"x1":2364,"y1":2331,"x2":329,"y2":2331,"stroke":1325,"style":286},"367.0",[2334,2366],{"points":2367,"fill":2337},"393.0,71.2 384.0,76.2 384.0,66.2",[270,2369],{"x":2370,"y":280,"width":2307,"height":2308,"rx":2309,"fill":330,"stroke":331,"style":286},"398.0",[288,2372,2374],{"transform":2373},"translate(462.5,37.8) scale(1.000)",[292,2375],{"d":2376,"fill":295,"stroke":338,"style":2317},"M3 5h18v14H3z M3 10h18 M3 15h18 M9 5v14",[299,2378,2381],{"x":2379,"y":2321,"style":2380},"474.5","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Company rules",[299,2383,2384],{"x":2379,"y":2326,"style":1355},"LLC, UK, GmbH, and",[91,2386],{"x1":2387,"y1":2331,"x2":2388,"y2":2331,"stroke":1325,"style":286},"556.0","578.0",[2334,2390],{"points":2391,"fill":2337},"582.0,71.2 573.0,76.2 573.0,66.2",[270,2393],{"x":2394,"y":280,"width":2307,"height":2308,"rx":2309,"fill":2395,"stroke":2396,"style":286},"587.0","#fdefd8","var(--gold,#b4740a)",[288,2398,2400],{"transform":2399},"translate(651.5,37.8) scale(1.000)",[292,2401],{"d":2402,"fill":295,"stroke":2403,"style":2317},"M2 12s4-7 10-7 10 7 10 7-4 7-10 7S2 12 2 12z M12 9a3 3 0 1 0 .01 0z","var(--gold-ink,#7a4e06)",[299,2405,2408],{"x":2406,"y":2321,"style":2407},"663.5","font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Review",[299,2410,2411],{"x":2406,"y":2326,"style":1355},"original + suggestion",[75,2413,2415],{"id":2414},"common-pitfalls","Common pitfalls",[2417,2418,2419,2429,2435,2441,2447],"ul",{},[2420,2421,2422,2428],"li",{},[2423,2424,2425,2427],"strong",{},[14,2426,32],{}," on everything."," It breaks Mc names, particles, suffixes and correctly cased names.",[2420,2430,2431,2434],{},[2423,2432,2433],{},"Recasing mixed-case names."," People know how their names are spelt; leave them alone.",[2420,2436,2437,2440],{},[2423,2438,2439],{},"Over-eager Mac rules."," Mack, Macy and many others are not Mac + name; keep an exception list.",[2420,2442,2443,2446],{},[2423,2444,2445],{},"Acronyms in company names."," Keep a list of words that stay upper case.",[2420,2448,2449,2452],{},[2423,2450,2451],{},"Overwriting without review."," Write suggestions beside the originals.",[75,2454,2456],{"id":2455},"conclusion","Conclusion",[10,2458,2459,2460,2462],{},"Correct name capitalisation needs rules that ",[14,2461,32],{}," lacks: capitals after apostrophes and hyphens, Mc and cautious Mac prefixes, lower-case particles between other words, upper-case generational suffixes, and for companies a list of acronyms and legal forms. Apply the rules only to values that are entirely upper or lower case — or per shouting word — so correctly written names are never damaged, and write the suggestions beside the originals with changed rows highlighted for a quick human review.",[75,2464,2466],{"id":2465},"frequently-asked-questions","Frequently asked questions",[10,2468,2469,2472],{},[2423,2470,2471],{},"Why does pandas str.title() give wrong names?","\nIt capitalises the first letter after every non-letter and lower-cases the rest, so it produces Mcdonald, Van for the Dutch particle and Iii for III, and it changes names that were already written correctly.",[10,2474,2475,2478],{},[2423,2476,2477],{},"How do I capitalise names like O'Brien and McDonald in Python?","\nLower-case the name, split each word on apostrophes and hyphens, capitalise each piece, and add rules for prefixes such as Mc followed by a capital letter.",[10,2480,2481,2484],{},[2423,2482,2483],{},"How do I avoid changing names that are already correct?","\nOnly recase values whose letters are all upper case or all lower case. Mixed-case names were probably typed deliberately.",[10,2486,2487,2490],{},[2423,2488,2489],{},"How do I keep acronyms like LLC and UK in capitals?","\nKeep a set of words that must stay upper case and check each word against it before applying the general rule.",[75,2492,2494],{"id":2493},"related","Related",[2417,2496,2497,2503,2510,2517],{},[2420,2498,2499,2500,2502],{},"Up one level: ",[69,2501,72],{"href":71}," — tidy data before analysis.",[2420,2504,2505,2509],{},[69,2506,2508],{"href":2507},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fsplit-full-names-into-first-and-last-names-with-pandas\u002F","Split Full Names into First and Last Names with pandas"," — the next step for many name columns.",[2420,2511,2512,2516],{},[69,2513,2515],{"href":2514},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fremove-accents-and-normalise-unicode-in-excel-text\u002F","Remove Accents and Normalise Unicode in Excel Text"," — accents and look-alike characters.",[2420,2518,2519,2523],{},[69,2520,2522],{"href":2521},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Ffind-near-duplicate-names-within-one-excel-column\u002F","Find Near-Duplicate Names Within One Excel Column"," — after case is fixed, duplicates show up.",[2525,2526,2527],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}",{"title":85,"searchDepth":142,"depth":142,"links":2529},[2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540],{"id":77,"depth":142,"text":78},{"id":115,"depth":142,"text":116},{"id":362,"depth":142,"text":363},{"id":536,"depth":142,"text":537},{"id":1429,"depth":142,"text":1430},{"id":1584,"depth":142,"text":1585},{"id":1945,"depth":142,"text":1946},{"id":2414,"depth":142,"text":2415},{"id":2455,"depth":142,"text":2456},{"id":2465,"depth":142,"text":2466},{"id":2493,"depth":142,"text":2494},"2026-10-02","Turn SHOUTED and lower-case names in an Excel list into proper names without the mistakes str.title makes: O'Brien instead of O'brien, McDonald, hyphenated surnames, particles such as van and de, generational suffixes like III, company suffixes and acronyms such as LLC and UK, leaving already mixed-case names alone, and a review list of everything that changed.","md",[2545,2547,2549,2551],{"q":2471,"a":2546},"It capitalises the first letter after every non-letter and lower-cases the rest, so it produces Mcdonald, Van for the Dutch particle and Iii for III, and it changes names that were already written correctly.",{"q":2477,"a":2548},"Lower-case the name, split each word on apostrophes and hyphens, capitalise each piece, and add rules for prefixes such as Mc followed by a capital letter.",{"q":2483,"a":2550},"Only recase values whose letters are all upper case or all lower case. Mixed-case names were probably typed deliberately.",{"q":2489,"a":2552},"Keep a set of words that must stay upper case and check each word against it before applying the general rule.","fix the capitalisation of names with exceptions in pandas",null,{"breadcrumb":2556},[2557,2560,2563],{"name":2558,"item":2559},"Home","\u002F",{"name":2561,"item":2562},"Advanced Data Transformation and Cleaning for Excel Automation","\u002Fadvanced-data-transformation-and-cleaning\u002F",{"name":2564,"item":71},"Cleaning Excel Data With Pandas: A Production Workflow","\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Ffix-the-capitalisation-of-names-with-exceptions-in-pandas",{"title":2567,"description":2568},"Fix Name Capitalisation with Exceptions in pandas","Proper-case names from Excel with rules str.title misses: apostrophes, Mc and Mac, hyphens, van\u002Fde\u002Fvon particles, II and III, LLC and other acronyms, only touching all-caps or all-lower values, and a review of changes.","fix-the-capitalisation-of-names-with-exceptions-in-pandas","advanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Ffix-the-capitalisation-of-names-with-exceptions-in-pandas\u002Findex",[2572,2573],"data-cleaning","pandas","how-to","IwNtfYLyvCpAguVa4eLI4hoGOtbbyx-sc8HagbG0hM8",[2577,2581],{"title":2578,"path":2579,"stem":2580,"children":-1},"Fix Garbled Characters Like \"CafÃ©\" and \"â€™\" in Excel Data","\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Ffix-garbled-characters-in-excel-data","advanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Ffix-garbled-characters-in-excel-data\u002Findex",{"title":2582,"path":2583,"stem":2584,"children":-1},"Keep the Latest Record per Key When Deduplicating with pandas","\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fkeep-the-latest-record-per-key-with-pandas","advanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fkeep-the-latest-record-per-key-with-pandas\u002Findex",[2586,2588],{"path":2587,"title":2564},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas",{"path":2589,"title":2561},"\u002Fadvanced-data-transformation-and-cleaning",[],[2592,2595,2598,2601,2604,2607],{"path":2593,"title":2594,"kind":2574},"\u002Fadvanced-data-transformation-and-cleaning\u002Fvalidating-excel-data-with-python\u002Ffind-duplicate-rows-in-excel-with-python","Find Duplicate Rows in Excel with Python",{"path":2596,"title":2597,"kind":2574},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-duplicate-values-in-excel-with-openpyxl","Highlight Duplicate Values in Excel with openpyxl",{"path":2599,"title":2600,"kind":2574},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fclean-mixed-currency-amounts-into-amount-and-currency-columns","Clean Mixed-Currency Amounts into Amount and Currency Columns",{"path":2602,"title":2603,"kind":2574},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fcoalesce-several-excel-columns-into-one-with-pandas","Coalesce Several Excel Columns into One with pandas",{"path":2605,"title":2606,"kind":2574},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fconvert-currency-strings-to-numbers-with-pandas","Convert Currency Strings Like \"$1,234.56\" and \"(500)\" to Numbers with pandas",{"path":2608,"title":2609,"kind":2574},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fconvert-excel-text-columns-to-numbers-with-pandas","Convert Excel Text Columns to Numbers with pandas",1790972080775]