#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) })