根据周数(ISOweek)将ID向量分配给R中的数据帧

时间:2016-06-18 16:46:22

标签: r if-statement dataframe week-number which

我正在尝试将ID代码添加到数据框(筒子架),这是2000年至2015年贝类登陆的时间序列。前几列如下:

    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的ID,Yell的“ab”,上面的行中的Foula等的“ac”。如果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") 

“aa”是我想在fID向量中分配的代码,仅在2004-W53和2015-W53周之间。我不确定R是否会识别&gt;或者&lt;当使用周数时 - 我确实发现unclass(creel $ week)给出了可以替代使用的周数的实际值。

我也尝试过使用ifelse,但仅适用于所有者在整个数据集中没有变化的船只(在这种情况下,周是不相关的)。像这样的东西,(也没用!):

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

数据集非常大,但如果更容易的话,我很乐意单独做每个人/船组合。

更新: 这是我拥有的另一个例子,详细说明谁拥有哪艘船,以及何时:

        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>

你可以看到詹姆斯拥有鲍勃之后的“穆萨”,并且韦恩在比尔之后拥有了“大喊”。我需要詹姆斯的身份证在他拥有Foula和Mousa的几个星期内保持“交流”(即我可以追踪渔夫的时间,不一定只是船)。

1 个答案:

答案 0 :(得分: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

编辑:我花了一个多小时试图弄清楚如何使用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
....