数据处理神器tidyverse(1)dplyr

作者: 柳叶刀与小鼠标 | 来源:发表于2019-08-27 11:21 被阅读0次

    tidyverse包主要是由一组超级有用的R包(ggplot2,dplyr,purrr,tidyr,readr,tibble)组成,tidyverse包也是一种整理数据的方法。学习tidyverse的优势:
    (1)无论你认为tidyverse还是Base R更好,tidyverse是当前的潮流。
    (2)以tidyverse样式编写的代码更容易阅读,并且比base R更加一致(例如,tidyverse的代码格式几乎相同。另一方面,Base R属于不同的功能和参数风格的混搭。
    (3)Tidyverse社区蓬勃发展。Tidyverse最初的大部分都是Hadley Wickham的心血,但是现在有很多人为Tidyverse做出贡献包括维护和发展。 tidyverse是开源和协作的(这意味着任何人可以为它做出贡献),并且托管在tidyverse github上:https//github.com/tidyverse。

    使用这些包之前,首先需要创建这些包

    # only ever run once to install the individual packages on your system
    install.packages("dplyr")
    install.packages("ggplot2")
    install.packages("purrr")
    install.packages("tidyr")
    install.packages("readr")
    install.packages("tibble")
    

    然后加载它们

    library(dplyr)
    library(ggplot2)
    library(purrr)
    library(tidyr)
    library(readr)
    library(tibble)
    

    或者可以直接创建tidyverse。这样可以同时创建上述的所有包。

    # only ever run once to install the tidyverse on your system
    install.packages("tidyverse")
    library(tidyverse)
    

    在本教程中,如果您连接到互联网,我们将使用可以直接加载的gapminder数据集。

    # to download the data directly:
    gapminder_orig <- read.csv("https://raw.githubusercontent.com/swcarpentry/r-novice-gapminder/gh-pages/_episodes_rmd/data/gapminder-FiveYearData.csv")
    # define a copy of the original dataset that we will clean and play with 
    gapminder <- gapminder_orig
    

    gapminder数据集有1704行,包含按年、国家、人口,预期寿命和人均GDP的信息。

    “整洁”的数据框是每一行都是一个观察单位(在这种情况下,按国家和年份编制索引),每列对应于为每个观测单位测量的变量(在这种情况下,对于每个国家) 年份,衡量人口,大陆,预期寿命和GDP)。

    dim(gapminder)
    ## [1] 1704    6
    head(gapminder)
    ##       country year      pop continent lifeExp gdpPercap
    ## 1 Afghanistan 1952  8425333      Asia  28.801  779.4453
    ## 2 Afghanistan 1957  9240934      Asia  30.332  820.8530
    ## 3 Afghanistan 1962 10267083      Asia  31.997  853.1007
    ## 4 Afghanistan 1967 11537966      Asia  34.020  836.1971
    ## 5 Afghanistan 1972 13079460      Asia  36.088  739.9811
    ## 6 Afghanistan 1977 14880372      Asia  38.438  786.1134
    

    管道函数: %>%


    管道函数 %>%是数据整理的主力。 管道函数允许用户将许多功能链接在一起,从而无需定义多个中间对象以用作后续功能的输入。 在我看来,管道函数也是tidyverse代码基本上比基本R代码更容易阅读的主要原因。

    gapminder %>%
      filter(continent == "Americas", year == "2007") %>%
      select(country, lifeExp)
    

    我在脑海中读到了这样的代码:采用gapminder数据集然后过滤大陆为美洲大陆和时间为2007年的观测值,然后选择国家和预期寿命变量两列。

    # take the gapminder dataset
    gapminder %>%
      # and filter to the rows whose continent is Americas and year is 2007
      filter(continent == "Americas", year == 2007) %>%
      # show the country and lifeExp values for these rows
      select(country, lifeExp)
    
    ##                country lifeExp
    ## 1            Argentina  75.320
    ## 2              Bolivia  65.554
    ## 3               Brazil  72.390
    ## 4               Canada  80.653
    ## 5                Chile  78.553
    ## 6             Colombia  72.889
    ## 7           Costa Rica  78.782
    ## 8                 Cuba  78.273
    ## 9   Dominican Republic  72.235
    ## 10             Ecuador  74.994
    ## 11         El Salvador  71.878
    ## 12           Guatemala  70.259
    ## 13               Haiti  60.916
    ## 14            Honduras  70.198
    ## 15             Jamaica  72.567
    ## 16              Mexico  76.195
    ## 17           Nicaragua  72.899
    ## 18              Panama  75.537
    ## 19            Paraguay  71.752
    ## 20                Peru  71.421
    ## 21         Puerto Rico  78.746
    ## 22 Trinidad and Tobago  69.819
    ## 23       United States  78.242
    ## 24             Uruguay  76.384
    ## 25           Venezuela  73.747
    

    要成为管道函数专家,您需要牢牢掌握它实际上在做什么。 管道函数使用%>%将左侧的对象作为右侧函数的第一个参数。例如,非管道版的

    filter(gapminder, continent == "Americas", year == 2007)
    

    在基础R的风格中,使代码更具可读性的常用方法是定义中间对象。

    gapminder_filtered <- filter(gapminder, continent == "Americas", year == 2007)
    gapminder_filtered_selected <- select(gapminder_filtered, country, lifeExp)
    gapminder_filtered_selected
    
    ##                country lifeExp
    ## 1            Argentina  75.320
    ## 2              Bolivia  65.554
    ## 3               Brazil  72.390
    ## 4               Canada  80.653
    ## 5                Chile  78.553
    ## 6             Colombia  72.889
    ## 7           Costa Rica  78.782
    ## 8                 Cuba  78.273
    ## 9   Dominican Republic  72.235
    ## 10             Ecuador  74.994
    ## 11         El Salvador  71.878
    ## 12           Guatemala  70.259
    ## 13               Haiti  60.916
    ## 14            Honduras  70.198
    ## 15             Jamaica  72.567
    ## 16              Mexico  76.195
    ## 17           Nicaragua  72.899
    ## 18              Panama  75.537
    ## 19            Paraguay  71.752
    ## 20                Peru  71.421
    ## 21         Puerto Rico  78.746
    ## 22 Trinidad and Tobago  69.819
    ## 23       United States  78.242
    ## 24             Uruguay  76.384
    ## 25           Venezuela  73.747
    

    对我来说,管道函数版本更加清晰,同时摆脱了在阅读代码时需要很多中间对象。

    数据操作 dplyr包


    在tidyverse中,你几乎不需要使用[,] 或者 $ 去选择行,列。因为可以使用 filter()select()
    # take the gapminder dataset
    gapminder %>%
      # and filter to the rows whose continent is Americas and year is 2007
      filter(continent == "Americas", year == 2007) %>%
      # show the country and lifeExp values for these rows
      select(country, lifeExp)
    

    这与下面的使用base R的代码输出的结果相同。

    # identify which rows correspond to the Americas and the year 2007
    continent_year_index <- which(gapminder["continent"] == "Americas" & gapminder["year"] == 2007)
    # pull only those rows and show the country and life expectency columns
    gapminder[continent_year_index, c("country", "lifeExp")]
    

    select:选择列

    gapminder %>% 
      select(country, gdpPercap) 
    

    同样可以使用select来用于删除列。

    gapminder %>% 
      select(-continent) 
    

    请注意,还有一些其他包(例如MASS包)也有一个名为select()的函数。 如果您在会话中加载tidyverse包后碰巧加载了其中一个包,则最终可能会出现一个错误:Error:unused argument(x)。 要解决这个问题,您需要使用dplyr :: select()直接从dplyr包中调用select()函数,或者确保在tidyverse包之前加载这些包(它会自动加载dplyr包)。

    filter:过滤满足特定条件的行

    过滤是一种非常简单的方法,只保留满足特定条件的行。 这些条件总是基于涉及数据帧的变量/列的逻辑语句。
    例如,要仅保留记录总数至少为10亿的行,可以使用包含pop变量的逻辑语句的过滤(再次取消引用)。

    gapminder %>% 
      filter(pop > 1000000000) 
    ##   country year        pop continent lifeExp gdpPercap
    ## 1   China 1982 1000281000      Asia  65.525  962.4214
    ## 2   China 1987 1084035000      Asia  67.274 1378.9040
    ## 3   China 1992 1164970000      Asia  68.690 1655.7842
    ## 4   China 1997 1230075000      Asia  70.426 2289.2341
    ## 5   China 2002 1280400000      Asia  72.028 3119.2809
    ## 6   China 2007 1318683096      Asia  72.961 4959.1149
    ## 7   India 2002 1034172547      Asia  62.879 1746.7695
    ## 8   India 2007 1110396331      Asia  64.698 2452.2104
    

    您可以使用逗号指定多个过滤条件(在这种情况下,过滤器函数将返回满足所有指定条件的行)。

    gapminder %>% 
      filter(pop > 100000000, year == 1992) 
    ##         country year        pop continent lifeExp  gdpPercap
    ## 1    Bangladesh 1992  113704579      Asia  56.018   837.8102
    ## 2        Brazil 1992  155975974  Americas  67.057  6950.2830
    ## 3         China 1992 1164970000      Asia  68.690  1655.7842
    ## 4         India 1992  872000000      Asia  60.223  1164.4068
    ## 5     Indonesia 1992  184816000      Asia  62.681  2383.1409
    ## 6         Japan 1992  124329269      Asia  79.360 26824.8951
    ## 7      Pakistan 1992  120065004      Asia  60.838  1971.8295
    ## 8 United States 1992  256894189  Americas  76.090 32003.9322
    

    mutate:添加一个新变量

    改变数据框涉及添加新变量。 这个新变量通常是现有变量的函数,但也可以基于外部对象定义。
    例如,下面我向gapminder数据框添加一个新变量gdp。 gdp等于gdpPercap乘以pop,然后使用经典的head()函数查看数据框的前6行。

    gapminder %>% 
      mutate(gdp = gdpPercap * pop) %>%
      head
    ##       country year      pop continent lifeExp gdpPercap         gdp
    ## 1 Afghanistan 1952  8425333      Asia  28.801  779.4453  6567086330
    ## 2 Afghanistan 1957  9240934      Asia  30.332  820.8530  7585448670
    ## 3 Afghanistan 1962 10267083      Asia  31.997  853.1007  8758855797
    ## 4 Afghanistan 1967 11537966      Asia  34.020  836.1971  9648014150
    ## 5 Afghanistan 1972 13079460      Asia  36.088  739.9811  9678553274
    ## 6 Afghanistan 1977 14880372      Asia  38.438  786.1134 11697659231
    

    请注意,我没有重新定义gapminder数据帧,所以我在这里所做的就是使用附加的gdp变量打印出数据帧。如果您希望能够在该行中使用此gdp变量,则需要重新定义gapminder数据框,以便gapminder现在对应于具有gdp变量的版本。

    gapminder <- gapminder %>% 
      mutate(gdp = gdpPercap * pop)
    

    arrange:按顺序排列数据框的行

    排列功能允许您以数据帧的一个(或多个)变量的递增或递减顺序轻松地重新排序数据帧的行。例如,您可以按照预期寿命的顺序排列数据框中的所有行。

    gapminder %>% 
      arrange(lifeExp) %>%
      head
    ##        country year     pop continent lifeExp gdpPercap         gdp
    ## 1       Rwanda 1992 7290203    Africa  23.599  737.0686  5373379682
    ## 2  Afghanistan 1952 8425333      Asia  28.801  779.4453  6567086330
    ## 3       Gambia 1952  284320    Africa  30.000  485.2307   137960781
    ## 4       Angola 1952 4232095    Africa  30.015 3520.6103 14899557133
    ## 5 Sierra Leone 1952 2143249    Africa  30.331  879.7877  1885604185
    ## 6  Afghanistan 1957 9240934      Asia  30.332  820.8530  7585448670
    

    当然也可以降序

    gapminder %>% 
      arrange(desc(gdpPercap)) %>%
      head
    ##   country year     pop continent lifeExp gdpPercap         gdp
    ## 1  Kuwait 1957  212846      Asia  58.033 113523.13 24162944745
    ## 2  Kuwait 1972  841934      Asia  67.712 109347.87 92063687055
    ## 3  Kuwait 1952  160000      Asia  55.565 108382.35 17341176464
    ## 4  Kuwait 1962  358266      Asia  60.470  95458.11 34199395868
    ## 5  Kuwait 1967  575003      Asia  64.624  80894.88 46514800559
    ## 6  Kuwait 1977 1140357      Asia  69.343  59265.48 67583801715
    

    group_by函数:

    在由一个或多个变量定义的组内单独应用其他dplyr函数。

    可以将group_by()视为根据您指定的分类变量将数据帧拆分为多个单独的数据帧。 应用于分组数据框的所有函数将分别应用于每个组,直到指定ungroup()函数为止。下面的代码将数据框架仅过滤到预期寿命高于其大陆平均预期寿命的观察值。

    gapminder %>%
      group_by(continent) %>%
      filter(lifeExp > mean(lifeExp)) %>%
      ungroup() 
    ## # A tibble: 873 x 7
    ##    country  year      pop continent lifeExp gdpPercap           gdp
    ##    <fct>   <int>    <dbl> <fct>       <dbl>     <dbl>         <dbl>
    ##  1 Albania  1987  3075321 Europe       72       3739.  11498418358.
    ##  2 Albania  1997  3428038 Europe       73.0     3193.  10945912519.
    ##  3 Albania  2002  3508512 Europe       75.7     4604.  16153932130.
    ##  4 Albania  2007  3600523 Europe       76.4     5937.  21376411360.
    ##  5 Algeria  1967 12760499 Africa       51.4     3247.  41433235247.
    ##  6 Algeria  1972 14760787 Africa       54.5     4183.  61739408943.
    ##  7 Algeria  1977 17152804 Africa       58.0     4910.  84227416174.
    ##  8 Algeria  1982 20033753 Africa       61.4     5745. 115097120653.
    ##  9 Algeria  1987 23254956 Africa       65.8     5681. 132119742845.
    ## 10 Algeria  1992 26298373 Africa       67.7     5023. 132102425043.
    ## # … with 863 more rows
    

    首先根据大陆分组,然后挑选那些大于该大陆平均寿命的观察值,然后ungroup以及计数。

    gapminder %>%
      group_by(continent) %>%
      filter(lifeExp > mean(lifeExp)) %>%
      ungroup() %>%
      count(continent)
    ## # A tibble: 5 x 2
    ##   continent     n
    ##   <fct>     <int>
    ## 1 Africa      282
    ## 2 Americas    176
    ## 3 Asia        216
    ## 4 Europe      189
    ## 5 Oceania      10
    

    挑选那些大于所有观察值综合的平均寿命,然后计数每个大陆的国家数量。

    gapminder %>%
      filter(lifeExp > mean(lifeExp)) %>%
      count(continent)
    ## # A tibble: 5 x 2
    ##   continent     n
    ##   <fct>     <int>
    ## 1 Africa       80
    ## 2 Americas    218
    ## 3 Asia        224
    ## 4 Europe      349
    ## 5 Oceania      24
    

    请注意,当您不按大陆分组时,包括的非洲国家数量明显减少,因为它们的生活预期往往低于全球平均水平。

    下面的代码首先过滤到2007年,然后按大陆将数据框分成几组,然后添加一列大陆平均寿命,然后只保留国家,大陆,寿命预期和大陆平均寿命这几列。

    gapminder %>% 
      # first filter to 2007
      filter(year == 2007) %>%
      # group by continent
      group_by(continent) %>%
      # add a column within each continent corresponding to the average life expectancy
      mutate(continent_lifeExp = mean(lifeExp)) %>%
      # ungroup the data frame
      ungroup() %>% 
      # only show a few variables
      select(country, continent, lifeExp, continent_lifeExp) %>%
      head(10)
    ## # A tibble: 10 x 4
    ##    country     continent lifeExp continent_lifeExp
    ##    <fct>       <fct>       <dbl>             <dbl>
    ##  1 Afghanistan Asia         43.8              70.7
    ##  2 Albania     Europe       76.4              77.6
    ##  3 Algeria     Africa       72.3              54.8
    ##  4 Angola      Africa       42.7              54.8
    ##  5 Argentina   Americas     75.3              73.6
    ##  6 Australia   Oceania      81.2              80.7
    ##  7 Austria     Europe       79.8              77.6
    ##  8 Bahrain     Asia         75.6              70.7
    ##  9 Bangladesh  Asia         64.1              70.7
    ## 10 Belgium     Europe       79.4              77.6
    

    请注意,同一大洲的所有行都具有相同的continent_lifeExp值。 请注意,即使此示例为每个大陆定义单个值,也会对该大陆内的所有行重复此值。

    summarize()(或summarize())函数聚合在数据框的各行中。 例如,您可以计算平均预期寿命以及总GDP。

    gapminder %>% 
      summarise(mean_lifeExp = mean(lifeExp),
                total_gdp = sum(gdp))
    ##   mean_lifeExp    total_gdp
    ## 1     59.47444 3.183235e+14
    

    汇总函数与group_by()函数非常吻合。 例如,首先按年分组,然后计算每年的平均预期寿命和总GDP。

    gapminder %>% 
      group_by(year) %>%
      summarise(mean_lifeExp = mean(lifeExp),
                total_gdp = sum(gdp)) 
    ## # A tibble: 12 x 3
    ##     year mean_lifeExp total_gdp
    ##    <int>        <dbl>     <dbl>
    ##  1  1952         49.1   7.04e12
    ##  2  1957         51.5   8.90e12
    ##  3  1962         53.6   1.10e13
    ##  4  1967         55.7   1.42e13
    ##  5  1972         57.6   1.84e13
    ##  6  1977         59.6   2.23e13
    ##  7  1982         61.5   2.54e13
    ##  8  1987         63.2   3.01e13
    ##  9  1992         64.2   3.45e13
    ## 10  1997         65.0   4.10e13
    ## 11  2002         65.7   4.73e13
    ## 12  2007         67.0   5.81e13
    

    更多dplyr函数

    其他非常有用的dplyr函数包括:rename() 对数据框的列进行重命名

    gapminder %>%
      rename(gdp_per_capita = gdpPercap,
             life_exp = lifeExp) %>%
      head
    ##       country year      pop continent life_exp gdp_per_capita         gdp
    ## 1 Afghanistan 1952  8425333      Asia   28.801       779.4453  6567086330
    ## 2 Afghanistan 1957  9240934      Asia   30.332       820.8530  7585448670
    ## 3 Afghanistan 1962 10267083      Asia   31.997       853.1007  8758855797
    ## 4 Afghanistan 1967 11537966      Asia   34.020       836.1971  9648014150
    ## 5 Afghanistan 1972 13079460      Asia   36.088       739.9811  9678553274
    ## 6 Afghanistan 1977 14880372      Asia   38.438       786.1134 11697659231
    

    distinct()用于提取变量的不同值(去重)。

    gapminder %>% 
      distinct(continent)
    ##   continent
    ## 1      Asia
    ## 2    Europe
    ## 3    Africa
    ## 4  Americas
    ## 5   Oceania
    

    sample_n() and sample_frac() 为在数据框中随机选择行列。

    gapminder %>% 
      sample_n(2)
    
    ##                    country year      pop continent lifeExp gdpPercap
    ## 1             South Africa 1997 42835005    Africa  60.236  7479.188
    ## 2 Central African Republic 1967  1733638    Africa  41.478  1136.057
    ##            gdp
    ## 1 320371065828
    ## 2   1969510918
    

    count()用于计算分类变量的每个类型的行数(观察值)。

    gapminder %>% 
      count(continent)
    ## # A tibble: 5 x 2
    ##   continent     n
    ##   <fct>     <int>
    ## 1 Africa      624
    ## 2 Americas    300
    ## 3 Asia        396
    ## 4 Europe      360
    ## 5 Oceania      24
    

    transmute()用于做一个mutate并同时选择:只保留数据框中新定义的变量。

    gapminder %>% 
      transmute(gdp = gdpPercap * pop) %>%
      head
    
    ##           gdp
    ## 1  6567086330
    ## 2  7585448670
    ## 3  8758855797
    ## 4  9648014150
    ## 5  9678553274
    ## 6 11697659231
    

    相关文章

      网友评论

        本文标题:数据处理神器tidyverse(1)dplyr

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