How to convert a string of hours and minutes to minutes in python?

Viewed 1623

I have a column in my dataframe df:

Time
2 hours 3 mins
5 hours 10 mins
1 hour 40 mins

I want to create a new column in df 'Minutes' that converts this column over to minutes

Minutes
123
310
100

Is there a python function to do this?

7 Answers

You need to convert it via to_datetime

s=pd.to_datetime(df.Time.replace({'hours':'hour'},regex=True),format='%H hour %M mins')
s.dt.hour*60+s.dt.minute
Out[406]: 
0    123
1    310
2    100
Name: Time, dtype: int64

Or we using str.findall with numpy dot

np.dot(np.array(df.Time.str.findall('\d+').tolist()).astype(int),[60,1])
Out[420]: array([123, 310, 100])

Fun with pd.eval

df['Minutes'] = pd.eval(
    df['Time'].replace(['hours?', 'mins'], ['*60+', ''], regex=True))
df
              Time Minutes
0   2 hours 3 mins     123
1  5 hours 10 mins     310
2   1 hour 40 mins     100

The idea is to have replace convert this into a mathematical expression, then have pandas evaluate it:

expr = df['Time'].replace(['hours?', 'mins'], ['* 60 +', ''], regex=True)
expr

0    2 * 60 +  3 
1    5 * 60 + 10 
2    1 * 60 + 40 
Name: Time, dtype: object

pd.eval(expr)
# array([123, 310, 100], dtype=object)

str.extract and multiplication

((df['Time'].str.extract(r'(\d+) hour.*?(\d+) min').astype(int) * [60, 1])
            .sum(axis=1))

0    123
1    310
2    100
dtype: int64

Write a simple regex to extract the digits, then convert to minutes using simple arithmetic. You can shorten the pattern to

(df['Time'].str.extract(r'(\d+)\D*(\d+)').astype(int) * [60, 1]).sum(axis=1)

0    123
1    310
2    100
dtype: int64

As per @Quang Hoang's suggestion.

"Is there a python function to do this?" not until you write one ...

def to_minutes(time_string):
    hours, _, minutes, _ = time_string.split(' ')
    return int(hours) * 60 + int(minutes)

Result should look something like:

>>> to_minutes('2 hours 3 mins')
123

I believe you can convert to timedelta and cast to timedelta64[m]:

pd.to_timedelta(df.Time.str.replace('mins', 'm'), unit='m').astype('timedelta64[m]')

Out[786]:
0    123.0
1    310.0
2    100.0
Name: Time, dtype: float64

If you fancy lambda functions you can also use:

df.Time.apply(lambda x: sum(np.array([ int(i) for i in re.match(r'(\d+) hour[s]? (\d+) min[s]?', x).groups()]) * [60, 1]))

assuming the Time column is always in the same format (same amount of spaces) you can use -

def Mins(row):
    return int(row['Time'].split(' ')[0])*60 + int(row['Time'].split(' ')[2])

df.apply(Mins,axis=1)

I don't think there is a built in function, but you can build one, and then use it in pandas with .apply().

It might not be the shortest answer, but it will let you understand how to use basic Python functions with Pandas. I think it's very helpful!

The function I built:

import re

def calculate_number_of_minutes(hours_string):
    regex = '\d+( )\w+'
    // I build a regex which can find a sequence of digits and a single word


    result = re.finditer(regex, text, re.DOTALL)
    // I find such patterns in the given string

    minutes = 0
    for element in result:
        fragment = element.group()

        if 'hour' in fragment:
            minutes += int(re.search('\d+', fragment).group()) * 60
            // if there are 'hours', the associated number is multiplied by 60
            // and added to the count
        else:
            minutes += int(re.search('\d+', fragment).group())

    return minutes


text = '5 hours 10 mins'
print(calculate_number_of_minutes(text))

What it does is search your string for numbers, then count the minute counts.

In order to apply it to your column, try this:

data.loc[;, 'Time'] = data['Time'].apply(lambda x: calculate_number_of_minutes(x))

Hope it's useful ;)

Related