3

我是 R 的新用户,我有点卡住了,我的数据如下所示:

dates        temp
01/31/2011    40
01/30/2011    34
01/29/2011    30
01/28/2011    52
01/27/2011    39
01/26/2011    37
...
01/01/2011    31

我只想将温度控制在 40 度以下,并注明开始和结束的日期以及持续多少天,例如:

from         to           days
01/29/2011   01/30/2011     2
01/26/2011   01/27/2011     2

我尝试了 difftime 但它没有用,也许它可以使用一个功能。

任何帮助,将不胜感激。

4

3 回答 3

3

我会做这样的事情。我会data.table在这里使用。

df <- read.table(header=TRUE, text="dates        temp
01/31/2011    40
01/30/2011    34
01/29/2011    30
01/28/2011    52
01/27/2011    39
01/26/2011    37", stringsAsFactors=FALSE)

require(data.table)
dt <- data.table(df)
dt <- dt[, `:=`(date.form = as.Date(dates, format="%m/%d/%Y"), 
          id = cumsum(as.numeric(temp >= 40)))][temp < 40]
dt[, list(from=min(date.form), to=max(date.form), count=.N), by=id]

#    id       from         to count
# 1:  1 2011-01-29 2011-01-30     2
# 2:  2 2011-01-26 2011-01-27     2

这个想法是首先创建一个列,该dates列首先转换为Date格式。然后,另一列id找到 where 的位置temp >= 40并使用它来创建在 two 范围内的值组temp>=40。也就是说,如果你有c(40, 34, 30, 52, 39, 37),那么你会想要c(1,1,1,2,2,2)。也就是说, 到 values 之间的所有内容都>= 40必须属于同一组(34, 30 -> 1 和 39, 37 -> 2)。这样做之后,我会删除temp >= 40条目。

然后,您可以按此组拆分,然后取minand maxlength(.)默认存储在 中.N)。

于 2013-03-25T11:05:23.117 回答
3

不像 Arun 那样优雅,data.table但这里有base解决方案

DF <- read.table(text = "dates        temp\n01/31/2011    40\n01/30/2011    34\n01/29/2011    30\n01/28/2011    52\n01/27/2011    39\n01/26/2011    37", 
    header = TRUE, stringsAsFactors = FALSE)

DF$dates <- as.POSIXct(DF$dates, format = "%m/%d/%Y")
DF <- DF[order(DF$dates), ]
DF$ID <- cumsum(DF$temp >= 40)
DF2 <- DF[DF$temp < 40, ]

# Explanation split : split DF2 by DF2$ID 
# lapply : apply function on each list element given by split
# rbind : bind all the data together

do.call(rbind, lapply(split(DF2, DF2$ID), function(x) 
            data.frame(from = min(x$dates),  
                       to = max(x$dates), 
                       count = length(x$dates))))
##         from         to count
## 0 2011-01-26 2011-01-27     2
## 1 2011-01-29 2011-01-30     2
于 2013-03-25T11:42:03.350 回答
3

首先读入数据。 read.zoo在一行中处理许多细节,包括将数据重新排序为升序并将日期转换为"Date"类。如果z是生成的动物园对象,则coredata(z)给出温度并time(z)给出日期。

Lines <- "
dates        temp
01/31/2011    40
01/30/2011    34
01/29/2011    30
01/28/2011    52
01/27/2011    39
01/26/2011    37
"

library(zoo)
z <- read.zoo(text = Lines, header = TRUE, format = "%m/%d/%Y")

所有这一切的症结在于使用rle哪些计算lengths以及values我们可以从中推导出所有数量:

tt <- time(z)
with(rle(coredata(z) < 40), {
   to <- cumsum(lengths)[values]
   lengths <- lengths[values]
   from <- to - lengths + 1
   data.frame(from = tt[from], to = tt[to], days = lengths)
})

使用显示的输入数据的前 6 行,我们得到:

       from          to   days
1 2011-01-26 2011-01-27      2
2 2011-01-29 2011-01-30      2
于 2013-03-25T15:53:59.290 回答