《R数据科学》||15-16章vectors向量数据概念+purrr循环迭代

《R数据科学》||15-16章vectors向量数据概念+purrr循环迭代_第1张图片
r4ds

写论文的间隙换换脑子继续学习R4ds这本书。对R语言中的数据格式有了更加系统的认识。这一章值得反复多看几遍。

  1. 英文原版在线https://r4ds.had.co.nz/index.html
  2. 中文翻译版已有售,建议纸质版书籍随时翻翻。电子版网盘分享 https://pan.baidu.com/s/1fkpqYahQHPkwx66XD2gGGg 提取码: akct
  3. 最近才公布的课后习题参考答案https://jrnold.github.io/r4ds-exercise-solutions/
  4. Rstudio的一些便捷CheetSheetshttps://www.rstudio.com/resources/cheatsheets/
  5. 另外在写代码过程中Rstudio操作时的方便快捷键:赋值<- Alt+“减号” ;管道符%>% Ctrl+Shift+M

十五章, 向量vectors

一. 向量概括

向量vectors包括两种:源自向量(atomic vectors)和列表(list)

  • 原子向量 :包括6种:logical,numeric(integer, double), character, complex, raw。向量种的各个值都是同种类型的;
  • 列表: 递归列表(recrusive list),
  • 拓展向量:向量中任意添加额外的元数据

二. 原子向量

  1. 逻辑型(logical)包括三种:TRUE, FALSE, NA

  2. 数值型(numeric):默认数值为双精度型double;

    • 注意双精度型double是近似值(approximations),所有的双精度值都当做是近似值处理,表示浮点数(floating point)
    • interger的特殊数据NA,double的特殊数据NA, NaN,Inf,-Inf需要以is.finite()等判断
  3. 字符串(character):可以包含任意数量的数据。

三. 原子向量的操作

  1. 强制转换:将一种原子强制转化为另一种;或者系统自动转化
    • 显示型强制转化as.numeric,as.character等;
    • 隐式强制转化:联系上下文context自动转化,如logical———>numeric;
x <- sample(x = 20,size = 100,replace = T)
y <- x>10
mean(y);sum(y)
  1. 检验是否为某一原子向量:利用purrr包中的函数is_is_logical(), is_character

  2. 标量与循环的规则:处理不同长度的向量会遵循 向量循环规则

  3. 向量命名:所有类型的向量都是可以命名的.向量完成后利用:purrr::set_names(x,nm=c("q","w","e"))命名。

  4. 向量的取子集:filter()函数对tibble使用,对于向量的筛选则使用[]。

    • 整数型数值向量进行筛选:x[c(1,2,2,4)], x[c(-1,-2,-3)]
    • 使用逻辑向量取子集,提取出TRUE值对应的元素。可利用比较函数
    • 对命名向量可用字符取子集
    • x[] 代表选取x中的全部元素,对于矩阵十分重要x[2,],x[,-3]特殊的,[[]] 代表只提取单个元素。明确表示需要提取单个元素时使用。对于矩阵/dataframe来说,x[,c(2)]返回的仍然是一个df(特殊的list),而x[[,2]]返回的才是真正的原子向量

四. 列表(递归向量recrusive vectors)

  1. 列表保存层级结构,树形结构。str(),重点关注列表的结构。
  2. 列表取子集 :
    • []提取子列表,返回的是一个子列表;可用逻辑向量,整数向量,字符向量提取。
    • 使用[[]]从列表中提取单个元素,并非子列表。
    • 直接使用$,作用相同于[[]]。综合使用。x[[1]][[1]]
    • 注意于tibble之间使用的异同点,tibble[1], tibble[[1]]
a <- list(a=1:3,b="a string",c=pi,d=list(-1,-5))
a[c(1:2)]
a["a"]
a[["a"]][1:2]

五. 特性:

  • 任何向量都可以通过其特性来附加任意元数据。
    泛型函数:可以根据不同类型的输入而进行不同的操作。面向对象编程的关键。

六. 拓展向量:

利用基础的原子向量和列表构建出的另外一些重要的向量类型,称为拓展向量,其具有类的附加特性

  1. 因子,表示有次序的分类数据factor(c("ef","cd","ab"),levels=c("ab","cd","ef"))
  2. 日期和日期时间。

Charpter16_purrr

一. For循环

  • 需为输出结果分配出足够的空间。对循环效率十分重要。
  • 涉及的函数包括 vector("double",ncol(df)), seq_along(df), [[]]
###16.2 for循环
require(tidyverse)
df <- tibble(a=rnorm(10),
             b=rnorm(10),
             c=rnorm(10),
             d=rnorm(10))

output <- vector("double",ncol(df))
output
for (i in seq_along(df)) {
  output[i] <- median(df[[i]])
}
output


### exercise Alice the Camel
humps <- c("five", "four","three","two","one","no")
for (i in humps) {
  cat(str_c("Alice the camel has",rep(i,3),"horse",collapse = "\n"),"\n")
}

二. for循环的变体

  1. 修改现有对象:与自定义的函数function()一起使用。

    • 注意再循环loop中,所有for循环使用的都是[[]] ,明确表示是要处理单个元素。
  2. 循环模式:

    • 通过对数值索引进行循环,再通过x[[i]]提取相应的值。
    • 通过对元素element索引
    • 通过使用名称索引for (i in names(x)),需要使用元素的名称时使用。
  3. 未知的输出长度。

    • 应该将loop每次的结果保存再一个列表中,循环结束后再利用unlist() 或者purrr::flatten_dbl()组合成一个向量
    • 当遇到类似的问题,如生成一个很长的字符串paste(out,collapse=""),或是个很大的数据框rbind_rows()。应首先使用一个更复杂的对象来保存每次迭代的结果,最后再一次性的组合起来。
means <- c(0,1,2)
output <- double()
for (i in seq_along(means)) {
  n <- sample(100,1)
  output <- c(output,rnorm(n,mean = means[[i]])) ### 十分不高效,这里会复制上一次的所有数据。
}

##高效法 
out <- vector("list",length = length(means))
for (i in seq_along(means)){
  n <- sample(100,1)
  out[[i]] <- rnorm(n,mean = means[[i]])
}
unlist(out)
  1. 未知的输入序列长度。利用while循环来实现。
####exercises
# 1.读取文件,保存在大的数据框中
files <- dir(path = ".",pattern = "tsv$",full.names = F) ###匹配某一路径下所有的文件。
data_list <- vector("list",length = length(files))
for (i in seq_along(files)) {
  data_list[[i]] <- read_delim(files[[i]],delim = "\t")
}
bind_rows(data_list)

#2.输出所有df中数值列的均值及名称show_mean(iris)
iris <- as_tibble(iris)
show_means <- function(df,digits=2){
  maxstr <- max(str_length(names(df)))
  for (i in names(df)) {
  if (is.numeric(df[[i]])) {
    cat(
      str_c(str_pad(str_c(i,":"),maxstr+1L,side = "right"),
            format(mean(df[[i]]),digits=2,nsmall=2),
                   sep=" "
              ),
     sep =  "\n"  
    )
  }
}
}

三. for循环与函数式编程

  • 函数式编程语言意味着可以先将for循环包装在函数中。即将函数名作为参数传入到另一个函数中
  • 利用purrr函数,可以将复杂问题解决成子问题,然后再通过管道操作将这些问题的结果组合起来。
col_summary <- function(x,fun){
  out <- vector("double",length(x))
  for (i in seq_along(x)) {
    out[[i]]=fun(x[[i]])
  }
  out
}

四. 映射函数 mapping function

purrr包函数map()(返回的是列表),map_lgl(),map_dbl(),map_chr()。map()第二个参数可以是公式,字符向量,整型向量,第三个参数为第二个函数中的附加参数。

  1. 快捷方式(shortcuts):对某个数据集中的每个分组都拟合一个线性模型。类似于factor中的一些功能。
  2. map(df,function(xxx) length(unique(xxx))——》map(df, ~ length(unique(.))) 因为需要一些更复杂的函数去实现一些功能
models <- mtcars %>% 
  split(.$cyl) %>% 
  map(function(df) lm(mpg ~ wt,data=df)) ##  df是一个匿名函数,可任意命名。

  1. 在对列表中的各个子集内部进行筛选
out ###str(out)
map(out, ~ .[. > 0.8]) ###筛选每一列中大于0.8的数据。


  1. exercises中涉及的一些函数:map(-2:2,rnorm, n=5), map(1:3,rnorm,mean=10).

五. 多参数映射mapping over multiple arguments

  1. map2(), pmap()对每一列的功能操作会涉及到多个参数时,就需要利用此函数。注意每次发生变化的参数放在函数功能的前面位置,值保持不变的参数放在函数的后面
mu <- list(5,10,-3)
map(mu, rnorm, n=5)
### map2 的应用
sigma <- list(1,5,10)
map2(mu,sigma,rnorm,n=5)
### pmap()应用,多个参数都未定,就将参数保存到大列表中
n <- list(3,5,8)
args <- list(n=n,sd=sigma,mean=mu)
pmap(args,rnorm)
  1. 多个参数 对于pmap()函数,可以将多个输入列表作为参数。且多个列表的长度一样**可以转换为tibble,确保每列都有名称,且与其它列具有相同的长度 **

  2. 多个参数,且多个映射函数,利用invoke_map()函数。(invoke 调用)

六. 游走函数,预测函数,归纳与累计

  1. 游走函数walk,输出保存多个文件时非常实用。walk(), pwalk
library(ggplot2)
plots <- mtcars %>% split(.$cyl) %>% 
  map( ~ ggplot(data = .,mapping = aes(mpg,wt))+geom_point())
  path=stringi::stri_c(names(plots),".pdf")
  
  pwalk(list(path,plots),ggsave,path=tempdir())

  1. 预测函数keep(), discard()函数可以保留输入中预测值为TRUE和FALSE的元素。some(), every()分别用来确定预测值是否对某个元素为真。detect()找出预测值为真的第一个元素,detect_index()返回找到的元素的位置。

  2. 归纳约简与累计 reduce/accumulate:复杂列表简化为一个简单列表。

vs <- list(c(1,2,3,4,5),
           c(1,2,3,4),
           c(1,2,3))
reduce(vs,intersect)

charpter21_ggplot2(graphics for communication)

  1. 标签labels:labs()
    • title="" 主标题
    • subtitle="" 副标题,添加附加信息;
    • caption= " " 描述数据来源 右下角添加信息
    • x=" ", y=" "坐标轴信息
    • color= "" 图例中的标题
    • x= quote() 坐标轴上使用数学公式
library(ggplot2)
require(tidyverse)
ggplot(mpg,aes(displ,hwy))+geom_point(aes(color=class))+labs(title = "aaaaa",subtitle = "bbbbb",caption = "cccc ",x="HWY",y="DISPL")
  1. 注释Annotation:为单个或分组的观测值添加标签。
    • filter(row_number(desc(hwy))==1) 筛选每个组中hwy数值最高的观测observation。
    • geom_point() + geom_text(aes(label= ),data=)
    • 利用ggrepel包可以自动调整注释标签的位置 geom_label_repel(aes(label=))
    • 将标题加在图形里的右上角角落上
    • 添加参考线geom_hline(),geom_vline(size=2,color=white)
    • 感兴趣的点周围添加个矩形 geom_rect()
    • 绘制箭头,指向关注的数据点geom_segment()
library(ggplot2)
library(ggrepel)
best_in_class <- mpg %>% group_by(class) %>% filter(row_number(desc(hwy))==1)
ggplot(mpg,aes(displ,hwy))+geom_point(aes(color=class))+geom_text(mapping = aes(label=model),data = best_in_class)
### 利用ggrepel用较大的空心圆来强调
ggplot(mpg,aes(displ,hwy))+geom_point(aes(color=class))+geom_point(size=4,shape=1,data = best_in_class)+geom_label_repel(aes(label=model),data = best_in_class)

### 将标题加在图形里的右上角角落上。
label <- mpg %>% summarise(displ=max(displ),hwy=max(hwy),label="AAAA\nbbbbbbbb")
ggplot(mpg,aes(displ,hwy))+geom_point()+geom_text(aes(label=label),data = label,vjust="top",hjust="right")

  1. 标度scale:控制从数据值到图形属性的映射。scale_x(图形属性名称)_continuous()(连续型/离散型/时间/日期时间型)
    • 调整坐标轴axis ticks: 刻度 scale_y_continuous(breaks=seq(1,40,by=5)),坐标轴图例项目scale_y_continuous(labels=NULL)
    • 图例legend:theme(legend.position="none/right/left/top/bottom"), 控制图例的显示guides(guide_legend())
    • 标度替换:对标度进行数学转换。
    • 颜色的转换:利用RColorBrewer/ggsci包,对于数量少的legend,可以添加形状映射。
ggplot(mpg,aes(displ,hwy))+geom_point(aes(color=class))+geom_smooth(se=F,color="darkgrey")+theme(legend.position = "bottom")+guides(color=guide_legend(nrow = 1,override.aes = list(size=4)))
library(ggsci)
library(RColorBrewer)
ggplot(mpg,aes(displ,hwy))+geom_point(aes(color=drv))+scale_color_brewer(palette = "Set1")
ggplot(mpg,aes(displ,hwy))+geom_point(aes(color=drv,shape=drv))+scale_color_aaas()

  1. 缩放,控制图形范围。coord_cartesian()函数设置xlim和ylim的参数值。
  2. 主题(themes):定制图形中的非数据元素。theme_bw(),theme_grey()(默认),theme_classic(),theme_light()
  3. 保存图形ggsave()

你可能感兴趣的:(《R数据科学》||15-16章vectors向量数据概念+purrr循环迭代)