R中按时间的平均值
Averages by Time in R
我每秒测量一次化合物浓度。我想做 30 秒和 60 秒的平均值。我一直在阅读这里的帖子,我尝试了 lubridate
和 dplyr
。但没有运气。我正在努力使这项工作,但我一直无法做到。我正在从 SAS 过渡到 R,所以请耐心等待。
这是我的数据:
head (data)#show the first 6 rows
Date Time Temp Appb Bppb Cppb Dppb Eppb Fppb
1 10/30/17 21:32:33 25.23 -0.469304 22.4445 35.5993 -18.4843 52.0488 -2.947340
2 10/30/17 21:32:34 25.23 -1.255780 21.8248 34.2364 -20.9051 47.4344 -2.071230
3 10/30/17 21:32:35 25.23 -0.769233 21.1590 30.5892 -20.9347 42.6061 -0.991607
4 10/30/17 21:32:36 25.23 -0.874262 21.3353 25.4841 -19.6127 38.3224 -0.452383
5 10/30/17 21:32:37 25.24 -0.819439 21.1916 21.4919 -16.5991 36.1331 -0.150002
6 10/30/17 21:32:38 25.24 -1.895730 21.5345 18.0576 -17.2539 31.7448 -0.311064
那么,您可以执行以下操作:
data$time_bucket <-
as.POSIXct(round(as.numeric(as.POSIXct(paste(data$Date, data$Time), format="%m/%d/%y %H:%M:%S"))/30)*30, origin='1970-01-01')
这可能看起来有点复杂,但它执行以下操作:
as.POSIXct(paste(data$Date, data$Time), format="%m/%d/%y %H:%M:%S")
将日期和时间列粘贴在一起以创建一个 "datetime" 对象。
as.numeric
将其转换为 "epoch" 数字 - 自 1970-01-01 以来的秒数
- 除以 30,舍入并乘以 30 - 这将创建 30 秒的桶。舍入到相同数字的所有时间在舍入后都将具有相同的 "label"。
- 最后使用
as.POSIXct
将其转换为 "datetime"。
完成所有这些后,您可以按时间段取平均值,例如使用 dplyr
:
data %>% group_by(time_bucket) %>%
summarize(mean(Temp))
希望这能回答您的问题。
这是 xts
中 period.apply
的另一个解决方案:
library(lubridate)
library(xts)
data_ts = as.xts(data[-c(1:2)], mdy_hms(paste(data$Date, data$Time)))
ep = endpoints(data_ts, 'seconds', k = 30)
period.apply(data_ts, ep, FUN = mean)
结果:
Temp Appb Bppb Cppb Dppb Eppb Fppb
2017-10-30 21:32:38 25.23333 -1.013958 21.58162 27.57642 -18.96497 41.3816 -1.153938
由于所有样本数据都在 30 秒内,因此每一列只能得到一个平均值。要验证我的答案是否有效,您可以尝试 2 秒均值:
test_ep = endpoints(data_ts, 'seconds', k = 2)
period.apply(data_ts, test_ep, FUN = mean)
结果:
Temp Appb Bppb Cppb Dppb Eppb Fppb
2017-10-30 21:32:33 25.230 -0.4693040 22.44450 35.5993 -18.4843 52.04880 -2.9473400
2017-10-30 21:32:35 25.230 -1.0125065 21.49190 32.4128 -20.9199 45.02025 -1.5314185
2017-10-30 21:32:37 25.235 -0.8468505 21.26345 23.4880 -18.1059 37.22775 -0.3011925
2017-10-30 21:32:38 25.240 -1.8957300 21.53450 18.0576 -17.2539 31.74480 -0.3110640
数据:
data = read.table(text = " Date Time Temp Appb Bppb Cppb Dppb Eppb Fppb
1 10/30/17 21:32:33 25.23 -0.469304 22.4445 35.5993 -18.4843 52.0488 -2.947340
2 10/30/17 21:32:34 25.23 -1.255780 21.8248 34.2364 -20.9051 47.4344 -2.071230
3 10/30/17 21:32:35 25.23 -0.769233 21.1590 30.5892 -20.9347 42.6061 -0.991607
4 10/30/17 21:32:36 25.23 -0.874262 21.3353 25.4841 -19.6127 38.3224 -0.452383
5 10/30/17 21:32:37 25.24 -0.819439 21.1916 21.4919 -16.5991 36.1331 -0.150002
6 10/30/17 21:32:38 25.24 -1.895730 21.5345 18.0576 -17.2539 31.7448 -0.311064",
header = TRUE, stringsAsFactors = FALSE)
这里有一个 data.table
和 lubridate
的完整性方法。
library(data.table)
library(lubridate)
dat <- read.table(text = "Date Time Temp Appb Bppb Cppb Dppb Eppb Fppb
1 10/30/17 21:32:33 25.23 -0.469304 22.4445 35.5993 -18.4843 52.0488 -2.947340
2 10/30/17 21:32:34 25.23 -1.255780 21.8248 34.2364 -20.9051 47.4344 -2.071230
3 10/30/17 21:32:35 25.23 -0.769233 21.1590 30.5892 -20.9347 42.6061 -0.991607
4 10/30/17 21:32:36 25.23 -0.874262 21.3353 25.4841 -19.6127 38.3224 -0.452383
5 10/30/17 21:32:37 25.24 -0.819439 21.1916 21.4919 -16.5991 36.1331 -0.150002
6 10/30/17 21:32:38 25.24 -1.895730 21.5345 18.0576 -17.2539 31.7448 -0.311064 ",
header = T, stringsAsFactors = F)
#convert to R date object
dat$tme <- as.POSIXct(strptime(paste(dat$Date, dat$Time), format = "%m/%d/%y %H:%M:%S"), tz = "America/Montreal")
#convert to data.table
dat <- as.data.table(dat)
#drop Date and Time since we have an R date object now
dat <- dat[,-c(1,2)]
#result
dat[, lapply(.SD, mean), .(tme = round_date(tme, "3 seconds"))]
我四舍五入到3秒,因为样本数据都在30秒以内(同上答案)。
结果如下:
tme Temp Appb Bppb Cppb Dppb Eppb Fppb
1: 2017-10-30 21:32:33 25.23000 -0.862542 22.13465 34.91785 -19.69470 49.74160 -2.5092850
2: 2017-10-30 21:32:36 25.23333 -0.820978 21.22863 25.85507 -19.04883 39.02053 -0.5313307
3: 2017-10-30 21:32:39 25.24000 -1.895730 21.53450 18.05760 -17.25390 31.74480 -0.3110640
我个人更喜欢 data.table
方法,尤其是对于较大的数据集,因为它的速度以及子集和执行操作的便利性。
我每秒测量一次化合物浓度。我想做 30 秒和 60 秒的平均值。我一直在阅读这里的帖子,我尝试了 lubridate
和 dplyr
。但没有运气。我正在努力使这项工作,但我一直无法做到。我正在从 SAS 过渡到 R,所以请耐心等待。
这是我的数据:
head (data)#show the first 6 rows
Date Time Temp Appb Bppb Cppb Dppb Eppb Fppb
1 10/30/17 21:32:33 25.23 -0.469304 22.4445 35.5993 -18.4843 52.0488 -2.947340
2 10/30/17 21:32:34 25.23 -1.255780 21.8248 34.2364 -20.9051 47.4344 -2.071230
3 10/30/17 21:32:35 25.23 -0.769233 21.1590 30.5892 -20.9347 42.6061 -0.991607
4 10/30/17 21:32:36 25.23 -0.874262 21.3353 25.4841 -19.6127 38.3224 -0.452383
5 10/30/17 21:32:37 25.24 -0.819439 21.1916 21.4919 -16.5991 36.1331 -0.150002
6 10/30/17 21:32:38 25.24 -1.895730 21.5345 18.0576 -17.2539 31.7448 -0.311064
那么,您可以执行以下操作:
data$time_bucket <-
as.POSIXct(round(as.numeric(as.POSIXct(paste(data$Date, data$Time), format="%m/%d/%y %H:%M:%S"))/30)*30, origin='1970-01-01')
这可能看起来有点复杂,但它执行以下操作:
as.POSIXct(paste(data$Date, data$Time), format="%m/%d/%y %H:%M:%S")
将日期和时间列粘贴在一起以创建一个 "datetime" 对象。as.numeric
将其转换为 "epoch" 数字 - 自 1970-01-01 以来的秒数
- 除以 30,舍入并乘以 30 - 这将创建 30 秒的桶。舍入到相同数字的所有时间在舍入后都将具有相同的 "label"。
- 最后使用
as.POSIXct
将其转换为 "datetime"。
完成所有这些后,您可以按时间段取平均值,例如使用 dplyr
:
data %>% group_by(time_bucket) %>%
summarize(mean(Temp))
希望这能回答您的问题。
这是 xts
中 period.apply
的另一个解决方案:
library(lubridate)
library(xts)
data_ts = as.xts(data[-c(1:2)], mdy_hms(paste(data$Date, data$Time)))
ep = endpoints(data_ts, 'seconds', k = 30)
period.apply(data_ts, ep, FUN = mean)
结果:
Temp Appb Bppb Cppb Dppb Eppb Fppb
2017-10-30 21:32:38 25.23333 -1.013958 21.58162 27.57642 -18.96497 41.3816 -1.153938
由于所有样本数据都在 30 秒内,因此每一列只能得到一个平均值。要验证我的答案是否有效,您可以尝试 2 秒均值:
test_ep = endpoints(data_ts, 'seconds', k = 2)
period.apply(data_ts, test_ep, FUN = mean)
结果:
Temp Appb Bppb Cppb Dppb Eppb Fppb
2017-10-30 21:32:33 25.230 -0.4693040 22.44450 35.5993 -18.4843 52.04880 -2.9473400
2017-10-30 21:32:35 25.230 -1.0125065 21.49190 32.4128 -20.9199 45.02025 -1.5314185
2017-10-30 21:32:37 25.235 -0.8468505 21.26345 23.4880 -18.1059 37.22775 -0.3011925
2017-10-30 21:32:38 25.240 -1.8957300 21.53450 18.0576 -17.2539 31.74480 -0.3110640
数据:
data = read.table(text = " Date Time Temp Appb Bppb Cppb Dppb Eppb Fppb
1 10/30/17 21:32:33 25.23 -0.469304 22.4445 35.5993 -18.4843 52.0488 -2.947340
2 10/30/17 21:32:34 25.23 -1.255780 21.8248 34.2364 -20.9051 47.4344 -2.071230
3 10/30/17 21:32:35 25.23 -0.769233 21.1590 30.5892 -20.9347 42.6061 -0.991607
4 10/30/17 21:32:36 25.23 -0.874262 21.3353 25.4841 -19.6127 38.3224 -0.452383
5 10/30/17 21:32:37 25.24 -0.819439 21.1916 21.4919 -16.5991 36.1331 -0.150002
6 10/30/17 21:32:38 25.24 -1.895730 21.5345 18.0576 -17.2539 31.7448 -0.311064",
header = TRUE, stringsAsFactors = FALSE)
这里有一个 data.table
和 lubridate
的完整性方法。
library(data.table)
library(lubridate)
dat <- read.table(text = "Date Time Temp Appb Bppb Cppb Dppb Eppb Fppb
1 10/30/17 21:32:33 25.23 -0.469304 22.4445 35.5993 -18.4843 52.0488 -2.947340
2 10/30/17 21:32:34 25.23 -1.255780 21.8248 34.2364 -20.9051 47.4344 -2.071230
3 10/30/17 21:32:35 25.23 -0.769233 21.1590 30.5892 -20.9347 42.6061 -0.991607
4 10/30/17 21:32:36 25.23 -0.874262 21.3353 25.4841 -19.6127 38.3224 -0.452383
5 10/30/17 21:32:37 25.24 -0.819439 21.1916 21.4919 -16.5991 36.1331 -0.150002
6 10/30/17 21:32:38 25.24 -1.895730 21.5345 18.0576 -17.2539 31.7448 -0.311064 ",
header = T, stringsAsFactors = F)
#convert to R date object
dat$tme <- as.POSIXct(strptime(paste(dat$Date, dat$Time), format = "%m/%d/%y %H:%M:%S"), tz = "America/Montreal")
#convert to data.table
dat <- as.data.table(dat)
#drop Date and Time since we have an R date object now
dat <- dat[,-c(1,2)]
#result
dat[, lapply(.SD, mean), .(tme = round_date(tme, "3 seconds"))]
我四舍五入到3秒,因为样本数据都在30秒以内(同上答案)。
结果如下:
tme Temp Appb Bppb Cppb Dppb Eppb Fppb
1: 2017-10-30 21:32:33 25.23000 -0.862542 22.13465 34.91785 -19.69470 49.74160 -2.5092850
2: 2017-10-30 21:32:36 25.23333 -0.820978 21.22863 25.85507 -19.04883 39.02053 -0.5313307
3: 2017-10-30 21:32:39 25.24000 -1.895730 21.53450 18.05760 -17.25390 31.74480 -0.3110640
我个人更喜欢 data.table
方法,尤其是对于较大的数据集,因为它的速度以及子集和执行操作的便利性。