[{"data":1,"prerenderedAt":2538},["ShallowReactive",2],{"doc:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Ftextbefore-textafter-and-textsplit-equivalents-in-pandas":3,"surround:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Ftextbefore-textafter-and-textsplit-equivalents-in-pandas":2504,"ancestors:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Ftextbefore-textafter-and-textsplit-equivalents-in-pandas":2513,"children:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Ftextbefore-textafter-and-textsplit-equivalents-in-pandas":2518,"related:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Ftextbefore-textafter-and-textsplit-equivalents-in-pandas":2519},{"id":4,"title":5,"body":6,"dateModified":2473,"datePublished":2473,"description":2474,"extension":2475,"faq":2476,"keyword":2485,"kind":2486,"meta":2487,"navigation":149,"path":2495,"seo":2496,"slug":2498,"stem":2499,"topics":2500,"type":2502,"__hash__":2503},"docs\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Ftextbefore-textafter-and-textsplit-equivalents-in-pandas\u002Findex.md","TEXTBEFORE, TEXTAFTER and TEXTSPLIT Equivalents in pandas",{"type":7,"value":8,"toc":2461},"minimark",[9,59,64,92,106,110,113,657,675,679,688,1048,1080,1183,1187,1190,1523,1541,1545,1551,1703,1732,1903,2046,2050,2056,2278,2304,2308,2360,2364,2396,2400,2406,2412,2418,2424,2428,2457],[10,11,12,13,17,18,21,22,25,26,30,31,34,35,38,39,38,42,45,46,49,50,52,53,58],"p",{},"Excel's newer text functions replaced a generation of ",[14,15,16],"code",{},"LEFT(A2, FIND(\"@\", A2) - 1)"," formulas. ",[14,19,20],{},"TEXTBEFORE(A2, \"@\")"," returns the part of an email address before the at-sign; ",[14,23,24],{},"TEXTAFTER(A2, \" - \", -1)"," the part after the ",[27,28,29],"em",{},"last"," separator; ",[14,32,33],{},"TEXTSPLIT(A2, \",\")"," spills each comma-separated value into its own column. pandas has string methods for all of these — ",[14,36,37],{},"str.partition",", ",[14,40,41],{},"str.rpartition",[14,43,44],{},"str.split"," with a limit — and they are fast and vectorised. But they differ from Excel in one important way: what happens when the delimiter is not there. Excel returns ",[14,47,48],{},"#N\u002FA"," unless told otherwise; ",[14,51,37],{}," quietly returns the whole text, which can pass an address without an at-sign through as a \"username\". This page maps each function and its options to pandas, handles the missing-delimiter case the way Excel does, and checks every result against the spreadsheet. It belongs to ",[54,55,57],"a",{"href":56},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002F","Excel Formula Equivalents in pandas",".",[60,61,63],"h2",{"id":62},"prerequisites","Prerequisites",[65,66,71],"pre",{"className":67,"code":68,"language":69,"meta":70,"style":70},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl\n","bash","",[14,72,73],{"__ignoreMap":70},[74,75,78,82,86,89],"span",{"class":76,"line":77},"line",1,[74,79,81],{"class":80},"sMTad","pip",[74,83,85],{"class":84},"srMev"," install",[74,87,88],{"class":84}," pandas",[74,90,91],{"class":84}," openpyxl\n",[10,93,94,97,98,101,102,105],{},[14,95,96],{},"records.xlsx"," holds four records with an email address (one missing its at-sign), a location made of city, postcode and country separated by \" - \", a comma-separated tag list with inconsistent spacing and one empty value, and a product code with mixed-case parts. LibreOffice (",[14,99,100],{},"soffice",") recalculates the equivalent spreadsheet formulas for comparison; the newer functions are written with the ",[14,103,104],{},"_xlfn."," prefix the file format requires.",[60,107,109],{"id":108},"step-1-the-spreadsheets-answers","Step 1 — The spreadsheet's answers",[10,111,112],{},"Write the formulas for each record and recalculate, to have reference results:",[65,114,118],{"className":115,"code":116,"language":117,"meta":70,"style":70},"language-python shiki shiki-themes github-light github-dark-high-contrast","import subprocess\nfrom openpyxl import load_workbook\n\nwb = load_workbook(\"records.xlsx\")\nws = wb.active\nheads = [\"user\", \"domain\", \"city\", \"country\", \"middle\", \"user or n\u002Fa\", \"after first a (any case)\"]\nfor j, h in enumerate(heads, start=5):\n    ws.cell(1, j, h)\nfor r in range(2, ws.max_row + 1):\n    ws.cell(r, 5, f'=_xlfn.TEXTBEFORE(A{r},\"@\")')\n    ws.cell(r, 6, f'=_xlfn.TEXTAFTER(A{r},\"@\")')\n    ws.cell(r, 7, f'=_xlfn.TEXTBEFORE(B{r},\" - \")')\n    ws.cell(r, 8, f'=_xlfn.TEXTAFTER(B{r},\" - \",-1)')\n    ws.cell(r, 9, f'=_xlfn.TEXTBEFORE(_xlfn.TEXTAFTER(B{r},\" - \"),\" - \")')\n    ws.cell(r, 10, f'=_xlfn.TEXTBEFORE(A{r},\"@\",,,,\"n\u002Fa\")')\n    ws.cell(r, 11, f'=_xlfn.TEXTAFTER(D{r},\"a\",1,1)')\nwb.save(\"records_formulas.xlsx\")\nsubprocess.run([\"soffice\", \"--headless\", \"--convert-to\", \"xlsx\", \"--outdir\", \"calc\", \"records_formulas.xlsx\"], check=True, capture_output=True)\ncalc = load_workbook(\"calc\u002Frecords_formulas.xlsx\", data_only=True).active\nexcel = [[calc.cell(r, c).value for c in range(5, 12)] for r in range(2, calc.max_row + 1)]\nfor row in excel:\n    print(row)\n","python",[14,119,120,130,144,151,169,180,227,258,270,300,331,356,382,408,434,459,485,496,556,581,635,648],{"__ignoreMap":70},[74,121,122,126],{"class":76,"line":77},[74,123,125],{"class":124},"s-kum","import",[74,127,129],{"class":128},"skGVy"," subprocess\n",[74,131,133,136,139,141],{"class":76,"line":132},2,[74,134,135],{"class":124},"from",[74,137,138],{"class":128}," openpyxl ",[74,140,125],{"class":124},[74,142,143],{"class":128}," load_workbook\n",[74,145,147],{"class":76,"line":146},3,[74,148,150],{"emptyLinePlaceholder":149},true,"\n",[74,152,154,157,160,163,166],{"class":76,"line":153},4,[74,155,156],{"class":128},"wb ",[74,158,159],{"class":124},"=",[74,161,162],{"class":128}," load_workbook(",[74,164,165],{"class":84},"\"records.xlsx\"",[74,167,168],{"class":128},")\n",[74,170,172,175,177],{"class":76,"line":171},5,[74,173,174],{"class":128},"ws ",[74,176,159],{"class":124},[74,178,179],{"class":128}," wb.active\n",[74,181,183,186,188,191,194,196,199,201,204,206,209,211,214,216,219,221,224],{"class":76,"line":182},6,[74,184,185],{"class":128},"heads ",[74,187,159],{"class":124},[74,189,190],{"class":128}," [",[74,192,193],{"class":84},"\"user\"",[74,195,38],{"class":128},[74,197,198],{"class":84},"\"domain\"",[74,200,38],{"class":128},[74,202,203],{"class":84},"\"city\"",[74,205,38],{"class":128},[74,207,208],{"class":84},"\"country\"",[74,210,38],{"class":128},[74,212,213],{"class":84},"\"middle\"",[74,215,38],{"class":128},[74,217,218],{"class":84},"\"user or n\u002Fa\"",[74,220,38],{"class":128},[74,222,223],{"class":84},"\"after first a (any case)\"",[74,225,226],{"class":128},"]\n",[74,228,230,233,236,239,243,246,250,252,255],{"class":76,"line":229},7,[74,231,232],{"class":124},"for",[74,234,235],{"class":128}," j, h ",[74,237,238],{"class":124},"in",[74,240,242],{"class":241},"sP0c6"," enumerate",[74,244,245],{"class":128},"(heads, ",[74,247,249],{"class":248},"sa561","start",[74,251,159],{"class":124},[74,253,254],{"class":241},"5",[74,256,257],{"class":128},"):\n",[74,259,261,264,267],{"class":76,"line":260},8,[74,262,263],{"class":128},"    ws.cell(",[74,265,266],{"class":241},"1",[74,268,269],{"class":128},", j, h)\n",[74,271,273,275,278,280,283,286,289,292,295,298],{"class":76,"line":272},9,[74,274,232],{"class":124},[74,276,277],{"class":128}," r ",[74,279,238],{"class":124},[74,281,282],{"class":241}," range",[74,284,285],{"class":128},"(",[74,287,288],{"class":241},"2",[74,290,291],{"class":128},", ws.max_row ",[74,293,294],{"class":124},"+",[74,296,297],{"class":241}," 1",[74,299,257],{"class":128},[74,301,303,306,308,310,313,316,320,323,326,329],{"class":76,"line":302},10,[74,304,305],{"class":128},"    ws.cell(r, ",[74,307,254],{"class":241},[74,309,38],{"class":128},[74,311,312],{"class":124},"f",[74,314,315],{"class":84},"'=_xlfn.TEXTBEFORE(A",[74,317,319],{"class":318},"sSjpA","{",[74,321,322],{"class":128},"r",[74,324,325],{"class":318},"}",[74,327,328],{"class":84},",\"@\")'",[74,330,168],{"class":128},[74,332,334,336,339,341,343,346,348,350,352,354],{"class":76,"line":333},11,[74,335,305],{"class":128},[74,337,338],{"class":241},"6",[74,340,38],{"class":128},[74,342,312],{"class":124},[74,344,345],{"class":84},"'=_xlfn.TEXTAFTER(A",[74,347,319],{"class":318},[74,349,322],{"class":128},[74,351,325],{"class":318},[74,353,328],{"class":84},[74,355,168],{"class":128},[74,357,359,361,364,366,368,371,373,375,377,380],{"class":76,"line":358},12,[74,360,305],{"class":128},[74,362,363],{"class":241},"7",[74,365,38],{"class":128},[74,367,312],{"class":124},[74,369,370],{"class":84},"'=_xlfn.TEXTBEFORE(B",[74,372,319],{"class":318},[74,374,322],{"class":128},[74,376,325],{"class":318},[74,378,379],{"class":84},",\" - \")'",[74,381,168],{"class":128},[74,383,385,387,390,392,394,397,399,401,403,406],{"class":76,"line":384},13,[74,386,305],{"class":128},[74,388,389],{"class":241},"8",[74,391,38],{"class":128},[74,393,312],{"class":124},[74,395,396],{"class":84},"'=_xlfn.TEXTAFTER(B",[74,398,319],{"class":318},[74,400,322],{"class":128},[74,402,325],{"class":318},[74,404,405],{"class":84},",\" - \",-1)'",[74,407,168],{"class":128},[74,409,411,413,416,418,420,423,425,427,429,432],{"class":76,"line":410},14,[74,412,305],{"class":128},[74,414,415],{"class":241},"9",[74,417,38],{"class":128},[74,419,312],{"class":124},[74,421,422],{"class":84},"'=_xlfn.TEXTBEFORE(_xlfn.TEXTAFTER(B",[74,424,319],{"class":318},[74,426,322],{"class":128},[74,428,325],{"class":318},[74,430,431],{"class":84},",\" - \"),\" - \")'",[74,433,168],{"class":128},[74,435,437,439,442,444,446,448,450,452,454,457],{"class":76,"line":436},15,[74,438,305],{"class":128},[74,440,441],{"class":241},"10",[74,443,38],{"class":128},[74,445,312],{"class":124},[74,447,315],{"class":84},[74,449,319],{"class":318},[74,451,322],{"class":128},[74,453,325],{"class":318},[74,455,456],{"class":84},",\"@\",,,,\"n\u002Fa\")'",[74,458,168],{"class":128},[74,460,462,464,467,469,471,474,476,478,480,483],{"class":76,"line":461},16,[74,463,305],{"class":128},[74,465,466],{"class":241},"11",[74,468,38],{"class":128},[74,470,312],{"class":124},[74,472,473],{"class":84},"'=_xlfn.TEXTAFTER(D",[74,475,319],{"class":318},[74,477,322],{"class":128},[74,479,325],{"class":318},[74,481,482],{"class":84},",\"a\",1,1)'",[74,484,168],{"class":128},[74,486,488,491,494],{"class":76,"line":487},17,[74,489,490],{"class":128},"wb.save(",[74,492,493],{"class":84},"\"records_formulas.xlsx\"",[74,495,168],{"class":128},[74,497,499,502,505,507,510,512,515,517,520,522,525,527,530,532,534,537,540,542,545,547,550,552,554],{"class":76,"line":498},18,[74,500,501],{"class":128},"subprocess.run([",[74,503,504],{"class":84},"\"soffice\"",[74,506,38],{"class":128},[74,508,509],{"class":84},"\"--headless\"",[74,511,38],{"class":128},[74,513,514],{"class":84},"\"--convert-to\"",[74,516,38],{"class":128},[74,518,519],{"class":84},"\"xlsx\"",[74,521,38],{"class":128},[74,523,524],{"class":84},"\"--outdir\"",[74,526,38],{"class":128},[74,528,529],{"class":84},"\"calc\"",[74,531,38],{"class":128},[74,533,493],{"class":84},[74,535,536],{"class":128},"], ",[74,538,539],{"class":248},"check",[74,541,159],{"class":124},[74,543,544],{"class":241},"True",[74,546,38],{"class":128},[74,548,549],{"class":248},"capture_output",[74,551,159],{"class":124},[74,553,544],{"class":241},[74,555,168],{"class":128},[74,557,559,562,564,566,569,571,574,576,578],{"class":76,"line":558},19,[74,560,561],{"class":128},"calc ",[74,563,159],{"class":124},[74,565,162],{"class":128},[74,567,568],{"class":84},"\"calc\u002Frecords_formulas.xlsx\"",[74,570,38],{"class":128},[74,572,573],{"class":248},"data_only",[74,575,159],{"class":124},[74,577,544],{"class":241},[74,579,580],{"class":128},").active\n",[74,582,584,587,589,592,594,597,599,601,603,605,607,610,613,615,617,619,621,623,625,628,630,632],{"class":76,"line":583},20,[74,585,586],{"class":128},"excel ",[74,588,159],{"class":124},[74,590,591],{"class":128}," [[calc.cell(r, c).value ",[74,593,232],{"class":124},[74,595,596],{"class":128}," c ",[74,598,238],{"class":124},[74,600,282],{"class":241},[74,602,285],{"class":128},[74,604,254],{"class":241},[74,606,38],{"class":128},[74,608,609],{"class":241},"12",[74,611,612],{"class":128},")] ",[74,614,232],{"class":124},[74,616,277],{"class":128},[74,618,238],{"class":124},[74,620,282],{"class":241},[74,622,285],{"class":128},[74,624,288],{"class":241},[74,626,627],{"class":128},", calc.max_row ",[74,629,294],{"class":124},[74,631,297],{"class":241},[74,633,634],{"class":128},")]\n",[74,636,638,640,643,645],{"class":76,"line":637},21,[74,639,232],{"class":124},[74,641,642],{"class":128}," row ",[74,644,238],{"class":124},[74,646,647],{"class":128}," excel:\n",[74,649,651,654],{"class":76,"line":650},22,[74,652,653],{"class":241},"    print",[74,655,656],{"class":128},"(row)\n",[10,658,659,660,662,663,666,667,670,671,674],{},"The results show the behaviours to match: the user and domain parts of each email, ",[14,661,48],{}," for \"chloe.martin\" which has no at-sign — and \"n\u002Fa\" where the formula supplies its ",[14,664,665],{},"if_not_found"," argument — the city before the first separator, the country after the last one (instance ",[14,668,669],{},"-1","), the postcode between them, and a case-insensitive match (",[14,672,673],{},"match_mode"," 1) that finds the \"a\" in \"SKU-a-104\" and the \"A\" in \"SKU-A-205\" alike.",[60,676,678],{"id":677},"step-2-before-and-after-the-first-or-last-delimiter","Step 2 — Before and after the first or last delimiter",[10,680,681,682,684,685,687],{},"The first occurrence is ",[14,683,37],{},", the last is ",[14,686,41],{},". Each returns three parts — before, the delimiter, after — and the missing-delimiter case needs one extra step to behave like Excel:",[65,689,691],{"className":115,"code":690,"language":117,"meta":70,"style":70},"import pandas as pd\n\ndf = pd.read_excel(\"records.xlsx\", keep_default_na=False)\n\ndef text_before(s, delim, last=False, if_not_found=None):\n    parts = (s.str.rpartition(delim) if last else s.str.partition(delim))\n    found = s.str.contains(delim, regex=False)\n    return parts[0].where(found, if_not_found)\n\ndef text_after(s, delim, last=False, if_not_found=None):\n    parts = (s.str.rpartition(delim) if last else s.str.partition(delim))\n    found = s.str.contains(delim, regex=False)\n    return parts[2].where(found, if_not_found)\n\nprint(df[\"Email\"].str.partition(\"@\")[0].tolist(), \"← plain partition\")\ndf[\"user\"] = text_before(df[\"Email\"], \"@\")\ndf[\"domain\"] = text_after(df[\"Email\"], \"@\")\ndf[\"city\"] = text_before(df[\"Location\"], \" - \")\ndf[\"country\"] = text_after(df[\"Location\"], \" - \", last=True)\nprint(df[[\"user\", \"domain\", \"city\", \"country\"]].to_string(index=False))\n",[14,692,693,706,710,734,738,764,786,805,819,823,844,860,876,886,890,920,943,964,986,1014],{"__ignoreMap":70},[74,694,695,697,700,703],{"class":76,"line":77},[74,696,125],{"class":124},[74,698,699],{"class":128}," pandas ",[74,701,702],{"class":124},"as",[74,704,705],{"class":128}," pd\n",[74,707,708],{"class":76,"line":132},[74,709,150],{"emptyLinePlaceholder":149},[74,711,712,715,717,720,722,724,727,729,732],{"class":76,"line":146},[74,713,714],{"class":128},"df ",[74,716,159],{"class":124},[74,718,719],{"class":128}," pd.read_excel(",[74,721,165],{"class":84},[74,723,38],{"class":128},[74,725,726],{"class":248},"keep_default_na",[74,728,159],{"class":124},[74,730,731],{"class":241},"False",[74,733,168],{"class":128},[74,735,736],{"class":76,"line":153},[74,737,150],{"emptyLinePlaceholder":149},[74,739,740,743,747,750,752,754,757,759,762],{"class":76,"line":171},[74,741,742],{"class":124},"def",[74,744,746],{"class":745},"s_Opv"," text_before",[74,748,749],{"class":128},"(s, delim, last",[74,751,159],{"class":124},[74,753,731],{"class":241},[74,755,756],{"class":128},", if_not_found",[74,758,159],{"class":124},[74,760,761],{"class":241},"None",[74,763,257],{"class":128},[74,765,766,769,771,774,777,780,783],{"class":76,"line":182},[74,767,768],{"class":128},"    parts ",[74,770,159],{"class":124},[74,772,773],{"class":128}," (s.str.rpartition(delim) ",[74,775,776],{"class":124},"if",[74,778,779],{"class":128}," last ",[74,781,782],{"class":124},"else",[74,784,785],{"class":128}," s.str.partition(delim))\n",[74,787,788,791,793,796,799,801,803],{"class":76,"line":229},[74,789,790],{"class":128},"    found ",[74,792,159],{"class":124},[74,794,795],{"class":128}," s.str.contains(delim, ",[74,797,798],{"class":248},"regex",[74,800,159],{"class":124},[74,802,731],{"class":241},[74,804,168],{"class":128},[74,806,807,810,813,816],{"class":76,"line":260},[74,808,809],{"class":124},"    return",[74,811,812],{"class":128}," parts[",[74,814,815],{"class":241},"0",[74,817,818],{"class":128},"].where(found, if_not_found)\n",[74,820,821],{"class":76,"line":272},[74,822,150],{"emptyLinePlaceholder":149},[74,824,825,827,830,832,834,836,838,840,842],{"class":76,"line":302},[74,826,742],{"class":124},[74,828,829],{"class":745}," text_after",[74,831,749],{"class":128},[74,833,159],{"class":124},[74,835,731],{"class":241},[74,837,756],{"class":128},[74,839,159],{"class":124},[74,841,761],{"class":241},[74,843,257],{"class":128},[74,845,846,848,850,852,854,856,858],{"class":76,"line":333},[74,847,768],{"class":128},[74,849,159],{"class":124},[74,851,773],{"class":128},[74,853,776],{"class":124},[74,855,779],{"class":128},[74,857,782],{"class":124},[74,859,785],{"class":128},[74,861,862,864,866,868,870,872,874],{"class":76,"line":358},[74,863,790],{"class":128},[74,865,159],{"class":124},[74,867,795],{"class":128},[74,869,798],{"class":248},[74,871,159],{"class":124},[74,873,731],{"class":241},[74,875,168],{"class":128},[74,877,878,880,882,884],{"class":76,"line":384},[74,879,809],{"class":124},[74,881,812],{"class":128},[74,883,288],{"class":241},[74,885,818],{"class":128},[74,887,888],{"class":76,"line":410},[74,889,150],{"emptyLinePlaceholder":149},[74,891,892,895,898,901,904,907,910,912,915,918],{"class":76,"line":436},[74,893,894],{"class":241},"print",[74,896,897],{"class":128},"(df[",[74,899,900],{"class":84},"\"Email\"",[74,902,903],{"class":128},"].str.partition(",[74,905,906],{"class":84},"\"@\"",[74,908,909],{"class":128},")[",[74,911,815],{"class":241},[74,913,914],{"class":128},"].tolist(), ",[74,916,917],{"class":84},"\"← plain partition\"",[74,919,168],{"class":128},[74,921,922,925,927,930,932,935,937,939,941],{"class":76,"line":461},[74,923,924],{"class":128},"df[",[74,926,193],{"class":84},[74,928,929],{"class":128},"] ",[74,931,159],{"class":124},[74,933,934],{"class":128}," text_before(df[",[74,936,900],{"class":84},[74,938,536],{"class":128},[74,940,906],{"class":84},[74,942,168],{"class":128},[74,944,945,947,949,951,953,956,958,960,962],{"class":76,"line":487},[74,946,924],{"class":128},[74,948,198],{"class":84},[74,950,929],{"class":128},[74,952,159],{"class":124},[74,954,955],{"class":128}," text_after(df[",[74,957,900],{"class":84},[74,959,536],{"class":128},[74,961,906],{"class":84},[74,963,168],{"class":128},[74,965,966,968,970,972,974,976,979,981,984],{"class":76,"line":498},[74,967,924],{"class":128},[74,969,203],{"class":84},[74,971,929],{"class":128},[74,973,159],{"class":124},[74,975,934],{"class":128},[74,977,978],{"class":84},"\"Location\"",[74,980,536],{"class":128},[74,982,983],{"class":84},"\" - \"",[74,985,168],{"class":128},[74,987,988,990,992,994,996,998,1000,1002,1004,1006,1008,1010,1012],{"class":76,"line":558},[74,989,924],{"class":128},[74,991,208],{"class":84},[74,993,929],{"class":128},[74,995,159],{"class":124},[74,997,955],{"class":128},[74,999,978],{"class":84},[74,1001,536],{"class":128},[74,1003,983],{"class":84},[74,1005,38],{"class":128},[74,1007,29],{"class":248},[74,1009,159],{"class":124},[74,1011,544],{"class":241},[74,1013,168],{"class":128},[74,1015,1016,1018,1021,1023,1025,1027,1029,1031,1033,1035,1038,1041,1043,1045],{"class":76,"line":583},[74,1017,894],{"class":241},[74,1019,1020],{"class":128},"(df[[",[74,1022,193],{"class":84},[74,1024,38],{"class":128},[74,1026,198],{"class":84},[74,1028,38],{"class":128},[74,1030,203],{"class":84},[74,1032,38],{"class":128},[74,1034,208],{"class":84},[74,1036,1037],{"class":128},"]].to_string(",[74,1039,1040],{"class":248},"index",[74,1042,159],{"class":124},[74,1044,731],{"class":241},[74,1046,1047],{"class":128},"))\n",[10,1049,1050,1051,1054,1055,1058,1059,1061,1062,1064,1065,1067,1068,1071,1072,1075,1076,1079],{},"The first line shows the trap: plain ",[14,1052,1053],{},"partition"," returns \"chloe.martin\" as the part before an at-sign that does not exist — a value that looks perfectly valid and would sail through into a \"username\" column. Checking with ",[14,1056,1057],{},"str.contains(..., regex=False)"," and replacing the not-found rows with ",[14,1060,761],{}," reproduces Excel's ",[14,1063,48],{}," as a missing value, or any ",[14,1066,665],{}," default. ",[14,1069,1070],{},"rpartition"," searches from the end, which is Excel's ",[14,1073,1074],{},"instance_num = -1",": the country \"UK\" after the last \" - \". ",[14,1077,1078],{},"regex=False"," matters because delimiters such as \".\" or \"|\" mean something else in a regular expression.",[1081,1082,1090,1091,1090,1095,1090,1099,1090,1106,1090,1116,1090,1127,1090,1134,1090,1140,1090,1145,1090,1149,1090,1153,1090,1158,1090,1165,1090,1170,1090,1174,1090,1177,1090,1180],"svg",{"viewBox":1083,"role":1084,"ariaLabelledBy":1085,"xmlns":1088,"style":1089},"4 0 752 207","img",[1086,1087],"tb-missing-t","tb-missing-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  ",[1092,1093,1094],"title",{"id":1086},"When the delimiter is missing",[1096,1097,1098],"desc",{"id":1087},"Excel's TEXTBEFORE returns",[1100,1101],"rect",{"x":1102,"y":815,"width":1103,"height":1104,"fill":1105},"4","752","207","#ffffff",[1100,1107],{"x":1108,"y":1109,"width":1110,"height":1111,"rx":1112,"fill":1113,"stroke":1114,"style":1115},"20.0","16.0","351.0","175.0","14","#fdefd8","var(--gold,#b4740a)","stroke-width:2px",[1117,1118,1120],"g",{"transform":1119},"translate(182.5,29.0) scale(1.083)",[1121,1122],"path",{"d":1123,"fill":1124,"stroke":1125,"style":1126},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","none","var(--gold-ink,#7a4e06)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[1128,1129,1133],"text",{"x":1130,"y":1131,"style":1132},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Excel TEXTBEFORE(A4,\"@\")",[76,1135],{"x1":1136,"y1":1137,"x2":1138,"y2":1137,"stroke":1114,"style":1139},"36.0","91.0","355.0","stroke-width:1px",[1128,1141,1144],{"x":1130,"y":1142,"style":1143},"111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","#N\u002FA when \"@\" is missing",[1128,1146,1148],{"x":1130,"y":1147,"style":1143},"137.0","or the if_not_found value",[1128,1150,1152],{"x":1130,"y":1151,"style":1143},"163.0","error is visible",[1100,1154],{"x":1155,"y":1109,"width":1110,"height":1111,"rx":1112,"fill":1156,"stroke":1157,"style":1115},"389.0","#fce9e9","var(--danger,#dc2626)",[1117,1159,1161],{"transform":1160},"translate(551.5,29.0) scale(1.083)",[1121,1162],{"d":1163,"fill":1124,"stroke":1164,"style":1126},"M6 6l12 12 M18 6L6 18","var(--accent-ink,#be185d)",[1128,1166,1169],{"x":1167,"y":1131,"style":1168},"564.5","font-size:14px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","plain str.partition(\"@\")[0]",[76,1171],{"x1":1172,"y1":1137,"x2":1173,"y2":1137,"stroke":1157,"style":1139},"405.0","724.0",[1128,1175,1176],{"x":1167,"y":1142,"style":1143},"returns the whole text",[1128,1178,1179],{"x":1167,"y":1147,"style":1143},"\"chloe.martin\" looks valid",[1128,1181,1182],{"x":1167,"y":1151,"style":1143},"bad data passes silently",[60,1184,1186],{"id":1185},"step-3-the-nth-occurrence-and-case-insensitive-matching","Step 3 — The nth occurrence, and case-insensitive matching",[10,1188,1189],{},"For the nth occurrence, split with a limit and rejoin; for case-insensitive matching, search a lower-cased copy and cut the original at the same position:",[65,1191,1193],{"className":115,"code":1192,"language":117,"meta":70,"style":70},"def text_after_nth(s, delim, n, if_not_found=None):\n    parts = s.str.split(delim, n=n, regex=False)\n    return parts.map(lambda p: p[n] if len(p) > n else if_not_found)\n\ndef text_before_nth(s, delim, n, if_not_found=None):\n    parts = s.str.split(delim, regex=False)\n    return parts.map(lambda p: delim.join(p[:n]) if len(p) > n else if_not_found)\n\ndef text_after_ci(s, delim, if_not_found=None):\n    pos = s.str.lower().str.find(delim.lower())\n    return pd.Series([t[i + len(delim):] if i >= 0 else if_not_found for t, i in zip(s, pos)], index=s.index)\n\ndf[\"middle\"] = text_before(text_after(df[\"Location\"], \" - \"), \" - \")\ndf[\"after 2nd sep\"] = text_after_nth(df[\"Location\"], \" - \", 2)\ndf[\"after first a\"] = text_after_ci(df[\"Code\"], \"a\")\nprint(df[[\"Location\", \"middle\", \"after 2nd sep\", \"Code\", \"after first a\"]].to_string(index=False))\n",[14,1194,1195,1211,1236,1268,1272,1287,1303,1328,1332,1348,1358,1409,1413,1439,1465,1489],{"__ignoreMap":70},[74,1196,1197,1199,1202,1205,1207,1209],{"class":76,"line":77},[74,1198,742],{"class":124},[74,1200,1201],{"class":745}," text_after_nth",[74,1203,1204],{"class":128},"(s, delim, n, if_not_found",[74,1206,159],{"class":124},[74,1208,761],{"class":241},[74,1210,257],{"class":128},[74,1212,1213,1215,1217,1220,1223,1225,1228,1230,1232,1234],{"class":76,"line":132},[74,1214,768],{"class":128},[74,1216,159],{"class":124},[74,1218,1219],{"class":128}," s.str.split(delim, ",[74,1221,1222],{"class":248},"n",[74,1224,159],{"class":124},[74,1226,1227],{"class":128},"n, ",[74,1229,798],{"class":248},[74,1231,159],{"class":124},[74,1233,731],{"class":241},[74,1235,168],{"class":128},[74,1237,1238,1240,1243,1246,1249,1251,1254,1257,1260,1263,1265],{"class":76,"line":146},[74,1239,809],{"class":124},[74,1241,1242],{"class":128}," parts.map(",[74,1244,1245],{"class":124},"lambda",[74,1247,1248],{"class":128}," p: p[n] ",[74,1250,776],{"class":124},[74,1252,1253],{"class":241}," len",[74,1255,1256],{"class":128},"(p) ",[74,1258,1259],{"class":124},">",[74,1261,1262],{"class":128}," n ",[74,1264,782],{"class":124},[74,1266,1267],{"class":128}," if_not_found)\n",[74,1269,1270],{"class":76,"line":153},[74,1271,150],{"emptyLinePlaceholder":149},[74,1273,1274,1276,1279,1281,1283,1285],{"class":76,"line":171},[74,1275,742],{"class":124},[74,1277,1278],{"class":745}," text_before_nth",[74,1280,1204],{"class":128},[74,1282,159],{"class":124},[74,1284,761],{"class":241},[74,1286,257],{"class":128},[74,1288,1289,1291,1293,1295,1297,1299,1301],{"class":76,"line":182},[74,1290,768],{"class":128},[74,1292,159],{"class":124},[74,1294,1219],{"class":128},[74,1296,798],{"class":248},[74,1298,159],{"class":124},[74,1300,731],{"class":241},[74,1302,168],{"class":128},[74,1304,1305,1307,1309,1311,1314,1316,1318,1320,1322,1324,1326],{"class":76,"line":229},[74,1306,809],{"class":124},[74,1308,1242],{"class":128},[74,1310,1245],{"class":124},[74,1312,1313],{"class":128}," p: delim.join(p[:n]) ",[74,1315,776],{"class":124},[74,1317,1253],{"class":241},[74,1319,1256],{"class":128},[74,1321,1259],{"class":124},[74,1323,1262],{"class":128},[74,1325,782],{"class":124},[74,1327,1267],{"class":128},[74,1329,1330],{"class":76,"line":260},[74,1331,150],{"emptyLinePlaceholder":149},[74,1333,1334,1336,1339,1342,1344,1346],{"class":76,"line":272},[74,1335,742],{"class":124},[74,1337,1338],{"class":745}," text_after_ci",[74,1340,1341],{"class":128},"(s, delim, if_not_found",[74,1343,159],{"class":124},[74,1345,761],{"class":241},[74,1347,257],{"class":128},[74,1349,1350,1353,1355],{"class":76,"line":302},[74,1351,1352],{"class":128},"    pos ",[74,1354,159],{"class":124},[74,1356,1357],{"class":128}," s.str.lower().str.find(delim.lower())\n",[74,1359,1360,1362,1365,1367,1369,1372,1374,1377,1380,1383,1386,1389,1391,1394,1396,1399,1402,1404,1406],{"class":76,"line":333},[74,1361,809],{"class":124},[74,1363,1364],{"class":128}," pd.Series([t[i ",[74,1366,294],{"class":124},[74,1368,1253],{"class":241},[74,1370,1371],{"class":128},"(delim):] ",[74,1373,776],{"class":124},[74,1375,1376],{"class":128}," i ",[74,1378,1379],{"class":124},">=",[74,1381,1382],{"class":241}," 0",[74,1384,1385],{"class":124}," else",[74,1387,1388],{"class":128}," if_not_found ",[74,1390,232],{"class":124},[74,1392,1393],{"class":128}," t, i ",[74,1395,238],{"class":124},[74,1397,1398],{"class":241}," zip",[74,1400,1401],{"class":128},"(s, pos)], ",[74,1403,1040],{"class":248},[74,1405,159],{"class":124},[74,1407,1408],{"class":128},"s.index)\n",[74,1410,1411],{"class":76,"line":358},[74,1412,150],{"emptyLinePlaceholder":149},[74,1414,1415,1417,1419,1421,1423,1426,1428,1430,1432,1435,1437],{"class":76,"line":384},[74,1416,924],{"class":128},[74,1418,213],{"class":84},[74,1420,929],{"class":128},[74,1422,159],{"class":124},[74,1424,1425],{"class":128}," text_before(text_after(df[",[74,1427,978],{"class":84},[74,1429,536],{"class":128},[74,1431,983],{"class":84},[74,1433,1434],{"class":128},"), ",[74,1436,983],{"class":84},[74,1438,168],{"class":128},[74,1440,1441,1443,1446,1448,1450,1453,1455,1457,1459,1461,1463],{"class":76,"line":410},[74,1442,924],{"class":128},[74,1444,1445],{"class":84},"\"after 2nd sep\"",[74,1447,929],{"class":128},[74,1449,159],{"class":124},[74,1451,1452],{"class":128}," text_after_nth(df[",[74,1454,978],{"class":84},[74,1456,536],{"class":128},[74,1458,983],{"class":84},[74,1460,38],{"class":128},[74,1462,288],{"class":241},[74,1464,168],{"class":128},[74,1466,1467,1469,1472,1474,1476,1479,1482,1484,1487],{"class":76,"line":436},[74,1468,924],{"class":128},[74,1470,1471],{"class":84},"\"after first a\"",[74,1473,929],{"class":128},[74,1475,159],{"class":124},[74,1477,1478],{"class":128}," text_after_ci(df[",[74,1480,1481],{"class":84},"\"Code\"",[74,1483,536],{"class":128},[74,1485,1486],{"class":84},"\"a\"",[74,1488,168],{"class":128},[74,1490,1491,1493,1495,1497,1499,1501,1503,1505,1507,1509,1511,1513,1515,1517,1519,1521],{"class":76,"line":461},[74,1492,894],{"class":241},[74,1494,1020],{"class":128},[74,1496,978],{"class":84},[74,1498,38],{"class":128},[74,1500,213],{"class":84},[74,1502,38],{"class":128},[74,1504,1445],{"class":84},[74,1506,38],{"class":128},[74,1508,1481],{"class":84},[74,1510,38],{"class":128},[74,1512,1471],{"class":84},[74,1514,1037],{"class":128},[74,1516,1040],{"class":248},[74,1518,159],{"class":124},[74,1520,731],{"class":241},[74,1522,1047],{"class":128},[10,1524,1525,1528,1529,1532,1533,1536,1537,1540],{},[14,1526,1527],{},"str.split(delim, n=2)"," splits at most twice, so element 2 is everything after the second delimiter — ",[14,1530,1531],{},"TEXTAFTER(..., 2)",". The middle field is \"after the first, before the next\", exactly as the nested Excel formula reads. For case-insensitive matching, ",[14,1534,1535],{},"str.find"," on the lower-cased text gives each match's position, and slicing the ",[27,1538,1539],{},"original"," text at that position keeps the original capitals in the result — \"SKU-a-104\" and \"SKU-A-205\" both yield the text after their first \"a\" in any case. (Note that \"SKU\" contains no \"a\", so the first match is the one in the middle.)",[60,1542,1544],{"id":1543},"step-4-textsplit-into-columns-or-into-rows","Step 4 — TEXTSPLIT into columns, or into rows",[10,1546,1547,1550],{},[14,1548,1549],{},"TEXTSPLIT(text, column_delimiter)"," spills values across columns; with a row delimiter, or when the next step is analysis, rows are often the more useful shape:",[65,1552,1554],{"className":115,"code":1553,"language":117,"meta":70,"style":70},"tags_cols = df[\"Tags\"].str.split(\",\", expand=True).apply(lambda c: c.str.strip())\nprint(tags_cols.to_string())\n\ntags_rows = (df.assign(Tag=df[\"Tags\"].str.split(\",\"))\n               .explode(\"Tag\")\n               .assign(Tag=lambda d: d[\"Tag\"].str.strip())\n               .query(\"Tag != ''\")[[\"Email\", \"Tag\"]])\nprint(tags_rows.to_string(index=False))\nprint(tags_rows[\"Tag\"].value_counts().to_dict())\n",[14,1555,1556,1592,1599,1603,1628,1638,1656,1676,1691],{"__ignoreMap":70},[74,1557,1558,1561,1563,1566,1569,1572,1575,1577,1580,1582,1584,1587,1589],{"class":76,"line":77},[74,1559,1560],{"class":128},"tags_cols ",[74,1562,159],{"class":124},[74,1564,1565],{"class":128}," df[",[74,1567,1568],{"class":84},"\"Tags\"",[74,1570,1571],{"class":128},"].str.split(",[74,1573,1574],{"class":84},"\",\"",[74,1576,38],{"class":128},[74,1578,1579],{"class":248},"expand",[74,1581,159],{"class":124},[74,1583,544],{"class":241},[74,1585,1586],{"class":128},").apply(",[74,1588,1245],{"class":124},[74,1590,1591],{"class":128}," c: c.str.strip())\n",[74,1593,1594,1596],{"class":76,"line":132},[74,1595,894],{"class":241},[74,1597,1598],{"class":128},"(tags_cols.to_string())\n",[74,1600,1601],{"class":76,"line":146},[74,1602,150],{"emptyLinePlaceholder":149},[74,1604,1605,1608,1610,1613,1616,1618,1620,1622,1624,1626],{"class":76,"line":153},[74,1606,1607],{"class":128},"tags_rows ",[74,1609,159],{"class":124},[74,1611,1612],{"class":128}," (df.assign(",[74,1614,1615],{"class":248},"Tag",[74,1617,159],{"class":124},[74,1619,924],{"class":128},[74,1621,1568],{"class":84},[74,1623,1571],{"class":128},[74,1625,1574],{"class":84},[74,1627,1047],{"class":128},[74,1629,1630,1633,1636],{"class":76,"line":171},[74,1631,1632],{"class":128},"               .explode(",[74,1634,1635],{"class":84},"\"Tag\"",[74,1637,168],{"class":128},[74,1639,1640,1643,1645,1648,1651,1653],{"class":76,"line":182},[74,1641,1642],{"class":128},"               .assign(",[74,1644,1615],{"class":248},[74,1646,1647],{"class":124},"=lambda",[74,1649,1650],{"class":128}," d: d[",[74,1652,1635],{"class":84},[74,1654,1655],{"class":128},"].str.strip())\n",[74,1657,1658,1661,1664,1667,1669,1671,1673],{"class":76,"line":229},[74,1659,1660],{"class":128},"               .query(",[74,1662,1663],{"class":84},"\"Tag != ''\"",[74,1665,1666],{"class":128},")[[",[74,1668,900],{"class":84},[74,1670,38],{"class":128},[74,1672,1635],{"class":84},[74,1674,1675],{"class":128},"]])\n",[74,1677,1678,1680,1683,1685,1687,1689],{"class":76,"line":260},[74,1679,894],{"class":241},[74,1681,1682],{"class":128},"(tags_rows.to_string(",[74,1684,1040],{"class":248},[74,1686,159],{"class":124},[74,1688,731],{"class":241},[74,1690,1047],{"class":128},[74,1692,1693,1695,1698,1700],{"class":76,"line":272},[74,1694,894],{"class":241},[74,1696,1697],{"class":128},"(tags_rows[",[74,1699,1635],{"class":84},[74,1701,1702],{"class":128},"].value_counts().to_dict())\n",[10,1704,1705,1708,1709,1711,1712,1715,1716,1719,1720,1723,1724,1727,1728,58],{},[14,1706,1707],{},"str.split(\",\", expand=True)"," gives one column per position, padding shorter lists with ",[14,1710,761],{}," — the same rectangle ",[14,1713,1714],{},"TEXTSPLIT"," spills, with Excel's ",[14,1717,1718],{},"pad_with"," behaviour built in. Stripping each piece fixes the inconsistent spaces around commas. For counting or filtering by tag, ",[14,1721,1722],{},"explode"," turns each list into one row per tag, and dropping empty strings removes the record whose tag list was blank. The rows shape is what makes \"how many records are tagged ",[27,1725,1726],{},"tools","?\" a one-liner — two records here, once the stray space in \"logistics \" has been stripped; the columns shape is what a spreadsheet user expects to see. More on this in ",[54,1729,1731],{"href":1730},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fsplit-delimited-cell-values-into-rows-with-pandas\u002F","Split Delimited Cell Values into Rows with pandas",[1081,1733,1090,1739,1090,1742,1090,1745,1090,1750,1090,1758,1090,1762,1090,1768,1090,1772,1090,1776,1090,1778,1090,1782,1090,1785,1090,1787,1090,1789,1090,1793,1090,1796,1090,1800,1090,1802,1090,1805,1090,1809,1090,1814,1090,1819,1090,1822,1090,1825,1090,1829,1090,1833,1090,1837,1090,1840,1090,1843,1090,1845,1090,1847,1090,1850,1090,1853,1090,1855,1090,1858,1090,1861,1090,1865,1090,1867,1090,1869,1090,1875,1090,1879,1090,1885,1090,1890,1090,1897],{"viewBox":1734,"role":1084,"ariaLabelledBy":1735,"xmlns":1088,"style":1738},"72 0 615 196",[1736,1737],"tb-split-t","tb-split-d","width:100%;max-width:615px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[1092,1740,1741],{"id":1736},"TEXTSPLIT into columns, or explode into rows",[1096,1743,1744],{"id":1737},"The tag list garden, tools, sale becomes three columns with str.split and expand, like TEXTSPLIT, or three rows with explode, which is better for counting and filtering tags.",[1100,1746],{"x":1747,"y":815,"width":1748,"height":1749,"fill":1105},"72","615","196",[1100,1751],{"x":1752,"y":1753,"width":1754,"height":1755,"rx":815,"fill":1756,"stroke":1757,"style":1139},"88.9","40.0","32.0","24.0","#e7ebef","var(--line,#cdd5e6)",[1100,1759],{"x":1760,"y":1753,"width":1761,"height":1755,"rx":815,"fill":1756,"stroke":1757,"style":1139},"120.9","123.7",[1128,1763,1767],{"x":1764,"y":1765,"style":1766},"182.7","57.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[1100,1769],{"x":1752,"y":1770,"width":1754,"height":1771,"rx":815,"fill":1756,"stroke":1757,"style":1139},"64.0","28.0",[1128,1773,266],{"x":1774,"y":1775,"style":1766},"104.9","83.0",[1100,1777],{"x":1760,"y":1770,"width":1761,"height":1771,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,1779,1781],{"x":1764,"y":1775,"style":1780},"font-size:10.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Tags",[1100,1783],{"x":1752,"y":1784,"width":1754,"height":1771,"rx":815,"fill":1756,"stroke":1757,"style":1139},"92.0",[1128,1786,288],{"x":1774,"y":1142,"style":1766},[1100,1788],{"x":1760,"y":1784,"width":1761,"height":1771,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,1790,1792],{"x":1764,"y":1142,"style":1791},"font-size:10.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","garden, tools, sale",[1100,1794],{"x":1752,"y":1795,"width":1754,"height":1771,"rx":815,"fill":1756,"stroke":1757,"style":1139},"120.0",[1128,1797,1799],{"x":1774,"y":1798,"style":1766},"139.0","3",[1100,1801],{"x":1760,"y":1795,"width":1761,"height":1771,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,1803,1804],{"x":1764,"y":1798,"style":1791},"cafe",[1100,1806],{"x":1807,"y":1753,"width":1808,"height":1771,"rx":815,"fill":1105,"stroke":1757,"style":1139},"518.6","90.3",[1128,1810,1813],{"x":1811,"y":1812,"style":1780},"563.7","59.0","Email",[1100,1815],{"x":1816,"y":1753,"width":1817,"height":1771,"rx":815,"fill":1756,"stroke":1757,"style":1818},"608.9","62.2","stroke-width:1.5px",[1128,1820,1615],{"x":1821,"y":1812,"style":1780},"640.0",[1100,1823],{"x":1807,"y":1824,"width":1808,"height":1771,"rx":815,"fill":1105,"stroke":1757,"style":1139},"68.0",[1128,1826,1828],{"x":1811,"y":1827,"style":1791},"87.0","ana.ruiz@…",[1100,1830],{"x":1816,"y":1824,"width":1817,"height":1771,"rx":815,"fill":1831,"stroke":1832,"style":1818},"#d9f4f1","var(--teal,#0f9488)",[1128,1834,1836],{"x":1821,"y":1827,"style":1835},"font-size:10.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","garden",[1100,1838],{"x":1807,"y":1839,"width":1808,"height":1771,"rx":815,"fill":1105,"stroke":1757,"style":1139},"96.0",[1128,1841,1828],{"x":1811,"y":1842,"style":1791},"115.0",[1100,1844],{"x":1816,"y":1839,"width":1817,"height":1771,"rx":815,"fill":1831,"stroke":1832,"style":1818},[1128,1846,1726],{"x":1821,"y":1842,"style":1835},[1100,1848],{"x":1807,"y":1849,"width":1808,"height":1771,"rx":815,"fill":1105,"stroke":1757,"style":1139},"124.0",[1128,1851,1828],{"x":1811,"y":1852,"style":1791},"143.0",[1100,1854],{"x":1816,"y":1849,"width":1817,"height":1771,"rx":815,"fill":1831,"stroke":1832,"style":1818},[1128,1856,1857],{"x":1821,"y":1852,"style":1835},"sale",[1100,1859],{"x":1807,"y":1860,"width":1808,"height":1771,"rx":815,"fill":1105,"stroke":1757,"style":1139},"152.0",[1128,1862,1864],{"x":1811,"y":1863,"style":1791},"171.0","ben@…",[1100,1866],{"x":1816,"y":1860,"width":1817,"height":1771,"rx":815,"fill":1831,"stroke":1832,"style":1818},[1128,1868,1804],{"x":1821,"y":1863,"style":1835},[1128,1870,1874],{"x":1871,"y":1872,"style":1873},"166.7","29.0","font-size:12.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","one cell",[1128,1876,1878],{"x":1877,"y":1872,"style":1873},"594.8","rows",[76,1880],{"x1":1881,"y1":1882,"x2":1883,"y2":1882,"stroke":1884,"style":1115},"254.6","94.0","504.6","var(--brand,#5b5cf0)",[1886,1887],"polygon",{"points":1888,"fill":1889},"508.6,94.0 499.6,99.0 499.6,89.0","#5b5cf0",[1100,1891],{"x":1892,"y":1893,"width":1894,"height":1895,"rx":466,"fill":1105,"stroke":1757,"style":1896},"288.0","61.0","187.2","22.0","stroke-width:1.2px",[1128,1898,1902],{"x":1899,"y":1900,"style":1901},"381.6","76.0","font-size:11.5px;font-weight:400;fill:var(--brand-strong,#4338ca);text-anchor:middle;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace","split(expand) \u002F explode",[1081,1904,1090,1909,1090,1912,1090,1915,1090,1918,1090,1921,1090,1926,1090,1932,1090,1935,1090,1939,1090,1943,1090,1947,1090,1949,1090,1954,1090,1956,1090,1959,1090,1962,1090,1966,1090,1968,1090,1971,1090,1973,1090,1976,1090,1978,1090,1982,1090,1984,1090,1988,1090,1990,1090,1993,1090,1996,1090,2000,1090,2002,1090,2006,1090,2008,1090,2011,1090,2014,1090,2018,1090,2020,1090,2024,1090,2026,1090,2028,1090,2031,1090,2035,1090,2037,1090,2041,1090,2043],{"viewBox":1905,"role":1084,"ariaLabelledBy":1906,"xmlns":1088,"style":1089},"4 0 752 276",[1907,1908],"tb-map-t","tb-map-d",[1092,1910,1911],{"id":1907},"Excel text-splitting options and their pandas tools",[1096,1913,1914],{"id":1908},"The first occurrence maps to str.partition, the last to str.rpartition, the nth to str.split with a limit, a case-insensitive match to str.find on a lower-cased copy, splitting into columns to str.split with expand, and splitting into rows to explode. The not-found value is set with where after str.contains.",[1100,1916],{"x":1102,"y":815,"width":1103,"height":1917,"fill":1105},"276",[1100,1919],{"x":1108,"y":1109,"width":1920,"height":1753,"rx":815,"fill":1105,"stroke":1757,"style":1139},"153.9",[1100,1922],{"x":1923,"y":1109,"width":1924,"height":1753,"rx":815,"fill":1925,"stroke":1884,"style":1896},"173.9","283.0","#f0f4ff",[1128,1927,1931],{"x":1928,"y":1929,"style":1930},"315.4","41.0","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Excel",[1100,1933],{"x":1934,"y":1109,"width":1924,"height":1753,"rx":815,"fill":1925,"stroke":1884,"style":1896},"457.0",[1128,1936,1938],{"x":1937,"y":1929,"style":1930},"598.5","pandas",[1100,1940],{"x":1108,"y":1941,"width":1920,"height":1942,"rx":815,"fill":1756,"stroke":1757,"style":1139},"56.0","34.0",[1128,1944,1946],{"x":1754,"y":1131,"style":1945},"font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:start","first delimiter",[1100,1948],{"x":1923,"y":1941,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,1950,1953],{"x":1928,"y":1951,"style":1952},"77.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","TEXTBEFORE(x, d)",[1100,1955],{"x":1934,"y":1941,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,1957,1958],{"x":1937,"y":1951,"style":1952},"str.partition(d)[0]",[1100,1960],{"x":1108,"y":1961,"width":1920,"height":1942,"rx":815,"fill":1756,"stroke":1757,"style":1139},"90.0",[1128,1963,1965],{"x":1754,"y":1964,"style":1945},"112.0","last delimiter",[1100,1967],{"x":1923,"y":1961,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,1969,1970],{"x":1928,"y":1142,"style":1952},"TEXTAFTER(x, d, -1)",[1100,1972],{"x":1934,"y":1961,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,1974,1975],{"x":1937,"y":1142,"style":1952},"str.rpartition(d)[2]",[1100,1977],{"x":1108,"y":1849,"width":1920,"height":1942,"rx":815,"fill":1756,"stroke":1757,"style":1139},[1128,1979,1981],{"x":1754,"y":1980,"style":1945},"146.0","nth delimiter",[1100,1983],{"x":1923,"y":1849,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,1985,1987],{"x":1928,"y":1986,"style":1952},"145.0","TEXTAFTER(x, d, 2)",[1100,1989],{"x":1934,"y":1849,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,1991,1992],{"x":1937,"y":1986,"style":1952},"str.split(d, n=2)[2]",[1100,1994],{"x":1108,"y":1995,"width":1920,"height":1942,"rx":815,"fill":1756,"stroke":1757,"style":1139},"158.0",[1128,1997,1999],{"x":1754,"y":1998,"style":1945},"180.0","ignore case",[1100,2001],{"x":1923,"y":1995,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,2003,2005],{"x":1928,"y":2004,"style":1952},"179.0","match_mode 1",[1100,2007],{"x":1934,"y":1995,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,2009,2010],{"x":1937,"y":2004,"style":1952},"find on str.lower()",[1100,2012],{"x":1108,"y":2013,"width":1920,"height":1942,"rx":815,"fill":1756,"stroke":1757,"style":1139},"192.0",[1128,2015,2017],{"x":1754,"y":2016,"style":1945},"214.0","into columns \u002F rows",[1100,2019],{"x":1923,"y":2013,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,2021,2023],{"x":1928,"y":2022,"style":1952},"213.0","TEXTSPLIT(x, d)",[1100,2025],{"x":1934,"y":2013,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,2027,1902],{"x":1937,"y":2022,"style":1952},[1100,2029],{"x":1108,"y":2030,"width":1920,"height":1942,"rx":815,"fill":1756,"stroke":1757,"style":1139},"226.0",[1128,2032,2034],{"x":1754,"y":2033,"style":1945},"248.0","not found",[1100,2036],{"x":1923,"y":2030,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,2038,2040],{"x":1928,"y":2039,"style":1952},"247.0","#N\u002FA or if_not_found",[1100,2042],{"x":1934,"y":2030,"width":1924,"height":1942,"rx":815,"fill":1105,"stroke":1757,"style":1139},[1128,2044,2045],{"x":1937,"y":2039,"style":1952},"where(contains, default)",[60,2047,2049],{"id":2048},"step-5-check-against-the-spreadsheet","Step 5 — Check against the spreadsheet",[10,2051,2052,2053,2055],{},"Compare every pandas result with the recalculated formulas, treating Excel's ",[14,2054,48],{}," and a missing value as the same:",[65,2057,2059],{"className":115,"code":2058,"language":117,"meta":70,"style":70},"ours = pd.DataFrame({\n    \"user\": df[\"user\"], \"domain\": df[\"domain\"], \"city\": df[\"city\"], \"country\": df[\"country\"], \"middle\": df[\"middle\"],\n    \"user or n\u002Fa\": text_before(df[\"Email\"], \"@\", if_not_found=\"n\u002Fa\"), \"after first a\": df[\"after first a\"],\n})\ndef same(a, b):\n    return (pd.isna(a) and str(b).startswith(\"#\")) or a == b\nchecks = [same(ours.iat[i, j], excel[i][j]) for i in range(len(ours)) for j in range(ours.shape[1])]\nprint(f\"{sum(checks)}\u002F{len(checks)} values match the spreadsheet\")\n",[14,2060,2061,2071,2116,2149,2154,2164,2198,2241],{"__ignoreMap":70},[74,2062,2063,2066,2068],{"class":76,"line":77},[74,2064,2065],{"class":128},"ours ",[74,2067,159],{"class":124},[74,2069,2070],{"class":128}," pd.DataFrame({\n",[74,2072,2073,2076,2079,2081,2083,2085,2087,2089,2091,2093,2095,2097,2099,2101,2103,2105,2107,2109,2111,2113],{"class":76,"line":132},[74,2074,2075],{"class":84},"    \"user\"",[74,2077,2078],{"class":128},": df[",[74,2080,193],{"class":84},[74,2082,536],{"class":128},[74,2084,198],{"class":84},[74,2086,2078],{"class":128},[74,2088,198],{"class":84},[74,2090,536],{"class":128},[74,2092,203],{"class":84},[74,2094,2078],{"class":128},[74,2096,203],{"class":84},[74,2098,536],{"class":128},[74,2100,208],{"class":84},[74,2102,2078],{"class":128},[74,2104,208],{"class":84},[74,2106,536],{"class":128},[74,2108,213],{"class":84},[74,2110,2078],{"class":128},[74,2112,213],{"class":84},[74,2114,2115],{"class":128},"],\n",[74,2117,2118,2121,2124,2126,2128,2130,2132,2134,2136,2139,2141,2143,2145,2147],{"class":76,"line":146},[74,2119,2120],{"class":84},"    \"user or n\u002Fa\"",[74,2122,2123],{"class":128},": text_before(df[",[74,2125,900],{"class":84},[74,2127,536],{"class":128},[74,2129,906],{"class":84},[74,2131,38],{"class":128},[74,2133,665],{"class":248},[74,2135,159],{"class":124},[74,2137,2138],{"class":84},"\"n\u002Fa\"",[74,2140,1434],{"class":128},[74,2142,1471],{"class":84},[74,2144,2078],{"class":128},[74,2146,1471],{"class":84},[74,2148,2115],{"class":128},[74,2150,2151],{"class":76,"line":153},[74,2152,2153],{"class":128},"})\n",[74,2155,2156,2158,2161],{"class":76,"line":171},[74,2157,742],{"class":124},[74,2159,2160],{"class":745}," same",[74,2162,2163],{"class":128},"(a, b):\n",[74,2165,2166,2168,2171,2174,2177,2180,2183,2186,2189,2192,2195],{"class":76,"line":182},[74,2167,809],{"class":124},[74,2169,2170],{"class":128}," (pd.isna(a) ",[74,2172,2173],{"class":124},"and",[74,2175,2176],{"class":241}," str",[74,2178,2179],{"class":128},"(b).startswith(",[74,2181,2182],{"class":84},"\"#\"",[74,2184,2185],{"class":128},")) ",[74,2187,2188],{"class":124},"or",[74,2190,2191],{"class":128}," a ",[74,2193,2194],{"class":124},"==",[74,2196,2197],{"class":128}," b\n",[74,2199,2200,2203,2205,2208,2210,2212,2214,2216,2218,2221,2224,2226,2229,2231,2233,2236,2238],{"class":76,"line":229},[74,2201,2202],{"class":128},"checks ",[74,2204,159],{"class":124},[74,2206,2207],{"class":128}," [same(ours.iat[i, j], excel[i][j]) ",[74,2209,232],{"class":124},[74,2211,1376],{"class":128},[74,2213,238],{"class":124},[74,2215,282],{"class":241},[74,2217,285],{"class":128},[74,2219,2220],{"class":241},"len",[74,2222,2223],{"class":128},"(ours)) ",[74,2225,232],{"class":124},[74,2227,2228],{"class":128}," j ",[74,2230,238],{"class":124},[74,2232,282],{"class":241},[74,2234,2235],{"class":128},"(ours.shape[",[74,2237,266],{"class":241},[74,2239,2240],{"class":128},"])]\n",[74,2242,2243,2245,2247,2249,2252,2254,2257,2260,2262,2265,2267,2269,2271,2273,2276],{"class":76,"line":260},[74,2244,894],{"class":241},[74,2246,285],{"class":128},[74,2248,312],{"class":124},[74,2250,2251],{"class":84},"\"",[74,2253,319],{"class":318},[74,2255,2256],{"class":241},"sum",[74,2258,2259],{"class":128},"(checks)",[74,2261,325],{"class":318},[74,2263,2264],{"class":84},"\u002F",[74,2266,319],{"class":318},[74,2268,2220],{"class":241},[74,2270,2259],{"class":128},[74,2272,325],{"class":318},[74,2274,2275],{"class":84}," values match the spreadsheet\"",[74,2277,168],{"class":128},[10,2279,2280,2281,2283,2284,2286,2287,2289,2290,2264,2293,2264,2296,2299,2300,58],{},"All 28 values — seven formulas for four records — match once a missing value on the pandas side is treated as the counterpart of Excel's ",[14,2282,48],{},", including the not-found case in both its ",[14,2285,48],{}," and ",[14,2288,665],{}," forms. Keeping such a comparison while translating a workbook pays off: text functions have many small options, and the one row where a delimiter is missing or doubled is precisely the row a quick visual check misses. The older ",[14,2291,2292],{},"LEFT",[14,2294,2295],{},"MID",[14,2297,2298],{},"FIND"," style is covered in ",[54,2301,2303],{"href":2302},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fexcel-text-functions-left-right-mid-and-concat-in-pandas\u002F","Excel Text Functions LEFT, RIGHT, MID and CONCAT in pandas",[60,2305,2307],{"id":2306},"common-pitfalls","Common pitfalls",[2309,2310,2311,2325,2334,2348,2354],"ul",{},[2312,2313,2314,2321,2322,58],"li",{},[2315,2316,2317,2318,2320],"strong",{},"Trusting ",[14,2319,37],{}," when the delimiter is missing."," It returns the whole text; check with ",[14,2323,2324],{},"contains",[2312,2326,2327,2330,2331,2333],{},[2315,2328,2329],{},"Regex delimiters."," Pass ",[14,2332,1078],{}," so \".\" and \"|\" are taken literally.",[2312,2335,2336,2339,2340,2343,2344,2347],{},[2315,2337,2338],{},"0-based versus 1-based instances."," ",[14,2341,2342],{},"split(n=2)[2]"," is the text after the ",[27,2345,2346],{},"second"," delimiter.",[2312,2349,2350,2353],{},[2315,2351,2352],{},"Case-insensitive search that changes the text."," Find on a lower-cased copy, slice the original.",[2312,2355,2356,2359],{},[2315,2357,2358],{},"Untrimmed split pieces."," Strip spaces after splitting on commas.",[60,2361,2363],{"id":2362},"conclusion","Conclusion",[10,2365,2366,2286,2369,2372,2373,2375,2376,2378,2379,2381,2382,2384,2385,2388,2389,2391,2392,2395],{},[14,2367,2368],{},"TEXTBEFORE",[14,2370,2371],{},"TEXTAFTER"," map onto ",[14,2374,37],{}," for the first delimiter and ",[14,2377,41],{}," for the last, ",[14,2380,44],{}," with a limit for the nth, and a find on a lower-cased copy for case-insensitive matching; ",[14,2383,1714],{}," maps onto ",[14,2386,2387],{},"str.split(expand=True)"," for columns and ",[14,2390,1722],{}," for rows. The one behaviour to add by hand is Excel's handling of a missing delimiter: test with ",[14,2393,2394],{},"str.contains(regex=False)"," and return a missing value or an explicit default instead of the whole text. Check the translation against the spreadsheet's results, including the rows where the delimiter is absent.",[60,2397,2399],{"id":2398},"frequently-asked-questions","Frequently asked questions",[10,2401,2402,2405],{},[2315,2403,2404],{},"What is the pandas equivalent of TEXTBEFORE?","\nUse str.partition with the delimiter and take the first part for the first occurrence, or str.rpartition for the last. Check with str.contains first, because partition returns the whole text when the delimiter is missing.",[10,2407,2408,2411],{},[2315,2409,2410],{},"How do I get the text after the last delimiter in pandas?","\nUse str.rpartition with the delimiter and take the third part, which corresponds to TEXTAFTER with an instance number of -1.",[10,2413,2414,2417],{},[2315,2415,2416],{},"What happens in pandas when the delimiter is not found?","\nstr.partition puts the whole text in the first part and empty strings in the others. Excel returns #N\u002FA, so replace not-found rows with a missing value or a default to match.",[10,2419,2420,2423],{},[2315,2421,2422],{},"How do I split a cell into rows instead of columns?","\nSplit with str.split into lists, then use DataFrame.explode on that column to get one row per item.",[60,2425,2427],{"id":2426},"related","Related",[2309,2429,2430,2436,2443,2450],{},[2312,2431,2432,2433,2435],{},"Up one level: ",[54,2434,57],{"href":56}," — spreadsheet functions in Python.",[2312,2437,2438,2442],{},[54,2439,2441],{"href":2440},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Ffind-search-and-substitute-equivalents-in-pandas\u002F","FIND, SEARCH and SUBSTITUTE Equivalents in pandas"," — positions and replacements.",[2312,2444,2445,2449],{},[54,2446,2448],{"href":2447},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fregexextract-regextest-and-regexreplace-equivalents-in-pandas\u002F","REGEXEXTRACT, REGEXTEST and REGEXREPLACE Equivalents in pandas"," — patterns instead of fixed delimiters.",[2312,2451,2452,2456],{},[54,2453,2455],{"href":2454},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fsplit-a-column-into-multiple-columns-with-pandas\u002F","Split a Column into Multiple Columns with pandas"," — the same task from the cleaning side.",[2458,2459,2460],"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 .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}",{"title":70,"searchDepth":132,"depth":132,"links":2462},[2463,2464,2465,2466,2467,2468,2469,2470,2471,2472],{"id":62,"depth":132,"text":63},{"id":108,"depth":132,"text":109},{"id":677,"depth":132,"text":678},{"id":1185,"depth":132,"text":1186},{"id":1543,"depth":132,"text":1544},{"id":2048,"depth":132,"text":2049},{"id":2306,"depth":132,"text":2307},{"id":2362,"depth":132,"text":2363},{"id":2398,"depth":132,"text":2399},{"id":2426,"depth":132,"text":2427},"2026-10-02","Reproduce Excel's TEXTBEFORE, TEXTAFTER and TEXTSPLIT in pandas: text before or after the first, nth or last delimiter, case-insensitive matching, the crucial difference when the delimiter is missing (Excel returns #N\u002FA, str.partition returns the whole text), splitting into columns and into rows, and a check of every case against the spreadsheet functions.","md",[2477,2479,2481,2483],{"q":2404,"a":2478},"Use str.partition with the delimiter and take the first part for the first occurrence, or str.rpartition for the last. Check with str.contains first, because partition returns the whole text when the delimiter is missing.",{"q":2410,"a":2480},"Use str.rpartition with the delimiter and take the third part, which corresponds to TEXTAFTER with an instance number of -1.",{"q":2416,"a":2482},"str.partition puts the whole text in the first part and empty strings in the others. Excel returns #N\u002FA, so replace not-found rows with a missing value or a default to match.",{"q":2422,"a":2484},"Split with str.split into lists, then use DataFrame.explode on that column to get one row per item.","textbefore textafter and textsplit equivalents in pandas",null,{"breadcrumb":2488},[2489,2491,2494],{"name":2490,"item":2264},"Home",{"name":2492,"item":2493},"Advanced Data Transformation and Cleaning for Excel Automation","\u002Fadvanced-data-transformation-and-cleaning\u002F",{"name":57,"item":56},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Ftextbefore-textafter-and-textsplit-equivalents-in-pandas",{"title":5,"description":2497},"Excel TEXTBEFORE, TEXTAFTER and TEXTSPLIT in pandas: partition, rpartition and split with n, nth and last occurrences, case-insensitive matches, missing delimiters handled like #N\u002FA, and spreadsheet-verified results.","textbefore-textafter-and-textsplit-equivalents-in-pandas","advanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Ftextbefore-textafter-and-textsplit-equivalents-in-pandas\u002Findex",[2501],"formula-equivalents","how-to","4PABxM84Br7isZ6-LqxBz9c-czfd-gcsKv6knAwt_kY",[2505,2509],{"title":2506,"path":2507,"stem":2508,"children":-1},"SUMPRODUCT and Weighted Averages in pandas","\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsumproduct-and-weighted-average-in-pandas","advanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fsumproduct-and-weighted-average-in-pandas\u002Findex",{"title":2510,"path":2511,"stem":2512,"children":-1},"TEXTJOIN Equivalent in pandas (Join Values per Group)","\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Ftextjoin-equivalent-in-pandas","advanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Ftextjoin-equivalent-in-pandas\u002Findex",[2514,2516],{"path":2515,"title":57},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas",{"path":2517,"title":2492},"\u002Fadvanced-data-transformation-and-cleaning",[],[2520,2523,2526,2529,2532,2535],{"path":2521,"title":2522,"kind":2502},"\u002Fadvanced-data-transformation-and-cleaning\u002Fmerging-and-joining-excel-dataframes\u002Fvlookup-equivalent-in-pandas-for-excel-files","The VLOOKUP Equivalent in pandas for Excel Files",{"path":2524,"title":2525,"kind":2502},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fextract-numbers-and-codes-from-text-with-pandas","Extract Numbers and Codes from Text with pandas",{"path":2527,"title":2528,"kind":2502},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fsplit-full-names-into-first-and-last-names-with-pandas","Split Full Names into First and Last Names with pandas",{"path":2530,"title":2531,"kind":2502},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fbin-values-into-ranges-with-pandas-cut","Bin Values into Ranges Like Excel FREQUENCY with pd.cut",{"path":2533,"title":2534,"kind":2502},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fcalculate-percent-of-total-per-group-in-pandas","Calculate Percent of Total per Group in pandas",{"path":2536,"title":2537,"kind":2502},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fcount-distinct-values-per-group-in-pandas","Count Distinct Values per Group in pandas",1790972088748]