Reputation: 606
Usually people want to calculate mode from each question, but in my case I need to calculate the mode for each respondente, across all questions.
This is how my data looks like:
> head(TiposMotivA)
Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 Q11 Q12 Q13 Q14 Q15 Q16 Q17 Q18 Q19 Q20 Q21
1 5 4 4 4 6 6 7 6 4 6 6 6 4 4 4 4 6 7 4 4 6
2 5 4 4 5 5 5 5 5 5 5 7 5 4 3 1 6 6 5 6 7 7
3 4 5 4 4 5 4 5 4 5 4 5 4 5 4 5 4 5 4 5 4 5
4 5 5 7 7 4 6 6 6 7 7 6 7 7 6 6 7 4 7 6 6 7
5 6 1 7 6 7 7 7 7 7 7 6 7 2 2 3 6 3 7 7 7 7
6 4 4 3 3 4 5 4 3 4 7 6 6 4 4 6 4 5 7 6 6 7
This Solution was the best I found so far:
apply(TiposMotivA, 1, Compose(table,
function(i) i==max(i),
which,
names,
function(i) paste0(i, collapse='/')
)
)
It was provided by Matthew Lundberg here: Select majority number of each row in matrix using r
It produced this:
[1] "4" "5" "4" "7" "7" "4" "7" "6" "7" "7" "7" "7" "7"
[14] "5/6" "7" "6" "7" "6" "7" "7" "7" "7" "7" "7" "7" "7"
[27] "7" "7" "7" "5" "2" "7" "7" "7" "7" "7" "6" "6" "7"
[40] "4/7" "3" "4" "7" "5/7" "6" "7" "7" "6" "7" "6" "7" "7"
[53] "7" "6" "7" "7" "5/7" "7" "7" "7" "7" "7"
>
My problem, which might seem basic for some, is driving me nuts. I need only one mode per row, so when there are two, I need simply the first. I have tried to use split() without success.
So, what I need is to get mode for each row, as presented above, but having only the first mode when there are two.
Something like this:
[1] "4" "5" "4" "7" "7" "4" "7" "6" "7" "7" "7" "7" "7"
[14] "5" "7" "6" "7" "6" "7" "7" "7" "7" "7" "7" "7" "7"
[27] "7" "7" "7" "5" "2" "7" "7" "7" "7" "7" "6" "6" "7"
[40] "4" "3" "4" "7" "5" "6" "7" "7" "6" "7" "6" "7" "7"
[53] "7" "6" "7" "7" "5" "7" "7" "7" "7" "7"
>
Any help is gonna be pretty appreciated.
Upvotes: 2
Views: 2734
Reputation: 269371
which.max
can be used to find the position of the first maximum:
apply(TiposMotivA, 1, function(x) { tab <- table(x); names(tab)[which.max(tab)] } )
giving:
1 2 3 4 5 6
"4" "5" "4" "7" "7" "4"
No packages are needed.
Upvotes: 4
Reputation: 886938
Another option would be to change from "wide" to "long" format using melt
, convert the "data.frame" to "data.table" with setDT
, get the count (.N
), grouped by variables ("Var1", "value"), find the index of maximum value of "N" (which.max(N)
) and use that to get the "value", grouped by "Var1"
library(reshape2)
library(data.table)
setDT(melt(as.matrix(TiposMotivA)))[, .N ,.(Var1, value)][,
value[which.max(N)], Var1]$V1
#[1] 4 5 4 7 7 4
Or you could use base R
functions (modified from the link)
apply(TiposMotivA, 1, function(idx) which.max(tabulate(idx)))
#1 2 3 4 5 6
#4 5 4 7 7 4
Upvotes: 2
Reputation: 1363
The solution you found will paste together all of the modes, we can modify it a little bit to just give you the first mode:
apply(TiposMotivA, 1, Compose(table,
function(i) i==max(i),
which,
names,
function(i) i[1]
)
)
Upvotes: 2