0

I currently have the following dataframe and would like to fill in the empty "weight" cells with a drifted value (explained below).

enter image description here

For values above 234 in the 'weight' column I would like to have the following values:

enter image description here

And, for values below 234, I would like to have the following values:

enter image description here

What is the best and most Pythonic way to achieve my objective in Python 3 and Pandas? (I'm open to using libraries that have this transformation built in; however, I'm yet to find one myself.)

EDIT 1: The textual version of the above:

The following is a simple version of the above dataframe.

   A  B
0  1  NaN
1  1  3
2  4  NaN

I would like all values above the value "3" in column B to take on the following formula. Note values within apostrophes are coordinates representing the x and y labels of the above dataframe.

"1B"/(1 + "0B")

I would like all values below the value "3" in column B to take on the following formula.

"1B" * (1 + "2A")

Note that the coordinates' relative distance to the current cell does not change. In Excel terminology, the references are "relative" and not "absolute". Read more about terminology here.

ptk
  • 6,835
  • 14
  • 45
  • 91
  • 2
    Please supply a **[mcve]**. This means no images / links, just text. See also [How to make good reproducible pandas examples](https://stackoverflow.com/questions/20109391/how-to-make-good-reproducible-pandas-examples). – jpp Aug 09 '18 at 10:41

2 Answers2

1

Since values are derived from the previously calculated value, you must use something akin to a for loop to achieve this:

# Grabbing index of non-empty row
j = int(df[df["weight"].notnull()].index[0])

# Logic for forward-filling values
for i in range(j+1, df.shape[0]):
    df.loc[i,'weight'] = df.loc[i-1,'weight'] * (1 + df.loc[i,'return'])

# Logic for backward-filling values
for i in range(j-1, -1, -1):
    df.loc[i,'weight'] = df.loc[i+1,'weight'] / (1 + df.loc[i,'return'])

Using this sample data:

   return  weight
0       1     NaN
1       1     3.0
2       4     NaN

We have this result:

   return  weight
0       1     1.5
1       1     3.0
2       4    15.0
iacob
  • 20,084
  • 6
  • 92
  • 119
1

Since you know you are using known data with only one value in the weight column, find the index and value of that entry.

Then just use one calculation above that index and the other below. Note that the index slicing is inclusive here:

import pandas as pd
import numpy as np

df = pd.DataFrame(data={'A': [i for i in range(10)], 'B': np.nan})
df.at[4,'B'] = 10

given_idx = df[df.B.notnull()].index.values[0]
given_val = df.at[given_idx, 'B']

df.loc[:given_idx-1, 'B'] = df['A'] + given_val
df.loc[given_idx+1:, 'B'] = df['A'] - given_val

print(df)
iacob
  • 20,084
  • 6
  • 92
  • 119
GeorgeLPerkins
  • 1,126
  • 10
  • 24