Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing a loop in lapply

Tags:

r

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.

like image 358
nathaneastwood Avatar asked Sep 03 '26 05:09

nathaneastwood


1 Answers

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...

like image 180
Stephan Kolassa Avatar answered Sep 04 '26 18:09

Stephan Kolassa



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!