R语言-实用功能性语句2

(2017-05-30 银河统计)

  本篇文章对工作中使用的R语言实用语句进行总结,方便查找和复用。

目录概览

1)R语言生成表格html

2)Json格式数据和R格式数据互转

3)[ ]数据的提取

4)which的用法

5)Subset

6)R读取excel数据

7)R设置stringsAsFactors=F问题相关

8)使用R读取json文件并转成data.frame

9)R运行环境初始化

10)R中函数的输出—print、return&list

11)异常值处理——如何报错

12)如何在循环中,实时输出时间消耗

13)“列表”用法小结

14)构造新序列

15)数据框和列表--直接定义变量名

16)names、str、unique组合使用

17)typeof()、mode()、class()组合使用

18)逻辑运算

19)数据合并-merge()函数

20)cbind和rbind函数

21)不等长合并

22)语句22

23)语句23

24)语句24

25)语句25

26)语句26

27)语句27

28)语句28

29)语句29

30)语句30


1)R语言生成表格html

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(oType1){
result <- paste("",rowdata,"",sep="",collapse="")
}else if(oType
2){
result <- paste("",rowdata,"",sep="",collapse="")
}
return(result)

}

oTitle <- names(mydata)
# length(oTitle)
oTitle <- paste("",oTitle,"",sep="",collapse="")
oTB1 <- "

"
oTB2 <- paste("",oTitle,"",sep="",collapse="")
oTB3 <- apply(mydata, 1, oTBPaste, 1)
# class(oTB3)
# length(oTB3)
oTB4 <- paste("",oTB3,"",sep="",collapse="")
oTB5 <- "
"
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)

2)Json格式数据和R格式数据互转

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

3)[ ]数据的提取

[] 用来提取对象相同的类型,可以包含不止一个元素
[[]] 用来提取额 list或data frame里面的元素,一般只能提取单个的元素
$ 通过名字来提取 list 或 data frame的元素

4)which的用法

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")

5)Subset

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, Year2009 & 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

6)R读取excel数据

有时候会遇见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]来调用。

7)R设置stringsAsFactors=F问题相关

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)

8)使用R读取json文件并转成data.frame

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)]])

9)R运行环境初始化

options(stringsAsFactors=F, scipen=99) # scipen 科学计数法相关
rm(list=ls())
gc() # 清空垃圾内存
getwd() # 获得工作路径信息
setwd() # 设置工作路径

10)R中函数的输出—print、return&list

如果有很多输出项目,那么需要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')
    }

11)异常值处理——如何报错

异常处理,当仅输入一个数据的时候,告知不能计算标准差

if(length(x) == 1){
stop("can not compute sd for one number, a numeric vector required.\n")
}

12)如何在循环中,实时输出时间消耗

第一办法:使用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方式,循环输出。

13)“列表”用法小结

  • 提取某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))

14)构造新序列

  • 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="😊

15)数据框和列表--直接定义变量名

数据储存形式

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)

16)names、str、unique组合使用

数据查看函数

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

18)逻辑运算

方法解释
!x逻辑非
x & y逻辑与
x && y逻辑与(仅匹配并返回第一个值)
x | y逻辑或
x || y逻辑或(仅返回第一个值)
x or (x,y)异或

19)数据合并-merge()函数

最常用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
4 3 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代表右连接

20)cbind和rbind函数

cbind()和rbind(),cbind()按照纵向方向,或者说按列的方式将矩阵连接到一起;rbind()按照横向的方向,或者说按行的方式将矩阵连接到一起。

rbind/cbind对数据合并的要求比较严格:合并的变量名必须一致;数据等长;指标顺序必须一致。相比来说,其他一些方法要好一些,有dplyr,sqldf中的union

21)不等长合并

  • 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

22)语句22

23)语句23

24)语句24

25)语句25

26)语句26

27)语句27

28)语句28

29)语句29

30)语句30

posted @ 2017-05-30 22:23  银河统计  阅读(1276)  评论(0)    收藏  举报