【问题标题】:How to Find a Conditional Difference by Day in R如何在 R 中按天查找条件差异
【发布时间】:2014-08-20 03:06:48
【问题描述】:

我有一个数值变量,称之为“Blah”。 Blah 在一天中以不同的时间间隔进行测量,并且一直在增加。我想找出每天 Blah 的第一次和最后一次观察之间的差异,并制作一张每天 Blah 增加总量的表格。

稍微复杂一点的是,如果 Blah 足够高,它将重置为非常低的数字。这总是以相同的(当前未知)数量和每天一次的最大速率发生。

一些可能很重要的细节:

Blah 也在不同的命名位置进行测量。我想要一个按位置统计的数据框。 :)

时间变量的格式为“mm/dd/yyyy hh:mm:ss”

这是我想出的总体大纲。我遇到的一个问题是我没有过多地使用 POSIXct 对象,也不知道如何获取这些值并实现这一点。

A<-first value of Day
B<-last value of Day
C<-Maximum value of Blah from a day where reset happens (last value before reset)

For (each Day)
   For (each Location)

     If A < B 
        Then 
           DayTotal = B-A
        Else
            DayTotal = (C-A)+B

编辑:

我这里有一些格式错误的数据。下面是正确的格式。


提前感谢您的帮助!

-迈克尔

另外,在 Blah 重置的那一天,A 将永远大于 B。

编辑 2 号

天哪,我是一个可怕的人。数据实际上是这样的

   DESCRIPTION  rawCount   localDateTime
1   Arch Exit    33166  2014-05-23 07:55:05
2   Arch Exit    33167  2014-05-23 08:00:06
3   Arch Exit    33170  2014-05-23 08:10:06
4   Arch Exit    33173  2014-05-23 08:15:05
5   Arch Exit    33175  2014-05-23 08:20:05
6   Arch Exit    33178  2014-05-23 08:25:06
7   Northside    48073  2014-05-24 15:01:40
8   Northside    48119  2014-05-24 15:05:49
9   Northside    48167  2014-05-24 15:10:59
10  Northside    48237  2014-05-24 15:20:49
11  Northside       73  2014-05-24 15:25:59
12  Northside      350  2014-05-24 15:35:49
13  Northside     1430  2014-05-24 15:44:06
14  Northside     2554  2014-05-24 16:00:49

(假设上面的数据每天都是完整的)我希望结果看起来像

DESCRIPTION  totalCount     Date
Arch Exit       12       2014-05-23
Northside      2718      2014-05-23

另一个编辑

好的,所以使用下面的答案,我做了以下我认为可以做到的事情。

rawDiff 是一个已经存在的变量(在 excel 中完成....yikes), parse_date_time 是 Lubridridate 包中的一个函数,“Full”是我的数据,“localdate”是我想要的日期变量。

blahblah<-with(Full, tapply(rawDiff, list(parse_date_time(Full$localDate, "mdy"),          DESCRIPTION), function(x) {
sum(x[x>=0])}))

NA 有一些奇怪之处,即使用单独的预制差异变量似乎有所帮助。另外,当它重置差异为负时,我只取了非负差异。

【问题讨论】:

  • 您确实应该包含一些示例数据和该数据所需的输出。阅读how to make a great R reproducible example 获取提示和建议。
  • 好的,我尝试根据您的要求进行编辑。一开始就应该这样做。我的坏哟。
  • 老兄。停止更改您的问题并阅读提供的答案哟!我花了几秒钟来更改 @MrFlick 原始答案中的变量名称以反映您的新变量并得到您期望 G 的答案。
  • 老兄!我没有改变问题只是数据是什么样的。 :)
  • @Michael,您似乎还没有回答这个问题。你能说明你仍然卡在哪里吗?

标签: r conditional posixct


【解决方案1】:

在寻求此类帮助时,提供示例数据和所需的输出非常有用。由于您没有提供,我将使用它(更新以匹配编辑 2 中的变量名称)

#sample data
set.seed(15)
dd<-data.frame(
    DESCRIPTION=rep(letters[1:3], 9*5),
    rawCount=cumsum(rpois(3*5*9, 4)) %% 75,
    localDateTime=rep(seq(as.POSIXct("2001-01-01"), as.POSIXct("2001-01-03"), 
        by="6 hours"), each=5*3)
)

我还将定义一个辅助函数,该函数将通过向下转换为一个简单的“日期”类来从 POSIXct 值中删除时间

droptime<-as.Date

那我们就可以了

with(dd, tapply(rawCount, list(droptime(localDateTime), DESCRIPTION), function(x) {
    d <- diff(x)
    d[d<0] <- tail(x,-1)[d<0]
    sum(d)
}))

或在 Edit 2 中获取表单

aggregate(rawCount~droptime(localDateTime)+DESCRIPTION, dd, FUN=function(x) {
    d <- diff(x)
    d[d<0] <- tail(x,-1)[d<0]
    sum(d)
})

这是针对每个位置/日期组合的,它将计算值的范围。我稍微重写了您的定义以查看成对差异,如果差异为负数,假设我们已经从零重新开始(这将允许数字重置两次的情况,即使您不会发生这种情况)。 tapply 版本将返回一个矩阵

             a   b   c
2001-01-01 221 233 243
2001-01-02 230 232 219
2001-01-03  32  34  36

日期值的字符串版本作为行名,位置作为列名或

  droptime(localDateTime) DESCRIPTION rawCount
1              2001-01-01           a      221
2              2001-01-02           a      230
3              2001-01-03           a       32
4              2001-01-01           b      233
5              2001-01-02           b      232
6              2001-01-03           b       34
7              2001-01-01           c      243
8              2001-01-02           c      219
9              2001-01-03           c       36

使用aggregate 方法(这里保留了 Date 类)。


要使用更新后的示例数据(编辑 1),您可以使用

sapply(xx[-1], function(x,g) {
    tapply(x, g, function(x) {
        d <- diff(x)
        d[d<0] <- tail(x,-1)[d<0]
        sum(d)
    })  
}, g=xx[[1]])

得到

  06/24/2014 06/25/2014
A          8         52
B          4         57

【讨论】:

  • 太棒了!给我几分钟检查一下。感谢您的帮助,因为这需要我永远弄清楚!
  • 老兄,我搞砸了数据的格式。日期实际上是另一个变量。
  • 我已更新我的原始答案以匹配编辑 2 中的变量名称。
【解决方案2】:

@MrFlick 的答案可以很容易地适应您的新数据,但我将分享一个变体来表明,由于您已经定义了逻辑,因此几乎可以逐字翻译。

我们从一个查看向量的简单函数开始。

myFun <- function(x) {
  A <- x[1]                    # What's the first value?
  B <- x[length(x)]            # What's the last value?
  if (B < A) {                 # If the last value is less than the first
    FLAG <- which(diff(x) < 0) # Identify where the value changes...
    C <- x[FLAG]               # ... and extract it
    C - A + B                  # Calculate according to your defined logic
  } else {                     # Otherwise, if things look straightforward
    B - A                      # Just calculate the difference
  }
}

拥有该函数后,您可以使用 R 中提供的众多“聚合”函数之一:例如,tapplybyaggregate。这些聚合函数将处理您的问题逻辑中的“每天,每个位置”部分。

这里是aggregate,因为它最接近您想要的输出:

aggregate(rawCount ~ DESCRIPTION + as.Date(localDateTime), mydf, myFun)
#   DESCRIPTION as.Date(localDateTime) rawCount
# 1   Arch Exit             2014-05-23       12
# 2   Northside             2014-05-24     2718

为此,我使用了以下示例数据:

mydf <- structure(list(
  DESCRIPTION = c("Arch Exit", "Arch Exit", "Arch Exit", "Arch Exit", 
                  "Arch Exit", "Arch Exit", "Northside", "Northside", 
                  "Northside", "Northside", "Northside", "Northside", 
                  "Northside", "Northside"), 
  rawCount = c(33166L, 33167L, 33170L, 33173L, 33175L, 33178L, 48073L, 
               48119L, 48167L, 48237L, 73L, 350L, 1430L, 2554L), 
  localDateTime = structure(c(1400831705, 1400832006, 1400832606, 
                              1400832905, 1400833205, 1400833506, 
                              1400943700, 1400943949, 1400944259, 
                              1400944849, 1400945159, 1400945749, 
                              1400946246, 1400947249), 
                            class = c("POSIXct", "POSIXt"), tzone = "GMT")), 
                  .Names = c("DESCRIPTION", "rawCount", "localDateTime"), 
                  row.names = c("1", "2", "3", "4", "5", "6", "7", "8", 
                                "9", "10", "11", "12", "13", "14"), 
                  class = "data.frame")

【讨论】:

  • 感谢您的详细解释。
  • 说真的,感谢所有帮助。很高兴这个网站有这么多人愿意提供帮助,因为搜索论坛会让人非常抓狂。
  • @Michael,没问题。 尝试提供可重现的数据示例,就像我在回答中所做的那样,就像 MrFlick 在他的回答中所做的那样。它使其他人能够更轻松地复制并粘贴到他们的环境中,并检查答案是否符合您的预期,从而使每个人的工作都更加轻松。我希望你不介意我的家伙和你的模仿:-)
  • 哈哈哈......绝对不是。我不容易分阶段!我喜欢一点俏皮的罗纹。啊,我明白你所说的数据是可重现的。我以后会这样做的。
猜你喜欢
  • 2020-10-12
  • 2011-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 2021-12-31
  • 2012-08-29
相关资源
最近更新 更多