生信小白菜之关于summarize函数的一切(part 2)

《R for Data Science》

常用的摘要函数

summarize()搭配使用

位置度量

# 前面用过mean() 求均值

# median() 求中位数
# 即50%的x大于它,同时50%的x小于它
# 举例
not_cancelled %>% 
  group_by(year,month,day) %>% 
  summarize(
    avg_delay1=mean(arr_delay), # 平均延误时间
    avg_delay2=mean(arr_delay[arr_delay>0]), # 平均正延误时间
    avg_delay3=median(arr_delay[arr_delay>0]) # # 正延误时间中位数
  )

# 有时候需要将聚合函数和逻辑筛选组合起来 (后面再讲)

分散程度度量

# 均方误差(又称标准误差,standard deviation,sd),衡量数据离散程度
# 四分位距IDR()和绝对中位差mad()基本等价,更适合有离群点的情况

# 为什么到某些目的地的距离比到其他目的地更多变?
not_cancelled %>% 
  group_by(dest) %>% # 按目的地分组
  summarise(distance_sd=sd(distance)) %>% 
  arrange(desc(distance_sd))

秩的度量

# 分位数是中位数的扩展
# 例如,quantile(x,0.25)会找出x中按从小到大顺序位于25%位置的数字
x<-c(1:10)
quantile(x,0.25) # 25% 3.25 
quantile(x,0.75) # 75% 7.75

# 最小值 min()

# 最大值 max()

# 每天最早和最晚的航班何时出发
not_cancelled %>% 
  group_by(year,month,day) %>% 
  summarize(
    first = min(dep_time),
    last = max(dep_time)
  )

定位度量

# 取第一个first(x),作用等同于 x[1]
# 取第二个nth(x,2),作用等同于 x[2] ## 当然也可以是任意数字/位置
# 取最后一个last(x),作用等同于 x[length(x)]

# 它们的优势是当定位不存在时
# 例如,从只有两个元素的分组中得到第三个元素
# 它们允许你设置一个默认值

# 找出每日最早、最晚出发的航班
not_cancelled %>% 
  group_by(year,month,day) %>% 
  summarise(
    first_dep=first(dep_time),
    last_dep=last(dep_time)
  )

# 这些函数对筛选操作进行了排秩方面的补充
# 筛选会返回所有变量,每个观测在单独一行中
not_cancelled %>% 
  group_by(year,month,day) %>% 
  mutate(r=min_rank(desc(dep_time))) %>% 
  filter(r %in% range(r)) 

计数

# n() 不需要任何函数,并返回当前分组的大小
# 如果想要计算出非缺失值的数量,可用sum(!is.na(x))

# 想要计算出唯一值的数量,可以使用n_distinct(x)

# 哪个目的地具有最多的航空公司
not_cancelled %>% 
  group_by(dest) %>% 
  summarise(
    carriers = n_distinct(carrier)
  ) %>% 
  arrange(desc(carriers))

# 除了n()之外,还有count()用于单纯计数
# count()用于统计一个或多个变量的唯一值
not_cancelled %>% 
  count(dest)
## df %>% count(a, b) 
## 大致等同于 
## df %>% group_by(a, b) %>% summarise(n = n()) 

# 还可以搭配一个加权变量
# count()提供 参数wt 来执行加权计数,将摘要从 n = n() 转换为 n = sum(wt)

# 例如计算出每架飞机飞行的总里程数(即求和)
not_cancelled %>% 
  count(tailnum,wt=distance) # 多了一列 n,即总和

## add_count 等同于 count()
## add_tally 等同于 tally()
## 但搭配 mutate() 而不是 summarise(),因此它们会添加一列新的分组计数

逻辑值的计数和比例

# 当和数值型函数一同使用时,TRUE会转换为1,FALSE会转换为0
# 那么就可以利用逻辑值进行计数
# sum(x) 可以计算出x中TRUE的数量
# mean(x) 可以得出x中TRUE的比例

# 例如
x<-1:20
sum(x>10) # 10
mean(x>10) # 0.5

# 多少架航班是在早上5点前出发的?
not_cancelled %>% 
  group_by(year,month,day) %>% 
  summarise(
    n_early = sum(dep_time<500)
  )

# 延误超过1h的航班比例是多少?
not_cancelled %>% 
  group_by(year,month,day) %>% 
  summarise(hour_perc=mean(arr_delay>60))

按多个变量分组

# 当使用多个变量进行分组时,每次的摘要统计会用掉一个分组变量
# 这样就可以轻松地对数据集进行循序渐进的分析
daily <- group_by(flights,year,month,day)
per_day <- summarise(daily,flights=n()) 
per_month <- summarise(per_day,flights=sum(flights))
per_year <- summarise(per_month,flights=sum(flights))

# 在循序渐进地进行摘要分析时,要注意:

# 使用求和和计数操作是没问题的
# 但是加权平均和方差操作容易出问题

# 因为对分组求和的结果再求和 == 对整体求和
# 但是分组中位数的中位数可不是整体的中位数

取消分组

# ungroup()函数取消分组
# 回到未分组的数据继续操作
daily %>% 
  ungroup() %>%          # 不再按日期分组
  summarise(flights=n()) # 所有航班数

练习题

# 1. 至少找出5种方法来确定一组航班的典型延误特征,思考以下场景;
# - 一架航班50%的时间会提前15分钟,50%的时间会延误15分钟
# - 一架航班总是会延误10分钟
# - 一架航班50%的时间会提前30分钟,50%的时间会延误30分钟
# - 一架航班99%的时间会准时,1%的时间会延误2小时
# 哪一种更重要,出发延误还是到达延误


# 找出另一种方法,要可以给出与not_cancelled %>% count(dest) 和 not_cancelled %>%  count(tailnum,wt=distance)同样的输出
not_cancelled %>% count(dest) # 标准一
not_cancelled %>%             # 仿写一
  group_by(dest) %>% 
  summarise(n=n())

not_cancelled %>%  count(tailnum,wt=distance) # 标准二
not_cancelled %>%                             # 仿写二
  group_by(tailnum) %>%       
  summarise(
    n=sum(distance))


# 对已取消航班的定义 (is.na(dep_delay))|(is.na(arr_delay)) 是否稍有欠佳?为什么?哪一列更重要?
not_cancelled <- flights %>%   # 原定义式,327346行
  filter(!is.na(dep_delay),!is.na(arr_delay))
no_airtime <- flights %>%      # 如果用air_time来筛选,也是327346行
  filter(!is.na(air_time)) 
# 从逻辑上可知没有出发就不会有到达,即dep_delay为NA则arr_delay一定为NA
# 如果有出发而没有抵达,说明飞机中途折返或者坠机
# 所以对于“取消航班”这个定义来说,是否出发更为重要


# 查看每天取消的航班数量,其中存在某种模式吗?已取消航班的比例与平均延误时间是否存在关系?
## 计数每天的航班数、取消的航班数和总延误时间
cancelled_perday <- flights %>% 
  group_by(year,month,day) %>% 
  summarise(
    cancelled_count=sum(is.na(air_time)), 
    all_count=n(),
    delay = arr_delay - dep_delay) %>% 
  filter(delay>0)
ggplot(cancelled_perday,aes(all_count,cancelled_count))+ 
  geom_point()

## 查看取消航班比例和平均延误时间
percent_averagedelay <- cancelled_perday %>% 
  summarise(
    cancelled_percent = cancelled_count/all_count,
    average_delay=mean(delay,na.rm=T)
  )
ggplot(percent_averagedelay,aes(average_delay,cancelled_percent))+
  geom_smooth()+
  geom_point()


# 哪个航空公司的延误情况最严重?
carriers_delay <- flights %>% 
  group_by(carrier) %>%
  summarise(
    n=n(),                                   # 计算每个航空公司的总航班
    delay=sum(arr_time-dep_time,na.rm = T),  # 计算每个航空公司的总延误时间
    average_delay=delay/n                    # 计算每个航空公司每一趟的平均延误时间
  ) %>% 
  arrange(desc(average_delay)) 

carriers_delay1 <- flights %>%               # 更简洁
  group_by(carrier) %>%
  summarise(                                 
    average_delay=mean(arr_time-dep_time,na.rm = T)  # 计算每个航空公司每一趟的平均延误时间
  ) %>% 
  arrange(desc(average_delay)) 

# 能否分清这是由于糟糕的机场设备,还是航空公司的问题?
flights %>%
  filter(!is.na(arr_delay)) %>%
  group_by(origin, dest, carrier) %>%  # 按每一条航线分类后,再分每一个航空公司
  summarise(
    arr_delay = sum(arr_delay),        # 计算每个航线内每个航空公司的总延误时间
    flights = n()                      # 计算每个航线内每个航空公司的飞行次数
  ) %>%
  group_by(origin, dest) %>%           # 计算每个航线内
  mutate(                              
    arr_delay_total = sum(arr_delay),  # 所有航班的总延误时间
    flights_total = sum(flights)       # 所有航班数
  ) %>%
  ungroup() %>%
  mutate(                              # 解除分组
    arr_delay_others = (arr_delay_total - arr_delay) /  # 所有航班的总延误时间-每个航线内每个航空公司的总延误时间
      (flights_total - flights),                        # 所有航班数-每个航线内每个航空公司的飞行次数
    arr_delay_mean = arr_delay / flights,               # 每个航线内每个航空公司的平均延误时间
    arr_delay_diff = arr_delay_mean - arr_delay_others  # 每个航线内每个航空公司的平均延误时间-该航线内其他航班的平均延误时间
  ) %>%
  filter(is.finite(arr_delay_diff)) %>%                 
  group_by(carrier) %>%
  summarise(arr_delay_diff = mean(arr_delay_diff)) %>%  # 再按航空公司汇总,求得每个航空公司的每条线路平均延误时间
  arrange(desc(arr_delay_diff))

分组新变量和筛选器

# 虽然group_by()与summarize()结合非常常用
# group_by()和mutate()、filter()也可以结合使用

# 找出每个分组中最多延误的
 flights_sml %>% 
  group_by(year,month,day) %>% 
  filter(rank(desc(arr_delay))<10)

# 找出大于某个阈值的所有分组
popular_dest <- flights %>% 
  group_by(dest) %>% 
  filter(n()>365)

# 对数据进行标准化以计算分组指标
popular_dest %>% 
  filter(arr_delay>0) %>% 
  mutate(prop_delay = arr_delay/sum(arr_delay)) %>% 
  select(year:day,dest,arr_delay,prop_delay)

## 分组筛选器的作用相当于分组新变量加上未分组筛选器
## 这个用法适合快速、粗略处理数据,缺点是很难检查数据处理结果是否正确

练习题

# 哪一架飞机具有最差的准点记录
worse_flight <- flights %>% 
  group_by(tailnum) %>% 
  summarise(
    average_delay = abs(mean(arr_delay))
  ) %>% 
  arrange(desc(average_delay))

# 如果想避免航班延误,应该一天内哪个时间搭乘飞机
time_flight <- flights %>% 
  filter(arr_delay >0) %>% 
  group_by(hour) %>% 
  summarise(
    average_delay = mean(arr_delay,na.sm=T)
  ) %>% 
  arrange(average_delay)
  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值