Python 100 Days Day74 Introduction to Pandas-5
26 Sep 2022 | beginner pythonauthor: jackfrued
Pandas的應用-5
DataFrame的應用
窗口計算
DataFrame對象的rolling方法允許我們將數據置於窗口中,然後就可以使用函數對窗口中的數據進行運算和處理。例如,我們獲取了某只股票近期的數據,想制作5日均線和10日均線,那麽就需要先設置窗口再進行運算。我們可以使用三方庫pandas-datareader來獲取指定的股票在某個時間段內的數據,具體的操作如下所示。
安裝pandas-datareader三方庫。
pip install pandas-datareader
通過pandas-datareader 提供的get_data_stooq從 Stooq 網站獲取百度(股票代碼:BIDU)近期股票數據。
import pandas_datareader as pdr
baidu_df = pdr.get_data_stooq('BIDU', start='2021-11-22', end='2021-12-7')
baidu_df.sort_index(inplace=True)
baidu_df
輸出:

上面的DataFrame有Open、High、Low、Close、Volume五個列,分別代碼股票的開盤價、最高價、最低價、收盤價和成交量,接下來我們對百度的股票數據進行窗口計算。
baidu_df.rolling(5).mean()
輸出:

上面的Close 列的數據就是我們需要的5日均線,當然,我們也可以用下面的方法,直接在Close列對應的Series對象上計算5日均線。
baidu_df.Close.rolling(5).mean()
輸出:
Date
2021-11-22 NaN
2021-11-23 NaN
2021-11-24 NaN
2021-11-26 NaN
2021-11-29 150.608
2021-11-30 151.014
2021-12-01 150.682
2021-12-02 150.196
2021-12-03 147.062
2021-12-06 146.534
2021-12-07 146.544
Name: Close, dtype: float64
相關性判定
在統計學中,我們通常使用協方差(covariance)來衡量兩個隨機變量的聯合變化程度。如果變量 $X$ 的較大值主要與另一個變量 $Y$ 的較大值相對應,而兩者較小值也相對應,那麽兩個變量傾向於表現出相似的行為,協方差為正。如果一個變量的較大值主要對應於另一個變量的較小值,則兩個變量傾向於表現出相反的行為,協方差為負。簡單的說,協方差的正負號顯示著兩個變量的相關性。方差是協方差的一種特殊情況,即變量與自身的協方差。
\[cov(X,Y) = E((X - \mu)(Y - \upsilon)) = E(X \cdot Y) - \mu\upsilon\]如果 $X$ 和 $Y$ 是統計獨立的,那麽二者的協方差為0,這是因為在 $X$ 和 $Y$ 獨立的情況下:
\[E(X \cdot Y) = E(X) \cdot E(Y) = \mu\upsilon\]協方差的數值大小取決於變量的大小,通常是不容易解釋的,但是正態形式的協方差大小可以顯示兩變量線性關系的強弱。在統計學中,皮爾遜積矩相關系數就是正態形式的協方差,它用於度量兩個變量 $X$ 和 $Y$ 之間的相關程度(線性相關),其值介於-1到1之間。
估算樣本的協方差和標準差,可以得到樣本皮爾遜系數,通常用希臘字母 $\rho$ 表示。
\[\rho = \frac {\sum_{i=1}^{n}(X_i - \bar{X})(Y_i - \bar{Y})} {\sqrt{\sum_{i=1}^{n}(X_i - \bar{X})^2} \sqrt{\sum_{i=1}^{n}(Y_i - \bar{Y})^2}}\]我們用 $\rho$ 值判斷指標的相關性時遵循以下兩個步驟。
- 判斷指標間是正相關、負相關,還是不相關。
- 當 $ \rho \gt 0 $,認為變量之間是正相關,也就是兩者的趨勢一致。
- 當 $ \rho \lt 0 $,認為變量之間是負相關,也就是兩者的趨勢相反。
- 當 $ \rho = 0 $,認為變量之間是不相關的,但並不代表兩個指標是統計獨立的。
- 判斷指標間的相關程度。
- 當 $ \rho $ 的絕對值在 $ [0.6,1] $ 之間,認為變量之間是強相關的。
- 當 $ \rho $ 的絕對值在 $ [0.1,0.6) $ 之間,認為變量之間是弱相關的。
- 當 $ \rho $ 的絕對值在 $ [0,0.1) $ 之間,認為變量之間沒有相關性。
皮爾遜相關系數適用於:
- 兩個變量之間是線性關系,都是連續數據。
- 兩個變量的總體是正態分布,或接近正態的單峰分布。
- 兩個變量的觀測值是成對的,每對觀測值之間相互獨立。
DataFrame對象的cov方法和corr方法分別用於計算協方差和相關系數,corr方法的第一個參數method的默認值是pearson,表示計算皮爾遜相關系數;除此之外,還可以指定kendall或spearman來獲得肯德爾系數或斯皮爾曼等級相關系數。
接下來,我們從名為boston_house_price.csv的文件中獲取著名的波士頓房價數據集來創建一個DataFrame,我們通過corr方法計算可能影響房價的13個因素中,哪些跟房價是正相關或負相關的,代碼如下所示。
boston_df = pd.read_csv('data/csv/boston_house_price.csv')
boston_df.corr()
說明:如果需要上面例子中的 CSV 文件,可以通過下面的百度雲盤地址進行獲取,數據在《從零開始學數據分析》目錄中。鏈接:https://pan.baidu.com/s/1rQujl5RQn9R7PadB2Z5g_g,提取碼:e7b4。
輸出:

斯皮爾曼相關系數對數據條件的要求沒有皮爾遜相關系數嚴格,只要兩個變量的觀測值是成對的等級評定資料,或者是由連續變量觀測資料轉化得到的等級資料,不論兩個變量的總體分布形態、樣本容量的大小如何,都可以用斯皮爾曼等級相關系數來進行研究。我們通過下面的方式來計算斯皮爾曼相關系數。
boston_df.corr('spearman')
輸出:

在 Notebook 或 JupyterLab 中,我們可以為PRICE列添加漸變色,用顏色直觀的展示出跟房價負相關、正相關、不相關的列,DataFrame對象style屬性的background_gradient方法可以完成這個操作,代碼如下所示。
boston_df.corr('spearman').style.background_gradient('RdYlBu', subset=['PRICE'])

上面代碼中的RdYlBu代表的顏色如下所示,相關系數的數據值越接近1,顏色越接近紅色;數據值越接近1,顏色越接近藍色;數據值在0附件則是黃色。
plt.get_cmap('RdYlBu')

Index的應用
我們再來看看Index類型,它為Series和DataFrame對象提供了索引服務,常用的Index有以下幾種。
範圍索引(RangeIndex)
代碼:
sales_data = np.random.randint(400, 1000, 12)
month_index = pd.RangeIndex(1, 13, name='月份')
ser = pd.Series(data=sales_data, index=month_index)
ser
輸出:
月份
1 703
2 705
3 557
4 943
5 961
6 615
7 788
8 985
9 921
10 951
11 874
12 609
dtype: int64
分類索引(CategoricalIndex)
代碼:
cate_index = pd.CategoricalIndex(
['蘋果', '香蕉', '蘋果', '蘋果', '桃子', '香蕉'],
ordered=True,
categories=['蘋果', '香蕉', '桃子']
)
ser = pd.Series(data=amount, index=cate_index)
ser
輸出:
蘋果 6
香蕉 6
蘋果 7
蘋果 6
桃子 8
香蕉 6
dtype: int64
代碼:
ser.groupby(level=0).sum()
輸出:
蘋果 19
香蕉 12
桃子 8
dtype: int64
多級索引(MultiIndex)
代碼:
ids = np.arange(1001, 1006)
sms = ['期中', '期末']
index = pd.MultiIndex.from_product((ids, sms), names=['學號', '學期'])
courses = ['語文', '數學', '英語']
scores = np.random.randint(60, 101, (10, 3))
df = pd.DataFrame(data=scores, columns=courses, index=index)
df
說明:上面的代碼使用了
MultiIndex的類方法from_product,該方法通過ids和sms兩組數據的笛卡爾積構造了多級索引。
輸出:
語文 數學 英語
學號 學期
1001 期中 93 77 60
期末 93 98 84
1002 期中 64 78 71
期末 70 71 97
1003 期中 72 88 97
期末 99 100 63
1004 期中 80 71 61
期末 91 62 72
1005 期中 82 95 67
期末 84 78 86
代碼:
# 計算每個學生的成績,期中占25%,期末占75%
df.groupby(level=0).agg(lambda x: x.values[0] * 0.25 + x.values[1] * 0.75)
輸出:
語文 數學 英語
學號
1001 93.00 92.75 78.00
1002 68.50 72.75 90.50
1003 92.25 97.00 71.50
1004 88.25 64.25 69.25
1005 83.50 82.25 81.25
日期時間索引(DatetimeIndex)
-
通過
date_range()函數,我們可以創建日期時間索引,代碼如下所示。代碼:
pd.date_range('2021-1-1', '2021-6-1', periods=10)輸出:
DatetimeIndex(['2021-01-01 00:00:00', '2021-01-17 18:40:00', '2021-02-03 13:20:00', '2021-02-20 08:00:00', '2021-03-09 02:40:00', '2021-03-25 21:20:00', '2021-04-11 16:00:00', '2021-04-28 10:40:00', '2021-05-15 05:20:00', '2021-06-01 00:00:00'], dtype='datetime64[ns]', freq=None)代碼:
pd.date_range('2021-1-1', '2021-6-1', freq='W')輸出:
DatetimeIndex(['2021-01-03', '2021-01-10', '2021-01-17', '2021-01-24', '2021-01-31', '2021-02-07', '2021-02-14', '2021-02-21', '2021-02-28', '2021-03-07', '2021-03-14', '2021-03-21', '2021-03-28', '2021-04-04', '2021-04-11', '2021-04-18', '2021-04-25', '2021-05-02', '2021-05-09', '2021-05-16', '2021-05-23', '2021-05-30'], dtype='datetime64[ns]', freq='W-SUN') -
通過
DateOffset類型,我們可以設置時間差並和DatetimeIndex進行運算,具體的操作如下所示。代碼:
index = pd.date_range('2021-1-1', '2021-6-1', freq='W') index - pd.DateOffset(days=2)輸出:
DatetimeIndex(['2021-01-01', '2021-01-08', '2021-01-15', '2021-01-22', '2021-01-29', '2021-02-05', '2021-02-12', '2021-02-19', '2021-02-26', '2021-03-05', '2021-03-12', '2021-03-19', '2021-03-26', '2021-04-02', '2021-04-09', '2021-04-16', '2021-04-23', '2021-04-30', '2021-05-07', '2021-05-14', '2021-05-21', '2021-05-28'], dtype='datetime64[ns]', freq=None)代碼:
index + pd.DateOffset(days=2)輸出:
DatetimeIndex(['2021-01-05', '2021-01-12', '2021-01-19', '2021-01-26', '2021-02-02', '2021-02-09', '2021-02-16', '2021-02-23', '2021-03-02', '2021-03-09', '2021-03-16', '2021-03-23', '2021-03-30', '2021-04-06', '2021-04-13', '2021-04-20', '2021-04-27', '2021-05-04', '2021-05-11', '2021-05-18', '2021-05-25', '2021-06-01'], dtype='datetime64[ns]', freq=None) - 可以使用
DatatimeIndex類型的相關方法來處理數據,具體包括:-
shift()方法:通過時間前移或後移數據,我們仍然以上面百度股票數據為例,代碼如下所示。代碼:
baidu_df.shift(3, fill_value=0)輸出:

代碼:
baidu_df.shift(-1, fill_value=0)輸出:

-
asfreq()方法:指定一個時間頻率抽取對應的數據,代碼如下所示。代碼:
baidu_df.asfreq('5D')輸出:

代碼:
baidu_df.asfreq('5D', method='ffill')輸出:

-
resample()方法:基於時間對數據進行重采樣,相當於根據時間周期對數據進行了分組操作,代碼如下所示。代碼:
baidu_df.resample('1M').mean()輸出:

說明:上面的代碼中,
W表示一周,5D表示5天,1M表示1個月。 -
-
時區轉換
-
獲取時區信息。
import pytz pytz.common_timezones -
tz_localize()方法:將日期時間本地化。代碼:
baidu_df = baidu_df.tz_localize('Asia/Chongqing') baidu_df輸出:

-
tz_convert()方法:轉換時區。代碼:
baidu_df.tz_convert('America/New_York')輸出:

-
Comments