0

The below code calculates the values for an indicator ( for example, say SMA) for all the values of the close price in a dataframe:

import pandas_ta as pta
df['SMA']= pta.sma(close=df['Close_NAVI.O'], length=10)

My query is that, is there a way to say calculate the value of SMA for a new close value that gets appended to the data frame ?

I know that we could re-run df['SMA']= pta.sma(close=df['Close_NAVI.O'], length=10) to get the SMA values for all close prices, but let's say I have a big dataframe which runs into thousands of rows and I don't want to waste my computing resources to keep re-calculating the values for all the row.

To give you a pictorial idea of what I said above, let's assume that the I now have a new close value of "16.6000" on "2014-05-07 00:00:00" of the below dataframe and I would like to calculate the value of SMA for that particular close price only.

image

I tried by using the below code,

df.loc[14, 'SMA']= pta.sma(close=df['Close_NAVI.O'], length=10)

but I get the following error:

df.loc[14, 'SMA']= pta.sma(close=df['Close_NAVI.O'], length=10)
Traceback (most recent call last):
  File "C:\Python37\lib\site-packages\IPython\core\interactiveshell.py", line 3325, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-64-3b6dc5d213d8>", line 1, in <module>
    df.loc[14, 'SMA']= pta.sma(close=df['Close_NAVI.O'], length=10)
  File "C:\Python37\lib\site-packages\pandas\core\indexing.py", line 670, in __setitem__
    iloc._setitem_with_indexer(indexer, value)
  File "C:\Python37\lib\site-packages\pandas\core\indexing.py", line 1642, in _setitem_with_indexer
    value = self._align_series(indexer, value)
  File "C:\Python37\lib\site-packages\pandas\core\indexing.py", line 1952, in _align_series
    raise ValueError("Incompatible indexer with Series")
ValueError: Incompatible indexer with Series
df.loc[13, 'SMA']= pta.sma(close=df['Close_NAVI.O'], length=10)
Traceback (most recent call last):
  File "C:\Python37\lib\site-packages\IPython\core\interactiveshell.py", line 3325, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-65-f0f4255ec13c>", line 1, in <module>
    df.loc[13, 'SMA']= pta.sma(close=df['Close_NAVI.O'], length=10)
  File "C:\Python37\lib\site-packages\pandas\core\indexing.py", line 670, in __setitem__
    iloc._setitem_with_indexer(indexer, value)
  File "C:\Python37\lib\site-packages\pandas\core\indexing.py", line 1642, in _setitem_with_indexer
    value = self._align_series(indexer, value)
  File "C:\Python37\lib\site-packages\pandas\core\indexing.py", line 1952, in _align_series
    raise ValueError("Incompatible indexer with Series")
ValueError: Incompatible indexer with Series

Could someone suggest a way to do this ?

Prateek Daniels
  • 451
  • 1
  • 4
  • 19

1 Answers1

1

Try subsetting your dataframe, copying the result into a new one ( be sure to use df_subset.copy() in order not to change the original df ), performing your calculation, and then retrieving the last value and inserting it back into the original dataframe.

length=10
start = df.shape[0] - length
aux = df.loc[start:,:].copy()
aux['SMA']= pta.sma(close=aux['close_price'], length=10)
aux2 = aux['SMA'].tail(1)
df.loc[14, 'SMA'] = aux2.values

That way, your new calculations will always be performed on a fixed size dataframe, which is only as large as it needs to be. I'm sure there are more elegant solutions out there, but this will get the job done.