简体   繁体   中英

Putting rowwise counts of value occurences into new variables, how to do that in R with dplyr?

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!

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)

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM