在 day/dusk/night/dawn 上添加信息以在 R 中跟踪数据
Adding information on day/dusk/night/dawn for tracking data in R
我有一个数据集,其中包含几个月的日期时间、纬度和经度变量的跟踪数据,如下所示:
> start <- as.POSIXct("2018-08-01 00:00:00", format="%Y-%m-%d %H:%M:%S", tz="UTC")
> datetime <- seq(from = start, length.out = 2880, by = "5 mins")
> lat<-rep(seq(from=50, to= 30, length.out = 10), each=288)
> lon<-rep(seq(from=110, to= 70, length.out = 10), each=288)
> data<-cbind.data.frame(datetime, lat, lon)
> head(data)
datetime lat lon
1 2018-08-01 00:00:00 50 110
2 2018-08-01 00:05:00 50 110
3 2018-08-01 00:10:00 50 110
4 2018-08-01 00:15:00 50 110
5 2018-08-01 00:20:00 50 110
6 2018-08-01 00:25:00 50 110
我想根据 getSunlightTimes
:
中的信息添加一个新列,其中包含一天中的时段信息,即白天、dusk、夜晚或黎明
> data$date<-as.Date(data$datetime)
> sun<-getSunlightTimes(data=data, tz="UTC", keep=c("sunrise","sunset","night","nightEnd"))
> head(sun)
date lat lon sunrise sunset night
1 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
2 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
3 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
4 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
5 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
6 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
nightEnd
1 2018-07-31 18:33:13
2 2018-07-31 18:33:13
3 2018-07-31 18:33:13
4 2018-07-31 18:33:13
5 2018-07-31 18:33:13
6 2018-07-31 18:33:13
所以 dusk 将对应于 sunset
和 night
之间的 datetime
值,nightEnd
和 sunrise
之间的黎明,[=19= 之间的天] =19=] 和 sunset
以及 night
和 nightEnd
之间的夜晚。
我试过:
> data$period<-rep(" ", length.out=nrow(data))
> data$period[which(data$datetime>sun$sunrise & data$datetime<sun$sunset)]<-"day"
> data$period[which(data$datetime>sun$sunset & data$datetime<sun$night)]<-"dusk"
> data$period[which(data$datetime>sun$nightEnd & data$datetime<sun$sunrise)]<-"dawn"
> data$period[which(data$period==" ")]<-"night"
但这会导致几天之间的过渡出现问题。有人有什么建议吗?
亲切的问候
我要做的是进行左连接,即将 sunset/sunrise 数据附加到您的实际日期并在那里发挥您的魔力。
library(suncalc)
start <- as.POSIXct("2018-08-01 00:00:00", format = "%Y-%m-%d %H:%M:%S",
tz = "UTC")
datetime <- seq(from = start, length.out = 2880, by = "5 mins")
lat <- rep(seq(from = 50, to = 30, length.out = 10), each = 288)
lon <- rep(seq(from = 110, to = 70, length.out = 10), each = 288)
data <- cbind.data.frame(datetime, lat, lon)
data$date <- as.Date(data$datetime)
sun <- getSunlightTimes(data = data, tz = "UTC",
keep = c("sunrise", "sunset", "night", "nightEnd"))
xy <- merge(x = data,
y = sun[, c("date", "sunrise", "sunset", "night", "nightEnd")],
by = "date")
xy$period <- rep(" ", length.out = nrow(xy))
xy$period[xy$datetime > xy$sunrise & xy$datetime < xy$sunset] <- "day"
xy$period[xy$datetime > xy$sunset & xy$datetime < xy$night] <- "dusk"
xy$period[xy$datetime > xy$nightEnd & xy$datetime < xy$sunrise] <- "dawn"
xy$period[xy$period == " "] <- "night"
set.seed(357)
xy[sample(1:nrow(xy), size = 7), ]
date datetime lat lon sunrise sunset night nightEnd period
396824 2018-08-05 2018-08-05 18:45:00 41.11111 92.22222 2018-08-04 22:51:28 2018-08-05 13:05:23 2018-08-05 14:55:08 2018-08-04 21:01:43 night
407953 2018-08-05 2018-08-05 22:00:00 41.11111 92.22222 2018-08-04 22:51:28 2018-08-05 13:05:23 2018-08-05 14:55:08 2018-08-04 21:01:43 night
685732 2018-08-09 2018-08-09 06:25:00 32.22222 74.44444 2018-08-09 00:23:28 2018-08-09 13:54:45 2018-08-09 15:25:18 2018-08-08 22:52:56 day
638810 2018-08-08 2018-08-08 16:50:00 34.44444 78.88889 2018-08-08 00:01:06 2018-08-08 13:41:48 2018-08-08 15:16:02 2018-08-07 22:26:53 night
392649 2018-08-05 2018-08-05 17:35:00 41.11111 92.22222 2018-08-04 22:51:28 2018-08-05 13:05:23 2018-08-05 14:55:08 2018-08-04 21:01:43 night
165451 2018-08-02 2018-08-02 23:50:00 47.77778 105.55556 2018-08-01 21:36:31 2018-08-02 12:34:05 2018-08-02 14:53:05 2018-08-01 19:17:31 night
159367 2018-08-02 2018-08-02 22:05:00 47.77778 105.55556 2018-08-01 21:36:31 2018-08-02 12:34:05 2018-08-02 14:53:05 2018-08-01 19:17:31 night
一个 tidyverse 选项——就像 Roman Luštrik 的解决方案一样——使用 left_join
。
library(dplyr)
library(lubridate)
df1 %>%
mutate(date = date(datetime)) %>%
left_join(df2) %>%
distinct() %>%
mutate(period = case_when(datetime %within% interval(sunset, night) ~ 'dusk',
datetime %within% interval(nightEnd, sunrise) ~ 'dawn',
datetime %within% interval(sunrise, sunset) ~ 'day',
datetime %within% interval(night, nightEnd) ~ 'night')) %>%
select(datetime, lat, lon, period)
# # A tibble: 6 x 4
# datetime lat lon period
# <dttm> <dbl> <dbl> <chr>
# 1 2018-08-01 00:00:00 50 110 day
# 2 2018-08-01 00:05:00 50 110 day
# 3 2018-08-01 00:10:00 50 110 day
# 4 2018-08-01 00:15:00 50 110 day
# 5 2018-08-01 00:20:00 50 110 day
# 6 2018-08-01 00:25:00 50 110 day
数据
df1 <- structure(list(datetime = structure(c(1533081600, 1533081900,
1533082200, 1533082500, 1533082800, 1533083100), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), lat = c(50, 50, 50, 50, 50, 50), lon = c(110,
110, 110, 110, 110, 110)), row.names = c(NA, -6L), class = c("tbl_df",
"tbl", "data.frame"))
df2 <- structure(list(date = structure(c(17744, 17744, 17744, 17744,
17744, 17744), class = "Date"), lat = c(50, 50, 50, 50, 50, 50
), lon = c(110, 110, 110, 110, 110, 110), sunrise = structure(c(1533071390,
1533071390, 1533071390, 1533071390, 1533071390, 1533071390), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), sunset = structure(c(1533126318, 1533126318,
1533126318, 1533126318, 1533126318, 1533126318), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), night = structure(c(1533135716, 1533135716,
1533135716, 1533135716, 1533135716, 1533135716), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), nightEnd = structure(c(1533061993,
1533061993, 1533061993, 1533061993, 1533061993, 1533061993), class = c("POSIXct",
"POSIXt"), tzone = "UTC")), row.names = c(NA, -6L), class = c("tbl_df",
"tbl", "data.frame"))
我有一个数据集,其中包含几个月的日期时间、纬度和经度变量的跟踪数据,如下所示:
> start <- as.POSIXct("2018-08-01 00:00:00", format="%Y-%m-%d %H:%M:%S", tz="UTC")
> datetime <- seq(from = start, length.out = 2880, by = "5 mins")
> lat<-rep(seq(from=50, to= 30, length.out = 10), each=288)
> lon<-rep(seq(from=110, to= 70, length.out = 10), each=288)
> data<-cbind.data.frame(datetime, lat, lon)
> head(data)
datetime lat lon
1 2018-08-01 00:00:00 50 110
2 2018-08-01 00:05:00 50 110
3 2018-08-01 00:10:00 50 110
4 2018-08-01 00:15:00 50 110
5 2018-08-01 00:20:00 50 110
6 2018-08-01 00:25:00 50 110
我想根据 getSunlightTimes
:
> data$date<-as.Date(data$datetime)
> sun<-getSunlightTimes(data=data, tz="UTC", keep=c("sunrise","sunset","night","nightEnd"))
> head(sun)
date lat lon sunrise sunset night
1 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
2 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
3 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
4 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
5 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
6 2018-08-01 50 110 2018-07-31 21:09:50 2018-08-01 12:25:18 2018-08-01 15:01:56
nightEnd
1 2018-07-31 18:33:13
2 2018-07-31 18:33:13
3 2018-07-31 18:33:13
4 2018-07-31 18:33:13
5 2018-07-31 18:33:13
6 2018-07-31 18:33:13
所以 dusk 将对应于 sunset
和 night
之间的 datetime
值,nightEnd
和 sunrise
之间的黎明,[=19= 之间的天] =19=] 和 sunset
以及 night
和 nightEnd
之间的夜晚。
我试过:
> data$period<-rep(" ", length.out=nrow(data))
> data$period[which(data$datetime>sun$sunrise & data$datetime<sun$sunset)]<-"day"
> data$period[which(data$datetime>sun$sunset & data$datetime<sun$night)]<-"dusk"
> data$period[which(data$datetime>sun$nightEnd & data$datetime<sun$sunrise)]<-"dawn"
> data$period[which(data$period==" ")]<-"night"
但这会导致几天之间的过渡出现问题。有人有什么建议吗?
亲切的问候
我要做的是进行左连接,即将 sunset/sunrise 数据附加到您的实际日期并在那里发挥您的魔力。
library(suncalc)
start <- as.POSIXct("2018-08-01 00:00:00", format = "%Y-%m-%d %H:%M:%S",
tz = "UTC")
datetime <- seq(from = start, length.out = 2880, by = "5 mins")
lat <- rep(seq(from = 50, to = 30, length.out = 10), each = 288)
lon <- rep(seq(from = 110, to = 70, length.out = 10), each = 288)
data <- cbind.data.frame(datetime, lat, lon)
data$date <- as.Date(data$datetime)
sun <- getSunlightTimes(data = data, tz = "UTC",
keep = c("sunrise", "sunset", "night", "nightEnd"))
xy <- merge(x = data,
y = sun[, c("date", "sunrise", "sunset", "night", "nightEnd")],
by = "date")
xy$period <- rep(" ", length.out = nrow(xy))
xy$period[xy$datetime > xy$sunrise & xy$datetime < xy$sunset] <- "day"
xy$period[xy$datetime > xy$sunset & xy$datetime < xy$night] <- "dusk"
xy$period[xy$datetime > xy$nightEnd & xy$datetime < xy$sunrise] <- "dawn"
xy$period[xy$period == " "] <- "night"
set.seed(357)
xy[sample(1:nrow(xy), size = 7), ]
date datetime lat lon sunrise sunset night nightEnd period
396824 2018-08-05 2018-08-05 18:45:00 41.11111 92.22222 2018-08-04 22:51:28 2018-08-05 13:05:23 2018-08-05 14:55:08 2018-08-04 21:01:43 night
407953 2018-08-05 2018-08-05 22:00:00 41.11111 92.22222 2018-08-04 22:51:28 2018-08-05 13:05:23 2018-08-05 14:55:08 2018-08-04 21:01:43 night
685732 2018-08-09 2018-08-09 06:25:00 32.22222 74.44444 2018-08-09 00:23:28 2018-08-09 13:54:45 2018-08-09 15:25:18 2018-08-08 22:52:56 day
638810 2018-08-08 2018-08-08 16:50:00 34.44444 78.88889 2018-08-08 00:01:06 2018-08-08 13:41:48 2018-08-08 15:16:02 2018-08-07 22:26:53 night
392649 2018-08-05 2018-08-05 17:35:00 41.11111 92.22222 2018-08-04 22:51:28 2018-08-05 13:05:23 2018-08-05 14:55:08 2018-08-04 21:01:43 night
165451 2018-08-02 2018-08-02 23:50:00 47.77778 105.55556 2018-08-01 21:36:31 2018-08-02 12:34:05 2018-08-02 14:53:05 2018-08-01 19:17:31 night
159367 2018-08-02 2018-08-02 22:05:00 47.77778 105.55556 2018-08-01 21:36:31 2018-08-02 12:34:05 2018-08-02 14:53:05 2018-08-01 19:17:31 night
一个 tidyverse 选项——就像 Roman Luštrik 的解决方案一样——使用 left_join
。
library(dplyr)
library(lubridate)
df1 %>%
mutate(date = date(datetime)) %>%
left_join(df2) %>%
distinct() %>%
mutate(period = case_when(datetime %within% interval(sunset, night) ~ 'dusk',
datetime %within% interval(nightEnd, sunrise) ~ 'dawn',
datetime %within% interval(sunrise, sunset) ~ 'day',
datetime %within% interval(night, nightEnd) ~ 'night')) %>%
select(datetime, lat, lon, period)
# # A tibble: 6 x 4
# datetime lat lon period
# <dttm> <dbl> <dbl> <chr>
# 1 2018-08-01 00:00:00 50 110 day
# 2 2018-08-01 00:05:00 50 110 day
# 3 2018-08-01 00:10:00 50 110 day
# 4 2018-08-01 00:15:00 50 110 day
# 5 2018-08-01 00:20:00 50 110 day
# 6 2018-08-01 00:25:00 50 110 day
数据
df1 <- structure(list(datetime = structure(c(1533081600, 1533081900,
1533082200, 1533082500, 1533082800, 1533083100), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), lat = c(50, 50, 50, 50, 50, 50), lon = c(110,
110, 110, 110, 110, 110)), row.names = c(NA, -6L), class = c("tbl_df",
"tbl", "data.frame"))
df2 <- structure(list(date = structure(c(17744, 17744, 17744, 17744,
17744, 17744), class = "Date"), lat = c(50, 50, 50, 50, 50, 50
), lon = c(110, 110, 110, 110, 110, 110), sunrise = structure(c(1533071390,
1533071390, 1533071390, 1533071390, 1533071390, 1533071390), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), sunset = structure(c(1533126318, 1533126318,
1533126318, 1533126318, 1533126318, 1533126318), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), night = structure(c(1533135716, 1533135716,
1533135716, 1533135716, 1533135716, 1533135716), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), nightEnd = structure(c(1533061993,
1533061993, 1533061993, 1533061993, 1533061993, 1533061993), class = c("POSIXct",
"POSIXt"), tzone = "UTC")), row.names = c(NA, -6L), class = c("tbl_df",
"tbl", "data.frame"))