2011-10-24 8 views
3

hereは、最大変数を選択することによってデータフレーム内の重複を排除する方法について説明しています。
これは、最小変数で複製を選択するためにこれをどのように適用できるかもわかります。
私の質問は今どのように表示されます平均すべての重複?例えば
すべての重複の平均を見つける

z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2)) 
# id var 
# 1 2 
# 1 4 
# 2 1 
# 2 3 
# 3 5 
# 4 2 

私は出力をしたいと思います:

# id var 
# 1 3  mean(2,4) 
# 2 2  mean(1,3) 
# 3 5 
# 4 2 


私の現在のコードは次のとおりです。

averages<-do.call(rbind,lapply(split(z,z$id),function(chunk) mean(chunk$var))) 
z<-z[order(z$id),] 
z<-z[!duplicated(z$id),] 
z$var<-averages 

私のコードは、非常にゆっくりと実行され、約10倍の時間がかかりますされます最大を選ぶ方法よりもこのコードを最適化するにはどうすればよいですか?実際にソリューションをタイミングした後、ここでは少し速く何かです:

z <- data.frame(id=rep(c(1,1,2,2,3,4),1e5),var=rnorm(6e5)) 
z$var <- ave(z$var, z$id, FUN=mean) 
z <- unique(z) 

UPDATE:

答えて

2

私はaveuniqueの組み合わせを使用します。

z <- data.frame(id=rep(c(1,1,2,2,3,4),1e5),var=rnorm(6e5)) 
system.time({ 
    averages <- t(sapply(split(z,z$id), function(x) sapply(x,mean))) 
}) 
# user system elapsed 
# 1.32 0.00 1.33 
system.time({ 
    z$var <- ave(z$var, z$id, FUN=mean) 
    z <- unique(z) 
}) 
# user system elapsed 
# 4.33 0.02 4.37 
+0

を使用して高速化ソリューションである知っていますか? – LostLin

+0

これはありがとう!私の時間を39秒から約4秒に短縮しました – LostLin

+0

@Ellipsis ...:あなたを大歓迎です。より速いソリューションのために私のアップデートを見てください(私のテストでは)。 –

4

私はsplit()unsplit()が一つの方法だと思います。

dupMean <- function(x) 
{ 
    result <- split(x[, 2], x[, 1]) 
    result <- lapply(result, mean) 
    result <- unsplit(result, unique(x[, 1])) 

    return(result) 
} 

あるいは、plyrで行を保存する:

require(plyr) 
dupMean <- function(x) 
{ 
    result <- split(x[, 2], x[, 1]) 
    result <- laply(result, mean) 

    return(result) 
} 

更新: ただ、好奇心のために、ここでは様々な機能が提案さの比較です。 Ramnath(fn3)は私のコンピュータの勝者に見えます。

require(plyr) 
require(data.table) 
require(rbenchmark) 

fn1 <- function(z){ 
    z$var <- ave(z$var, z$id, FUN=mean) 
    return(unique(z)) 
} 

fn2 <- function(z) { 
    t(sapply(split(z,z$id), function(x) sapply(x,mean))) 
} 

fn3 <- function(z){ 
    data.table(z)[,list(var = mean(var)), 'id'] 
} 

fn4 <- function(x) 
{ 
    result <- t(sapply(split(x,x$id), function(y) sapply(y,mean))) 

    return(result) 
} 

fn5 <- function(x) 
{ 
    x$var <- ave(x$var, x$id, FUN=mean) 
    x <- unique(x) 

    return(x) 
} 

fn6 <- function(x) 
{ 
    result <- do.call(rbind,lapply(split(x,x$id),function(chunk) mean(chunk$var))) 

    return(data.frame(id = unique(x[, 1]), var = result)) 
} 

fn7 <- function(x) 
{ 
    result <- split(x[, 2], x[, 1]) 
    result <- lapply(result, mean) 
    result <- unsplit(result, unique(x[, 1])) 


    return(data.frame(id = unique(x[, 1]), var = result)) 
} 


fn8 <- function(x) 
{ 
    result <- split(x[, 2], x[, 1]) 
    result <- laply(result, mean) 

    return(data.frame(id = unique(x[, 1]), var = result)) 
} 



z <- data.frame(id = rep(c(1,1,2,2,3,4,5,6,6,7), 1e5), var = rnorm(1e6)) 

benchmark(f1 <- fn1(z), f2 <- fn2(z), f3 <- fn3(z), f4 <- fn4(z), f5 <- fn5(z), f6 <- fn6(z), f7 <- fn7(z), f8 <- fn8(z), replications = 2) 

結果:ユニークが高速であるか、重複を超えるいずれかの利点を持っている場合ここで

  test replications elapsed relative user.self sys.self 
1 f1 <- fn1(z)   2 13.45 20.692308  13.27  0.15 
2 f2 <- fn2(z)   2 3.54 5.446154  3.43  0.09 
3 f3 <- fn3(z)   2 0.65 1.000000  0.54  0.10 
4 f4 <- fn4(z)   2 3.62 5.569231  3.50  0.09 
5 f5 <- fn5(z)   2 13.57 20.876923  13.25  0.25 
6 f6 <- fn6(z)   2 3.53 5.430769  3.36  0.14 
7 f7 <- fn7(z)   2 3.34 5.138462  3.28  0.03 
8 f8 <- fn8(z)   2 3.34 5.138462  3.26  0.03 
+0

は私の持つ最初の解決策ではありませんか? – LostLin

+0

'unsplit()'を使うと 'rbind()'と比較して時間を半減できます。しかし、ジョシュアの方がはるかに高速です。 10^7行のデータフレームをテストすると、合計経過時間はそれぞれ9.83,4.70,0となりました。 – jthetzel

5

data.table

library(data.table) 
z <- data.frame(id=sample(letters, 6e5, replace = TRUE),var = rnorm(6e5)) 

fn1 <- function(z){ 
    z$var <- ave(z$var, z$id, FUN=mean) 
    return(unique(z)) 
} 

fn2 <- function(z) { 
    t(sapply(split(z,z$id), function(x) sapply(x,mean))) 
} 

fn3 <- function(z){ 
    data.table(z)[,list(var = mean(var)), 'id'] 
} 

library(rbenchmark) 
benchmark(f1 <- fn1(z), f2 <- fn2(z), f3 <- fn3(z), replications = 2) 

    est replications elapsed   relative  user.self sys.self 
1 f1 <- fn1(z)   2 3.619 8.455607  3.331 0.242   
2 f2 <- fn2(z)   2 0.586 1.369159  0.365 0.220   
3 f3 <- fn3(z)   2 0.428 1.000000  0.341 0.086 
+0

いつから0.868が0.586よりもはるかに速いのですか? ;-)最速の解決策はOPのデータに依存しますが、私の賭けはdata.tableになります。 –

+0

ポイントを取って編集しました!私は娘が拾って叫んでいた間に出力を貼り付けました:) – Ramnath

+0

これはおかげでありましたが、私のデータに重複したクラスタがないので、 – LostLin

関連する問題