r - 计算 df2 的几列之间的平均值,该平均值可以根据 df1 的变量 `var1` 变化,并将该值添加到 df1 中的新变量
问题描述
我有一个数据框df1
,它总结了不同地方不同鱼的深度。
另一方面,我总结了在特定位置以 8 米(、、和)df2
间隔从地表到 39 米深度的电流强度随时间(每 3 小时)的强度。举个例子:m0-7
m8-15
m16-23
m24-31
m32-39
df1<-data.frame(Datetime=c("2016-08-01 15:34:07","2016-08-01 16:25:16","2016-08-01 17:29:16","2016-08-01 18:33:16","2016-08-01 20:54:16","2016-08-01 22:48:16"),Site=c("BD","HG","BD","BD","BD","BD"),Ind=c(16,17,19,16,17,16), Depth=c(5.3,24,36.4,42,NA,22.1))
df1$Datetime<-as.POSIXct(df1$Datetime, format="%Y-%m-%d %H:%M:%S",tz="UTC")
> df1
Datetime Site Ind Depth
1 2016-08-01 15:34:07 BD 16 5.3
2 2016-08-01 16:25:16 HG 17 24.0
3 2016-08-01 17:29:16 BD 19 36.4
4 2016-08-01 18:33:16 BD 16 42.0
5 2016-08-01 20:54:16 BD 17 NA
6 2016-08-01 22:48:16 BD 16 22.1
df2<-data.frame(Datetime=c("2016-08-01 12:00:00","2016-08-01 15:00:00","2016-08-01 18:00:00","2016-08-01 21:00:00","2016-08-02 00:00:00"), Site=c("BD","BD","BD","BD","BD"),var1=c(2.75,4,6.75,2.25,4.3),var2=c(3,4,4.75,3,2.1),var3=c(2.75,4,5.75,2.25,1.4),var4=c(3.25,3,6.5,2.75,3.4),var5=c(3,4,4.75,3,1.7))
df2$Datetime<-as.POSIXct(df2$Datetime, format="%Y-%m-%d %H:%M:%S",tz="UTC")
colnames(df2)<-c("Datetime","Site","m0-7","m8-15","m16-23","m24-31","m32-39")
> df2
Datetime Site m0-7 m8-15 m16-23 m24-31 m32-39
1 2016-08-01 12:00:00 BD 2.75 3.00 2.75 3.25 3.00
2 2016-08-01 15:00:00 BD 4.00 4.00 4.00 3.00 4.00
3 2016-08-01 18:00:00 BD 6.75 4.75 5.75 6.50 4.75
4 2016-08-01 21:00:00 BD 2.25 3.00 2.25 2.75 3.00
5 2016-08-02 00:00:00 BD 4.30 2.10 1.40 3.40 1.70
我想创建一个变量,df1
以反映鱼不在的深度层的平均电流。例如,如果鱼在 20 米深,对应于 层m16-23
,我想知道层m0-7
、m8-15
和m24-31
的平均电流m32-39
。
注1:如果我的鱼在39米以上的深度,我认为它好像在最深处(m32-39
)。的第 4 行中的一个示例df1
。
注2:由于当前记录是每三个小时,每一个小时表示df2$Datetime
多一个半小时,少一个半小时。df2
即, at 中指出的电流强度21:00:00
反映了 和 之间的19:30:00
电流22:30:00
。其余时间也一样。
我希望这样:
> df1
Datetime Site Ind Depth current.Mean
1 2016-08-01 15:34:07 BD 16 5.3 3.75
2 2016-08-01 16:25:16 HG 17 24.0 NA
3 2016-08-01 17:29:16 BD 19 36.4 5.94
4 2016-08-01 18:33:16 BD 16 42.0 5.94
5 2016-08-01 20:54:16 BD 17 NA NA
6 2016-08-01 22:48:16 BD 16 22.1 2.87
有谁知道该怎么做?
解决方案
我会分两步解决这个问题:
- 使用 avg_speed_elsewhere 为 df2 中的每个日期时间、站点和深度创建一个查找表。
- 加入 df1。
这是一个查找表:
library(tidyverse)
df2_long <- df2 %>%
gather(depth_rng, speed, `m0-7`:`m32-39`) %>%
separate(depth_rng, c("min_depth", "max_depth")) %>%
mutate_at(vars(matches("depth")), parse_number) %>%
# EDIT -- added to make deep category cover >39 too
mutate(max_depth = if_else(max_depth == 39, 10000, max_depth)) %>%
group_by(Datetime, Site) %>%
# Avg Speed elsewhere is the sum of all speeds, minus this speed, all divided by 4.
mutate(avg_speed_elsewhere = (sum(speed) - speed) / 4)
> df2_long
# A tibble: 25 x 6
# Groups: Datetime, Site [5]
Datetime Site min_depth max_depth speed avg_speed_elsewhere
<dttm> <fct> <dbl> <dbl> <dbl> <dbl>
1 2016-08-18 12:00:00 BD 0 7 2.75 3
2 2016-08-18 15:00:00 BD 0 7 4 3.75
3 2016-08-18 18:00:00 BD 0 7 6.75 5.44
4 2016-08-18 21:00:00 BD 0 7 2.25 2.75
5 2016-08-19 00:00:00 BD 0 7 4.3 2.15
6 2016-08-18 12:00:00 BD 8 15 3 2.94
7 2016-08-18 15:00:00 BD 8 15 4 3.75
8 2016-08-18 18:00:00 BD 8 15 4.75 5.94
9 2016-08-18 21:00:00 BD 8 15 3 2.56
10 2016-08-19 00:00:00 BD 8 15 2.1 2.7
# ... with 15 more rows
我希望这会起作用,但您提供的数据不会重叠,所以我不确定:
df1 %>%
# EDIT - replaced floor_date with round_date
mutate(Datetime_3hr = lubridate::round_date(Datetime, "3 hour")) %>%
left_join(df2_long, by = c("Site", "Datetime_3hr" = "Datetime")) %>%
filter(Depth >= min_depth & Depth < max_depth + 1 | is.na(Depth))