Как проверить, находится ли значение под условием в интервале под другим условием в R? - PullRequest
1 голос
/ 16 мая 2019

У меня есть фрейм данных следующего типа:

Time    Behavior   Status
16.403  FOR    START
26.425  FOR    STOP
26.426  NI     START
28.460  NI     STOP
28.461  FOR    START
29.480  TSp    POINT
31.298  FOR    STOP
31.299  NI     START
33.297  NI     STOP
33.298  FOR    START
34.798  FOR    STOP

....

NI и FOR - это длительное поведение: начните со времени, обозначенного START в строке статуса,и заканчивается в СТОП.TSp является точечным событием.Поведение TSp может появляться несколько раз.Мне нужно проверить, включен ли он в интервал времени, определяемый поведением FOR.

Я пробовал несколько методов с циклами дифференциалов, но мне не удалось правильно кодировать .. Формат вывода не важен, может быть вектором True / False или числом или чем-то еще.

Если бы кто-то мог помочь, я был бы очень благодарен !!

Ответы [ 2 ]

2 голосов
/ 16 мая 2019

Вот еще один data.table подход

. Он использует скользящее соединение для создания интервалов FOR и неэквивалентное соединение для нахождения ТОЧЕК в этих интервалах FOR.

образец данных

df <- fread('
Time    Behavior   Status
16.403  FOR    START
26.425  FOR    STOP
26.426  NI     START
28.460  NI     STOP
28.461  FOR    START
29.480  TSp    POINT
31.298  FOR    STOP
31.299  NI     START
33.297  NI     STOP
33.298  FOR    START
34.798  FOR    STOP
', key = "Time" )

код

#create FOR-intervals using a rolling join on FOR-START and FOR-STOP
forInterval <- df[ Behavior == "FOR" & Status == "START", ][
  df[ Behavior == "FOR" & Status == "STOP", ], 
  endTime := i.Time, roll = TRUE 
  ]

#      Time Behavior Status endTime
# 1: 16.403      FOR  START  26.425
# 2: 28.461      FOR  START  31.298
# 3: 33.298      FOR  START  34.798

#check if yout Tsp is within a forInterval using a non-equi join
df[Behavior == "TSp", ][forInterval, 
                        inside_FOR := paste0( i.Time, "-", i.endTime ), 
                        on = .(Time >= Time, Time <= endTime)][]

выход

#     Time Behavior Status    inside_FOR
# 1: 29.48      TSp  POINT 28.461-31.298
1 голос
/ 16 мая 2019

Присвойте каждому интервалу идентификатор и приведите к широкой форме на основе Status

library(data.table)
setDT(df)

df[, id := (1 + (rowid(Behavior) - 1) %/% 2)*(Status != 'POINT')]

ints <- dcast(df[Status != 'POINT'], Behavior + id ~ Status, value.var = 'Time')

ints
#    Behavior id  START   STOP
# 1:      FOR  1 16.403 26.425
# 2:      FOR  2 28.461 31.298
# 3:      FOR  3 33.298 34.798
# 4:       NI  1 26.426 28.460
# 5:       NI  2 31.299 33.297

Опция 1: Добавьте дополнительные столбцы к ints, показывая соответствующие точки

ints[df[Status == 'POINT'], on = .(START < Time, STOP > Time),
     `:=`(Point_Behavior = i.Behavior, Point_Time = i.Time)]
#    Behavior id  START   STOP Point_Behavior Point_Time
# 1:      FOR  1 16.403 26.425           <NA>         NA
# 2:      FOR  2 28.461 31.298            TSp      29.48
# 3:      FOR  3 33.298 34.798           <NA>         NA
# 4:       NI  1 26.426 28.460           <NA>         NA
# 5:       NI  2 31.299 33.297           <NA>         NA

Опция2: Подмножество df только для точек и отображения соответствующих интервалов

df[Status == 'POINT'][
  ints, on = .(Time > START, Time < STOP),
  `:=`(i.Behavior = i.Behavior, START = START, STOP = STOP, id = i.id)][]
#     Time Behavior Status id i.Behavior  START   STOP
# 1: 29.48      TSp  POINT  2        FOR 28.461 31.298

Используемые данные

df <- fread('
Time    Behavior   Status
16.403  FOR    START
26.425  FOR    STOP
26.426  NI     START
28.460  NI     STOP
28.461  FOR    START
29.480  TSp    POINT
31.298  FOR    STOP
31.299  NI     START
33.297  NI     STOP
33.298  FOR    START
34.798  FOR    STOP
')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...