3

I need to calculate two interdependent values at the same time. The problem is that a and b depend on the previous value of a and b. So we need to calculate them simultaneously while referring to the last calculated values of the loop. What I have so far is this:

   x = df.x # just a list containing randomly 1 and 0
   df['a']=100 # 100 is just the starting value for a and b and shall be then overwritten by the while loop
   df['b']=100
   i=1    
   while i<len(df.index):
       df.a[i] = x*((df.a.shift(1)*0.45)+(df.b.shift(1)*0.5))+abs(1-x)*df.a.shift(1)
       df.b[i] = x*((df.b.shift(1)*0.5)+(df.a.shift(1)*0.59))+abs(1-x)*df.b.shift(1)
       i+1

df is a DataFrame. Currently I get the error: ValueError: setting an array element with a sequence.

I also know why I am getting this this problem, see this question. The question is, how can I solve this? There is probably a more efficient solution than a while loop...

Community
  • 1
  • 1
hb.klein
  • 381
  • 1
  • 4
  • 16
  • 5
    In Python you can do e.g. `a, b = some_op(a, b), other_op(a, b)` to use the old values on the right-hand side and assign both new values on the left-hand side. – jonrsharpe Jun 03 '15 at 10:30
  • 1
    A common solution to this 2-variable problem is to use a temporary variable to store the 'old' value of a. So something like `old_a = a; a = get_new_a(a, b); b = get_new_b(old_a, b)`. – Tom Dalton Jun 03 '15 at 10:30
  • How would I implement such a solution? – hb.klein Jun 03 '15 at 10:34
  • The error you are reporting has nothing to do with the question you are asking. Try to keep the issues separate so you can understand the answer (and we the question). – alexis Jun 03 '15 at 13:03
  • Could be interesting to you: https://wiki.python.org/moin/GlobalInterpreterLock – firelynx Jun 03 '15 at 14:31

2 Answers2

1

I can note that df.a and df.b are both sequences. So you could use map for obtain your result.

Example:

l = [1, 2, 3]
set_negative = lambda x: x * -1  # Some function o lammbda that receives a sinble argument
ml = map(set_negative, l) # ml = [-1, -2, -3]

In your case you could write your code like this:

in_a = lambda _: x*((df.a.shift(1)*0.45)+(df.b.shift(1)*0.5))+abs(1-x)*df.a.shift(1)
in_b = lambda _: x*((df.b.shift(1)*0.5)+(df.a.shift(1)*0.59))+abs(1-x)*df.b.shift(1)

df.a = map(in_a, df.a)
df.b = map(in_b, df.b)

You could try more sofisiticated solutions using: starmap or imap

Raydel Miranda
  • 13,825
  • 3
  • 38
  • 60
  • what are "l = [1, 2, 3]" and "ml = map(set_negative, l) # ml = [-1, -2, -3]" for? – hb.klein Jun 03 '15 at 22:05
  • Are just for ilustrate the use of map function: `l` is a list containing the integer values 1, 2 and 3 and `ml` is a list we have obtained as the result of apply the `set_negative` lambda to `l`. In others words we have applied a function to each element of the sequence `l` without using a `for` o `while` loop. – Raydel Miranda Jun 03 '15 at 22:54
0

Basicly first you say df['a'] is an int, and after that you want to iterate over df.a as if it's an array. So if you change df['a']=100 to df['a'][0] = 100 it should work.

Guinn
  • 1,355
  • 13
  • 29
  • Don't I define the length of df.a with: df['a']= [100]? - It returns: ValueError: Length of values does not match length of index – hb.klein Jun 03 '15 at 10:43
  • It returns: KeyError: 'a', the point is that df['a'] = 100 is fine. It creates a dataframe column filled with 100 to be than overwritten on the fly (important is just starting with 100). The problem, that creates the error in the lines below while since I try there to pass a series to one single row. - But thats just my understanding so far.... – hb.klein Jun 03 '15 at 11:23
  • I think I misunderstood, as I don't have your df I can't check what value your assignments ends up looking like, could you print your `x*((df.a.shift(1)*0.5.....` and see what kind of result is printed? – Guinn Jun 03 '15 at 11:56
  • df.a is filled with only 100s - that's df['a']=100 – hb.klein Jun 03 '15 at 11:58
  • So the outcome of your variable assignment is always 100? I mean if you do like: `test = x*((df.a.shift(1)*0.5...... ; print(test)` what is printed? – Guinn Jun 03 '15 at 12:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/79532/discussion-between-hb-klein-and-guinn). – hb.klein Jun 03 '15 at 12:18