dplyr包进行数据转换

使用dplyr进行数据转换

tidyverse 中的另一个核心 R 包 ——dplyr

1 nycflights13

介绍 dplyr 中的基本数据操作,我们需要使用 nycflights13::flights。这个数据框包含了 2013 年从纽约市出发的所有 336 776 次航班的信息。

install.packages("nycflights13")

library(nycflights13)

library(tidyverse)

想看到整个数据集,可以使用 View(flights)

int 表示整数型变量。

dbl 表示双精度浮点数型变量,或称实数。

chr 表示字符向量,或称字符串。

dttm 表示日期时间(日期 + 时间)型变量

lgl 表示逻辑型变量,是一个仅包括 TRUE FALSE 的向量。

fctr 表示因子,R 用其来表示具有固定数目的值的分类变量。

date 表示日期型变量。

2 dplyr基础

5 dplyr 核心函数:

• 按值筛选观测(filter())。

• 对行进行重新排序(arrange())。

• 按名称选取变量(select())。

• 使用现有变量的函数创建新变量(mutate())。

• 将多个值总结为一个摘要统计量(summarize())。

这些函数都可以和 group_by() 函数联合起来使用,group_by() 函数可以改变以上每个函数的作用范围,让其从在整个数据集上操作变为在每个分组上分别操作。这 6 个函数构成了数据处理语言的基本操作。

2.1  使用filter()筛选行

filter() 函数可以基于观测的值筛选出一个观测子集。第一个参数是数据框名称,第二个参数以及随后的参数是用来筛选数据框的表达式。例如,我们可以使用以下代码筛选出 11 日的所有航班信息:

filter(flights, month == 1, day == 1)

 

2.1.1 比较运算符

比较运算符:>>=<<=!=(不等于)和 ==(等于)

比较浮点数是否相等时,不能使用 ==,而应该使用 near()

2.1.2 逻辑运算符

布尔运算符:& 表示| 表示! 表示

以下代码可以找出 11 月或 12 月出发的所有航班:

filter(flights, month == 11 | month == 12)

 

2.2 缺失值

缺失值称 NAnot available,不可用)。NA 表示未知的值,因此缺失值是“可传染的”。如果运算中包含了未知值,那么运算结果一般来说也是个未知值

filter() 只能筛选出条件为 TRUE 的行;它会排除那些条件为 FALSE NA 的行。如果想保

留缺失值,可以明确指出。

RNA代表缺失值,NA是不可用,not avaliable的简称,用来存储缺失信息,这里的NA表示没有,但并不一定是0NA是不知多少,也可能是0,也可能是任何值,缺失值和值为零完全不同。

关于NA的计算,使用函数na.rm=T/F 可以去掉缺失值。

使用相应的逻辑函数is.na() 可以显示是否存在缺失值NA

导入需要的包 install.packages("VIM")

ia.na()函数测试数据集sleep中的缺失值。

返回mtcars数据集每一行的缺失值rowSums(mtcars)

返回mtcars数据集每一列的缺失值cloSums(mtcars)

使用函数na.omit()去除缺失数据。

使用函数可以去除包含缺失值的行na.omit(mtcars),这样处理会删除很多行,影响数据的完整性。

1 处理缺失值

删除某一个缺失值 na.rm=TRUE

删除空值所在的整个行 na.omit(数据集名字)

3 使用arrange()排列行

arrange() 函数的工作方式与 filter() 函数非常相似,但前者不是选择行,而是改变行的

顺序。

arrange(flights, year, month, day)

 

4 使用select()选择列

select() 函数可以让你快速生成一个有用的变量子集。

# 按名称选择列

select(flights, year, month, day)

 

# 选择“year”和“day”之间的所有列(包括“year”和“day”)

select(flights, year:day)

 

# 选择不在“year”和“day”之间的所有列(不包括“year”和“day”)

select(flights, -(year:day))

 

还可以在 select () 函数中使用一些辅助函数。

starts_with("abc"):匹配以“abc”开头的名称。

ends_with("xyz"):匹配以“xyz”结尾的名称。

contains("ijk"):匹配包含“ijk”的名称。

matches("(.)\\1"):选择匹配正则表达式的那些变量。这个正则表达式会匹配名称中有

重复字符的变量。

num_range("x", 1:3):匹配 x1x2 x3

select() 可以重命名变量,使用 select() 函数的变体 rename() 函数来重命名变量,以保留所有未明确提及的变量:

rename(flights, tail_num = tailnum)   #给变量重命名

select() 函数和 everything() 辅助函数结合起来使用。当想要将几个变量移到数据框开头时,这种用法非常奏效:

select(flights, time_hour, air_time, everything())

 

5 使用mutate()添加新变量

mutate() 总是将新列添加在数据集的最后,查看所有列的最简单的方法就是使用 View()

函数:

flights_sml <- select(flights,

 year:day,

 ends_with("delay"),

 distance,

 air_time

)

mutate(flights_sml,

 gain = arr_delay - dep_delay,

 speed = distance / air_time * 60

)

 

5.1 常用创建函数

算术运算符:+-*/^

模运算符:%/% %%

对数函数:log()log2() log10()

偏移函数:lead() lag() 函数可以返回一个序列的领先值和滞后值。

累加和滚动聚合R 提供了计算累加和、累加积、累加最小值和累加最大值的函数:cumsum()cumprod()commin() cummax()dplyr 还提供了 cummean() 函数以计算累加均值。如果想要计算滚动聚合(即滚动窗口求和),那么可以尝试使用 RcppRoll 包。

逻辑比较:<<=>>= != 

6 使用summarize()进行分组摘要

summarize(),它可以将数据框折叠成一行:

summarize(flights, delay = mean(dep_delay, na.rm = TRUE))

 

group_by() 可以将分析单位从整个数据集更改为单个分组,在分组后的数据框上使用 dplyr 函数时,它们会自动地应用到每个分组。

按日期分组,可以得到每日平均延误时间:

by_day <- group_by(flights, year, month, day)

summarize(by_day, delay = mean(dep_delay, na.rm = TRUE))

 

6.1 使用管道组合多种操作

要研究每个目的地的距离和平均延误时间之间的关系解决这个问题的另一种方法是使用管道,%>%

delays <- flights %>%

 group_by(dest) %>%

 summarize(

 count = n(),     #n() 返回当前分组的大小

 dist = mean(distance, na.rm = TRUE),

 delay = mean(arr_delay, na.rm = TRUE)

) %>%

filter(count > 20, dest != "HNL")

在阅读代码时,%>% 最好读作然后。使用这种方法时,x %>% f(y) 会转换为 f(x, y)x %>% f(y) %>% g(z) 会转换为 g(f(x, y), z),以此类推。支持管道操作是 tidyverse 中的 R 包的核心原则之一。

6.2 缺失值

所有聚合函数都有一个 na.rm 参数,它可以在计算前除去缺失值:

flights %>%

 group_by(year, month, day) %>%

 summarize(mean = mean(dep_delay, na.rm = TRUE))

也可以通过先去除取消的航班来解决缺失值问题。

not_cancelled <- flights %>%

 filter(!is.na(dep_delay), !is.na(arr_delay))

not_cancelled %>%

 group_by(year, month, day) %>%

 summarize(mean = mean(dep_delay))

 

6.3 计数

聚合操作中包括一个计数(n())或非缺失值的计数(sum(!is_na()))是个好主意。这样你就可以检查一下,以确保自己没有基于非常少量的数据作出结论。例如,我们查看一下具有最长平均延误时间的飞机(通过机尾编号进行识别):

delays <- not_cancelled %>%

 group_by(tailnum) %>%

 summarize(

 delay = mean(arr_delay)

 )

ggplot(data = delays, mapping = aes(x = delay)) +

 geom_freqpoly(binwidth = 10)

 

结果分析:有些飞机的平均延误时间长达 5 小时(300 分钟)。

6.4 常用的摘要函数

位置度量我们已经使用过 平均mean(x),但中位数median(x) 也非常有用。

not_cancelled %>%

 group_by(year, month, day) %>%

 summarize(

 # 平均延误时间:

 avg_delay1 = mean(arr_delay),

 # 平均正延误时间:

 avg_delay2 = mean(arr_delay[arr_delay > 0])

 )

 

分散程度度量:sd(x)IQR(x) mad(x)。均方误差(又称标准误差,standard deviationsd)是分散程度的标准度量方式。四分位距 IQR() 和绝对中位差 mad(x) 基本等价,更适合有离群点的情况。

# 为什么到某些目的地的距离比到其他目的地更多变?

not_cancelled %>%

 group_by(dest) %>%

     summarize(distance_sd = sd(distance)) %>%

     arrange(desc(distance_sd))

 

秩的度量:min(x)quantile(x, 0.25) max(x)分位数是中位数的扩展。例如,quantile(x, 0.25) 会找出 x 中按从小到大顺序大于前25% 而小于后 75% 的值:

# 每天最早和最晚的航班何时出发?

not_cancelled %>%

  group_by(year, month, day) %>%

  summarize(

  first = min(dep_time),

  last = max(dep_time)

 )

定位度量:first(x)nth(x, 2) last(x)这几个函数的作用与 x[1]x[2] x[length(x)] 相同,只是当定位不存在时(比如尝试从只有两个元素的分组中得到第三个元素),前者允许你设置一个默认值。例如,我们可以找出每天最早和最晚出发的航班:

not_cancelled %>%

   group_by(year, month, day) %>%

   summarize(

     first_dep = first(dep_time),

last_dep = last(dep_time)

  )

 

计数你已经见过 n(),它不需要任何参数,并返回当前分组的大小。如果想要计算出非

缺失值的数量,可以使用 sum(!is.na(x))。要想计算出唯一值的数量,可以使用 n_distinct(x)

# 哪个目的地具有最多的航空公司?

not_cancelled %>%

   group_by(dest) %>%

   summarize(carriers = n_distinct(carrier)) %>%

   arrange(desc(carriers))

 

dplyr 提供了一个简单的辅助函数,用于只需要计数的情况:

not_cancelled %>%

  count(dest)

 

可以选择提供一个加权变量。例如,你可以使用以下代码算出每架飞机飞行的总里程

数(实际上就是求和):

not_cancelled %>%

   count(tailnum, wt = distance)

 

逻辑值的计数和比例:sum(x > 10) mean(y == 0)

当与数值型函数一同使用时,TRUE 会转换为 1FALSE 会转换为 0。这使得 sum() 和mean()非常适用于逻辑值:sum(x) 可以找出 x TRUE 的数量,mean(x) 则可以找出比例。

# 多少架航班是在早上5点前出发的?(这通常表明前一天延误的航班数量)

not_cancelled %>%

  group_by(year, month, day) %>%

  summarize(n_early = sum(dep_time < 500))

 

# 延误超过1小时的航班比例是多少?

not_cancelled %>%

   group_by(year, month, day) %>%

   summarize(hour_perc = mean(arr_delay > 60))

 

6.5 按多个变量分组

daily <- group_by(flights, year, month, day)

(per_day <- summarize(daily, flights = n()))    #每天航班数量

 

(per_month <- summarize(per_day, flights = sum(flights)))  #每月航班数量

 

(per_year <- summarize(per_month, flights = sum(flights)))     #每年航班数量

 

6.6 取消分组

如果想要取消分组,并回到未分组的数据继续操作,那么可以使用 ungroup() 函数:

daily %>%

  ungroup() %>% # 不再按日期分组

  summarize(flights = n()) # 所有航班

 

7 分组新变量(和筛选器)

summarize() 函数结合起来使用是最有效的,分组也可以与 mutate() filter()函数结合,以完成非常便捷的操作。

找出每个分组中最差的成员:

flights_sml %>%

  group_by(year, month, day) %>%

  filter(rank(desc(arr_delay)) < 10)

 

找出大于某个阈值的所有分组:

popular_dests <- flights %>%

   group_by(dest) %>%

   filter(n() > 365)

popular_dests

对数据进行标准化以计算分组指标:

popular_dests %>%

  filter(arr_delay > 0) %>%

  mutate(prop_delay = arr_delay / sum(arr_delay)) %>%    #增加了列prop_delay

  select(year:day, dest, arr_delay, prop_delay)

 

posted @ 2021-11-19 13:51  zhang-X  阅读(251)  评论(0)    收藏  举报