2

「ユーザー」ごとに X 行を含むデータフレームがあります。X はユーザー間で一定ではありません。私がやりたいことは、乱数を生成して新しい列を埋めることができるようにすることですが、「ユーザー」ごとに、乱数はそのユーザーに対応するすべての行で同じです。たとえば、データは次のようになります。

user    feature1     feature2
 1        "A"           "B"
 1        "L"           "L"
 1        "Q"           "B"
 1        "D"           "M"
 1        "D"           "M"
 1        "P"           "E"
 2        "A"           "B"
 2        "R"           "P"
 2        "A"           "F"
 3        "X"           "U"
...       ...           ...

次のような新しい列を生成したいと思います。

user    feature1     feature2   new_rand
 1        "A"           "B"       0.183
 1        "L"           "L"       0.183
 1        "Q"           "B"       0.183
 1        "D"           "M"       0.183
 1        "D"           "M"       0.183
 1        "P"           "E"       0.183
 2        "A"           "B"       0.971
 2        "R"           "P"       0.971
 2        "A"           "F"       0.971
 3        "X"           "U"       0.302
...       ...           ...

私が行った最初のアプローチは基本的に使用することでしたs <- split(df, df$user)が、データフレームには膨大な数のユーザーが含まれており、これはおそらく非常に非効率的な方法だと思います.

どうもありがとう。

4

3 に答える 3

6

@akrun のメソッドは 1 回限りの優れた方法ですが、ベクトル化を活用していないため (rnormの各レベル内で 1 回繰り返し呼び出しますuser)、おそらく遅い側にあります。これを行うより一般的な方法は次のとおりです。

library(data.table)
setDT(df)
df[unique(df, by = "user")[ , new_rand := rnorm(.N)],
   new_rand := i.new_rand, on = "user"]

何が起きてる?すべての重複した観測 ( で定義されているように、ここでは) が削除されuniqueた新しいを返します。次に、この新しいオブジェクトに列を追加します ( )。最後に、この拡張が元のテーブルに結合されます。data.tablebyuser[, := ]data.table

ここではrnorm1 回だけ呼び出して、正確なサイズのベクトルを返すことに注意してください。次に、これを元のデータセットに結合し、必要に応じて各 のすべての観測値に値を「分散」しますuser

または、より具体的なグループに割り当てるには、userandfeature1およびfeature2:

grps <- c("user", "feature1", "feature2")
df[unique(df, by = grps)[ , new_rand := rnorm(.N)],
   new_rand := i.new_rand, on = grps]
于 2015-11-25T19:56:17.457 に答える
3

試すことができdata.tableます。'data.frame' を 'data.table' に変換し ( setDT(df1))、'user' でグループ化し、単一の乱数を取得し ( rnorm(1))、代入 ( :=) して 'new_rand' を作成します。

library(data.table)
setDT(df1)[, new_rand := rnorm(1)  , by = user]

または、 を使用できますdplyr

library(dplyr)
df1 %>%
   group_by(user) %>%
   mutate(new_rand = rnorm(1)) 

または別のオプションleft_join

distinct(df1, user) %>%
      mutate(new_rand=rnorm(n())) %>%
      left_join(df1, ., by='user')
于 2015-11-25T19:52:17.357 に答える