2016-06-18 5 views
0

Я пытаюсь добавить идентификационные коды в dataframe (creel), который является временным рядом посадок моллюсков с 2000 по 2015 год. несколько столбцов приведены ниже:Присвоение ID-вектора в dataframe в R, на основе номера недели (ISOweek)

head(creel,10) 

      week year  boat fID 
    1 2000-W01 2000  Mousa NA 
    2 2000-W01 2000  Yell NA 
    3 2000-W01 2000  Foula NA 
    4 2000-W01 2000  Foula NA 
    5 2000-W02 2000  Foula NA 
    6 2000-W02 2000 Papa Stour NA 
    7 2000-W02 2000  Fetlar NA 
    8 2000-W02 2000  Unst NA 
    9 2000-W03 2000  Foula NA 
    10 2000-W03 2000 Fair Isle NA 
    ... 

ID для владельцев лодок, которые меняются со временем. У меня есть данные о том, кто владеет лодкой и когда, и создали уникальные коды для добавления в столбец «fID» (который я создал и заполнил NA). Для целей этого, скажем, «aa» - это идентификатор для Mousa, «ab» для Yell, «ac» для Foula и т. Д. В строках выше. Если владелец Mousa покупает новую лодку, которая находится в кадре данных, «aa» отправится вместе с ними и будет назначено новое имя лодки.

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

creel$week <- as.ordered(creel$week) 
    #Levels:2000-W01 < 2000-W02 < 2000-W03 < 2000-W04 < 2000-W05<...<2015-W53 

Я попытался добавить уникальные FID код для одной лодки, чтобы начать с, но это не так работа:

creel$fID[which(creel$boat=="Mousa" & creel$week=>"2004-W53" & creel$week=<"2015-W53"),] <- as.factor("aa") 

«аа» код, который я хотел бы назначить в векторе FID, только между неделями 2004-W53 и 2015-W53. Я не был уверен, узнает ли R> или < при использовании с неделями - я обнаружил, что unclass (creel $ week) дает фактические значения для чисел недели, которые, возможно, могут быть использованы вместо этого.

Я также пробовал использовать ifelse, но только для лодок, где владелец не менялся по всему набору данных (в этом случае неделя не имеет значения). Нечто подобное, (тоже не работает!):

creel$fID <- ifelse(creel$boat=="Unst", as.factor(creel$fID=="ad"), NA) 

Набор данных очень большой, хотя я рад сделать каждый комбо человек/лодка индивидуально, если это проще.

UPDATE: Вот пример другого ДФ у меня есть, что детали, которые принадлежат какой лодке, и когда:

 Person code  boat1 date_from date_to boat2 date_from2 date_to2 
    1  Bob aa  Mousa 2002-W53 2005-W34 <NA>  <NA>  <NA> 
    2  Bill ab  Yell 1999-W52 2010-W52 <NA>  <NA>  <NA> 
    3 James ac  Foula 1999-W52 2005-W26 Mousa 2005-W35 2015-W53 
    4  Tom ad  Unst 1999-W52 2015-W53 <NA>  <NA>  <NA> 
    5 Willie ae Fetlar 2007-W35 2015-W53 <NA>  <NA>  <NA> 
    6 Wayne af  Yell 2011-W01 2013-W13 <NA>  <NA>  <NA> 

Вы можете видеть, что Джеймс владел «Мусы» после Боба, и что Уэйн принадлежал «Yell» после Билла. Мне нужен идентификатор Джеймса, чтобы он оставался «ac» в течение недель, в течение которых ему принадлежали как Foula, так и Mousa (т. Е. Я мог проследить рыбака во времени, а не только от лодки).

+0

Вы не указали общее правило для идентификаторов. Вы дали только пример «aa». Откуда вы знаете, какие строки должны получить «ac», например? –

+0

@PierreLafortune ac будет ходить во все ряды, где лодка = Foula, за номера недели, которые этот человек владел лодкой. Затем лодку можно продать кому-то еще после человека «ac», тогда потребуется новый идентификатор владельца. У меня есть все номера недели для владения лодкой всего 99 владельцев (каждый с идентификатором). –

+0

Что касается фильтрации по датам, почему бы вам не сохранить (также) точные даты источника? На них вы можете использовать «<" and ">» –

ответ

0

Вот что я хотел бы сделать, хотя, вероятно, есть лучшие методы. Я использую dplyr, но лишь незначительно рассчитываю на наблюдения в неделю. Я считаю, что все остальное делается в базе R.

library(dplyr) 

creel$ref.week<- rep(1:length(unique(creel$week)), 
        (creel %>% group_by(week) %>% summarise(n= n()))$n) 
#add a reference column 

creel.subset<-creel[creel$ref.week %in% c(1,2),] 
#subset the weeks you want by that reference column. Obviously your 
#reference weeks will be different. 

creel.subset$fID<-with(creel.subset, ifelse(boat =="Mousa", "aa", 
              ifelse(boat == "Yell", "ab", 
                ifelse(boat == "Foula", "ac", NA)))) 
#name the fID's however you want. This is just example. 

creel.subset 

     week year  boat fID ref.week 
1 2000-W01 2000  Mousa aa  1 
2 2000-W01 2000  Yell ab  1 
3 2000-W01 2000  Foula ac  1 
4 2000-W01 2000  Foula ac  1 
5 2000-W02 2000  Foula ac  2 
6 2000-W02 2000 Papa_Stour <NA>  2 
7 2000-W02 2000  Fetlar <NA>  2 
8 2000-W02 2000  Unst <NA>  2 

Если вы хотите, чтобы поставить все это вместе в один большой data.frame:

creel.back_together<-rbind(creel.subset, creel[!creel$ref.week %in% c(1,2),]) 
creel.back_together 
     week year  boat fID ref.week 
1 2000-W01 2000  Mousa aa  1 
2 2000-W01 2000  Yell ab  1 
3 2000-W01 2000  Foula ac  1 
4 2000-W01 2000  Foula ac  1 
5 2000-W02 2000  Foula ac  2 
6 2000-W02 2000 Papa_Stour <NA>  2 
7 2000-W02 2000  Fetlar <NA>  2 
8 2000-W02 2000  Unst <NA>  2 
9 2000-W03 2000  Foula <NA>  3 
10 2000-W03 2000 Fair_Isle <NA>  3 

Edit: я потратил больше часа, пытаясь выяснить, как чтобы сделать эту работу с значениями ISOweek, но не повезло. Я определенно думаю, что было бы легче иметь дело с регулярными значениями даты. Вот мое решение с дополнительным data.frame, который вы предоставили, который я назвал mydata, хотя он в конечном итоге стал mydata3делать ожидать, что это будет довольно медленным для больших наборов данных, но я уверен, что он делает то, что вы хотели:

library(ISOweek) 
library(lubridate) 
library(data.table) 

fullWeek<-function(x){ 
    paste(x, "-1", sep = "") 
} 

creel$week<-as.character(creel$week) 
creel$week<-fullWeek(creel$week) 
creel$week<-ISOweek2date(creel$week) 
creel$week<-as_date(ymd(creel$week)) 

mydata1<-mydata[,1:5] 
mydata2<-mydata[,c(1:2,6:8)] 
colnames(mydata2)<-colnames(mydata1) 
mydata3<-na.omit(rbind(mydata1, mydata2)) 
mydata3[,4:5]<-sapply(mydata3[,4:5], fullWeek) 
mydata3[,4:5]<-lapply(mydata3[,4:5], ISOweek2date) 
mydata3[,4:5]<-lapply(mydata3[,4:5], function(x) as_date(ymd(x))) 
## undoing all of the ISOweek nonsense 

for(i in 1:nrow(mydata3)){ 
    boat1<-mydata3[i,]$boat1 
    date_from<-mydata3[i,]$date_from 
    date_to<-mydata3[i,]$date_to 
    code<-mydata3[i,]$code 

    for(j in 1:nrow(creel)){ 
    boat2<-creel[j,]$boat 
    date<-creel[j,]$week 

    if(boat1 == boat2 && date %between% c(date_from, date_to)) { 
    creel[j,]$fID<-code 
    } 
    } 
} 

creel 

     week year  boat fID 
2000-01-03 2000  Mousa <NA> 
2000-01-03 2000  Yell ab 
2000-01-03 2000  Foula ac 
2000-01-03 2000  Foula ac 
2000-01-10 2000  Foula ac 
2000-01-10 2000 Papa_Stour <NA> 
2000-01-10 2000  Fetlar <NA> 
2000-01-10 2000  Unst ad 
2000-01-17 2000  Foula ac 
2000-01-17 2000 Fair_Isle <NA> 

Теперь, если вы решите, что вы хотите работать с ISOweek датами из удобства , то:

creel$week<-ISOweek(creel$week) 
creel 

    week year  boat fID 
2000-W01 2000  Mousa <NA> 
2000-W01 2000  Yell ab 
2000-W01 2000  Foula ac 
2000-W01 2000  Foula ac 
2000-W02 2000  Foula ac 
.... 
+0

Если я правильно понимаю, ваше решение будет работать хорошо, если лодки не изменят руки. К сожалению, новые лодки куплены, а старые продаются (часто в пределах флота, поэтому одно и то же название лодки переходит к новому человеку/ID). Я создал еще один df - с «от-до» датами (номерами недель) для каждой комбинации человек/лодка. Спасибо –

+0

Ну, вам нужно будет обновлять имена каждый раз, когда лодка сменила руки. Если у вас были даты, когда были куплены покупки/продажи, вы можете подмножество в эти недели и повторно применить идентификаторы. Если вы поместите новый 'df' вверх (часть его), тогда было бы проще придумать способ сделать это программно. –

+0

Я добавил пример df дат лодки. Надеюсь, это немного улучшит то, что я ищу. Благодарю. –