Выбор коэффициентов на основе расстояния между двумя строками в столбце

#r #dplyr

#r #dplyr

Вопрос:

Я пытаюсь выбрать идентификаторы из приведенного ниже фрейма данных, которые имеют значения 2 в столбце num, которые находятся на расстоянии не менее 2 строк друг от друга. Другими словами, учитывая следующий фрейм данных:

 df2 <- data.frame(id=c(1,1,1,1,1,2,2,2,2,3,3,3,3,3,3),
                 num=c(1,2,1,1,2,1,1,1,2,2,1,1,1,2,2))
df2$id <- as.factor(df2$id)
  

Как я могу выбрать переменные идентификатора таким образом, чтобы значения 2 разделялись хотя бы одной строкой?

Результатом процедуры, которую я ищу, будет выбор идентификатора 1, поскольку значения 2 разделены по крайней мере одной строкой (2 строки в этом примере). Спасибо.

Кроме того, приведенное ниже решение, похоже, не работает в следующем примере:

 df <- data.frame(
  id=c(1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4),
  num=c(1,2,1, 1,2,2, 1,1,1,2,2,1, 1,1,1,2,2,1, 1,2,1,2,2,2)
)     
df$id<-as.factor(df$id) 
  

Опять же, результатом должен быть только идентификатор 1. Я просто хочу найти для каждого идентификатора любые экземпляры, в которых число 2 разделено еще на 2 одной или несколькими строками.

Комментарии:

1. Каков ожидаемый результат для второго примера?

2. то же, что и в первом случае. Я просто хочу найти для каждого идентификатора любые экземпляры, в которых число 2 разделено еще на 2 одной или несколькими строками.

3. ОК. Как правило, лучше с самого начала четко указать такое требование. Я прочитал это как «все значения» вместо «любые значения», поскольку вы его не указали. Я думаю, что измененный ответ может сработать.

Ответ №1:

data.table Я бы использовал пакет data.table:

 library(data.table)
setDT(df)

df[num == 2, .N > 1L amp;amp; any(diff(.I) > 2L), by=id]

   id    V1
1:  1  TRUE
2:  2 FALSE
3:  3 FALSE
  

Как это работает: синтаксис DT[i, j, by]

  • i подмножества строк
  • затем by группирует оставшиеся строки
  • затем j вычисляется

Внутри j у нас есть .I , который хранит номер строки для удобства; и .N количество строк в by группе. Итак, чтобы извлечь идентификаторы V1 == TRUE , мы можем сделать res[V1 == TRUE, id] . С другой стороны, вся операция может быть связана следующим образом

 df[num == 2, .N > 1L amp;amp; any(diff(.I) > 2L), by=id][V1 == TRUE, id]

[1] 1
Levels: 1 2 3
  

base или dplyr (почти) аналог в базе R равен

 sapply(split(df$num == 2, df$id), function(x){
  w = which(x)
  length(w) > 1L amp;amp; any(diff(w) > 2L) 
})

    1     2     3 
 TRUE FALSE FALSE 
  

Последнее также работает в dplyr

 library(dplyr)

df %>% group_by(id) %>% summarise(x = {
  w = which(num == 2)
  length(w) > 1L amp;amp; any(diff(w) > 2L) 
})

# A tibble: 3 x 2
      id     x
  <fctr> <lgl>
1      1  TRUE
2      2 FALSE
3      3 FALSE
  

Комментарии:

1. Можно ли обобщить ваше решение, если фрейм данных имеет следующий вид: df<-data.frame(id=c(1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4), num= c(1,2,1,1,2,2, 1,1,1,2,2,1, 1,1,1,2,2,1, 1,2,1,2,2,2)) df$id<-как.factor(df$id)

2. @user85727 Не могли бы вы привести это в качестве другого примера в вопросе? Трудно скопировать-вставить из вашего комментария.

3. не уверен, что any (diff (w)> 2L) работает вообще, может потребоваться any (diff (w)> 1L)

4. @user85727 Если он переключен на 1, то идентификатор 4 также идентифицируется как true, но вы сказали, что он должен быть false, поэтому я вывел другой порог. Как правило, если вы очень четко указываете желаемый результат и правила, стоящие за ним, в вопросе, такого рода путаницы часто можно избежать.

5. ваш код выдает ошибку: недопустимая (do_set) левая сторона для назначения: > библиотека (dplyr) > > df %>% group_by(id) %>% summarise(x = { w = which(num == 2) длина (w) > 1L amp;amp;любой (разница (w)> 2L) })