timetableВ этом примере показано, как анализировать схемы движения велосипедов на основе данных датчиков с помощью timetable контейнер данных для организации и предварительной обработки данных с временной меткой. Данные поступают с датчиков на Бродвей-стрит в Кембридже, штат Массачусетс. Город Кембридж предоставляет доступ общественности к полному набору данных на сайте Cambridge Open Data.
В этом примере показано, как выполнять различные задачи по очистке, прогону и предварительной обработке данных, такие как удаление отсутствующих значений и синхронизация данных с отметками времени с различными временными интервалами. Кроме того, подсвечивается изучение данных, включая визуализации и сгруппированные расчеты с использованием 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
Данные имеют временные метки, поэтому удобно использовать расписание для хранения и анализа данных. Расписание аналогично таблице, но включает метки времени, связанные со строками данных. Метки времени, или время строки, представлены как 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 расписания, чтобы показать, что время строки является первым измерением расписания, а переменные - вторым измерением. 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.Propertiesans =
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 года. Если указана только дата, то предполагается, что это время равно полуночи или 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 значения для указания отсутствующих времен строк.
timetable тип данных предоставляет несколько различных способов разрешения отсутствующих, повторяющихся или неравномерных моментов времени. Можно также выполнить повторную выборку или агрегировать данные для создания регулярного расписания. Когда расписание является регулярным, оно имеет время строк, которые сортируются и уникальны, и имеют равномерный или равномерно разнесенный шаг времени между ними.
Чтобы найти отсутствующие значения времени строки, используйте ismissing.
Чтобы удалить недостающее время и данные, используйте rmmissing.
Чтобы отсортировать расписание по времени строки, используйте sortrows.
Чтобы составить расписание с уникальным и отсортированным временем строк, используйте unique и retime.
Чтобы составить регулярное расписание, укажите равномерно разнесенный вектор времени и используйте retime.

Определите, отсортировано ли расписание. Расписание сортируется, если его время строк указано в порядке возрастания.
issorted(bikeData)
ans = logical
0
Сортируйте расписание. sortrows функция сортирует строки по времени их строк, от самого раннего до последнего времени. Если есть строки с повторяющимися временами строк, то sortrows копирует все дубликаты в выходные данные.
bikeData = sortrows(bikeData); issorted(bikeData)
ans = logical
1
График может содержать отсутствующие индикаторы данных в своих переменных или времени строк. Например, можно указать отсутствующие числовые значения как NaNs и отсутствующие значения datetime как NaTs. Можно назначить, найти, удалить и заполнить отсутствующие значения с помощью 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
Трижды повторяют и 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
В этом случае время дублирования может быть ошибочным, поскольку данные и окружающее время являются согласованными. Хотя это, кажется, представляет 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
Проверьте влияние погоды на поведение велосипедистов, сравнив количество велосипедов с данными о погоде. Загрузите график погоды, который включает исторические данные погоды из Бостона, Массачусетс, включая штормовые явления.
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')
Гистограмма показывает, что в будние дни трафик тяжелее. Кроме того, существует разница в направлениях 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')
Кроме того, тенденции между восточным и западным направлениями различны. В целом, направление Уэстбаунда - это жилые районы, окружающие район Кембриджа, и университеты. Направление в восточном направлении к Бостону.
Позднее в течение дня трафик в западном направлении тяжелее, чем в восточном. Это может указывать на расписание университетов и трафик из-за ресторанов в этом районе. Осмотрите тренд по дням недели и часам суток.
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')
Схожие тенденции наблюдаются и в обычные рабочие дни с понедельника по пятницу, причем пик в час пик и трафик сужаются вечером. Пятница имеет меньший объем, хотя общая тенденция аналогична другим рабочим дням. Тренды на субботу и воскресенье похожи друг на друга, без пиков часов пик и с большим объемом позже в день. Тенденции позднего вечера также схожи для понедельника-пятницы, с меньшим объемом в пятницу.
Чтобы изучить общее время суток трендов, разбейте данные по часам пик. Можно использовать разное время суток или единицы времени, используя 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