web-dev-qa-db-ja.com

data.frame内のグループごとの加重平均を表示します

コマンドbyおよびweighted.meanに関する問題はすでに存在しますが、問題の解決に役立つものはありませんでした。私はRに不慣れで、プログラミングよりもデータマイニング言語に慣れています。

個人(観測/行)ごとに、収入、教育レベル、サンプルの重みを含むデータフレームがあります。教育レベルごとの収入の加重平均を計算し、その結果を次のように元のデータフレームの新しい列の各個人に関連付けたいと思います。

obs income education weight incomegroup
1.   1000      A       10    --> display weighted mean of income for education level A
2.   2000      B        1    --> display weighted mean of income for education level B
3.   1500      B        5    --> display weighted mean of income for education level B
4.   2000      A        2    --> display weighted mean of income for education level A

私は試した:

data$incomegroup=by(data$education, function(x) weighted.mean(data$income, data$weight))    

それは動作しません。加重平均はなんらかの方法で計算され、「収入グループ」の列に表示されますが、グループごとではなくセット全体、または1つのグループのみについてはわかりません。パッケージplyrまたはaggregateに関することを読みましたが、興味のあることを実行していないようです。

ave{stats}コマンドは、私が探しているものを正確に提供しますが、単純な意味のためだけです。

data$incomegroup=ave(data$income,data$education,FUN = mean)

ウェイトと一緒に使用することはできません。

よろしくお願いします!

8
Elixterra

mutateを使用すると、left_joinを回避できます。

library(dplyr)
df %>%
   group_by(education) %>% 
   mutate(weighted_income = weighted.mean(income, weight))
#    obs income education weight weighted_income
#  <int>  <int>    <fctr>  <int>           <dbl>
#1     1   1000         A     10        1166.667
#2     2   2000         B      1        1583.333
#3     3   1500         B      5        1583.333
#4     4   2000         A      2        1166.667
8
akrun

次のようにdplyrパッケージを使用してみてください。

df <- read.table(text = 'obs income education weight   
                          1   1000      A       10     
                          2   2000      B        1     
                          3   1500      B        5     
                          4   2000      A        2', 
                 header = TRUE)     

library(dplyr)

df_summary <- 
  df %>% 
  group_by(education) %>% 
  summarise(weighted_income = weighted.mean(income, weight))

df_summary
# education weighted_income
#     A        1166.667
#     B        1583.333

df_final <- left_join(df, df_summary, by = 'education')

df_final
# obs income education weight weighted_income
#  1   1000         A     10        1166.667
#  2   2000         B      1        1583.333
#  3   1500         B      5        1583.333
#  4   2000         A      2        1166.667
5
Alex Ioannides

ベースRには関数weighted.meanがあります。残念ながら、aveで簡単に機能します。 1つの解決策は、data.tableを使用することです。

library(data.table)
setDT(data)
data[, incomeGroup := weighted.mean(income, weight), by=education]
data
   income education weight incomeGroup
1:   1000         A     10    1166.667
2:   2000         B      1    1583.333
3:   1500         B      5    1583.333
4:   2000         A      2    1166.667

aveで機能する奇妙なメソッドは

ave(df[c("income", "weight")], df$education,
    FUN=function(x) weighted.mean(x$income, x$weight))[[1]]
[1] 1166.667 1583.333 1583.333 1166.667

サブセットdata.frameを関数にフィードしてから、グループ化変数でグループ化します。 FUN引数は、data.frameを受け取り、結果にweighted.meanを適用する関数を作成します。最終出力はdata.frameであるため、[[1]]は目的の結果を持つベクトルを返します。

これはこれが可能であることの単なる証拠であることに注意してください。この方法はお勧めしません。data.frame手法ははるかにクリーンで、1000回の観測値を超えるデータセットでははるかに高速になります。

1
lmo