Jason
Jason

Reputation: 467

Too many values to unpack using apply()

Here is the code I have:

def f(row):
  if row['CountInBedDate'] == 1 and row['CountOutBedDate'] == 1:
    SleepDate = row['DateInBed']
    InBedTimeFinal = row['InBedTime']
    OutBedTimeFinal = row['OutBedTime']
  else:
    SleepDate = -1
    InBedTimeFinal = -1
    OutBedTimeFinal = -1
  return SleepDate, InBedTimeFinal, OutBedTimeFinal

s1['SleepDate'], s1['InBedTimeFinal'], s1['OutBedTimeFinal'] = s1.apply(f, axis=1)

I would like to create 3 new columns with apply() but there is

ValueError: too many values to unpack (expected 3)

If I use this, only one column was created with 3 values combined:

s1['SleepDate', 'InBedTimeFinal', 'OutBedTimeFinal'] = s1.apply(f, axis=1)

Could you please help? Thanks.

Upvotes: 0

Views: 817

Answers (2)

Andy L.
Andy L.

Reputation: 25259

Your function f returns tuple for each row, so apply stacks tuples to series. You need f return series and unpack on ndarray of the result of apply

def f(row):
  if row['CountInBedDate'] == 1 and row['CountOutBedDate'] == 1:
    SleepDate = row['DateInBed']
    InBedTimeFinal = row['InBedTime']
    OutBedTimeFinal = row['OutBedTime']
  else:
    SleepDate = -1
    InBedTimeFinal = -1
    OutBedTimeFinal = -1
  return pd.Series([SleepDate, InBedTimeFinal, OutBedTimeFinal]) #change here

s1['SleepDate'], s1['InBedTimeFinal'], s1['OutBedTimeFinal'] = s1.apply(f, axis=1).T.values

Upvotes: 1

Ben.T
Ben.T

Reputation: 29635

if f is your real function, then you should consider using where instead of apply, it will be way faster.

s1[['SleepDate', 'InBedTimeFinal', 'OutBedTimeFinal']] = \
           s1[['DateInBed','InBedTime','OutBedTime']].where(s1['CountInBedDate'].eq(1), other=-1)

Note it seems that in your function you check twice that CountInBedDate is equal to 1

If you want to use apply, then you can try:

s1[['SleepDate', 'InBedTimeFinal', 'OutBedTimeFinal']] = \
               pd.DataFrame(s1.apply(f, axis=1).tolist(), s1.index)

Upvotes: 2

Related Questions