【问题标题】:Categorizing dataframe based on information in another dataframe根据另一个数据帧中的信息对数据帧进行分类
【发布时间】:2020-12-21 07:58:22
【问题描述】:

我试图根据另一个数据帧中的信息对一个数据帧进行分类。在 df1 我有关于测量类型的信息(例如,如果一个罐子里有湿土还是干土,以及处理是否是“无”或“ul5”)在给定时间。在 df2 我有关于在给定时间测量值 X 的信息。我需要知道 X 的每个测量值的测量类型。

我曾尝试使用 full_join 和 fill(),但都无法达到我想要的结果。有什么想法吗?

这里是 df1:

df1 <- structure(list(Jar = c("Soil_dry", "Soil_dry", "soil_wet", "soil_wet", 
"Soil_dry", "Soil_dry", "soil_wet"), Treatment = c("None", "None", 
"None", "None", "ul5", "ul5", "ul5"), Timestamp = structure(c(1608129063, 
1608129122, 1608129126, 1608129136, 1608129189, 1608129242, 1608129252
), class = c("POSIXct", "POSIXt"), tzone = "UTC")), class = c("spec_tbl_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -7L), spec = structure(list(
    cols = list(Jar = structure(list(), class = c("collector_character", 
    "collector")), Treatment = structure(list(), class = c("collector_character", 
    "collector")), Timestamp = structure(list(format = ""), class = c("collector_datetime", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1), class = "col_spec"))

df2:

df2 <- structure(list(X = c(5, 3, 34, 4, 65, 9, 7), Timestamp = structure(c(1608129064, 
1608129122, 1608129125, 1608129133, 1608129188, 1608129240, 1608129243
), class = c("POSIXct", "POSIXt"), tzone = "UTC")), class = c("spec_tbl_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -7L), spec = structure(list(
    cols = list(X = structure(list(), class = c("collector_double", 
    "collector")), Timestamp = structure(list(format = ""), class = c("collector_datetime", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1), class = "col_spec"))

所需数据:

desired_data <- structure(list(X = c(5, 3, 34, 4, 65, 9, 7), Timestamp = structure(c(1608129064, 
1608129122, 1608129125, 1608129133, 1608129188, 1608129240, 1608129243
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), Jar = c("Soil_dry", 
"Soil_dry", "Soil_dry", "soil_wet", "soil_wet", "Soil_dry", "Soil_dry"
), Treatment = c("None", "None", "None", "None", "None", "ul5", 
"ul5")), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame"
), row.names = c(NA, -7L), spec = structure(list(cols = list(
    X = structure(list(), class = c("collector_double", "collector"
    )), Timestamp = structure(list(format = ""), class = c("collector_datetime", 
    "collector")), Jar = structure(list(), class = c("collector_character", 
    "collector")), Treatment = structure(list(), class = c("collector_character", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
"collector")), skip = 1), class = "col_spec"))

【问题讨论】:

  • left_join 怎么样?像这样:left_join(df2, df1) %&gt;% fill(Jar, Treatment).
  • 感谢@CainãMaxCouto-Silva 的建议,我觉得效果很好!

标签: r tidyverse


【解决方案1】:

尝试data.table 的滚动加入。

library(data.table)
setDT(df1)
setDT(df2)
df1[df2, roll = "nearest", on = "Timestamp"]

如果我们想确保选择的行总是大于Timestamp from df2

library(dplyr)

tidyr::crossing(df1 %>%rename(Timestamp1 = Timestamp), 
                df2 %>% rename(Timestamp2 = Timestamp)) %>%
  mutate(diff = as.numeric(Timestamp2 - Timestamp1)) %>%
  filter(diff > 0) %>% 
  arrange(Jar, Timestamp2, diff) %>%
  group_by(Timestamp2) %>%
  slice(1L) %>%
  ungroup %>%
  arrange(Timestamp2) %>%
  select(-diff)

#  Jar      Treatment Timestamp1              X Timestamp2         
#  <chr>    <chr>     <dttm>              <dbl> <dttm>             
#1 Soil_dry None      2020-12-16 14:31:03     5 2020-12-16 14:31:04
#2 Soil_dry None      2020-12-16 14:31:03     3 2020-12-16 14:32:02
#3 Soil_dry None      2020-12-16 14:32:02    34 2020-12-16 14:32:05
#4 Soil_dry None      2020-12-16 14:32:02     4 2020-12-16 14:32:13
#5 Soil_dry None      2020-12-16 14:32:02    65 2020-12-16 14:33:08
#6 Soil_dry ul5       2020-12-16 14:33:09     9 2020-12-16 14:34:00
#7 Soil_dry ul5       2020-12-16 14:34:02     7 2020-12-16 14:34:03

【讨论】:

  • 感谢您的建议@Ronak Shah!我想知道您的解决方案是否适用于所有情况,因为我忘记在我原来的问题中完全描述这种情况。假设在 2020-12-16 14:38:02 有一个值 X。我猜这个测量值会被归类为“Soil_wet”/“None”,因为它最接近第 10 行,soil_wet,None,2020-12-16 14:38:03。实际上它应该是 soil_dry,因为只有 14:38:03 之后的测量值才应该归类为 soil_wet。
  • 是的,data.table rolling join 采用最近的匹配。对于您的具体情况,我认为更新后的答案应该有助于我们仅从df2 中选择时间戳之后出现的那些值。
  • 嗯,更新后的解决方案看起来 X 值不正确
  • X 值呢?您能否将示例缩短一点(可能是 5 行),以便更容易检查。你能更新一下你的预期输出吗?
  • 该解决方案执行left_join,因此它依赖于两个数据帧中某处的时间戳完全匹配的事实。如果没有完全匹配,这将返回所有NA。此外,如果您仔细查看解决方案,它不会始终返回正确的时间戳。例如,如果您在 2020-12-16 14:38:03 有一个完全匹配,并且在 2020-12-16 14:38:05 有另一个条目需要与 2020-12-16 14:38 匹配:06 它将取值为 2020-12-16 14:38:03 而不是 2020-12-16 14:38:05。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多