0

I have the below array Object which is essentially time in hours, minutes and seconds. I want to convert this object into minutes but am getting an error. The error seem to be due to different string lengths while unpacking .split method result. Any suggestions?

df6['Chip Time']
0         16:42
1         17:34
2         18:13
3         18:32
4         19:12
         ...   
1453    1:35:08
1454    1:43:41
1455    1:45:36
1456    1:45:40
1457    1:48:13
Name: Chip Time, Length: 1458, dtype: object

time_list = df6['Chip Time'].tolist()
# You can use a for loop to convert 'Chip Time' to minutes
time_mins = []
for i in time_list:
    h,m,s = i.split(':')
    math = (int(h)*3600+int(m)*60+int(s))/60
    time_mins.append(math)
print(time_mins)

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-52-ac7d4ab91169> in <module>
      3 time_mins = []
      4 for i in time_list:
----> 5     h,m,s = i.split(':')
      6     math = (int(h)*3600+int(m)*60+int(s))/60
      7     time_mins.append(math)

ValueError: not enough values to unpack (expected 3, got 2)
Srinivas
  • 568
  • 1
  • 4
  • 21

3 Answers3

2

Take a look at the first few rows. Let's say 2nd row 17:34. This is what happens when you split it.

In [1]: "17:34".split(":")
Out[1]: ['17', '34']

As you can see there are only 2 values because you have only one : and you are trying to unpack it to 3 variables h,m,s what can not be done.

You have several options to overcome this problem.

  1. You could format your data differently and always include hours so 17:34 -> 0:17:34
  2. You could handle 2 cases in your parser
values = i.split(':')
if len(values) == 2:
    h = 0
    m,s = values
else:
   h,m,s = values
  1. You could use regex but I would not recommend it as it is less readable then other options
Quba
  • 4,776
  • 7
  • 34
  • 60
1

You can add 0: if length of strins is 5 by Series.mask and Series.str.len, then connvert column to timedeltas by to_timedelta, get seconds by Series.dt.total_seconds and divide 60:

s = df6['Chip Time'].mask(df6['Chip Time'].str.len().eq(5), '0:' + df6['Chip Time'])
df6['min'] = pd.to_timedelta(s).dt.total_seconds() / 60
print (df6)
     Chip Time         min
0        16:42   16.700000
1        17:34   17.566667
2        18:13   18.216667
3        18:32   18.533333
4        19:12   19.200000
1453   1:35:08   95.133333
1454   1:43:41  103.683333
1455   1:45:36  105.600000
1456   1:45:40  105.666667
1457   1:48:13  108.216667

Details:

print (s)
0       0:16:42
1       0:17:34
2       0:18:13
3       0:18:32
4       0:19:12
1453    1:35:08
1454    1:43:41
1455    1:45:36
1456    1:45:40
1457    1:48:13
Name: Chip Time, dtype: object
jezrael
  • 822,522
  • 95
  • 1,334
  • 1,252
1

using a little bit of input from this answer, you could also obtain the total seconds of your timestamps as

def timestring_to_seconds(ts, sep=':'):  
    return sum(x * int(t) for x, t in zip((1,60,3600), reversed(ts.split(sep))))

ts = '00:04:23'
print(timestring_to_seconds(ts))
# 263

ts = '04:23'
print(timestring_to_seconds(ts))
# 263

ts = '23'
print(timestring_to_seconds(ts))
# 23

Note that this works even if there are only seconds (no minutes or hours) provided in the timestring. Of course you can include / 60 if you want minutes instead. And you can map the function to a df column:

import pandas as pd
df = pd.DataFrame({'Chip Time': ['00:04:23', '04:23', '23']})
df['s'] = df['Chip Time'].map(timestring_to_seconds)
# df
#   Chip Time    s
# 0  00:04:23  263
# 1     04:23  263
# 2        23   23
FObersteiner
  • 22,500
  • 8
  • 42
  • 72