R tidyverse 学习

作者: 生信小白2018 | 来源:发表于2019-08-06 17:35 被阅读0次

    Tidyverse是一系列优秀R包的合集,其中最常用的7个package包括ggplot2/tibble/tidyr/readr/purrr/dplyr/stringr/forcat。
    每个包的功能如下:

    readr:用于数据读取
    tibble:用于形成强化数据框
    tidyr:用于长宽表格转换,数据整洁,数据清理
    dplyr:用于数据操纵,数据整理
    stringr:用于处理字符串数据
    forcats:用于处理因子数据
    ggplot2:用于数据可视化
    

    对于大多部分数据分析任务,通常有一些固定的操作,操作对应的命令和对应的R包也是相对固定的,基本可以用下图概括。

    image.png

    安装-载入-大概了解tidyverse

    install.packages("tidyverse")
    library(tidyverse)
    
    tidyverse_conflicts()     # tidyverse与其他包的冲突
    tidyverse_deps()          # 列出所有tidyverse的依赖包
    tidyverse_logo()          #获取tidyverse的logo
    tidyverse_packages()      # 列出所有tidyverse包
    tidyverse_update()        # 更新tidyverse包
    

    载入数据,了解数据

    library(datasets)
    install.packages("gapminder")
    library(gapminder)
    attach(iris)
    
    head(iris)
    str(iris)
    glimpse(iris)
    typeof(iris)
    dim(iris)
    

    readr包

    readr包中主要的函数有:
    read_csv,
    read_delim,
    read_table,
    write_delim,
    write_csv,
    write_excel_csv,
    write_delim函数,
    其中read_table中分隔符是指定为固定空格的,不能修改分隔符,函数read_delim可以指定分隔符
    

    管道符:%>%

    意思是将%>%左边的对象传递给右边的函数;可以大量减少内存中的对象,节省内存;
    f(x)变成这样:x %>% f和这样的东西:h(g(f(x)))变成这样:x%>%f%>%g%>%h

    x %>% f   等效与   f(x) 
    x %>% f(y)   等效与   f(x, y) 
    x %>% f %>% g %>% h   等价于   h(g(f(x)))
    

    参数占位符

    x %>% f(y,. )   等价于   f(y, x)
    x %>% f(y, z =. )   就相当于   f(y, z = x)
    

    正在使用属性的占位符
    它直接在右边的表达式中多次使用占位符。 但是,当占位符仅出现在嵌套表达式magrittr中时,仍将应用第一个参数规则。 原因是在大多数情况下,这种结果更清晰。

    x %>% f(y = nrow(.), z = ncol(.))     就相当于     f(x, y = nrow(x), z = ncol(x))
    

    行为可以通过在大括号中封闭右手来实现 overruled:

    x %>% {f(y = nrow(.), z = ncol(.))}     就相当于     f(y = nrow(x), z = ncol(x))
    

    带变量的管道
    许多函数接受数据参数,比如 lmaggregate,这在一个处理数据的管道中非常有用。 还有一些函数没有数据参数,对于公开数据中的变量很有用。 这是用 %$% 运算符完成的:

    library(tidyverse)
    library(magrittr)
    iris %>%
      subset(Sepal.Length> mean(Sepal.Length)) %$%
      cor(Sepal.Length, Sepal.Width)
    
    data.frame(z= rnorm(100)) %$% ts.plot(z)
    

    复合分配管道操作
    还有一个管道运算符,可以用作 shorthand 符号,在左手边是"被覆盖":

    iris$Sepal.Length<- 
      iris$Sepal.Length %>%
      sqrt()
    

    要避免在赋值运算符后面立即重复左边的操作,请使用 %<>% 运算符:

    iris$Sepal.Length %<>% sqrt
    

    这里运算符与 %>% 完全一样,只是管道分配结果而不是返回结果。 它必须是长链中的第一个管道操作符。

    除了%>%这个好用的符号外,magrittr还提供了其他三个比较好用的符号,%$%,%<>%和%T>%。

    %>%        forward-pipe operator.
    %T>%     tee operator.
    %<>%     compound assignment pipe-operator. (大神不建议这样做,要听话)
    %$%        exposition pipe-operator.
    

    tidyr, reshape2的替代者,功能更纯粹

    tidyr会将数据变的整洁
    整洁数据有三个原则:

    1 变量构成列
    2 观察组成行
    3 值放在单元里面
    

    整齐的数据特性:每一列都是一个变量;每一行都是一个观测值
    tidyr 四大常用函数

    gather() 使“宽”数据变成长数据
    spread() 使“长”数据变成宽数据
    separate() 将单个列拆分为多个列
    unite() 将多个列组合成一个列
    

    我们使用gather()来挖掘最初分散在三列中的数据,并将它们分为两列:键和值
    Gather占用多列并折叠成键值对,根据需要复制所有其他列, 当你注意到你的列不是变量时,你可以使用gather()。 “这就是tidyverse定义gather的方式。

    kv_gathered <- key_value %>% 
      gather(key, # this will be the new column for the 3 key columns
             value, # this will contain the 9 distinct values
             key1:key3, # this is the range of columns we want gathered
             na.rm = TRUE # handles missing
      )
    kv_gathered
    

    gather 函数主要四个参数
    data :数据集
    key :列明
    value :原来值的新的列名
    ...: 需要聚集的变量,删除前面加-

    gather(data, key = "key", value = "value", ..., na.rm = FALSE, convert = FALSE, factor_key = FALSE)
         第一个参数data放的是原数据,数据类型要是一个数据框;
         下面传一个键值对,名字是自己起的,这两个值是做新转换成的二维表的表头,即两个变量名;
         第四个是选中要转置的列,这个参数不写的话就默认全部转置;
         后面还可以加可选参数na.rm,如果na.rm = TRUE,那么将会在新表中去除原表中的缺失值(NA)。
    

    gather()举例
    先构造一个数据框stu:

    stu<-data.frame(grade=c("A","B","C","D","E"), female=c(5, 4, 1, 2, 3), male=c(1, 2, 3, 4, 5))  #成绩-性别的人数分布
    gather(stu,gender,count, -grade)
    第一个参数是原数据stu,二、三两个参数是键值对(性别,人数),第四个表示减去(除去grade列,就只转置剩下两列)
    

    separate负责分割数据,把一个变量中就包含两个变量的数据分来(上例gather中是属性名也是一个变量,一个属性名一个变量)
    separate(data, col, into, sep (= 正则表达式), remove =TRUE,convert = FALSE, extra = "warn", fill = "warn", ...)
    第一个参数放要分离的数据框;
    第二个参数放要分离的列;
    第三个参数是分割成的变量的列(肯定是多个),用向量表示;
    第四个参数是分隔符,用正则表达式表示,或者写数字,表示从第几位分开(文档里是这样写的:

    stu2<-data.frame(grade=c("A","B","C","D","E"), 
                     female_1=c(5, 4, 1, 2, 3), male_1=c(1, 2, 3, 4, 5),
                     female_2=c(4, 5, 1, 2, 3), male_2=c(0, 2, 3, 4, 6))
    stu2
    stu2_new<-gather(stu2,gender_class,count,-grade)
    stu2_new
    

    现在我们要做的就是把gender_class这一列分开:

    separate(stu2_new,gender_class,c("gender","class"))
    

    spread用来扩展表,把某一列的值(键值对)分开拆成多列。

    spread(data, key, value, fill = NA, convert = FALSE, drop =TRUE, sep = NULL)
    

    key是原来要拆的那一列的名字(变量名),value是拆出来的那些列的值应该填什么(填原表的哪一列)

    name<-rep(c("Sally","Jeff","Roger","Karen","Brain"),c(2,2,2,2,2))
    test<-rep(c("midterm","final"),5)
    class1<-c("A","C",NA,NA,NA,NA,NA,NA,"B","B")
    class2<-c(NA,NA,"D","E","C","A",NA,NA,NA,NA)
    class3<-c("B","C",NA,NA,NA,NA,"C","C",NA,NA)
    class4<-c(NA,NA,"A","C",NA,NA,"A","A",NA,NA)
    class5<-c(NA,NA,NA,NA,"B","A",NA,NA,"A","C")
    stu3<-data.frame(name,test,class1,class2,class3,class4,class5)
    stu3
    gather(stu3,class,grade, class1:class5, na.rm=TRUE)
    

    用spread函数将test列分来成midterm和final两列,这两列的值是选的两门课的成绩。
    再重复一遍,第二个参数是要拆分的那一列的列名,第三个参数是扩展出的列的值应该来自原表的哪一列的列名。

    stu3_new<-gather(stu3, class, grade, class1:class5, na.rm = TRUE)
    spread(stu3_new,test,grade)
    

    最后补充一条,现在class列显得有些冗余,直接用数字似乎更简洁,使用readr包中的parse_number()提出数字(还用到了dplyr的mutate函数)

    library(readr)
    library(dplyr)
    mutate(spread(stu3_new,test,grade),class=parse_number(class))
    

    unite--多列合并为一列

    unite(data, col, …, sep = “_”, remove = TRUE)
    data:为数据框
    col:被组合的新列名称
    …:指定哪些列需要被组合
    sep:组合列之间的连接符,默认为下划线
    remove:是否删除被组合的列
    

    先虚构一数据框

    set.seed(1)
    date <- as.Date('2016-11-01') + 0:14
    hour <- sample(1:24, 15)
    min <- sample(1:60, 15)
    second <- sample(1:60, 15)
    event <- sample(letters, 15)
    data <- data.table(date, hour, min, second, event)
    

    把date,hour,min和second列合并为新列datetime
    R中的日期时间格式为"Year-Month-Day-Hour:Min:Second"

    dataNew <- data %>%unite(datehour, date, hour, sep = ' ') %>%unite(datetime, datehour, min, second, sep = ':')
    dataNew
    

    dplyr

    主要功能:

    1、选择数据表的行: filter
    2、排序arrange
    3、改变数据表的列: mutate, transmute
        mutate 会保留改变前和改变后的列
        transmute 则只会保留改变后的列, 而扔掉改变前的列
    选择数据表的列: select, rename
    4、select 只会选择你指定的列
    5、rename 则会改变列名, 并选择其他所有的列
    6、通过 group_by 和 summarize 函数可以把数据进行分组进行分析
    
    

    过滤 filter()函数可以用来取数据子集。提取符合特定逻辑条件的行。

    例如,iris%>%filter(Sepal.Length> 6)

    iris %>% filter(Species == "virginica") # 指定满足的行
    iris %>% filter(Species == 'virginica',Sepal.Length > 6)  #多个条件用,分割
    

    选择 Sepal.Length > 6.7,且Species == "versicolor"或者 Species == "virginica"的行

    iris %>% filter(
      Sepal.Length > 6.7, 
      Species %in% c("versicolor", "virginica" )
    )
    

    排序 arrange()函数用来对观察值排序,默认是升序。

    iris %>% arrange(Sepal.Length)  #升序
    iris %>% arrange(desc(Sepal.Length))  #降序
    arrange(my_data, -Sepal.Length)  #根据Sepal.Length值排序(降序)
    

    新增变量 mutate()可以更新或者新增数据框一列。

    iris %>% mutate(Sepal.Length = Sepal.Length*10) # 将该列数值变成以mm为单位
    iris %>% mutate(SLMn = Sepal.Length * 10) # 创建新的一列
    

    select 选择指定列

    iris %>% select(1:3) #选择第一列到第三列
    iris %>% select(1,3)#选择第一列和第三列
     
    iris %>% select(Sepal.Length, Petal.Length)
    iris %>% select(Sepal.Length:Petal.Length)
    iris %>% select(starts_with("Petal"))  # Select column whose name starts with "Petal"
    iris %>% select(ends_with("Width"))  # Select column whose name ends with "Width"
    iris %>% select(contains("etal"))  # Select columns whose names contains "etal"
    iris %>% select(matches(".t."))  # Select columns whose name maches a regular expression
    iris %>% select(one_of(c("Sepal.Length", "Petal.Length")))  # selects variables provided in a character vector.
    
    iris %>% select_if(is.numeric)  #选择列属性为数字的列
    
    #删除列(根据列的属性)
    iris %>% select(-Sepal.Length, -Petal.Length)  #Removing Sepal.Length and Petal.Length columns
    iris %>% select(-(Sepal.Length:Petal.Length))  #Removing all columns from Sepal.Length to Petal.Length
    iris %>% select(-starts_with("Petal"))  #Removing all columns whose name starts with “Petal”:
    
    #根据列的位置删除列
    iris %>% select(-1)  #删除第1列
    iris %>% select(-(1:3))   #删除第1到3列
    iris %>% select(-1, -3)   #删除第1列与第3列
    

    rename()重命名列

    iris %>% 
      rename(
        sepal_length = Sepal.Length,
        sepal_width = Sepal.Width
      )
    #将列Sepal.Length重命名为sepal_length,将Sepal.Width重命名为sepal_width:
    # Rename column where names is "Sepal.Length"
    names(iris)[names(iris) == "Sepal.Length"] <- "sepal_length"
    names(iris)[names(iris) == "Sepal.Width"] <- "sepal_width"
    iris #使用函数名称()或colnames()获取列名称
     #根据列位置重命名
    names(iris)[1] <- "sepal_length"
    names(iris)[2] <- "sepal_width"
    

    整合函数流:

    iris %>%
    filter(Species == "Virginica") %>%
    mutate(SLMm = Sepal.Length) %>%
    arrange(desc(SLMm))

    summarize()函数可以让我们将很多变量汇总为单个的数据点。

    iris %>% summarize(medianSL = median(Sepal.Length))
    
    iris %>% 
      filter(Species == "virginica") %>%
      summarize(medianSL=median(Sepal.Length))
    #还可以一次性汇总多个变量;用,分割
    iris %>% 
      filter(Species == "virginica") %>% 
      summarize(medianSL = median(Sepal.Length),
                maxSL = max(Sepal.Length))
    

    group_by()可以让我们安装指定的组别进行汇总数据,而不是针对整个数据框

    iris %>% 
      group_by(Species) %>% 
      summarize(medianSL = median(Sepal.Length),
                maxSL = max(Sepal.Length))
    
    iris %>% 
      filter(Sepal.Length>6) %>% 
      group_by(Species) %>% 
      summarize(medianPL = median(Petal.Length), 
                maxPL = max(Petal.Length))
    

    ggplot2

    #散点图
    #散点图可以帮助我们理解两个变量的数据关系,使用geom_point()可以绘制散点图:
    iris_small<- iris %>% 
      filter(Sepal.Length > 5)
    ggplot(iris_small, aes(x=Petal.Length, y= Petal.Width)) + 
      geom_point()  
    
    #颜色
    ggplot(iris_small, aes(x = Petal.Length,
                           y = Petal.Width,
                           color = Species)) + 
      geom_point()
    
    #大小
    ggplot(iris_small, aes(x = Petal.Length,
                           y = Petal.Width,
                           color = Species,
                           size = Sepal.Length)) + 
      geom_point()
    
    #分面
    ggplot(iris_small, aes(x = Petal.Length,
                           y = Petal.Width)) + 
      geom_point() + 
      facet_wrap(~Species)
    
    
    #线图
    by_year <- gapminder %>% 
      group_by(year) %>% 
      summarize(medianGdpPerCap = median(gdpPercap))
    
    ggplot(by_year, aes(x = year,
                        y = medianGdpPerCap)) +
      geom_line() + 
      expand_limits(y=0)
    
    #条形图
    by_species <- iris %>%  
      filter(Sepal.Length > 6) %>% 
      group_by(Species) %>% 
      summarize(medianPL=median(Petal.Length))
    
    ggplot(by_species, aes(x = Species, y=medianPL)) + 
      geom_col()
    
    #直方图
    ggplot(iris_small, aes(x = Petal.Length)) + 
      geom_histogram()
    ## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
    
    #箱线图
    ggplot(iris_small, aes(x=Species, y=Sepal.Length)) + 
      geom_boxplot()
    

    其他数据导入和建模类的包

    DBI,用于联接数据库
    haven,用于读入SPSS、SAS、Stata 数据
    httr,用于联接网页API
    jsonlite,用于读入JSON 数据
    readxl,用于读入Excel 文档
    rvest,用于网络爬虫
    xml2,用于读入xml 数据
    modelr,用于使用管道函数建模
    broom,用于统计模型结果的整洁
    

    相关文章

      网友评论

        本文标题:R tidyverse 学习

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