序列內置一些函數,用於循環對序列的元素執行操作。
一,應用和轉換函數
應用apply
對序列的各個元素應用函數:
Series.apply(self, func, convert_dtype=True, args=(), **kwds)
參數注釋:
- func:應用的函數,可以是自定義的函數,或NumPy函數
- convert_dtype:默認值是True,嘗試把func應用的結果轉換為更好的數據類型,如果設置為False,把結果轉換為dtype=object.
- args:元組,在序列值之后,傳遞給func的位置參數(positional arguments)
- **kwds:傳遞給func的關鍵字(keyword)參數,可以有0、1、多個
位置參數和關鍵字參數的區別是:
- 位置參數是通過匹配位置來傳參,關鍵字參數是通過匹配參數名稱來傳參。
- 關鍵字參數可以有多個,參數的名稱不固定,只能在apply函數()的最后面,例如,關鍵字參數k1,k2,k3,那么kwargs=[k1,k2,k3]
- 位置參數args只能有一個
1,傳遞自定義的函數(使用位置參數)
創建自定義的函數,把函數應用於序列之上
>>> s = pd.Series([20, 21, 12], index=['London', 'New York', 'Helsinki']) >>> def subtract_custom_value(x, custom_value): ... return x - custom_value >>> s.apply(subtract_custom_value, args=(5,)) London 15 New York 16 Helsinki 7 dtype: int64
2,傳遞自定義的函數(使用關鍵字參數)
可以看到,關鍵字參數只能在apply函數的后面,
>>> def add_custom_values(x, **kwargs): ... for month in kwargs: ... x += kwargs[month] ... return x >>> s.apply(add_custom_values, june=30, july=20, august=25) London 95 New York 96 Helsinki 87 dtype: int64
轉換transform
轉換是對序列的一個軸進行轉換,對於序列來說,axis=0,對行序列進行轉換:
Series.transform(self, func, axis=0, *args, **kwargs)
二,分組
對序列分組,返回分組之后的對象,並可以調用聚合函數獲得每個分組的聚合值:
Series.groupby(self, by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, observed=False, **kwargs)
參數注釋:
by:用於對序列進行分組,參數by的值可以是函數,列名或列名列表,映射
1,by是函數
如果by是函數,那么調用的是序列索引的值
>>> s=pd.Series([1,2,3,4]) >>> s.groupby(by=lambda x: x<3).count() False 1 True 3 dtype: int64
可以通過索引值來訪問序列的元素值:
>>> s.groupby(by=lambda x: s.iat[x]<3).count() False 2 True 2 dtype: int64
2,by是標簽列表
如果by是標簽列表,通常是按照列值來對數據進行分組,通常用於數據框(DataFrame)中
3,映射(字典)
當使用字典作為映射時,字典的key對應序列的值,按照字典的value對原始序列進行分組
>>> s.groupby(by={1:'a',2:'a',3:'b',4:'b'}).count()
a 2
b 1
dtype: int64
4,映射(序列)
當使用序列作為映射時,by序列的值用於對原始序列進行分組,by序列中相同的值對應着原始序列的值屬於同一個分組;原始序列和by序列進行匹配的方法是索引對齊。
>>> s.groupby(by=pd.Series(data=[1,2,1,1],index=[0,2,3,1])).mean() 1 2.333333 2 3.000000 dtype: float64
索引對齊是怎么回事?
對於by參數的序列,數據是1, 2, 1, 1,這意味着,把原始序列分為2組,分組的key分別是1和2。
by序列的索引是0, 2, 3, 1,也就是說,當原始序列的索引為0, 3, 1 時,對應的分組key是1,當原始序列的索引為2時,對應的分組key是2。
索引對齊之后,原始序列中的值1,2,4屬於分組1;原始序列中的值3屬於分組2,再計算每個分組的均值。
三,滾動
滾動窗口計算,每個窗口計算一個聚合值,每次向前滾動一步(一步是一個元素):
Series.rolling(self, window, min_periods=None, center=False, win_type=None, on=None, axis=0, closed=None)
參數注釋:
- window:滾動的窗口值,或偏移量,每一個窗口都是一個固定值。
- min_periods:每個窗口的最小值,如果窗口中的元素數量小於min_periods,返回NaN;默認情況下,min_periods等於window參數的值。
舉個例子,對於序列,當窗口設置為2時,如果不設置min_periods,那么窗口要想有值,那么窗口的大小必須是2,序列的第一個元素在窗口中只有一個值,因此返回NaN。
>>> s=pd.Series([1,2,3,4]) >>> s.rolling(2).sum() 0 NaN 1 3.0 2 5.0 3 7.0 dtype: float64 >>> s.rolling(window=2,min_periods =1).sum() 0 1.0 1 3.0 2 5.0 3 7.0 dtype: float64
四,擴展
擴展是指由序列的第一個元素開始,逐個元素向后計算聚合值,當聚合函數是sum時,表示從第一個元素開始,計算累加:
Series.expanding(self, min_periods=1, center=False, axis=0)
舉個例子,從第一個元素開始計算序列1,2,3,4的累加:
>>> s=pd.Series([1,2,3,4]) >>> s.expanding().sum() 0 1.0 1 3.0 2 6.0 3 10.0 dtype: float64
五,指數加權移動平均
ewm(Exponentially Weighted Moving)是指數加權移動的簡稱,通常情況下,是對序列的元素進行指數加權,計算加權后的均值:
Series.ewm(self, com=None, span=None, halflife=None, alpha=None, min_periods=0, adjust=True, ignore_na=False, axis=0)
1,參數注釋
在進行指數加權時,平滑因子有四種指定方式得出:

adjust:處於初期的衰減調整因子,以解決相對權重不平衡的問題。
- 當設置adjust為True時,加權均值的計算公式是: (1-alpha)**(n-1), (1-alpha)**(n-2), …, 1-alpha, 1
- 當設置adjust為False時,加權均值的計算公式是:weighted_average[0] = arg[0]; weighted_average[i] = (1-alpha)*weighted_average[i-1] + alpha*arg[i].
2,指數加權移動平均的意義
指數加權移動均值(EWMA,Exponentially Weighted Moving Average) 的公式是:EWMA(t) = aY(t) + (1-a)EWMA(t-1),t = 1,2,.....,n;
表示的含義是:在t時刻,根據實際的觀測值可以求取EWMA(t),其中,EWMA(t) 表示 t 時刻的估計值;Y(t) t時刻的測量值;n 所觀察的總的時間;a(0 < a <1)表示對於歷史測量值權重系數。
之所以稱之為指數加權,是因為加權系數a是以指數式遞減的,即各指數隨着時間而呈現出指數式遞減。系數a越接近1表示對當前抽樣值的權重越高,對過去測量值得權重越低,估計值(器)的時效性就越強,反之,越弱。
這種現象可以描述為應付突變的平穩性,平穩性隨着a的增大而減小。當設置較小的系數a時,得出的均值更大程度上是參考過去的測量值,在較小程度上參考當前值,表現出很強的平穩性;當設置較大的系數a,得出的均值更大程度上是參考當前的測量值,表現出很強的波動性。舉個例子,對於序列,設置較大的指數a=0.8和較小的指數a=0.2,位置越靠后,得出的均值越接近或越遠離當前值:
>>> s=pd.Series([1,2,3,4]) >>> s.ewm(alpha=0.8).mean() 0 1.000000 1 1.833333 2 2.774194 3 3.756410 dtype: float64 >>> s.ewm(alpha=0.2).mean() 0 1.000000 1 1.555556 2 2.147541 3 2.775068 dtype: float64
參考文檔:
