创建一个循环以在同一行中记录下一个记录时间和日期(基于唯一 ID)

Posted

技术标签:

【中文标题】创建一个循环以在同一行中记录下一个记录时间和日期(基于唯一 ID)【英文标题】:Create a loop to record next record time and date (based on unique id) in same row 【发布时间】:2022-01-21 01:51:27 【问题描述】:

我正在尝试创建一个循环和一个 if/else 语句来拉下一行的时间以将其记录为超时。如果没有下一行(即没有汽车 id#)作为结束/退出返回。 Data and envisioned output

这是我的代码,但它根本不起作用,可能没有正确掌握基础知识。

for(i in 1:dim(df2)[1])
  if(df2$car.id[i] == df2$car.id[i +1])
    return$timein[i+1]
  else
    print("end")
   
    
)

【问题讨论】:

欢迎来到 Stack Overflow。请不要使用数据图像,因为没有大量不必要的努力就无法使用它们。 For multiple reasons。如果你的问题是可重复的,你更有可能得到积极的回应。 See Stack Overflow question guidance 粘贴 dput(df2) 的输出或数据框的样本。 【参考方案1】:

下面有几个注释,但先试试这个:

df2$Timeout <- ave(df2$Timein, df2$car.id, FUN = function(z) c(z[-1], NA))

上面的代码返回df2$Timein的下一个值每个df2$car.id,当下一行是不同的car.id时正确重置。顺序很重要,所以如果您需要对Timein 进行排序,那么您应该在调用ave(.) 之前对其进行排序。 (这将正确处理car.id 出现故障甚至混杂。)

您的(图像)代码存在问题。如果上述方法不起作用,您需要澄清这些要点。

    nrow(df2) 是比dim(df2)[1] 更规范的方法。

    我推荐for (i in seq_len(nrow(df2))),而不是nrow(.),因为它至少在一个极端情况下表现更好。

    您的[i+1] 索引将超出索引限制并返回 NA,这最终将与missing value where TRUE/FALSE needed 出错。

    return$timein[i+1] 似乎是错误的,除非您有一个命名列表或data.frame 对象,即return;我不鼓励这样做,因为它可能(被人们)与基本 R 原语(函数)return(.) 混淆。如果它不是一个对象,那么你就用错了,坦率地说我不知道​​它应该是什么,因为这里的 for 循环似乎没有必要。

    您的预期输出并不完全清楚,但我猜您想要时间戳或文字 "End"。后者会破坏你的时间戳,将它们从POSIXt-class 对象转换为字符串。一般来说,框架中的一列不能混合类。

【讨论】:

【参考方案2】:

尝试使用dplyr。使用玩具数据。

library(dplyr)

dat %>% group_by( car.id ) %>% 
  mutate( Timeout=lead(as.character(Timein), default="END") ) %>% ungroup
# A tibble: 10 x 4
      car.id car.type Timein              Timeout            
       <dbl>    <dbl> <dttm>              <chr>              
 1  14359825        1 2021-12-18 17:28:58 2021-12-18 17:33:58
 2  14359825        1 2021-12-18 17:33:58 2021-12-18 18:03:58
 3  14359825        1 2021-12-18 18:03:58 2021-12-18 18:08:58
 4  14359825        1 2021-12-18 18:08:58 2021-12-18 18:13:58
 5  14359825        1 2021-12-18 18:13:58 END                
 6 243095743        2 2021-12-18 18:30:38 2021-12-18 18:37:18
 7 243095743        2 2021-12-18 18:37:18 2021-12-18 19:17:18
 8 243095743        2 2021-12-18 19:17:18 2021-12-18 19:23:58
 9 243095743        2 2021-12-18 19:23:58 2021-12-18 19:30:38
10 243095743        2 2021-12-18 19:30:38 END 

如果您想要一个仅限日期的 Timeout 列,您可以随时重铸

as.POSIXct( dat$Timeout, format="%F %T" )
 [1] "2021-12-18 17:33:58 CET" "2021-12-18 18:03:58 CET"
 [3] "2021-12-18 18:08:58 CET" "2021-12-18 18:13:58 CET"
 [5] NA                        "2021-12-18 18:37:18 CET"
 [7] "2021-12-18 19:17:18 CET" "2021-12-18 19:23:58 CET"
 [9] "2021-12-18 19:30:38 CET" NA

或直接使用

dat %>% group_by( car.id ) %>% mutate( Timeout=lead( Timein ) )

数据

dat <- structure(list(car.id = c(14359825, 14359825, 14359825, 14359825, 
14359825, 243095743, 243095743, 243095743, 243095743, 243095743
), car.type = c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2), Timein = structure(c(1639844938.6685, 
1639845238.6685, 1639847038.6685, 1639847338.6685, 1639847638.6685, 
1639848638.6685, 1639849038.6685, 1639851438.6685, 1639851838.6685, 
1639852238.6685), class = c("POSIXct", "POSIXt"))), row.names = c(NA, 
10L), class = "data.frame")

【讨论】:

仅供参考,如果 TimeinPOSIXt,那么使用此解决方案,Timout 将是 character。如果Timein 是开头的字符串向量,则不是问题。 @r2evans 是的,我决定默默地转换为字符以匹配所需的输出。但你可能有权在某处提及该演员......

以上是关于创建一个循环以在同一行中记录下一个记录时间和日期(基于唯一 ID)的主要内容,如果未能解决你的问题,请参考以下文章

按月/年创建和关闭的记录数

循环遍历列表映射以在一个资源块中为多个域创建 DNS 记录

尝试在 php 中创建循环卡(引导程序)

如何在同一行获得两个日期选择器?

MySQL:在同一行中的某些条件下选择值和最小值

如何在同一行记录控制台或清除节点中的控制台? [复制]