Предварительная обработка и исследование штампованных по времени данных с помощью timetable

В этом примере показано, как анализировать шаблоны движения велосипедов из данных о датчике с помощью timetable контейнер данных для организации и предварительной обработки штампованных по времени данных. Данные получены с датчиков на Бродвейской улице в Кембридже, штат Массачусетс. City of Cambridge предоставляет общедоступный доступ к полному набору данных на сайте Cambridge Open Data.

В этом примере показано, как выполнить множество задач очистки, обжатия и предварительной обработки данных, таких как удаление отсутствующих значений и синхронизация данных с отметкой времени с различными временными шагами. В сложение подсвечивается исследование данных, включая визуализацию и сгруппированные вычисления с использованием timetable контейнер данных для:

  • Исследуйте ежедневный велосипедный трафик

  • Сравнение движения велосипедов с местными погодными условиями

  • Анализ велосипедного движения в различные дни недели и время суток

Импорт данных велосипедного трафика в 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')

Figure contains an axes. The axes with title Bicycle Counts on July 4, 2015 contains an object of type bar.

От графика в течение дня становится больше объема, выравниваясь днем. Из-за того, что многие предприятия закрыты, график не показывает типичный трафик в командные часы. Шипы позже вечером можно отнести к торжествам с фейерверками, которые происходят после темноты. Чтобы более тщательно изучить эти тренды, данные следует сравнить с данными за типичные дни.

Сравните данные за 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')

Figure contains an axes. The axes with title Bicycle Counts in July contains 2 objects of type line. These objects represent 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

Идентифицируйте и удаляйте недостающее время и данные

Расписание может иметь индикаторы недостающих данных в его переменных или временах строк. Для примера можно указать отсутствующие числовые значения как NaNs, и отсутствующие значения datetime как NaTs. Вы можете назначать, находить, удалять и заполнять отсутствующие значения 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)])

Figure contains an axes. The axes with title Bicycle Counts and Temperature Over Time contains 2 objects of type line.

График показывает, что данные о трафике и погоде могут следовать аналогичным трендам. Изменение масштаба графика.

xlim([datetime('2015-11-01'),datetime('2016-05-01')])

Figure contains an axes. The axes with title Bicycle Counts and Temperature Over Time contains 2 objects of type line.

Тренды схожи, что указывает на то, что меньше людей вращается в более холодные дни.

Анализ по дням недели и времени суток

Исследуйте данные на основе различных интервалов, таких как день недели и время дня. Определите общее количество в день с помощью 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')

Figure contains an axes. The axes with title Bicycle Count by Day of Week contains 2 objects of type bar. These objects represent Westbound, Eastbound.

Эта столбиковая диаграмма указывает, что в будние дни трафик становится более тяжелым. Кроме того, существует различие в направлениях 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')

Figure contains an axes. The axes with title Mean Bicycle Count by Hour of Day contains 2 objects of type bar. These objects represent Westbound, Eastbound.

Существуют скачки трафика в типичные часы поездок, около 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')

Figure contains an axes. The axes with title Bicycle Count by Hour and Day of Week contains 7 objects of type surface.

Существуют аналогичные тренды для обычных рабочих дней с понедельника по пятницу, с 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')

Figure contains an axes. The axes with title Mean Bicycle Count During Rush Hours contains an object of type bar.

В целом трафика в этом районе в вечернее и утреннее часы пик примерно в два раза больше по сравнению с другими временами суток. Трафика в этом районе рано утром очень мало, но в вечернее и позднее вечернее время по-прежнему наблюдается значительный трафик, сопоставимый с днем вне утренних и вечерних часов пик.

См. также

| | | | | | | | | |

Похожие темы