美文网首页R数据科学读书会R数据科学
详解《R数据科学》--第五章 EDA

详解《R数据科学》--第五章 EDA

作者: 小洁忘了怎么分身 | 来源:发表于2018-09-17 23:20 被阅读177次

    中文版第5章对应英文版第七章。讲的是探索性数据分析,结合了dplyr和ggplot2。


    1.简介

    提出问题→通过可视化,转换和建模来解决问题→优化并提出新问题

    2.提出问题

    变量自身会发生何种变动?
    变量之间会发生何种相关变动?
    术语:在tidydata(整洁的数据)中,行是观测,列是变量。

    3.变动

    3.1对分布进行可视化表示

    分类变量--例如diamonds中的cut
    View(diamonds)

    第一件事还是端详数据:

    #复习一下如何查看每列的非重复值
    distinct(diamonds,cut)
    #如何查看每个非重复值出现的次数
    count(diamonds,cut)
    

    cut仅有5个固定的取值,是分类变量,可以用条形图进行可视化。

    library(tidyverse)
    ggplot(data = diamonds) +
      geom_bar(mapping = aes(x = cut))
    
    连续变量-例如diamonds中的carat

    用直方图进行可视化

    ggplot(data = diamonds) +
      geom_histogram(mapping = aes(x = carat), binwidth = 0.5)
    

    其中,binwidth是定义等宽分箱的宽度,也可以用bins定义分箱数。
    在同一张图中叠加多个直方图,用geom_freqpoly()代替。
    统计每个区间的观测数量

    diamonds %>% 
      count(cut_width(carat, 0.5))
    

    3.3.典型值

    直方图或条形图较高的读数,表示常见值。聚集成簇成为子组。

    3.3.异常值

    以diamonds中的y列为例作直方图,发现x轴取值范围出气地宽。(此处翻译有误,原文是x轴)



    为了便于查看异常值,用coord_cartesian(ylim())将y轴靠近0地部分放大。

    ggplot(diamonds) + 
      geom_histogram(mapping = aes(x = y), binwidth = 0.5)
    ggplot(diamonds) + 
      geom_histogram(mapping = aes(x = y), binwidth = 0.5) +
      coord_cartesian(ylim = c(0, 50))
    

    找出异常值

    filter(diamonds,y < 3 | y > 20) %>% 
      select(price, x, y, z) %>%
      arrange(y)
    

    在异常值中,有7个是缺失值,长宽高都是零蛋。

    4.缺失值

    #异常值的处理方法:
    #(1)丢弃
    diamonds2 <- diamonds %>% 
      filter(between(y, 3, 20))
    #(2)用缺失值代替异常值
    diamonds2 <- diamonds %>% 
      mutate(y = ifelse(y < 3 | y > 20, NA, y))#表示如果符合要求,就替换为NA
    
    #ggplot中明确移除缺失值的命令:na.rm=TRUE
    ggplot(data = diamonds2, mapping = aes(x = x, y = y)) + 
      geom_point(na.rm = TRUE)
    

    flights中取消的航班:

    nycflights13::flights %>% 
      mutate(
        cancelled = is.na(dep_time),
        sched_hour = sched_dep_time %/% 100,
        sched_min = sched_dep_time %% 100,
        sched_dep_time = sched_hour + sched_min / 60
      ) %>% 
      ggplot(mapping = aes(sched_dep_time)) + 
        geom_freqpoly(mapping = aes(colour = cancelled), binwidth = 1/4)
    

    新加的cancelled变量是逻辑值,TRUE和FALSE,所以将颜色映射给它,就自然分成了两组,变成了两条曲线。
    练习(1):直方图会丢弃缺失值,条形图则会将NA单列为一个分类,统计其数目。

    5.相关变动

    (1)分类变量与连续变量

    其实钻石质量、钻石切割水平都不是决定价格的决定性因素,因此出现负相关很正常,可以不理他。
    reorder函数对变量进行重排序:
    (请注意例子是根据hwy来对class进行重排序)

    ggplot(data = mpg) +
      geom_boxplot(mapping = aes(x = reorder(class, hwy, FUN = median), y = hwy)) #FUN是分类依据
    

    翻转在ggplot2中讲过,用coord_flip()

    (2)两个分类变量

    geom_count和geom_tile
    例子是diamonds中cut和color的相关变动,统计每个组合的观测数量:

    count(diamonds,color,cut) 
    ggplot(data = diamonds) +
      geom_count(mapping = aes(x = cut, y = color)) #count的可视化表示
    diamonds %>% 
      count(color, cut) %>%  
      ggplot(mapping = aes(x = color, y = cut)) +
        geom_tile(mapping = aes(fill = n)) #geom_tile更好看
    

    (3)两个连续变量

    ggplot(data = diamonds) +
      geom_point(mapping = aes(x = carat, y = price)) #散点图
    ggplot(data = diamonds) + 
      geom_point(mapping = aes(x = carat, y = price), alpha = 1 / 100)#设置透明度更美观的散点图
    smaller <- diamonds %>% 
      filter(carat < 3)
    ggplot(data = smaller) +
      geom_bin2d(mapping = aes(x = carat, y = price))#矩形分箱
    # install.packages("hexbin")
    ggplot(data = smaller) +
      geom_hex(mapping = aes(x = carat, y = price))#六边形分箱
    

    将其中一个连续变量分箱,使其相当于分类变量,每组生成一个箱线图。其缺点是不体现每个分箱的观测数量。
    设置var.width=TRUE使箱线图的宽度与观测数量成正比,或用cut_number设置箱线图分组的数目。

    ggplot(data = smaller, mapping = aes(x = carat, y = price)) + 
      geom_boxplot(mapping = aes(group = cut_width(carat, 0.1)))
    

    6.模式和模型

    模式是两个变量之间存在的系统性关系,可以揭示相关变动。
    如果说变动会生成不确定性,那么相关变动就会减少不确定性。
    如果两个变量共同变化,可以根据一个预测另一个
    如果相关变动归因于因果关系,可以使用一个控制另一个。
    “模型是用于从数据中抽取模式的一种工具”

    library(modelr)
    
    mod <- lm(log(price) ~ log(carat), data = diamonds)
    
    diamonds2 <- diamonds %>% 
      add_residuals(mod) %>% 
      mutate(resid = exp(resid))
    
    ggplot(data = diamonds2) + 
      geom_point(mapping = aes(x = carat, y = resid))
    

    对于残差反应价格,我是非常不理解的,怎么预测一个值的误差,能反映这个值本身的大小呢?看到这段代码一脸懵逼。
    于是进行了一些探索
    注意:以下探索并非标准答案,如有谬误敬请指出。

    ?lm
    ?add_residuals
    

    lm的帮助文档看完还是懵逼,在add_residuals中找到了一段有用的说明和一个例子:
    model,add_residuals takes a single model; the output column will be called resid
    这个函数为数据框添加新列resid,即残差。

    df <- tibble::data_frame(
      x = sort(runif(100)),
      y = 5 * x + 0.5 * x ^ 2 + 3 + rnorm(length(x))
    )
    plot(df)
    m1 <- lm(y ~ x, data = df)
    df %>% add_residuals(m1)
    m2 <- lm(y ~ poly(x, 2), data = df)
    df %>% spread_residuals(m1, m2)
    df %>% gather_residuals(m1, m2)
    

    示例代码中有m1 <- lm(y ~ x, data = df)以及df %>% add_residuals(m1),与书中的代码比较相似了。
    由此得知,lm是一个创建模型的命令,add_residuals则是增加残差列。书中的代码增加了log和exp,数量级差异很大的数字,被log函数改造成了一组同一数量级、差别很小的数字,残差都在3以内,约等于没有啊,这就是做到了消除价格和克拉数的强关系,好烧脑。。
    --此处感谢刘靖涛师兄帮我理清思路。


    微信公众号生信星球同步更新我的文章

    相关文章

      网友评论

        本文标题:详解《R数据科学》--第五章 EDA

        本文链接:https://www.haomeiwen.com/subject/utsknftx.html