将组 ID 分配给时间序列中连续的唯一值序列

jgo*_*ald 6 datetime r

我正在处理一个大时间序列,其中一列包含四个不同的传感器,一列包含测量值。我需要为属于同一时间的测量值分配一个 id。问题是,每个设备的测量时间略有不同,因此我不能简单地按时间戳对它们进行分组。在按时间排序的数据帧中,可以通过唯一设备 ID 序列来标识应该分组的测量。这里的问题是,一次有 4 台设备记录一个值,而另一次有 3 台设备记录一个值。我的数据看起来像这样。

       timestamp                  device   measurement
    1  2019-08-27 07:29:20.671313 sdr_03   49.868820
    2  2019-08-27 07:29:20.932043 sdr_02   54.160831
    3  2019-08-27 07:29:21.839312 sdr_03   48.974476
    4  2019-08-27 07:29:21.850454 sdr_02   50.808674
    5  2019-08-27 08:57:01.990833 sdr_03   50.533058
    6  2019-08-27 08:57:02.022798 sdr_04   51.143322
    7  2019-08-27 09:16:56.454308 sdr_02   57.447151
    8  2019-08-27 09:16:56.482433 sdr_04   50.012745
    9  2019-08-27 09:16:56.761776 sdr_01   71.500305
    10 2019-08-27 09:16:57.305510 sdr_02   56.851177
    11 2019-08-27 09:16:57.333628 sdr_04   60.390141
    12 2019-08-27 09:16:57.612972 sdr_01   73.470345
Run Code Online (Sandbox Code Playgroud)

你可以用这个重现:

my_data<-data.frame(timestamp = c("2019-08-27 07:29:20.671313","2019-08-27 07:29:20.932043","2019-08-27 07:29:21.839312",
                                       "2019-08-27 07:29:21.850454", "2019-08-27 08:57:01.990833","2019-08-27 08:57:02.022798",
                                       "2019-08-27 09:16:56.454308", "2019-08-27 09:16:56.482433", "2019-08-27 09:16:56.761776",
                                       "2019-08-27 09:16:57.305510" ,"2019-08-27 09:16:57.333628", "2019-08-27 09:16:57.612972"),
               device=c("sdr_03", "sdr_02", "sdr_03", "sdr_02", "sdr_03" ,"sdr_04", "sdr_02", "sdr_04" ,"sdr_01", "sdr_02" ,"sdr_04",
                        "sdr_01"),
               measurement=c(49.868820, 54.160831, 48.974476, 50.808674, 50.533058, 51.143322,57.447151,50.012745, 71.500305,56.851177,
                             60.390141, 73.470345)
               )

Run Code Online (Sandbox Code Playgroud)

只要列设备前几行中的任何元素都不再出现,我就需要为连续行分配相同的值

             timestamp        device   measurement match_id
1  2019-08-27 07:29:20.671313 sdr_03   49.868820        1
2  2019-08-27 07:29:20.932043 sdr_02   54.160831        1
3  2019-08-27 07:29:21.839312 sdr_03   48.974476        2
4  2019-08-27 07:29:21.850454 sdr_02   50.808674        2
5  2019-08-27 08:57:01.990833 sdr_03   50.533058        3
6  2019-08-27 08:57:02.022798 sdr_04   51.143322        3
7  2019-08-27 09:16:56.454308 sdr_02   57.447151        3
8  2019-08-27 09:16:56.482433 sdr_04   50.012745        4
9  2019-08-27 09:16:56.761776 sdr_01   71.500305        4
10 2019-08-27 09:16:57.305510 sdr_02   56.851177        4
11 2019-08-27 09:16:57.333628 sdr_04   60.390141        5
12 2019-08-27 09:16:57.612972 sdr_01   73.470345        5
Run Code Online (Sandbox Code Playgroud)

你可以从:

my_data<-data.frame(timestamp = c("2019-08-27 07:29:20.671313","2019-08-27 07:29:20.932043","2019-08-27 07:29:21.839312",
                                   "2019-08-27 07:29:21.850454", "2019-08-27 08:57:01.990833","2019-08-27 08:57:02.022798",
                                   "2019-08-27 09:16:56.454308", "2019-08-27 09:16:56.482433", "2019-08-27 09:16:56.761776",
                                   "2019-08-27 09:16:57.305510" ,"2019-08-27 09:16:57.333628", "2019-08-27 09:16:57.612972"),
           device=c("sdr_03", "sdr_02", "sdr_03", "sdr_02", "sdr_03" ,"sdr_04", "sdr_02", "sdr_04" ,"sdr_01", "sdr_02" ,"sdr_04",
                    "sdr_01"),
           measurement=c(49.868820, 54.160831, 48.974476, 50.808674, 50.533058, 51.143322,57.447151,50.012745, 71.500305,56.851177,
                         60.390141, 73.470345),match_id=c(1,1,2,2,3,3,3,4,4,4,5,5) )

Run Code Online (Sandbox Code Playgroud)

我一直在寻找答案三天了。很感谢任何形式的帮助。

Allan Camerons dplyr 解决方案导致匹配 ID 稍后重新出现在数据框中 - 请参见第 1、2、6、9 行。一次记录的设备数量可能少于 4 个,因此总是期望每次测量使用相同数量的记录设备的解决方案是行不通的。

# A tibble: 12 x 4
# Groups:   device [4]
   timestamp                  device measurement new_id
   <dttm>                     <fct>        <dbl>  <int>
 1 2019-08-27 07:29:20.671313 sdr_03        49.9      1
 2 2019-08-27 07:29:20.932043 sdr_02        54.2      1
 3 2019-08-27 07:29:21.839312 sdr_03        49.0      2
 4 2019-08-27 07:29:21.850454 sdr_02        50.8      2
 5 2019-08-27 08:57:01.990833 sdr_03        50.5      3
 6 2019-08-27 08:57:02.022798 sdr_04        51.1      1
 7 2019-08-27 09:16:56.454308 sdr_02        57.4      3
 8 2019-08-27 09:16:56.482433 sdr_04        50.0      2
 9 2019-08-27 09:16:56.761775 sdr_01        71.5      1
10 2019-08-27 09:16:57.305510 sdr_02        56.9      4
11 2019-08-27 09:16:57.333627 sdr_04        60.4      3
12 2019-08-27 09:16:57.612972 sdr_01        73.5      2
Run Code Online (Sandbox Code Playgroud)

虽然 Sotos 解决方案导致比存在的唯一设备更多的连续匹配 ID。例如第 5-9 行

# A tibble: 12 x 4
   timestamp           device measurement new_id
   <chr>               <fct>        <dbl>  <int>
 1 2019-08-27 07:29:20 sdr_03        49.9      1
 2 2019-08-27 07:29:20 sdr_02        54.2      1
 3 2019-08-27 07:29:21 sdr_03        49.0      2
 4 2019-08-27 07:29:21 sdr_02        50.8      2
 5 2019-08-27 08:57:01 sdr_03        50.5      3
 6 2019-08-27 08:57:02 sdr_04        51.1      3
 7 2019-08-27 09:16:56 sdr_02        57.4      3
 8 2019-08-27 09:16:56 sdr_04        50.0      3
 9 2019-08-27 09:16:56 sdr_01        71.5      3
10 2019-08-27 09:16:57 sdr_02        56.9      4
11 2019-08-27 09:16:57 sdr_04        60.4      4
12 2019-08-27 09:16:57 sdr_01        73.5      4
Run Code Online (Sandbox Code Playgroud)

如果测量之间的时间差异 > 0.7 秒或同时记录 4 个设备,则这两种解决方案都非常有效(谢谢!)。可悲的是,大多数时候情况并非如此。我认为,忽略时间戳而是检查连续行中的重复项的解决方案可能会更好。我使用 rle() 或 data.table 找到了许多重复值的解决方案,但没有解决方案来识别唯一值的序列。请帮帮我!

Sot*_*tos 2

我很确定我真的想太多了,但这是一个可行的解决方案,

library(dplyr)

data %>% 
 mutate(timestamp = format(timestamp, '%Y-%m-%d %H:%M:%S')) %>%
 group_by(timestamp) %>% 
 mutate(new = data.table::rleid(duplicated(device))) %>% 
 group_by(timestamp, new) %>% 
 mutate(new1 = row_number() + new) %>% 
 ungroup() %>% 
 mutate(new_id = cumsum(c(TRUE, diff(new1) < 0))) %>% 
 select(-c(new, new1))
Run Code Online (Sandbox Code Playgroud)

这使,

# A tibble: 12 x 4
   timestamp           device measurement new_id
   <fct>               <fct>        <dbl>  <int>
 1 2019-08-27 09:48:54 sdr_02        80.2      1
 2 2019-08-27 09:48:54 sdr_01        71.7      1
 3 2019-08-27 09:48:54 sdr_04        74.2      1
 4 2019-08-27 09:48:54 sdr_03        62.6      1
 5 2019-08-27 09:48:55 sdr_02        77.1      2
 6 2019-08-27 09:48:55 sdr_01        69.2      2
 7 2019-08-27 09:48:55 sdr_03        62.1      2
 8 2019-08-27 09:48:55 sdr_02        77.1      3
 9 2019-08-27 09:48:55 sdr_01        54.6      3
10 2019-08-27 09:48:55 sdr_03        64.3      3
11 2019-08-27 09:48:56 sdr_02        66.5      4
12 2019-08-27 09:48:56 sdr_01        71.7      4
Run Code Online (Sandbox Code Playgroud)