R-应用流行病学和公共卫生-2.R语言基础

名词解释

  • RStudio - RStudio 是一个图形用户界面 (GUI),可以更轻松地使用
  • 对象- 您存储在 R 中的所有内容 - 数据集、变量、列表、总人口数,甚至是图形等输出 -是分配了名称并且可以在以后的命令中引用的对象。
  • 函数- 函数是接受输入并返回转换后的输出的代码块。
  • - R 包是可共享的功能包。
  • 脚本- 脚本是保存您的命令的文档文件。

学习资源

  • Rstudio网站:RStudio Cheatsheets - RStudio
  • Rstudio帮助文档:输入 ?函数名 回车,即可查看该函数,同时Rstudio页面有包列表,点击进入即可查看在线文档
  • Twitter:这个资源需要,打不开,有兴趣的可以去原文网址查看

软件下载安装

R语言官网:R: The R Project for Statistical Computing,下载后按照安装引导安装即可,更新方式:installr::updateR()

Rstudio官网:Download the RStudio IDE - RStudio,下载后按照安装引导安装即可,更新方式:“帮助”->“检查更新”

TinyTex 是一个自定义的 LaTeX 发行版,在尝试从 R 生成 PDF 时很有用

install.packages('tinytex')
tinytex::install_tinytex()
# to uninstall TinyTeX, run tinytex::uninstall_tinytex()

Pandoc 是一个文档转换器,是一个独立于 R 的软件。它与 RStudio 捆绑在一起,不需要下载。它有助于将 Rmarkdown 文档转换为 .pdf 等格式并添加复杂功能。

RTools 是用于为 R 构建包的软件集合,网址为:https://cran.r-project.org/bin/windows/Rtools/

phantomjs 这通常用于拍摄网页的“截图”。例如,当您使用epicontacts包制作传输链时,会生成一个交互式和动态的 HTML 文件。如果你想要一个静态图像,使用webshot包来自动化这个过程会很有用。这将需要外部程序“phantomjs”。您可以使用命令通过webshot包安装 phantomjs webshot::install_phantomjs()

Rstudio简介

RStudio是一个界面 (GUI),可以更轻松地使用R。您可以将 R 视为车辆的引擎,做关键的工作,而 RStudio 则视为车辆的主体(包括座椅、配件等),帮助您实际使用引擎前进!您可以在此处查看完整的 RStudio 用户界面文档 (PDF)

页面介绍

默认情况下,RStudio 显示四个矩形窗格。

R-应用流行病学和公共卫生-2.R语言基础_第1张图片

源窗格:默认情况下,该窗格位于左上角,是编辑、运行和保存脚本的空间。此窗格还可以显示数据集(数据框)以供查看。

R 控制台窗格:R 控制台,默认情况下位于 R Studio 的左侧或左下窗格,是 R“引擎”的主页。这是实际运行命令并出现非图形输出和错误/警告消息的地方。您可以直接在 R 控制台中输入和运行命令,但要同步保存到脚本中,否则将不会被保存。

环境窗格:此窗格默认位于右上角,最常用于查看当前会话中 R 环境中对象的简要摘要。这些对象可能包括导入、修改或创建的数据集、您定义的参数或您在分析期间定义的向量或列表。您可以单击数据框名称旁边的箭头以查看其变量。

绘图、查看器、包和帮助窗格:右下方的窗格包括几个重要的选项卡。包括文档列表,可用于打开或删除文件;绘图窗口展示左侧命令运行得到的图像;Packages 窗格允许您查看、安装、更新、删除、加载/卸载 R 包,并查看您拥有的包的版本;帮助窗口展示相应的文档和帮助文件。

快捷键

Windows/Linux Mac Action
Esc Esc Interrupt current command (useful if you accidentally ran an incomplete command and cannot escape seeing “+” in the R console)
Ctrl+s Cmd+s Save (script)
Tab Tab Auto-complete
Ctrl + Enter Cmd + Enter Run current line(s)/selection of code
Ctrl + Shift + C Cmd + Shift + c comment/uncomment the highlighted lines
Alt + - Option + - Insert <-
Ctrl + Shift + m Cmd + Shift + m Insert %>%
Ctrl + l Cmd + l Clear the R console
Ctrl + Alt + b Cmd + Option + b Run from start to current line
Ctrl + Alt + t Cmd + Option + t Run the current code section (R Markdown)
Ctrl + Alt + i Cmd + Shift + r Insert code chunk (into R Markdown)
Ctrl + Alt + c Cmd + Option + c Run current code chunk (R Markdown)
up/down arrows in R console Same Toggle through recently run commands
Shift + up/down arrows in script Same Select multiple code lines
Ctrl + f Cmd + f Find and replace in current script
Ctrl + Shift + f Cmd + Shift + f Find in files (search/replace across many scripts)
Alt + l Cmd + Option + l Fold selected code
Shift + Alt + l Cmd + Shift + Option+l Unfold selected code

函数

函数就像一台机器,它接收输入,对这些输入执行一些操作,然后产生输出。输出是什么取决于功能。函数通常对放置在函数括号内的某些对象进行操作。例如,该函数sqrt()计算一个数的平方根:

sqrt(49)
## [1] 7

提供给函数的对象也可以是数据集中的一列。因为 R 可以存储多个数据集,所以您需要同时指定数据集和列。一种方法是使用$符号来链接数据集的名称和列的名称 ( dataset$column)。在下面的示例中,该函数summary()应用于age数据集中的数值列linelist,输出是该列的数值和缺失值的汇总。

# Print summary statistics of column 'age' in the dataset 'linelist'
summary(linelist$age)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    0.00    6.00   13.00   16.07   23.00   84.00      86

函数可以要求几个输入,称为arguments,位于函数的括号内,通常用逗号分隔。

例子,age_pyramid()生成性别年龄金字塔图。该函数在括号内给出了三个参数,用逗号分隔。

# Create an age pyramid
age_pyramid(
  data = linelist,        # use case linelist
  age_group = "age_cat5", # provide age group column
  split_by = "gender"     # use gender column for two sides of pyramid
  )

如果参数以特定顺序编写,则不需要指定参数分配

age_pyramid(
  linelist,                    # use case linelist
  "age_cat5",                  # age group column
  "gender",                    # split by gender
  proportional = TRUE,         # percents instead of counts
  pal = c("orange", "purple")  # colors
  )

 包

安装及加载

原始方法

# install a single package with base R
install.packages("tidyverse")

# install multiple packages with base R
install.packages(c("tidyverse", "rio", "here"))
# load packages for use, with base R
library(tidyverse)
library(rio)
library(here)

使用pacman

# Install (if necessary) and load packages for use
pacman::p_load(rio, tidyverse, here)
# install/load the epicontacts package from its Github repository
p_load_gh("reconhub/epicontacts")
# install the "timeline" branch of the epicontacts package from Github
p_load_gh("reconhub/epicontacts@timeline")

从压缩包安装

# install the package from a URL
packageurl <- "https://cran.r-project.org/src/contrib/Archive/dsr/dsr_0.2.2.tar.gz"
install.packages(packageurl, repos=NULL, type="source")
# install the package from a zip
remotes::install_local("~/Downloads/dplyr-master.zip")
install.packages("~/Downloads/dplyr-master.zip", repos=NULL, type="source")

代码语法

为了在本手册中清晰起见,函数有时会在其包名之前使用::符号以下列方式开头:package_name::function_name(),一旦为会话加载了包,就不需要这种显式样式。一个可以用function_name()plot()但是,当函数名很常见并且可能存在于多个包中时, 如果尚未加载,写入包名也会加载该包。

# This command uses the package "rio" and its function "import()" to import a dataset
linelist <- rio::import("linelist.xlsx", which = "Sheet1")

卸载

p_delete()
remove.packages()

查看依赖

# See the dependencies of a package
p_depends()
# see which packages depend on it
p_depends_reverse()

脚本

注释

在R中注释一般使用#

风格

提倡tidyverse 风格指南。还有一些包比如stylerlintr可以帮助你适应这种风格。

基本的点:
* 命名对象时,仅使用小写字母、数字和下划线_,例如 my_data
* 使用频繁的空格,包括运算符周围,例如 n = 1age_new <- age_old + 3

示例:

R-应用流行病学和公共卫生-2.R语言基础_第2张图片

R markdown

R markdown 脚本是一种 R 脚本,其中脚本本身成为输出文档(PDF、Word、HTML、Powerpoint 等)。是非常有用且用途广泛的工具,通常用于创建动态和自动化报告。

R notebooks

在 Rmarkdown 和 R 笔记本中书写没有区别。然而,文件的执行略有不同。有关更多详细信息,请参阅此站点。

Shiny

shiny应用程序/网站包含在一个脚本中,必须命名为app.R. 该文件包含三个组件:

  1. 用户界面 (ui)
  2. 服务器功能
  3. shinyApp函数的调用

请参阅Dashboards with Shiny上的手册页面,或在线教程:Shiny tutorial

代码折叠

您可以折叠部分代码以使您的脚本更易于阅读。

为此,请使用# 创建一个文本标题,编写您的标题,并在其后面添加至少 4 个破折号 (-)、井号 (#) 或等号 (=)。完成此操作后,左侧的“装订线”中将出现一个小箭头。您可以单击此箭头和下面的代码,直到下一个标题折叠并在其位置出现双箭头图标。要展开代码,请再次单击装订线中的箭头或双箭头图标。

R-应用流行病学和公共卫生-2.R语言基础_第3张图片

 工作目录

使用R-project规定项目位置(推荐),或者使用setwd()指定工作目录。

对象

R 中的一切都是对象,而 R 是一种“面向对象”的语言:

  • 如何创建对象 ( <-)
  • 对象的类型(例如数据框、向量..)
  • 如何访问对象的子部分(例如数据集中的变量)
  • 对象的类别(例如数字、逻辑、整数、双精度、字符、因子)

定义对象 ( <-)

通过使用 <- 运算符为对象分配一个值来创建对象。

current_week <- "2018-W10" # this command creates the object current_week by assigning it a value
current_week  # this command prints the current value of current_week object in the console

注意: 可以随时通过运行分配命令重新定义其值来覆盖对象的值。因此,命令运行的顺序非常重要

等号=

您还将在 R 代码中看到等号:

  • 两个对象或值之间的双等号==提出了一个逻辑问题:“这等于那个吗?”。
  • 您还将在用于指定函数参数值的函数中看到等号(在下面的部分中阅读这些内容),例如max(age, na.rm = TRUE).
  • 可以使用单个等号=代替<-来创建和定义对象,但不鼓励这样做。您可以在此处了解为什么不鼓励这样做。

数据集

数据集也是对象(通常是“数据框”),在导入时必须指定名称。

# linelist is created and assigned the value of the imported CSV file
linelist <- import("my_linelist.csv")

注意:关于对象命名的快速说明:

  • 对象名称不得包含空格,但应使用下划线 (_) 或句点 (.) 代替空格。
  • 对象名称区分大小写(意味着 Dataset_A 与 dataset_A 不同)。
  • 对象名称必须以字母开头(不能以 1、2 或 3 等数字开头)。

数据集中的列也是对象,可以定义、覆盖和创建

# create new "bmi" column using base R syntax
linelist$bmi <- linelist$wt_kg / (linelist$ht_cm/100)^2

但是,在本手册中,我们强调了一种定义列的不同方法,它使用mutate()dplyr包中的函数并使用管道运算符 ( %>%) 进行。该语法更易于阅读,并且在清理数据和核心功能页面中解释了其他优点。

# create new "bmi" column using dplyr syntax
linelist <- linelist %>% 
  mutate(bmi = wt_kg / (ht_cm/100)^2)

对象结构

对象可以是单个数据(例如 my_number <- 24),也可以由结构化数据组成。

下图是从这个在线 R 教程中借用的。它显示了一些常见的数据结构及其名称。此图像中不包括空间数据,在GIS 基础页面中进行了讨论。

R-应用流行病学和公共卫生-2.R语言基础_第4张图片

在流行病学(尤其是现场流行病学)中,您最常遇到数据框和向量:

Common structure Explanation Example
Vectors A container for a sequence of singular objects, all of the same class (e.g. numeric, character). “Variables” (columns) in data frames are vectors (e.g. the column age_years).
Data Frames Vectors (e.g. columns) that are bound together that all have the same number of rows.

linelist is a data frame.

请注意,要创建一个“独立”(不是数据框的一部分)的向量,c()用于组合不同的元素。例如,如果创建一个颜色向量图的色标:vector_of_colors <- c("blue", "red2", "orange", "grey")

对象类

存储在 R 中的所有对象都有一个,该类告诉 R 如何处理该对象。有许多可能的类,但常见的包括:

Class Explanation Examples
Character These are text/words/sentences “within quotation marks”. Math cannot be done on these objects. “Character objects are in quotation marks”
Integer Numbers that are whole only (no decimals) -5, 14, or 2000
Numeric These are numbers and can include decimals. If within quotation marks they will be considered character class. 23.1 or 14
Factor These are vectors that have a specified order or hierarchy of values An variable of economic status with ordered values
Date Once R is told that certain data are Dates, these data can be manipulated and displayed in special ways. See the page on Working with dates for more information. 2018-04-12 or 15/3/1954 or Wed 4 Jan 1980
Logical Values must be one of the two special values TRUE or FALSE (note these are not “TRUE” and “FALSE” in quotation marks) TRUE or FALSE
data.frame A data frame is how R stores a typical dataset. It consists of vectors (columns) of data bound together, that all have the same number of observations (rows). The example AJS dataset named linelist_raw contains 68 variables with 300 observations (rows) each.
tibble tibbles are a variation on data frame, the main operational difference being that they print more nicely to the console (display first 10 rows and only columns that fit on the screen) Any data frame, list, or matrix can be converted to a tibble with as_tibble()
list A list is like vector, but holds other objects that can be other different classes A list could hold a single number, and a dataframe, and a vector, and even another list within it!

您可以通过将对象的名称提供给函数来测试对象的类class()。注意:您可以使用$来引用数据集中的特定列。

高级提示:一些更复杂的对象(例如列表或epicontacts对象)可能有多个级别,可以通过多个美元符号访问。例如epicontacts$linelist$date_onset

有时,您需要将对象或列转换为另一个类:

Function Action
as.character() Converts to character class
as.numeric() Converts to numeric class
as.integer() Converts to integer class
as.Date() Converts to Date class - Note: see section on dates for details
factor() Converts to factor - Note: re-defining order of value levels requires extra arguments

使用括号()[]访问/索引

您可能需要查看对象的某些部分,也称为“索引”,这通常使用方括号来完成[ ]。使用$进行数据框访问列也是一种索引。

my_vector <- c("a", "b", "c", "d", "e", "f")  # define the vector
my_vector[5]                                  # print the 5th element
## [1] "e"

括号还可用于返回返回输出的特定部分,例如summary()函数的输出。

括号也适用于数据框以查看特定的行和列。您可以使用以下语法执行此操作dataframe[rows, columns]

# View a specific row (2) from dataset, with all columns (don't forget the comma!)
linelist[2,]

# View all rows, but just one column
linelist[, "date_onset"]

# View values from row 2 and columns 5 through 10
linelist[2, 5:10] 

# View values from row 2 and columns 5 through 10 and 18
linelist[2, c(5:10, 18)] 

# View rows 2 through 20, and specific columns
linelist[2:20, c("date_onset", "outcome", "age")]

# View rows and columns based on criteria
# *** Note the dataframe must still be named in the criteria!
linelist[linelist$age > 25 , c("date_onset", "outcome", "age")]

# Use View() to see the outputs in the RStudio Viewer pane (easier to read) 
# *** Note the capital "V" in View() function
View(linelist[2:20, "date_onset"])

# Save as a new object
new_table <- linelist[2:20, c("date_onset")] 

请注意,您还可以使用dplyr语法

# View first 100 rows
linelist %>% head(100)

# Show row 5 only
linelist %>% filter(row_number() == 5)

# View rows 2 through 20, and three specific columns (note no quotes necessary on column names)
linelist %>% filter(row_number() %in% 2:20) %>% select(date_onset, outcome, age)

索引类list的对象时,即使只返回一个对象,单括号也总是与类列表一起返回。但是,双括号可用于访问单个元素并返回与列表不同的类。

# define demo list
my_list <- list(
  # First element in the list is a character vector
  hospitals = c("Central", "Empire", "Santa Anna"),
  # second element in the list is a data frame of addresses
  addresses   = data.frame(
    street = c("145 Medical Way", "1048 Brown Ave", "999 El Camino"),
    city   = c("Andover", "Hamilton", "El Paso")
    )
  )

my_list
## $hospitals
## [1] "Central"    "Empire"     "Santa Anna"
## 
## $addresses
##            street     city
## 1 145 Medical Way  Andover
## 2  1048 Brown Ave Hamilton
## 3   999 El Camino  El Paso

my_list[1] # this returns the element in class "list" - the element name is still displayed
## $hospitals
## [1] "Central"    "Empire"     "Santa Anna"

my_list[[1]] # this returns only the (unnamed) character vector
## [1] "Central"    "Empire"     "Santa Anna"

my_list[["hospitals"]] # you can also index by name of the list element
## [1] "Central"    "Empire"     "Santa Anna"

my_list[[1]][3] # this returns the third element of the "hospitals" character vector
## [1] "Santa Anna"

my_list[[2]][1] # This returns the first column ("street") of the address data frame
##            street
## 1 145 Medical Way
## 2  1048 Brown Ave
## 3   999 El Camino

移除对象

您可以通过将名称放在rm()函数中(不带引号)从 R 环境中删除单个对象:

rm(object_name)

您可以通过运行删除所有对象(清除工作区):

rm(list = ls(all = TRUE))

管道

简单地说,管道运算符 ( %>%) 将中间输出从一个函数传递到下一个函数。
你可以把它想象成“那么”。许多功能可以用 链接在一起%>%

  • 管道强调一系列动作,而不是正在执行动作的对象
  • 当必须对一个对象执行一系列操作时,管道是最好的
  • 管道来自包magrittr,它自动包含在包dplyr和tidyverse 中
  • 管道可以让代码更干净、更容易阅读、更直观

在 tidyverse样式指南中阅读有关此方法的更多信息,管道不是基本功能。要使用管道,必须安装并加载magrittr包(这通常通过加载包含它的tidyversedplyr包来完成)。您可以在 magrittr 文档中阅读有关管道的更多信息。

# A fake example of how to bake a cake using piping syntax

cake <- flour %>%       # to define cake, start with flour, and then...
  add(eggs) %>%   # add eggs
  add(oil) %>%    # add oil
  add(water) %>%  # add water
  mix_together(   # mix together
    utensil = spoon,
    minutes = 2) %>%    
  bake(degrees = 350,   # bake
    system = "fahrenheit",
    minutes = 35) %>%  
  let_cool()            # let it cool down

%<>% magrittr包中的一个“分配管道”,它向前传递一个对象并重新定义该对象。它必须是链中的第一个管道运算符。它是速记。以下两个命令是等价的:

linelist <- linelist %>%
  filter(age > 50)

linelist %<>% filter(age > 50)

关键操作符和功能

赋值运算符

<-

R 中的基本赋值运算符是<-. 这样object_name <- value
这个赋值运算符也可以写成=。我们建议将<-用于一般 R 用途。
为了便于阅读,我们还建议在这些运算符周围加上空格。

<<-

如果编写函数,或以与源脚本交互的方式使用 R,那么您可能需要使用此赋值运算符<<-(来自基本R)。此运算符用于在更高的“父”R 环境中定义对象。请参阅此在线参考。

%<>%

这是magrittr包中的一个“分配管道”,它向前传递一个对象并重新定义该对象。它必须是链中的第一个管道运算符。

%<+%

这用于使用ggtree包将数据添加到系统发育树。请参阅系统发育树页面或在线资源。

关系和逻辑运算符

关系运算符比较值,通常在定义新变量和数据集子集时使用。以下是 R 中常见的关系运算符:

Meaning Operator Example Example Result
Equal to == "A" == "a" FALSE (because R is case sensitive) Note that == (double equals) is different from = (single equals), which acts like the assignment operator <-
Not equal to != 2 != 0 TRUE
Greater than > 4 > 2 TRUE
Less than < 4 < 2 FALSE
Greater than or equal to >= 6 >= 4 TRUE
Less than or equal to <= 6 <= 4 FALSE
Value is missing is.na() is.na(7) FALSE (see page on Missing data)
Value is not missing !is.na() !is.na(7) TRUE

逻辑运算符(例如 AND 和 OR)通常用于连接关系运算符并创建更复杂的条件。复杂的语句可能需要括号 ( ) 用于分组和应用顺序。

Meaning Operator
AND &
OR | (vertical bar)
Parentheses ( ) Used to group criteria together and clarify order of operations

缺失值

要测试一个值是否为NAis.na(),请使用返回TRUE的特殊函数FALSE

rdt_result <- c("Positive", "Suspected", "Positive", NA)   # two positive cases, one suspected, and one unknown
is.na(rdt_result)  # Tests whether the value of rdt_result is NA
## [1] FALSE FALSE FALSE  TRUE

数学和统计学

此页面中的所有运算符和函数都可以使用base R自动使用。

Purpose Example in R
addition 2 + 3
subtraction 2 - 3
multiplication 2 * 3
division 30 / 5
exponent 2^3
order of operations ( )

数学函数

Purpose Function
rounding round(x, digits = n)
rounding janitor::round_half_up(x, digits = n)
ceiling (round up) ceiling(x)
floor (round down) floor(x)
absolute value abs(x)
square root sqrt(x)
exponent exponent(x)
natural logarithm log(x)
log base 10 log10(x)
log base 2 log2(x)

科学计数法:使用科学记数法的可能性取决于scipen期权的价值。如果将其设置为较低的数字(例如 0),它将始终“打开”。要在 R 会话中“关闭”科学记数法,请将其设置为非常高的数字,例如:

# turn off scientific notation
options(scipen=999)

四舍五入

危险: round()使用“银行家四舍五入法”,仅当上限为偶数时才从 0.5 向上舍入。使用round_half_up()from janitor始终将一半四舍五入到最接近的整数。

统计功能

注意:默认情况下,以下函数将在计算中包含缺失值。NA除非指定了参数,否则缺少值将导致输出na.rm = TRUE。这可以简写为na.rm = T.

Objective Function
mean (average) mean(x, na.rm=T)
median median(x, na.rm=T)
standard deviation sd(x, na.rm=T)
quantiles* quantile(x, probs)
sum sum(x, na.rm=T)
minimum value min(x, na.rm=T)
maximum value max(x, na.rm=T)
range of numeric values range(x, na.rm=T)
summary** summary(x)

其他有用的功能

Objective Function Example
create a sequence seq(from, to, by) seq(1, 10, 2)
repeat x, n times rep(x, ntimes) rep(1:3, 2) or rep(c("a", "b", "c"), 3)
subdivide a numeric vector cut(x, n) cut(linelist$age, 5)
take a random sample sample(x, size) sample(linelist$id, size = 5, replace = TRUE)

%in%

一个非常有用的运算符,用于匹配值,以及快速评估值是否在向量或数据框中

my_vector <- c("a", "b", "c", "d")
"a" %in% my_vector
## [1] TRUE
"h" %in% my_vector
## [1] FALSE

要询问一个值是否不是 向量,请在逻辑语句%in%加上感叹号 (!) :

# to negate, put an exclamation in front
!"a" %in% my_vector
## [1] FALSE
!"h" %in% my_vector
## [1] TRUE

%in%在使用dplyr函数时非常有用case_when()。您可以先定义一个向量,然后再引用它。例如:

affirmative <- c("1", "Yes", "YES", "yes", "y", "Y", "oui", "Oui", "Si")

linelist <- linelist %>% 
  mutate(child_hospitaled = case_when(
    hospitalized %in% affirmative & age < 18 ~ "Hospitalized Child",
    TRUE                                      ~ "Not"))

错误与警告

运行命令时,R 控制台可能会以红色文本显示警告或错误消息。

  • 警告意味着 R 已完成您的命令,但必须采取其他步骤或产生您应该注意的异常输出。

  • 错误意味着 R 无法完成您的命令。

可能的问题:

  • 错误/警告消息通常会包含问题的行号。

  • 如果一个对象“未知”或“未找到”,可能是您拼写错误,忘记使用 library() 调用包,或者忘记在更改后重新运行脚本。

在 R 中编写命令时要记住几件事,以避免错误和警告:

  • 右括号检查 - 提示:计算每个代码块的左括号“(”和右括号“)”的数量
  • 避免列名和对象名中的空格。请改用下划线 (_) 或句点 (.)
  • 跟踪并记住用逗号分隔函数的参数
  • R区分大小写,含义Variable_A不同于variable_A

当您犯错时,任何脚本(RMarkdown 或其他)都会提供线索。例如,如果您忘记在需要的地方写逗号或关闭括号,RStudio 将在该行的脚本右侧引发一个标志,以警告您。

你可能感兴趣的:(流病,r语言)