如何根据R中的预定义模式对数据进行子集?

时间:2017-06-28 19:23:35

标签: r

我有一个数据集,其中包含人们超过特定天数的信息 - 数据具有三种长格式嵌套级别。首先是人,第二是日,第三是位置。每行表示一个位置。我有信息类型的位置(家庭,工作等),用于到达该位置的旅行模式(步行,自行车,公共汽车等),以及到达和离开时间。这是一份每日旅行日记,从家里开始,到家里结束 我需要聚合数据以创建每天每个人的以下类型的旅程的信息:

1. Journey from home to work without detour. (H-W)
2. Journey from home to work with detour. (H-dt-W) the number of detour does not matter. 
3. Journey work to home without detour. (W-H) 
4. Journey work to home with detour. (W-dt-H) the number of detour does not matter
5. Journey starting from home and ending at home and does not include work in between. (H-O..-H)
6. Journey starting from work and ending at work and does not include home in between. (W-O..-W)

对于所有这些类别,我需要旅行模式和总旅行时间的信息。 例如:想象一个星期一;一个人在家里醒来(H)吃早餐,然后前往他的车上办公(W);在途中,他在星巴克停下来喝咖啡(C),然后从他们的家中接走一名同事(D)。在工作的白天,该人去不同地点(E)拜访客户并重返工作岗位;这次他需要火车。那个人然后在那天早些时候回家,因为他需要去杂货店。所以这个人回到家里,去了位置(F)的杂货店,回到家里,这次走到杂货店。这个人做了不同的旅程:1)H-dt(C-D)-W,2)W-O(E)-W,3)W-H,5)H-O(F)-H。他使用不同的模式进行旅程,1)驾驶,2)火车,3)步行。我们可以使用到达和离开时间为每个位置添加旅行时间。下面是数据的表格形式。 (以下数据仅适用于一个人的一天,但我的数据有更多的日期和人员。)

    ###Data I have
Person   Day ID     Place   Location_Code   Mode    Arrive      Depart
   5        1       0           H           NA      NA          8:00:00 AM
   5        1       1           C           D       8:30:00 AM  9:30:00 AM
   5        1       2           D           D       10:00:00 AM 11:00:00 AM
   5        1       3           W           D       11:30:00 AM 12:00:00 PM
   5        1       4           E           T       1:00:00 PM  1:30:00 PM
   5        1       5           W           T       2:30:00 PM  3:45:00 PM
   5        1       6           H           D       4:00:00 PM  4:30:00 PM
   5        1       7           F           P       5:00:00 PM  6:00:00 PM
   5        1       8           H           P       7:00:00 PM  NA


###Data I want
Person  Day     Journey Type    Mode/s  Travel Time(hr)     
5       1       H-dt-W          DDD         1.5     
5       1       W-O-W           TT          2       
5       1       W-H             D           0.25        
5       1       H-O-H           PP          1.5

我还enter image description here附上了我的数据图片和我想要的数据。

1 个答案:

答案 0 :(得分:1)

以下是使用tidyversedata.tablelubridatestringr中的函数的解决方案。 dt6是最终输出。请注意dt6Journey Type列之外的所需输出完全相同,因为我不知道编码的逻辑和增强(例如为什么HCDW是H-dt(CD) - W2)。我只是结合了所有信息。您可以根据自己的喜好更改编码。

# Load package
library(tidyverse)
library(data.table)
library(lubridate)
library(stringr)

数据准备

# Create example data frame
dt <- read.table(text = "Person   'Day ID'     Place   Location_Code   Mode    Arrive      Depart
5        1       0           H           NA      NA          '8:00:00 AM'
5        1       1           C           D       '8:30:00 AM'  '9:30:00 AM'
5        1       2           D           D       '10:00:00 AM' '11:00:00 AM'
5        1       3           W           D       '11:30:00 AM' '12:00:00 PM'
5        1       4           E           T       '1:00:00 PM'  '1:30:00 PM'
5        1       5           W           T       '2:30:00 PM'  '3:45:00 PM'
5        1       6           H           D       '4:00:00 PM'  '4:30:00 PM'
5        1       7           F           P       '5:00:00 PM'  '6:00:00 PM'
5        1       8           H           P       '7:00:00 PM'  NA",
                 header = TRUE, stringsAsFactors = FALSE)

第1步:转换到达并离开日期时间等级

如果您的所有移动事件都发生在同一天,那么年份和月份2000-01无关紧要。我刚刚添加它们以便更容易转换为日期时间类。

dt2 <- dt %>%
  mutate(Arrive = ymd_hms(paste0("2000-01-", Day.ID, " ", Arrive)),
         Depart = ymd_hms(paste0("2000-01-", Day.ID, " ", Depart))) 

步骤2:根据Arrive和Depart将数据帧从宽格式转换为长格式。创建一个MoveID,这是Place列的一个滞后差异。

dt3 <- dt2 %>%
  # Convert to long format
  gather(Action, Time, Arrive, Depart) %>%
  arrange(Person, Day.ID, Place, Location_Code, Action) %>%
  group_by(Person, Day.ID, Place, Location_Code) %>%
  # Create a Moving ID
  mutate(MoveID = lag(Place)) %>%
  ungroup() %>%
  fill(MoveID, .direction = "down") 

步骤3:计算每次MoveID

的出发和到达之间的时差
dt4 <- dt3 %>%
  # Calculate time difference 
  group_by(Person, Day.ID, MoveID) %>%
  summarise(Travel_Time = difftime(dplyr::last(Time), dplyr::first(Time),
                                   units = "hours")) %>%
  ungroup() %>%
  select(MoveID, Travel_Time) %>%
  right_join(dt3, by = "MoveID") 

第4步:将Travel_Time移动一个。根据模式创建运行长度ID。

dt5 <- dt4 %>%
  mutate(Travel_Time = lag(Travel_Time)) %>%
  mutate(RunID = rleid(Mode)) %>%
  group_by(Person, Day.ID, Place) %>%
  slice(1) %>%
  select(-Action, -Time) %>%
  ungroup()

步骤5:创建所有所需的列

dt6 <- dt5 %>%
  group_by(Person, Day.ID, RunID) %>%
  summarise(Travel_Time_Sum = sum(Travel_Time), 
            Mode_Sum = paste(Mode, collapse = ""),
            Journey = paste(Location_Code, collapse = "-")) %>%
  mutate(Journey = paste(str_sub(lag(Journey), start = -1, end = -1), 
                         Journey, sep = "-")) %>%
  # Remove any columns with NA in Travel_Time_Sum
  drop_na(Travel_Time_Sum) %>%
  select(Person, Day = Day.ID, `Journey Type` = Journey, `Mode/s` = Mode_Sum, 
         `Travel Time(hr)` = Travel_Time_Sum)