官术网_书友最值得收藏!

1.5 向量化與隱式循環

數據分析語言的有趣特征之一是函數可以應用許多不同的數據對象,如向量、矩陣、數組與數據集等,而非僅僅標量而已,此即稱為向量化(vectorization),請看下面范例(Kabacoff,2015)。

上例中a為一常數(標量),而函數sqrt()如同計算機(calculator)一般執行于單值標量上。如果將函數round()與log()分別應用到一維向量或二維的矩陣,其結果如下:

從上面的結果讀者不難發現,sqrt()、round()與log()等函數是施加在數據中的每一個元素上,但是有些函數就并非如此執行了!例如下面常用的平均值計算函數mean():

mean()函數計算矩陣m的12個元素的算術平均數,因此讀者須經常注意輸入的數據對象(此處m為3×4矩陣),經函數處理后產生的輸出對象(上例傳回單值),其維度是否改變?數據結構是否改變?類型是否改變?這是掌握數據驅動程序設計的重要概念(參見1.9節程序調試與效率監測)。

上例中如果要計算矩陣m三行的平均值或四列的平均值,可以運用apply()函數:

其語法為:

apply (m, MARGIN, FUN,...)

apply()函數是將FUN運算施加于矩陣或數組對象的某一維度上,其中m是數組(包括二維矩陣),MARGIN是給定運作維度的數值向量或字符串向量,FUN是欲應用的函數,而...是額外要傳入FUN的參數值。m為二維的矩陣或數據集時,MARGIN=1表示逐行套用函數,MARGIN=2表示逐列套用函數。在數據驅動的程序語言中,R或Python的numpypandas等模塊,建議避免寫顯式循環(explicit looping,即for循環),而以隱式循環(implicit looping)的apply()系列函數取代之,不過上例中apply()還是比rowMeans()或colMeans()等更直接的向量化函數慢。Python語言apply()方法的編程應用,請參見1.6節編程范式與面向對象概念、2.2.3節Python語言群組與摘要,以及4.2.2節在線音樂城關聯規則分析等各節范例。

若為一維的向量或列表對象,可以使用lapply()或sapply()函數,兩者執行方式相同,其中"s"意指簡化(simplify),此函數在必要時將簡化lapply()函數返回的數據對象。以下用簡例說明兩者的用法:

R語言apply系列函數眾多,mapply()可施加一個函數于多個列表或向量的對應元素上,下例中firstList與secondList均是長度為3的列表對象,mapply()將identical()函數施加在上述兩列表的對應元素上,判斷其是否完全相同。

mapply()函數語法中的FUN也可以是如下自定義的匿名函數(anonymous function),計算firstList與secondList對應元素的列數和,其他apply系列函數也可以調用自定義的匿名函數。

活用mapply()函數有時可以快速完成某些分組處理或可視化的工作,下例在mapply()函數中定義繪制各組回歸直線的匿名函數后,將其添加到iris數據集的Sepal.Width對Petal.Length的散點圖上,然后在適當位置標出圖例(圖1.9)(Verzani,2014)。

圖1.9 鳶尾花花萼寬度與花瓣長度分布情形及分組回歸直線圖

其實數據驅動程序設計中輸入輸出的變量符號(symbol)大多是數據對象,它們可能是一維、二維或更高維的結構。因此,數據分析語言多采用向量化數據處理與計算的方式,以避免額外循環執行,提升工作效率。許多運算符(如乘方運算符^、比較運算符>、加號+)及函數(如apply(),lapply(),sapply(),scale(),rowMeans(),colMeans())都是向量化函數,也就是說函數中隱藏著循環(implicit looping)的處理方式。所以再次提醒讀者注意思考下面問題:輸入的數據對象經函數處理后產生的輸出對象,其維度是否改變?數據結構是否改變?類型是否改變?(參見1.9節程序調試與效率監測)反復思索上述問題可以掌握數據驅動程序設計背后的運行邏輯。

主站蜘蛛池模板: 通城县| 维西| 房山区| 土默特右旗| 偃师市| 长武县| 大城县| 灌南县| 宾阳县| 琼中| 泰兴市| 广西| 彭山县| 阿克苏市| 双流县| 阿图什市| 宜兰县| 定远县| 明水县| 隆化县| 天全县| 泉州市| 建始县| 松溪县| 比如县| 扶余县| 岐山县| 临沧市| 潞城市| 正定县| 赤水市| 泾阳县| 石棉县| 拉孜县| 长宁区| 宜州市| 长岛县| 冀州市| 大宁县| 林州市| 根河市|