【问题标题】:Create a new categorical variable in df1 that takes into account one df1 variable and several df2 variables with multiple conditions在 df1 中创建一个新的分类变量,该变量考虑一个 df1 变量和多个具有多个条件的 df2 变量
【发布时间】:2019-05-17 23:35:30
【问题描述】:

我有一个类似于thisthis 帖子中使用的数据框。原因是我需要在我的数据集中创建三个不同的变量,并且我为每个问题写了不同的帖子,因为它们的处理方式彼此不同。

df1总结了不同时间不同鱼在不同地方的深度。 df2 以 8 米的间隔(m0-7m8-15m16-23m24-31m32-39)总结了随时间(每三个小时)从地表到 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","BD","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   BD  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,9.8,2.25,1.4),var4=c(3.25,3,6.5,8.9,3.4),var5=c(3,4,2.3,2.6,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.0
2 2016-08-01 15:00:00   BD 4.00  4.00   4.00   3.00    4.0
3 2016-08-01 18:00:00   BD 6.75  4.75   9.80   6.50    2.3
4 2016-08-01 21:00:00   BD 2.25  3.00   2.25   8.90    2.6
5 2016-08-02 00:00:00   BD 4.30  2.10   1.40   3.40    1.7

我想在df1 中创建一个名为Outside_currents 的新变量,以反映鱼是否避免高电流。我将Outside_currents 列定义为“告诉我,当鱼有机会出现或不出现时,它是否会避免处于高电流层中”。我的鱼总是在大于 15 米的深度移动,所以我只考虑最后三列(m16-23m24-31m32-39)的计算。

将其转化为数学:

Outside_currents:“当考虑的三层中的一层或两层(m16-23m24-31m32-39)的电流强度比其他一层或两层大三倍时,鱼在外面吗?” .

可能的答案是:

  1. Yes:鱼在当前强度比其他一层或两层低三倍的层中。
  2. No:鱼在水流强度是其他层三倍以上的层中。
  3. NA:当该条件不存在时(没有任何层的电流强度是其他层的 3 倍),或者当可变深度为“NA”时。

我希望这样:

> df1
             Datetime Site Ind Depth Out_current
1 2016-08-01 15:34:07   BD  16   5.3          NA
2 2016-08-01 16:25:16   BD  17  24.0          NA
3 2016-08-01 17:29:16   BD  19  36.4         YES
4 2016-08-01 18:33:16   BD  16  42.0         YES
5 2016-08-01 19:33:16   BD  17  24.0          NO
6 2016-08-01 20:54:16   BD  16    NA          NA
7 2016-08-01 22:48:16   BD  16  22.1          NA

【问题讨论】:

  • 这个问题的 90% 似乎在重复您之前的问题:stackoverflow.com/questions/56190193/… 有没有办法可以让您的问题更简单,以便我们可以帮助您解决尚未解决的问题已解决,这可能对其他人更有用。
  • 为什么第 3 行和第 4 行是YES?它们似乎没有大三倍,但也许我看错了值。
  • 我上面提到的这个问题和stackoverflow.com/questions/56191446/…之间有很多重叠
  • 感谢您的评论 william3031 和 Jon Spring。 @JonSpring,这篇文章与我在其他帖子中遇到的其他帖子不同。我使用了相同的示例,因为在这 3 种情况下,我使用相同的数据集,但我需要创建不同的变量,所有变量都与电流相关。其中一篇文章是计算鱼所在深度的电流强度,另一篇文章是计算鱼不在的地方的平均电流,而这篇文章是看另一个不同的问题:鱼会避开大电流吗?这个问题的方法不同,我现在不知道该怎么做。
  • 其实这里我稍微改一下数据框df2。 @william3031,你是对的......我在df2 上犯了一个错误,我用错了。我已经改变了它,现在你可以看到为什么df1[3 , ]df1[4 , ]YES,因为在df218:00:00)中这些日期时间最接近,如果我们只看最后三个深度层,我们看到在 32 到 39 米之间的深度,水流比m16-23m24-31 层低三倍以上,由于鱼在 36 或 42 米深度,他选择在潮流之外。

标签: r dataframe dplyr tidyverse lubridate


【解决方案1】:

我想我错过了关于您的问题的一些内容。似乎您只查看 df2 并且任何时候电流标记为比一个深度高 3 倍,电流将标记为在其他深度之一低 3 倍。我把这个放在一起。看看它是否可以帮助您入门。

library(tidyverse)

outside_calcs <-
  df2 %>% 
  gather(depth, value, m16_23:m32_39) %>% 
  left_join(df2) %>% 
  mutate(
    comp_16 = m16_23/value,
    comp_24 = m24_31/value,
    comp_32 = m32_39/value,
    min_diff = pmin(comp_16, comp_24, comp_32),
    max_diff = pmax(comp_16, comp_24, comp_32)
  ) %>% 
  mutate(
    outside_currents = 
      case_when(
        min_diff < 0.33 ~ "Yes",
        max_diff > 3 ~ "No",
        TRUE ~ NA_character_
      )
  )

#            Datetime Site  depth value m16_23 m24_31 m32_39 comp_16 comp_24 comp_32 min_diff max_diff outside_currents
# 2016-08-18 21:00:00   BD m16_23  2.25   2.25    8.9    2.6   1.000    3.96   1.156    1.000     3.96               No
# 2016-08-18 21:00:00   BD m24_31  8.90   2.25    8.9    2.6   0.253    1.00   0.292    0.253     1.00              Yes
# 2016-08-18 21:00:00   BD m32_39  2.60   2.25    8.9    2.6   0.865    3.42   1.000    0.865     3.42               No
final_outside <-
  outside_calcs %>% 
  mutate(depth = str_replace(depth, "m", "c")) %>% 
  select(
    Datetime, Site,
    depth, outside_currents
  ) %>% 
  spread(depth, outside_currents) %>% 
  left_join(df2) %>% 
  select(Datetime, Site, starts_with("m"), starts_with("c"))

final_outside  

#            Datetime Site m16_23 m24_31 m32_39 c16_23 c24_31 c32_39
# 2016-08-18 12:00:00   BD   2.75   3.25    3.0   <NA>   <NA>   <NA>
# 2016-08-18 15:00:00   BD   4.00   3.00    4.0   <NA>   <NA>   <NA>
# 2016-08-18 18:00:00   BD   9.80   6.50    2.3    Yes   <NA>     No
# 2016-08-18 21:00:00   BD   2.25   8.90    2.6     No    Yes     No
# 2016-08-19 00:00:00   BD   1.40   3.40    1.7   <NA>   <NA>   <NA>

【讨论】:

  • 谢谢@yake84。我的目标是发现我的鱼在可以选择时是否避开高水流层(如果它们不能选择,这个问题就没有意义)。电流强度记录每 3 小时反映在df2 中。我需要在我的变量Outside_currents 中说,如果鱼在特定的Datetime 并考虑到它的深度,避免了高电流。
  • 当最后三个深度层中没有一个的电流比其他层低 3 倍时,我将NA 写入Outside_currents。这方面的一个例子是df1 中的第 2 行,因为根据df2,在15:00:00(最接近16:25:16 的时间)根本没有任何高电流。
  • df2 的第 3 行和第 4 行中存在 HIGH CURRENTS 的一个示例,因为在它们中,至少有三分之一的最后一层的电流强度比在其他。不知道你懂没... @)...
【解决方案2】:

解决办法:

library(data.table)

library(lubridate)

library(dplyr)

df1<-data.frame(Datetime=c("2016-08-01 12:34:07","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 19:23:16","2016-08-01 20:01:16","2016-08-01 20:54:16","2016-08-01 22:48:16","2016-08-01 23:48:16","2016-08-02 01:07:16"), Site=c("BD","BD","HG","BD","BD","BD","BD","BD","BD","HG","BD"),Ind=c(16,16,17,19,16,16,17,16,16,17,16), Depth=c(15.50,5.30,24.00,36.40,42.00,25.00,NA,22.10,54.00,27.00,21.50))
df1$Datetime<-as.POSIXct(df1$Datetime, format="%Y-%m-%d %H:%M:%S",tz="UTC")
df1$Datetime_rounded<-round_date(df1$Datetime, "3 hour")

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.00,6.75,2.25,4.30),
            var2=c(3.80,7.75,4.75,3.00,2.10),
            var3=c(2.20,4.30,6.80,2.25,3.40),
            var4=c(5.40,1.10,2.25,3.30,6.50),
            var5=c(7.30,5.20,1.30,2.60,1.70))
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")

df1<-df1[,c(1,5,2,3,4)] # Rearrange the data frame

setDT(df1) # We convert into data.table
setDT(df2)

setkey(df1, Site, Datetime_rounded) # We indicate the key variables.
setkey(df2, Site, Datetime)

df_merge = df2[df1, roll = -Inf] # Associate one table with the other.
df_merge<-df_merge[,c(8,2,9,10,3:7)] # Rearrange the data.table

df_merge[, Outside_current := case_when(
  Site != "BD" ~ "NA",
  Depth == "NA" ~ "NA",
  Depth < 15 ~ "NA",
  Depth >= 15 & Depth < 24 & (`m16-23`*3 < `m24-31` | `m16-23`*3 < `m32-39` | `m16-23`*3 < (`m24-31`+`m32-39`)/2 ) ~ "Yes",
  Depth >= 24 & Depth < 32 & (`m24-31`*3 < `m16-23` | `m24-31`*3 < `m32-39` | `m24-31`*3 < (`m16-23`+`m32-39`)/2 ) ~ "Yes",
  Depth >= 32 & (`m32-39`*3 < `m16-23` | `m32-39`*3 < `m24-31` | `m32-39`*3 < (`m16-23`+`m24-31`)/2 ) ~ "Yes",
  Depth >= 24 & (`m16-23`*3 < `m24-31` | `m16-23`*3 < `m32-39` | `m16-23`*3 < (`m24-31`+`m32-39`)/2 ) ~ "No",
  (Depth >= 15 & Depth <24 | Depth >= 32) & (`m24-31`*3 < `m16-23` | `m24-31`*3 < `m32-39`  | `m24-31`*3 < (`m16-23`+`m32-39`)/2 ) ~ "No",
  Depth < 32 & (`m32-39`*3 < `m16-23` | `m32-39`*3 < `m24-31` | `m32-39`*3 < (`m16-23`+`m24-31`)/2 ) ~ "No",
  T ~ "NA")]

> df_merge
             i.Datetime Site Ind Depth m0-7 m8-15 m16-23 m24-31 m32-39 Outside_current
 1: 2016-08-01 12:34:07   BD  16  15.5 2.75  3.80   2.20   5.40    7.3             Yes
 2: 2016-08-01 15:34:07   BD  16   5.3 4.00  7.75   4.30   1.10    5.2              NA
 3: 2016-08-01 17:29:16   BD  19  36.4 6.75  4.75   6.80   2.25    1.3             Yes
 4: 2016-08-01 18:33:16   BD  16  42.0 6.75  4.75   6.80   2.25    1.3             Yes
 5: 2016-08-01 19:23:16   BD  16  25.0 6.75  4.75   6.80   2.25    1.3             Yes
 6: 2016-08-01 20:01:16   BD  17    NA 2.25  3.00   2.25   3.30    2.6              NA
 7: 2016-08-01 20:54:16   BD  16  22.1 2.25  3.00   2.25   3.30    2.6              NA
 8: 2016-08-01 22:48:16   BD  16  54.0 4.30  2.10   3.40   6.50    1.7             Yes
 9: 2016-08-02 01:07:16   BD  16  21.5 4.30  2.10   3.40   6.50    1.7              No
10: 2016-08-01 16:25:16   HG  17  24.0   NA    NA     NA     NA     NA              NA
11: 2016-08-01 23:48:16   HG  17  27.0   NA    NA     NA     NA     NA              NA

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多