Billy
Billy

Reputation: 7

PANDAS - Inserting additional columns and Values based off another column

I have a Dataframe, with a "time in seconds" column. Which looks like the following:

   Number    Seconds      Col[2] Col[3] ... Col[n]  
0    1      57047.9293      v2     v3   ...  vn 
1    2      57048.9824      --     --        --
...
m

I am attempting to insert additional columns before the Seconds for Hours and Minutes. So it looks like so:

   Number  Hour  Min    Sec  
0     1      15    50   47.9293   ... vn
1     2      15    50   48.9824   ... vn

I am receiving the following errors with the code below

How can I resolve this properly, and is there a better way than to make multiple calls to df.insert()?

import datetime

def convertSecondsto_(time, value):

  fullTime = str(datetime.timedelta(seconds=value)).split(':')

  if time == 1 # Getting Hour Value
    value = fullTime[0]

  if time == 2 # Getting Minute Value
    value = fullTime[1]

  if time == 3 # Getting Second Value
    value == f'{float(fullTime[2]):.4f}' # only 4 Decimal places

  return value

df.insert(1, "Hour", convertSecondsto_(1, df["Seconds"])))

#TypeError: unsupported type for timedelta seconds component: Series

df.insert(1, "Hour", convertSecondsto_(1, float(df["Seconds"]))))

#TypeError: cannot convert the series to <class 'float'>

Upvotes: 0

Views: 351

Answers (3)

Naveed
Naveed

Reputation: 11650

here is one way to do it

df['hour'] = pd.to_datetime(df["Seconds"], unit='s').dt.hour
df['min'] = pd.to_datetime(df["Seconds"], unit='s').dt.minute
df['sec'] = df['Seconds'] - ((df['hour']*3600) + (df['min'] * 60))


# rearrange the columns to bring it before the seconds
df.insert(1,'hour', df.pop('hour'))
df.insert(2,'min', df.pop('min'))
df.insert(3,'sec', df.pop('sec'))
df.drop(columns='Seconds')
    Number  hour    min     sec     Col[2]  Col[3]  Col[n]
0       1   15       50     47.9293     v2    v3    vn
1       2   15       50     48.9824     --    --    --

Upvotes: 1

SergFSM
SergFSM

Reputation: 1491

you can also do something like this:

df[['hour','min','sec']] = pd.to_timedelta(df['seconds'],unit='s').astype(str).str[7:-2].str.split(':',expand=True)

>>> df
'''
      seconds hour min      sec
0  57047.9293   15  50  47.9293
1  57048.9824   15  50  48.9824

Upvotes: 0

atif_sreezon
atif_sreezon

Reputation: 74

The function convertSecondsto_ takes a float value as argument. But it's receiving a series from the insert method. You need to change the function to convert every value in the series and produce a list that can be inserted in the dataframe.

def convertSecondsto_(time, value):
    convertedTime = []
    for seconds in value:
        fullTime = str(datetime.timedelta(seconds=seconds)).split(':')
        if time == 1: # Getting Hour Value
            convertedTime.append(fullTime[0])
        if time == 2: # Getting Minute Value
            convertedTime.append(fullTime[1])
        if time == 3: # Getting Second Value
            convertedTime.append(f'{float(fullTime[2]):.4f}') # only 4 Decimal places

    return convertedTime


df.insert(1, "Hour", convertSecondsto_(1, df["Seconds"]))
df.insert(2, "Min", convertSecondsto_(2, df["Seconds"]))
df.insert(3, "Sec", convertSecondsto_(3, df["Seconds"]))

This works as intended.

Upvotes: 1

Related Questions