2013-03-09 5 views
1

Я обновил вопрос, так как а) я сформулировал вопрос непонятно с первой попытки, б) моя точная потребность также немного изменилась.Выберите последовательные записи даты

Я хочу особо поблагодарить Хеммо за большую помощь до сих пор - и извинения за то, что я недостаточно ясно сформулировал свой вопрос. Его код (который касается более ранней версии проблемы) показан в разделе ответа.

На высоком уровне - я ищу код, который помогает идентифицировать и различать различные блоки последовательного свободного времени разных людей. Более конкретно - код в идеале:

  • Проверить whehter деятельность помечена как «Free»
  • Проверьте ли последовательные недели (на неделю раньше, неделю позже) время, затрачиваемого одним и тем же лицом, где также помечен как " Свободно".
  • Дайте весь блок последовательных недель этого человека, помеченных как «Свободный» индикатор в желаемом столбце результата. Обратите внимание, что длина периодов времени (например, 1 неделя consec, 4 недели consec, 8 consec weeks) будет изменяться
  • Наконец, из-за необходимости дальнейшего анализа характеристик этих кластеров различные блоки должны получать разные индикаторы. (Например, марш блок Павла будет иметь значение 1, значение мая блок 2 и блок Кима в марте будет иметь значение 3)

Надеюсь, это становится более ясным, когда один смотрит на примере dataframe (см желаемая итоговая колонка)

Любая помощь, которую высоко оценили, код для тестового блока данных ниже.

Большое спасибо заранее,

Вт

примера (обратите внимание, что последний столбец должен быть сформирован с помощью кода, чисто включены в качестве иллюстрации):

  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 

код для dataframe:

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 
+0

Это все еще неясно, что ваши выходные средства. Не могли бы вы рассказать? – flodel

ответ

2

EDIT: Это было грязно уже, поскольку вопрос был отредактирован несколько раз, поэтому я удалил старые ответы.

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 

Это должно сделать это, хотя приведенный выше код, вероятно, далек от оптимального.

+0

Hemmo - большое спасибо. обратите внимание, что я скорректировал вопрос - извинения за неясность. попытался поиграть/скорректировать свое предыдущее предложение, но изо всех сил пытался выделить весь блок за несколько недель того же кода. Попытался увеличить вашу функцию, что с дополнительной строкой, которая также проверяет «по вертикали» предыдущие оценки ожидаемого результата, чтобы определить, нужен ли новый индикатор, но не смог заставить его работать – user1885116

+0

@ user1885116 Я создал новую функцию, которая должна делать то, что вы хотеть.В будущем я предлагаю вам задать новый вопрос, так как теперь результат совершенно другой, чем раньше, другие ответы стали устаревшими, и позже трудно читать то, что здесь происходит. –

+0

Спасибо hemmo (снова). Должен ли я передать все это как новый вопрос? Единственное, что ваш новый код не охватывает, - это если предыдущая строка не является предыдущей неделей (например, если в заданную дату есть несколько записей проекта, а бесплатный вход предыдущей недели - 2 или 3 или более строк вверх). К сожалению, из-за структурной базы данных не отфильтровывайте это. однако - я могу создать небольшой цикл, чтобы проверить предыдущие 5-10 строк или работать с функцией недели). Еще раз спасибо -Wouter – user1885116

1

Используя замечание user1885116 к ответу Hemmo в качестве руководства к тому, что желательно, здесь несколько более простой подход:

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 
Смежные вопросы