exponenta event banner

Предварительная обработка и изучение данных с отметками времени с помощью 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.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 года. Если указана только дата, то предполагается, что это время равно полуночи или 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 значения для указания отсутствующих времен строк.

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)])

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.

Кроме того, тенденции между восточным и западным направлениями различны. В целом, направление Уэстбаунда - это жилые районы, окружающие район Кембриджа, и университеты. Направление в восточном направлении к Бостону.

Позднее в течение дня трафик в западном направлении тяжелее, чем в восточном. Это может указывать на расписание университетов и трафик из-за ресторанов в этом районе. Осмотрите тренд по дням недели и часам суток.

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.

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

Анализ трафика в час пик

Чтобы изучить общее время суток трендов, разбейте данные по часам пик. Можно использовать разное время суток или единицы времени, используя 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.

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

См. также

| | | | | | | | | |

Связанные темы