Creating two columns of cumulative sum based on the categories of one column

98 Views Asked by At

I like to create two columns with cumulative frequency of "A" and "B" in the assignment columns.

df = data.frame(id = 1:10, assignment= c("B","A","B","B","B","A","B","B","A","B"))

            id assignment
        1   1          B
        2   2          A
        3   3          B
        4   4          B
        5   5          B
        6   6          A
        7   7          B
        8   8          B
        9   9          A
        10 10          B

The resulting table would have this format

            id  assignment  A   B
        1   1   B           0   1
        2   2   A           1   1
        3   3   B           1   2
        4   4   B           1   3
        5   5   B           1   4
        6   6   A           2   4
        7   7   B           2   5
        8   8   B           2   6
        9   9   A           3   6
       10   10  B           3   7

How to generalize the codes for more than 2 categories (say for "A","B",C")? Thanks

3

There are 3 best solutions below

2
On

Use lapply over unique values in assignment to create new columns.

vals <- sort(unique(df$assignment))
df[vals] <- lapply(vals, function(x) cumsum(df$assignment == x))
df

#   id assignment A B
#1   1          B 0 1
#2   2          A 1 1
#3   3          B 1 2
#4   4          B 1 3
#5   5          B 1 4
#6   6          A 2 4
#7   7          B 2 5
#8   8          B 2 6
#9   9          A 3 6
#10 10          B 3 7
1
On

We can use model.matrix with colCumsums

library(matrixStats)
cbind(df, colCumsums(model.matrix(~ assignment - 1, df[-1])))
0
On

A base R option

transform(
  df,
  A = cumsum(assignment == "A"),
  B = cumsum(assignment == "B")
)

gives

   id assignment A B
1   1          B 0 1
2   2          A 1 1
3   3          B 1 2
4   4          B 1 3
5   5          B 1 4
6   6          A 2 4
7   7          B 2 5
8   8          B 2 6
9   9          A 3 6
10 10          B 3 7