数据处理神器tidyverse(1)dplyr
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