背景介绍
为了分析自己的驾驶行为,最近斥巨资35元在PDD上买了2个OBD盒子。结合Car Scanner得到了CSV格式的数据。在此基础上,计划利用R进行分析。
参考资料
R语言教程 ,北京大学出品,适合快速上手。
R语言中变量命名规则与反引号的使用 ,阐述了R中变量名的自动转换问题。
将数据从CSV文件导入R
1
| data <- read.csv("2022-05-17+08-26-13.csv", header=TRUE, as.is=TRUE, check.names=FALSE)
|
程序中的选项header=TRUE
指明第一行作为变量名行, 选项as.is=TRUE
说明字符型列要原样读入而不是转换为因子(factor),check.names=FALSE
禁止变量名检查与自动转换。如果不禁用变量名检查,导入R的列名如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| > colnames(data) [1] "time" [2] "发动机转速..rpm." [3] "已耗燃油..L." [4] "已耗燃油.总计...L." [5] "平均速度..km.h." [6] "平均速度..GPS...km.h." [7] "气压..kPa." [8] "氧传感器1宽范围.电流.mA...mA." [9] "氧传感器1宽范围.等价比..." [10] "燃料价格...." [11] "燃料价格.总计....." [12] "燃油平均消耗.升.100公里...L.100km." [13] "燃油平均消耗.升.100公里..10.sec..L.100km." [14] "燃油平均消耗.升.100公里..总计...L.100km." [15] "燃油瞬时消耗.升.100公里...L.100km." [16] "省油器.基于燃油系统状态和油门位置...." [17] "瞬时发动机功率.根据燃油消耗...kW." [18] "瞬时燃油消耗.升.小时...L.h." [19] "节气门位置...." [20] "计算增压..bar." [21] "路程..km." [22] "路程.总计...km." [23] "车辆加速..g." [24] "车速..km.h." [25] "进气歧管绝对压力..kPa." [26] "进气温度...." [27] "速度..GPS...km.h." [28] "高度..GPS...m." [29] "Latitude" [30] "Longtitude" [31] "X"
|
禁用检查后,结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| > colnames(data) [1] "time" [2] "发动机转速 (rpm)" [3] "已耗燃油 (L)" [4] "已耗燃油(总计) (L)" [5] "平均速度 (km/h)" [6] "平均速度 (GPS) (km/h)" [7] "气压 (kPa)" [8] "氧传感器1宽范围 电流(mA) (mA)" [9] "氧传感器1宽范围 等价比 ()" [10] "燃料价格 (¥)" [11] "燃料价格(总计) (¥)" [12] "燃油平均消耗(升/100公里) (L/100km)" [13] "燃油平均消耗(升/100公里) 10 sec (L/100km)" [14] "燃油平均消耗(升/100公里)(总计) (L/100km)" [15] "燃油瞬时消耗(升/100公里) (L/100km)" [16] "省油器(基于燃油系统状态和油门位置) ()" [17] "瞬时发动机功率(根据燃油消耗) (kW)" [18] "瞬时燃油消耗(升/小时) (L/h)" [19] "节气门位置 (%)" [20] "计算增压 (bar)" [21] "路程 (km)" [22] "路程(总计) (km)" [23] "车辆加速 (g)" [24] "车速 (km/h)" [25] "进气歧管绝对压力 (kPa)" [26] "进气温度 (℃)" [27] "速度 (GPS) (km/h)" [28] "高度 (GPS) (m)" [29] "Latitude" [30] "Longtitude" [31] ""
|
禁用变量检查与转换后,可以不加考虑地通过列名调用指定列:
1 2 3 4 5 6 7 8 9 10
| > data$"发动机转速 (rpm)" [1] NA NA NA 911 910 NA NA 907 908 902 909 899 895 895 [15] 896 895 895 902 910 910 898 910 902 898 902 896 897 897 [29] 895 903 907 902 903 903 901 905 900 900 900 898 904 905 [43] 905 902 899 899 901 900 905 898 897 900 900 898 905 902 [57] 899 897 897 896 906 897 903 904 899 904 908 908 901 898 [71] 899 893 893 903 902 909 904 897 891 891 903 902 903 892 [85] 889 895 892 892 882 886 889 896 892 887 887 890 896 893 [99] 893 893 884 895 890 893 891 880 880 883 890 889 886 889 [113] 892 892 886 890 900 890 886 895 895 886 887 895 889 891
|
(数据为节选)
绘制折线图
字符串转时间
分析某一变量随时间变化趋势,首先尝试绘制折线图。这里有一个小小的问题:数据中的时间格式如下:
1 2 3 4
| > data$time [1] "08:26:19.571" "08:26:19.573" "08:26:19.575" "08:26:20.597" [5] "08:26:20.771" "08:26:20.933" "08:26:21.100" "08:26:21.266" [9] "08:26:21.424" "08:26:21.612" "08:26:21.769" "08:26:21.938"
|
这种格式的数据R不能直接使用,需要进行转换,即将字符串转换为R可以理解的时间。
显而易见,原始数据中的时间格式为hms
格式,R提供了一个同名的第三方包:
如果没用用户权限,包就会安装在home下某一个目录内。
然后加载这个包:
进行类型转换:
缺失值处理
OBD通过采样读取数据流,受采样率限制,不可能在同一时间读取到全部参数,所以值缺失现象在样本数据中随处可见。为了绘制折线图,需要对缺失值进行适当处理。
发动机转速随时间变化折线图
1 2 3 4
| library(hms) rpm <- data.frame(x = data$time, y = data$"发动机转速 (rpm)") rpm <- rpm[!is.na(rpm$y),] plot(as_hms(rpm$x), rpm$y, type = "b")
|
然后就得到了一个比较简陋的发动机转速随时间变化折线图。由于数据采样比较频繁,不显示标点的”l”类型更合适。添加主标题,xy轴标题,得到的折线图好看了一些:
1
| plot(as_hms(rpm$x), rpm$y, type = "l", main = "远景x3 pro cvt 发动机转速随时间变化折线图", xlab = "时间", ylab = "发动机转速(rpm)")
|
最大值、最小值、平均值、分位数
1 2 3 4 5 6 7 8 9
| > max(data$"发动机转速 (rpm)", na.rm=TRUE) [1] 1837 > min(data$"发动机转速 (rpm)", na.rm=TRUE) [1] 724 > mean(data$"发动机转速 (rpm)", na.rm=TRUE) [1] 1199.271 > quantile(data$"燃油平均消耗(升/100公里) (L/100km)", na.rm=TRUE) 0% 25% 50% 75% 100% 10.43989 11.06329 13.97581 31.61916 57746.89340
|
summary提供了更快捷的数据摘要:
1 2 3 4
| > summary(data$"发动机转速 (rpm)") Min. 1st Qu. Median Mean 3rd Qu. Max. NA's 724 895 1251 1199 1460 1837 1002 >
|
异常值处理
将异常值标记为NA
在整体数据的summary中,发现 高度 (GPS) (m) 的最小值为零:
1 2 3 4 5 6 7 8
| 高度 (GPS) (m) Min. : 0.0 1st Qu.:144.4 Median :147.3 Mean :134.1 3rd Qu.:149.8 Max. :176.3 NA's :2690
|
结合实际,显然这些零值是错误的,应当视为缺失值一并处理:
1 2 3 4
| > data$"高度 (GPS) (m)"[data$"高度 (GPS) (m)"==0] <- NA > summary(data$"高度 (GPS) (m)") Min. 1st Qu. Median Mean 3rd Qu. Max. NA's 140.3 145.2 147.8 148.6 150.0 176.3 2780
|
剔除零值后数据变得更有意义了。
拓展阅读:如何理解R中因子(factor)的概念?,猴子的回答同时阐明了 因子 的概念。
library(hms)
rpm <- data.frame(x = data$time, y = data$”高度 (GPS) (m)”)
rpm <- rpm[!is.na(rpm$y),]
plot(as_hms(rpm$x), rpm$y, type = “l”, main = “高度随时间变化折线图”, xlab = “时间”, ylab = “高度”)
library(hms)
rpm <- data.frame(x = data$time, y = data$”燃油平均消耗(升/100公里) (L/100km)”)
rpm <- rpm[!is.na(rpm$y),]
rpm <- rpm[!is.na(quantile(rpm$y,probs=c(.3, .75),na.rm=TRUE)),]
plot(as_hms(rpm$x), rpm$y, type = “l”, main = “燃油平均消耗(升/100公里) (L/100km)”, xlab = “时间”, ylab = “燃油平均消耗(升/100公里) (L/100km)”)
y=log2(x)
x=2^y