Meesha
Meesha

Reputation: 821

Numbering in R based on a column value

Name Grade
John   C
John   C+
John   C
John   B
John   A
John   A+
Kat    B
Kat    C
Kat    B

I want to add a new column, Months , starting from 3 and then continue with its multiples. The rows are all sorted. The output would look something like

Name Grade Months
John   C     3
John   C+    6
John   C     9
John   B     12
John   A     15
John   A+    18
Kat    B     3
Kat    C     6
Kat    B     9

Rcode

name <- df$Name[1]
count <- 0
for (i in 1:length(df[,1])){
    if (name!=df$Name[i]){
        count <- 0
        name <- df$Name[i]
     }
    df$Months[i] <- count
    count <- count + 3
}

Can I do it without a loop?

Upvotes: 2

Views: 310

Answers (4)

mpalanco
mpalanco

Reputation: 13570

Another alternative, very similar to Psidom's answer, using seq with ave, and 1:nrow(df) instead of df$Nameto avoid a character vector as an output.

ave(1:nrow(df), df$Name, FUN = seq)*3
# [1]  3  6  9 12 15 18  3  6  9

Upvotes: 1

akrun
akrun

Reputation: 886948

Using data.table, convert the 'data.frame' to 'data.table' (setDT(df1)), grouped by 'Name', assign (:=) the product of 3 with sequence of rows to 'Months'.

library(data.table)
setDT(df1)[, Months := 3* seq_len(.N) , by = Name]
df1
#   Name Grade Months
#1: John     C      3
#2: John    C+      6
#3: John     C      9
#4: John     B     12
#5: John     A     15
#6: John    A+     18
#7:  Kat     B      3
#8:  Kat     C      6
#9:  Kat     B      9

Upvotes: 1

akuiper
akuiper

Reputation: 214927

You can do a cumulative sum on a vector of 3 grouped by Name:

with(df, ave(rep(3, length(Name)), Name, FUN = cumsum))
# [1]  3  6  9 12 15 18  3  6  9

Upvotes: 3

user2100721
user2100721

Reputation: 3587

Try this

library(dplyr)
df1 %>% group_by(Name) %>% mutate(Months=3*seq(n()))

Upvotes: 5

Related Questions