R语言-实用功能性语句2
本篇文章对工作中使用的R语言实用语句进行总结,方便查找和复用。
目录概览
17)typeof()、mode()、class()组合使用
# oPath <- "D:/"
# oName <- "test"
# oType <- "csv"
# oPathFile <- paste(oPath,oName,'.',oType,sep="",collapse="")
# mydata <- read.csv(oPathFile,header=T)
mydata <- read.table("clipboard",header=T)
class(mydata)
dim(mydata)
head(mydata)
oTBPaste <- function(rowdata, oType){
if(oType==1){
result <- paste("<td>",rowdata,"</td>",sep="",collapse="")
}else if(oType==2){
result <- paste("<th>",rowdata,"</th>",sep="",collapse="")
}
return(result)
}
oTitle <- names(mydata)
# length(oTitle)
oTitle <- paste("<th>",oTitle,"</th>",sep="",collapse="")
oTB1 <- "<table style='width:100%; font-size:8pt;' border=1>"
oTB2 <- paste("<tr style='font-weight: bold;text-align:left;font-size:8pt;color:#990000'>",oTitle,"</tr>",sep="",collapse="")
oTB3 <- apply(mydata, 1, oTBPaste, 1)
# class(oTB3)
# length(oTB3)
oTB4 <- paste("<tr>",oTB3,"</tr>",sep="",collapse="")
oTB5 <- "</table>"
oTB <- paste(oTB1,oTB2,oTB4,oTB5,sep="",collapse="")
# oTB
cat(oTB, "\n")
# oPath <- "C:/Users/abdata/Desktop/"
# oName <- "oTB"
# oType <- "txt"
# oPathFile <- paste(oPath,oName,'.',oType,sep="",collapse="")
# write.csv(oTB,file=oPathFile,row.names=F,quote=F)
library(rjson)
oJs_str <- '{"oTableName":"data_sf_bc_index_price" , "oFieldType":["number", "text", "number"], "oNum":[1, 0, 1]}'
oJs <- fromJSON(oJs_str)
oTableName <- oJs$oTableName
oFieldType <- oJs$oFieldType
oNum <- oJs$oNum
oTableName
oFieldType
oNum
[] 用来提取对象相同的类型,可以包含不止一个元素
[[]] 用来提取额 list或data frame里面的元素,一般只能提取单个的元素
$ 通过名字来提取 list 或 data frame的元素
zz<-c(5,2,-3,8,12,1)
which(zz*zz>8)
[1] 1 3 4 5
### which反馈回来的满足要求的索引号
a[which(a$Ozone>31 & a$Temp>90),]
a[which(a$Month==6),]
mydata[which(mydata$gender=='F' & mydata$age > 65), ]
### 重新提取数据的奇数行
ni[seq(1,nrow(ni),2), ]
### 判断某个数是否存在
aa$a <- c(6,1,4,5,5,1)
if (length(which(aa$a ==100))) print("zzz")
if (length(which(aa$a ==6))) print("zzz")
if (!length(which(aa$a ==6))) print("zzz")
subset(mydata, age >= 20 | age < 10,select=c(ID, Weight))
subset(mydata, sex=="m" & age > 25, select=weight:income)
### 注:& 表示 和, | 表示 或
mydata[sample(1:nrow(mydata), 50,replace=FALSE),]
library(gcookbook) # For the data set
cdat <- subset(countries, Year==2009 & Name %in% c("Canada", "Ireland", "United Kingdom", "United States"))
c2009 <- subset(countries, Year==2009, select=c(Name, GDP, laborrate, healthexp, infmortality))
### subset筛选与索引筛选的区别
#### 索引筛选没法区分NA,不知道该不该删去
> x<-c(6,1:3,NA,12)
> x
[1] 6 1 2 3 NA 12
> x[x>5]
[1] 6 NA 12
> subset(x,x>5)
[1] 6 12
# 有时候会遇见Excel文件,使用R语言读取略显麻烦。写个函数即可,代码如下(注意使用了RODBC包):
xlsx_read <- function(fileName) {
require(RODBC)
conn = odbcConnectExcel(fileName)
sheetName <- sqlTables(conn)$TABLE_NAME
data <- list()
for(i in 1 : length(sheetName)) {
data[[i]] = sqlFetch(conn, sheetName[i])
}
close(conn)
return(data)
}
# 获取目录下所有文件名
filenames=dir("C:/Users/abdata/Desktop/")
## or推荐第二种
setwd("C:/Users/abdata/Desktop/")
filenames=dir()
# 读取文件输出文件
require(data.table)
da<- fread("test_data.csv", header=FALSE)
u<- read.csv("test_data.csv",fileEncoding='gbk',header = TRUE) # 读取gbk编码文件
write.table (out, file ="test_data.csv", sep ="," , row.names=F, col.names=F, quote=F)
# 读写xlsx文件
library("xlsx")
t=read.xlsx('test_data.xlsx',sheetIndex=1)
write.xlsx(t, file="./s.xlsx")
# list在批量读取数据时候的用法:
1、如何循环读取xlsx中的sheet数据,然后批量放入list之中?——先定义list
2、如何定义写出时候的文件名字——paste函数
批量读取的基本流程就是:写入(list[[i]])、操作、写出
#1、读取xlsx中所有的sheet表格
# 如果像vector一样定义List??——list()函数来主动定义,用data.list[[i]]来赋值
data.list<-list()
for (i in 1:2){
data.list[[i]]=read.xlsx("C1.xlsx",i)
}
以上是写入,看看如何写出:
# 3、利用List批量读出操作
# 难点:如果构造输出表格的名称——paste来构造名称
flie=list()
xlsxflie=paste(1:2,".xlsx",sep="")
for(i in 1:2){
flie[[i]]=paste("C:/Users/long/Desktop/",xlsxflie[i],sep="")
write.xlsx(data.list2[[i]],file)
}
写出时候文件名称困扰我很久,如何按照一定的规则来命名,可以先用paste弄好固定格式,然后通过paste[i]循环调用。其中:paste之后会有如vector一般的格式,可以用[i]来调用。
stringsAsFactors=F
# 以前在r里读数据,经常把character读成factor,还得费半天劲把它转回来,尤其是把factor转成numeric还没有那么直接。例如:
dat <- read.csv("C:/Users/abdata/Desktop/test_data.csv", header=T, stringsAsFactors = F)
# 存数据时,经常多出一列id,很讨厌,设置row.names = F,比如:
write.csv(dat, "C:/Users/abdata/Desktop/test_data.csv", row.names = F)
library(jsonlite)
ftag <- "C:/Users/abdata/Desktop/twitter_text_test_period"
data <- readLines(gzfile(paste0(ftag,"1.json.gz")))
datalist <- strsplit(data, '\n')
b <- sapply(datalist, fromJSON)
indx <- sapply(b, length)
df <- as.data.frame(do.call(rbind, lapply(b, 'length<-', max(indx))))
colnames(df) <- names(b[[which.max(indx)]])
options(stringsAsFactors=F, scipen=99) # scipen 科学计数法相关
rm(list=ls())
gc() # 清空垃圾内存
getwd() # 获得工作路径信息
setwd() # 设置工作路径
如果有很多输出项目,那么需要return(终止运算,并输出return中的项目)最终输出的项目。
R中默认的情况是将最后一句作为返回值。
-
return&list组合
sbdeep <- function(data, parts, xiaoz){ parts<-parts # 分几个箱 xiaoz<-xiaoz # 极小值 # 这里以data等比分为4段,步长为1/4 value<-quantile(data,probs = seq(0,1,1/parts)) number<-mapply(function(x){ for (i in 1:(parts-1)) { if(x>=(value[i]-xiaoz)&x<value[i+1]) { return(i) } } if(x+xiaoz>value[parts]) { return(parts) } return(-1) },data) # 打标签L1 L2 L3 L4 return(list(degree=paste("L",number,sep=""),degreevalue=number,value=table(value),number=table(number))) # 将连续变量转化成定序变量,此时为L1,L2,L3,L4...根据parts } return和list的组合输出结果比较合理。 该函数是对单个序列数据进行等深分箱,可以返回四类: 一个基于L1L2L3....的每个指标标签序列degree; 标签序列值degreevalue, 每个百分位数对应的变量值value, 不同百分点的数量number。
-
print直接输出
function(){ print(plot(cv.out)) } function(){ print('hello world') }
# 异常处理,当仅输入一个数据的时候,告知不能计算标准差
if(length(x) == 1){
stop("can not compute sd for one number, a numeric vector required.\n")
}
第一办法:使用Rstudio版本,里面有一个Profiling with profvis,可以很好的对你函数每一步的耗时进行参看。
第二办法:利用difftime函数
t1 = Sys.time()
for (i in 1:5){
a=a+1
b=a*a
print(difftime(Sys.time(), t1, units = 'sec'))
}
先预设当前时间,然后用difftime+print方式,循环输出。
-
提取某List某指标
方法一:先编写一个提取list子集的函数:
subdate<- function(x){ x$DATE }
然后用lapply或者sapply,sapply(s,subdate)看一下出来的结果
方法二:提取DATE内容:
s[[1]]$DATE
变动其中的数字,就可以把每一组的DATE提取出来了。(需要自己编写循环)
方法三:提取长度大于某程度的list
x[lapply(x, length)>100]
用lapply计算每个x的长度。
-
list之间的合并
list之间的合并用:
c(list(1),list(2))
-
1、数值构造函数rep与seq
# 数值构造rep与seq rep(1:4,each=2) # 依次重复1:4两遍 rep(1:4,2) # 注意,重复1:4两遍 seq(from=3,to=5,by=0.2) rep(seq(from=3,to=5,by=0.2),2) # 混合使用
rep在使用过程中也很灵活,each代表AABB;默认的为ABAB。
> rep(c("id","use"),list(2,3)) [1] "id" "id" "use" "use" "use" > rep(c("id","use"),each=2) [1] "id" "id" "use" "use" > rep(c("id","use"),2) [1] "id" "use" "id" "use" > rep(c("id","use"),unlist(2,3)) [1] "id" "use" "id" "use"
rep与list相结合
> rep(c("id","use"),list(2,3)) [1] "id" "id" "use" "use" "use"
可以实现AABBB,与each相似。在构造一些序列时候十分好用。
-
2、矩阵构造
构造矩阵
# byrow按行的顺序(横向)赋值;bycol按列(竖)赋值 matrix(1:15,nrow=3,ncol=5,byrow=T) # 只能按列(竖)赋值 array(1:15,dim=c(3,5))
-
3、字符构造paste
seq代表是ck与数值1 之间用啥记号,如:ck_1,ck*2
collapse代表是ck1与ck2之间用啥记号如:ck1_ck2 ck1 * ck2
字符构造paste
paste("CK", 1:6, sep="") paste("CK", 1:6, sep="*") # 对比 paste("CK", 1:6,collapse = "") paste("CK", 1:6,collapse = "_") # 对比
-
4、paste与list合用——批量处理
list能够很好与paste函数应用起来
paste与list合用
x <- list(a="aaa", b="bbb", c="ccc") y <- list(d=1, e=2) z <- paste(x, y, sep="-") paste("T", z, sep=":")
数据储存形式
data.frame(wi=iris,ci=cars) # 数据框形式,可以直接定义变量名
list(wi=iris,ci=cars) # list,也可以直接定义变量名
注意:attach()、detach()
可以将数据框中的变量释放到Rs内存中,然后就可以直接调用。
attach(iris)
names(setosa)
detach(iris)
在data.frame中,是可以实现数据集重命名的,比如data.frame(x=iris,y=cars),也可以实现横向、纵向重命名,data.frame(x=iris,y=cars,row.names=iris)
数据查看函数
names(iris) # 查看所有变量名字
str(iris) # 变量属性(int整数,num数值)
unique(iris$setosa) # 查看分类变量的水平
table(iris$setosa) # 分类水平,不同水平的个数(=unique+sum功能)
summary(iris) # 所有变量各自的均值、分位数、众数、最大、最小值等统计量,在回归中就是系数表等
attributes(iris) # 包括names(变量名)、row.names(序号的名称)、class(数据形式)
一般names、str、unique会组合使用。
17)typeof()、mode()、class()组合使用
> gl(2,5) # 新建一个因子
[1] 1 1 1 1 1 2 2 2 2 2
Levels: 1 2
> class(gl(2,5)) # 查看变量的类,显示为因子;
[1] "factor"
> mode(gl(2,5)) # 查看数据大类,显示为数值型;
[1] "numeric"
> typeof(gl(2,5)) # 查看数据细类,显示为整数型;
[1] "integer"
从精细度上说,typeof>mode>class
方法 | 解释 |
---|---|
!x | 逻辑非 |
x & y | 逻辑与 |
x && y | 逻辑与(仅匹配并返回第一个值) |
x | y | 逻辑或 |
x || y | 逻辑或(仅返回第一个值) |
x or (x,y) | 异或 |
最常用merge()函数,但是这个函数使用时候这两种情况需要注意:
1、merge(a,b),纯粹地把两个数据集合在一起,没有沟通a、b数据集的by,这样出现的数据很多,相当于a*b条数据;
2、merge函数是匹配到a,b数据集的并,都有的才匹配出来,如果a、b数据集ID不同,要用all=T(下面有all用法的代码)。
# 横向合并
ID<-c(1,2,3,4)
name<-c("Jim","Tony","Lisa","Tom")
score<-c(89,22,78,78)
student1<-data.frame(ID,name)
student2<-data.frame(ID,score)
total_student<-merge(student1,student2,by="ID") #或者rbind()
total_student
# 纵向合并
ID<-c(1,2,3)
name<-c("Jame","Kevin","Sunny")
student1<-data.frame(ID,name)
ID<-c(4,5,6)
name<-c("Sun","Frame","Eric")
student2<-data.frame(ID,name)
total<-cbind(student1,student2)
total
# merge的all用法
> id=c("1","2","3")
> M=c("7","2","3")
> ink2=data.frame(id,M)
>
> merge(ink1,ink2,by="id",all=T) # 所有数据列都放进来,空缺的补值为NA
id R M
1 1 9 7
2 2 7 2
3 4 9 <NA>
4 3 <NA> 3
> merge(ink1,ink2,by="id",all=F) # 默认,只取两者的共有的部分
id R M
1 1 9 7
2 2 7 2
# 其中,all=T代表全连接,all.x=T代表左联结;all.y=T代表右连接
cbind()和rbind(),cbind()按照纵向方向,或者说按列的方式将矩阵连接到一起;rbind()按照横向的方向,或者说按行的方式将矩阵连接到一起。
rbind/cbind对数据合并的要求比较严格:合并的变量名必须一致;数据等长;指标顺序必须一致。相比来说,其他一些方法要好一些,有dplyr,sqldf中的union
-
plyr包
rbind.fill函数可以很好将数据进行合并,并且补齐没有匹配到的缺失值为NA。 # 不等长合并 # 如何解决合并时数据不等长问题——两种方法:do.call函数以及rbind.fill函数(plyr包) # rbind.fill函数只能合并数据框格式 # do.call函数在数据框中执行函数(函数,数据列) library("plyr") #加载获取rbind.fill函数 # 第一种方法 list1<-list() list1[[1]]<-data.frame(t(data.frame(Job_Pwordseg.ct[1]))) list1[[2]]<-data.frame(t(data.frame(Job_Pwordseg.ct[2]))) do.call(rbind.fill,list1) # 第二种方法 u<-rbind.fill(data.frame(t(data.frame(Job_Pwordseg.ct[1]))),data.frame(t(data.frame(Job_Pwordseg.ct[2])))) 核心函数是plyr包中的rbind.fill函数(合并的数据,必须是data.frame),do.call可以用来批量执行。
-
dplyr包
dplyr::bind_rows() 效果是,不匹配到的放在最后,且等于NA NA NA NA
©哈尔滨商业大学 银河统计工作室
银河统计工作室成员由在校统计、计算机部分师生和企业数据数据分析师组成,维护和开发银河统计网和银河统计博客(技术文档)。专注于数据挖掘技术研究和运用,探索统计学、应用数学和IT技术有机结合,尝试大数据条件下新型统计学教学模式。