1

非常に単純な質問で、SO で質問しなければならなかったことを後悔しています。私が思っていたよりも優れた解決策を世の中のクリエイティブな人が見つけてくれることを願っています。

「タイプ」の値が同じであるマトリックスの隣接する値の違いを見つけたいです。以下の例では、値が 2,6,1 のベクトルが必要です。

mat
     value type
[1,]  5   A
[2,]  7   A
[3,]  1   B
[4,]  2   C
[5,]  8   C
[6,]  9   C

私は2つの方法で実装しようとしましたが、どちらも非常に遅いです:

  • アプローチ 1: の場合type(row 1) = type(row 2)、 を見つけてvalue(row 2) - value(row 1)、1 ずつ増やします。の場合type(row 1) != type(row 2)、2 ずつ増加します。

  • アプローチ 2: それぞれの違いをループして、typeすべての違いを見つけます。

約 500,000 の異なる「タイプ」と 500 万の異なる行があります。誰かがより効率的な方法を考えることができますか? 私は言語 R でプログラミングしています。R 言語には、違いを見つける関数が既にあります (?diff を参照)。

4

2 に答える 2

2

これを行うには行が多すぎると言うので、data.table解決策を提案します。

require(data.table)
DT <- data.table(df) # where `df` is your data.frame

DT[, diff(value), by=type]$V1
# [1] 2 6 1

ディメンションのデータでこのコードをシミュレートします。

diffディメンションのデータでは、20 秒近くかかります (ボトルネックは の呼び出しです)。

require(data.table)
set.seed(45)
types <- sapply(1:5e5, function(x) paste0(sample(letters, 5, TRUE), collapse=""))

DT <- data.table(value=sample(100, 5e6, TRUE), type=sample(types, 5e6, TRUE))
system.time(t1 <- DT[, diff(value), by=type]$V1)
#   user  system elapsed 
# 18.610   0.238  19.166 

他の回答と比較するにはtapply

system.time(t2 <- tapply(DT[["value"]], DT[["type"]], diff))
#   user  system elapsed 
# 48.471   0.664  51.673 

また、元の順序を維持する場合と同様にtapply、結果をtypewhere で並べ替えます。data.tablekey


編集: @eddiのコメントに続いて:

> system.time(t3 <- DT[, value[-1]-value[-.N], by=type]$V1)
#  user  system elapsed 
# 6.221   0.195   6.641 

への呼び出しを削除することで、3 倍の改善がありますdiff。ありがとう@eddi。

于 2013-07-16T21:32:50.137 に答える