在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
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 <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 21 6 160 110 3.9 2.620 16.46 0 1 4 4 2 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 <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> 1 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 2 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 3 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 4 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 5 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 6 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 7 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 8 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2 9 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2 10 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 * <dbl> <dbl> <dbl> <dbl> 1 160.0 110 3.90 2.620 2 160.0 110 3.90 2.875 3 108.0 93 3.85 2.320 4 258.0 110 3.08 3.215 5 360.0 175 3.15 3.440 6 225.0 105 2.76 3.460 7 360.0 245 3.21 3.570 8 146.7 62 3.69 3.190 9 140.8 95 3.92 3.150 10 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 <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <int> 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 1 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 2 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 3 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 4 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 5 6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 6 7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 7 8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 8 9 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 <dbl> 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 <dbl> <int> 1 4 11 2 6 7 3 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:将原数据框中的所有列赋给一个新变量key value:将原数据框中的所有值赋给一个新变量value …:可以指定哪些列聚到同一列中 na.rm:是否删除缺失值 widedata <- data.frame(person=c('Alex','Bob','Cathy'),grade=c(2,3,4),score=c(78,89,88)) widedata person grade score 1 Alex 2 78 2 Bob 3 89 3 Cathy 4 88 longdata <- gather(widedata, variable, value,-person) longdata person variable value 1 Alex grade 2 2 Bob grade 3 3 Cathy grade 4 4 Alex score 78 5 Bob score 89 6 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 wt 1 AMC Javelin 0 2 8 304 3.15 3 150 15.2 17.30 0 3.435 2 Cadillac Fleetwood 0 4 8 472 2.93 3 205 10.4 17.98 0 5.250 3 Camaro Z28 0 4 8 350 3.73 3 245 13.3 15.41 0 3.840 4 Chrysler Imperial 0 4 8 440 3.23 3 230 14.7 17.42 0 5.345 5 Datsun 710 1 1 4 108 3.85 4 93 22.8 18.61 1 2.320 6 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 information 1 Alex-2-78 2 Bob-3-89 3 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 score 1 Alex 2 78 2 Bob 3 89 3 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) DF DT identical(dim(DT), dim(DF)) # TRUE identical(DF$a, DT$a) # TRUE is.list(DF) # TRUE is.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 DF DT=as.data.table(DF,keep.rownames=TRUE) setDT(x, keep.rownames=FALSE, key=NULL, check.names=FALSE) 把一个R对象转化为data.table,比as.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是新列名 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: TRUE data.table=getOption("datatable.fread.datatable") # default: TRUE ) input输入的文件,或者字符串(至少有一个"\n"); 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等; data.table数据框结构处理语法data.table[ i , j , by] i 决定显示的行,可以是整型,可以是字符,可以是表达式,j 是对数据框进行求值,决定显示的列,by对数据进行指定分组,除了by ,也可以添加其它的一系列参数: i 决定显示的行DT = data.table(x=rep(c("b","a","c"),each=3), y=c(1,3,6), v=1:9) #新建data.table对象DT DT[2] #取第二行 DT[2:3] #取第二到第三行 DT[order(x)] #将DT按照X列排序,简化操作,另外排序也可以setkey(DT,x),出来的DT就已经是按照x列排序的了。用haskey(DT)判断DT是否已经设置了key,可以设置多个列作为key DT[y>2] # DT$y>2的行 DT[!2:4] #除了2到4行剩余的行 DT["a",on="x"] #on 参数,DT[D,on=c("x","y")]取DT上"x","y"列上与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",on=.(x)]如果有几个key的话推荐用on DT[x!="b" | y!=3] #x列不等于"b"或者y列不等于3的行 DT[.("b", 3), on=.(x, v)] #取DT的x,v列上x="b",v=3的行 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.table DT[, 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 对数据进行分组 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用最近的行填充 |
请发表评论