终于安排上了时间再把《R数据科学》这本书学习了一遍。以下是学习的过程中的一些参考资料,分享一下。
- 英文原版在线https://r4ds.had.co.nz/index.html
- 中文翻译版已有售,建议纸质版书籍随时翻翻。电子版网盘分享 https://pan.baidu.com/s/1fkpqYahQHPkwx66XD2gGGg 提取码: akct
- 最近才公布的课后习题参考答案https://jrnold.github.io/r4ds-exercise-solutions/
- Rstudio的一些便捷CheetSheetshttps://www.rstudio.com/resources/cheatsheets/
- 另外在写代码过程中Rstudio操作时的方便快捷键:赋值<-
Alt+“减号”
;管道符%>%Ctrl+Shift+M
第五章,探索性数据分析 exploratory data analysis(EDA)
变动:是一个变量内部的行为,每次测量时数据值的变化趋势。
相关变动:两个或多个变量以相关的方式共同变化所表现出的趋势。多个变量之间的行为。
模式:如果两个变量之间存在系统性的关系,那么这种关系就会再数据中表示一种模式。
5.3 变动:
一维数据的表示:geom_bar(binwidth=1)
可以对一维连续变量进行分箱,然后使用条形的高度表示落入箱中的数量。并且对于geom_bar()
,geom_histogram()
可以利用geom_freqpoly()
替代,此为叠加的折线图,并可以在折线图内aes(color= *)
参数映射其它数据。
异常值:可用图层coord_cartesian(ylim=c(0,50))
滤出(不显示,但会保留)大于此取值的,而不是ylim(0,50)直接丢弃。
- 将异常值当做缺失值处理:利用
mutate()
函数创建新变量代替原来的变量,使用ifelse()函数将异常值替换为NA:diamons %>% mutate(y = ifelse(y < 3 | y>20, NA, y))
- 计算画图时以参数
na.rm=TRUE
过滤掉
- 异常值差异不大的,可以用缺失值来代替,而异常值较大的需要探究其原因。
## 5.3 变动,分布进行可视化表示
ggplot(data = diamonds)+geom_bar(mapping = aes(x=cut))
ggplot(data = diamonds)+geom_bar(mapping = aes(x=carat),binwidth = 0.5)
diamonds %>% filter(carat<3) %>% ggplot(mapping = aes(x=carat))+geom_histogram(binwidth = 0.1)
diamonds %>% filter(carat<3) %>% ggplot(mapping = aes(x=carat))+ geom_freqpoly(aes(color=cut),binwidth=0.1)+scale_color_brewer(palette = "Set1")
### 5.3.3异常值,
ggplot(diamonds)+geom_histogram(mapping = aes(x=y),binwidth = 0.5)+ylim(0,60)
ggplot(diamonds)+geom_histogram(mapping = aes(x=y),binwidth = 0.5)+coord_cartesian(ylim = c(0,60))
# 5.4 异常值,推荐是将异常值改为缺失值处理。
diamonds %>% filter(between(y,3,20))
#### mutate()创建新变量代替原来的变量
diamonds <- diamonds %>% mutate(y=ifelse(y<3 | y>30,NA,y))
diamonds <- select(diamonds,-(`ifelse(y < 3 | y > 30, NA, y)`))
ggplot(diamonds,aes(x=x,y=y))+geom_point(na.rm = T)
flights %>% mutate(cancelled=is.na(dep_time),sched_hour=sched_dep_time%/%100,sched_min=sched_dep_time%%100,sched_depart_time=sched_hour+sched_min/60) %>% select(sched_hour,sched_min,sched_depart_time,everything()) %>% ggplot(aes(x=sched_depart_time))+geom_freqpoly(aes(color=cancelled),binwidth=1/5)
5.5 相关变动:
- 分类变量与连续变量:
- 对
geom_freqpoly(aes(color=cut))
,对一维的count计数进行标准化可以y=..density..标准化。 - 箱线图boxplot()标准化:reorder(class,hwy,FUN=median) 对分类变量进行排序。
- 对
- 两个分类变量:可以利用heatmap图,geom_tile, geom_count
- geom_count()函数
- 另外可先count(x,y)计数,再利用
geom_tile()
和geom_count()
填充图形属性。
- 两个连续变量:
- 通常的geom_point(),可通过alpha参数设置透明度。
- 对连续变量数据进行分箱,
geom_bin2d
,geom_hex()
可以正方形和六边形分享。
5.6 模式和模型:如果两个变量之间存在系统性的关系,那么这种关系就会再数据中表示一种模式。
- 变动会生成不确定性,那么相关变动就是减少不确定性,如果两个变量是存在系统性的关系的,那么就可以通过一个变量的值来预测另一个变量的值。
- 模型:就是抽取模式的一种工具,找到两个变量间系统性关系的方法。
# 5.5 相关变动:两个或者多个变量间的关系。
ggplot(diamonds,mapping = aes(x=price))+geom_freqpoly(aes(color=cut),binwidth=500)
ggplot(diamonds)+geom_freqpoly(aes(x=price,y=..density..,color=cut),binwidth=200)+scale_color_brewer(palette = "Set2")
###mpg
ggplot(mpg,mapping = aes(x=class,y=hwy))+geom_boxplot()
ggplot(mpg)+geom_boxplot(mapping = aes(x=reorder(class,hwy,FUN = mean),y=hwy,fill=class))
ggplot(mpg)+geom_boxplot(mapping = aes(x=reorder(class,hwy,FUN=median),y=hwy))+coord_flip()
### 5.5.1分类变量与连续变量
### 5.5.2俩个分类变量间的关系,geom_tile(aes(fill=count))
ggplot(data = diamonds)+geom_count(mapping = aes(x=cut,y=color))
diamonds %>% count(color,cut) %>% ggplot()+geom_tile(aes(x=color,y=cut,fill=n))
### 5.5.3 两个连续变量
geom_point()
geom_bin2d() ## 对连续变量的数据做分箱处理。
geom_hex()
diamonds %>% ggplot(aes(carat,price))+geom_hex()
第七章. tibble表
是对传统R中的data.frame的升级版替换。
- tibble在打印大数据时会默认仅显示10行(observation),屏幕可显示的列(variety)
- tibble 是特殊的列表list(list(a=1),list(b=2))
第八章. 使用readr进行数据的导入
8.1 常用的tidyverse所提供的数据导入的方式:
-
read_csv()
:以,分割 -
read_csv2()
:以; 分割 -
read_tsv()
:以\t分割 -
read_delim()
:可以读取以任意分隔符的文件delim="\t" (delimiter 分界符)
8.2 以read_csv()为例,内部提供的函数:
- skip=2,跳过开头的n行
- comment="#" 跳过以#开头的行
- col_names=FALSE 不以第一行作为列标题。也可col_names=c("a","b","c")来对列进行命名
- na="." 设定哪个值为文件的缺失值
8.3 解析向量:主要依靠parse_*()
函数族解析,第一个参数为需要解析的字符向量,na参数设定 缺失值处理na=".",函数族包括parse_logical(), parse_double(), character(), factor(), datetime().
- parse_number()可以忽略数值前后的非数值型字符,可以处理 货币/百分比,提取嵌在文本中的数值
- character:UTF-8可以对人类使用的所有字符进行编码,ASCII为美国信息交换标准代码。
- 因子:表示 已知集合的分类变量
- 日期时间等
8.4 解析文件:readr会通过文件的前1000行以启发式算法guess_parser()返回readr最可信的猜测,接着用parse_guess()使用这个猜测来解析列。
8.5 写入文件和其它导入文件:
- 通过
write_csv
,write_tsv
,其会自动使用UTF-8对字符串编码。 -
write_excel_csv()
函数导为Excel文件。 -
readxl
可以读取EXCEL文件 -
haven
读取SPSS,SAS数据 -
DBI
可对RMySQL等数据库查询 -
jsonlite
读取JSON的层次数据。 -
xml2
读取XML文件数据
第九章. 使用dplyr处理关系数据,多个数据表。
综合多个表中的数据来解决感兴趣的问题。存在于多个表中的数据称为关系数据。且关系总是定义于两个表之间的。 包括有三类操作处理关系数据:
- 合并数据:在一个表中添加另一个表的新变量,添加新变量的方式是以连接两个表的键来实现的。
- 筛选连接:在A表中,根据键是否存在于B表中来筛选这个A表中的数据。
- 集合操作:将观测作为集合元素来处理。
基本数据的准备包括nycflights13
包中的几个表。airlines/airports/planes/weather等。
9.3 键:唯一标识观测的变量
- 主键:唯一标识 其所在数据表中的观测。
- 外键:唯一标识 另一个数据表中的观测。
- 代理键:当一张表没有主键,需要使用
mutate()
函数和row_number()
函数为表加上一个主键。 - 理解不同数据表之间的关系的关键时:记住每种关系只与两张表有关,不需要清楚所有的事情,只需要明白所关心的表格即可。
9.4 合并连接:通过两个表中的键(变量们)来匹配观测(行数值),再将一个表中的变量复制到另一个表格中。 对比cheatsheet中的信息
- 内连接:相当于连取交集。将两个表中的相等的键值取出来。
X %>% inner_join(y,by="key")
- 外连接:至少保留存在于一个表中的观测。在另一个表中未匹配的变量会以
NA
表示。left_join()
right_join()
full_join()
- 重复键:一对多(),多对一,以及多对多的关系(两表中都不唯一,会以笛卡尔积分的方式呈现)。
- 定义两个表中匹配的键:
- by=NULL,默认,使用存在于两个表中的所有变量。
left_join(x,y,by="weather")
left_join(x,y,c("dest"="faa "))
9.5 筛选连接:根据键来对观测数值进行筛选
- semi_join(x,y):保留x表中 与 y表中的观测数值相匹配的数据。
- anti_join(x,y):丢弃x表中 与y表中观测(行)数据相匹配的数据。
9.6整理数据时需要对数据进行整理:
- 需要找出每个表中可以作为主键的变量。应基于数据的真实含义来找主键
- 确保主键中的每个变量没有缺失值,如果有缺失值则不能被识别!
- 检查主键是否可以与另一个表中的外键相匹配。利用
anti_join()
来确定。
9.7集合的操作:
-
intersect(x,y)
两个表中皆存在。 -
union()
:返回x表中与y表中的唯一观测。 -
setdiff()
:在x表中,但不在y表中的数值。
library(tidyverse)
library(nycflights13)
planes;airports;airlines;weather;
## 9.3键
weather %>% count(year,month,day,hour,origin) %>% filter(n>1) ### 筛选唯一的键
## 9.4 合并连接
flights2 <- flights %>% select(year:day,hour,origin,dest,tailnum,carrier)
flights2 %>% select(-(hour:origin)) %>% left_join(airlines,by = "carrier")
flights2 %>% select(-(hour:origin)) %>% right_join(airlines,by = "carrier")
flights2 %>% left_join(weather) ## 自然连接,使用存在于两个表中的所有变量。
flights2 %>% left_join(planes,by = "tailnum") ## 共有的
flights2 %>% left_join(airports,c("origin" = "faa"))
### exercise
##9.4.6-1目的地的平均延误时间,与空间分布。
flights %>% group_by(dest) %>% summarise(dest_delay=mean(arr_delay,na.rm = T)) %>% left_join(airports,c("dest"="faa")) %>% filter(dest_delay>0)%>%ggplot(aes(lon,lat))+borders("state")+geom_point(aes(size=dest_delay))
airports %>% semi_join(flights,c("faa"="dest")) %>% ggplot(aes(lon,lat))+borders("state")+geom_point()
##exercise3 飞机的机龄与延误时间
flights %>% group_by(tailnum) %>% summarise(count=n(),delay_tailnum=mean(arr_delay,na.rm = T)) %>% left_join(planes,by="tailnum") %>% filter(!is.na(year)) %>% ggplot(aes(x=delay_tailnum))+geom_freqpoly(aes(color=year),binwidth=1)
###geom_ribbon作图
## 9.5 筛选连接
(top_dest <- flights %>% count(dest,sort = T) %>% head(10))
flights %>% filter(dest %in% top_dest$dest)
flights %>% semi_join(top_dest,by = "dest")
使用tidyr整理数据表 Tidy data
这一章在中文版里并没有,所以跟着英文在线版的学。
整洁的数据基本准则(以tidyr内部数据table1,table2,table3,table4a,table4b)为例:
- 每个变量(variables)都只有一列;
- 每个观测(observation)只有一行;
- 每个数据仅有一个位置cell。
整理数据表,应对一个变量对应多行 or 一个观测对应多行的问题。利用gather
,spread()
-
gather()
:对于table4a来说,其存在两列1999/2000对应相同的变量值。故需要合并,合并后的两列重新起名字,根据key=""
,和value=""
。gather(1999,2000,key="year",value="cases")
-
spread()
:对于table2来说,存在冗余。需要拆分出多个变量spread(table2,key=type,value=count)
-
separate()
:对于table3来说,rate一列数据可以拆分。separate(table3,rate,into=c("cases","population"))
-
sep=
参数默认是以非数字 非字母的字符为分隔符,也可以指定分隔符根据正则匹配。sep=4表示以4个字符作为分隔符。 -
convert = TRUE
表示改变分割后的数据结构。
-
unite()
:对指定两列合并处理。- unite(new,centry,year,sep="")
-
rename()
,rename_all()
: 对variables变量进行重命名。通过library(stringr)。rename_all(tolower) %>% rename_all(~str_replace_all(., "\\.", "_"))
-
mutate()
,mutate_all()
:对所有的value进行重命名,修改名称mutate_all(tolower) %>% mutate_all(~str_replace_all(., " ", "_"))
-
rowwise()
,对每行的数据进行处理,加和/平均值处理。iris %>% select(contains("Length")) %>% rowwise() %>% mutate(avg_length = mean(c(Petal.Length, Sepal.Length)))
## 1 tidy_data
#### compare different dataset
table1
table2
table3
table4a;table4b
table1 %>% mutate(rate=cases/population *10000)
table1 %>% count(year,wt=cases)
ggplot(table1,aes(year,cases)) + geom_line(aes(color=country))+geom_point(color="grey")
## 2 gather()
table4a
table4a %>% gather(`1999`,`2000`,key = "year",value = "cases")
table4b %>% gather(`1999`,`2000`,key="year",value="population")
left_join(table4a,table4b,by=c("country","year"))
## 3 spread()
table2
table2 %>% spread(key = type,value = count)
stocks <- tibble(
year=c(2015,2015,2016,2016),
half=c(1,2,1,2),
return=c(1.88,0.59,0.92,0.17)
)
stocks
stocks %>% spread(year,return) %>% gather("year","return",`2015`,`2016`)
## 综合操作
who %>%
gather(new_sp_m014:newrel_f65,key="key",value="count",na.rm = T) %>%
mutate(key=str_replace(key,"newrel","new_rel")) %>%
separate(key,into = c("new","var","sexage"),sep="_") %>%
select(-iso2,-iso3,-new) %>%
separate(sexage,into = c("sex","age"),sep=1)