如何高效的在R里寫出一個循環?
不管在Python還是R,在代碼中使用循環都會極大的提升工作效率。作為一個初學小白,題主在寫循環的時候十分掙扎。希望知乎的朋友們能分享一下經驗,怎樣高效的寫出循環?
最新的 RStudio 有 snippet 功能…
兩種方法:
1. 打完 for 停頓 250 毫秒,等提示出現,按回車。2. 打完 for 按 tab,等提示,回車。哪種更高效取決於能不能在 250 毫秒內按下 tab。
謝邀。
少用for的循環,多用Python的list comprehension或map或reduce(通常跟lambda算式用在一起),或R中各樣的apply函數。
PythonList comprehensiona = [2*i for i in range (10)]
map / reduce
a = map(lambda i: 2*i, range(10))
from operator import add
print "sum = ", reduce(add, a)
a&<-mapply(function(i) 2*i, 0:9)
lapply
a&<-lapply(0:9, function(i) 2*i)
Reduce
Reduce(function(i1, i2) {i1+i2}, a)
performance - Why are loops slow in R?這裡面的答案說得很清楚了,for慢的原因就是R的一切都是需要開銷,一個括弧,一個加減號,對比C來說,都是很慢的,而使用for則把這一切都放大了,累積起來,就顯得for慢了。其實for沒有你想像中的慢,放心寫吧影響性能的地方永遠是代碼中最慢的那一部分,千萬不要把程序的每一部分都優化一遍,如果你想把每一個for都想辦法優化,那都不用做其他事情了。。現在我分享一下R語言程序優化的方法吧如何找到最慢的部分?可以使用
lineprof包找到。當你使用lineprof包找到你最慢的部分,你可以嘗試的方法:
- 進行向量化(向量化後還有個好處就是很容易並行化如:parallel包的ParApply)
- 使用高效的包去加速你的程序,如(data.table dplyr等)
- 可以考慮將那部分的代碼使用Rcpp重寫。
不管在Python還是R,在代碼中使用循環都會極大的提升工作效率。
呃。。。然而並不是這樣,至少在R中(和Matlab),使用循環通常是程序運行效率殺手。寫R程序,要避免循環,盡量向量化。當你在「初學小白」的狀態時,其實很多問題都是可以向量化的。
另外,你的問題是如何「高效的寫出循環」,還是寫出高效的循環?前者沒有什麼特別,看看教程就好了。對於後者,大多數人的答案會是讓你向量化,因為R的循環就是很慢。對於真的無法向量化的循環(例如複雜的蒙特卡洛模擬),也會有一些小技巧,比如減少大矩陣/數據框的讀寫次數之類。
關於向量化可以搜索到很多相關文章,知乎也有一些回答,比如:
R語言在哪些情況下for循環可以避免? - R(編程語言)有哪些向量化寫法讓你拍案叫絕? - 數據分析Python寫的不多,主要說一下R。R的特點之一就是向量化運算,在解決問題的過程中,操作的單位不在是單個元素,而是這一類元素的一個有序集合,也就是向量。換句話說,當你用的for的時候,你在操作一個點,當你做向量化運算或者利用lapply時,你操作的是一條線。體育老師教的語文,讓大家見笑了。說點實際的吧,為什麼for比lapply慢。R的for語句在R本身這個層面運行,向量化和lapply則是調運底層的C,自然lapply要快很多。
可以試試Rcpp, Rcpp像是橋樑鏈接C和R。 你可以在C中寫循環然後在R中調用它, 速度會有明顯提升。但如果數據量實在大那大概只能用cluster了。
方法:
1.預先設置好向量類型及長度2.將條件在循環外判斷3.盡量使用ifelse 替代if() else4.盡量使用apply/sapply/各種apply
5.使用compiler包的cmpfun()6.運用並行運算開始舉栗子---------------------------------------------------------------------------------------------------------------------------R代碼:test &<- data.frame(rnorm(12^5, 0, 2))
for(i in nrow(test)){
if(test[i,1] &> 0){
test[i,2] &<- "p"
}
else {
test[i,2] &<- "n"
}
}
方法1:
test &<- data.frame(rnorm(12^5, 0, 2))
add_col &<- character(nrow(test)) # 預先定義類型與長度
for(i in nrow(test)){
if(test[i,1] &> 0){
add_col[i] &<- "p"
}
else {
add_col[i] &<- "n"
}
}
test &<- cbind(test, add_col)
方法2:
test &<- data.frame(rnorm(12^5, 0, 2))
condition &<- test[,1] &> 0 # 預先計算好條件值
test[condition, 2] &<- "p"
test[!condition, 2] &<- "n"
方法3:
test &<- data.frame(rnorm(12^5, 0, 2))
for(i in nrow(test)){
ifelse(test[i,1] &> 0, test[i,2] &<- "p", test[i,2] &<- "n") #盡量用ifelse
}
推薦閱讀:
※如何用R語言匹配兩個表的數據?
※r 如何更新,不需要重裝的手段進行更新?
※R語言 安裝完軟體後如何進行界面語言的設置?
※有哪些比較好的R語言網路視頻教程推薦?
※如何理解R中因子(factor)的概念?
TAG:R編程語言 |