davids12
davids12

Reputation: 323

Flag first by-group in R data frame

I have a data frame which looks like this:

id  score
1   15
1   18
1   16
2   10
2   9
3   8
3   47
3   21

I'd like to identify a way to flag the first occurrence of id -- similar to first. and last. in SAS. I've tried the !duplicated function, but I need to actually append the "flag" column to my data frame since I'm running it through a loop later on. I'd like to get something like this:

id  score   first_ind
1   15      1
1   18      0
1   16      0
2   10      1
2   9       0
3   8       1
3   47      0
3   21      0

Upvotes: 7

Views: 3493

Answers (4)

Ben Bolker
Ben Bolker

Reputation: 226332

Using plyr:

library("plyr")
ddply(x,"id",transform,first=as.numeric(seq(length(score))==1))

or if you prefer dplyr:

x %>% group_by(id) %>% 
    mutate(first=c(1,rep(0,n-1)))

(although if you're operating completely in the plyr/dplyr framework you probably wouldn't need this flag variable anyway ...)

Upvotes: 3

talat
talat

Reputation: 70286

Another base R option:

df$first_ind <- ave(df$id, df$id, FUN = seq_along) == 1
df
#  id score first_ind
#1  1    15      TRUE
#2  1    18     FALSE
#3  1    16     FALSE
#4  2    10      TRUE
#5  2     9     FALSE
#6  3     8      TRUE
#7  3    47     FALSE
#8  3    21     FALSE

This also works in case of unsorted ids. If you want 1/0 instead of T/F you can easily wrap it in as.integer(.).

Upvotes: 2

Roman Luštrik
Roman Luštrik

Reputation: 70633

You can find the edges using diff.

x <- read.table(text = "id  score
1   15
1   18
1   16
2   10
2   9
3   8
3   47
3   21", header = TRUE)

x$first_id <- c(1, diff(x$id))
x

  id score first_id
1  1    15        1
2  1    18        0
3  1    16        0
4  2    10        1
5  2     9        0
6  3     8        1
7  3    47        0
8  3    21        0

Upvotes: 6

Jilber Urbina
Jilber Urbina

Reputation: 61164

> df$first_ind <- as.numeric(!duplicated(df$id))
> df
  id score first_ind
1  1    15         1
2  1    18         0
3  1    16         0
4  2    10         1
5  2     9         0
6  3     8         1
7  3    47         0
8  3    21         0

Upvotes: 17

Related Questions