Splitting at Underscore in Python and Storing the First Value

Splitting at Underscore in Python and Storing the First Value

I have a pandas data frame like df with a column construct_name

construct_name
aaaa_t1_2    
cccc_t4_10
bbbb_g3_3

and so on. I want to first split all the names at the underscore and store the first element (aaaa,cccc, etc.) as another column name.

Expected output

construct_name  name
aaaa_t1_2       aaaa
cccc_t4_10      bbbb

and so on.

I tried the following df['construct_name'].map(lambda row:row.split("_")) and it gives me a list like

[aaaa,t1,2]
[cccc,t4,10]

and so on

But when I do

df['construct_name'].map(lambda row:row.split("_"))[0] to get the first element of the list I get an error. Can you suggest a fix. Thanks

5 Answers

Just use the vectorised str method split and use integer indexing on the list to get the first element:

In [228]:

df['first'] = df['construct_name'].str.split('_').str[0]
df
Out[228]:
  construct_name first
0      aaaa_t1_2  aaaa
1     cccc_t4_10  cccc
2      bbbb_g3_3  bbbb
df['name'] = df['construct_name'].str.split('_').str.get(0)

or

df['name'] = df['construct_name'].str.split('_').apply(lambda x: x[0])

After you do the split, you should get the first element (using [0]). And not after the map.:

In [608]: temp['name'] = temp['construct_name'].map(lambda v: v.split('_')[0])

In [609]: temp
Out[609]: 
  construct_name  name
0      aaaa_t1_2  aaaa
1     cccc_t4_10  cccc
2      bbbb_g3_3  bbbb

Another way of using the vectorised str.split method is passing the expand=True flag which then returns one column for each of the split parts.

>>> s = pd.Series( ['aaaa_t1_2', 'cccc_t4_10', 'bbbb_g3_3'], name='construct_name')

>>> s.str.split('_', expand=True)  # to see what expand=True does
      0   1   2
0  aaaa  t1   2
1  cccc  t4  10
2  bbbb  g3   3

>>>  s.str.split('_', expand=True)[0]  # what you want, select first elements
0    aaaa
1    cccc
2    bbbb

This would be specially useful if you wanted to keep the first and second values for example.

In terms of the general behaviour of the expand=True flag, note that if the input strings do not have the same number of underscores you ca get Nones:

>>> s = pd.Series( ['aaaa_t1_2', 'cccc_t4', 'bbbb_g33'], name='construct_name')

>>> s.str.split('_', expand=True)
      0    1     2
0  aaaa   t1     2
1  cccc   t4  None
2  bbbb  g33  None

split take an optional argument maxsplit:

>>> construct_name = 'aaaa_t1_2'
>>> name, rest = construct_name.split('_', 1)
>>> name
'aaaa'
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

James H. Sterling
Author

James H. Sterling

James Sterling reports on renewable energy developments, climate policy, ecological conservation, and green tech innovations around the globe.