timetable
В этом примере показано, как анализировать шаблоны движения велосипедов из данных о датчике с помощью timetable
контейнер данных для организации и предварительной обработки штампованных по времени данных. Данные получены с датчиков на Бродвейской улице в Кембридже, штат Массачусетс. City of Cambridge предоставляет общедоступный доступ к полному набору данных на сайте Cambridge Open Data.
В этом примере показано, как выполнить множество задач очистки, обжатия и предварительной обработки данных, таких как удаление отсутствующих значений и синхронизация данных с отметкой времени с различными временными шагами. В сложение подсвечивается исследование данных, включая визуализацию и сгруппированные вычисления с использованием timetable
контейнер данных для:
Исследуйте ежедневный велосипедный трафик
Сравнение движения велосипедов с местными погодными условиями
Анализ велосипедного движения в различные дни недели и время суток
Импортируйте выборку данных о велосипедном трафике из текстового файла, разделенного запятыми. The 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
Данные имеют временные метки, поэтому для хранения и анализа данных удобно использовать расписание. Расписание подобно таблице, но включает временные метки, которые связаны со строками данных. Временные метки, или время строки, представлены datetime
или duration
значения. 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 1412425 timetable bikeTbl 9387x5 1487735 table
Преобразуйте Day
переменная к категориальной. Категориальный тип данных предназначен для данных, которые состоят из конечного набора дискретных значений, таких как имена дней недели. Перечислите категории, чтобы они отображались в дневном порядке. Используйте индексирование через точку для доступа к переменным по имени.
bikeData.Day = categorical(bikeData.Day,{'Sunday','Monday','Tuesday',... 'Wednesday','Thursday','Friday','Saturday'});
В расписании время обрабатывается отдельно от переменных данных. Доступ к Properties
timetable, чтобы показать, что время строки является первой размерностью timetable, и переменные являются вторым измерением. The 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
может быть удобнее, чем вручную индексировать в таблицу или timetable, чтобы выбрать переменные. Вычислим средства и опускаем 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 года. Если вы указываете только дату, то время принимается полуночным, или 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
функция.
Индексируйте расписание, используя временную область значений на весь день 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 июля - понедельник, но часто отмечается как праздник. Эти тренды можно более тщательно изучить при дальнейшей предварительной обработке и анализе.
timetable
Наборы данных с временной меткой часто являются нечеткими и могут содержать аномалии или ошибки. Расписания хорошо подходят для разрешения аномалий и ошибок.
Расписание не должно иметь свои строки в каком-либо конкретном порядке. Он может содержать строки, которые не сортируются по их времени. Расписание может также содержать несколько строк с одним и тем же временем строки, хотя строки могут иметь различные значения данных. Даже когда время строки отсортировано и уникально, они могут отличаться временными шагами разных размеров. Расписание может даже содержать NaT
или NaN
значения для указания отсутствующего времени строки.
The timetable
Тип данных предоставляет несколько различных способов разрешения пропущенных, повторяющихся или неоднородных моментов времени. Можно также переизбрать или агрегировать данные для создания регулярного расписания. Когда расписание является регулярным, оно имеет время строк, которые сортируются и уникальны, и имеет равномерный или равномерно разнесенный временной шаг между ними.
Чтобы найти отсутствующее время строки, используйте ismissing
.
Чтобы удалить отсутствующее время и данные, используйте rmmissing
.
Чтобы отсортировать расписание по временам строк, используйте sortrows
.
Чтобы создать расписание с уникальным и отсортированным временем строки, используйте unique
и retime
.
Чтобы создать регулярное расписание, задайте равномерно разнесенный временной вектор и используйте retime
.
Определите, отсортировано ли расписание. Расписание сортируется, если его строки указаны в порядке возрастания.
issorted(bikeData)
ans = logical
0
Отсортируйте расписание. The sortrows
функция сортирует строки по времени их строк, от самого раннего до последнего времени. Если есть строки с повторяющимися временами строк, то sortrows
копирует все дубликаты в выход.
bikeData = sortrows(bikeData); issorted(bikeData)
ans = logical
1
Расписание может иметь индикаторы недостающих данных в его переменных или временах строк. Для примера можно указать отсутствующие числовые значения как NaN
s, и отсутствующие значения datetime как NaT
s. Вы можете назначать, находить, удалять и заполнять отсутствующие значения standardizeMissing
, ismissing
, rmmissing
, и fillmissing
функций, соответственно.
Найдите и подсчитайте отсутствующие значения в переменных timetable. В этом примере отсутствующие значения указывают на обстоятельства, когда данные не были собраны.
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)
находит отсутствующие данные только в переменных timetable, но не во времени. Чтобы найти отсутствующее время строки, вызовите 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
Трижды повторяются и 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
Первый имеет дублированные, но не дублирующие данные, в то время как другие полностью дублированы. Строки timetable рассматриваются как дубликаты, когда они содержат одинаковое время строк и одинаковые значения данных в строках. Можно использовать unique
удаление повторяющихся строк в расписании. The 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)
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
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
функция.
Синхронизируйте данные из обоих timetables с общим временным вектором, созданным из пересечения их отдельных ежедневных временных векторов.
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')
Эта столбиковая диаграмма указывает, что в будние дни трафик становится более тяжелым. Кроме того, существует различие в направлениях Eastbound и Westbound. Это может указывать на то, что люди, как правило, проходят разные маршруты при въезде и выезде из города. Другой возможностью является то, что некоторые люди заходят в один день и возвращаются в другой день.
Определите час дня и используйте 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 и 17:00. Кроме того, тренды между направлениями Eastbound и Westbound различны. В целом, Уэстбордское направление направлено к жилым районам, окружающим район Кембриджа, и к университетам. Восточное направление направлено в сторону Бостона.
Трафик более тяжелый в более позднем возрасте в направлении Westbound по сравнению с направлением Eastbound. Это может указывать на расписание университетов и трафик из-за ресторанов в этом районе. Исследуйте тренд по дням недели и часам суток.
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
| head
| retime
| rmmissing
| sortrows
| summary
| table2timetable
| timerange
| timetable
| unstack
| varfun