So I have a dataframe with four columns: Course ID, User ID, Day (an integer), and Cumulative Points Received. What I want to do is, for each user-course pair, use lowess to smooth the cumulative points over all of the days of the course. The lowess function takes a vector, applies a smoothing algorithm, and then returns two vectors x and y… I’m only interested in the y vector.
My first idea was
aggregate(df$CumulativePointsReceived,
list(df$UserID, df$CourseID),
function(x) lowess(x)$y)
But that returns a basically unusable dataframe where the third column is a list of those vectors. What I want is a dataframe exactly like the input df, but with a column of the smoothed point values for each user-course-day. I’m sure there’s a non-for-loop way to do this, but I can’t seem to think about it the right way. Thanks in advance…
Here’s the dput of the first user-course pair in the original df. I would have put more, but it gets stupidly large with 110 days for each user-course.
structure(list(CourseID = c(6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L, 6567146L,
6567146L), UserID = c(4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L, 4759679L,
4759679L), DayInCourse = 1:110, CumulativePointsReceived = c(0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 47, 47, 47, 47, 47, 47, 47,
47, 47, 47, 47, 47, 107, 107, 107, 107, 107, 107, 107, 107, 107,
107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107,
107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, 107)), .Names = c("CourseID",
"UserID", "DayInCourse", "CumulativePointsReceived"), row.names = c(46085L,
46118L, 46120L, 46133L, 46102L, 46086L, 46182L, 46184L, 46159L,
46139L, 46088L, 46090L, 46144L, 46161L, 46187L, 46113L, 46177L,
46193L, 46151L, 46143L, 46126L, 46121L, 46104L, 46170L, 46128L,
46131L, 46167L, 46098L, 46127L, 46178L, 46101L, 46129L, 46152L,
46175L, 46093L, 46122L, 46096L, 46136L, 46106L, 46116L, 46148L,
46173L, 46189L, 46117L, 46172L, 46162L, 46164L, 46108L, 46091L,
46112L, 46135L, 46181L, 46190L, 46171L, 46169L, 46100L, 46141L,
46103L, 46168L, 46110L, 46107L, 46089L, 46154L, 46165L, 46125L,
46163L, 46147L, 46166L, 46183L, 46160L, 46150L, 46097L, 46115L,
46157L, 46194L, 46138L, 46188L, 46153L, 46155L, 46179L, 46180L,
46191L, 46095L, 46176L, 46111L, 46105L, 46142L, 46087L, 46109L,
46158L, 46145L, 46114L, 46192L, 46140L, 46146L, 46174L, 46094L,
46124L, 46149L, 46119L, 46186L, 46130L, 46134L, 46156L, 46185L,
46099L, 46123L, 46137L, 46132L, 46092L), class = "data.frame")
You can do this with base R functions. E.g.
which returns:
We can modify this approach to include the transformation step:
As you only supplied one course/user combo, the result is a list with just one component. In a real world example, the list would have more components. In such circumstances do
The reason the
aggregate()step failed is that you are passinglowess()a data frame and it expects two vectorsxandy. I don’t think this is the right approach here. Doing the split-apply-combine by hand would be the way to go unless you want to learn plyr.