I have a loop which I would like to get rid of, I just can't quite see how too. Say I have a dataframe:
tmp = data.frame(Gender = rep(c("Male", "Female"), each = 6),
Ethnicity = rep(c("White", "Asian", "Other"), 4),
Score = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12))
I then want to calculate the mean for each level in both the Gender and Ethnicity columns which would give:
$Female
[1] 9.5
$Male
[1] 3.5
$Asian
[1] 6.5
$Other
[1] 7.5
$White
[1] 5.5
This is easy enough to do, but I don't want to use loops - I'm going for speed. So I currently have the following:
for(i in c("Gender", "Ethnicity"))
print(lapply(split(tmp$Score, tmp[, i]), function(x) mean(x)))
Obviously, this uses a loop and is where I am stuck.
There may well be a function which already does this kind of thing that I am unaware of. I have looked at aggregate but I don't think that's what I want.
You can sapply() over the names of tmp, except for Score, and then use by() (or aggregate()):
> sapply(setdiff(names(tmp),"Score"),function(xx)by(tmp$Score,tmp[,xx],mean))
$Gender
tmp[, xx]: Female
[1] 9.5
------------------------------------------------------------
tmp[, xx]: Male
[1] 3.5
$Ethnicity
tmp[, xx]: Asian
[1] 6.5
------------------------------------------------------------
tmp[, xx]: Other
[1] 7.5
------------------------------------------------------------
tmp[, xx]: White
[1] 5.5
However, this internally uses a loop, so it won't speed up a lot...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With