3

多くの列を持つフレームがありますc1c2c3 c4 ... c30 d

c1..30で一意のすべての行を集計して検索し、その行のmin(d)を取得します。SQLでは、これはc1、...、c30によるグループになります。

dは日付タイプです。

私はここでいくつかの解決策をスタックで見つけましたが、1)非常に多くの列2)合計の代わりに分を実行するために機能するものはないようです。

どんな入力でも素晴らしいでしょう。

4

2 に答える 2

4

data.tableいくつかの偽のデータを含むパッケージを使用した回答は次のとおりです。

library(data.table)

DT<-data.table(matrix(sample(1:2,3000,replace=TRUE),ncol=30))
DT2<-DT[sample(seq_len(nrow(DT)),9000,replace=TRUE)]
# EDIT: now "d" is a date.
DT2[,d:=as.POSIXct(origin = "1960-01-01",rnorm(nrow(DT2), sd = 1000))]
setnames(DT2,c(paste0("c",1:30),"d"))

## pick up herewith your own data, starting with the commented next line
# DT2 <- as.data.table(dataset)
setkeyv(DT2,paste0("c",1:30))

DT3<-DT2[,list(minD=min(d)),by=key(DT2)]

dim(DT2)
# [1] 9000   31
dim(DT3)
# [1] 100  31

マシューからの小さな追加:

+10、そして素敵な偽データ。最初にキーを設定して実行by=key(DT)できるようにするのは、少し面倒な場合があるため、通常は、簡単にするためにこのようなことをアドホックに行います。しかし、最初に最も自然なことを試してみてください:

DT2[,min(d),by=paste0("c",1:30)]
Error in `[.data.table`(DT2, , min(d), by = paste0("c", 1:30)) : 
    'by' appears to evaluate to column names but isn't c() or key(). Use by=
    list(...) if you can. Otherwise, by=eval(paste0("c", 1:30)) should work.
    This is for efficiency so data.table can detect which columns are needed.

エラーメッセージは、代わりに何をする必要があるかを示しています:

ans = DT2[,min(d),by=eval(paste0("c",1:30))]
dim(ans)
[1] 100  31

もちろん、次の自然な考えは次のとおりです。まあ、data.table がby列名を知っていて、それをエラー メッセージに入れるのに十分賢いなら、なぜそれができないのでしょうか? 答えは、データに基づいて推測しているだけだということです。いくつかのエッジケースでは、それほど明確ではありません。したがって、現在、ユーザーから追加のインテントが必要です: でラッピングしevalます。とはいえ、完全に満足しているわけではないので、改善できるかもしれません。

編集: 新しい data.table の名前を変更する

私のアプローチでは、次のminDように入力して作成したときに新しい列に名前を付けました

DT3<-DT2[,list(minD=min(d)),by=key(DT2)]

Matthew Dowle のアプローチを使用すると、次のように入力して、ほぼ同じ方法でこれを実現できます。

ans = DT2[,list(minD=min(d)),by=eval(paste0("c",1:30))]

すでに列を作成していて名前を変更したい場合は、次のように使用setnamesします。

setnames(DT3,old="minD",new="theNewMinD")

これにより、全体のコピーが回避data.tableされ、メモリの割り当てが保存されます (これらの利点は両方とも、 を使用すると失われnames(DT3)<-"something"ます)。?setnames

于 2012-07-05T18:17:04.710 に答える
1

最小限の再現可能な例なしでテストされていません:

apply(unique(dataset), 1, min)

それを分解してください:

x <- unique(dataset)  #finds only unique rows
apply(x, 1, min) # applies min across rows
                 # replace the 1 with a 2 and it applies across columns
于 2012-07-05T18:01:29.540 に答える