Tidyverse ------Tidyr

趁着今天有时间,想着是不是该记录点东西了,没错是该记录一下了。今天的重头戏是tidyr package。
Tidy datasets are all alike, but every messy dataset is messy in its own way 。这是 Hadley Wickham(牛人)的总结。
数据预处理对于后续的分析很关键,处理过后的Tidy data 只要有三类特征:

  1. 每一列代表一个变量
  2. 每一行代表一个观测值
  3. 每一单元格代表一个value
    在Tidyverse(它是由RStudio选出多个资料科学应用套件的集合)中其他一些如dplyr、ggplot2等都是基于Tidy tada,下面这张图片很好的说明了tidy data的数据结构。这个内容也是我最近在学习的内容。


    2019-05-02 20-20-20 的屏幕截图.png

1. spreading and gathering

拿到一个数据首先要分辨出观测值和变量,然后就是解决两个很常见的问题:

  1. 一个变量分散在多列
  2. 一个观测分散在多行
    因此,就要进行长宽数据结构的转换,因此你需要用到tidyr package 中两个重要的函数: spread 和 gather

1.1 gather

让数据变成长窄型


2019-05-02 21-31-21 的屏幕截图.png
> table4a
# A tibble: 3 x 3
  country             `1999`  `2000`
*                          
1 Afghanistan      745         2666
2 Brazil                37737       80488
3 China                212258    213766
对于上面的数据,可以看出1999和2000两列可以合并成一个新变量year,要完成这个转换:
        Usage :    gather(key= , value=  , ...)
          1. 为需要合并的多列定义新的变量名,key = "year"
          2. 为分布在单元格变量定义一个变量名,value = "cases"
          3. 设置需要合并成一个变量的列名,`1999`,`2000`,若需要合并成多列可直接指定列的索引值

tidy4a <- table4a  %>%  gahter (key = "year", value = "cases", `1999`,`2000`)
> tidy4a
# A tibble: 6 x 3
  country                    year   cases
                            
1 Afghanistan         1999     745
2 Brazil                      1999   37737
3 China                     1999  212258
4 Afghanistan         2000    2666
5 Brazil                      2000   80488
6 China                      2000  213766

1.2 spread

让数据变成宽短型


2019-05-02 21-33-25 的屏幕截图.png
> table2
# A tibble: 12 x 4
   country                   year              type            count
                                                 
 1 Afghanistan       1999              cases             745
 2 Afghanistan       1999         population   19987071
 3 Afghanistan       2000              cases            2666
 4 Afghanistan       2000         population   20595360
 5 Brazil                    1999             cases           37737
 6 Brazil                    1999         population  172006362
 7 Brazil                    2000            cases           80488
 8 Brazil                    2000        population   174504898
 9 China                   1999            cases            212258
10 China                  1999       population    1272915272
11 China                  2000            cases           213766
12 China                  2000       population    1280428583
对于上面的数据可以看出一个观测值是每个国家每一年的数据,然而每一个观测值确被分成两行排列,要完成这个转换:
      Usage: spread(key=  ,value = )
      1.  包含变量名的列,即key列,key = "type"
      2.  包含value的列,即value列,value = "count"
      对于这个函数的理解,将type列和count列每一行数据看成key-value pair ,从而利用spread对每一个key-value进行列的转换

table2 %>% spread(key = "type",value = "count")
# A tibble: 6 x 4
  country                   year         cases      population
                                            
1 Afghanistan         1999          745         19987071
2 Afghanistan         2000         2666        20595360
3 Brazil                      1999        37737      172006362
4 Brazil                      2000        80488      174504898
5 China                     1999        212258    1272915272
6 China                     2000        213766    1280428583

2. Separating and uniting

对于一些数据,如果每一列的每一个单元格是由多个变量组成,那么我们需要将这一列分割成两列,这时候就要用到separate ; 又或者将多列合并成一列,就要用到unite

2.1 separate

> table3
# A tibble: 6 x 3
  country                    year             rate             
*                                              
1 Afghanistan          1999           745/19987071     
2 Afghanistan          2000           2666/20595360    
3 Brazil                       1999           37737/172006362  
4 Brazil                       2000           80488/174504898  
5 China                      1999            212258/1272915272
6 China                      2000            213766/1280428583
    Usage: separate (col = , into =  , sep =  )
    1. 定义需要分割的列名 col = "rate"
    2. 定义分割后的多个列名 into = c("cases", "population")
    3. 指定分隔符,默认以非字母、数字为分割符,也可用数字指定从字符串的那个字符分割

table3 %>% separate(col = rate,into = c("cases","population"))
# A tibble: 6 x 4
  country                             year    cases       population
                                                    
1 Afghanistan                 1999      745          19987071  
2 Afghanistan                 2000     2666        20595360  
3 Brazil                             1999      37737     172006362 
4 Brazil                             2000      80488     174504898 
5 China                            1999      212258   1272915272
6 China                            2000      213766   1280428583
从返回的结果可以看出新生成的cases 和population两列数据类型为数值型,而结果是字符型,因此需要指定参数convert = TRUE
table3 %>% separate(col = rate,into = c("cases","population"),convert = TRUE)

table3 %>%  separate(year, into = c("century", "year"), sep = 2) # 表示从year列中第二个字符后进行分割
# A tibble: 6 x 4
  country                 century              year           rate             
                                                            
1 Afghanistan          19                       99             745/19987071     
2 Afghanistan          20                       00             2666/20595360    
3 Brazil                       19                       99             37737/172006362  
4 Brazil                       20                       00             80488/174504898  
5 China                      19                       99              212258/1272915272
6 China                      20                       00              213766/1280428583

2.2 unite

对上面的数据century和year 两列进行合并
    Usage : unite(col = , ... , sep = ,)
    1. 定义合并后的列名
    2. 指定需要合并的多列(列名或索引)
    3. 指定合并后来自不同列数据的连接符,默认是"_" 

unite (col = "new" , "century", "year", sep = "")
# A tibble: 6 x 3
  country                    year             rate             
*                                              
1 Afghanistan          1999           745/19987071     
2 Afghanistan          2000           2666/20595360    
3 Brazil                       1999           37737/172006362  
4 Brazil                       2000           80488/174504898  
5 China                      1999            212258/1272915272
6 China                      2000            213766/1280428583

3. missing value

改变数据结构的同时,会出现一些缺失值,缺失值主要有以下两种方式: 1、原数据集中有NA 标记 ; 2、 有些观测值不存在数据集中

> stocks
# A tibble: 7 x 3
   year      qtr     return
      
1  2015     1       1.88
2  2015     2       0.59
3  2015     3       0.35
4  2015     4       NA   
5  2016     2      0.92
6  2016     3      0.17
7  2016     4      2.66
观测数据可以看出: 有一个明确的缺失值NA, 还有一个隐藏的观测值缺失
为了让隐藏的缺失值变成NA,可以spread 将year列展开

stocks %>% spread(key = year,value = return)
>stocks
# A tibble: 4 x 3
    qtr     `2015`  `2016`
          
1     1        1.88         NA   
2     2        0.59        0.92
3     3        0.35        0.17
4     4         NA          2.66
一般原本存在的NA可能不是很重要,因此你可以利用gather将NA变成隐藏的缺失。

stocks %>% spread(key = year,value = return)  %>% gather (key = "year" , value = "return" ,`2015`,`2016`, na.rm = TRUE)
# A tibble: 6 x 3
    qtr        year        count
           
1     1       2015        1.88
2     2       2015        0.59
3     3       2015        0.35
4     2       2016        0.92
5     3       2016        0.17
6     4       2016        2.66

另一个让隐藏的缺失值变成NA的函数: complete()
stocks %>%  complete(year, qtr) #列出year和qtr所有的观测组合
# A tibble: 8 x 3
   year          qtr   return
         
1  2015         1       1.88
2  2015         2       0.59
3  2015         3       0.35
4  2015         4        NA   
5  2016         1        NA   
6  2016         2       0.92
7  2016         3       0.17
8  2016         4       2.66

还有一种情况就是对于数据录入员来说,有时候缺失值表示与之前值相同故而省略
> treament
# A tibble: 4 x 3
  person                     treament     response
                                       
1 Derrick Whitmore        1                  7
2 NA                                       2                10
3 NA                                       3                  7
4 Katherine Burke           1                  4

treatment %>% fill(person)

# A tibble: 4 x 3
  person                              treament response
                                          
1 Derrick Whitmore              1             7
2 Derrick Whitmore              2            10
3 Derrick Whitmore              3             7
4 Katherine Burke                 1             4

有了Tidy data,我们就可以开展后续数据整理和分析,这就要介绍到Tidyverse家族另一个重要的dplyr package,可以实现类似SQL的功能,虽然一些R基础包中函数也可以完成目标,但是当你熟悉了dplyr的操作,你会感到很High!!!

附上原文链接: https://r4ds.had.co.nz/

你可能感兴趣的:(Tidyverse ------Tidyr)