【问题标题】:How to lookup values in R如何在 R 中查找值
【发布时间】:2015-06-02 11:56:28
【问题描述】:

谁能帮忙,我有一个数据框 (set_rise),每一行包含当天的日落时间和第二天的日出时间。我有第二个数据框(data),其中有一列日期/时间。我想通过在data 中获取日期/时间并检查它是否在set_rise 中的任何时间之间,在data 中创建一个对应于白天或晚上的字母的第二列.

#df1- sunset, sunrise times
set_rise
                  set                rise 
1 2013-03-01 18:28:00 2013-03-02 08:27:00   
2 2013-03-02 18:31:00 2013-03-03 08:23:00    
3 2013-03-03 18:35:00 2013-03-04 08:19:00  
4 2013-03-04 18:38:00 2013-03-05 08:15:00   
5 2013-03-05 18:42:00 2013-03-06 08:12:00  
6 2013-03-06 18:45:00 2013-03-07 08:08:00   

#df2 my data    
  timedate
1 2013-03-01 19:00:00
2 2013-03-03 10:00:00
3 2013-03-06 00:01:00

我想要这样的输出

data
timedate night_day
2013-03-01 19:00:00  N
2013-03-03 10:00:00  D
2013-03-06 00:01:00  N

输出 dput(set_rise)

dput(set_rise)
structure(list(set = structure(list(sec = 0, min = 28L, hour = 18L, 
mday = 1L, mon = 2L, year = 113L, wday = 5L, yday = 59L, 
isdst = 0L, zone = "WET", gmtoff = NA_integer_), .Names = c("sec", 
"min", "hour", "mday", "mon", "year", "wday", "yday", "isdst", 
 "zone", "gmtoff"), class = c("POSIXlt", "POSIXt")), rise = structure(list(
sec = 0, min = 27L, hour = 8L, mday = 2L, mon = 2L, year = 113L, 
wday = 6L, yday = 60L, isdst = 0L, zone = "WET", gmtoff = NA_integer_), .Names = c("sec", 
"min", "hour", "mday", "mon", "year", "wday", "yday", "isdst", 
"zone", "gmtoff"), class = c("POSIXlt", "POSIXt")), night = "N"), .Names = c("set", 
"rise", "night"), row.names = 1L, class = "data.frame")

dput(数据)的输出

dput(data)
structure(list(timedate = structure(c(1362873600, 1362960000, 
1364342400), class = c("POSIXct", "POSIXt"))), .Names = "timedate",     row.names = c(NA, 
-3L), class = "data.frame")

【问题讨论】:

  • 如果您添加了一个您希望看到的输出示例,将会有所帮助。
  • 看来你搞乱了日期时间转换。对于set_rise,我得到13-03-01 日期(这是13 年而不是2013 年)!只需提供 set_risedata 并跳过构建它的方式。完成后发布dput(set_rise)dput(data) 的输出。但在此之前,请检查日期是否符合您的预期。
  • 感谢您的回复,我已经解决了日期问题并优化了发布的数据并发布了首选输出。
  • 谢谢,该解决方案完美运行。
  • 感谢所有花时间提供帮助的人,非常感谢。由于速度的原因,我已经接受了 nicola 的回答,我有很多大型数据集(每个 cirka 20 000)。

标签: r


【解决方案1】:

这需要一些准备,但速度非常快。首先,将set_rise 转换为POSIXct(而不是POSIXlt)。接下来,将日期转换为numeric 并组合所有值,这样它们就形成了白天和黑夜的交替值。然后,您调用findInterval,它会告诉您data 的每个日期所处的间隔:如果间隔是奇数,则为晚上,否则为白天。所以:

#convert to POSIXct
set_rise[]<-lapply(set_rise,as.POSIXct)
#combine all the numeric values together
intervals<-c(t(matrix(c(as.numeric(set_rise$set),as.numeric(set_rise$rise)),ncol=2)))
#call findInterval and set the values, checking the parity
c("D","N")[1+(findInterval(as.numeric(data$timedate),intervals) %% 2)]
#[1] "N" "D" "N"

【讨论】:

    【解决方案2】:

    我不确定我是否理解正确,但这是一个开始:

    check_night() 检查data$timedate 中的每个值是否位于set_rise 中的设置/上升时间之一内。

    timedate <- c('2013-03-10 19:00:00', '2013-03-11 10:00:00', '2013-03-27 00:01:00')
    data <- data.frame(timedate)
    data$timedate <- as.POSIXct(data$timedate)
    
    check_night <- function (t) {
      night <- "D"
      for (i in 1:length(rownames(set_rise))) {
        if ((t > set_rise[i,"set"]) && (t < set_rise[i,"rise"]))
          night <- "N"
      }
      return(night)
    }
    
    dplyr::mutate(.data = data, night=sapply(data$timedate, FUN = check_night))
    
    # Output
                 timedate night
    1 0013-03-10 19:00:00     D
    2 0013-03-11 10:00:00     N
    3 0013-03-27 00:01:00     D
    

    注意:很可能有一个不需要 for 循环的解决方案。

    【讨论】:

      【解决方案3】:

      我有一个与 maj 类似的解决方案,我只是做了嵌套的 for 循环,而不是创建一个函数和 sapply。我还使用了 strptime 而不是 as.POSIXct 因为出于某种原因这给了我 NA 。如果您有一个大型数据集,请继续使用该函数并使用 sapply 或 lapply,它更容易阅读并且可能更快。我发布这个给你一些选择,maj's 可能比我的更快更优雅。

      df1<-read.csv("~/mysrc/data/sunsethelp.csv", header=T, stringsAsFactors=F)
      df1$set<-strptime(df1$set, "%m/%d/%Y %H:%M")
      df1$rise<-strptime(df1$rise, "%m/%d/%Y %H:%M")
      
      timedate<-c('2013-03-01 19:00:00', '2013-03-03 10:00:00', '2013-03-06     00:01:00')
      df2 <- data.frame(timedate)
      df2$timedate <- strptime(timedate, "%Y-%m-%d %H:%M")
      
      for(i in seq(nrow(df2))){
        for(j in seq(nrow(df1))){
          df2$night_day[i]<-ifelse(df2$timedate[i]>df1$set[j] && df2$timedate[i]    <df1$rise[j], "N", "D")
          if(df2$night_day[i]=="N")
            break
        }
      }
      
      #Output
                   timedate night_day
      1 2013-03-01 19:00:00         N
      2 2013-03-03 10:00:00         D
      3 2013-03-06 00:01:00         N
      

      【讨论】:

        猜你喜欢
        • 2011-05-07
        • 1970-01-01
        • 2014-01-13
        • 2016-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多