【问题标题】:Header names as dates in r标题名称作为 r 中的日期
【发布时间】:2014-08-26 00:50:35
【问题描述】:

我正在尝试计算用户的“死亡”,这意味着我想确定从用户注册某个程序到他们不再在该程序中处于活动状态之间的持续时间。我有两个使用read.csv("filename",header=TRUE) 读入的文件:

 >   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-19
7     Mary   2013-03-20
8   Mickey   2013-03-20

还有文件 2:

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

我想做的是将 df2 的标题名称转换为日期,这样我就可以创建一个新的数据框,其中包含用户名、开始日期和“死亡天数”,这将是当用户df2 中的条目为 0:

      name   start.date   days.to.death
1  Allison   2013-03-16   33
2   Andrew   2013-03-16   0
3     Carl   2013-03-16   NA
4     Dora   2013-03-17   NA
5   Hilary   2013-03-17   31
6    Louis   2013-03-19   NA
7     Mary   2013-03-20   30
8   Mickey   2013-03-20   28

请注意,安德鲁从未“活着”,而卡尔、朵拉和路易斯还没有“死去”。我对 R 还是比较陌生,因此非常感谢任何输入!

【问题讨论】:

  • 这是 df2 的列标题中的错字吗?都应该是 2013 年吗?
  • 我很抱歉。是的,df2 中的所有日期都应该是 2013 年

标签: r time-series


【解决方案1】:

假设 df2 的列标题中有错字,以下使用 dplyr 和 tidyr 的解决方案可以帮助您完成大部分工作...

  library(tidyr)
  library(dplyr)

  colnames(df)<-c("names", "start") #  To join dfs, the first column header needs to be identical to df2
  df$start<-as.Date(df$start, format="%m/%d/%Y") #formatting date

以下方法在 df2 上工作,方法是长形数据、格式化日期(类似于 MrFlick 的建议),然后只保留其中包含 0 的日期。然后它采用第一个实例(即假设您的日期从左到右按时间顺序排列的最早日期)。然后它计算从该日期(结束日期)到 df 的开始日期的日期差异。我使用了与 MrFlick 相同的格式 - 但您可以简单地将差异计算为整数。

  df2 %>% 
  filter(X04.16.2013!=0) %>%   #removes Andrew who has 0 in first date col
  gather(key,value,2:5) %>%     
  mutate(date=as.Date(key, format="X%m.%d.%Y")) %>%
  left_join(df) %>%
  filter(value==0) %>%
  group_by(names) %>%
  filter(date == nth(date, 1)) %>% 
  select(names, start, date) %>%
  mutate (daydiff=difftime(date,start, unit="days"))

给这个...

    names      start       date daydiff
1  Hilary 2013-03-17 2013-04-17 31 days
2 Allison 2013-03-16 2013-04-18 33 days
3  Mickey 2013-03-20 2013-04-18 29 days
4    Mary 2013-03-20 2013-04-19 30 days

应该很容易放入 NA 和那些从未生活过的人。也许这有点帮助?​​

【讨论】:

    【解决方案2】:

    具有正确格式的简单as.Date 会将列名转换为日期。首先,数据的可复制粘贴形式

    df<-structure(list(name = structure(1:8, .Label = c("Allison", "Andrew", 
    "Carl", "Dora", "Hilary", "Louis", "Mary", "Mickey"), class = "factor"), 
        start.date = structure(c(15780, 15780, 15780, 15781, 15781, 
        15783, 15784, 15784), class = "Date")), .Names = c("name", 
    "start.date"), row.names = c("1", "2", "3", "4", "5", "6", "7", 
    "8"), class = "data.frame")
    
    df2<-structure(list(names = structure(1:8, .Label = c("Allison", "Andrew", 
    "Carl", "Dora", "Hilary", "Louis", "Mary", "Mickey"), class = "factor"), 
        X04.16.2013 = c(5L, 0L, 8L, 6L, 2L, 18L, 4L, 9L), X04.17.2013 = c(5L, 
        0L, 8L, 4L, 0L, 10L, 7L, 5L), X04.18.2014 = c(0L, 0L, 11L, 
        9L, 0L, 8L, 7L, 0L), X04.19.2013 = c(0L, 0L, 10L, 3L, 0L, 
        3L, 0L, 0L)), .Names = c("names", "X04.16.2013", "X04.17.2013", 
    "X04.18.2014", "X04.19.2013"), class = "data.frame", row.names = c("2001", 
    "2002", "2003", "2004", "2005", "2006", "2007", "2008"))
    

    现在

    nn <- names(df2)[-1]
    dts <- as.Date(nn, format="X%m.%d.%Y")
    dts
    # [1] "2013-04-16" "2013-04-17" "2014-04-18" "2013-04-19"
    

    然后

    lastedateid<-apply(df2[,-1], 1, function(x) {i<-which(x==0); ifelse(length(i), head(i,1), NA)})
    lastdate <- dts[lastedateid]
    lastdate
    # [1] "2014-04-18" "2013-04-16" NA           NA           "2013-04-17"
    # [6] NA           "2013-04-19" "2014-04-18"
    

    只要df$name==df2$names

    transform(df, days.to.death=difftime(lastdate,start.date, unit="days"))
    

    假设 start.date 也是正确的 Date 类,将给出以下内容

         name start.date days.to.death
    1 Allison 2013-03-16      398 days
    2  Andrew 2013-03-16       31 days
    3    Carl 2013-03-16       NA days
    4    Dora 2013-03-17       NA days
    5  Hilary 2013-03-17       31 days
    6   Louis 2013-03-19       NA days
    7    Mary 2013-03-20       30 days
    8  Mickey 2013-03-20      394 days
    

    【讨论】:

      【解决方案3】:

      以下简单的代码可能有用:

      names(df2)[1] = 'name'
      merge(df, ddf2)
      dfm$days.to.death = ifelse(dfm[,3]==0,0,ifelse(dfm[,4]==0,31, ifelse(dfm[,5]==0,33,ifelse(dfm[,6]==0,28,NA))))
      
      dfm[,c(1,2,7)]
           name start.date days.to.death
      1 Allison 2013-03-16            33
      2  Andrew 2013-03-16             0
      3    Carl 2013-03-16            NA
      4    Dora 2013-03-17            NA
      5  Hilary 2013-03-17            31
      6   Louis 2013-03-19            NA
      7    Mary 2013-03-20            28
      8  Mickey 2013-03-20            33
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多