导图社区 循环与函数
循环与函数知识总结,包括循环的逻辑元素、循环的模板、函数的模板、一些函数重要功能的理解等等。
编辑于2022-06-09 22:31:21循环与函数
循环的逻辑元素
其适用与所有语句
在这里我们相对1000个数据集绘图,并保存于gpeg格式
但要保证其语法正确
所有语句都可以是函数
i 从 1变到1000
提取第i个数据集
对于第i个数据集执行计算统计表的函数
对于第i个数据集执行作图与存储的函数
对于第i个数据集执行多元分析的函数
循环结束
优点?
让代码变得容易被人脑所解析
但是其实函数可以分解为一系列基础的命令
i 从 1 变到 1000
提取第i个数据集
对于第i个数据集选取适当的图像标签
针对第i个数据集作图
将第i个数据集的图像存储起来
循环结束
执行方法?
将i换成1-1000,然后将那4步过程执行1000次
循环的模板
1. 载入数据,熟悉变量名,使用read.table,names和str命令
setwd("C:\\Users\\Administrator\\Desktop\\RBook")
Owls <- read.table(file="Owls.txt",header = TRUE)
names(Owls)
str(Owls)
2. 提取一个鸟巢的数据,对于这个子集绘制出同胞写上对到达时间的散点图
unique(Owls$Nest)
Owls.ATV <- Owls[Owls$Nest=="AutavauxTV",]
3. 添加图像的标题以及x轴和y轴的坐标轴名称。此鸟巢的名字应该包含在主题中。
plot(x = Owls.ATV$ArrivalTime, y = Owls.ATV$NegPerChick, xlab = "Arrival Time", main = "AutavauxTV", ylab = "Negotiation behaviour")
4. 提取第二个鸟巢的数据,确定需要对原始图像做哪些修改。
Owls. i <- Owls[Owls$Nest=="Bochet",]
plot(x = Owls.i$ArtrivalTime, y = Owls.i$NegPerChick, xlab = "Arrival Time", main = "Bochet", ylab = "Negotiation behaviour")
把名称存储于Nest.i这个变量中
Nest.i <- "Bochet"
Owls.i <- Owls[Owls$Nest == Nest.i,]
plot(x = Owls.i$ArtrivalTime, y = Owls.i$NegPerChick, xlab = "Arrival Time", main = "Nest.i", ylab = "Negotiation behaviour")
优势:你只需要修改一下名字,之后的都会被自动更改
5. 确定如何将图片存储为jpeg格式。
如何操作jpeg图片
详见?jpeg
1. 选择一个文件名。这个可以是任何名字,例如,“AnyName.jpg"。
2. 通过键入jpeg(file = "AnyName. jpj")打开一个jpeg文件。
3. 使用plot命令来绘制图像。由于你键入了jpeg命令,R将把所有的图像存储为jpeg文件,并且图像的输出不会出现在屏幕上。
可以执行其它的绘图命令如:plot, lines, points, text
4. 通过键入dev.off()关闭jpeg文件。
device off
在执行dev.off命令之后输入的绘图命令都不能讲结果存为jpeg文件,但是会将结果显示在屏幕上。
代码模板
选取x轴和y轴
x <- seq(1:100)
y <- seq(1:100)
将所有的输出都显示在屏幕上
plot(x,y)
lines(x,y)
points(x,y)
将所有输出都存储为jpg文件
jpeg(file="AnyName.jpg")
plot(x,y)
lines(x,y)
points(x,y)
dev.off()
其目的为停止疯狂的存储输出.
在执行dev.off命令之后输入的绘图命令都不将讲结果存为jpeg文件,但是会将结果显示在屏幕上。
再次将所有的输出都显示在屏幕上
plot(x,y) lines(x,y) points(x,y)
关于存储的目录
其实就是setwd定义的
关于存储的文件名
paste函数
paste(Nest.i, ".jpg". sep = " ")
其它存储格式的函数
bmp
png
tiff
postscript
windows
最终代码
setwd("C:/AllGraphs/")
Nest.i <- "Bochet"
Owls.i <- Owls[Owls$Nest == Nest.i,]
YourFileName <- paste(Nest.i, ".jpg", sep = "")
jpeg(file = YourFileName)
plot(x = Owls.i$ArrivalTime, y = Owls.i$NegPerChick, xlab = "Arrival Time", main = Nest.i, ylab = "Negotiation behaviour")
dev.off()
6. 写一个可以提取第i个鸟巢数据的循环,使用第i个鸟巢的数据绘制图像,并将其存储为一个具有易识别的名字的jpeg格式图片。
R中循环的基本语法
for (i in 1 : 27) { do something do something do some thing }
do something 必须是有效的R命令
命令必须放在两个花括号{和}之间
1:27是因为我们有27个鸟巢
将i等价到鸟巢的名字
Nest.i <- AllNests[i]
最终代码
AllNests <- unique(Owls$Nest)
for(i in 1:27){
Nest.i <- AllNests[i]
Owls.i <- Owls[Owls$Nest == Nest.i, ]
YourFileName <- paste(Nest.1, ".jpg", sep = "")
jpeg(file = YourFileName)
plot(x = Owls.i$ArrivalTime, y = Owls.i$NegPerChick, xlab = "Arrival Time", ylab = "Negotiation behaviour", main = Nest.i)
dev.off()
}
函数的模板
功能
将一些输入的数值处理好输出
输入可以是任何格式
可以是一个变量
可以是多个变量
多个时按照变量的输入顺序定为x,y,z,与位置相互匹配
确定数据中有多少零和空
建议每一个变量制作一个表格来给出它含有缺失值和零的个数。
建议对每一种情形使用表格给出缺失值(或零)的个数。
线性回归函数会删除缺失值
而有些多元函数和单变量函数也会导致很多问题
实例
设计一个识别空数量的函数
输入
包含这些数据的数据框
输出
每个变量含有的缺失值个数
语法
NAPerVariable <- function(X1) { D1 <- is.na(X1) colSums(D1) }
你输入到R中看不到任何结果,但之后你就可以执行它...
NAPerVariable(Veg[,5:24])
解析此函数内部执行的操作
X1
函数内部的唯一的参数,列表示变量,行表示观察值
is.na
一种常用语法,其生成了一个与X1维数相同的布尔矩阵
如果X1矩阵中某些元素的值为缺失值,则此矩阵中相应的位置为TRUE值,否则,为FALSE值。
colSums
R中已有的函数,它计算每一列(变量)中元素的和
一般输入是具有数值的矩阵
当使用的对象是布尔矩阵的时候,它会将TRUE转化为1,将FALSE转化为0.
coluSums(D1)输出的是每一个变量的缺失值个数。
用rowSums则是每一个观察值缺失值的个数
识别零数量的函数
ZerosPerVariable <- function(X1) {
D1 = (X1 == 0)
colSums(D1,na.rm = TRUE)
没有na.rm = TRUE,任何位置有NA的变量就会输出NA
}
当 x1 中的元素值为0时,矩阵D1的相应位置取TRUE值, 否则取FALSE值。
然后你可以思考各变量为0值时的意义。
具有多个参数的函数
既能计算观察值中零值数量的和,也能计算观察值中空值数量的和的函数。
VariableInfo <- function(X1, Choice1) {
if (Choice1 == "Zeros"){ D1 = (X1 == 0) }
if (Choice1 == "NAs") { D1 <- is.na(X1)}
colSums(D1, na.rm = TRUE)
}
当确定了此函数代码的正确性并且无bug时,你就可以忘记变量X1,Choice1和D1了,并且不用管函数内部是怎么运行的,你所需知道的就是输入和结果
VariableInfo(Parasite, "Zeros")
VariableInfo(Parasite, "NAs")
把计算结果存储于另一个变量中
Results <- VariableInfo(Parasite, "Zeros")
在操作界面中再次输入Results,将得到和上边相同的结果
技术上的常见问题
函数内部使用的变量名称
X1
位置匹配原则
位置匹配原则,输入的第一个就是X1,跟其名字无关A1,Y1,ASDW1都行,就是按位置
外部变量A,B和C在函数中被相应地成为x,y和z
第一个位置输入的就是第一个参数
问题
这个变量名一定要是一个新的变量名
若是D1 <- is.na(X)则不行
X这个变量在函数外部可能存在,R就不会通知你直接使用其值
给用户结果信息的形式
函数的最后一行代码的结果将是返回信息
NAPerVariable 中最后一行是 colSums(D1)
若函数的最后一行是一个列表,输出也是一个列表
函数兼容的数据集
取决于你内部包含函数的兼容性
colSums命令的工作对象仅可以是包含多个列的数据,或至少是矩阵
通常用##在代码中说明函数的兼容性和输出形式
D1
函数输入错误的提示信息
默认的显示
把choice1的选项拼错
根据位置匹配原则,数据框Parasite和字符串“Zeros"在函数内部分别被称为X1和Choice1
变量Choice1就会等于一个不存在的字符”zeroos",所以此时就不会执行任何命令。
忘记输入choice1
变量Choice1没有值,函数代码的第一行就无法执行。设计函数中很大的一个挑战就是预知可能出现的错误,这里,我们看到了两个很傻的(但是很常见)错误,事实上,针对于此类错误,函数是可以被设计的更稳健的
自己设定的显示
代码如下
你可以看到加了第三个if else
其意思是,当Choice1 的值不等于“Zeros"或”NAs"时,输出警告信息,否则,执行colSums命令。
但这种用一堆if的程序结构虽然方便编写,但是若if太多,检索会花费大量计算量
更加优秀的代码
有ifelse可代替前两个if命令
ifelse(Choice == "Zeros", D1 <- (X1 == 0), D1 <- is. na (X1))
其意思是,如果Choice1的值等于“Zeros", D1 <- (X1 == 0)命令将被执行,其它所有情况下,执行D1 <- is.na(X1)。
用ifelse可以避免检索大量的if指令,或if else指令
默认值保证函数的稳健性
我们可以给变量Choice1赋一个默认值,这样即使Choice在使用中忘输了,函数也能用默认值来计算
你可以看到在choice1后加了个Zeros。。。
所以即使不给变量Choice1赋值也会得到月Choice1="Zeros"相同的结果
不要忘记给默认编写帮助文件
再做一次建筑师
1.载入数据,确定变量的类型,变量的名词,数据的维数等等。
Subtopic
2.计算站点1的生物总量,然后是站点2的,使用尽可能通用的代码来使这一步实现自动化处理,让人也要使代码简洁有效。
3. 计算站点1不同物种的数量,然后是站点2的,使用尽可能通用的代码来使这一步实现自动化处理。
4. 应用同样的方法来处理香农指数。
5. 合并代码并用if指令来实现选择计算不同的指数,注意使用简洁的代码。
6. 将所有代码置入一个函数中,允许用户指定数据和多样性指数。函数需要实现返回实际的指数值并且显示选择了哪种多样性指数(使用字符串)。
最终结果
函数是根据最后一行的命令来返回信息的,所以此处输出是一个list的输出
list可以结合不同维数的数据,所以其可输出一个有45个值的变量和一个所选指数的名称。
需要注意的
if后面小括号里也要用==,即布尔向量的逻辑语言表述等价关系
这里一些函数重要功能的理解
ifelse
ifelse(Choice == "Zeros", D1 <- (X1 == 0), D1 <- is. na (X1))
意义
ifelse(x,y,z)
等于if(x){y} else {z}
paste
YourFileName <- paste(Station.i, ".jpg", sep = "")
Owls$NestNight <- paste(Owls$Nest, "1",sep = "_")
这个函数的x是一个变量,y是一个随便的标记,z是一个分隔符项
输出
将x,y按照z的分隔符连接起来,输出了一个字符
所以其功能是拼接