参考:R package: https://r-pkgs.org/index.html
接着上一次的文章:R包开发基本步骤(上)
Step4
Edit DESCRIPTION
我们可以看到上次的warning里面,有提到关于license和document的问题:
Non-standard license specification
Undocumented code objects: 'fbind'
这是因为我们没有对函数进行任何说明,也没有声明包的作者、许可等信息
Make these edits:
- Make yourself the author.
- Write some descriptive text in the
Title
andDescription
fields.
直接在Rstudio里打开Description文件,编辑成像下面的样子:
Package: foofactors
Title: Make Factors Less Aggravating
Version: 0.0.0.9000
Authors@R:
person("Jane", "Doe", email = "jane@example.com", role = c("aut", "cre"))
Description: Factors have driven people to extreme measures, like ordering
custom conference ribbons and laptop stickers to express how HELLNO we
feel about stringsAsFactors. And yet, sometimes you need them. Can they
be made less maddening? Let's find out.
License: What license it uses
Encoding: UTF-8
LazyData: true
use_mit_license()
这里用的是MIT的license,需要在Description中写好,然后用use_mit_license进行声明
use_mit_license("Jane Doe")
#> ✔ Setting License field in DESCRIPTION to 'MIT + file LICENSE'
#> ✔ Writing 'LICENSE.md'
#> ✔ Adding '^LICENSE\\.md$' to '.Rbuildignore'
#> ✔ Writing 'LICENSE'
这时目录下多了一个LICENSE文件
打开license文件,确认里面的信息:
YEAR: 2019
COPYRIGHT HOLDER: Jane Doe
document()
平常需要查某个函数的帮助文档时就是用help,如果我们也希望自己的函数可以通过help调出帮助文档呢?这里需要对函数添加document,这些document都放在man文件夹下
package called roxygen2 handle the creation of
man/fbind.Rd
打开fbind脚本,把光标插入函数里任意地方,然后点击 Code > Insert roxygen skeleton,编辑如下:
#' Bind two factors
#'
#' Create a new factor from two existing factors, where the new factor's levels
#' are the union of the levels of the input factors.
#'
#' @param a factor
#' @param b factor
#'
#' @return factor
#' @export
#' @examples
#' fbind(iris$Species[c(1, 51, 101)], PlantGrowth$group[c(1, 11, 21)])
这还不够,注意要用document函数对我们添加的comment进行更新:
document()
#> Updating foofactors documentation
#> Updating roxygen version in /tmp/RtmpsJ87ir/foofactors/DESCRIPTION
#> Writing NAMESPACE
#> Loading foofactors
#> Writing NAMESPACE
#> Writing fbind.Rd
测试下:
?fbind
NAMESPACE
changes
上一步document函数执行以后更新了NAMESPACE文件,像下面这样:
# Generated by roxygen2: do not edit by hand
export(fbind)
命名空间里的export声明了该函数可以通过library进行调用:
The export directive in
NAMESPACE
is what makesfbind()
available to a user after attaching foofactors vialibrary(foofactors)
. Just as it is entirely possible to author.Rd
files “by hand”, you can manageNAMESPACE
explicitly yourself. But we choose to delegate this to devtools (and roxygen2).
check()
again
重新检查,发现原来的两个warning没有了:
check()
#> ── R CMD check results ───────────────────────── foofactors 0.0.0.9000 ────
#> Duration: 8.8s
#>
#> 0 errors ✔ | 0 warnings ✔ | 0 notes ✔
Step5
install()
可以说我们现在有了一个最小最简单的完整的R包,可以通过install()
下载到我们的library中了:
install()
checking for file ‘/tmp/RtmpsJ87ir/foofactors/DESCRIPTION’ ...
✔ checking for file ‘/tmp/RtmpsJ87ir/foofactors/DESCRIPTION’
─ preparing ‘foofactors’:
checking DESCRIPTION meta-information ...
✔ checking DESCRIPTION meta-information
─ checking for LF line-endings in source and make files and shell scripts
─ checking for empty or unneeded directories
─ building ‘foofactors_0.0.0.9000.tar.gz’
Running /home/travis/R-bin/lib/R/bin/R CMD INSTALL \
/tmp/RtmpsJ87ir/foofactors_0.0.0.9000.tar.gz --install-tests
* installing to library ‘/home/travis/R/Library’
* installing *source* package ‘foofactors’ ...
** using staged installation
** R
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
** testing if installed package can be loaded from final location
** testing if installed package keeps a record of temporary installation path
* DONE (foofactors)
而且fbind函数可以正常使用:
library(foofactors)
a <- factor(c("character", "hits", "your", "eyeballs"))
b <- factor(c("but", "integer", "where it", "counts"))
fbind(a, b)
#> [1] character hits your eyeballs but integer where it
#> [8] counts
#> Levels: but character counts eyeballs hits integer where it your
use_testthat()
先载入必要包:library(testthat)
接着上次写的fbind函数,我们希望可以对函数做更细节化的测试,可以用到use_testthat()
这个函数,初始化一个test的环境:
use_testthat()
#> ✔ Adding 'testthat' to Suggests field in DESCRIPTION
#> ✔ Creating 'tests/testthat/'
#> ✔ Writing 'tests/testthat.R'
#> ● Call `use_test()` to initialize a basic test file and open it for editing.
接着,我们用use_test
对具体的函数进行测试,这会生成新的tests目录和函数的测试文件:
use_test("fbind")
#> ✔ Increasing 'testthat' version to '>= 2.1.0' in DESCRIPTION
#> ✔ Writing 'tests/testthat/test-fbind.R'
在test-fbind.R这个文件里写入下列内容:
test_that("fbind() binds factor (or character)", {
x <- c("a", "b")
x_fact <- factor(x)
y <- c("c", "d")
z <- factor(c("a", "b", "c", "d"))
expect_identical(fbind(x, y), z)
expect_identical(fbind(x_fact, y), z)
})
这里就是为了测试一下fbind函数的输出结果是否和预期相符。
然后run一下:
test()
#> ✔ | OK F W S | Context
#>
⠏ | 0 | fbind
✔ | 2 | fbind
#>
#> ══ Results ════════════════════════════════════════════════════════════════
#> OK: 2
#> Failed: 0
#> Warnings: 0
#> Skipped: 0
没有报错说明test结果是和预期相符的。
use_package()
注意我们写的函数可能需要用到其他包里的函数,哪怕是很常见的utils::head()
,也是需要从其他包的命名空间里import的。如果没有import,在check的时候会有warning。
use_package("forcats")
#> ✔ Adding 'forcats' to Imports field in DESCRIPTION
#> ● Refer to functions with `forcats::fun()`
这时在DESCRIPTION文件里会出现Import forcats
然后我们再补充一个函数:
use_r("fcount")
#> ● Edit 'R/fcount.R'
添加如下:
#' Make a sorted frequency table for a factor
#'
#' @param x factor
#'
#' @return A tibble
#' @export
#' @examples
#' fcount(iris$Species)
fcount <- function(x) {
forcats::fct_count(x, sort = TRUE)
}
load_all()
在这里就是模拟一下包的下载安装过程
load_all()
#> Loading foofactors
fcount(iris$Species)
#> # A tibble: 3 x 2
#> f n
#> <fct> <int>
#> 1 setosa 50
#> 2 versicolor 50
#> 3 virginica 50
同样要更新帮助文档:
document()
#> Updating foofactors documentation
#> Writing NAMESPACE
#> Loading foofactors
#> Writing NAMESPACE
#> Writing fcount.Rd
use_github()
怎么把Rstudio的项目和Github关联起来呢?参考:
https://happygitwithr.com/new-github-first.html
use_readme_rmd()
如果你的R包已经在Github上了,那么一个完整的README.md文件将显得尤为重要,也就是每个R包的home page,记录了整个R包的完整信息
use_readme_rmd()
函数初始化一个可执行的Rmarkdown文档待编辑:
use_readme_rmd()
#> ✔ Writing 'README.Rmd'
#> ✔ Adding '^README\\.Rmd$' to '.Rbuildignore'
#> ✔ Writing '.git/hooks/pre-commit'
功能是:
README.Rmd
already has sections that:
- Prompt you to describe the purpose of the package.
- Provide code to install your package.
- Prompt you to show a bit of usage.
完整的编辑内容示例如下:
---
output:
md_document:
variant: markdown_github
---
<!-- README.md is generated from README.Rmd. Please edit that file -->
```{r, echo = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "README-"
)
```
**NOTE: This is a toy package created for expository purposes, for the second edition of [R Packages](https://r-pkgs.org). It is not meant to actually be useful. If you want a package for factor handling, please see [forcats](https://forcats.tidyverse.org).**
### foofactors
Factors are a very useful type of variable in R, but they can also be very aggravating. This package provides some helper functions for the care and feeding of factors.
### Installation
```{r installation, eval = FALSE}
devtools::install_github("jennybc/foofactors")
```
### Quick demo
Binding two factors via `fbind()`:
```{r}
library(foofactors)
a <- factor(c("character", "hits", "your", "eyeballs"))
b <- factor(c("but", "integer", "where it", "counts"))
```
Simply catenating two factors leads to a result that most don't expect.
```{r}
c(a, b)
```
The `fbind()` function glues two factors together and returns factor.
```{r}
fbind(a, b)
```
Often we want a table of frequencies for the levels of a factor. The base `table()` function returns an object of class `table`, which can be inconvenient for downstream work.
```{r}
set.seed(1234)
x <- factor(sample(letters[1:5], size = 100, replace = TRUE))
table(x)
```
The `fcount()` function returns a frequency table as a tibble with a column of factor levels and another of frequencies:
```{r}
fcount(x)
```
然后我们要制作README.md文件,需要执行这个Rmarkdown:
rmarkdown::render("README.Rmd") ## or use "Knit HTML" in RStudio
然后README.md就自动生成了。
The end: check()
and install()
最终检查:
check()
#> ── R CMD check results ───────────────────────── foofactors 0.0.0.9000 ────
#> Duration: 9.6s
#>
#> 0 errors ✔ | 0 warnings ✔ | 0 notes ✔
没有问题,那就可以安装使用了
install()
网友评论