4

特定の日付にプロジェクトに取り組んだ人々を説明する次のデータフレーム DF があります。

ID    ProjectName    StartDate 
1       Health        3/1/06 18:20
2       Education     2/1/07 15:30
1       Education     5/3/09 9:00
3       Wellness      4/1/10 12:00
2       Health        6/1/11 14:20

目標は、各 ID に対応する最初のプロジェクトを見つけることです。たとえば、予想される出力は次のようになります。

ID    ProjectName    StartDate 
1       Health        3/1/06 18:20
2       Education     2/1/07 15:30
3       Wellness      4/1/10 12:00

これまでのところ、各 ID の最初の StartDate を取得するために次のことを行いました。

sub <- ddply(DF, .(ID), summarise, st = min(as.POSIXct(StartDate)));

この後、sub の各行を元の DF と照合し、その ID と StartDate に対応するプロジェクトを抽出する必要があります。これは、サブの各行のループで実行できます。ただし、私のデータセットは非常に大きいため、このマッチングを実行して DF からこのサブセットを抽出する効率的な方法があるかどうかを知りたいです。

4

4 に答える 4

7

以下を返すmatchため、これを使用するのはかなり簡単です。match

2 番目の引数の最初の引数の最初の一致の位置のベクトル

したがって、日付で並べ替えてから、 を使用uniqueして各 ID の 1 つのインスタンスを取得matchし、最初の位置を見つけるだけです。データの再現可能な例を提供してくれた @MatthewLunberg に感謝します。

DF <- DF[ order(as.POSIXct(DF$StartDate, format="%m/%d/%y %H:%M")) , ]
DF[ match( unique( DF$ID ) , DF$ID ) , ]
#  ID ProjectName    StartDate
#6  1      Health 1/1/06 11:10
#2  2   Education 2/1/07 15:30
#4  3    Wellness 4/1/10 12:00

1 つの利点は、再ソートする前に元のデータフレームの行番号を保持することです。これがあなたに役立つかどうかはわかりません。

于 2013-04-27T21:30:10.860 に答える
2

これが基本Rソリューションです

dat <- data.frame(
    ID=c(1,2,1,3,2), 
    PRJ=c("H","E","E", "W", "H"), 
    START=strptime(
      c(
        "3/1/06 18:20", "2/1/07 15:30", "5/3/09 9:00",
        "4/1/10 12:00","6/1/11 14:20"), 
      "%d/%m/%y %H:%M")
    )
min_date <- function(x) {x[which.min(x$START), ]}
s <- split(dat, dat$ID) # split
a <- lapply(s, FUN=min_date) # apply
do.call("rbind", a) # combine

その結果

  ID PRJ               START
1  1   H 2006-01-03 18:20:00
2  2   E 2007-01-02 15:30:00
3  3   W 2010-01-04 12:00:00

ただし、@ SimonO101 の注文一致ソリューションは、これよりもはるかに高速です。

楽しみのために、これを使用したさらに別のソリューションを次に示しますsqldf

sqldf("select * from dat group by ID having START=min(START)")
于 2013-04-27T20:24:39.540 に答える
1

plyr最後に、パッケージに基づくソリューションを次に示します。textConnectionデータを読みやすくするために、余分な列を追加しました。

dfProjects = as.data.frame(read.table(textConnection("ID    ProjectName    Date Time 
  1       Health        3/1/06 18:20
  2       Education     2/1/07 15:30
  1       Education     5/3/09 9:00
  3       Wellness      4/1/10 12:00
  2       Health        6/1/11 14:20"), header = TRUE))
ddply(within(dfProjects, dfProjects[order(
  as.POSIXct(paste(Date, Time), format = "%m/%d/%y %H:%M")), ]), 
      .(ID), function(dataFrame) dataFrame[1, ])
于 2013-04-28T07:04:40.030 に答える