您好,欢迎来到尚车旅游网。
搜索
您的当前位置:首页R语言之数据处理常用包

R语言之数据处理常用包

来源:尚车旅游网
R语⾔之数据处理常⽤包

dplyr包是Hadley Wickham的新作,主要⽤于数据清洗和整理,该包专注dataframe数据格式,从⽽⼤幅提⾼了数据处理速度,并且提供了与其它数据库的接⼝;tidyr包的作者是Hadley Wickham, 该包⽤于“tidy”你的数据,这个包常跟dplyr结合使⽤。dplyr、tidyr包安装及载⼊

install.packages(\"dplyr\")install.packages(\"tidyr\")library(dplyr)library(tidyr)

使⽤datasets包中的mtcars数据集做演⽰,⾸先将过长的数据整理成友好的tbl_df数据:

mtcars_df = tbl_df(mtcars)

⼀、dplyr包基本操作 1.1 筛选: filter()

按给定的逻辑判断筛选出符合要求的⼦数据集

filter(mtcars_df,mpg==21,hp==110)

# A tibble: 2 x 11

mpg cyl disp hp drat wt qsec vs am gear carb

1 21 6 160 110 3.9 2.620 16.46 0 1 4 42 21 6 160 110 3.9 2.875 17.02 0 1 4 4

 1.2 排列: arrange()

按给定的列名依次对⾏进⾏排序:

arrange(mtcars_df, disp) #可对列名加 desc(disp) 进⾏倒序

# A tibble: 32 x 11

mpg cyl disp hp drat wt qsec vs am gear carb

1 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 12 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 23 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 14 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 15 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 26 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 17 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 18 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 29 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 210 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2# ... with 22 more rows

 1.3 选择: select()

⽤列名作参数来选择⼦数据集:

select(mtcars_df, disp:wt)# A tibble: 32 x 4

disp hp drat wt

* 1 160.0 110 3.90 2.6202 160.0 110 3.90 2.8753 108.0 93 3.85 2.3204 258.0 110 3.08 3.2155 360.0 175 3.15 3.4406 225.0 105 2.76 3.4607 360.0 245 3.21 3.5708 146.7 62 3.69 3.1909 140.8 95 3.92 3.15010 167.6 123 3.92 3.440# ... with 22 more rows

 1.4 变形: mutate()

对已有列进⾏数据运算并添加为新列:

mutate(mtcars_df,

NO = 1:dim(mtcars_df)[1])

# A tibble: 32 x 12

mpg cyl disp hp drat wt qsec vs am gear carb NO

1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 12 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 23 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 34 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 45 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 56 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 67 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 78 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 89 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 9

10 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 10# ... with 22 more rows

 1.5 汇总: summarise()

对数据框调⽤其它函数进⾏汇总操作, 返回⼀维的结果:

summarise(mtcars_df,

mdisp = mean(disp, na.rm = TRUE))# A tibble: 1 x 1 mdisp 1 230.7219

 1.6 分组: group_by()

当对数据集通过group_by()添加了分组信息后,mutate(),arrange() 和 summarise() 函数会⾃动对这些 tbl 类数据执⾏分组操作。

cars <- group_by(mtcars_df, cyl)

countcars <- summarise(cars, count = n()) # count = n()⽤来计算次数# A tibble: 3 x 2 cyl count 1 4 112 6 73 8 14

  

  1.7 连接符%>%

  包⾥还新引进了⼀个操作符, 使⽤时把数据名作为开头, 然后依次对此数据进⾏多步操作.

Batting %>%group_by(playerID) %>%summarise(total = sum(G)) %>%arrange(desc(total)) %>%head(5)

⼆、tidyr包基本操作

 2.1 宽转长:gather()

使⽤gather()函数实现宽表转长表,语法如下:

gather(data, key, value, …, na.rm = FALSE, convert = FALSE)data:需要被转换的宽形表

key:将原数据框中的所有列赋给⼀个新变量keyvalue:将原数据框中的所有值赋给⼀个新变量value…:可以指定哪些列聚到同⼀列中na.rm:是否删除缺失值

widedata <- data.frame(person=c('Alex','Bob','Cathy'),grade=c(2,3,4),score=c(78,89,88))widedata

person grade score1 Alex 2 782 Bob 3 893 Cathy 4 88

longdata <- gather(widedata, variable, value,-person)longdata

person variable value1 Alex grade 22 Bob grade 33 Cathy grade 44 Alex score 785 Bob score 896 Cathy score 88

 2.2 长转宽:spread()

有时,为了满⾜建模或绘图的要求,往往需要将长形表转换为宽形表,或将宽形表变为长形表。如何实现这两种数据表类型的转换。使⽤spread()函数实现长表转宽表,语法如下:

spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE)data:为需要转换的长形表

key:需要将变量值拓展为字段的变量value:需要分散的值

fill:对于缺失值,可将fill的值赋值给被转型后的缺失值

mtcarsSpread <- mtcarsNew %>% spread(attribute, value)head(mtcarsSpread)

car am carb cyl disp drat gear hp mpg qsec vs wt1 AMC Javelin 0 2 8 304 3.15 3 150 15.2 17.30 0 3.4352 Cadillac Fleetwood 0 4 8 472 2.93 3 205 10.4 17.98 0 5.2503 Camaro Z28 0 4 8 350 3.73 3 245 13.3 15.41 0 3.8404 Chrysler Imperial 0 4 8 440 3.23 3 230 14.7 17.42 0 5.3455 Datsun 710 1 1 4 108 3.85 4 93 22.8 18.61 1 2.3206 Dodge Challenger 0 2 8 318 2.76 3 150 15.5 16.87 0 3.520

 2.3 合并:unit()unite的调⽤格式如下:

unite(data, col, …, sep = “_”, remove = TRUE)data:为数据框

col:被组合的新列名称…:指定哪些列需要被组合

sep:组合列之间的连接符,默认为下划线

remove:是否删除被组合的列

wideunite<-unite(widedata, information, person, grade, score, sep= \"-\")wideunite information1 Alex-2-782 Bob-3-893 Cathy-4-88

 2.4 拆分:separate()

separate()函数可将⼀列拆分为多列,⼀般可⽤于⽇志数据或⽇期时间型数据的拆分,语法如下:

separate(data, col, into, sep = “[^[:alnum:]]+”, remove = TRUE,convert = FALSE, extra = “warn”, fill = “warn”, …)data:为数据框

col:需要被拆分的列

into:新建的列名,为字符串向量sep:被拆分列的分隔符

remove:是否删除被分割的列

widesep <- separate(wideunite, information,c(\"person\",\"grade\",\"score\"), sep = \"-\")widesep

person grade score1 Alex 2 782 Bob 3 893 Cathy 4 88

三、data.table

R语⾔data.table包是⾃带包data.frame的升级版,⽤于数据框格式数据的处理,最⼤的特点快。包括两个⽅⾯,⼀⽅⾯是写的快,代码简洁,只要⼀⾏命令就可以完成诸多任务,另⼀⽅⾯是处理快,内部处理的步骤进⾏了程序上的优化,使⽤多线程,甚⾄很多函数是使⽤C写的,⼤⼤加快数据运⾏速度。因此,在对⼤数据处理上,使⽤data.table⽆疑具有极⾼的效率。这⾥我们主要讲的是它对数据框结构的快捷处理。可见separate()函数和unite()函数的功能相反。和data.frame的⾼度兼容

DT = data.table(x=rep(c(\"b\",\"a\",\"c\"),each=3), y=c(1,3,6), v=1:9)

下⾯DT都是⽤这个data.table

可见它是属于data.table和data.frame类,并且取列,维数,都可以采⽤data.frame的⽅法。

DF = data.frame(x=rep(c(\"b\",\"a\",\"c\"),each=3), y=c(1,3,6), v=1:9)DT = data.table(x=rep(c(\"b\",\"a\",\"c\"),each=3), y=c(1,3,6), v=1:9)DFDT

identical(dim(DT), dim(DF)) # TRUEidentical(DF$a, DT$a) # TRUEis.list(DF) # TRUEis.list(DT) # TRUE

is.data.frame(DT) # TRUE

不过data.frame默认将⾮数字转化为因⼦;⽽data.table 会将⾮数字转化为字符data.table数据框也可使⽤dplyr包的管道,这⾥不作阐述。

data.table常⽤的函数

as.data.table(x, keep.rownames=FALSE, ...) 将⼀个R对象转化为data.table,R可以时⽮量,列表,data.frame等,keep.rownames决定是否保留⾏名或者列表名,默认FALSE,如果TRUE,将⾏名存在\"rn\"⾏中,keep.rownames=\"id\⾏名保存在\"id\"⾏中。

DF = data.frame(x=rep(c(\"b\",\"a\",\"c\"),each=3), y=c(1,3,6), v=1:9) #新建data.frame DFDT=as.data.table(DF,keep.rownames=TRUE)

setDT(x, keep.rownames=FALSE, key=NULL, check.names=FALSE) 把⼀个R对象转化为data.table,⽐as.data.table快,因为以传地址的⽅式直接修改原对象,没有拷贝

copy(x) 深度拷贝⼀个data.table,x即data.table对象。data.table为了加快速度,会直接在对象地址修改,因此如果需要就要在修改前copy,直接修改的命令有:=添加⼀列,set系列命令⽐如下⾯提到的setattr,setnames,setorder等;当使⽤dt_names = names(DT)的时候,修改dt_names会修改原data.table的列名,如果不想被修改,这个时候应copy原data.table,也可以使⽤dt_names <- copy(names(DT))直接copy列名,这样不必copy整个data.table。

kDT=copy(DT) #kDT时DT的⼀个copy

rowid(..., prefix=NULL)  产⽣unique的id,prefix参数在id前⾯加前缀

setattr 设置DT的属性,setattr(x,name,value) x时data.table,list或者data.frame,⽽name时属性名,value时属性值,setnames(x,old,new),设置x的列名,old是旧列名或者数字位置,new是新列名

setcolorder(x,neworder) 重新安排列的顺序,neworder字符⽮量或者⾏数

set(DT,rownum,colnum,value)直接修改某个位置的值,rownum⾏号,colnum,列号,⾏号列号推荐使⽤整型,保证最快速度,⽅法是在数字后⾯加L,⽐如1L,value是需要赋予的值。⽐:=还快,通常和循环配合使⽤

⾄于这个操作究竟有多快,可以看⼀下(参照官⽅manual的命令),另外个⼈觉得最⽜的三个函数是set(),fread,和fwrite

fread

fread(input, sep=\"auto\", sep2=\"auto\", nrows=-1L, header=\"auto\", na.strings=\"NA\", file,stringsAsFactors=FALSE, verbose=getOption(\"datatable.verbose\"), autostart=1L,skip=0L, select=NULL, drop=NULL, colClasses=NULL,integer64=getOption(\"datatable.integer64\"),# default: \"integer64\"

dec=if (sep!=\".\") \".\" else \, col.names,

check.names=FALSE, encoding=\"unknown\", quote=\"\\\"\",

strip.white=TRUE, fill=FALSE, blank.lines.skip=FALSE, key=NULL,showProgress=getOption(\"datatable.showProgress\"), # default: TRUEdata.table=getOption(\"datatable.fread.datatable\") # default: TRUE)

input输⼊的⽂件,或者字符串(⾄少有⼀个\"\\n\");sep列之间的分隔符;

sep2,分隔符内再分隔的分隔符,功能还没有应⽤;nrow,读取的⾏数,默认-l全部,nrow=0仅仅返回列名;header第⼀⾏是否是列名;na.strings,对NA的解释;

file⽂件路径,再确保没有执⾏shell命令时很有⽤,也可以在input参数输⼊;stringsASFactors是否转化字符串为因⼦,verbose,是否交互和报告运⾏时间;

autostart,机器可读这个区域任何⾏号,默认1L,如果这⾏是空,就读下⼀⾏;

skip跳过读取的⾏数,为1则从第⼆⾏开始读,设置了这个选项,就会⾃动忽略autostart选项,也可以是⼀个字符,skip=\"string\那么会从包含该字符的⾏开始读;select,需要保留的列名或者列号,不要其它的;

drop,需要取掉的列名或者列号,要其它的;

colClasses,类字符⽮量,⽤于罕见的覆盖⽽不是常规使⽤,只会使⼀列变为更⾼的类型,不能降低类型;integer64,读如64位的整型数;

dec,⼩数分隔符,默认\".\"不然就是\

col.names,给列名,默认试⽤header或者探测到的,不然就是V+列号;

encoding,默认\"unknown\",其它可能\"UTF-8\"或者\"Latin-1\",不是⽤来重新编码的,⽽是允许处理的字符串在本机编码;

quote,默认\"\"\",如果以双引开头,fread强有⼒的处理⾥⾯的引号,如果失败了就会⽤其它尝试,如果设置quote=\"\默认引号不可⽤strip.white,默认TRUE,删除结尾空⽩符,如果FALSE,只取掉header的结尾空⽩符;fill,默认FALSE,如果TRUE,不等长的区域可以⾃动填上,利于⽂件顺利读⼊;blank.lines.skip,默认FALSE,如果TRUE,跳过空⽩⾏key,设置key,⽤⼀个或多个列名,会传递给setkeyshowProgress,TRUE会显⽰脚本进程,R层次的C代码data.table,TRUE返回data.table,FALSE返回data.frame

实例如下,1.8GB的数据读⼊94秒,可见读⼊⽂件速度⾮常快,

fwrite

fwrite(x, file = \"\", append = FALSE, quote = \"auto\",sep = \, sep2 = c(\"\",\"|\",\"\"),

eol = if (.Platform$OS.type==\"windows\") \"\\r\\n\" else \"\\n\",

na = \"\", dec = \".\", row.names = FALSE, col.names = TRUE,qmethod = c(\"double\",\"escape\"),

logicalAsInt = FALSE, dateTimeAs = c(\"ISO\",\"squash\",\"epoch\",\"write.csv\"),buffMB = 8L, nThread = getDTthreads(),

showProgress = getOption(\"datatable.showProgress\"),verbose = getOption(\"datatable.verbose\"))

x,具有相同长度的列表,⽐如data.frame和data.table等;file,输出⽂件名,\"\"意味着直接输出到操作台;append,如果TRUE,在原⽂件的后⾯添加;

quote,如果\"auto\因⼦和列名只有在他们需要的时候才会被加上双引号,例如该部分包括分隔符,或者以\"\\n\"结尾的⼀⾏,或者双引号它⾃⼰,如果FALSE,那么区域不会加上双引号,如果TRUE,就像写⼊CSV⽂件⼀样,除了数字,其它都加上双引号;sep,列之间的分隔符;

sep2,对于是list的⼀列,写出去时list成员间以sep2分隔,它们是处于⼀列之内,然后内部再⽤字符分开;eol,⾏分隔符,默认Windows是\"\\r\\n\其它的是\"\\n\";na,na值的表⽰,默认\"\";

dec,⼩数点的表⽰,默认\".\";

row.names,是否写出⾏名,因为data.table没有⾏名,所以默认FALSE;

col.names ,是否写出列名,默认TRUE,如果没有定义,并且append=TRUE和⽂件存在,那么就会默认使⽤FALSE;qmethod,怎样处理双引号,\"escape\类似于C风格,⽤反斜杠逃避双引,“double\默认,双引号成对;logicalAsInt,逻辑值作为数字写出还是作为FALSE和TRUE写出;

dateTimeAS, 决定 Date/IDate,ITime和POSIXct的写出,\"ISO\"默认,-2016-09-12, 18:12:16和2016-09-12T18:12:16.999999Z;\"squash\和

20160912181216999;\"epoch\,65536和1473703936;\"write.csv\",就像write.csv⼀样写⼊时间,仅仅对POSIXct有影响,as.character将digits.secs转化字符并通过R内部UTC转回本地时间。前⾯三个选项都是⽤新的特定C代码写的,较快buffMB,每个核⼼给的缓冲⼤⼩,在1到1024之间,默认80MBnThread,⽤的核⼼数。

showProgress,在⼯作台显⽰进程,当⽤file==\"\"时,⾃动忽略此参数verbose,是否交互和报告时间

data.table数据框结构处理语法

data.table[ i , j , by]

   i 决定显⽰的⾏,可以是整型,可以是字符,可以是表达式,j 是对数据框进⾏求值,决定显⽰的列,by对数据进⾏指定分组,除了by ,也可以添加其它的⼀系列参数:

keyby,with,nomatch,mult,rollollends,which,.SDcols,on。

i 决定显⽰的⾏

DT = data.table(x=rep(c(\"b\",\"a\",\"c\"),each=3), y=c(1,3,6), v=1:9) #新建data.table对象DTDT[2] #取第⼆⾏

DT[2:3] #取第⼆到第三⾏

DT[order(x)] #将DT按照X列排序,简化操作,另外排序也可以setkey(DT,x),出来的DT就已经是按照x列排序的了。⽤haskey(DT)判断DT是否已经设置了key,可以设置多个列作为keyDT[y>2] # DT$y>2的⾏

DT[!2:4] #除了2到4⾏剩余的⾏

DT[\"a\",on=\"x\"] #on 参数,DT[D,on=c(\"x\取DT上\"x\列上与D上“x\"、\"y\"的列相关联的⾏,与D进⾏merge。⽐如此例取出DT 中 X 列为\"a\"的⾏,和\"a\"进⾏merge。on参数的第⼀列必须是DT的第⼀列DT[.(\"a\"), on=\"x\"] #和上⾯⼀样.()有类似与c()的作⽤DT[\"a\", on=.(x)] #和上⾯⼀样

DT[x==\"a\"] # 和上⾯⼀样,和使⽤on⼀样,都是使⽤⼆分查找法,所以它们速度⽐⽤data.frame的快。也可以⽤setkey之后的DT,输⼊DT[\"a\"]或者DT[\"a\如果有⼏个key的话推荐⽤onDT[x!=\"b\" | y!=3] #x列不等于\"b\"或者y列不等于3的⾏DT[.(\"b\", 3), on=.(x, v)] #取DT的x,v列上x=\"b\的⾏

j 对数据框进⾏求值输出

  j 参数对数据进⾏运算,⽐如sum,max,min,tail等基本函数,输出基本函数的计算结果,还可以⽤n输出第n列,.N(总列数,直接在j输⼊.N取最后⼀列),:=(直接在data.table上添加列,没有copy过程,所以快,有需要的话注意备份),.SD输出⼦集,.SD[n]输出⼦集的第n列,DT[,.(a = .(), b = .())] 输出⼀个a、b列的数据框,.()就是

要输⼊的a、b列的内容,还可以将⼀系列处理放⼊⼤括号,如{tmp <- mean(y);.(a = a-tmp, b = b-tmp)}

DT[,y] #返回y列,⽮量

DT[,.(y)] #返回y列,返回data.tableDT[, sum(y)] #对y列求和

DT[, .(sv=sum(v))] #对y列求和,输出sv列,列中的内容就是sum(v)DT[, .(sum(y)), by=x] # 对x列进⾏分组后对各分组y列求总和

DT[, sum(y), keyby=x] #对x列进⾏分组后对各分组y列求和,并且结果按照x排序DT[, sum(y), by=x][order(x)] #和上⾯⼀样,采取data.table的链接符合表达式

DT[v>1, sum(y), by=v] #对v列进⾏分组后,取各组中v>1的⾏出来,各组分别对定义的⾏中的y求和DT[, .N, by=x] #⽤by对DT ⽤x分组后,取每个分组的总列数

DT[, .SD, .SDcols=x:y] #⽤.SDcols 定义SubDadaColums(⼦列数据),这⾥取出x到之间的列作为⼦集,然后.SD 输出所有⼦集DT[2:5, cat(y, \"\\n\")] #直接在j ⽤cat函数,输出2到5列的y值

DT[, plot(a,b), by=x] #直接在j⽤plot函数画图,对于每个x的分组画⼀张图

DT[, m:=mean(v), by=x] #对DT按x列分组,直接在DT上再添加⼀列m,m的内容是mean(v),直接修改并且不输出到屏幕上DT[, m:=mean(v), by=x] [] #加[]将结果输出到屏幕上

DT[,c(\"m\",\"n\"):=list(mean(v),min(v)), by=x][] # 按x分组后同时添加m,n 两列,内容是分别是mean(v)和min(v),并且输出到屏幕DT[, `:=`(m=mean(v),n=min(v)),by=x][] #内容和上⾯⼀样,另外的写法DT[,(seq = min(y):max(v)), by=x] #输出seq列,内容是min(a)到max(b)

DT[, c(.(y=max(y)), lapply(.SD, min)), by=x, .SDcols=y:v] #对DT取y:v之间的列,按x分组,输出max(y),对y到v之间的列每列求最⼩值输出。

by,on,with等参数

by 对数据进⾏分组

on DT[D,on=c(\"x\取DT上\"x\列上与D上\"x\列相关联的⾏,并与D进⾏merge

DT[X, on=\"x\"] #左联接X[DT, on=\"x\"] #右联接

DT[X, on=\"x\", nomatch=0] #内联接,nomatch=0表⽰不返回不匹配的⾏,nomatch=NA表⽰以NA返回不匹配的值

with 默认是TRUE,列名能够当作变量使⽤,即x相当于DT$\"x\当是FALSE时,列名仅仅作为字符串,可以⽤传统data.frame⽅法并且返回data.table,x[, cols,with=FALSE] 和x[, .SD, .SDcols=cols]⼀样

mult 当有i 中匹配到的有多⾏时,mult控制返回的⾏,\"all\"返回全部(默认),\"first\返回第⼀⾏,\"last\"返回最后⼀⾏

roll 当i中全部⾏匹配只有某⼀⾏不匹配时,填充该⾏空⽩,+Inf(或者TRUE)⽤上⼀⾏的值填充,-Inf⽤下⼀⾏的值填充,输⼊某数字时,表⽰能够填充的距离,near⽤最近的⾏填充

rollends 填充⾸尾不匹配的⾏,TRUE填充,FALSE不填充,与roll⼀同使⽤

which TRUE返回匹配的⾏号,NA返回不匹配的⾏号,默认FALSE返回匹配的⾏

.SDcols 取特定的列,然后.SD就包括了页写选定的特定列,可以对这些⼦集应⽤函数处理

allow.cartesian FALSE防⽌结果超出nrow(x)+nrow(i)⾏,常常因为i中有重复的列⽽超出。这⾥的cartesian和传统上的cartesian不⼀样。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- sceh.cn 版权所有

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务