0%

利用R分析OBD数据

背景介绍

为了分析自己的驾驶行为,最近斥巨资35元在PDD上买了2个OBD盒子。结合Car Scanner得到了CSV格式的数据。在此基础上,计划利用R进行分析。

参考资料

  1. R语言教程 ,北京大学出品,适合快速上手。

  2. R语言中变量命名规则与反引号的使用 ,阐述了R中变量名的自动转换问题。

将数据从CSV文件导入R

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的列名如下:

> 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"                                        

禁用检查后,结果如下:

> 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] ""  

禁用变量检查与转换后,可以不加考虑地通过列名调用指定列:

> 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

(数据为节选)

绘制折线图

字符串转时间

分析某一变量随时间变化趋势,首先尝试绘制折线图。这里有一个小小的问题:数据中的时间格式如下:

> 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提供了一个同名的第三方包:

install.packages("hms")

如果没用用户权限,包就会安装在home下某一个目录内。

然后加载这个包:

library(hms)

进行类型转换:

x <- as_hms(data$time)

缺失值处理

OBD通过采样读取数据流,受采样率限制,不可能在同一时间读取到全部参数,所以值缺失现象在样本数据中随处可见。为了绘制折线图,需要对缺失值进行适当处理。

发动机转速随时间变化折线图

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轴标题,得到的折线图好看了一些:

plot(as_hms(rpm$x), rpm$y, type = "l", main = "远景x3 pro cvt 发动机转速随时间变化折线图", xlab = "时间", ylab = "发动机转速(rpm)")

最大值、最小值、平均值、分位数

> 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提供了更快捷的数据摘要:

> summary(data$"发动机转速 (rpm)")
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
    724     895    1251    1199    1460    1837    1002 
> 

异常值处理

将异常值标记为NA

在整体数据的summary中,发现 高度 (GPS) (m) 的最小值为零:

高度 (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 

结合实际,显然这些零值是错误的,应当视为缺失值一并处理:

> 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