【问题标题】:Dataset Manipulation with Factors and Time variables in R在 R 中使用因子和时间变量进行数据集操作
【发布时间】:2017-11-21 02:20:40
【问题描述】:

我有一个关于数据操作的简单问题。给定以下数据集:

n = c("john","jane","tim","john","jimmy","tim","jane","john","jimmy")
s = c("2012-03-21","2013-02-12","2014-01-01","2012-05-21","2010-12-17","2012-01-21","2013-03-12","2013-08-21","2010-09-17")

df = data.frame(n,s)
     n      s
1  john 2012-03-21
2  jane 2013-02-12
3   tim 2014-01-01
4  john 2012-05-21
5 jimmy 2010-12-17
6   tim 2012-01-21
7  jane 2013-03-12
8  john 2013-08-21
9 jimmy 2010-09-17

我想创建第三列数据,其中我计算了每个人从他们最早的时间点开始的月数。它会如下所示:

         n      s        output
    1  john 2012-03-21     0
    2  jane 2013-02-12     0
    3   tim 2014-01-01     24
    4  john 2012-05-21     2
    5 jimmy 2010-12-17     3
    6   tim 2012-01-21     0
    7  jane 2013-03-12     1
    8  john 2013-08-21    17
    9 jimmy 2010-09-17     0

如您所见,以john为例,最早的时间点是2012-03-21,所以它计算的月数是从2012-03-21到2012-05-21,再到2013-08- 21 并将输出放在适当的行中。

我认为 dplyr 或 apply 函数会派上用场,但我发现我正在为不应该太困难的事情编写大量代码。

感谢您的帮助。

【问题讨论】:

  • 为什么john的最后一点是73.5? 2013-08-21 - 2012-03-21 不应该是 17 岁吗?
  • 很抱歉是手动计算这些并更改了一些日期以使其更易于查看,但一定忘记更改该输出。谢谢。

标签: r datetime dataset dplyr apply


【解决方案1】:

使用dplyr 我们可以做到:


n = c("john","jane","tim","john","jimmy","tim","jane","john","jimmy")
s = c("2012-03-21","2013-02-12","2014-01-01","2012-05-21","2010-12-17","2012-01-21","2013-03-12","2013-08-21","2010-09-17")
s = as.Date(s)
df = data.frame(n,s)


library(dplyr)

df %>% 
  group_by(n) %>% 
  mutate(out = round(as.integer(difftime(s, s[which.min(s)], units = 'days')) / 30, 0))
#> # A tibble: 9 x 3
#> # Groups:   n [4]
#>        n          s   out
#>   <fctr>     <date> <dbl>
#> 1   john 2012-03-21     0
#> 2   jane 2013-02-12     0
#> 3    tim 2014-01-01    24
#> 4   john 2012-05-21     2
#> 5  jimmy 2010-12-17     3
#> 6    tim 2012-01-21     0
#> 7   jane 2013-03-12     1
#> 8   john 2013-08-21    17
#> 9  jimmy 2010-09-17     0

与往常一样,计算月数很棘手,因为不同的月份有不同的长度。

【讨论】:

    【解决方案2】:

    在我的回答中,我使用lubridate 包来确保df 中的s 列不会被视为字符串或因子:

    library(dplyr)
    library(lubridate)
    df$s = as_date(df$s)
    

    为开始日期创建一个单独的数据框:

    df.startdate = df %>% group_by(n) %>% summarise(start_date = min(s))
    

    现在将主df 合并到新构建的df.startdate

    answer = merge(df, df.startdate, by = "n") %>% 
        mutate(output = interval(start_date, s) %/% months(1))
    

    【讨论】:

    • 这也很好用,遗憾的是不能标记多个答案。感谢您发布并帮助解决此问题!
    • @Tim 真的吗?我倾向于投票给所有对我的问题给出良好答案的人:(
    • 糟糕,你绝对值得一票!自从我来到这里已经有一段时间了。再次感谢
    猜你喜欢
    • 2014-08-11
    • 1970-01-01
    • 2018-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    • 1970-01-01
    相关资源
    最近更新 更多