1

I have a large dataframe (df) that looks like this:

structure(list(var1 = c(1, 2, 3, 4, 2, 3, 4, 3, 2), var2 = c(2, 
3, 4, 1, 2, 1, 1, 1, 3), var3 = c(4, 4, 2, 3, 3, 1, 1, 1, 4), 
    var4 = c(2, 2, 2, 2, 3, 2, 3, 4, 1), var5 = c(4, 4, 2, 3, 
    3, 1, 1, 1, 4)), .Names = c("var1", "var2", "var3", "var4", 
"var5"), row.names = c(NA, -9L), class = "data.frame")

  var1 var2 var3 var4 var5
1    1    2    4    2    4
2    2    3    4    2    4
3    3    4    2    2    2
4    4    1    3    2    3
5    2    2    3    3    3
6    3    1    1    2    1
7    4    1    1    3    1
8    3    1    1    4    1
9    2    3    4    1    4

Now I need to count the occurence of values rowwise and make new variables of the counts. This should be the result:

  var1 var2 var3 var4 var5 n_1 n_2 n_3 n_4
1    1    2    4    2    4   1   2   0   2
2    2    3    4    2    4   0   2   1   2
3    3    4    2    2    2   0   3   1   1
4    4    1    3    2    3   1   1   2   1
5    2    2    3    3    3   0   2   3   0
6    3    1    1    2    1   3   1   1   0
7    4    1    1    3    1   3   0   1   1
8    3    1    1    4    1   3   0   1   1
9    2    3    4    1    4   1   1   1   2

As you can see variable n_1 shows the rowcounts of the 1's, n_2 the row counts of the 2's, etc.

I tried some dplyr functions (because I like their speed), but haven't succeeded yet. I know this is definately ugly code :-), but my approache would be something in this way:

newdf <- mutate(rowwise(df, n_1 = sum(df==1))

Does anyone have an idea about how to deal with this problem? Many thanks in advance!

rdatasculptor
  • 8,112
  • 14
  • 56
  • 81

3 Answers3

3

This uses rowwise() and do() from dplyr but it's definitely ugly.

Not sure if there is something that can modify from this so that you get a data.frame output directly as shown over @ https://github.com/hadley/dplyr/releases.

interim_res <- df %>% 
                  rowwise() %>% 
                  do(out = sapply(min(df):max(df), function(i) sum(i==.)))

interim_res <- interim_res[[1]] %>% do.call(rbind,.) %>% as.data.frame(.)

Then to get intended result:

res <- cbind(df,interim_res)
npjc
  • 4,134
  • 1
  • 22
  • 34
2

This is a solution using base functions

dd <- t(apply(df, 1, function(x) table(factor(x, levels=1:4))))
colnames(dd) <- paste("n",1:4, sep="_")
cbind(df, dd)

Just use the table command across rows of your data.frame to get counts of each value from 1-4.

MrFlick
  • 195,160
  • 17
  • 277
  • 295
1

Here is an approach using qdapTools package:

library(qdapTools)

data.frame(dat, setNames(mtabulate(split(dat, id(dat))), paste0("n_", 1:4)))

##   var1 var2 var3 var4 var5 n_1 n_2 n_3 n_4
## 1    1    2    4    2    4   1   2   0   2
## 2    2    3    4    2    4   0   2   1   2
## 3    3    4    2    2    2   0   3   1   1
## 4    4    1    3    2    3   1   1   2   1
## 5    2    2    3    3    3   0   2   3   0
## 6    3    1    1    2    1   3   1   1   0
## 7    4    1    1    3    1   3   0   1   1
## 8    3    1    1    4    1   3   0   1   1
## 9    2    3    4    1    4   1   1   1   2
Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519