使用 timetable
预处理和探索时间戳数据
此示例说明如何使用 timetable
数据容器组织和预处理时间戳数据,从而基于传感器数据分析自行车交通模式。这些数据来自马萨诸塞州剑桥市百老汇大街上的传感器。剑桥市允许公众访问位于 Cambridge Open Data 站点上的完整数据。
以下示例演示如何执行各种数据清洗、整理和预处理任务,例如删除缺失值以及将时间戳数据与不同的时间步同步。此外,还将突出显示数据探索,包括使用 timetable
数据容器进行可视化和分组计算,以便:
探查每日自行车流量
将自行车流量与当地天气状况进行比较
分析一周中的不同天和一天中的不同时间的自行车流量
将自行车流量数据导入时间表
从逗号分隔的文本文件中导入自行车流量数据样本。readtable
函数在表中返回这些数据。使用 head
函数来显示前八行。
bikeTbl = readtable('BicycleCounts.csv');
head(bikeTbl)
Timestamp Day Total Westbound Eastbound ___________________ _____________ _____ _________ _________ 2015-06-24 00:00:00 {'Wednesday'} 13 9 4 2015-06-24 01:00:00 {'Wednesday'} 3 3 0 2015-06-24 02:00:00 {'Wednesday'} 1 1 0 2015-06-24 03:00:00 {'Wednesday'} 1 1 0 2015-06-24 04:00:00 {'Wednesday'} 1 1 0 2015-06-24 05:00:00 {'Wednesday'} 7 3 4 2015-06-24 06:00:00 {'Wednesday'} 36 6 30 2015-06-24 07:00:00 {'Wednesday'} 141 13 128
这些数据具有时间戳,因此可以使用时间表方便地存储和分析这些数据。时间表与表类似,但包含与数据行关联的时间戳。时间戳(即行时间)由 datetime
或 duration
值表示。datetime
和 duration
是建议的数据类型,分别用于表示时间点或已用时间。
使用 table2timetable
函数将 bikeTbl
转换为时间表。由于 readtable
返回的是表,因此必须使用转换函数。table2timetable
可将表中的第一个 datetime
或 duration
变量转换为时间表的行时间。行时间是用来标记行的元数据。但是,当您显示时间表时,行时间和时间表变量以相似方式显示。请注意,该表有五个变量,而时间表只有四个变量。
bikeData = table2timetable(bikeTbl); head(bikeData)
Timestamp Day Total Westbound Eastbound ___________________ _____________ _____ _________ _________ 2015-06-24 00:00:00 {'Wednesday'} 13 9 4 2015-06-24 01:00:00 {'Wednesday'} 3 3 0 2015-06-24 02:00:00 {'Wednesday'} 1 1 0 2015-06-24 03:00:00 {'Wednesday'} 1 1 0 2015-06-24 04:00:00 {'Wednesday'} 1 1 0 2015-06-24 05:00:00 {'Wednesday'} 7 3 4 2015-06-24 06:00:00 {'Wednesday'} 36 6 30 2015-06-24 07:00:00 {'Wednesday'} 141 13 128
whos bikeTbl bikeData
Name Size Bytes Class Attributes bikeData 9387x4 1562713 timetable bikeTbl 9387x5 1638055 table
访问时间和数据
将 Day
变量转换为分类类型。分类数据类型设计用于由有限的离散值集组成的数据,例如一周中的星期几的名称。列出类别,以便它们按星期几的顺序显示。使用圆点下标按名称访问变量。
bikeData.Day = categorical(bikeData.Day,{'Sunday','Monday','Tuesday',... 'Wednesday','Thursday','Friday','Saturday'});
在时间表中,时间与数据变量分开处理。访问时间表的 Properties
以显示行时间是时间表的第一个维度,变量是第二个维度。DimensionNames
属性显示两个维度的名称,而 VariableNames
属性显示沿第二个维度的变量的名称。
bikeData.Properties
ans = TimetableProperties with properties: Description: '' UserData: [] DimensionNames: {'Timestamp' 'Variables'} VariableNames: {'Day' 'Total' 'Westbound' 'Eastbound'} VariableTypes: ["categorical" "double" "double" "double"] VariableDescriptions: {} VariableUnits: {} VariableContinuity: [] RowTimes: [9387x1 datetime] StartTime: 2015-06-24 00:00:00 SampleRate: NaN TimeStep: NaN Events: [] CustomProperties: No custom properties are set. Use addprop and rmprop to modify CustomProperties.
默认情况下,在将表转换为时间表时,table2timetable
将 Timestamp
分配为第一个维度名称,因为这是原始表中的变量名称。可以通过 Properties
更改维度的名称和其他时间表元数据。
将维度的名称更改为 Time
和 Data
。
bikeData.Properties.DimensionNames = {'Time' 'Data'}; bikeData.Properties
ans = TimetableProperties with properties: Description: '' UserData: [] DimensionNames: {'Time' 'Data'} VariableNames: {'Day' 'Total' 'Westbound' 'Eastbound'} VariableTypes: ["categorical" "double" "double" "double"] VariableDescriptions: {} VariableUnits: {} VariableContinuity: [] RowTimes: [9387x1 datetime] StartTime: 2015-06-24 00:00:00 SampleRate: NaN TimeStep: NaN Events: [] CustomProperties: No custom properties are set. Use addprop and rmprop to modify CustomProperties.
显示时间表的前八行。
head(bikeData)
Time Day Total Westbound Eastbound ___________________ _________ _____ _________ _________ 2015-06-24 00:00:00 Wednesday 13 9 4 2015-06-24 01:00:00 Wednesday 3 3 0 2015-06-24 02:00:00 Wednesday 1 1 0 2015-06-24 03:00:00 Wednesday 1 1 0 2015-06-24 04:00:00 Wednesday 1 1 0 2015-06-24 05:00:00 Wednesday 7 3 4 2015-06-24 06:00:00 Wednesday 36 6 30 2015-06-24 07:00:00 Wednesday 141 13 128
确定最晚行时间与最早行时间之间经过的天数。在一次引用一个变量时,可以通过圆点表示法访问变量。
elapsedTime = max(bikeData.Time) - min(bikeData.Time)
elapsedTime = duration
9383:30:00
elapsedTime.Format = 'd'
elapsedTime = duration
390.98 days
要确定某给定天的典型自行车计数,请计算总自行车数的均值、向西行进和向东行进的自行车数。
通过使用花括号对 bikeData
的内容进行索引,将数值数据以矩阵的形式返回。显示前八行。要访问多个变量,须使用标准表下标。
counts = bikeData{:,2:end}; counts(1:8,:)
ans = 8×3
13 9 4
3 3 0
1 1 0
1 1 0
1 1 0
7 3 4
36 6 30
141 13 128
由于均值仅适合数值数据,因此可以使用 vartype
函数选择数值变量。vartype
可能比手动对表或时间表进行索引以选择变量更方便。计算均值并忽略 NaN
值。
counts = bikeData{:,vartype('numeric')}; mean(counts,'omitnan')
ans = 1×3
49.8860 24.2002 25.6857
按日期和一天中的时间选择数据
为了确定有多少人在假期中骑自行车,将检查在 7 月 4 日这一假日中的数据。按行时间对 2015 年 7 月 4 日的时间表建立索引。当对行时间建立索引时,必须与时间完全匹配。可以将时间索引指定为 datetime
或 duration
值,或者指定为可以转换为日期时间的字符向量。可以将多个时间指定为数组。
使用特定的日期时间对 bikeData
进行索引以提取 2015 年 7 月 4 日的数据。如果仅指定日期,则时间假定为午夜,即 00:00:00。
bikeData('2015-07-04',:)
ans=1×4 timetable
Time Day Total Westbound Eastbound
___________________ ________ _____ _________ _________
2015-07-04 00:00:00 Saturday 8 7 1
d = {'2015-07-04 08:00:00','2015-07-04 09:00:00'}; bikeData(d,:)
ans=2×4 timetable
Time Day Total Westbound Eastbound
___________________ ________ _____ _________ _________
2015-07-04 08:00:00 Saturday 15 3 12
2015-07-04 09:00:00 Saturday 21 4 17
如果使用此策略提取一整天的数据,则是非常繁琐的工作。您也可以指定时间范围,而不对特定的时间建立索引。要创建时间范围下标来作为帮助,请使用 timerange
函数。
使用 2015 年 7 月 4 日一整天作为时间范围来对时间表建立下标。指定起始时间为 7 月 4 日午夜,结束时间为 7 月 5 日午夜。默认情况下,timerange
涵盖了从起始时间直至结束时间(但不包含结束时间)的所有时间。绘制这一天内各时间段的自行车计数。
tr = timerange('2015-07-04','2015-07-05'); jul4 = bikeData(tr,'Total'); head(jul4)
Time Total ___________________ _____ 2015-07-04 00:00:00 8 2015-07-04 01:00:00 13 2015-07-04 02:00:00 4 2015-07-04 03:00:00 1 2015-07-04 04:00:00 0 2015-07-04 05:00:00 1 2015-07-04 06:00:00 8 2015-07-04 07:00:00 16
bar(jul4.Time,jul4.Total) ylabel('Bicycle Counts') title('Bicycle Counts on July 4, 2015')
从绘图中可看出,整天的自行车流量较高,下午的流量比较平稳。由于当天非工作日,许多公司未上班,因此该绘图并未反映典型的上下班时间内的交通情况。峰值出现在夜晚较晚时间可能归因于在天黑后进行的烟花燃放庆祝活动。要更准确地确定这些趋势,应将当天的数据与典型一天中的数据进行比较。
将 7 月 4 日的数据与 7 月中其他日期的数据进行比较。
jul = bikeData(timerange('2015-07-01','2015-08-01'),:); plot(jul.Time,jul.Total) hold on plot(jul4.Time,jul4.Total) ylabel('Total Count') title('Bicycle Counts in July') hold off legend('Bicycle Count','July 4 Bicycle Count')
该绘图显示的差异可以归因于工作日与周末之间的流量变化。7 月 4 日和 5 日的流量模式与周末的流量模式一致。7 月 5 日是周一,但通常作为假日进行观察。通过进一步的预处理和分析,可更准确地确定这些趋势。
使用 timetable
预处理时间和数据
时间戳数据集通常是杂乱的,可能包含异常情况或错误。时间表非常适合解决异常情况和错误。
时间表的行时间无需采用任何特定顺序。它可以包含未按行时间排序的行。时间表也可以包含多个具有相同行时间的行,即使这些行具有不同的数据值也是如此。即使行时间已排序并且是唯一的,也会因不同大小的时间步而异。时间表甚至可以包含 NaT
或 NaN
值以指示缺失的行时间。
timetable
数据类型提供了很多种不同的方式来解决时间缺失、重复或不均匀时间问题。您也可以对数据重采样或聚合数据以创建一个规则时间表。当时间表为规则时间表时,其行时间已排序并且是唯一的,并且行时间之间具有均匀或等间距的时间步。
要查找缺失的行时间,请使用
ismissing
。要删除缺失的时间和数据,请使用
rmmissing
。要按行时间对时间表进行排序,请使用
sortrows
。要使时间表具有唯一和已排序的行时间,请使用
unique
和retime
。要创建规则时间表,请指定一个均匀间隔时间向量并使用
retime
。
按时间顺序排序
确定该时间表是否已排序。如果时间表的行时间按升序列出,则说明它已进行了排序。
issorted(bikeData)
ans = logical
0
对时间表排序。sortrows
函数按照行的行时间(从最早时间到最晚时间)对行进行排序。如果存在具有重复行时间的行,则 sortrows
会将所有重复项复制到输出。
bikeData = sortrows(bikeData); issorted(bikeData)
ans = logical
1
确定并删除缺失的时间和数据
时间表可以在其变量或行时间中包含数据缺失指示符。例如,可以将缺失的数值指示为 NaN
,将缺失的日期时间值指示为 NaT
。可以分别使用 standardizeMissing
、ismissing
、rmmissing
和 fillmissing
函数来分配、查找、删除和填充缺失值。
查找和统计时间表变量中的缺失值。在下面的示例中,缺失值指示未收集任何数据的情况。
missData = ismissing(bikeData); sum(missData)
ans = 1×4
1 3 3 3
来自 ismissing
的输出是一个大小与表相同的 logical
矩阵,将缺失的数据值标识为 true。显示具有缺失数据指示符的任何行。
idx = any(missData,2); bikeData(idx,:)
ans=3×4 timetable
Time Day Total Westbound Eastbound
___________________ ___________ _____ _________ _________
2015-08-03 00:00:00 Monday NaN NaN NaN
2015-08-03 01:00:00 Monday NaN NaN NaN
NaT <undefined> NaN NaN NaN
ismissing(bikeData)
仅在时间表变量中查找缺失的数据,而并不查找缺失的时间。要查找缺失的行时间,请对行时间调用 ismissing
。
missTimes = ismissing(bikeData.Time); bikeData(missTimes,:)
ans=2×4 timetable
Time Day Total Westbound Eastbound
____ ___________ _____ _________ _________
NaT <undefined> NaN NaN NaN
NaT Friday 6 3 3
在本示例中,缺失的时间或数据值指示测量有误,可以将这些数据排除。使用 rmmissing
删除包含缺失数据值和缺失行时间的表行。
bikeData = rmmissing(bikeData); sum(ismissing(bikeData))
ans = 1×4
0 0 0 0
sum(ismissing(bikeData.Time))
ans = 0
删除重复的时间和数据
确定是否存在重复的时间和/或重复的数据行。您可能需要排除多余的重复项,因为这些项也会被视为测量错误。通过找出排序时间的差异完全为零的位置来确定重复的时间。
idx = diff(bikeData.Time) == 0; dup = bikeData.Time(idx)
dup = 3x1 datetime
2015-08-21 00:00:00
2015-11-19 23:00:00
2015-11-19 23:00:00
三个时间是重复的,并且 2015 年 11 月 19 日重复两次。检查与重复时间关联的数据。
bikeData(dup(1),:)
ans=2×4 timetable
Time Day Total Westbound Eastbound
___________________ ______ _____ _________ _________
2015-08-21 00:00:00 Friday 14 9 5
2015-08-21 00:00:00 Friday 11 7 4
bikeData(dup(2),:)
ans=3×4 timetable
Time Day Total Westbound Eastbound
___________________ ________ _____ _________ _________
2015-11-19 23:00:00 Thursday 17 15 2
2015-11-19 23:00:00 Thursday 17 15 2
2015-11-19 23:00:00 Thursday 17 15 2
第一项有重复时间,但是没有重复数据,其他项则完全重复。时间表的不同行如果包含相同的行时间与数据值,则被视为重复。可以使用 unique
删除时间表中的重复行。unique
函数还会按照行的行时间对行进行排序。
bikeData = unique(bikeData);
具有重复时间但没有重复数据的行需要提供某些解释。检查围绕这些时间的数据。
d = dup(1) + hours(-2:2); bikeData(d,:)
ans=5×4 timetable
Time Day Total Westbound Eastbound
___________________ ________ _____ _________ _________
2015-08-20 22:00:00 Thursday 40 30 10
2015-08-20 23:00:00 Thursday 25 18 7
2015-08-21 00:00:00 Friday 11 7 4
2015-08-21 00:00:00 Friday 14 9 5
2015-08-21 02:00:00 Friday 6 5 1
在本例中,重复的时间可能有误,因为其数据和前后的时间都是连贯的。尽管它看起来应该是 01:00:00,但不能确定它真正的时间。可以累加数据来说明两个时间点的数据。
sum(bikeData{dup(1),2:end})
ans = 1×3
25 16 9
这仅仅是可以手动执行的一种情况。但是,如果有很多行,则可以使用 retime
函数来执行此计算。使用 sum
函数累加唯一时间对应的数据以计算总和。总和适合于数值数据,但不适合于时间表中的分类数据。使用 vartype
确定数值变量。
vt = vartype('numeric'); t = unique(bikeData.Time); numData = retime(bikeData(:,vt),t,'sum'); head(numData)
Time Total Westbound Eastbound ___________________ _____ _________ _________ 2015-06-24 00:00:00 13 9 4 2015-06-24 01:00:00 3 3 0 2015-06-24 02:00:00 1 1 0 2015-06-24 03:00:00 1 1 0 2015-06-24 04:00:00 1 1 0 2015-06-24 05:00:00 7 3 4 2015-06-24 06:00:00 36 6 30 2015-06-24 07:00:00 141 13 128
不能对分类数据计算总和,但由于一个标签代表一整天,因此取每一天的第一个值。可以使用相同的时间向量再次执行 retime
操作,并将时间表串联到一起。
vc = vartype('categorical'); catData = retime(bikeData(:,vc),t,'firstvalue'); bikeData = [catData,numData]; bikeData(d,:)
ans=4×4 timetable
Time Day Total Westbound Eastbound
___________________ ________ _____ _________ _________
2015-08-20 22:00:00 Thursday 40 30 10
2015-08-20 23:00:00 Thursday 25 18 7
2015-08-21 00:00:00 Friday 25 16 9
2015-08-21 02:00:00 Friday 6 5 1
检查时间间隔的均匀性
数据似乎具有相同的时间步长,即一小时。要确定是否时间表中的所有行时间都是这种情况,请使用 isregular
函数。对于已排序、间隔等间距的时间(单调递增),并且没有重复或缺失的时间(NaT
或 NaN
),isregular
函数返回 true
。
isregular(bikeData)
ans = logical
0
输出 0
或 false
表示时间表中的时间不是间隔均匀的。更详细地探索时间间隔。
dt = diff(bikeData.Time); [min(dt); max(dt)]
ans = 2x1 duration
00:30:00
03:00:00
要将时间表放到均匀时间间隔中,请使用 retime
或 synchronize
并指定相关的时间间隔。
确定每天自行车数量
使用 retime
函数确定每天的自行车计数。使用 sum
方法累加每天的计数数据。此操作适合于数值数据,但不适合于时间表中的分类数据。使用 vartype
按数据类型标识变量。
dayCountNum = retime(bikeData(:,vt),'daily','sum'); head(dayCountNum)
Time Total Westbound Eastbound ___________________ _____ _________ _________ 2015-06-24 00:00:00 2141 1141 1000 2015-06-25 00:00:00 2106 1123 983 2015-06-26 00:00:00 1748 970 778 2015-06-27 00:00:00 695 346 349 2015-06-28 00:00:00 153 83 70 2015-06-29 00:00:00 1841 978 863 2015-06-30 00:00:00 2170 1145 1025 2015-07-01 00:00:00 997 544 453
如上所述,可以再次执行 retime
操作,以使用合适方法表示分类数据并将时间表串联到一起。
dayCountCat = retime(bikeData(:,vc),'daily','firstvalue'); dayCount = [dayCountCat,dayCountNum]; head(dayCount)
Time Day Total Westbound Eastbound ___________________ _________ _____ _________ _________ 2015-06-24 00:00:00 Wednesday 2141 1141 1000 2015-06-25 00:00:00 Thursday 2106 1123 983 2015-06-26 00:00:00 Friday 1748 970 778 2015-06-27 00:00:00 Saturday 695 346 349 2015-06-28 00:00:00 Sunday 153 83 70 2015-06-29 00:00:00 Monday 1841 978 863 2015-06-30 00:00:00 Tuesday 2170 1145 1025 2015-07-01 00:00:00 Wednesday 997 544 453
同步自行车计数和天气数据
通过使用天气数据比较自行车计数,来确定天气对骑自行车行为的影响。加载天气数据时间表,其中包括马萨诸塞州波士顿市的历史天气数据,包括风暴活动。
load BostonWeatherData
head(weatherData)
Time TemperatureF Humidity Events ___________ ____________ ________ ____________ 01-Jul-2015 72 78 Thunderstorm 02-Jul-2015 72 60 None 03-Jul-2015 70 56 None 04-Jul-2015 67 75 None 05-Jul-2015 72 67 None 06-Jul-2015 74 69 None 07-Jul-2015 75 77 Rain 08-Jul-2015 79 68 Rain
要汇总时间表中的时间和变量,请使用 summary
函数。
summary(weatherData)
weatherData: 383x3 timetable Row Times: Time: datetime Variables: TemperatureF: double Humidity: double Events: categorical (7 categories) Statistics for applicable variables and row times: NumMissing Min Median Max Mean Std Time 0 01-Jul-2015 08-Jan-2016 17-Jul-2016 08-Jan-2016 2656:57:49 TemperatureF 0 2 55 85 55.2950 16.3505 Humidity 0 29 64 97 65.2193 14.0507 Events 0
使用 synchronize
将自行车数据和天气数据合并到一个公共时间向量。可以使用 synchronize
函数参考页上记录的任一方法来重采样或聚合时间表数据。
将两个时间表中的数据同步到一个公共时间向量,即基于两个时间表各自的日时间向量的交集来构造。
data = synchronize(dayCount,weatherData,'intersection');
head(data)
Time Day Total Westbound Eastbound TemperatureF Humidity Events ___________________ _________ _____ _________ _________ ____________ ________ ____________ 2015-07-01 00:00:00 Wednesday 997 544 453 72 78 Thunderstorm 2015-07-02 00:00:00 Thursday 1943 1033 910 72 60 None 2015-07-03 00:00:00 Friday 870 454 416 70 56 None 2015-07-04 00:00:00 Saturday 669 328 341 67 75 None 2015-07-05 00:00:00 Sunday 702 407 295 72 67 None 2015-07-06 00:00:00 Monday 1900 1029 871 74 69 None 2015-07-07 00:00:00 Tuesday 2106 1140 966 75 77 Rain 2015-07-08 00:00:00 Wednesday 1855 984 871 79 68 Rain
在单独的 y 轴上比较自行车交通计数和室外温度以确定趋势。删除数据中的周末以进行可视化。
idx = ~isweekend(data.Time); weekdayData = data(idx,{'TemperatureF','Total'}); figure yyaxis left plot(weekdayData.Time, weekdayData.Total) ylabel('Bicycle Count') yyaxis right plot(weekdayData.Time,weekdayData.TemperatureF) ylabel('Temperature (\circ F)') title('Bicycle Counts and Temperature Over Time') xlim([min(data.Time) max(data.Time)])
绘图显示,交通和天气数据可能遵循相似的趋势。放大绘图。
xlim([datetime('2015-11-01'),datetime('2016-05-01')])
趋势是类似的,指示天气越冷,骑自行车的人越少。
按星期几和一天中的时间进行分析
基于不同的时间间隔检查数据,例如星期几和一天中的时间。使用 varfun
确定每天的总计数,以对变量执行分组计算。使用函数句柄指定 sum
函数,使用名称-值对组指定分组变量和首选输出类型。
byDay = varfun(@sum,bikeData,'GroupingVariables','Day',... 'OutputFormat','table')
byDay=7×5 table
Day GroupCount sum_Total sum_Westbound sum_Eastbound
_________ __________ _________ _____________ _____________
Sunday 1344 25315 12471 12844
Monday 1343 79991 39219 40772
Tuesday 1320 81480 39695 41785
Wednesday 1344 86853 41726 45127
Thursday 1344 87516 42682 44834
Friday 1342 76643 36926 39717
Saturday 1343 30292 14343 15949
figure bar(byDay{:,{'sum_Westbound','sum_Eastbound'}}) legend({'Westbound','Eastbound'},'Location','eastoutside') xticklabels({'Sun','Mon','Tue','Wed','Thu','Fri','Sat'}) title('Bicycle Count by Day of Week')
条形图指示,交通在工作日更为拥堵。此外,向东行进和向西行进的流量数据存在差异。这可能指示,人们进入和离开城市时,倾向于采用不同的路线。另外一种可能性是一些人在某一天进入城市,在另一天离开城市。
确定一天中的小时并使用 varfun
按组计算。
bikeData.HrOfDay = hour(bikeData.Time); byHr = varfun(@mean,bikeData(:,{'Westbound','Eastbound','HrOfDay'}),... 'GroupingVariables','HrOfDay','OutputFormat','table'); head(byHr)
HrOfDay GroupCount mean_Westbound mean_Eastbound _______ __________ ______________ ______________ 0 389 5.4396 1.7686 1 389 2.7712 0.87147 2 391 1.8696 0.58312 3 391 0.7468 0.289 4 391 0.52685 1.0026 5 391 0.70588 4.7494 6 391 3.1228 22.097 7 391 9.1176 63.54
bar(byHr{:,{'mean_Westbound','mean_Eastbound'}}) legend('Westbound','Eastbound','Location','eastoutside') xlabel('Hour of Day') ylabel('Bicycle Count') title('Mean Bicycle Count by Hour of Day')
在上午约 9:00 和下午约 5:00 是流量高峰期。此外,向东行进和向西行进的趋势是明显不同的。通常情况下,向西行进的目标是围绕剑桥区的居住区和大学。向东行进的目标是波士顿。
在一天中的晚些时候,相对于向东方向,向西方向的交通更为拥堵。这可能指示,由于餐馆位于该区域中,这可能是大学学生活动和交通导致。按星期几和一天中小时确定趋势。
byHrDay = varfun(@sum,bikeData,'GroupingVariables',{'HrOfDay','Day'},... 'OutputFormat','table'); head(byHrDay)
HrOfDay Day GroupCount sum_Total sum_Westbound sum_Eastbound _______ _________ __________ _________ _____________ _____________ 0 Sunday 56 473 345 128 0 Monday 55 202 145 57 0 Tuesday 55 297 213 84 0 Wednesday 56 374 286 88 0 Thursday 56 436 324 112 0 Friday 55 442 348 94 0 Saturday 56 580 455 125 1 Sunday 56 333 259 74
若要安排时间表以便将星期几作为变量,可使用 unstack
函数。
hrAndDayWeek = unstack(byHrDay(:,{'HrOfDay','Day','sum_Total'}),'sum_Total','Day'); head(hrAndDayWeek)
HrOfDay Sunday Monday Tuesday Wednesday Thursday Friday Saturday _______ ______ ______ _______ _________ ________ ______ ________ 0 473 202 297 374 436 442 580 1 333 81 147 168 173 183 332 2 198 77 68 93 128 141 254 3 86 41 43 44 50 61 80 4 51 81 117 101 108 80 60 5 105 353 407 419 381 340 128 6 275 1750 1867 2066 1927 1625 351 7 553 5355 5515 5818 5731 4733 704
ribbon(hrAndDayWeek.HrOfDay,hrAndDayWeek{:,2:end}) ylim([0 24]) xlim([0 8]) xticks(1:7) xticklabels({'Sun','Mon','Tue','Wed','Thu','Fri','Sat'}) ylabel('Hour') title('Bicycle Count by Hour and Day of Week')
从周一到周五的正常工作日也有类似的趋势,在上下班高峰时段达到峰值,夜间交通逐渐减少。周五的交通拥堵情况较少,尽管这一天的总体趋势与其他工作日类似。周六与周日的情况大同小异,无高峰时段峰值,日间晚些时候交通流量有所增加。从周一到周五深夜时段的趋势类似,周五深夜交通流量较少。
分析高峰时段中的交通
要确定一天中的时间的总体趋势,请按高峰时段时间划分数据。使用 discretize
函数时,可以使用一天中的不同时间或不同时间单位。例如,按 AM
、AMRush
、Day
、PMRush
、PM
将数据划分为组。然后,使用 varfun
按组计算均值。
bikeData.HrLabel = discretize(bikeData.HrOfDay,[0,6,10,15,19,24],'categorical',... {'AM','RushAM','Day','RushPM','PM'}); byHrBin = varfun(@mean,bikeData(:,{'Total','HrLabel'}),'GroupingVariables','HrLabel',... 'OutputFormat','table')
byHrBin=5×3 table
HrLabel GroupCount mean_Total
_______ __________ __________
AM 2342 3.5508
RushAM 1564 94.893
Day 1955 45.612
RushPM 1564 98.066
PM 1955 35.198
bar(byHrBin.mean_Total)
cats = categories(byHrBin.HrLabel);
xticklabels(cats)
title('Mean Bicycle Count During Rush Hours')
通常情况下,在此区域中早晚高峰时段的交通量是一天中其他时间的交通量的两倍。在此区域中的清早的交通量很少,但在傍晚和晚间的交通量仍较大,相当于一天中除早晚高峰时段外的交通量。
另请参阅
timetable
| table2timetable
| head
| summary
| varfun
| timerange
| sortrows
| rmmissing
| retime
| datetime
| unstack