[{"data":1,"prerenderedAt":1880},["ShallowReactive",2],{"doc:\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-country-names-and-codes-with-python":3,"surround:\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-country-names-and-codes-with-python":1846,"ancestors:\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-country-names-and-codes-with-python":1855,"children:\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-country-names-and-codes-with-python":1860,"related:\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-country-names-and-codes-with-python":1861},{"id":4,"title":5,"body":6,"dateModified":1812,"datePublished":1812,"description":1813,"extension":1814,"faq":1815,"keyword":1824,"kind":1825,"meta":1826,"navigation":111,"path":1836,"seo":1837,"slug":1840,"stem":1841,"topics":1842,"type":1844,"__hash__":1845},"docs\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-country-names-and-codes-with-python\u002Findex.md","Standardise Country Names and Codes with Python",{"type":7,"value":8,"toc":1800},"minimark",[9,24,29,60,66,70,76,321,341,345,348,731,741,891,895,902,1147,1158,1162,1165,1337,1351,1463,1537,1541,1544,1683,1686,1690,1725,1729,1735,1739,1745,1751,1757,1763,1767,1796],[10,11,12,13,17,18,23],"p",{},"A country column typed by people never has one spelling per country. Sales by country comes out with separate rows for \"Germany\", \"germany\", \"DE\", \"Deutschland\" and \"Federal Republic of Germany\"; the UK appears as \"UK\", \"U.K.\", \"United Kingdom\", \"Great Britain\" and \"England\"; the Netherlands as \"Netherlands\" and \"Holland\". A mapping table maintained by hand never quite keeps up. The ",[14,15,16],"code",{},"pycountry"," package contains the ISO 3166 list of countries with their official names and two- and three-letter codes, so most values can be resolved by lookup, and a small override table handles the rest — nicknames, names in other languages, and countries whose official name has changed. This page builds that standardiser, uses fuzzy matching only where it is safe, and reports every value it could not resolve with confidence. It belongs to ",[19,20,22],"a",{"href":21},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002F","Cleaning Excel Data with pandas",".",[25,26,28],"h2",{"id":27},"prerequisites","Prerequisites",[30,31,36],"pre",{"className":32,"code":33,"language":34,"meta":35,"style":35},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl pycountry\n","bash","",[14,37,38],{"__ignoreMap":35},[39,40,43,47,51,54,57],"span",{"class":41,"line":42},"line",1,[39,44,46],{"class":45},"sMTad","pip",[39,48,50],{"class":49},"srMev"," install",[39,52,53],{"class":49}," pandas",[39,55,56],{"class":49}," openpyxl",[39,58,59],{"class":49}," pycountry\n",[10,61,62,65],{},[14,63,64],{},"orders_by_country.xlsx"," has 25 orders whose country was typed freehand: official names, codes, nicknames, native-language names, a renamed country, abbreviations with dots, an ambiguous \"Korea\", a typo and a placeholder. The examples were run with pycountry 26.2.",[25,67,69],{"id":68},"step-1-exact-lookups-first","Step 1 — Exact lookups first",[10,71,72,75],{},[14,73,74],{},"pycountry.countries.lookup"," matches a value exactly — case-insensitively — against official names, common names and the alpha-2 and alpha-3 codes:",[30,77,81],{"className":78,"code":79,"language":80,"meta":35,"style":35},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\nimport pycountry\n\ndf = pd.read_excel(\"orders_by_country.xlsx\", keep_default_na=False)\ndf[\"clean\"] = df[\"Country\"].astype(str).str.strip()\n\ndef exact(value):\n    try:\n        c = pycountry.countries.lookup(value)\n        return c.alpha_2\n    except LookupError:\n        return None\n\ndf[\"iso2\"] = df[\"clean\"].map(exact)\nprint(df[[\"Country\", \"iso2\"]].to_string(index=False))\nprint(\"resolved exactly:\", df[\"iso2\"].notna().sum(), \"of\", len(df))\n","python",[14,82,83,99,106,113,144,173,178,191,200,211,220,231,239,244,263,291],{"__ignoreMap":35},[39,84,85,89,93,96],{"class":41,"line":42},[39,86,88],{"class":87},"s-kum","import",[39,90,92],{"class":91},"skGVy"," pandas ",[39,94,95],{"class":87},"as",[39,97,98],{"class":91}," pd\n",[39,100,102,104],{"class":41,"line":101},2,[39,103,88],{"class":87},[39,105,59],{"class":91},[39,107,109],{"class":41,"line":108},3,[39,110,112],{"emptyLinePlaceholder":111},true,"\n",[39,114,116,119,122,125,128,131,135,137,141],{"class":41,"line":115},4,[39,117,118],{"class":91},"df ",[39,120,121],{"class":87},"=",[39,123,124],{"class":91}," pd.read_excel(",[39,126,127],{"class":49},"\"orders_by_country.xlsx\"",[39,129,130],{"class":91},", ",[39,132,134],{"class":133},"sa561","keep_default_na",[39,136,121],{"class":87},[39,138,140],{"class":139},"sP0c6","False",[39,142,143],{"class":91},")\n",[39,145,147,150,153,156,158,161,164,167,170],{"class":41,"line":146},5,[39,148,149],{"class":91},"df[",[39,151,152],{"class":49},"\"clean\"",[39,154,155],{"class":91},"] ",[39,157,121],{"class":87},[39,159,160],{"class":91}," df[",[39,162,163],{"class":49},"\"Country\"",[39,165,166],{"class":91},"].astype(",[39,168,169],{"class":139},"str",[39,171,172],{"class":91},").str.strip()\n",[39,174,176],{"class":41,"line":175},6,[39,177,112],{"emptyLinePlaceholder":111},[39,179,181,184,188],{"class":41,"line":180},7,[39,182,183],{"class":87},"def",[39,185,187],{"class":186},"s_Opv"," exact",[39,189,190],{"class":91},"(value):\n",[39,192,194,197],{"class":41,"line":193},8,[39,195,196],{"class":87},"    try",[39,198,199],{"class":91},":\n",[39,201,203,206,208],{"class":41,"line":202},9,[39,204,205],{"class":91},"        c ",[39,207,121],{"class":87},[39,209,210],{"class":91}," pycountry.countries.lookup(value)\n",[39,212,214,217],{"class":41,"line":213},10,[39,215,216],{"class":87},"        return",[39,218,219],{"class":91}," c.alpha_2\n",[39,221,223,226,229],{"class":41,"line":222},11,[39,224,225],{"class":87},"    except",[39,227,228],{"class":139}," LookupError",[39,230,199],{"class":91},[39,232,234,236],{"class":41,"line":233},12,[39,235,216],{"class":87},[39,237,238],{"class":139}," None\n",[39,240,242],{"class":41,"line":241},13,[39,243,112],{"emptyLinePlaceholder":111},[39,245,247,249,252,254,256,258,260],{"class":41,"line":246},14,[39,248,149],{"class":91},[39,250,251],{"class":49},"\"iso2\"",[39,253,155],{"class":91},[39,255,121],{"class":87},[39,257,160],{"class":91},[39,259,152],{"class":49},[39,261,262],{"class":91},"].map(exact)\n",[39,264,266,269,272,274,276,278,281,284,286,288],{"class":41,"line":265},15,[39,267,268],{"class":139},"print",[39,270,271],{"class":91},"(df[[",[39,273,163],{"class":49},[39,275,130],{"class":91},[39,277,251],{"class":49},[39,279,280],{"class":91},"]].to_string(",[39,282,283],{"class":133},"index",[39,285,121],{"class":87},[39,287,140],{"class":139},[39,289,290],{"class":91},"))\n",[39,292,294,296,299,302,305,307,310,313,315,318],{"class":41,"line":293},16,[39,295,268],{"class":139},[39,297,298],{"class":91},"(",[39,300,301],{"class":49},"\"resolved exactly:\"",[39,303,304],{"class":91},", df[",[39,306,251],{"class":49},[39,308,309],{"class":91},"].notna().sum(), ",[39,311,312],{"class":49},"\"of\"",[39,314,130],{"class":91},[39,316,317],{"class":139},"len",[39,319,320],{"class":91},"(df))\n",[10,322,323,324,328,329,332,333,336,337,340],{},"Exact lookup resolves 11 of the 25 values — \"Germany\", \"germany\", \"DE\", \"DEU\", \"United Kingdom\", \"USA\", \"United States of America\", \"Netherlands\", \"Türkiye\", \"Czech Republic\" and \"france\" — the Czech one because pycountry also stores former names that are still widely used. It deliberately does ",[325,326,327],"em",{},"not"," guess: \"UK\", \"U.K.\", \"Holland\", \"Deutschland\", \"Espana\" and \"Turkey\" are not ISO names or codes, so they stay unresolved. \"UK\" in particular is not the ISO code for the United Kingdom, which is GB — a frequent source of confusion. Stripping spaces first lets ",[14,330,331],{},"\"  france \""," match. ",[14,334,335],{},"keep_default_na=False"," matters here: by default ",[14,338,339],{},"read_excel"," turns placeholder text such as \"n\u002Fa\" into a missing value, and \"NA\" — Namibia's ISO code — would disappear the same way. Reading the column exactly as typed keeps every value visible, so the placeholder can be reported rather than silently dropped.",[25,342,344],{"id":343},"step-2-an-override-table-for-what-iso-does-not-cover","Step 2 — An override table for what ISO does not cover",[10,346,347],{},"The values exact lookup misses are predictable: nicknames, parts of a country, native-language names, renamed countries and punctuation. Keep them in one override table, mapped to the ISO alpha-2 code:",[30,349,351],{"className":78,"code":350,"language":80,"meta":35,"style":35},"OVERRIDES = {\n    \"uk\": \"GB\", \"u.k.\": \"GB\", \"great britain\": \"GB\", \"england\": \"GB\", \"scotland\": \"GB\", \"wales\": \"GB\",\n    \"u.s.a.\": \"US\", \"u.s.\": \"US\", \"united states of america\": \"US\", \"america\": \"US\",\n    \"holland\": \"NL\", \"the netherlands\": \"NL\",\n    \"deutschland\": \"DE\", \"espana\": \"ES\", \"españa\": \"ES\",\n    \"turkey\": \"TR\", \"ivory coast\": \"CI\",\n}\n\ndef resolve(value):\n    key = value.strip().lower()\n    if key in OVERRIDES:\n        return OVERRIDES[key], \"override\"\n    code = exact(value)\n    return (code, \"exact\") if code else (None, None)\n\ndf[[\"iso2\", \"how\"]] = df[\"clean\"].apply(lambda v: pd.Series(resolve(v)))\nprint(df.loc[df[\"how\"] == \"override\", [\"Country\", \"iso2\"]].to_string(index=False))\nprint(\"unresolved:\", df.loc[df[\"iso2\"].isna(), \"Country\"].tolist())\n",[14,352,353,364,423,462,483,514,536,541,545,554,564,580,592,602,637,641,671,708],{"__ignoreMap":35},[39,354,355,358,361],{"class":41,"line":42},[39,356,357],{"class":139},"OVERRIDES",[39,359,360],{"class":87}," =",[39,362,363],{"class":91}," {\n",[39,365,366,369,372,375,377,380,382,384,386,389,391,393,395,398,400,402,404,407,409,411,413,416,418,420],{"class":41,"line":101},[39,367,368],{"class":49},"    \"uk\"",[39,370,371],{"class":91},": ",[39,373,374],{"class":49},"\"GB\"",[39,376,130],{"class":91},[39,378,379],{"class":49},"\"u.k.\"",[39,381,371],{"class":91},[39,383,374],{"class":49},[39,385,130],{"class":91},[39,387,388],{"class":49},"\"great britain\"",[39,390,371],{"class":91},[39,392,374],{"class":49},[39,394,130],{"class":91},[39,396,397],{"class":49},"\"england\"",[39,399,371],{"class":91},[39,401,374],{"class":49},[39,403,130],{"class":91},[39,405,406],{"class":49},"\"scotland\"",[39,408,371],{"class":91},[39,410,374],{"class":49},[39,412,130],{"class":91},[39,414,415],{"class":49},"\"wales\"",[39,417,371],{"class":91},[39,419,374],{"class":49},[39,421,422],{"class":91},",\n",[39,424,425,428,430,433,435,438,440,442,444,447,449,451,453,456,458,460],{"class":41,"line":108},[39,426,427],{"class":49},"    \"u.s.a.\"",[39,429,371],{"class":91},[39,431,432],{"class":49},"\"US\"",[39,434,130],{"class":91},[39,436,437],{"class":49},"\"u.s.\"",[39,439,371],{"class":91},[39,441,432],{"class":49},[39,443,130],{"class":91},[39,445,446],{"class":49},"\"united states of america\"",[39,448,371],{"class":91},[39,450,432],{"class":49},[39,452,130],{"class":91},[39,454,455],{"class":49},"\"america\"",[39,457,371],{"class":91},[39,459,432],{"class":49},[39,461,422],{"class":91},[39,463,464,467,469,472,474,477,479,481],{"class":41,"line":115},[39,465,466],{"class":49},"    \"holland\"",[39,468,371],{"class":91},[39,470,471],{"class":49},"\"NL\"",[39,473,130],{"class":91},[39,475,476],{"class":49},"\"the netherlands\"",[39,478,371],{"class":91},[39,480,471],{"class":49},[39,482,422],{"class":91},[39,484,485,488,490,493,495,498,500,503,505,508,510,512],{"class":41,"line":146},[39,486,487],{"class":49},"    \"deutschland\"",[39,489,371],{"class":91},[39,491,492],{"class":49},"\"DE\"",[39,494,130],{"class":91},[39,496,497],{"class":49},"\"espana\"",[39,499,371],{"class":91},[39,501,502],{"class":49},"\"ES\"",[39,504,130],{"class":91},[39,506,507],{"class":49},"\"españa\"",[39,509,371],{"class":91},[39,511,502],{"class":49},[39,513,422],{"class":91},[39,515,516,519,521,524,526,529,531,534],{"class":41,"line":175},[39,517,518],{"class":49},"    \"turkey\"",[39,520,371],{"class":91},[39,522,523],{"class":49},"\"TR\"",[39,525,130],{"class":91},[39,527,528],{"class":49},"\"ivory coast\"",[39,530,371],{"class":91},[39,532,533],{"class":49},"\"CI\"",[39,535,422],{"class":91},[39,537,538],{"class":41,"line":180},[39,539,540],{"class":91},"}\n",[39,542,543],{"class":41,"line":193},[39,544,112],{"emptyLinePlaceholder":111},[39,546,547,549,552],{"class":41,"line":202},[39,548,183],{"class":87},[39,550,551],{"class":186}," resolve",[39,553,190],{"class":91},[39,555,556,559,561],{"class":41,"line":213},[39,557,558],{"class":91},"    key ",[39,560,121],{"class":87},[39,562,563],{"class":91}," value.strip().lower()\n",[39,565,566,569,572,575,578],{"class":41,"line":222},[39,567,568],{"class":87},"    if",[39,570,571],{"class":91}," key ",[39,573,574],{"class":87},"in",[39,576,577],{"class":139}," OVERRIDES",[39,579,199],{"class":91},[39,581,582,584,586,589],{"class":41,"line":233},[39,583,216],{"class":87},[39,585,577],{"class":139},[39,587,588],{"class":91},"[key], ",[39,590,591],{"class":49},"\"override\"\n",[39,593,594,597,599],{"class":41,"line":241},[39,595,596],{"class":91},"    code ",[39,598,121],{"class":87},[39,600,601],{"class":91}," exact(value)\n",[39,603,604,607,610,613,616,619,622,625,628,631,633,635],{"class":41,"line":246},[39,605,606],{"class":87},"    return",[39,608,609],{"class":91}," (code, ",[39,611,612],{"class":49},"\"exact\"",[39,614,615],{"class":91},") ",[39,617,618],{"class":87},"if",[39,620,621],{"class":91}," code ",[39,623,624],{"class":87},"else",[39,626,627],{"class":91}," (",[39,629,630],{"class":139},"None",[39,632,130],{"class":91},[39,634,630],{"class":139},[39,636,143],{"class":91},[39,638,639],{"class":41,"line":265},[39,640,112],{"emptyLinePlaceholder":111},[39,642,643,646,648,650,653,656,658,660,662,665,668],{"class":41,"line":293},[39,644,645],{"class":91},"df[[",[39,647,251],{"class":49},[39,649,130],{"class":91},[39,651,652],{"class":49},"\"how\"",[39,654,655],{"class":91},"]] ",[39,657,121],{"class":87},[39,659,160],{"class":91},[39,661,152],{"class":49},[39,663,664],{"class":91},"].apply(",[39,666,667],{"class":87},"lambda",[39,669,670],{"class":91}," v: pd.Series(resolve(v)))\n",[39,672,674,676,679,681,683,686,689,692,694,696,698,700,702,704,706],{"class":41,"line":673},17,[39,675,268],{"class":139},[39,677,678],{"class":91},"(df.loc[df[",[39,680,652],{"class":49},[39,682,155],{"class":91},[39,684,685],{"class":87},"==",[39,687,688],{"class":49}," \"override\"",[39,690,691],{"class":91},", [",[39,693,163],{"class":49},[39,695,130],{"class":91},[39,697,251],{"class":49},[39,699,280],{"class":91},[39,701,283],{"class":133},[39,703,121],{"class":87},[39,705,140],{"class":139},[39,707,290],{"class":91},[39,709,711,713,715,718,721,723,726,728],{"class":41,"line":710},18,[39,712,268],{"class":139},[39,714,298],{"class":91},[39,716,717],{"class":49},"\"unresolved:\"",[39,719,720],{"class":91},", df.loc[df[",[39,722,251],{"class":49},[39,724,725],{"class":91},"].isna(), ",[39,727,163],{"class":49},[39,729,730],{"class":91},"].tolist())\n",[10,732,733,734,130,737,740],{},"The overrides are checked before the ISO lookup, so they can also correct values that ISO would interpret differently. England, Scotland and Wales map to GB because ISO 3166 has no separate entries for them; if your business needs the distinction, use ISO 3166-2 subdivision codes (",[14,735,736],{},"GB-ENG",[14,738,739],{},"GB-SCT",") in a separate column instead. \"Turkey\" maps to TR because the country's ISO name changed to Türkiye in 2022, and older systems keep sending the former name. This table is the part of the code that grows: every new spelling reported in Step 4 gets one line here.",[742,743,751,752,751,756,751,760,751,768,751,778,751,789,751,796,751,801,751,807,751,812,751,816,751,823,751,828,751,831,751,835,751,838,751,843,751,850,751,856,751,860,751,864,751,868,751,871,751,876,751,883,751,888],"svg",{"viewBox":744,"role":745,"ariaLabelledBy":746,"xmlns":749,"style":750},"4 0 752 142","img",[747,748],"cc-order-t","cc-order-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  ",[753,754,755],"title",{"id":747},"How each country value is resolved",[757,758,759],"desc",{"id":748},"A value is cleaned and lower-cased, checked against the override table, then looked up exactly in ISO 3166 by name or code, and only then offered to fuzzy search, whose suggestions are accepted only when there is a single clear candidate. Anything else is reported.",[761,762],"rect",{"x":763,"y":764,"width":765,"height":766,"fill":767},"4","0","752","142","#ffffff",[761,769],{"x":770,"y":771,"width":772,"height":773,"rx":774,"fill":775,"stroke":776,"style":777},"20.0","16.0","153.0","110.5","12","#e7ebef","var(--line,#cdd5e6)","stroke-width:2px",[779,780,782],"g",{"transform":781},"translate(84.5,37.8) scale(1.000)",[783,784],"path",{"d":785,"fill":786,"stroke":787,"style":788},"M20 11a8 8 0 1 0-2.3 5.7 M20 4v7h-7","none","var(--text,#172033)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[790,791,795],"text",{"x":792,"y":793,"style":794},"96.5","84.2","font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Clean",[790,797,800],{"x":792,"y":798,"style":799},"103.8","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","strip, lower-case",[41,802],{"x1":803,"y1":804,"x2":805,"y2":804,"stroke":806,"style":777},"178.0","71.2","200.0","var(--brand,#5b5cf0)",[808,809],"polygon",{"points":810,"fill":811},"204.0,71.2 195.0,76.2 195.0,66.2","#5b5cf0",[761,813],{"x":814,"y":771,"width":772,"height":773,"rx":774,"fill":815,"stroke":806,"style":777},"209.0","#f0f4ff",[779,817,819],{"transform":818},"translate(273.5,37.8) scale(1.000)",[783,820],{"d":821,"fill":786,"stroke":822,"style":788},"M3 5h18v14H3z M3 10h18 M3 15h18 M9 5v14","var(--brand-strong,#4338ca)",[790,824,827],{"x":825,"y":793,"style":826},"285.5","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Overrides",[790,829,830],{"x":825,"y":798,"style":799},"UK, Holland, Turkey …",[41,832],{"x1":833,"y1":804,"x2":834,"y2":804,"stroke":806,"style":777},"367.0","389.0",[808,836],{"points":837,"fill":811},"393.0,71.2 384.0,76.2 384.0,66.2",[761,839],{"x":840,"y":771,"width":772,"height":773,"rx":774,"fill":841,"stroke":842,"style":777},"398.0","#d9f4f1","var(--teal,#0f9488)",[779,844,846],{"transform":845},"translate(462.5,29.0) scale(1.000)",[783,847],{"d":848,"fill":786,"stroke":849,"style":788},"M11 4a7 7 0 1 0 .01 0z M16 16l5 5","var(--teal-ink,#0b6157)",[790,851,855],{"x":852,"y":853,"style":854},"474.5","75.5","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","ISO lookup",[790,857,859],{"x":852,"y":858,"style":799},"95.0","name, alpha-2,",[790,861,863],{"x":852,"y":862,"style":799},"112.5","alpha-3",[41,865],{"x1":866,"y1":804,"x2":867,"y2":804,"stroke":806,"style":777},"556.0","578.0",[808,869],{"points":870,"fill":811},"582.0,71.2 573.0,76.2 573.0,66.2",[761,872],{"x":873,"y":771,"width":772,"height":773,"rx":774,"fill":874,"stroke":875,"style":777},"587.0","#fdefd8","var(--gold,#b4740a)",[779,877,879],{"transform":878},"translate(651.5,37.8) scale(1.000)",[783,880],{"d":881,"fill":786,"stroke":882,"style":788},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","var(--gold-ink,#7a4e06)",[790,884,887],{"x":885,"y":793,"style":886},"663.5","font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Fuzzy or report",[790,889,890],{"x":885,"y":798,"style":799},"one clear match only",[25,892,894],{"id":893},"step-3-fuzzy-search-used-cautiously","Step 3 — Fuzzy search, used cautiously",[10,896,897,898,901],{},"What remains are typos and genuinely ambiguous values. ",[14,899,900],{},"search_fuzzy"," returns candidates ranked by similarity; accept a suggestion only when there is exactly one candidate, and report the rest:",[30,903,905],{"className":78,"code":904,"language":80,"meta":35,"style":35},"def fuzzy(value):\n    try:\n        matches = pycountry.countries.search_fuzzy(value)\n    except LookupError:\n        return None, \"unmatched\", []\n    codes = [m.alpha_2 for m in matches]\n    return (codes[0], \"fuzzy\", codes) if len(codes) == 1 else (None, \"ambiguous\", codes[:4])\n\nrest = df[\"iso2\"].isna()\nfor i in df.index[rest]:\n    code, how, candidates = fuzzy(df.at[i, \"clean\"])\n    df.at[i, \"iso2\"], df.at[i, \"how\"] = code, how\n    print(f\"{df.at[i, 'Country']!r:12} → {how:9} {candidates}\")\n",[14,906,907,916,922,932,940,955,976,1027,1031,1045,1057,1071,1090],{"__ignoreMap":35},[39,908,909,911,914],{"class":41,"line":42},[39,910,183],{"class":87},[39,912,913],{"class":186}," fuzzy",[39,915,190],{"class":91},[39,917,918,920],{"class":41,"line":101},[39,919,196],{"class":87},[39,921,199],{"class":91},[39,923,924,927,929],{"class":41,"line":108},[39,925,926],{"class":91},"        matches ",[39,928,121],{"class":87},[39,930,931],{"class":91}," pycountry.countries.search_fuzzy(value)\n",[39,933,934,936,938],{"class":41,"line":115},[39,935,225],{"class":87},[39,937,228],{"class":139},[39,939,199],{"class":91},[39,941,942,944,947,949,952],{"class":41,"line":146},[39,943,216],{"class":87},[39,945,946],{"class":139}," None",[39,948,130],{"class":91},[39,950,951],{"class":49},"\"unmatched\"",[39,953,954],{"class":91},", []\n",[39,956,957,960,962,965,968,971,973],{"class":41,"line":175},[39,958,959],{"class":91},"    codes ",[39,961,121],{"class":87},[39,963,964],{"class":91}," [m.alpha_2 ",[39,966,967],{"class":87},"for",[39,969,970],{"class":91}," m ",[39,972,574],{"class":87},[39,974,975],{"class":91}," matches]\n",[39,977,978,980,983,985,988,991,994,996,999,1002,1004,1007,1010,1012,1014,1016,1019,1022,1024],{"class":41,"line":180},[39,979,606],{"class":87},[39,981,982],{"class":91}," (codes[",[39,984,764],{"class":139},[39,986,987],{"class":91},"], ",[39,989,990],{"class":49},"\"fuzzy\"",[39,992,993],{"class":91},", codes) ",[39,995,618],{"class":87},[39,997,998],{"class":139}," len",[39,1000,1001],{"class":91},"(codes) ",[39,1003,685],{"class":87},[39,1005,1006],{"class":139}," 1",[39,1008,1009],{"class":87}," else",[39,1011,627],{"class":91},[39,1013,630],{"class":139},[39,1015,130],{"class":91},[39,1017,1018],{"class":49},"\"ambiguous\"",[39,1020,1021],{"class":91},", codes[:",[39,1023,763],{"class":139},[39,1025,1026],{"class":91},"])\n",[39,1028,1029],{"class":41,"line":193},[39,1030,112],{"emptyLinePlaceholder":111},[39,1032,1033,1036,1038,1040,1042],{"class":41,"line":202},[39,1034,1035],{"class":91},"rest ",[39,1037,121],{"class":87},[39,1039,160],{"class":91},[39,1041,251],{"class":49},[39,1043,1044],{"class":91},"].isna()\n",[39,1046,1047,1049,1052,1054],{"class":41,"line":213},[39,1048,967],{"class":87},[39,1050,1051],{"class":91}," i ",[39,1053,574],{"class":87},[39,1055,1056],{"class":91}," df.index[rest]:\n",[39,1058,1059,1062,1064,1067,1069],{"class":41,"line":222},[39,1060,1061],{"class":91},"    code, how, candidates ",[39,1063,121],{"class":87},[39,1065,1066],{"class":91}," fuzzy(df.at[i, ",[39,1068,152],{"class":49},[39,1070,1026],{"class":91},[39,1072,1073,1076,1078,1081,1083,1085,1087],{"class":41,"line":233},[39,1074,1075],{"class":91},"    df.at[i, ",[39,1077,251],{"class":49},[39,1079,1080],{"class":91},"], df.at[i, ",[39,1082,652],{"class":49},[39,1084,155],{"class":91},[39,1086,121],{"class":87},[39,1088,1089],{"class":91}," code, how\n",[39,1091,1092,1095,1097,1100,1103,1107,1110,1113,1116,1119,1122,1125,1127,1130,1133,1135,1138,1141,1143,1145],{"class":41,"line":241},[39,1093,1094],{"class":139},"    print",[39,1096,298],{"class":91},[39,1098,1099],{"class":87},"f",[39,1101,1102],{"class":49},"\"",[39,1104,1106],{"class":1105},"sSjpA","{",[39,1108,1109],{"class":91},"df.at[i, ",[39,1111,1112],{"class":49},"'Country'",[39,1114,1115],{"class":91},"]",[39,1117,1118],{"class":87},"!r:12",[39,1120,1121],{"class":1105},"}",[39,1123,1124],{"class":49}," → ",[39,1126,1106],{"class":1105},[39,1128,1129],{"class":91},"how",[39,1131,1132],{"class":87},":9",[39,1134,1121],{"class":1105},[39,1136,1137],{"class":1105}," {",[39,1139,1140],{"class":91},"candidates",[39,1142,1121],{"class":1105},[39,1144,1102],{"class":49},[39,1146,143],{"class":91},[10,1148,1149,1150,1154,1155,1157],{},"The typo \"Frnace\" has no fuzzy match at all — pycountry's fuzzy search matches words and subdivision names rather than misspellings — so it is reported as unmatched. \"Korea\" returns two candidates, North and South Korea, and is reported as ambiguous instead of being silently assigned to the first. \"n\u002Fa\" is unmatched, as it should be. This conservative policy is deliberate: a wrong country is worse than a blank one, because it puts revenue in the wrong place without anyone noticing. For typos, a string-similarity match against the list of country names, as in ",[19,1151,1153],{"href":1152},"\u002Fadvanced-data-transformation-and-cleaning\u002Fmerging-and-joining-excel-dataframes\u002Ffuzzy-match-names-between-two-excel-files-with-python\u002F","Fuzzy Match Names Between Two Excel Files with Python",", works better than ",[14,1156,900],{}," — and its suggestions should still go to a person for confirmation.",[25,1159,1161],{"id":1160},"step-4-add-official-names-and-report-the-leftovers","Step 4 — Add official names and report the leftovers",[10,1163,1164],{},"With codes resolved, add the official name and three-letter code for every row, and write the values that need attention to a review list:",[30,1166,1168],{"className":78,"code":1167,"language":80,"meta":35,"style":35},"def details(code):\n    c = pycountry.countries.get(alpha_2=code) if isinstance(code, str) else None\n    return (c.alpha_3, getattr(c, \"common_name\", c.name)) if c else (None, None)\n\ndf[[\"iso3\", \"country_name\"]] = df[\"iso2\"].apply(lambda c: pd.Series(details(c)))\nreview = df.loc[df[\"iso2\"].isna(), [\"Order\", \"Country\", \"how\"]]\nprint(review.to_string(index=False))\nprint(df[\"how\"].value_counts().to_dict())\n",[14,1169,1170,1180,1214,1250,1254,1281,1310,1325],{"__ignoreMap":35},[39,1171,1172,1174,1177],{"class":41,"line":42},[39,1173,183],{"class":87},[39,1175,1176],{"class":186}," details",[39,1178,1179],{"class":91},"(code):\n",[39,1181,1182,1185,1187,1190,1193,1195,1198,1200,1203,1206,1208,1210,1212],{"class":41,"line":101},[39,1183,1184],{"class":91},"    c ",[39,1186,121],{"class":87},[39,1188,1189],{"class":91}," pycountry.countries.get(",[39,1191,1192],{"class":133},"alpha_2",[39,1194,121],{"class":87},[39,1196,1197],{"class":91},"code) ",[39,1199,618],{"class":87},[39,1201,1202],{"class":139}," isinstance",[39,1204,1205],{"class":91},"(code, ",[39,1207,169],{"class":139},[39,1209,615],{"class":91},[39,1211,624],{"class":87},[39,1213,238],{"class":139},[39,1215,1216,1218,1221,1224,1227,1230,1233,1235,1238,1240,1242,1244,1246,1248],{"class":41,"line":108},[39,1217,606],{"class":87},[39,1219,1220],{"class":91}," (c.alpha_3, ",[39,1222,1223],{"class":139},"getattr",[39,1225,1226],{"class":91},"(c, ",[39,1228,1229],{"class":49},"\"common_name\"",[39,1231,1232],{"class":91},", c.name)) ",[39,1234,618],{"class":87},[39,1236,1237],{"class":91}," c ",[39,1239,624],{"class":87},[39,1241,627],{"class":91},[39,1243,630],{"class":139},[39,1245,130],{"class":91},[39,1247,630],{"class":139},[39,1249,143],{"class":91},[39,1251,1252],{"class":41,"line":115},[39,1253,112],{"emptyLinePlaceholder":111},[39,1255,1256,1258,1261,1263,1266,1268,1270,1272,1274,1276,1278],{"class":41,"line":146},[39,1257,645],{"class":91},[39,1259,1260],{"class":49},"\"iso3\"",[39,1262,130],{"class":91},[39,1264,1265],{"class":49},"\"country_name\"",[39,1267,655],{"class":91},[39,1269,121],{"class":87},[39,1271,160],{"class":91},[39,1273,251],{"class":49},[39,1275,664],{"class":91},[39,1277,667],{"class":87},[39,1279,1280],{"class":91}," c: pd.Series(details(c)))\n",[39,1282,1283,1286,1288,1291,1293,1296,1299,1301,1303,1305,1307],{"class":41,"line":175},[39,1284,1285],{"class":91},"review ",[39,1287,121],{"class":87},[39,1289,1290],{"class":91}," df.loc[df[",[39,1292,251],{"class":49},[39,1294,1295],{"class":91},"].isna(), [",[39,1297,1298],{"class":49},"\"Order\"",[39,1300,130],{"class":91},[39,1302,163],{"class":49},[39,1304,130],{"class":91},[39,1306,652],{"class":49},[39,1308,1309],{"class":91},"]]\n",[39,1311,1312,1314,1317,1319,1321,1323],{"class":41,"line":180},[39,1313,268],{"class":139},[39,1315,1316],{"class":91},"(review.to_string(",[39,1318,283],{"class":133},[39,1320,121],{"class":87},[39,1322,140],{"class":139},[39,1324,290],{"class":91},[39,1326,1327,1329,1332,1334],{"class":41,"line":193},[39,1328,268],{"class":139},[39,1330,1331],{"class":91},"(df[",[39,1333,652],{"class":49},[39,1335,1336],{"class":91},"].value_counts().to_dict())\n",[10,1338,1339,1340,1343,1344,1347,1348,1350],{},"Unresolved rows hold a missing value rather than a code, which is why the helper checks for a string before looking it up. Each resolved row now carries the ISO alpha-2 code, the alpha-3 code and a single display name — pycountry's ",[14,1341,1342],{},"common_name"," where one exists (\"Bolivia\" rather than \"Bolivia, Plurinational State of\"), otherwise the official ",[14,1345,1346],{},"name",". The review list holds three rows: the typo, the ambiguous \"Korea\" and the placeholder. Once someone decides that \"Frnace\" is France, the fix is a line in the override table, so the same typo is handled automatically next month. The ",[14,1349,1129],{}," column records whether each value was resolved by override, exact lookup or fuzzy match, which is useful evidence if a figure is questioned.",[742,1352,751,1357,751,1360,751,1363,751,1366,751,1371,751,1376,751,1382,751,1385,751,1389,751,1393,751,1399,751,1401,751,1405,751,1407,751,1410,751,1413,751,1417,751,1419,751,1423,751,1425,751,1427,751,1430,751,1434,751,1436,751,1440,751,1442,751,1445,751,1448,751,1452,751,1454,751,1458,751,1460],{"viewBox":1353,"role":745,"ariaLabelledBy":1354,"xmlns":749,"style":750},"4 0 752 208",[1355,1356],"cc-results-t","cc-results-d",[753,1358,1359],{"id":1355},"How the 25 values were resolved",[757,1361,1362],{"id":1356},"Official names and codes resolve by exact ISO lookup. Nicknames, native names and the former name Turkey resolve through the override table. The typo Frnace and the placeholder n\u002Fa are unmatched, and Korea is ambiguous between North and South Korea.",[761,1364],{"x":763,"y":764,"width":765,"height":1365,"fill":767},"208",[761,1367],{"x":770,"y":771,"width":1368,"height":1369,"rx":764,"fill":767,"stroke":776,"style":1370},"135.9","40.0","stroke-width:1px",[761,1372],{"x":1373,"y":771,"width":1374,"height":1369,"rx":764,"fill":815,"stroke":806,"style":1375},"155.9","292.0","stroke-width:1.2px",[790,1377,1381],{"x":1378,"y":1379,"style":1380},"301.9","41.0","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","examples",[761,1383],{"x":1384,"y":771,"width":1374,"height":1369,"rx":764,"fill":815,"stroke":806,"style":1375},"448.0",[790,1386,1388],{"x":1387,"y":1379,"style":1380},"594.0","result",[761,1390],{"x":770,"y":1391,"width":1368,"height":1392,"rx":764,"fill":775,"stroke":776,"style":1370},"56.0","34.0",[790,1394,1398],{"x":1395,"y":1396,"style":1397},"32.0","78.0","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:start","exact ISO lookup",[761,1400],{"x":1373,"y":1391,"width":1374,"height":1392,"rx":764,"fill":767,"stroke":776,"style":1370},[790,1402,1404],{"x":1378,"y":1403,"style":799},"77.0","Germany, DE, DEU, USA, Türkiye",[761,1406],{"x":1384,"y":1391,"width":1374,"height":1392,"rx":764,"fill":767,"stroke":776,"style":1370},[790,1408,1409],{"x":1387,"y":1403,"style":799},"resolved",[761,1411],{"x":770,"y":1412,"width":1368,"height":1392,"rx":764,"fill":775,"stroke":776,"style":1370},"90.0",[790,1414,1416],{"x":1395,"y":1415,"style":1397},"112.0","override table",[761,1418],{"x":1373,"y":1412,"width":1374,"height":1392,"rx":764,"fill":767,"stroke":776,"style":1370},[790,1420,1422],{"x":1378,"y":1421,"style":799},"111.0","UK, Holland, Deutschland, Turkey",[761,1424],{"x":1384,"y":1412,"width":1374,"height":1392,"rx":764,"fill":767,"stroke":776,"style":1370},[790,1426,1409],{"x":1387,"y":1421,"style":799},[761,1428],{"x":770,"y":1429,"width":1368,"height":1392,"rx":764,"fill":775,"stroke":776,"style":1370},"124.0",[790,1431,1433],{"x":1395,"y":1432,"style":1397},"146.0","ambiguous",[761,1435],{"x":1373,"y":1429,"width":1374,"height":1392,"rx":764,"fill":767,"stroke":776,"style":1370},[790,1437,1439],{"x":1378,"y":1438,"style":799},"145.0","Korea",[761,1441],{"x":1384,"y":1429,"width":1374,"height":1392,"rx":764,"fill":767,"stroke":776,"style":1370},[790,1443,1444],{"x":1387,"y":1438,"style":799},"KP or KR → review",[761,1446],{"x":770,"y":1447,"width":1368,"height":1392,"rx":764,"fill":775,"stroke":776,"style":1370},"158.0",[790,1449,1451],{"x":1395,"y":1450,"style":1397},"180.0","unmatched",[761,1453],{"x":1373,"y":1447,"width":1374,"height":1392,"rx":764,"fill":767,"stroke":776,"style":1370},[790,1455,1457],{"x":1378,"y":1456,"style":799},"179.0","Frnace, n\u002Fa",[761,1459],{"x":1384,"y":1447,"width":1374,"height":1392,"rx":764,"fill":767,"stroke":776,"style":1370},[790,1461,1462],{"x":1387,"y":1456,"style":799},"review",[742,1464,751,1469,751,1472,751,1475,751,1478,751,1483,751,1490,751,1495,751,1500,751,1504,751,1508,751,1512,751,1514,751,1519,751,1524,751,1528,751,1531,751,1534],{"viewBox":1465,"role":745,"ariaLabelledBy":1466,"xmlns":749,"style":750},"4 0 752 207",[1467,1468],"cc-fuzzy-t","cc-fuzzy-d",[753,1470,1471],{"id":1467},"Accepting or reporting a fuzzy result",[757,1473,1474],{"id":1468},"A fuzzy search that returns exactly one candidate, such as Holland returning the Netherlands, can be accepted and recorded as fuzzy. One that returns several candidates, such as Korea returning North and South Korea, or none, such as the typo Frnace, is reported for a person to decide.",[761,1476],{"x":763,"y":764,"width":765,"height":1477,"fill":767},"207",[761,1479],{"x":770,"y":771,"width":1480,"height":1481,"rx":1482,"fill":841,"stroke":842,"style":777},"351.0","175.0","14",[779,1484,1486],{"transform":1485},"translate(182.5,29.0) scale(1.083)",[783,1487],{"d":1488,"fill":786,"stroke":849,"style":1489},"M5 12.5l4.5 4.5L19 7","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[790,1491,1494],{"x":1492,"y":1396,"style":1493},"195.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","accept",[41,1496],{"x1":1497,"y1":1498,"x2":1499,"y2":1498,"stroke":842,"style":1370},"36.0","91.0","355.0",[790,1501,1503],{"x":1492,"y":1421,"style":1502},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","exactly one candidate",[790,1505,1507],{"x":1492,"y":1506,"style":1502},"137.0","recorded as 'fuzzy'",[790,1509,1511],{"x":1492,"y":1510,"style":1502},"163.0","e.g. Holland → NL",[761,1513],{"x":834,"y":771,"width":1480,"height":1481,"rx":1482,"fill":874,"stroke":875,"style":777},[779,1515,1517],{"transform":1516},"translate(551.5,29.0) scale(1.083)",[783,1518],{"d":881,"fill":786,"stroke":882,"style":1489},[790,1520,1523],{"x":1521,"y":1396,"style":1522},"564.5","font-size:14px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","report",[41,1525],{"x1":1526,"y1":1498,"x2":1527,"y2":1498,"stroke":875,"style":1370},"405.0","724.0",[790,1529,1530],{"x":1521,"y":1421,"style":1502},"several candidates (Korea → KP, KR)",[790,1532,1533],{"x":1521,"y":1506,"style":1502},"no candidate (Frnace)",[790,1535,1536],{"x":1521,"y":1510,"style":1502},"decision → override table",[25,1538,1540],{"id":1539},"step-5-summaries-that-finally-add-up","Step 5 — Summaries that finally add up",[10,1542,1543],{},"The payoff is a country summary with one row per country:",[30,1545,1547],{"className":78,"code":1546,"language":80,"meta":35,"style":35},"before = df.groupby(\"Country\")[\"Revenue\"].sum()\nafter = df.dropna(subset=[\"iso2\"]).groupby([\"iso2\", \"country_name\"])[\"Revenue\"].sum().sort_values(ascending=False)\nprint(\"groups before:\", len(before), \"| groups after:\", len(after))\nprint(after.head(5).to_string())\ndf.drop(columns=\"clean\").to_excel(\"orders_by_country_clean.xlsx\", index=False)\n",[14,1548,1549,1570,1616,1642,1655],{"__ignoreMap":35},[39,1550,1551,1554,1556,1559,1561,1564,1567],{"class":41,"line":42},[39,1552,1553],{"class":91},"before ",[39,1555,121],{"class":87},[39,1557,1558],{"class":91}," df.groupby(",[39,1560,163],{"class":49},[39,1562,1563],{"class":91},")[",[39,1565,1566],{"class":49},"\"Revenue\"",[39,1568,1569],{"class":91},"].sum()\n",[39,1571,1572,1575,1577,1580,1583,1585,1588,1590,1593,1595,1597,1599,1602,1604,1607,1610,1612,1614],{"class":41,"line":101},[39,1573,1574],{"class":91},"after ",[39,1576,121],{"class":87},[39,1578,1579],{"class":91}," df.dropna(",[39,1581,1582],{"class":133},"subset",[39,1584,121],{"class":87},[39,1586,1587],{"class":91},"[",[39,1589,251],{"class":49},[39,1591,1592],{"class":91},"]).groupby([",[39,1594,251],{"class":49},[39,1596,130],{"class":91},[39,1598,1265],{"class":49},[39,1600,1601],{"class":91},"])[",[39,1603,1566],{"class":49},[39,1605,1606],{"class":91},"].sum().sort_values(",[39,1608,1609],{"class":133},"ascending",[39,1611,121],{"class":87},[39,1613,140],{"class":139},[39,1615,143],{"class":91},[39,1617,1618,1620,1622,1625,1627,1629,1632,1635,1637,1639],{"class":41,"line":108},[39,1619,268],{"class":139},[39,1621,298],{"class":91},[39,1623,1624],{"class":49},"\"groups before:\"",[39,1626,130],{"class":91},[39,1628,317],{"class":139},[39,1630,1631],{"class":91},"(before), ",[39,1633,1634],{"class":49},"\"| groups after:\"",[39,1636,130],{"class":91},[39,1638,317],{"class":139},[39,1640,1641],{"class":91},"(after))\n",[39,1643,1644,1646,1649,1652],{"class":41,"line":115},[39,1645,268],{"class":139},[39,1647,1648],{"class":91},"(after.head(",[39,1650,1651],{"class":139},"5",[39,1653,1654],{"class":91},").to_string())\n",[39,1656,1657,1660,1663,1665,1667,1670,1673,1675,1677,1679,1681],{"class":41,"line":146},[39,1658,1659],{"class":91},"df.drop(",[39,1661,1662],{"class":133},"columns",[39,1664,121],{"class":87},[39,1666,152],{"class":49},[39,1668,1669],{"class":91},").to_excel(",[39,1671,1672],{"class":49},"\"orders_by_country_clean.xlsx\"",[39,1674,130],{"class":91},[39,1676,283],{"class":133},[39,1678,121],{"class":87},[39,1680,140],{"class":139},[39,1682,143],{"class":91},[10,1684,1685],{},"Grouped by the raw column, 25 orders produce 25 separate \"countries\"; grouped by ISO code they collapse to nine real countries, with the UK and Germany each gathering five spellings into one line and the US and the Netherlands three each. Grouping by the code rather than the name is the safer habit: names change and differ by language, codes do not. Keep the original column in the output so the mapping can always be audited. The same codes are what joins to other data need: exchange rates, VAT rates, regions and sales territories are usually keyed by ISO code, so a clean code column is what makes those lookups work at all.",[25,1687,1689],{"id":1688},"common-pitfalls","Common pitfalls",[1691,1692,1693,1701,1707,1713,1719],"ul",{},[1694,1695,1696,1700],"li",{},[1697,1698,1699],"strong",{},"Treating \"UK\" as an ISO code."," The ISO code for the United Kingdom is GB.",[1694,1702,1703,1706],{},[1697,1704,1705],{},"Accepting the first fuzzy match."," Ambiguous values like \"Korea\" must go to a person.",[1694,1708,1709,1712],{},[1697,1710,1711],{},"Forgetting renamed countries."," \"Turkey\" is no longer the ISO name; add it to the overrides.",[1694,1714,1715,1718],{},[1697,1716,1717],{},"Mapping England, Scotland and Wales without thinking."," Use subdivision codes if the distinction matters.",[1694,1720,1721,1724],{},[1697,1722,1723],{},"Grouping by name."," Group by ISO code; display the name.",[25,1726,1728],{"id":1727},"conclusion","Conclusion",[10,1730,1731,1732,1734],{},"To standardise a country column, clean the values, check them first against a small override table for nicknames, native names and renamed countries, then resolve the rest by exact lookup in ",[14,1733,16],{}," against official names and ISO codes. Use fuzzy search only when it returns a single candidate, and report ambiguous and unmatched values for review rather than guessing. Store ISO alpha-2 and alpha-3 codes alongside one display name, group summaries by the code, and keep the original values for audit.",[25,1736,1738],{"id":1737},"frequently-asked-questions","Frequently asked questions",[10,1740,1741,1744],{},[1697,1742,1743],{},"How do I convert country names to ISO codes in Python?","\nUse pycountry.countries.lookup(name), which matches official names and alpha-2 and alpha-3 codes case-insensitively and returns an object with alpha_2, alpha_3 and name.",[10,1746,1747,1750],{},[1697,1748,1749],{},"Why doesn't pycountry recognise UK or Holland?","\nThey are not ISO 3166 names or codes; the United Kingdom's code is GB and Holland is a region of the Netherlands. Map such values with an override table.",[10,1752,1753,1756],{},[1697,1754,1755],{},"Is it safe to use fuzzy matching for country names?","\nOnly when there is a single clear candidate. Values such as Korea match several countries, and typos may not match at all, so report them for review.",[10,1758,1759,1762],{},[1697,1760,1761],{},"Should I group sales by country name or code?","\nBy code. Country names vary by language and change over time, while ISO codes stay stable.",[25,1764,1766],{"id":1765},"related","Related",[1691,1768,1769,1775,1782,1789],{},[1694,1770,1771,1772,1774],{},"Up one level: ",[19,1773,22],{"href":21}," — tidy data before analysis.",[1694,1776,1777,1781],{},[19,1778,1780],{"href":1779},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-category-values-with-a-mapping-table\u002F","Standardise Category Values with a Mapping Table"," — the general technique.",[1694,1783,1784,1788],{},[19,1785,1787],{"href":1786},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fnormalise-postcodes-and-zip-codes-with-pandas\u002F","Normalise Postcodes and ZIP Codes with pandas"," — the next address field.",[1694,1790,1791,1795],{},[19,1792,1794],{"href":1793},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Flocalise-an-excel-report-for-other-languages-and-locales\u002F","Localise an Excel Report for Other Languages and Locales"," — showing country names in other languages.",[1797,1798,1799],"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 .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}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":35,"searchDepth":101,"depth":101,"links":1801},[1802,1803,1804,1805,1806,1807,1808,1809,1810,1811],{"id":27,"depth":101,"text":28},{"id":68,"depth":101,"text":69},{"id":343,"depth":101,"text":344},{"id":893,"depth":101,"text":894},{"id":1160,"depth":101,"text":1161},{"id":1539,"depth":101,"text":1540},{"id":1688,"depth":101,"text":1689},{"id":1727,"depth":101,"text":1728},{"id":1737,"depth":101,"text":1738},{"id":1765,"depth":101,"text":1766},"2026-10-02","Map a free-typed country column — \"Germany\", \"DE\", \"deutschland\", \"UK\", \"U.S.A.\", \"Holland\", \"Turkey\" — to ISO 3166 codes and one official name with pycountry: exact lookups by name and code, an override table for nicknames, native names and renamed countries, cautious use of fuzzy search, a report of ambiguous and unmatched values, and summaries that finally add up per country.","md",[1816,1818,1820,1822],{"q":1743,"a":1817},"Use pycountry.countries.lookup(name), which matches official names and alpha-2 and alpha-3 codes case-insensitively and returns an object with alpha_2, alpha_3 and name.",{"q":1749,"a":1819},"They are not ISO 3166 names or codes; the United Kingdom's code is GB and Holland is a region of the Netherlands. Map such values with an override table.",{"q":1755,"a":1821},"Only when there is a single clear candidate. Values such as Korea match several countries, and typos may not match at all, so report them for review.",{"q":1761,"a":1823},"By code. Country names vary by language and change over time, while ISO codes stay stable.","standardise country names and codes with python",null,{"breadcrumb":1827},[1828,1831,1834],{"name":1829,"item":1830},"Home","\u002F",{"name":1832,"item":1833},"Advanced Data Transformation and Cleaning for Excel Automation","\u002Fadvanced-data-transformation-and-cleaning\u002F",{"name":1835,"item":21},"Cleaning Excel Data With Pandas: A Production Workflow","\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-country-names-and-codes-with-python",{"title":1838,"description":1839},"Standardise Country Names and ISO Codes with Python","Clean a country column from Excel with pycountry: lookup by name, alpha-2 and alpha-3 codes, overrides for UK, Holland, Deutschland and Turkey, careful fuzzy matching, ambiguous and unmatched reports, and ISO codes.","standardise-country-names-and-codes-with-python","advanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-country-names-and-codes-with-python\u002Findex",[1843],"data-cleaning","how-to","RThZ_w438Keu5kfOUujFDza6-oDzZi57z-Y2mEPN3fg",[1847,1851],{"title":1848,"path":1849,"stem":1850,"children":-1},"Standardise Category Values with a Mapping Table in pandas","\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-category-values-with-a-mapping-table","advanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-category-values-with-a-mapping-table\u002Findex",{"title":1852,"path":1853,"stem":1854,"children":-1},"Standardise Excel Column Names with pandas","\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-excel-column-names-with-pandas","advanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstandardise-excel-column-names-with-pandas\u002Findex",[1856,1858],{"path":1857,"title":1835},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas",{"path":1859,"title":1832},"\u002Fadvanced-data-transformation-and-cleaning",[],[1862,1865,1868,1871,1874,1877],{"path":1863,"title":1864,"kind":1844},"\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":1866,"title":1867,"kind":1844},"\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":1869,"title":1870,"kind":1844},"\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":1872,"title":1873,"kind":1844},"\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":1875,"title":1876,"kind":1844},"\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":1878,"title":1879,"kind":1844},"\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",1790972086007]