R4DS:在线电子书用于学习tidyverse的用法
数据科学处理使用tidyverse
data.table
大数据处理首选data.table,多CPU并行运算,100G内存即可支持20亿行的基准测试。速度读取写入速度都比dplyr快。
R和python的数据处理包的速度对比评测
性能评测一般是:group_by和join函数,显然data.table速度快于dplyr.
dplyr data.table
dplyr data.table对比
tidyverse
包含多个包
-ggplot2 用于可视化
-dplyr 数据处理
-tidyr 数据处理
-stringr 字符串的处理
-readr 文件的读取
-purrr 函数的迭代
-forcats 处理因子问题
-tibble 实现data.table类似的优雅处理dataframe问题
dplyr参考
数据处理经常用到的包
dplyr
,data.table
,Base R
测试表明,dplyr的速度要快于data.table.
dplyr
是tidyverse
其中的一个包。
数据处理一般的流程:
1.数据过滤(去重)
2.选择
3.比对,匹配
4.分组
5.排序
6.抽样
在excel中也可以完成上述操作,但是当数量达到十万以上级别后,excel速度慢如蜗牛。
dplyr用法示例
数据去重
distinct(df,V1,V2)
根据V1和V2两个条件来进行去重
新增列
mutate(df,vnew1=v1-v2,vnew2=vnew1+v3)
支持在创建的新列的基础上,再新建列。
过滤函数
filter(df,cond1,cond2,…)
用逗号,隔开表示条件是and的关系
filter(df,cond1|cond2|…)
用竖线|隔开表示条件是or的关系
slice(df,80:100)
选取索引80到100的数据
排序
arrange(df,V1,desc(V2),V3)
V1,V3升序,V2降序
arranage(df,V1)
升序排列V1
arrange(df,desc(V3))
降序排列V3
选择
select(df,V1,V2,V3)
选择V1,V2,V3这三列
select(df,V1:V3)
选择V1到V3列之间的所有列
select(df,-c(v1,V3))
选择除V1,V3之外的所有列
分组
group_by(df,V1,V2)
df根据V1,V2进行分组
计算统计数据
summarise(df,mean(V1),sum(V4))
随机抽取
sample_n(df,1000)
随机抽取1000个数据
sample_frac(df,0.7)
随机抽取70%的数据
参考地址https://www.cnblogs.com/nxld/p/6060533.html
数据格式转换tidyr包
library(tidyr)
library(dplyr)
-
- 缺失值的简单补齐
-
- 长形表变宽形表与宽形表变长形表 gather-把宽度较大的数据转换成一个更长的形式,它类比于从reshape2包中融合函数的功能 spread-把长的数据转换成一个更宽的形式,它类比于从reshape2包中铸造函数的功能。 gather()相反的是spread(),前者将不同的列堆叠起来,后者将同一列分开
长短数据的转换主要是用于ggplot2的出图,ggplot2需要的是长数据,而我们日常输入的数据是宽数据
宽数据实例
下面数据的第一列数字是R中的行号
allinfo
内容如下
province primary middle senior higher postgraduate
1 北京 109.4579 110.5105 96.20949 98.91572 107.82594
2 天津 113.4776 114.0266 94.79238 99.90067 88.54674
3 河北 114.6299 113.0214 91.19643 87.67520 81.96543
4 山西 107.9786 108.3219 92.03961 82.94410 73.76735
5 内蒙古 109.1339 108.9091 92.13359 89.96668 67.54206
6 辽宁 110.3081 110.8525 91.70425 112.46839 87.90451
```
`allinfoNew`内容如下
转换成长数据后
`allinfoNew <- allinfo %>% gather(school,value, -province)`
将allinfo的所有列,除了province列之外全部合并成两列,一列是school,一列是value.
province school value
1 北京 primary 109.45794 2 天津 primary 113.47760 3 河北 primary 114.62993 4 山西 primary 107.97863 5 内蒙古 primary 109.13391 6 辽宁 primary 110.30810 7 北京 middle 110.51045 8 天津 middle 114.02665 9 河北 middle 113.02139 10 山西 middle 108.32195 11 内蒙古 middle 108.90907 12 辽宁 middle 110.85252 13 北京 senior 96.20949 14 天津 senior 94.79238 15 河北 senior 91.19643 16 山西 senior 92.03961 17 内蒙古 senior 92.13359 18 辽宁 senior 91.70425 19 北京 higher 98.91572 20 天津 higher 99.90067 21 河北 higher 87.67520 22 山西 higher 82.94410 23 内蒙古 higher 89.96668 24 辽宁 higher 112.46839 25 北京 postgraduate 107.82594 26 天津 postgraduate 88.54674 27 河北 postgraduate 81.96543 28 山西 postgraduate 73.76735 29 内蒙古 postgraduate 67.54206 30 辽宁 postgraduate 87.90451
####长数据转为宽数据
`allinfoFat <- allinfoNew %>% spread(school,value)`
`allinfoFat`和allinfo的内容一致。
school是要拆分的列的对象,value是要拆分列的值。
- 3. 列分割与列合并
separate-将一列按分隔符分割为多列
unite-将多列按指定分隔符合并为一列
tidyr包:(gather(宽数据转为长数据)、spread(长数据转为宽数据)、unit(多列合并为一列)、separate(将一列分离为多列))
#### stringr的用法
library(stringr) x <- c("why", "video", "cross", "extra", "deal", "authority") str_length(x)#获取字符串的长度
> [1] 3 5 5 5 4 9
str_c(x, collapse = ", ")#替换分隔符
> [1] "why, video, cross, extra, deal, authority"
str_sub(x, 1, 2)#提取指定长度的字符串
> [1] "wh" "vi" "cr" "ex" "de" "au"
str_subset(x, "[aeiou]") #匹配包含aeiou的字符串
> [1] "video" "cross" "extra" "deal" "authority"
str_count(x, "[aeiou]")#匹配包含aeiou的字符的数量
> [1] 0 3 1 2 2 4
str_detect(x, "[aeiou]") #返回是否包含aeiou字符串的逻辑值
> [1] FALSE TRUE TRUE TRUE TRUE TRUE
str_locate(x, "[aeiou]") #返回每个字符串首次匹配的起始位置和终止位置。(例子中需要匹配的字符串长度都是1,所以终止位置和起始位置是一样的) str_locate_all(x, "[aeiou]") #返回每个字符串所有的与匹配字符匹配的起始位置和终止位置。 str_extract(x, "[aeiou]") #提取每个字符串中与匹配字符串一致的字符 str_match(x, "(.)aeiou") #匹配 str_replace(x, "[aeiou]", "^") #替换匹配的字符
[1] "why" "v^deo" "cr^ss" "^xtra" "d^al" "^uthority"
str_split(c("a,b", "c,d,e"), ",") #指定使用逗号分割字符串
#### forcats的 用法
library(forcats) fct_reorder()#: 按另一个变量重新排序一个因子。 fct_infreq()#:按值的频率对因子重新排序。 fct_relevel()#:手动更改因子的顺序。 fct_lump()#:将一个因素的最少/最频繁值折叠为“其他”。 starwars %>% filter(!is.na(species)) %>% count(species, sort = TRUE) starwars %>% filter(!is.na(species)) %>% mutate(species = fct_lump(species, n = 3)) %>% count(species)
filter(starwars,!is.na(hair_color))%>% ggplot(aes(x = hair_color)) + geom_bar() + coord_flip() starwars %>% filter(!is.na(hair_color))%>% mutate(hair_color = fct_infreq(hair_color))%>% ggplot(aes(x = hair_color)) + geom_bar() + coord_flip()
### readr读取文件
`readr`比baseR读取快10倍
`data.table`包的`fread`的速度比`readr`快1-2倍
library(readr) read_csv()#: 逗号分隔 (CSV) 文件 read_tsv()#: 制表符分隔的文件 read_delim()#: 一般分隔文件 read_fwf()#: 固定宽度文件 read_table()#:列由空格分隔的表格文件。 read_log()#: 网络日志文件
#purrr用于迭代函数,速度非常快
library(purrr)
purrr的所有函数是C实现的,所以速度非常快。map实现的是for循环,返回值是向量
map() #map的第一个参数可以是向量或数据框。 map_lgl() #生成一个逻辑向量。 map_int() #生成一个整数向量。 map_dbl() #形成一个双向量。 map_chr() #制作一个字符向量。
示例:
map_int(x,str_count)
x1 <- rnorm(100,mean = 50,sd=15) #产生随机数100个,均值50,标准差15 x2 <- rnorm(100,mean=100) x3 <- rnorm(100) xd <- data.frame(x1,x2,x3) map(xd,sum) map(xd,sd)
### dplyr包的使用:数据处理
library(dplyr)
数据包 航班 世界发展 棒球数据
if(!require(c("nycflights13", "gapminder", "Lahman")))install.packages(c("nycflights13", "gapminder", "Lahman")) #三个数据包 library(nycflights13) flights #是2013年美国纽约出发的航班信息
dplyr常用的函数
根据其值(filter())选择观察值。
重新排序行(arrange())。
按变量名称(select())选择变量。
使用现有变量(mutate())的功能创建新变量。
将许多值折叠为一个摘要(summarise())。
April_1st <- filter(flights,month==4,day==1) #查询2013年4月1日出发的航班
filter(flights,!(dep_delay>60|arr_delay>60),month %in% c(4,5,6)) #查看第二季度的出发和到达时间延误均小于等于60min的航班
查找早上7点前到达和23点之后到达的航班,根据出发时间从早到晚,和到达时间从晚到早排序
filter(flights,arr_time<700 | arr_time>2300) %>% arrange(dep_time,desc(arr_time))
挑选指定列
select(flights,origin,dest,distance,air_time)
挑选指定列和指定列之间的列
select(flights, flight:hour)
挑选除了指定列和指定列之间的列之外所有的列
select(flights, -(flight:hour))
挑选指定列之外的列
select(flights,-c(year,month,day))
重命名列名(新的列名在前面,=后是旧的列名)
rename(flights, departtime = dep_time)
select内部辅助函数
starts_with("abc"):匹配以“ abc”开头的名称。
ends_with("xyz"):匹配以“ xyz”结尾的名称。
contains("ijk"):匹配包含“ ijk”的名称。
matches("(.)\1"):选择与正则表达式匹配的变量。该变量与任何包含重复字符的变量匹配。您将了解有关字符串中的正则表达式的更多信息。
num_range("x", 1:3):匹配x1,x2和x3。
挑选列名以time结尾的列
select(flights,ends_with("time"))
挑选包含dep起飞信息的列
select(flights,contains("dep"))
select和everything联用,用于调整列的顺序(把origin和dest拍到最前面)
select(flights, origin, dest, everything())
select选择合适的列
flights_sml <- select(flights, year:day, ends_with("delay"), distance, air_time ) head(flights_sml)
mutate增加新的列,同时保留原来的列
mutate(flights_sml, gain = dep_delay - arr_delay, speed = distance / air_time * 60 )
transmute是生成新的列,但是不保留原来的列
transmute(flights, gain = dep_delay - arr_delay, hours = air_time / 60, gain_per_hour = gain / hours )
near 判断两个数字是否相等
因为计算机有效数字的问题,无限不循环小数会被截断,所以有时候==并不成立
sqrt(2)^2 == 2 #返回FALSE near(sqrt(2)^2,2) #返回TRUE
lead/lag前导值或滞后值
滚动分析
x <- seq(1,29,by=3) x cumsum(x)
> [1] 1 5 12 22 35 51 70 92 117 145
cummean(x)
[1] 1.0 2.5 4.0 5.5 7.0 8.5 10.0 11.5 13.0 14.5
cumprod(x) cummax(x) cummin(x)
分析航班的(到达时间-出发时间)和空中时间的差值,可以看出非飞行时间在机舱内的
时间比较长的航班都是长距离航班>1000km,而且主要是目的地是JFK机场的航班。说明JFK的进港时间比较长,机场地勤比较慢
flights %>% arrange(origin) %>% group_by(origin) %>% select(contains("time"),dest,distance) %>% mutate(groundtime = arr_time - dep_time - air_time) %>% arrange(desc(groundtime))
flights %>% head(10) %>% identity() %>% rownames() ggplot(aes(x=air_time))+ #geom_histogram()+ NULL geom_boxplot(aes(carrier,flight))
summaries
summarise(flights,delay=mean(dep_delay,na.rm=TRUE))
显示出每天的平均出发延误时长
by_day <- group_by(flights,year,month,day) summarise(by_day,delay = mean(dep_delay,na.rm=TRUE))
显示出发地和到达地的平均延误时长
by_port <- group_by(flights,origin,dest) summarise(by_port,delay=mean(dep_delay,na.rm=TRUE))
by_dest <- group_by(flights, dest) #根据出发地分组 delay <- summarise(by_dest, count = n(), dist = mean(distance, na.rm = TRUE), #距离的均值 delay = mean(arr_delay, na.rm = TRUE) #到达时延误的均值 ) %>% filter(count > 20, dest != "HNL") #过滤掉计数少于20,目的地是HNL的数据,HNL距离其他机场太远了
It looks like delays increase with distance up to ~750 miles
and then decrease. Maybe as flights get longer there's more
ability to make up delays in the air?
ggplot(data = delay, mapping = aes(x = dist, y = delay)) + geom_point(aes(size = count), alpha = 1/3) + geom_smooth(se = FALSE)
> geom_smooth()
using method = 'loess' and formula 'y ~ x'
na.rm = TRUE #是删除含有NA的行
包含NA的表示航班取消,第一步先过滤掉这部分航班
normal_flight <- flights %>% filter(!is.na(dep_delay),!is.na(arr_delay))
delays <- normal_flight %>% group_by(tailnum) %>% summarise(delay=mean(arr_delay)) ggplot(data=delays,mapping = aes(x=delay))+geom_freqpoly(binwidth = 10)
filter是过滤
arrange是排序,arrange(desc(air_time)) desc是倒序
```