split string row wise with condition in python

Viewed 141

I have some strings in a column and I want to explode the words out only if they are not within brackets. The column looks like this

pd.DataFrame(data={'a': ['first,string','(second,string)','third,string (another,string,here)']})

and I want the output to look like this

pd.DataFrame(data={'a': ['first','string','(second,string)','third','string','(another,string,here)']})

This sort of works, but i would like to not have to put the row number in each time

re.split(r',(?![^()]*\))', x['a'][0])
re.split(r',(?![^()]*\))', x['a'][1])
re.split(r',(?![^()]*\))', x['a'][2])

i thought i could do with a lmbda function but i cannot get it to work. Thanks for checking this out

x['a'].apply(lambda i: re.split(r',(?![^()]*\))', i))
1 Answers

It is not clear to me if the elements in your DataFrame may have multiple groups between brackets. Given that doubt, I have implemented the following:

import pandas as pd
import re

df = pd.DataFrame(data={'a': ['first,string','(second,string)','third,string (another,string,here)']})

pattern = re.compile("([^\(]*)([\(]?.*[\)]?)(.*)", re.IGNORECASE)

def findall(ar, res = None):
    if res is None:
        res = []
    m = pattern.findall(ar)[0]
    if len(m[0]) > 0:
        res.extend(m[0].split(","))
    if len(m[1]) > 0:
        res.append(m[1])
    if len(m[2]) > 0:
        return findall(ar[2], res = res)
    else:
        return res
    
res = []
for x in df["a"]:
    res.extend(findall(x))
    
print(pd.DataFrame(data={"a":res}))

Essentially, you recursively scan the last part of the match until you find no more words between strings. If order was not an issue, the solution is easier.

Related