How to apply regex over all the rows of a dataset?

Viewed 269

I have a dataset as follow:

    data = {"C1" : ['DDDSSDSSDS','SSDDDSSDDS', 
   'DDDDDDDDDD','SSSSSSSSSS','SSSSSSSDSS','DDDDDSDDDD','SDDDDDDDDD']}
    dt = pd.DataFrame(data)
    print(dt)

For each string I want to get the positions of first element and last element of each "Uninterrupted S groups". For example, for first row I have 'DDDSSDSSDS' (as you see I have three groups of S) and my favorite output for this "S group"s is something like [(3,5),(6,8),(9-10)] which shows the positions for first and second and third "uninterrupted S groups" in first row.

So an example of output could be as:

           C1                         C2
0  DDDSSDSSDS       [(3, 5), (6, 8), (9-10)]
1  SSDDDSSDDS  [(0, 2), (5, 7), (9, 10)]
2  DDDDDDDDDD                         []
3  SSSSSSSSSS                  [(1, 11)]
4  SSSSSSSDSS          [(0, 7), (8, 10)]
5  DDDDDSDDDD                   [(5, 6)]
6  SDDDDDDDDD                   [(0, 1)]

My current solution is:

def split_it(mystring):
    x = re.findall('(S*)', mystring)
    if x :
      return(x)

dt['C2'] = dt['C1'].apply(split_it)
print(dt)

which leads to the following output:

0  DDDSSDSSDS  [, , , SS, , SS, , S, ]
1  SSDDDSSDDS  [SS, , , , SS, , , S, ]
2  DDDDDDDDDD   [, , , , , , , , , , ]
3  SSSSSSSSSS           [SSSSSSSSSS, ]
4  SSSSSSSDSS        [SSSSSSS, , SS, ]
5  DDDDDSDDDD  [, , , , , S, , , , , ]
6  SDDDDDDDDD  [S, , , , , , , , , , ]
2 Answers

You can use

def split_it(mystring):
    return [(m.start(), m.end()) for m in re.finditer('S+', mystring)]

Output:

>>> dt['C1'].apply(split_it)
0    [(3, 5), (6, 8), (9, 10)]
1    [(0, 2), (5, 7), (9, 10)]
2                           []
3                    [(0, 10)]
4            [(0, 7), (8, 10)]
5                     [(5, 6)]
6                     [(0, 1)]
Name: C1, dtype: object

The re.finditer('S+', mystring) returns all match objects found in the string and you may get the start and end positions via .start() and .end() calls.

Note you got empty matches in your output because S* matches zero or more S chars, you need to use + to match one or more.

You can apply regex using findall:

(
    dt
    .assign(C2= lambda x: x['C1'].str.findall('S+'))
    .assign(C2= lambda x: x.apply(lambda s: [(s[0].find(item),s[0].find(item)+len(item)) for item in s[1]] ,axis=1))
)

           C1                        C2
0  DDDSSDSSDS  [(3, 5), (3, 5), (3, 4)]
1  SSDDDSSDDS  [(0, 2), (0, 2), (0, 1)]
2  DDDDDDDDDD                        []
3  SSSSSSSSSS                 [(0, 10)]
4  SSSSSSSDSS          [(0, 7), (0, 2)]
5  DDDDDSDDDD                  [(5, 6)]
6  SDDDDDDDDD                  [(0, 1)]
Related