Reputation: 13
I need to build a function which will receive a vector and a factor and will return a list containing the division of the vector by factor levels. Meaning it should take the levels from the factor, and for each level, create an item, or element, in the list containing the subset of the vector that is equivalent to the level in the factor. The level name should be used to name the list item. It is a vector and a factor in a data frame.
Right now this is what I have but it only returns list on NA:
mk_factor_list <- function(x,f) {
{
{if (length(x) == length(f) )
{print(":)")}
else { stop(print("f and x don't have the same length"))}
listf <- rep (NA, length(levels(f)))
for (i in levels (f))
listf[i] <-x[i]
}}
return (listf)
}
Upvotes: 0
Views: 31
Reputation: 145895
A few comments on your attempt:
print(':)')
can be nice for debugging, but if you intend to leave it in the function when you're done, use message
not print
so users can disable it if they want.print()
inside stop()
. Just use stop("f and x ...")
.listf
is a vector, not a list
when you define it as listf <- rep (NA, length(levels(f)))
. Make it a list
by using listf = list()
instead.'a'
and 'b
'. When you do for (i in levels (f))
, that means i
will first be 'a'
and then it will be 'b'
. TSo when you assign listf[i] <- x[i]
what R sees is listf['a'] <- x['a']
. listf['a']
is bad only because you should be using double brackets for a single list item: listf[['a']] <- ...
is needed. x['a']
doesn't make any sense. You want the elements of x
corresponding to which elements of f
are 'a'
, so use x[which(f == i)]
.Putting those together, you should be able to get a working answer. But if you want to see a really pro way of doing this, type split.default
into your console and see R core version.
Based on your comment, here's a working version. Most of what I did to get from your comment was delete lines (why all the extra {
at the beginning?) and replace with code from my bullets above.
mk_factor_list <- function(x, f) {
if (length(x) != length(f)) {
stop("f and x don't have the same length")
}
listf = list()
for (i in levels (f)) {
listf[[i]] <- x[which(f == i)]
}
return(listf)
}
mk_factor_list(x = 1:5, f = factor(c('a', 'b', 'a', 'b', 'c'))
# $a
# [1] 1 3
#
# $b
# [1] 2 4
#
# $c
# [1] 5
Upvotes: 1