1
+ import os
2
+
1
3
from typing import (
2
4
Any ,
3
5
Callable ,
8
10
Optional
9
11
)
10
12
13
+ import pandas as pd
11
14
from pandas import (
12
15
Series
13
16
)
33
36
MetaDataFrame
34
37
)
35
38
39
+ # #27
40
+ if os .environ .get ('STOCK_PANDAS_COW' , '' ).lower () in ('1' , 'on' , 'true' ):
41
+ # Enable pandas Copy-on-Write mode
42
+ # https://pandas.pydata.org/pandas-docs/stable/user_guide/copy_on_write.html#copy-on-write-chained-assignment
43
+ pd .options .mode .copy_on_write = True
44
+
36
45
37
46
class StockDataFrame (MetaDataFrame ):
38
47
"""The wrapper class for `pandas.DataFrame`
@@ -326,23 +335,10 @@ def _get_or_calc_series(
326
335
period
327
336
)
328
337
329
- self ._set_new_item ( name , array )
338
+ self .loc [:, name ] = array
330
339
331
340
return name , array
332
341
333
- def _set_new_item (
334
- self ,
335
- name : str ,
336
- value : ndarray
337
- ) -> None :
338
- """Set a new column and avoid SettingWithCopyWarning by using
339
- pandas internal APIs
340
-
341
- see: https://github.com/pandas-dev/pandas/blob/v1.1.0/pandas/core/frame.py#L3114
342
- """
343
-
344
- self ._set_item (name , value )
345
-
346
342
def _fulfill_series (self , column_name : str ) -> ndarray :
347
343
column_info = self ._stock_columns_info_map .get (column_name )
348
344
size = len (self )
@@ -369,9 +365,15 @@ def _fulfill_series(self, column_name: str) -> ndarray:
369
365
if neg_delta == calc_delta :
370
366
array = partial
371
367
else :
368
+ # #27
369
+ # With `pd.options.mode.copy_on_write = True`,
370
+ # Series.to_numpy() will returns the
371
+ # read-only underlying numpy array of the Series
372
+ # so we need to copy it before modifying
373
+ array = array .copy ()
372
374
array [fulfill_slice ] = partial [fulfill_slice ]
373
375
374
- self ._set_new_item ( column_name , array )
376
+ self .loc [:, column_name ] = array
375
377
376
378
column_info .size = size
377
379
0 commit comments