1

I want to add some data to a dataframe to analyse stock price movements. I want to check, if a row is the narrowst range in 7 bars. Unfortunately I seem to be able to run through the df array and perform a basic check. But I can´t assign a string to a column when the If-Statement fulfilled.Any ideas what´s wrong? I am coming XL VBA and so far it´s still a little bit overwhelming in python/ pandas...

import pandas as pd
import numpy as np

path = '/Users/chri....in/Documents/Python_Script/dataset/'
df = pd.read_csv(path+'AAPL.csv')

df['SMA10'] = df['Close'].rolling(10).mean()
df['ADR20'] = ((df['High'].rolling(20).mean()/df['Low'].rolling(20).mean())-1)*100
df['ADR1'] = (df['High']/df['Low']-1)*100
df['Range'] = df['High']-df['Low']
df['NR7'] = 'na'

for i, row in df.iterrows():
    #Condition for defining NR7, 4
    if df.iloc[i]['Range'] < df.iloc[i-1]['Range']: 
        df.iloc[i, 'NR7'] = ['NR4'] ***#This doesn´t seem to work***
petezurich
  • 9,280
  • 9
  • 43
  • 57
Chris
  • 13
  • 2
  • 1
    [Looping over dataframes is bad practice](https://stackoverflow.com/a/55557758/15873043). In 99.9% of the time, there's a proper, vectorized way to do it. In this case, you can remove `df['NR7'] = 'na'` and everything below that and instead do `df.loc[df.Range < df.Range.shift(), "NR7"] = "NR4"`. No need to loop, no need to initialize the column. – fsimonjetz Sep 18 '22 at 14:15
  • Yeah, watched yesterday a YT about this. As I am taking baby steps right now I am focused on the basics. It´s all a bit different than Visual Basic...Will look more into the vectorization. Thanks! – Chris Sep 18 '22 at 19:36

2 Answers2

1

You don't need any loop at all. You don't need even df['NR7'] = 'na'.

Just create NR7 column the following way:

df['NR7'] = np.where(df.Range < df.Range.shift(), 'NR4', 'na')
Valdi_Bo
  • 30,023
  • 4
  • 23
  • 41
  • This works perfectly. Need to look more into this on YT. Realized that it needs some time to calculate. Many thanks for your input. – Chris Sep 18 '22 at 19:21
  • 1
    Ok, convinced. Without the loop it´s super fast. Will look more into this. Seems to be highly efficient. – Chris Sep 18 '22 at 19:38
0

You got it right everywhere else...

df.iloc[i]['NR4'] = 'NR4'

When using iloc you can't use the column names.

Also, unless you want to assign a list containing one element, don't put square brackets around the string.

s_pike
  • 1,710
  • 1
  • 10
  • 22
  • Thanks for your reply. It seems to accept integers according to documentation and tested it succesfully with df.iloc[i, 11] = 'NR4' – Chris Sep 18 '22 at 19:32
  • Yes, that's right. You can use the index position of the column (e.g. your 12th column is position 11). You just can't use the column name. – s_pike Sep 18 '22 at 19:39