【问题标题】:Subsetting data based on variable start date in R基于R中可变开始日期的子集数据
【发布时间】:2014-09-18 20:09:06
【问题描述】:

我正在尝试编写一些代码,该代码将根据开始日期抓取数据帧的一部分,其中每个用户的每个开始日期都不同。

假设我有以下 data.frames(实际上我的数据集要大几个数量级,但这足以作为样本集)

df1:

 >   df
      name   start.date
1  Allison   2013-03-16
2   Andrew   2013-03-16
3     Carl   2013-03-16
4     Dora   2013-03-17
5   Hilary   2013-03-17
6    Louis   2013-03-18
7     Mary   2013-03-19
8   Mickey   2013-03-20

还有 df2:

> df2
       names X03.16.2013 X03.17.2013 X03.18.2013  X03.19.2013
2001 Allison           5           5           0           0
2002  Andrew           2           0           0           0
2003    Carl           10          8           11          10
2004    Dora           0           4           0           0
2005  Hilary           0           3           5           0
2006   Louis           0           0           8           3
2007    Mary           0           0           0           7
2008  Mickey           0           0           0           0

我将这两个数据帧合并为一个名为 tmp 的数据帧:

>tmp

   name   start.date         X03.16.2013 X03.17.2013 X03.18.2013  X03.19.2013
    1  Allison   2013-03-16         5           5           0           0
    2   Andrew   2013-03-16         2           0           0           0
    3     Carl   2013-03-16         10          8           11          10
    4     Dora   2013-03-17         0           4           0           0
    5   Hilary   2013-03-17         0           3           5           0
    6    Louis   2013-03-18         0           0           8           3
    7     Mary   2013-03-19         0           0           0           7
    8   Mickey   2013-03-20         0           0           0           0

我还有一个将 df2 的列名转换为日期的列表:

>dts

[1] "2014-03-16" "2014-03-17" "2014-03-18" "2014-03-19" 

我认为解决此问题的一种方法是使用以下嵌套循环将 df2 中每个用户开始日期之前出现的所有零条目更改为 NA:

for (i in 1:dim(tmp)[1]){
  for (j in 1:length(dts)){
    for (z in 4:dim(tmp)[2]){
    if (dts[j]< tmp$Date.of.Sign.Up[i]){
      tmp[i,z]<-NA
    } else {tmp[i,z]<-tmp[i,z]}
  }
}
}

这个循环的问题在于 1. 它会无限运行 2. 不起作用。无论开始日期如何,它都会将 tmp 中的所有值从 tmp[,3:end] 更改为零。理想情况下,我会得到这样的结果:

     name   start.date         X03.16.2013 X03.17.2013 X03.18.2013  X03.19.2013
  Allison   2013-03-16         5           5           0           0
   Andrew   2013-03-16         2           0           0           0
     Carl   2013-03-16         10          8           11          10
     Dora   2013-03-17         NA           4           0          0
   Hilary   2013-03-17         NA           3           5          0
    Louis   2013-03-18         NA           NA          8          3
     Mary   2013-03-19         NA           NA          NA         7
   Mickey   2013-03-20         NA           NA          NA         NA

有什么建议吗?提前谢谢!

【问题讨论】:

    标签: r date subset


    【解决方案1】:

    您可以将“tmp”重塑为长格式,将以前的标题转换为日期,将它们与开始日期进行比较,并在开始日期出现在“标题日期”之后时插入NA

    library(reshape2)
    
    # melt data from wide to long format
    df3 <- melt(tmp, id.vars = c("name", "start.date"))
    
    # convert 'variable' to class Date
    df3$variable <- as.Date(df3$variable, format = "X%m.%d.%Y")
    
    # compare start dates with 'variable dates' and insert NA
    df3$value[df3$start.date > df3$variable] <- NA
    
    # reshape back to wide
    dcast(df3, name + start.date ~ variable)
    
    #      name start.date 2013-03-16 2013-03-17 2013-03-18 2013-03-19
    # 1 Allison 2013-03-16          5          5          0          0
    # 2  Andrew 2013-03-16          2          0          0          0
    # 3    Carl 2013-03-16         10          8         11         10
    # 4    Dora 2013-03-17         NA          4          0          0
    # 5  Hilary 2013-03-17         NA          3          5          0
    # 6   Louis 2013-03-18         NA         NA          8          3
    # 7    Mary 2013-03-19         NA         NA         NA          7
    # 8  Mickey 2013-03-20         NA         NA         NA         NA
    

    我们在“tmp”中循环“日期列名”的另一种可能性:

    dates <- names(tmp)[-c(1, 2)]
    
    tmp[ , -c(1, 2)] <- sapply(dates, function(x){
      date <- as.Date(x, format = "X%m.%d.%Y")
      tmp[ , x][df2$start.date > date] <- NA
      tmp[ , x]
    })
    
    tmp  
    #      name start.date X03.16.2013 X03.17.2013 X03.18.2013 X03.19.2013
    # 1 Allison 2013-03-16           5           5           0           0
    # 2  Andrew 2013-03-16           2           0           0           0
    # 3    Carl 2013-03-16          10           8          11          10
    # 4    Dora 2013-03-17          NA           4           0           0
    # 5  Hilary 2013-03-17          NA           3           5           0
    # 6   Louis 2013-03-18          NA          NA           8           3
    # 7    Mary 2013-03-19          NA          NA          NA           7
    # 8  Mickey 2013-03-20          NA          NA          NA          NA
    

    【讨论】:

    • 当你写声明df3 &lt;- melt(df2, id.vars = c("name", "start.date"))时你的意思是说df3 &lt;- melt(df, id.vars = c("name", "start.date"))
    • 对于您的第二个解决方案,我没有放入任何 NA。我不确定您在提到 df2 时是否要说 tmp。我使用了以下代码两次,一次是假设您在说 df2 的任何地方都说 tmp,一次是原样:dates &lt;- names(tmp)[-c(1, 2,3)]tmp[ , -c(1,2,3)] &lt;- sapply(dates, function(x){ date &lt;- as.Date(x, format = "X%m.%d.%Y") tmp[ , x][tmp$Date.of.Sign.Up &lt; date] &lt;- NA tmp[ , x]})
    • 两次都没有插入 NAs
    • 对不起,我弄乱了数据框的名称。我已经编辑了我的答案。
    • 嗯,即使编辑改为使用 tmp,我发现这不是一个可行的解决方案,因为在开始日期之前没有输入 NA 值来代替零。我输入了以下内容(请注意,对于我更大的数据集,我还需要排除 tmp 的第三列,因为它包含不相关的信息)tmp[ , -c(1,2,3)] &lt;- sapply(dates, function(x){ date &lt;- as.Date(x, format = "X%m.%d.%Y") tmp[ , x][tmp$Date.of.Sign.Up &gt; date] &lt;- NA tmp[ , x]})
    猜你喜欢
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2017-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-26
    相关资源
    最近更新 更多