Предварительная обработка и Исследование Данных С меткой времени Используя расписание
Этот пример показывает, как анализировать велосипедные шаблоны трафика от данных датчика с помощью контейнера данных timetable
, чтобы организовать и предварительно обработать данные, к которым добавляют метку времени. Данные прибывают из датчиков на улице Broadway в Кембридже, MA. Город Кембриджа предоставляет открытый доступ полному набору данных в Кембридже Открытый сайт Данных.
Этот пример показывает, как выполнить разнообразие очистки данных, порчи и предварительной обработки задач, таких как удаление отсутствующих значений и синхронизация данных с меткой времени с различными тактами. Кроме того, исследование данных подсвечено включая визуализацию и сгруппированные вычисления с помощью контейнера данных timetable
для:
Исследуйте ежедневный велосипедный трафик
Сравните велосипедный трафик с локальными погодными условиями
Анализируйте велосипедный трафик в различные дни недели и времени суток
Импортируйте выборку велосипедных данных трафика от разделенного от запятой текстового файла. Функция readtable
возвращает данные в таблице. Отобразите первые восемь строк с помощью функции head
.
bikeTbl = readtable('BicycleCounts.csv');
head(bikeTbl)
ans=8×5 table
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
Данные имеют метки времени, таким образом, удобно использовать расписание, чтобы сохранить и анализировать данные. Расписание подобно таблице, но включает метки времени, которые сопоставлены со строками данных. Метки времени, или времена строки, представлены значениями duration
или datetime
. datetime
и duration
являются рекомендуемыми типами данных для представления моментов времени или прошедшие времена, соответственно.
Преобразуйте bikeTbl
в расписание с помощью функции table2timetable
. Необходимо использовать функцию преобразования, потому что readtable
возвращает таблицу. table2timetable
преобразовывает первый datetime
или переменную duration
в таблице во времена строки расписания. Времена строки являются метаданными, которые маркируют строки. Однако, когда вы отображаете расписание, времена строки и переменные расписания отображены подобным способом. Обратите внимание на то, что таблица имеет пять переменных, тогда как расписание имеет четыре.
bikeData = table2timetable(bikeTbl); head(bikeData)
ans=8×4 timetable
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 1487627 timetable bikeTbl 9387x5 1562953 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'} VariableDescriptions: {} VariableUnits: {} VariableContinuity: [] RowTimes: [9387x1 datetime] StartTime: 2015-06-24 00:00:00 SampleRate: NaN TimeStep: NaN 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'} VariableDescriptions: {} VariableUnits: {} VariableContinuity: [] RowTimes: [9387x1 datetime] StartTime: 2015-06-24 00:00:00 SampleRate: NaN TimeStep: NaN CustomProperties: No custom properties are set. Use addprop and rmprop to modify CustomProperties.
Отобразите первые восемь строк расписания.
head(bikeData)
ans=8×4 timetable
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
Чтобы определить сколько людей велосипед во время праздника, исследуйте данные 4-го июля праздник. Индексируйте в расписание ко временам строки на 4 июля 2015. Когда вы индексируете на временах строки, необходимо совпадать с временами точно. Можно задать индексы времени как datetime
или значения duration
, или как векторы символов, которые могут быть преобразованы в даты и времена. Можно задать многократно как массив.
Индексируйте в bikeData
с определенными датами и временами, чтобы извлечь данные на 4 июля 2015. Если вы задаете дату только, то время принято, чтобы быть полуночью или 0: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
.
Индекс в расписание с помощью времени располагается в течение целого дня от 4 июля 2015. Задайте время начала как полночь 4 июля и время окончания как полночь 5 июля. По умолчанию timerange
покрывает все случаи начиная со времени начала и до, но не включая, время окончания. Постройте график велосипедных количеств в течение дня.
tr = timerange('2015-07-04','2015-07-05'); jul4 = bikeData(tr,'Total'); head(jul4)
ans=8×1 timetable
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')
Из графика существует больше объема в течение дня, выравнивающегося днем. Поскольку многие компании закрываются, график не показывает типичный трафик в течение часов поездки на работу. Скачки позже вечером могут быть приписаны торжествам с фейерверком, который происходит после наступления темноты. Чтобы исследовать эти тенденции более тесно, данные должны сравниться с данными в течение типичных дней.
Сравните данные на 4 июля с данными для остальной части месяца июля.
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')
График показывает изменения, которые могут быть приписаны различиям в трафике между рабочими днями и выходными. Шаблоны трафика на 4 и 5 июля сопоставимы с шаблоном для трафика выходных дней. 5 июля понедельник, но часто наблюдается как праздник. Эти тенденции могут быть исследованы более тесно с дальнейшей предварительной обработкой и анализом.
Предварительная обработка Времен и Данных Используя расписание
Наборы данных с меткой времени часто грязны и могут содержать аномалии или ошибки. Расписания хорошо подходят для решения аномалий и ошибок.
Расписание не должно иметь своих времен строки ни в каком конкретном порядке. Это может содержать строки, которые не сортируются по их временам строки. Расписание может также содержать несколько строк с тем же временем строки, хотя строки могут иметь различные значения данных. Даже когда времена строки сортируются и уникальны, они могут отличаться временными шагами различных размеров. Расписание может даже содержать 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
s и недостающие значения datetime как NaT
s. Можно присвоить, найти, удалить и заполнить отсутствующие значения с standardizeMissing
, ismissing
, rmmissing
и функциями fillmissing
, соответственно.
Найдите и считайте отсутствующие значения в переменных расписания. В этом примере отсутствующие значения указывают на обстоятельства, когда никакие данные не были собраны.
missData = ismissing(bikeData); sum(missData)
ans = 1×4
1 3 3 3
Вывод от ismissing
является матрицей logical
, тот же размер как таблица, идентифицируя пропускающий значения данных как верные. Отобразите любые строки, которые имеют недостающие индикаторы данных.
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 array
2015-08-21 00:00:00
2015-11-19 23:00:00
2015-11-19 23:00:00
Три раза повторяются, и 19 ноября 2015 повторяется дважды. Исследуйте данные, сопоставленные с повторными временами.
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
В этом случае дублирующееся время, возможно, было ошибочно, поскольку данные и окружающие времена сопоставимы. Хотя это, кажется, представляет 1: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)
ans=8×3 timetable
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
. isregular
возвращает true
в течение отсортированных, равномерно распределенных времен (монотонно увеличивающийся) без копии или недостающие времена (NaT
или NaN
).
isregular(bikeData)
ans = logical
0
Вывод 0
или false
, указывает, что времена в расписании равномерно не расположены с интервалами. Исследуйте временной интервал более подробно.
dt = diff(bikeData.Time); [min(dt); max(dt)]
ans = 2x1 duration array
00:30:00
03:00:00
Чтобы поместить расписание на интервал постоянного времени, используйте retime
или synchronize
и задайте временной интервал интереса.
Определите количества в день с помощью функции retime
. Накопите данные количества в течение каждого дня с помощью метода sum
. Это подходит для числовых данных, но не категориальных данных в расписании. Используйте vartype
, чтобы идентифицировать переменные типом данных.
dayCountNum = retime(bikeData(:,vt),'daily','sum'); head(dayCountNum)
ans=8×3 timetable
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)
ans=8×4 timetable
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
Исследуйте эффект погоды на циклически повторяющемся поведении путем сравнения велосипедного количества с данными о погоде. Загрузите погодное расписание, которое включает исторические данные о погоде из Бостона, MA включая штормовые события.
load BostonWeatherData
head(weatherData)
ans=8×3 timetable
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)
RowTimes: Time: 383x1 datetime Values: Min 01-Jul-2015 Median 08-Jan-2016 Max 17-Jul-2016 TimeStep 24:00:00 Variables: TemperatureF: 383x1 double Values: Min 2 Median 55 Max 85 Humidity: 383x1 double Values: Min 29 Median 64 Max 97 Events: 383x1 categorical Values: Fog 7 Hail 1 Rain 108 Rain-Snow 4 Snow 18 Thunderstorm 12 None 233
Объедините велосипедные данные с данными о погоде к общему временному вектору с помощью synchronize
. Можно передискретизировать или совокупные данные расписания с помощью любого из методов, зарегистрированных на странице с описанием для функции synchronize
.
Синхронизируйте данные от обоих расписаний до общего временного вектора, созданного из пересечения их отдельных ежедневных временных векторов.
data = synchronize(dayCount,weatherData,'intersection');
head(data)
ans=8×7 timetable
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)
ans=8×4 table
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 a. m. и 5:00 p. m. Кроме того, тенденции между Идущими на восток и Движущимися на запад направлениями отличаются. В целом Движущееся на запад направление находится к жилым районам, окружающим область Cambridge и к Университетам. Идущее на восток направление находится к Бостону.
Трафик более тяжел позже в тот же день в Движущемся на запад направлении по сравнению с Идущим на восток направлением. Эта сила указывает на университетские расписания и трафик из-за ресторанов в области. Исследуйте тенденцию за день недели, а также часа дня.
byHrDay = varfun(@sum,bikeData,'GroupingVariables',{'HrOfDay','Day'},... 'OutputFormat','table'); head(byHrDay)
ans=8×6 table
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)
ans=8×8 table
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')
Существуют подобные тенденции в течение дней постоянной работы понедельника в течение пятницы с peaks в час пик и трафик, сужающийся вечером. Пятница имеет меньше объема, хотя полная тенденция подобна другим рабочим дням. Тенденции в течение субботы и воскресенья подобны друг другу без peaks часа пик и с большим количеством объема позже в тот же день. Тенденции позднего вечера также подобны в течение понедельника в течение пятницы с меньшим количеством объема в пятницу.
Чтобы исследовать полные тенденции времени суток, разделите данные ко временам часа пик. Возможно использовать различное время суток или модули времени с помощью функции 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')
В целом, существует о вдвое большем количестве трафика в этой области в течение вечерних и утренних часов пик по сравнению с другими временами дня. Существует очень мало трафика в этой области рано утром, но существует все еще значительный трафик вечерним и поздним вечером, сопоставим со днем за пределами утренних и вечерних часов пик.
datetime
| голова
| повторная синхронизация
| rmmissing
| sortrows
| сводные данные
| table2timetable
| временной диапазон
| расписание
| нестек
| varfun