【问题标题】:Merging two rows within a dataframe - start and end time合并数据框中的两行 - 开始时间和结束时间
【发布时间】:2021-03-24 02:33:58
【问题描述】:

我希望我做得对,因为这是我第一次在这里发帖!我目前有一个看起来像这样的数据集(总共有 160k 个条目):

Geocode Barrier.ID Device.ID City Date Time State.code
603 7 392 Por 31/01/2021 10:39:10 Deactivated
603 7 392 Por 31/01/2021 10:54:18 Deactivated
603 7 392 Por 31/01/2021 11:10:38 Activated
603 7 392 Por 31/01/2021 11:11:37 Deactivated
603 7 392 Por 31/01/2021 11:12:18 Activated
603 7 392 Por 31/01/2021 11:13:37 Deactivated
603 7 392 Por 31/01/2021 11:17:38 Activated
603 7 392 Por 31/01/2021 11:19:37 Deactivated
603 7 392 Por 31/01/2021 11:26:25 Activated
603 7 392 Por 31/01/2021 11:29:37 Deactivated
603 7 392 Por 31/01/2021 11:40:38 Activated
603 7 392 Por 31/01/2021 11:45:38 Activated
603 7 392 Por 31/01/2021 11:49:38 Deactivated

原始数据输入:

structure(list(Geocode = c("603", "603", "603", "603", "603", "603", "603", "603", "603", "603", "603", "603", "603"), 
Barrier.ID = c("7",  "7", "7", "7", "7", "7", "7", "7", "7", "7", "7", "7", "7"), 
Device.ID = c("392","392", "392", "392", "392","392", "392", "392", "392", "392", "392","392", "392"), 
City = c("Por", "Por", "Por", "Por", "Por", "Por", "Por", "Por", "Por", "Por", "Por", "Por", "Por"),
Date = c("31/01/2021", "31/01/2021", "31/01/2021", "31/01/2021", "31/01/2021", "31/01/2021", "31/01/2021", "31/01/2021", "31/01/2021", "31/01/2021", "31/01/2021", "31/01/2021", "31/01/2021"), 
Time = c("10:39:10", "10:54:18", "11:10:38", "11:11:37", "11:12:18", "11:13:37", 
"11:17:38", "11:19:37", "11:26:25", "11:29:37", "11:40:38", "11:45:38", "11:49:38"), 
State.code = c("Deactivated", "Deactivated", "Activated", "Deactivated", 
"Activated", "Deactivated", "Activated", "Deactivated", "Activated", 
"Deactivated", "Activated", "Activated", "Deactivated")), 
row.names = c(NA, 13L), 
class = "data.frame")

我想创建类似于下表的内容。请注意,第一个表的前两行已被删除,因为事件必须始终以“激活”状态代码开头。上表的第 11 行也已被删除,因为那里有一个不完整的事件。只有“Activated”事件,没有“deactivated”事件。

Geocode Barrier.ID Device.ID City Date State.code Activated Deactivated
603 7 392 Por 31/01/2021 Activated 11:10:38 11:11:37
603 7 392 Por 31/01/2021 Activated 11:12:18 11:13:37
603 7 392 Por 31/01/2021 Activated 11:17:38 11:19:37
603 7 392 Por 31/01/2021 Activated 11:26:25 11:29:37
603 7 392 Por 31/01/2021 Activated 11:45:38 11:49:38

根据 state.code 中的值,时间是“激活”或“停用”时间。我设法通过使用来划分时间:

df$Activated <- ifelse(df$State.code == "Activated", df$Time, NA)
df$Deactivated <- ifelse(df$State.code == "Deactivated", df$Time, NA)

这给了我:

Geocode Barrier.ID Device.ID City Date Time State.code Activated Deactivated
603 7 392 Por 31/01/2021 10:39:10 Deactivated 10:39:10
603 7 392 Por 31/01/2021 10:54:18 Deactivated 10:54:18
603 7 392 Por 31/01/2021 11:10:38 Activated 11:10:38
603 7 392 Por 31/01/2021 11:11:37 Deactivated 11:11:37
603 7 392 Por 31/01/2021 11:12:18 Activated 11:12:18
603 7 392 Por 31/01/2021 11:13:37 Deactivated 11:13:37
603 7 392 Por 31/01/2021 11:17:38 Activated 11:17:38
603 7 392 Por 31/01/2021 11:19:37 Deactivated 11:19:37
603 7 392 Por 31/01/2021 11:26:25 Activated 11:26:25
603 7 392 Por 31/01/2021 11:29:37 Deactivated 11:29:37
603 7 392 Por 31/01/2021 11:40:38 Activated 11:40:38
603 7 392 Por 31/01/2021 11:45:38 Activated 11:45:38
603 7 392 Por 31/01/2021 11:49:38 Deactivated 11:49:38

然后我被卡住了,我不知道如何继续。因此,我的问题是:

  1. 如何将这些行合并在一起,以便它们在数据框中的一行上显示“激活”和“停用”时间(如第二个表所示)?

  2. 如何排除“不完整”的事件(某些事件缺少相应的“激活”或“停用”时间的情况)?

我曾想过使用 cbind 将这两行合并,但由于事件不完整(即“激活”事件缺少“停用”事件),这不起作用,对吧?

如果有人能进一步帮助我,我将不胜感激!

【问题讨论】:

  • 您可以使用tidyr::pivot_wider 轻松完成此操作。但是什么唯一标识要合并的匹配行对?仅仅是它们是顺序的吗?还是其他列的组合?
  • 仅基于它们是否确实是连续的;其余的列都是相同的(除非我们移动到一个新的障碍——这一切都会有所不同)。我现在要去检查 pivot_wider - 谢谢!
  • 您可能需要先创建一个标识对的列,然后group_by(pair_id_col),执行数据透视,最后执行tidyr::drop_na 以删除缺少停用时间的那些
  • 谢谢!您对如何执行配对有什么建议吗?这是否需要一个 if 语句,因为可能存在不完整的事件(即,如果“激活”或“停用”在彼此之后出现两次,则删除行)?还是可以用更简单的方式完成?
  • 嘿,没问题!我刚刚添加了数据中可能发生的真正例外情况(并更新了输出)。在表 1 中,可以最好地发现错误。事件总是以“已激活”事件开始,因此必须删除前两行。在第 11 行和第 12 行中,“Activated”出现了两次,没有出现“deactivated”事件,这意味着出现了问题,应该删除第 11 行的条目。我希望能解决它

标签: r dataset data-transform


【解决方案1】:

即使是未排列的数据,以下内容也适用。

注意事项-

  • 我已加入日期和时间列,以便检查在其停用之前的日历日开始的事件。
  • 我假设如果有多个激活状态在持续,则只计算最后一个。
library(dplyr)
library(tidyr)

df %>% group_by(Geocode, Barrier.ID, Device.ID, City) %>%
  mutate(Date = as.POSIXct(paste(Date, Time), format = "%d/%m/%Y %H:%M:%S"),
         code = State.code == "Activated") %>%
  select(-Time) %>%
  arrange(Date) %>%
  mutate(code = cumsum(code)) %>%
  filter(code != 0) %>%
  group_by(Geocode, Barrier.ID, Device.ID, City, code) %>%
  filter(n() ==2) %>%
  pivot_wider(id_cols = c(Geocode, Barrier.ID, Device.ID, City, code), names_from = State.code, values_from = Date) %>%
  select(-code)

# A tibble: 5 x 7
# Groups:   Geocode, Barrier.ID, Device.ID, City, code [5]
   code Geocode Barrier.ID Device.ID City  Activated           Deactivated        
  <int> <chr>   <chr>      <chr>     <chr> <dttm>              <dttm>             
1     1 603     7          392       Por   2021-01-31 11:10:38 2021-01-31 11:11:37
2     2 603     7          392       Por   2021-01-31 11:12:18 2021-01-31 11:13:37
3     3 603     7          392       Por   2021-01-31 11:17:38 2021-01-31 11:19:37
4     4 603     7          392       Por   2021-01-31 11:26:25 2021-01-31 11:29:37
5     6 603     7          392       Por   2021-01-31 11:45:38 2021-01-31 11:49:38
  • 但是,如果您有多个停用状态,则以下策略将起作用
library(data.table)
df %>% group_by(Geocode, Barrier.ID, Device.ID, City) %>%
  mutate(Date = as.POSIXct(paste(Date, Time), format = "%d/%m/%Y %H:%M:%S"),
         code = State.code == "Activated") %>%
  select(-Time) %>%
  arrange(Date) %>%
  mutate(code = cumsum(code),
         code2 = rleid(State.code)) %>%
  filter(code != 0) %>%
  group_by(Geocode, Barrier.ID, Device.ID, City, code) %>%
  filter(n() != 1) %>%
  group_by(code2) %>% slice_tail() %>%
  pivot_wider(id_cols = c(Geocode, Barrier.ID, Device.ID, City, code), names_from = State.code, values_from = Date) %>%
  select(-code)

  Geocode Barrier.ID Device.ID City  Activated           Deactivated        
  <chr>   <chr>      <chr>     <chr> <dttm>              <dttm>             
1 603     7          392       Por   2021-01-31 11:10:38 2021-01-31 11:11:37
2 603     7          392       Por   2021-01-31 11:13:37 2021-01-31 11:19:37
3 603     7          392       Por   2021-01-31 11:26:25 2021-01-31 11:29:37
4 603     7          392       Por   2021-01-31 11:45:38 2021-01-31 11:49:38

df
> df
   Geocode Barrier.ID Device.ID City       Date     Time  State.code
1      603          7       392  Por 31/01/2021 10:39:10 Deactivated
2      603          7       392  Por 31/01/2021 10:54:18 Deactivated
3      603          7       392  Por 31/01/2021 11:10:38   Activated
4      603          7       392  Por 31/01/2021 11:11:37 Deactivated
5      603          7       392  Por 31/01/2021 11:12:18   Activated
6      603          7       392  Por 31/01/2021 11:13:37   Activated
7      603          7       392  Por 31/01/2021 11:17:38 Deactivated
8      603          7       392  Por 31/01/2021 11:19:37 Deactivated
9      603          7       392  Por 31/01/2021 11:26:25   Activated
10     603          7       392  Por 31/01/2021 11:29:37 Deactivated
11     603          7       392  Por 31/01/2021 11:40:38   Activated
12     603          7       392  Por 31/01/2021 11:45:38   Activated
13     603          7       392  Por 31/01/2021 11:49:38 Deactivated

【讨论】:

  • 非常感谢!第一个代码示例似乎运行良好!
猜你喜欢
  • 1970-01-01
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
  • 2019-03-09
  • 1970-01-01
  • 2016-09-24
  • 2019-02-14
  • 1970-01-01
相关资源
最近更新 更多