Как создать новый столбец в кадре данных A на основе нескольких условий в кадре данных B - PullRequest
0 голосов
/ 28 марта 2020

Полагаю, я не вижу леса сквозь деревья ... Итак, я хотел бы попросить о помощи.

Данные: для вывода dput () см. На конец вопроса.

-Dataframe dfA with the columns: ID; ts. ts being POSIXct

-Dataframe dfB with the columns: ID; start; end; state_id. ID (corresponding to the ID in dfA), start (POSIXct), end (POSIXct), state_id.

Задача:

Я хотел бы создать новый столбец в dfA со значениями 1/0 основанный на условии. Условие в словах: если идентификатор в dfA и dfB совпадает, и если временная метка dfA $ ts находится между или равна dfB $ start и dfB $ end, то значение 1 должно быть записано в dfA $ x, в противном случае a 0 должен быть там.

Я думаю, что код должен выглядеть примерно так:

dfA$x <- iflese( dfA$ID == dfB$ID & dfA$ts >= dfB$start & dfA$ts <= dfB$end, 1, 0)

Спасибо за помощь уже заранее.

dput ( dfB):

структура (список (ID = c (1151L, 1151L, 1150L, ​​1150L, ​​1150L, ​​1150L, ​​1152L, 1152L, 1152L, 1345L), start = структура ( c (1443142500, 1443144600, 1442934900, 1442942400, 1442944800, 1442946300, 1443103500, 1443132600, 1443137400, 1443389400), класс = c ("POSIXct", "POSIXt")), конец = структура (

(144) , 1443145500, 1442935500, 1442943000, 1442945400, 1442950200, 1443106200, 1443134100, 1443140100, 1443392400), класс = c ("POSIXct", "POSIXt")), state_id = c (1L, 2L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 1L)), row.names = c (NA, -10L), class = "data.frame")

dput ( dfA):

*1034*

структура (список (ID = c (1151L, 1151L, 1151L, 1151L, 1151L, 1151L, 1151L, 1151L, 1151L, 1151L, 1151L, 1151L, 1151L) , 1151L, 1151L, 1151L, 1151L, 1151L, 1151L, 1151L, 1150L , 1150L, ​​1150L, ​​1150L, ​​1150L, ​​1150L, ​​1150L, ​​1150L, ​​1150L, ​​1150L, ​​1150L, ​​1150L, ​​1152L, 1152L, 1152L, 1152L, 1152L, 1152L, 1152L, 1152L, 1152L, 1152L, 1152L, 1152L, 1152L , 1152L, 1152L, 1345L, 1345L, 1345L, 1345L, 1345L, 1345L, 1345L, 1345L, 1345L, 1345L), ts = структура (c (1443141300, 1443141600, 1443141900, 1443142200, 1443142500, 144314310000, 144314310000 1443143700, 1443144000, 1443144300, 1443144600, 1443144900, 1443145200, 1443145500, 1443145800, 1443146100, 1443146400, 1443146700, 1443147000, 1442934900, 1442935200, 1442935500, 1442935800, 1442936100, 1442936400, 1442936700, 1442937000, 1442937300, 1442937600, 1442937900, 1442938200, 1443103500, 1443103800, 1443104100, 1443104400, 1443104700, 1443105000, 1443105300, 1443105600, 1443105900, 1443106200, 1443106500, 1443106800, 1443107100, 1443107400, 1443107700, 1443107700, 1443100000, 14433000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 или830000000000000000000000000000000000000000000000000000000000 как бор в Эпоха 1443103800, 1443103800, 1443104400 , класс = c ("поз. IXct "," POSIXt "))), row.names = c (NA, -58L), class =" data.frame ")

Ответы [ 3 ]

1 голос
/ 28 марта 2020

Вы можете использовать data.table, условную замену на :=:

data.table::setDT(dfA)
dfA[,value := 0L]
dfA[(get('ID') == dfB$ID) & (get('ts') >= dfB$start) & (get('ts') <= dfB$end), value := 1L]

Обратите внимание, что я помещаю имена столбцов из dfA в вызов get, чтобы избежать путаницы с dfB столбцами.

В этой ситуации dfA и dfB должны иметь одинаковое количество строк. Если это не так, используйте merge на основе ID столбца

0 голосов
/ 28 марта 2020

Это обновление неэквивалентного объединения:

library(data.table)

setDT(dfA); setDT(dfB)

dfA[dfB, match := 1, on=.(ID=ID, ts>=start, ts<=end)][, match:=ifelse(is.na(match), 0, match)]

      ID                  ts match
 1: 1151 2015-09-25 07:35:00     0
 2: 1151 2015-09-25 07:40:00     0
 3: 1151 2015-09-25 07:45:00     0
 4: 1151 2015-09-25 07:50:00     0
 5: 1151 2015-09-25 07:55:00     1
 6: 1151 2015-09-25 08:00:00     1
 7: 1151 2015-09-25 08:05:00     1
 8: 1151 2015-09-25 08:10:00     1
 9: 1151 2015-09-25 08:15:00     0
10: 1151 2015-09-25 08:20:00     0
...
0 голосов
/ 28 марта 2020

Мы можем left_join dfA и dfB на 'ID', group_by каждый ID и ts и проверить, находится ли значение any в диапазоне для этой группы.

library(dplyr)

dfA %>%
  left_join(dfB, by = 'ID') %>%
  group_by(ID, ts) %>% 
  summarise(x = +any(ts >= start & ts <= end))


#      ID ts                      x
#   <int> <dttm>              <int>
# 1  1150 2015-09-22 23:15:00     1
# 2  1150 2015-09-22 23:20:00     1
# 3  1150 2015-09-22 23:25:00     1
# 4  1150 2015-09-22 23:30:00     0
# 5  1150 2015-09-22 23:35:00     0
# 6  1150 2015-09-22 23:40:00     0
# 7  1150 2015-09-22 23:45:00     0
# 8  1150 2015-09-22 23:50:00     0
# 9  1150 2015-09-22 23:55:00     0
#10  1150 2015-09-23 00:00:00     0
# … with 48 more rows
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...