所以我有一个包含四列的数据框:课程ID,用户ID,日(整数)和收到的累积点数。我想要做的是,对于每个用户课程对,使用lowess
来平滑课程所有日子的累积分数。 lowess
函数采用向量,应用平滑算法,然后返回两个向量x
和y
...我只对y
向量感兴趣。< / p>
我的第一个想法是
aggregate(df$CumulativePointsReceived,
list(df$UserID, df$CourseID),
function(x) lowess(x)$y)
但是返回一个基本上无法使用的数据帧,其中第三列是这些向量的列表。我想要的是一个与输入df完全相同的数据帧,但是每个用户课程日都有一列平滑点值。我确信有一种非循环方式可以做到这一点,但我似乎无法以正确的方式思考它。提前谢谢......
这是原始df中第一个用户课程对的输入。我会增加更多,但是每个用户课程都需要110天才会变得非常大。
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")
答案 0 :(得分:3)
您可以使用基本R功能执行此操作。 E.g。
lapply(split(df, list(df$UserID, df$CourseID)),
function(x) with(x, lowess(DayInCourse, CumulativePointsReceived))$y)
返回:
$`4759679.6567146`
[1] 40.92152 42.50447 44.08898 45.67481 47.26167 48.84919
[7] 50.43697 52.02450 53.61120 55.19639 56.77928 58.35896
[13] 59.93435 61.50424 63.06724 64.62175 66.16596 67.69780
[19] 69.21547 70.71909 72.20948 73.68773 75.15522 76.61367
[25] 78.06516 79.51217 80.95767 82.40508 83.85843 85.32230
[31] 86.80193 88.30315 89.83235 91.39619 93.00115 94.65248
[37] 96.35240 98.75650 100.73124 102.31467 103.55841 104.51780
[43] 105.24556 105.78855 106.18658 106.47246 106.67275 106.80862
[49] 106.89685 106.95067 106.98051 106.99458 106.99936 107.00000
[55] 107.00000 107.00000 107.00000 107.00000 107.00000 107.00000
[61] 107.00000 107.00000 107.00000 107.00000 107.00000 107.00000
[67] 107.00000 107.00000 107.00000 107.00000 107.00000 107.00000
[73] 107.00000 107.00000 107.00000 107.00000 107.00000 107.00000
[79] 107.00000 107.00000 107.00000 107.00000 107.00000 107.00000
[85] 107.00000 107.00000 107.00000 107.00000 107.00000 107.00000
[91] 107.00000 107.00000 107.00000 107.00000 107.00000 107.00000
[97] 107.00000 107.00000 107.00000 107.00000 107.00000 107.00000
[103] 107.00000 107.00000 107.00000 107.00000 107.00000 107.00000
[109] 107.00000 107.00000
我们可以修改此方法以包含转换步骤:
out <- lapply(split(df, list(df$UserID, df$CourseID)),
function(x) transform(x, smooth = lowess(DayInCourse,
CumulativePointsReceived)$y))
> head(out[[1]])
CourseID UserID DayInCourse CumulativePointsReceived smooth
46085 6567146 4759679 1 0 40.92152
46118 6567146 4759679 2 0 42.50447
46120 6567146 4759679 3 0 44.08898
46133 6567146 4759679 4 0 45.67481
46102 6567146 4759679 5 0 47.26167
46086 6567146 4759679 6 0 48.84919
由于您只提供了一个课程/用户组合,因此结果是一个只包含一个组件的列表。在现实世界的示例中,列表将包含更多组件。在这种情况下做
final <- do.call(rbind, out)
aggregate()
步失败的原因是您要传递lowess()
数据框,并且它需要两个向量x
和y
。我不认为这是正确的做法。除非您想学习 plyr ,否则手动进行拆分 - 应用组合将是您的选择。
答案 1 :(得分:1)
我认为使用plyr
:
df <- ddply(df, .(CourseID, UserID), transform,
smoothed = lowess(DayInCourse, CumulativePointsReceived)$y)
plyr
的一般哲学是“分裂 - 应用 - 结合”。 ddply
函数的语法(它接受一个数据框并返回一个数据框 - 还有其他函数用于数组或列表)
ddply(dataframe, field-list, function, function-args)
然后,该函数将数据帧拆分为行块,其中field-list
中指定的所有字段值都相同。然后,它接受每个块并应用function
以及任何其他function-args
,然后将这些函数调用的结果合并到一个数据框中。
以下是一个例子:
ddply(mtcars, "cyl", colMeans)
在这种情况下,colMeans是一个函数,它取数据框中每列的平均值,因此对cyl
的每个值分别采用均值。
您也可以指定自己的功能:
ddply(mtcars, "cyl", function(df) c(hp.mean=mean(df$hp), hp.sd=sd(df$hp)))
现在解释transform
。 transform
是一个方便的函数,用于向数据框添加新列而不会出现难看的索引。比较以下两个相同的电话:
Orange$score <- Orange$age * Orange$circumference^2
Orange <- transform(Orange, score = age * circumference^2)
第二个版本更易于阅读且不易出错。从这个例子中可以看出,transform
的语法是
tranform(dataframe, myname2 = some-value, myname2 = some-other-value)
等等。
当用作transform
中的函数调用时, plyr
真正自成一体。在上面给出的示例中,smoothed = lowess(DayInCourse, CumulativePointsReceived)$y)
只是传递给转换的附加参数,因此对于拆分数据框中的每个块x
,ddply
将transform
应用为
transform(x, smoothed = lowess(DayInCourse, CumulativePointsReceived)$y))
然后结合结果。