4

私はr(sasから来ました)に比較的慣れていません。各グループ内で異なる数の観測を選択する必要があります。グループは 2 つの変数の値によって識別されます

ToSelect <- data.frame(
                           key1=c(1,1,1,1,1,2,2,2,2,2,2,2),
                           key2=c("a","a","b","b","b","a","a","a","a","b","b","b"),
                           var1=c(2,3,4,6,2,7,8,5,7,1,8,5)
                          )
NumObs <- data.frame(
                           key1=c(1,1,2,2),
                           key2=c("a","b","a","b"),
                           NumObs=c(1,2,2,1)
                       )

試してみました(質問「Rの各レベルで最初の80個の観測を選択してください」から)

ToSelect <- merge(x=ToSelect,y=NumObs,by=c("key1","key2"))
library(plyr)
Selected <- ddply(ToSelect, .(key1,key2), head, n = NumObs)

を与える

エラー: length(n) == 1L は TRUE ではありません

これはおそらく専門家にとって明らかなエラーです (na スカラー、NumObs はベクトル?)

同じ質問から、私は試しました:

Selected <- do.call(
                     rbind, 
                     lapply(split(ToSelect, c(ToSelect$key1,ToSelect$key2)), head, NumObs)
                    )

を与える

エラー: length(n) == 1L は TRUE ではありません。さらに: 警告メッセージ: Split.default(x = seq_len(nrow(x)), f = f, drop = drop, ...) : データ長が分割変数の倍数ではありません

それで、前と同じエラーに加えて、複数のもの、グループの長さが異なる場合、分割を使用できませんか?

次に、「グループごとの観測番号」という質問を見つけました。私の場合、rle /シーケンスの回答を機能させることができませんでしたが、ddplyの回答を適応させました。

ToSelect <- ddply(ToSelect, .(key1, key2), function(z){
                                                         cbind(var1=z$var1,NumObs=z$NumObs,
                                                         data.frame(
                                                                       SeqNum = seq_along(z$key2)
                                                                    )
                                                               )
                                                       }
                 )
Selected <- ToSelect[ToSelect$SeqNum<=ToSelect$NumObs,c("key1","key2","var1")]

動作します。

明らかに、私の実際のデータははるかに大きいので、代替のより良い方法はありますか? ありがとう!

4

3 に答える 3

2

data.table効率を求めるなら、パッケージを調べることをお勧めします。この問題に対するかなり単純な解決策は次のとおりです。

#Convert objects to data.table
require("data.table")
ToSelect <- data.table(ToSelect)
NumObs <- data.table(NumObs)

#Merge data
ToSelect <- merge(ToSelect,NumObs,by=c("key1","key2"),all.x=T)

#Provide intra-group ordering variable
ToSelect[,Grp.Seq:=seq(1:.N),by=c("key1","key2")]
Selected <- ToSelect[NumObs>=Grp.Seq]
Selected

   key1 key2 var1 NumObs Grp.Seq
1:    1    a    2      1       1
2:    1    b    4      2       1
3:    1    b    6      2       2
4:    2    a    7      2       1
5:    2    a    8      2       2
6:    2    b    1      1       1

とにかく初心者で、大規模なデータセットを扱うことが多い場合は、最初Rから学ぶのが理にかなっているかもしれませんdata.table。私は自分の仕事で非常に大きなデータセットを扱っていますが、data.frame クラスは、私が行う仕事の多くではあまり実用的ではありません。data.frame必要に応じてとを簡単に切り替えることdata.tableができます。

于 2014-05-20T11:43:18.967 に答える
1

あなたがやろうとしていると私が思うことをやろうとしているなら、data.table非常に役に立ちます。var1この小さな 1 つのライナーは、基本的に、テーブルに指定された観測の数に応じて、グループごとにの値をランダムにサンプリングしNumObsます。試す:

# Load package
require(data.table)
# Make your data.frames into data.tables                       
ts <- data.table( ToSelect , key = c( "key1","key2"))
no <- data.table( NumObs , key = c( "key1","key2") )

# Join together based on key columns and sample by group
no[ts][ , sample( var1 , NumObs , TRUE ) , by = c("key1","key2") ]
#   key1 key2 V1
#1:    1    a  2 
#2:    1    b  6 #|_ Two observations of group 1b
#3:    1    b  6 #|
#4:    2    a  5 #|_ Two observations of group 2a
#5:    2    a  8 #|
#6:    2    b  5

置換を使用してサンプリングしたくない場合 (上記のように、グループ 1b の値を見てください - それらは同じです) のTRUE引数を削除しますsample(したがって、各グループの観測の総数よりも多くの観測を選択することはできません)。

于 2014-05-20T11:44:41.447 に答える
0

これは、および-ペアToSelectのグループごとに n 個の観測値を選択できるアプローチです。この場合の n は、 data.frameで指定されます。key1key2NumObsNumObs

これを行うには、パッケージを使用しますdplyrが、同じことを行う方法は他にもあります。

パッケージをインストールしてライブラリにロードします。

require(dplyr)

まず、両方の data.frame を結合 (=マージ) します。

df <- left_join(ToSelect, NumObs, by=c("key1", "key2"))

次に、結果の data.frame df をkey1andでグループ化し、グループごとに観測key2の最初のNumObs数を選択します。

df <- df %.% group_by(key1, key2) %.% filter(1:n() <= NumObs)

>df
#  key1 key2 var1 NumObs
#1    1    a    2      1
#2    1    b    4      2
#3    1    b    6      2
#4    2    a    7      2
#5    2    a    8      2
#6    2    b    1      1

NumObs列のない結果の data.frame が必要な場合は、次のように調整できます。

df <- df %.% group_by(key1, key2) %.% filter(1:n() <= NumObs) %.% select(-NumObs)
于 2014-05-20T11:14:05.237 に答える