2

したがって、コース ID、ユーザー ID、日 (整数)、累積ポイントの 4 つの列を持つデータフレームがあります。私がやりたいことは、ユーザーとコースのペアごとlowessに、コースのすべての日にわたって累積ポイントを平滑化するために使用することです。このlowess関数はベクトルを受け取り、平滑化アルゴリズムを適用してから、2 つのベクトルxを返します。yそのベクトルにのみ関心がありyます。

私の最初のアイデアは

aggregate(df$CumulativePointsReceived, 
          list(df$UserID, df$CourseID),
          function(x) lowess(x)$y)

しかし、それは基本的に使用できないデータフレームを返します.3列目はそれらのベクトルのリストです. 私が欲しいのは、入力 df とまったく同じデータフレームですが、ユーザーコース日ごとに平滑化されたポイント値の列があります。これを行うためのループ以外の方法があると確信していますが、正しい方法で考えることができないようです。前もって感謝します...

これは、元の df の最初のユーザーとコースのペアの dput です。もっと入れてもよかったのですが、ユーザーコースごとに 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")
4

2 に答える 2

3

これは、ベース R 関数で行うことができます。例えば

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

コースとユーザーの組み合わせを 1 つだけ指定したため、結果はコンポーネントが 1 つだけのリストになります。実際の例では、リストにはさらに多くのコンポーネントがあります。そのような状況では

final <- do.call(rbind, out)

ステップが失敗した理由は、データ フレームaggregate()を渡しlowess()ており、2 つのベクトルxy. これはここでの正しいアプローチではないと思います。plyrを学びたくない場合は、手動で分割 - 適用 - 結合を行うのがよいでしょう。

于 2012-11-02T21:42:17.253 に答える
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は、見苦しいインデックスを作成せずにデータフレームに新しい列を追加するための便利な関数です。次の2つの同一の呼び出しを比較します。

Orange$score <- Orange$age * Orange$circumference^2

Orange <- transform(Orange, score = age * circumference^2)

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

次に、結果を結合します。

于 2012-11-02T21:12:31.567 に答える