Как выбрать первую и последнюю строки для каждого уникального id
в следующем фрейме данных?
tmp <- structure(list(id = c(15L, 15L, 15L, 15L, 21L, 21L, 22L, 22L,
22L, 23L, 23L, 23L, 24L, 24L, 24L, 24L), d = c(1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), gr = c(2L, 1L,
1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 2L), mm = c(3.4,
4.9, 4.4, 5.5, 4, 3.8, 4, 4.9, 4.6, 2.7, 4, 3, 3, 2, 4, 2), area = c(1L,
2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 2L, 3L)), .Names = c("id",
"d", "gr", "mm", "area"), class = "data.frame", row.names = c(NA,
-16L))
tmp
#> id d gr mm area
#> 1 15 1 2 3.4 1
#> 2 15 1 1 4.9 2
#> 3 15 1 1 4.4 1
#> 4 15 1 1 5.5 2
#> 5 21 1 1 4.0 2
#> 6 21 1 2 3.8 2
#> 7 22 1 1 4.0 2
#> 8 22 1 1 4.9 2
#> 9 22 1 2 4.6 2
#> 10 23 1 1 2.7 2
#> 11 23 1 1 4.0 2
#> 12 23 1 2 3.0 2
#> 13 24 1 1 3.0 2
#> 14 24 1 1 2.0 3
#> 15 24 1 1 4.0 2
#> 16 24 1 2 2.0 3
Мы можем также использовать ave
в основе R. Для каждого id
мы выбираем первую и последнюю строку.
tmp[as.logical(with(tmp,ave(d, id, FUN = function(x)
seq_along(x) %in% c(1L, length(x))))), ]
# id d gr mm area
#1 15 1 2 3.4 1
#4 15 1 1 5.5 2
#5 21 1 1 4.0 2
#6 21 1 2 3.8 2
#7 22 1 1 4.0 2
#9 22 1 2 4.6 2
#10 23 1 1 2.7 2
#12 23 1 2 3.0 2
#13 24 1 1 3.0 2
#16 24 1 2 2.0 3
А более короткая версия использовала бы range
, range
возвраты минимальное и максимальное значение от вектора
tmp[as.logical(with(tmp, ave(seq_along(d), id,FUN = function(x) x %in% range(x)))),]
<час> , Мы можем также использовать split
+ sapply
подход с [1 110]
tmp[c(sapply(split(seq_len(nrow(tmp)), tmp$id), range)), ]
<час> Используя [1 111], хотя я предпочел бы slice
подход, показанный @rcs, но здесь являюсь одним способом использовать filter
, который подобен [1 114] решение, где мы создаем логический вектор путем сравнения row_number()
library(dplyr)
tmp %>% group_by(id) %>% filter(row_number() %in% c(1L, n()))
Во всем вышеупомянутом решении, мы можем также использовать match
вместо [1 117], поскольку %in%
просто обертка приблизительно [1 119].