4

一連の時間枠にわたるグループごとのローリングカウント/発生の合計を計算しようとしています。

次のようなサンプルデータを含むデータフレームがあります。

dates = as.Date(c("2011-10-09",
        "2011-10-15",
        "2011-10-16", 
        "2011-10-18", 
        "2011-10-21", 
        "2011-10-22", 
        "2011-10-24"))

group1=c("A",
         "C",
         "A", 
         "A", 
         "L", 
         "F", 
         "A")
group2=c("D",
         "A",
         "B", 
         "H", 
         "A", 
         "A", 
         "E")

df1 <- data.frame(dates, group1, group2)

一意の「グループ」ごとに個々のデータ フレームを反復処理します。たとえば、「A」のグループは次のようになります (グループ 1 かグループ 2 かにかかわらず、すべての行に存在します)。

イベントの「日付」(つまり、現在の行の日付) と過去 4 日間の時間範囲内のイベントの発生数を「A」(およびその後の各グループ) でカウントしたいと考えています。それをロールフォワードしたいので、たとえば、行 1 のカウントは 1、行 2 のカウントも 1 (現在の日付を除いて過去 4 日間にイベントはありません)、行 3 のカウントは 2、行4 には 3 などがあります。

行ごとに、基本的に、このイベント日に、現在の日付 (日付列に示されている) と過去 4 日間に発生したイベントが X 個あるという列を作成したいと思います。 .

4

2 に答える 2

5

この例では、次sapplyのように、その日または最大 4 日前までのエントリ数をカウントして、各行を分析するためにおそらく使用できます。

df1$lastFour <-
  sapply(df1$dates, function(x){
    sum(df1$dates <= x & df1$dates >= x - 4)
  })

結果df1:

       dates group1 group2 lastFour
1 2011-10-09      A      D        1
2 2011-10-15      C      A        1
3 2011-10-16      A      B        2
4 2011-10-18      A      H        3
5 2011-10-21      L      A        2
6 2011-10-22      F      A        3
7 2011-10-24      A      E        3

あなたの質問が示唆するように、データがより大きなセットからのものであり、各グループで分析を行いたい場合 (概念的には、質問は、過去 4 日間にこのグループがあったイベントの数は? 日のみに尋ねられます)そのグループからのイベントで)、次の手順に従うことができます。

まず、アルファベットの最初の 10 文字としてラベル付けされたグループを含むいくつかの大きなサンプル データを次に示します。

biggerData <-
  data.frame(
    dates = sample(seq(as.Date("2011-10-01")
                       , as.Date("2011-10-31")
                       , 1)
                   , 100, TRUE)
    , group1 = sample(LETTERS[1:10], 100, TRUE)
    , group2 = sample(LETTERS[1:10], 100, TRUE)
  )

次に、データ内のすべてのグループを抽出します (ここではそれらを知っていますが、実際のデータについては、そのグループのリストを既に持っている場合と持っていない場合があります)

groupsInData <-
  sort(unique(c(as.character(biggerData$group1)
                , as.character(biggerData$group2))))

次に、そのグループ名のベクトルをループし、そのグループを 2 つのグループの 1 つとして各イベントを抽出し、上記と同じ列を追加し、個別の data.frames をリストに保存します (名前を付けて作成します)。より簡単にアクセス/追跡できます)。

sepGroupCounts <- lapply(groupsInData, function(thisGroup){
  dfTemp <- biggerData[biggerData$group1 == thisGroup | 
                         biggerData$group2 == thisGroup, ]

  dfTemp$lastFour <-
    sapply(dfTemp$dates, function(x){
      sum(dfTemp$dates <= x & dfTemp$dates >= x - 4)
    })
  return(dfTemp)

}) 

names(sepGroupCounts) <- groupsInData

データ内の各グループに対して、上記のように data.frame を返します。

そして、私は自分自身を助けることができなかったので、ここにdplyrtidyr解決策があります。上記のリストベースのソリューションと大差ありませんが、すべてが同じ data.frame に返される点が異なります (特に、この方法ではイベントごとに 2 つのエントリがあるため、これは良いことかもしれませんし、そうでない場合もあります)。

まず、簡単にするために、日付チェックを行う関数を定義しました。これは上記でも簡単に使用できます。

myDateCheckFunction <- function(x){
  sapply(x, function(thisX){
    sum(x <= thisX & x >= thisX - 4 )
  })
}

次に、各グループが存在するかどうかを判断する一連の論理テストを作成します。これらは、各グループの列を生成するために使用され、各イベントの存在/不在に TRUE/FALSE を与えます。

dotsConstruct <-
  paste0("group1 == '", groupsInData, "' | "
         , "group2 == '", groupsInData, "'") %>%
  setNames(groupsInData)

最後に、すべてを 1 つのパイプ呼び出しにまとめます。説明する代わりに、各ステップについてコメントしました。

withLastFour <-
  # Start with data
  biggerData %>%
  # Add a col for each group using Standard Evaluation
  mutate_(.dots = dotsConstruct) %>%
  # convert to long form; one row per group per event
  gather(GroupAnalyzed, Present, -dates, -group1, -group2) %>%
  # Limit to only rows where the `GroupAnalyzed` is present
  filter(Present) %>%
  # Remove the `Present` column, as it is now all "TRUE"
  select(-Present) %>%
  # Group by the groups we are analyzing
  group_by(GroupAnalyzed) %>%
  # Add the column for count in the last four dates
  # `group_by` limits this to just counts within that group
  mutate(lastFour = myDateCheckFunction(dates)) %>%
  # Sort by group and date for prettier checking
  arrange(GroupAnalyzed, dates)

結果は上記の出力と似ていlistますが、すべてが 1 つの data.frame に含まれているため、一部の機能を簡単に分析できます。上部は次のようになります。

       dates group1 group2 GroupAnalyzed lastFour
      <date> <fctr> <fctr>         <chr>    <int>
1 2011-10-01      B      A             A        1
2 2011-10-02      J      A             A        2
3 2011-10-05      C      A             A        5
4 2011-10-05      C      A             A        5
5 2011-10-05      G      A             A        5
6 2011-10-08      E      A             A        5

私のランダム サンプルには 2005 年 10 月に複数のイベントがあったため、ここではカウントが大きくなっていることに注意してください。

于 2016-11-02T12:29:32.980 に答える