Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Extracting maximum number from DataFrame of strings (and some NaN values)

Look at the DataFrame:

import pandas as pd
import numpy as np
data=pd.DataFrame(['random 15 numbers 128 and 12 letters','12-5','page 65'],columns=['text'])

enter image description here

I want to extract all numbers from the strings and write the maximum number into a new column. I achieved that with this code:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

data['list']=data['text'].str.extractall('(\d+)').unstack().values.tolist()
data['max']=data['list'].apply(lambda row:max([int(x) for x in row if x is not np.nan]))

This results in this DataFrame:

enter image description here

First question: Is there a more elegant way to do that?

My actual problem: My code works only if there is no NaN value in my original DataFrame. How would you adapt the code in that case? The result should be a NaN column for each NaN value with the correct index. Replace the data defining line by the following to make the problem appear:

data=pd.DataFrame(['random 15 numbers 128 and 12 letters','12-5','page 65',np.nan],columns=['text'])

Additionally I want to deal the code with entrys which are not NaN but strings without a number. In that case the intermediate list should be empty and the last row should be NaN (this last thing is easy to achive by manipulating the last line).

>Solution :

Don’t use a list as intermediate, directly go with a groupby.max:

data['max'] = (data['text']
              .str.extractall('(\d+)')[0]
              .astype(int)
              .groupby(level=0).max()
              )

Output:

                                   text    max
0  random 15 numbers 128 and 12 letters  128.0
1                                  12-5   12.0
2                               page 65   65.0
3                                   NaN    NaN

If you need both the list and the max:

g = (data['text']
     .str.extractall('(\d+)')[0]
     .astype(int)
     .groupby(level=0)
     )

data['list'] = g.agg(list)
data['max'] = g.max()

Output:

                                   text           list    max
0  random 15 numbers 128 and 12 letters  [15, 128, 12]  128.0
1                                  12-5        [12, 5]   12.0
2                               page 65           [65]   65.0
3                                   NaN            NaN    NaN
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading