Python股票数据处理的一些代码细节
Python股票數據處理的一些代碼細節
- Numpy和Pandas相關
- Numpy和Pandas比較
- numpy.ndarray和多類型數據
- Numpy神奇的取值方法
- Pandas透視表
- 如何刪除numpy.ndarray中指定位置的元素
- 如何確定numpy.ndarray中指定值的元素的位置
- 如何對多維numpy.ndarray進行降維
- map()、np.apply_along_axis()和pd.apply()
- 如何向numpy.ndarray中插入元素
- 如何在三維數組中使用min()函數
- 如何改變數組維度
 
Numpy和Pandas相關
Numpy和Pandas比較
Pandas和Numpy各有所長。
在處理股票數據的基礎階段,Pandas能夠清晰地展示股票代碼、交易日期、價格等信息,且對于信息的分類、歸集、整理有很多針對性強的功能函數,非常便捷。
在處理股票數據的高級階段,尤其在涉及機器學習領域,Numpy用處更多。首先因為Keras等函數庫要求的輸入類型多為numpy.ndarray,更深層的原因是Numpy在多維數據儲存和處理上更具優勢,而且由于Numpy的數據為單一類型,處理速度比Pandas快很多。
numpy.ndarray和多類型數據
由于numpy.ndarray要求存儲單一類型數據,用np.array()函數轉換DataFrame時,如果value有多種數據類型,比如string、int、float,轉換后dtype(數據表中的元素類型)會顯示為object(不是很懂這是什么東西),雖然單獨提取時,會“還原”為string、int或float(datatime會被轉換為int),但接下來對整塊數據操作時,比如遇到要求float數據類型,必須先用astype(float)進行轉換,否則會報錯。
i_str = [['a', 'b', 'c']] i_int = [[1, 2, 3]] i_float = [[1.1, 2.2, 3.3]]i_array = np.concatenate((i_str, i_int, i_float), axis = 0) print(i_array) [['a' 'b' 'c']['1' '2' '3']['1.1' '2.2' '3.3']] print(i_array.dtype) output: <U32 a = i_array[0,1] b = i_array[1,1] c = i_array[2,1] d = c.astype(float) print(type(a)) output: <class 'numpy.str_'> print(type(b)) output: <class 'numpy.str_'> print(type(c)) output: <class 'numpy.str_'> print(type(d)) output: <class 'numpy.float64'>還是由于存儲單一類型數據的限制,可以對提取的元素單獨進行類型轉換,但對整塊元素進行類型轉換是行不通的。
i_array[1:,:] = i_array[1:,:].astype(float) print(i_array) [['a' 'b' 'c']['1.0' '2.0' '3.0']['1.1' '2.2' '3.3']]轉換后由于有第一行string類型的限制,二、三行在被轉換成float后,又被轉換回string了。
Numpy神奇的取值方法
不同于DataFrame,numpy.ndarray本身是沒有索引的,但它的索引方式相當靈活。
比如,以長度相同的,元素為布爾值的numpy.ndarray作為索引。
y = np.array([1, 2, 3, 4, 5]) z = np.array([False,False,False,True,True]) x = y[z] print(x) output: [4 5]再此基礎上,又可以用各種方法生成這種布爾值索引,比如以下:
y = np.array([1, 2, 3, 4, 5]) z = np.array([11, 12, 13, 14, 15]) x = y[z>13] print(x) output: [4 5]Pandas透視表
在獲取股票數據,尤其是從一些金融數據庫獲取數據時,數據的原始索引方式往往不符合我們的需求,這時我們需要對數據做一些變換處理。
比如下列張原始的DataFrame數據表(僅展示了表尾部分),它包含了股票代碼、日期和因子三個維度。
instrument turn volume date high low \ 3958753 603016.SHA 2.866226 4246600 2019-12-30 17.138489 15.550813 3958863 603217.SHA 4.498146 1023778 2019-12-30 48.560001 47.790001 3958928 603348.SHA 15.438673 10807071 2019-12-30 22.463787 20.058041 3958999 603578.SHA 1.548533 503583 2019-12-30 20.669724 20.160618 3959111 603787.SHA 8.877831 6293495 2019-12-30 14.495040 13.518423 open amount close 3958753 15.698014 66799268.0 16.833570 3958863 48.349998 49327120.0 48.560001 3958928 20.261057 227867088.0 22.463787 3958999 20.252256 10112697.0 20.608631 3959111 13.939911 85766672.0 14.330557由于DataFrame擅長處理二維數據,我需要將它提取轉換為多張,每張展示一個因子,以日期為行索引,股票代碼為列索引的DataFrame。
最直觀的方式是采取For循環的辦法,先構建一張空DataFrame,然后把各個元素依次提取填入空DataFrame,但是處理效率非常低。
我起初采取的方法是依靠DataFrame的切片和拼接功能,盡量整塊操作,減少循環次數:
df_close = pd.concat([df.loc[df['instrument']==i].set_index('date')['close'] for i in stock_codes], axis=1)直到發現pd.pivot_table()這個函數可以方便直接地處理這些變換:
df_close = pd.pivot_table(df_all,values='close',index=['date'],columns=['instrument']) print(df_close.tail()) instrument 002233.SZA 002394.SZA 002454.SZA 002567.SZA 002581.SZA \ date 2019-12-24 30.662279 40.128410 13.877932 44.442993 18.995348 2019-12-25 31.158939 40.042206 13.764643 43.988461 18.879875 2019-12-26 31.524900 40.257717 13.764643 44.240978 19.053085 2019-12-27 31.786301 40.300819 13.623031 45.655075 19.053085 2019-12-30 32.335243 40.559433 13.764643 44.493496 18.995348 instrument ... 601015.SHA 601117.SHA 601336.SHA 601872.SHA \ date ... 2019-12-24 ... 6.118216 7.116693 50.495480 8.824105 2019-12-25 ... 6.098415 7.071863 50.623913 8.885554 2019-12-26 ... 6.118216 7.195144 50.837967 9.561496 2019-12-27 ... 6.138015 7.139107 50.955696 9.389438 2019-12-30 ... 6.217216 7.206352 52.518295 9.672104如何刪除numpy.ndarray中指定位置的元素
首先利用numpy.ndarray索引的特性創建一個list或numpy.ndarray,列出想要刪除元素的位置(不必按順序),然后用np.delete()函數刪除。注意這里輸入的a可以是list或numpy.ndarray類型,輸出的c是numpy.ndarray類型。
a = [1,2,3,4,5] b = [3,1,4] c = np.delete(a, b, axis=0) print(c) output: [1 3]如何確定numpy.ndarray中指定值的元素的位置
我沒有找過直接刪除指定值的方法,而是先用np.where()函數確定指定值所在的位置,再用np.delete()函數刪除。這樣做的好處是,在中間環節生成了一個索引,可以在機器學習中用于同步處理矩陣x和其對應的label 矩陣y。
a = [1,2,3,1,1] b = np.where(np.array(a)==1)np.where()函數要求輸入類型為numpy.ndarray,如果是一個list或其他類型,需要進行轉換。
print(b) print(type(b)) output: (array([0, 3, 4]),) output: <class 'tuple'>比較吊詭的是np.where()函數的輸出類型為tuple,當遇到有些函數比如np.random.choice()只接受一維的array類型或int類型,我們還需要對tuple進行轉換。
如何對多維numpy.ndarray進行降維
接著上一個例子:
c = list(b) print(c) output: [array([0, 3, 4])]當我們將b從tuple轉換成list后,發現它仍是一個包含array的list。
d = np.array(b) print(d) print(type(d)) print(np.shape(d)) output: [[0 3 4]] output: <class 'numpy.ndarray'> output: (1, 3)當我們將b從tuple轉換成numpy.ndarray后,發現它是二維,還需繼續轉換成一維,這里用flatten()函數。
e = d.flatten() print(e) output: [0 3 4]map()、np.apply_along_axis()和pd.apply()
標題中分別是Python、Numpy和Pandas的函數,向下兼容。當需要對list、numpy.ndarray或DataFrame進行操作時,效率會大大高于for循環。
其中map()的對象是list、numpy.ndarray或DataFrame中的單個元素;np.apply_along_axis()的對象是numpy.ndarray或DataFrame中的整列;pd.apply()的對象是DataFrame中的整列。
三者中效率map() > np.apply_along_axis() > pd.apply()
在np.apply_along_axis()和pd.apply()中指定axis=0或1或2……會選定行或列,然后延其他軸方向運算。
如果需要指定三維及以上操作,還有np.apply_over_axis()函數可用。
a = np.array([[[1,2,3,4],[1,2,3,4],[1,2,3,4]],[[4,3,2,1],[4,3,2,1],[4,3,2,1]],[[6,6,6,6],[6,6,6,6],[6,6,6,6]]]) b = map(lambda x: x ** 2, a) c = np.array(list(map(lambda x: x ** 2, a))) print(b) print(c)輸入一個3x3x4的三維array,這里func用的是匿名函數lambda,map()會將a中的元素逐個帶入x,計算x^2。注意map()函數返回的是內存地址,需要先轉換成list,再根據需要轉換成array。
output: <map object at 0x7f5ba948bbe0> [[[ 1 4 9 16][ 1 4 9 16][ 1 4 9 16]][[16 9 4 1][16 9 4 1][16 9 4 1]][[36 36 36 36][36 36 36 36][36 36 36 36]]]未完待續……
如何向numpy.ndarray中插入元素
向已有的numpy.ndarray中添加數據或者補零,可以用np.insert(arr,obj,values,axis)函數。其中:
 arr——被插入的目標數組;
 obj——插入的目標位置,在這個位置之前插入;
 value——要插入的值,注意如果是多個值,形狀要同被插入的目標數組匹配,如果是單個值,僅需填入一個數字,這時函數會自動擴充以匹配數組的形狀;
 axis——目標位置的軸。
比如:在數組a的0軸位置3添加三行0:
a = np.array([[1,2,3],[4,5,6],[7,8,9]]) loc = [3,3,3] b = np.insert(a, (loc), 0, axis=0) print(b) [[1 2 3][4 5 6][7 8 9][0 0 0][0 0 0][0 0 0]]之前還用過np.zeros()函數生成一個三維的零矩陣,后來發現全無必要。
如果要在原有的array矩陣四周添加元素,還有一種方法是將它當作一張圖片,用np.pad()函數補邊。
如何在三維數組中使用min()函數
a = np.arange(0,18,1).reshape(2,3,3) print(a) [[[ 0 1 2][ 3 4 5][ 6 7 8]][[ 9 10 11][12 13 14][15 16 17]]] b = a.min(axis=2) c = b.min(axis=1) print(b) [[ 0 3 6][ 9 12 15]] print(c) [0 9]對多維數組進行操作常常會被axis的含義困擾,以np.min()函數為例,axis=2代表按行分組取值,比如上例中取第一行的最小數0,第二行的最小數3……依次類推。
另一個困擾是取值后函數會按什么規則輸出新的矩陣。比如上例中axis=2維度的結構被拆除了,0、3、6……先是依次被填入axis=1維度,再形成axis=0維度。
如何改變數組維度
np.reshape()函數的參數代表各維度上的行列數,如果不確定某一維的行列數,可以輸入-1可以讓函數自動補齊,但其余維度的行列數必須明確。
函數會按從上到下,從左往右的順序依次填充矩陣。下例相當于對數組a做了90°垂直翻轉。
a = np.arange(0,18,1).reshape(-1,3) print(a) [[ 0 1 2][ 3 4 5][ 6 7 8][ 9 10 11][12 13 14][15 16 17]] b = a.reshape(-1,1,3) print(b) [[[ 0 1 2]][[ 3 4 5]][[ 6 7 8]][[ 9 10 11]][[12 13 14]][[15 16 17]]]如果僅需要增加維度,不需要改變數組的形狀,也不清楚數組的形狀,還可以用np.newaxis函數,比reshape()快很多。
c = a[:, np.newaxis]總結
以上是生活随笔為你收集整理的Python股票数据处理的一些代码细节的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: js正则表达式验证金额
- 下一篇: 高通骁龙712处理器规格参数介绍
