0

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.

Jason
  • 467
  • 2
  • 4
  • 12
  • Could you give more information about `s1`? Looks like `s1.apply(f, axis=1)` returns more that 3 values. – maciek97x Jun 03 '20 at 23:00
  • s1 is a dataframe with many columns – Jason Jun 03 '20 at 23:02
  • Does this answer your question? [Pandas DataFrame apply() ValueError: too many values to unpack (expected 2)](https://stackoverflow.com/questions/35373223/pandas-dataframe-apply-valueerror-too-many-values-to-unpack-expected-2) – Trenton McKinney Jun 03 '20 at 23:18

2 Answers2

2

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)
Ben.T
  • 29,160
  • 6
  • 32
  • 54
  • Thank you. My mistake. I have changed that to CountOutBedDate. I would like to use if else because I will add other conditions to the codes. This is just a small part of it. – Jason Jun 03 '20 at 23:12
1

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
Andy L.
  • 24,909
  • 4
  • 17
  • 29