1

私は質問を更新しました.a)最初の試みで質問を明確に表現しなかったため、b)正確な必要性も多少変化しました.

特に Hemmo にはこれまで多大な助けをいただいたことに感謝したいと思います。また、私の質問を彼に十分に明確に説明できなかったことをお詫びします。彼のコード (以前のバージョンの問題に対処したもの) は、回答セクションに示されています。

大まかに言えば、さまざまな個人の連続した自由時間のさまざまなブロックを識別して区別するのに役立つコードを探しています。より具体的には、コードは理想的には次のようになります。

  • アクティビティに「無料」のラベルが付いているかどうかを確認する
  • 同じ人が連続して何週間 (前の週、後) に費やした時間が「無料」と表示されているかを確認します。
  • 「無料」とラベル付けされたその人の連続した週のブロック全体に、望ましい結果の列に指標を付けます。期間の長さ (例: 1 連続週、4 連続週、8 連続週) はさまざまであることに注意してください。
  • 最後に、これらのクラスターの特性をさらに分析する必要があるため、異なるブロックは異なるインジケーターを受け取る必要があります。(たとえば、ポールの行進ブロックの値は 1、5 月のブロックの値は 2、3 月のキムのブロックの値は 3 になります)

データフレームの例を見ると、これがより明確になることを願っています(目的の最終列を参照してください)

以下に従って、テストデータフレームのコードを作成してください。

よろしくお願いします。

W

例 (最後の列はコードによって生成される必要があることに注意してください。純粋に説明として含まれています):

         Week Name  Activity Hours Desired_Outcome
1  01/01/2013 Paul      Free    40               1
2  08/01/2013 Paul      Free    10               1
3  08/01/2013 Paul Project A    30               0
4  15/01/2013 Paul Project B    30               0
5  15/01/2013 Paul Project A    10               0
6  22/01/2013 Paul      Free    40               2
7  29/01/2013 Paul Project B    40               0
8  05/02/2013 Paul      Free    40               3
9  12/02/2013 Paul      Free    10               3
10 19/02/2013 Paul      Free    30               3
11 01/01/2013  Kim Project E    40               0
12 08/01/2013  Kim      Free    40               4
13 15/01/2013  Kim      Free    40               4
14 22/01/2013  Kim Project E    40               0
15 29/01/2013  Kim      Free    40               5

データフレームのコード:

Name=c(rep("Paul",10),rep("Kim",5))
Week=c("01/01/2013","08/01/2013","08/01/2013","15/01/2013","15/01/2013","22/01/2013","29/01/2013","05/02/2013","12/02/2013","19/02/2013","01/01/2013","08/01/2013","15/01/2013","22/01/2013","29/01/2013")
Activity=c("Free","Free","Project A","Project B","Project A","Free","Project B","Free","Free","Free","Project E","Free","Free","Project E","Free")
Hours=c(40,10,30,30,10,40,40,40,10,30,40,40,40,40,40)
Desired_Outcome=c(1,1,0,0,0,2,0,3,3,3,0,4,4,0,5)
df=as.data.frame(cbind(Week,Name,Activity,Hours,Desired_Outcome))        
df
4

2 に答える 2

2

編集:質問が数回編集されたため、これはすでに面倒だったので、古い回答を削除しました。

checkFree<-function(df){
  df$Week<-as.Date(df$Week,format="%d/%m/%Y")
  df$outcome<-numeric(nrow(df))

  if(df$Activity[1]=="Free"){ #check first
    counter<-1
    df$outcome[1]<-counter    
  } else counter<-0
  for(i in 2:nrow(df)){
    if(df$Activity[i]=="Free"){
       LastWeek <- (df$Week >= (df$Week[i]-7) & 
                        df$Week < (df$Week[i]))  
      if(all(df$Activity[LastWeek]!="Free"))
        counter<-counter+1 
      df$outcome[i]<-counter
    }
  }
  df
}

splitdf<-split(df, Name)

df<-unsplit(lapply(splitdf,checkFree),Name)

uniqs<-unique(df2$Name) #for renumbering
for(i in 2:length(uniqs))
  df$outcome[df$Name==uniqs[i] & df$outcome>0]<-
  max(df$outcome[df$Name==uniqs[i-1]]) +
  df$outcome[df$Name==uniqs[i] & df$outcome>0]
  df

上記のコードはおそらく最適とは言えませんが、これで十分です。

于 2013-03-09T12:17:14.923 に答える
1

Hemmo の回答に対する user1885116 のコメントを、必要なもののガイドとして使用すると、やや単純なアプローチになります。

N <- 1
x <- with(df, df[Activity=='Free',])
y <- with(x, diff(Week)) <= N*7

df$outcome <- 0
df[rownames(x[c(y, FALSE) | c(FALSE, y),]),]$outcome <- 1

df

##         Week  Activity Hours Desired_Outcome outcome
## 1 2013-01-01 Project A    40               0       0
## 2 2013-01-08 Project A    10               0       0
## 3 2013-01-08      Free    30               1       1
## 4 2013-01-15 Project B    30               0       0
## 5 2013-01-15      Free    10               1       1
## 6 2013-01-22 Project B    40               0       0
## 7 2013-01-29      Free    40               0       0
## 8 2013-02-05 Project C    40               0       0
于 2013-03-09T17:25:21.377 に答える