R包開發的標準姿勢


一個R包本質上就是一系列函數的集合,通過調用R包的函數從而實現相應的功能。R包開發對R語言編程能力提升有極大幫助,更能方便理解他人編寫的包,而不僅僅調參。

R語言已經存在上萬的開源包,總會有一個包滿足需求。當一個真香的調參俠纔可節省時間。

以windows系統爲平臺,這裏展示一個開發R包的簡單流程。通過R包的形式實現一個多分類變量啞變量的功能。

可以回覆easydummy下載這個文件夾,雙擊文件夾內easydummy.RprojRstudio打開項目。也可以手擼代碼。

啞變量是以多分類變量取值爲變量,生成1是,0否的情況。如多分類變量爲喜歡喫的水果,取值爲蘋果、香蕉、西瓜。啞變量後,蘋果、香蕉、西瓜各自爲一個單獨變量,取值爲1代表喜歡喫,0代表不喜歡喫。

必要條件

  • 軟件
    • Rstudio(R語言最佳工具)
    • Rtools(win用戶需要安裝Rtools。使用Rstudio生成R包時會提示安裝,自動配置環境)
    • devtools(R包開發輔助包可以幫助生成文檔之類內容)
    • 安裝install.packages("devtools")

本次包的開發需要使用stringr包,自行安裝。

建立R包項目

Rstudio中點擊File - New Project - New Directory - R Package - 給自己R包取名和選擇包地址,確定即可。

這裏命名爲easydummy

R包命名.png

打開項目文件夾

可以看到easydummy文件包含以下內容

  • man(編寫幫助文檔,平時help()函數查看的就是這裏面的內容)
  • R(存放R代碼的地方)
  • DESCRIPTION(R包的相關描述)
  • NAMESPACE(用來規定可以調用的R函數功能,如果這裏沒有寫明,即是R文件夾裏面有相關函數功能也不能在之後調用)
  • 其他(一些項目地址之類的內容,不需要理會)
    項目組成部分.png

Rstudio在建立R包項目時會自動生成一個Hello函數,這裏把R文件夾hello.Rman文件夾hello.Rd以及NAMESPACE文件刪除。

這三者存在聯動關係。實際開發中,使用devtools等輔助包相關函數,可以關注於R函數的編寫,自動生成man文件夾NAMESPACE文件相關內容。

編寫DESCRIPTION文件

在Rstudio中打開DESCRTION文件,編寫包的描述。

相關內容包括:

  • Package:包的名字
  • Type: Package(類型)
  • Title: 包的介紹,這裏的內容就是RstudioPackages面板下各種包的描述
  • Version: 0.1.0(版本號,版本號存在一定規範。這裏只是一個簡單的R包開發教程,不需理會)
  • Author: 作者
  • Maintainer: The package maintainer [email protected](包的貢獻者名字及郵箱)
  • Description: 包的描述
  • License: 許可證(包的公共許可,開源程序的特色。這裏也不理會,以GPL-3爲協議)
  • Encoding: UTF-8(編碼方式)
  • LazyData: true(R包內置數據時選中)
  • Depends : 依賴環境
  • Imports : 需要使用的包
  • Suggests: 建議配合使用的包
  • 其他如網址、bug報告地址等內容,這裏不涉及。

本包的DESCRIPTION如下:

Package: easydummy
Type: Package
Title: make dummy easy
Version: 0.1.0
Author: DA_BY_R
Maintainer: DA_BY_R <[email protected]>
Description: this package was my first package
License: GPL-3
Depends:
  R (>= 3.5.0)
Imports:
	stringr,
    stats
Encoding: UTF-8
LazyData: true

Imports導入包需要使用usethis::use_package('包名')生成。
如usethis::use_package(‘stringr’),usethis::use_package(‘stats’)

編寫R函數

Rstudio中File - New File - R Script生成一個文件,將其命名爲easydummy.R,保存在項目R文件夾內。

接下來就是在easydummy文件中編寫函數內容,以實現功能

學會調用各種基本函數,實現各種功能的過程,對R語言的理解、函數調用與熟悉具有極大的提升。

實現一個啞變量功能,基本函數如下。

本次僅介紹R語言包的開發過程。具體的函數內容並不需要理會,直接複製即可(#後註釋如果有礙觀瞻,也可以刪除)。僅僅是爲了說明R函數功能實現的思路

要實現啞變量功能,需要數據和需要啞變量化的變量位置。因此這裏選擇兩個參數

data:數據框類型數據

loc:變量的位置

easydummy <- function(data,loc) {
#需要數據沒有缺失值
#complete.cases函數判斷數據各行是否完整
#which函數確定提取完整數據的行的位置
#依次選中無缺失值數據
  data <- data[which(complete.cases(data)),]
  #用apply向量化函數替代for循環,遍歷數據
  #用unique函數求各列(變量)唯一值
  unique <- apply(data, 2, unique)
  #得到需要啞變量化的變量的唯一值
  values <- unique[[loc]]
  #建立一個僅含一個變量的空數據框。
  #變量名可以是任何名字(x,y,z之類)會刪除。
  zero <- data.frame(z=0)
  #用for循環遍歷唯一值,將各取值化作變量。
  for (val in values) {
    zero[val] <- 0
  }
  #刪除第一列,即刪除z變量
  #這時爲僅含唯一值轉化的變量的空數據框
  z <- zero[-1]
  #for循環嵌套for循環
  #第一個for循環遍歷數據各行
  #第二個for循環遍歷各唯一值
  for (i in 1:nrow(data)) {
    for (len in 1:length(values)) {
    #用stringr包str_detect函數檢測啞變量的那一列的每行是否存在各唯一值
      if (str_detect(data[i,loc],values[len])==TRUE) {
      #如果存在的話,z空數據框的i行len列等於1
        z[i,len]=1
      }else{
      #如果不存在的話,z空數據框的i行len列等於0
        z[i,len]=0
      }
    }
  }
  #用cbind函數將原數據與z數據框拼接,命名爲data
  data <- cbind(data,z)
  #返回data數據框
  return(data)
}

這個函數如果仔細看還有許多粗糙與改進之處,如啞變量要求多分類變量,可以用變量類型是否爲因子類型縮小搜索範圍。for循環是否可以用向量化函數提升等等。

編寫文檔

使用devtools包相關功能可以專注於R函數功能,編寫文檔只需要在R函數文件內代碼上方以#‘開頭加入各種roxygen2包相關函數即可(無需加載)。

一般來說:

  • 第一段標題

空行

  • 第二段描述

空行

  • 第三段細節

接下來是一些細節文檔

  • @param 函數參數
  • @return 說明本函數返回值
  • @importFrom 包名 函數名 函數名
  • @export不添加,這個函數就不顯示也就不能直接使用
  • @examples提供示例代碼

easydummy函數的代碼與文檔描述爲:

#'@title  easydummy
#'
#'@description  a friendly funtion that dummy your data
#'
#'@details  I used some funtions in base R,like unique,gen a new funtion.
#'by the way,this is my first package,it's true.
#'
#'@param data need a dataframe
#'@param loc  location of your want dummy
#'@return a dataframe
#'@importFrom stats complete.cases
#'@importFrom stringr str_detect
#'@export
#'@examples
#'easydummy(iris,5)
easydummy <- function(data,loc) {
  data <- data[which(complete.cases(data)),]
  unique <- apply(data, 2, unique)
  values <- unique[[loc]]
  zero <- data.frame(z=0)
  for (val in values) {
    zero[val] <- 0
  }
  z <- zero[-1]
  for (i in 1:nrow(data)) {
    for (len in 1:length(values)) {
      if (str_detect(data[i,loc],values[len])==TRUE) {
        z[i,len]=1
      }else{
        z[i,len]=0
      }
    }
  }
  data <- cbind(data,z)
  return(data)
}

建立數據

可以內置數據,以方便包的函數功能展示。

  • easydummy文件夾內新建data文件夾

  • 使用save(數據,file=‘文件名.rda’)方式生成數據

save(iris,file = 'iris.rda')

  • rda文件放在data文件夾下

數據文件描述

如果內置數據同樣需要描述(過程與R代碼文檔類似),在R文件夾內生成data同名R文件iris.R

依次填寫:

  • 標題
  • 描述
  • @docType data (必須填寫,類型必須爲data)
  • @name 數據名 (必須填寫)
  • @format說明文件格式(可選)
  • @soure說明數據來源(可選)
  • NULL(這個文件內容不能爲空,否則不能檢測,填寫NULL表示下存在感)
  • 其他

本包數據描述爲:

#'somedata
#'
#'used to  demo of this package
#'@docType data
#'@name iris
NULL

devtools

使用devtools包document()函數自動生成文檔

Rstudio中ConSole面板輸入devtools::document()

duang~

man文件夾內的內容與NAMESPACE文件就自動生成了

devtools::document()
#餘下爲輸出結果(有刪減)
Updating easydummy documentation
Writing NAMESPACE
Loading easydummy
Writing NAMESPACE
Writing easydummy.Rd
Writing iris.Rd

生成包

Rstudio中點擊Build面板Installand Restart,即自動打包.

也可以點擊Check檢查是否符合規範

生成包.png

試用

生成包完成後可以試用包的效果,以便修改完善。

使用help函數help('easydummy',package = 'easydummy')
可以看到和其他包一樣的幫助文檔
試用.png

函數試用

data <- easydummy(iris,5)
View(data)

完善

這僅僅是一個功能單一的R包,可以不斷添加函數,以完善包。還可以爲這個包添加demo和pdf文檔等等。

具體可以參考書籍:

  • Hadley Wickham:R Packages,
  • Writing R Extensions:繁雜細緻

發表

主要發表平臺爲:

  • cran(符合cran規範)
  • github(沒有條件)

作爲一個自用野包,放在github上,使用devtools包安裝即可。當然某天野包也會轉正。


RR語言小白速通
R懂點R語言
歡迎分享收藏關注

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章