首页 > 解决方案 > 计算 df2 的几列之间的平均值,该平均值可以根据 df1 的变量 `var1` 变化,并将该值添加到 df1 中的新变量

问题描述

我有一个数据框df1,它总结了不同地方不同鱼的深度。

另一方面,我总结了在特定位置以 8 米(、、和)df2间隔从地表到 39 米深度的电流强度随时间(每 3 小时)的强度。举个例子:m0-7m8-15m16-23m24-31m32-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-7m8-15m24-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

有谁知道该怎么做?

标签: rdplyrtidyverse

解决方案


我会分两步解决这个问题:

  1. 使用 avg_speed_elsewhere 为 df2 中的每个日期时间、站点和深度创建一个查找表。
  2. 加入 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))

推荐阅读