任何人都可以提供帮助,我有一个数据框(set_rise
),每行包含当天的日落时间和第二天的日出时间。我有第二个数据框(data
),其中包含一列日期/时间。我想在data
中创建第二列,其中包含对应于白天或晚上的字母,方法是在data
中查看日期/时间并检查其中是否存在任何set_rise
中的时间。
#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
输出输出(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(data)输出
dput(data)
structure(list(timedate = structure(c(1362873600, 1362960000,
1364342400), class = c("POSIXct", "POSIXt"))), .Names = "timedate", row.names = c(NA,
-3L), class = "data.frame")
答案 0 :(得分:1)
我不确定我是否理解正确,但这是一个开始:
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循环。
答案 1 :(得分: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 :(得分:0)
我有一个类似maj的解决方案,我只是嵌套for循环而不是制作一个函数和sapply。我也使用strptime而不是as.POSIXct,因为那是因为某种原因给了我NA。如果你有一个大型数据集,那就去制作这个函数并使用sapply或lapply,它更容易阅读,而且可能更快。我发布这个给你一些选择,maj可能比我的更快更优雅。
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