質問はオリジナルから編集されました。
この興味深い discussion を読んだ後、たとえば、Lahmanバッティングデータでdplyrを使用して列内のNAを置換する方法を考えていました。
Source: local data frame [96,600 x 3]
Groups: teamID
yearID teamID G_batting
1 2004 SFN 11
2 2006 CHN 43
3 2007 CHA 2
4 2008 BOS 5
5 2009 SEA 3
6 2010 SEA 4
7 2012 NYA NA
以下は期待通りにnot動作します
library(dplyr)
library(Lahman)
df <- Batting[ c("yearID", "teamID", "G_batting") ]
df <- group_by(df, teamID )
df$G_batting[is.na(df$G_batting)] <- mean(df$G_batting, na.rm = TRUE)
ソース:ローカルデータフレーム[20 x 3]グループ:yearID、teamID
yearID teamID G_batting
1 2004 SFN 11.00000
2 2006 CHN 43.00000
3 2007 CHA 2.00000
4 2008 BOS 5.00000
5 2009 SEA 3.00000
6 2010 SEA 4.00000
7 2012 NYA **49.07894**
> mean(Batting$G_battin, na.rm = TRUE)
[1] **49.07894**
実際、グループの平均ではなく、全体の平均に帰属しています。 dplyrチェーンでこれをどのように行いますか?基Rからtransform
を使用しても、notはグループ平均ではなく全体平均を代入するので機能します。また、このアプローチはデータを通常のデータに変換します。フレーム。これを行うためのより良い方法はありますか?
df %.%
group_by( yearID ) %.%
transform(G_batting = ifelse(is.na(G_batting),
mean(G_batting, na.rm = TRUE),
G_batting)
)
編集:transform
をmutate
に置き換えると、次のエラーが発生します
Error in mutate_impl(.data, named_dots(...), environment()) :
INTEGER() can only be applied to a 'integer', not a 'double'
編集:as.integerを追加するとエラーが解決されるようで、doesが期待される結果を生成します。 @eddiの回答も参照してください。
df %.%
group_by( teamID ) %.%
mutate(G_batting = ifelse(is.na(G_batting), as.integer(mean(G_batting, na.rm = TRUE)), G_batting))
Source: local data frame [96,600 x 3]
Groups: teamID
yearID teamID G_batting
1 2004 SFN 11
2 2006 CHN 43
3 2007 CHA 2
4 2008 BOS 5
5 2009 SEA 3
6 2010 SEA 4
7 2012 NYA 47
> mean_NYA <- mean(filter(df, teamID == "NYA")$G_batting, na.rm = TRUE)
> as.integer(mean_NYA)
[1] 47
編集:@Romainのコメントをフォローアップして、私はgithubからdplyrをインストールしました:
> head(df,10)
yearID teamID G_batting
1 2004 SFN 11
2 2006 CHN 43
3 2007 CHA 2
4 2008 BOS 5
5 2009 SEA 3
6 2010 SEA 4
7 2012 NYA NA
8 1954 ML1 122
9 1955 ML1 153
10 1956 ML1 153
> df %.%
+ group_by(teamID) %.%
+ mutate(G_batting = ifelse(is.na(G_batting), mean(G_batting, na.rm = TRUE), G_batting))
Source: local data frame [96,600 x 3]
Groups: teamID
yearID teamID G_batting
1 2004 SFN 0
2 2006 CHN 0
3 2007 CHA 0
4 2008 BOS 0
5 2009 SEA 0
6 2010 SEA 1074266112
7 2012 NYA 90693125
8 1954 ML1 122
9 1955 ML1 153
10 1956 ML1 153
.. ... ... ...
そのため、エラーは発生しませんでした(良い)が、(一見)奇妙な結果が得られました。
主な問題は、mean
がdoubleを返し、G_batting
列が整数であるということです。したがって、平均をas.integer
でラップすると機能するか、列全体をnumeric
に変換する必要があると思います。
とは言っても、ここにはいくつかのdata.table
の選択肢があります。どちらが速いかはチェックしませんでした。
library(data.table)
# using ifelse
dt = data.table(a = 1:2, b = c(1,2,NA,NA,3,4,5,6,7,8))
dt[, b := ifelse(is.na(b), mean(b, na.rm = T), b), by = a]
# using a temporary column
dt = data.table(a = 1:2, b = c(1,2,NA,NA,3,4,5,6,7,8))
dt[, b.mean := mean(b, na.rm = T), by = a][is.na(b), b := b.mean][, b.mean := NULL]
そして、これは私が理想的にやりたいことです( FRがあります これについて):
# again, atm this is pure fantasy and will not work
dt[, b[is.na(b)] := mean(b, na.rm = T), by = a]
dplyr
のifelse
バージョンは次のとおりです(OPの場合):
dt %>% group_by(a) %>% mutate(b = ifelse(is.na(b), mean(b, na.rm = T), b))
dplyr
の1行に2番目のdata.table
アイデアを実装する方法がわかりません。また、dplyr
がデータのスクランブル/順序付けを停止する方法(インデックス列の作成を除く)もわかりません。