Update (for first reading)
If you are really only interested in row indexes, it might be useful to use the direct use of split and range . The following assumes that the growth names in your dataset are sequentially numbered, but adaptation is likely to be possible as well.
irisFirstLast <- sapply(split(iris, iris$Species), function(x) range(as.numeric(rownames(x)))) irisFirstLast
If you work with named strings, the general approach is the same, but you must specify the range yourself. Here's a generic pattern:
datasetFirstLast <- sapply(split(dataset, dataset$groupingvariable), function(x) c(rownames(x)[1], rownames(x)[length(rownames(x))]))
Initial Answer (edited)
If you are interested in extracting rows and not in line number for other purposes, you can also examine data.table . Here are some examples:
library(data.table) DT <- data.table(iris, key="Species") DT[J(unique(Species)), mult = "first"] # Species Sepal.Length Sepal.Width Petal.Length Petal.Width # 1: setosa 5.1 3.5 1.4 0.2 # 2: versicolor 7.0 3.2 4.7 1.4 # 3: virginica 6.3 3.3 6.0 2.5 DT[J(unique(Species)), mult = "last"] # Species Sepal.Length Sepal.Width Petal.Length Petal.Width # 1: setosa 5.0 3.3 1.4 0.2 # 2: versicolor 5.7 2.8 4.1 1.3 # 3: virginica 5.9 3.0 5.1 1.8 DT[, .SD[c(1,.N)], by=Species] # Species Sepal.Length Sepal.Width Petal.Length Petal.Width # 1: setosa 5.1 3.5 1.4 0.2 # 2: setosa 5.0 3.3 1.4 0.2 # 3: versicolor 7.0 3.2 4.7 1.4 # 4: versicolor 5.7 2.8 4.1 1.3 # 5: virginica 6.3 3.3 6.0 2.5 # 6: virginica 5.9 3.0 5.1 1.8
This last approach is quite convenient. For example, if you need the first three lines and the last three lines of each group, you can use: DT[, .SD[c(1:3, (.N-2):.N)], by=Species] (Only for Help: .N represents the number of cases for each group.
Other useful approaches include:
DT[, tail(.SD, 2), by = Species]