0

The following function:

def func(x):
    for k in x['slices']:
        for j in k:
            print(x['low'].iloc[j]) 

applied in the following manner works:

func(test)

but as follow doesn't:

test.apply(func, axis=1)

Would you be able to determine why?


EDIT: I used the print only for debug purpose: the function used to be :

def func(x):
    result=[]
    for k in x:
        for j in k:    
            result.append(x['low'].iloc[j])
    return result

which also didn't work

Below the elements to reconstructs the data.

df = pd.DataFrame(dict, columns=["low", "slices"])

   dict = {'low': {0: 1207.25,
      1: 1207.5,
      2: 1205.75,
      3: 1206.0,
      4: 1201.0,
      5: 1202.75,
      6: 1203.75},
     'slices': {0: [slice(1, 2, None)],
      1: [slice(1, 3, None), slice(2, 3, None)],
      2: [slice(1, 4, None), slice(2, 4, None), slice(3, 4, None)],
      3: [slice(1, 5, None),
       slice(2, 5, None),
       slice(3, 5, None),
       slice(4, 5, None)],
      4: [slice(1, 6, None),
       slice(2, 6, None),
       slice(3, 6, None),
       slice(4, 6, None),
       slice(5, 6, None)],
      5: [slice(1, 7, None),
       slice(2, 7, None),
       slice(3, 7, None),
       slice(4, 7, None),
       slice(5, 7, None),
       slice(6, 7, None)],
      6: [slice(1, 8, None),
       slice(2, 8, None),
       slice(3, 8, None),
       slice(4, 8, None),
       slice(5, 8, None),
       slice(6, 8, None),
       slice(7, 8, None)]}}
jim jarnac
  • 4,804
  • 11
  • 51
  • 88
  • What is the observed behavior when you use apply? Does it throw an error? Does it print empty strings? More information will help to answer the question. – Apollo2020 Jan 03 '17 at 23:26
  • @dave When using the apply() the error returned is: `an integer is required` and `KeyError: ('slices', 'occurred at index slices')`. Note that when using `func(test)`, it returns the correct output with no error message. – jim jarnac Jan 03 '17 at 23:31
  • @jimbasquiat What do you expect the outcome to look like, a new `Series` containing lists from the slices? – Moses Koledoye Jan 03 '17 at 23:33
  • @MosesKoledoye yes the output looks something like that: `1 1207.5 Name: low, dtype: float64 1 1207.50 2 1205.75 Name: low, dtype: float64 2 1205.75 Name: low, dtype: float64 1 1207.50 2 1205.75 3 1206.00 Name: low, dtype: float64 2 1205.75 3 1206.00 Name: low, dtype: float64 3 1206.0 Name: low, dtype: float64 1 1207.50 2 1205.75 3 1206.00 4 1201.00` I didnt post it at first as it is quite long. Yes it is Series based on the slices – jim jarnac Jan 03 '17 at 23:38
  • 1
    `.apply` does not work like so. `print` returns None and the output you have is not valid `Series` object – Moses Koledoye Jan 03 '17 at 23:40
  • @Moses Koledoye please see my edit – jim jarnac Jan 03 '17 at 23:49

1 Answers1

2

define your function this way

def fun(slices):
    return [df.low.loc[s].tolist() for s in slices]

And apply over the slices column

df['slices_low'] = df.slices.apply(fun)

df

enter image description here

piRSquared
  • 285,575
  • 57
  • 475
  • 624
  • no i cannot change so drastically the function. I want to understand why `func(test)` and `test.apply(func)` are different. I dont understand why you say that *test.apply(func, axis=0) is equivalent to calling func(test['low']) then calling func(test['slices']) separately.* For me that would be true of `map` but not of `apply`. `apply` considers each row as a Series, no? – jim jarnac Jan 03 '17 at 23:59
  • no! `apply` treats each column as a series unless you pass `axis=1`. The `axis` parameter tells `apply` which axis to use as the index of the series. If `axis=0` the row indices will be used as the index and that means columns are the objects that are being passed to the `apply` function. – piRSquared Jan 04 '17 at 00:08
  • yes i think `axis=1` is the first thing i tried actually. But it should work though right? it returns `TypeError: ("'slice' object is not iterable", 'occurred at index 0')` Sorry i'm confused i tried so many things... – jim jarnac Jan 04 '17 at 00:09
  • No again. Your function anticipates a dataframe hence the double loop. You iterate through each element in the slices column, then through each slice. Understand that when you use apply, `pd.Series` objects are passed to the function. That means that `x['slices']` is already the list of slices you are looking for. You don't want to iterate again. – piRSquared Jan 04 '17 at 00:12
  • Also, when you slice within the function, you are slicing the object that is passed to the function and not the dataframe in the outer scope. That means will get another error or not get the full slices you are looking for. My sincerest advice is to look for another way or rewrite that function. Sometimes questions like "This should work, why doesn't it work?" Should be "I'm trying to accomplish this, how do I do it?" – piRSquared Jan 04 '17 at 00:15
  • Please have a look...http://stackoverflow.com/questions/41454751/python-pandas-table-manipulation-with-slices-as-variables – jim jarnac Jan 04 '17 at 01:14