【问题标题】:Assigning an ID vector to a dataframe in R, based on week number (ISOweek)根据周数(ISOweek)将 ID 向量分配给 R 中的数据框
【发布时间】:2016-06-18 16:46:21
【问题描述】:

我正在尝试将 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,“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") 

“aa”是我想在 fID 向量中分配的代码,仅在 2004-W53 和 2015-W53 周之间。我不确定 R 是否会在与周一起使用时识别 > 或

我也尝试使用 ifelse,但仅适用于船主在整个数据集中没有变化的船(在这种情况下,星期无关紧要)。像这样的东西,(也没有工作!):

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

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

更新: 这是我拥有的另一个 df 的示例,其中详细说明了谁拥有哪条船以及何时拥有:

        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>

您可以看到 James 在 Bob 之后拥有“Mousa”,而 Wayne 在 Bill 之后拥有“Yell”。我需要 James 的 ID 在他同时拥有 Foula 和 Mousa 的那几周内保持为“ac”(也就是说,我可以通过时间追踪渔夫,而不仅仅是船)。

【问题讨论】:

  • 您没有提供 id 的通用规则。你只给出了'aa'的例子。例如,你怎么知道哪些行应该得到“ac”?
  • @PierreLafortune ac 将转到该船 = Foula 的所有行,以获取相关人员拥有该船的周数。然后可以在人“ac”之后将船卖给其他人,然后需要一个新的所有者 ID。我总共有 99 位船主(每个船主都有一个 ID)的所有船舶所有权周数。
  • 至于过滤日期,为什么不保留(也)准确的源日期?在它们上,您可以使用“”
  • @EricLecoutre 我也许应该有。数据框中有许多变量(着陆、温度、风等),它们都被分组为几周进行分析。这是在决定将渔夫 ID 添加到数据框之前完成的。

标签: r dataframe if-statement week-number


【解决方案1】:

这就是我要做的,不过,可能有更好的方法。我使用dplyr,但仅略微计入每周的观察次数。我相信其他一切都是在 base 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
....

【讨论】:

  • 如果我理解正确,假设船只不易手,您的解决方案将运作良好。不幸的是,买了新船,卖掉了旧船(通常在船队内,所以相同的船名属于新人/ID)。我确实为每个人/船组合创建了另一个 df - 带有“从到”日期(周数)。谢谢
  • 嗯,每次船易手时,您都必须更新名称。如果您有购买/出售发生的日期,您可以在这些周进行子集化并重新应用 ID。如果你把新的df (它的一部分)放在上面,那么想出一种以编程方式完成它的方法会更容易。
  • 我添加了一个船期的示例 df。希望它能让我更清楚我在寻找什么。谢谢。
  • 显然有了完整的数据集,那些NAs 就会消失。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-04
  • 2017-09-22
  • 2015-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多