5.4 缺失值
处理异常值有2种方法:
1.将带有可疑值的行全部丢弃
diamonds2 <- diamonds %>% filter(between(y, 3, 20))
我们不建议使用这种方式,因为一个无效测量不代表所有测量都是无效的。此外,如果数据质量不高,若对每个变量都采取这种做法,那么你最后可能会发现数据已经所剩无几!
2. 缺失值代替
最简单的做法就是使用mutate()
函数创建一个新变量来代替原来的变量。你可以使用ifelse()
函数将异常值替换为 NA:
diamonds2 <- diamonds %>% mutate(y = ifelse(y < 3 | y > 20, NA, y))
上面ifelse()
函数含义为:如果y小于3或y大于20,则y=NA,反之,y还是为原来值。
注意:和 R 一样,ggplot2也遵循不能无视缺失值的原则。因为无法明确地绘制出缺失值,所以ggplot2 在绘图时会忽略缺失值,但会提出警告以通知缺失值被丢弃了:
ggplot(data = diamonds2, mapping = aes(x = x, y = y)) + geom_point() #> Warning: Removed 9 rows containing missing values #> (geom_point).
要想不显示这条警告,可以在geom_point()
中设置na.rm = TRUE
。
比较有无缺失值的区别
有时你会想弄清楚造成有缺失值的观测和没有缺失值的观测间的区别的原因。例如,在nycflights13::flights
中,dep_time 变量中的缺失值表示航班取消了。因此,你应该比较一下已取消航班和未取消航班的计划出发时间。可以使用 is.na()
函数创建一个新变量来完成这个操作:
nycflights13::flights %>% mutate( cancelled = is.na(dep_time), sched_hour = sched_dep_time %/% 100, sched_min = sched_dep_time %% 100, sched_dep_time = sched_hour + sched_min / 60 ) %>% ggplot(mapping = aes(sched_dep_time)) + geom_freqpoly( mapping = aes(color = cancelled), binwidth = 1/4 )
5.4 习题解答
该节的作业习题较少,就直接在内容后面附上了。
问题一
直方图如何处理缺失值?条形图如何处理缺失值?为什么会有这种区别?
解答
- 直方图:当计算每个箱中的观察数时,丢失的值被删除。请参阅警告信息。在直方图中x需要是数值型的,
stat_bin()
按范围将观察结果分组到各个箱中。由于NA观测值的数值是未知的,它们不能被放置在特定的容器中,因此被丢弃。
diamonds2 <- diamonds %>% mutate(y = ifelse(y < 3 | y > 20, NA, y)) ggplot(diamonds2, aes(x = y)) + geom_histogram() #> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`. #> Warning: Removed 9 rows containing non-finite values (stat_bin).
- 条形图:在
geom_bar()
函数中NA被视为单独一类的数据,此函数要求x是一个离散的(分类的)变量,缺失的值类似于另一个类别。
diamonds %>% mutate(cut = if_else(runif(n()) < 0.1, NA_character_, as.character(cut))) %>% ggplot() + geom_bar(mapping = aes(x = cut))
问题二
na.rm = TRUE
在 mean()
和sum()
函数中的作用是什么?
解答
该命令在计算平均值和总和之前从原数据中删除NA值。
mean(c(0, 1, 2, NA), na.rm = TRUE) #> [1] 1 sum(c(0, 1, 2, NA), na.rm = TRUE) #> [1] 3