【问题标题】:Check if values of datetime column in df2 is within datateime values of df1 in R检查 df2 中 datetime 列的值是否在 R 中 df1 的 datateime 值内
【发布时间】:2016-02-15 07:12:17
【问题描述】:

我有 2 个这样的数据框:

df1

ID <- c("A","B","A","C","C","B","B","A")
StartDatetime <- c("2015-09-29 00:00:13", "2015-09-29 05:55:50", "2015-09-29 11:45:14", "2015-09-29 15:24:00",
                               "2015-09-29 17:24:12", "2015-09-29 21:34:31", "2015-09-29 22:22:22", "2015-09-29 23:38:22") 
EndDatetime <- c("2015-09-29 00:13:56", "2015-09-29 06:13:50", "2015-09-29 12:23:14", "2015-09-29 15:58:00",
                             "2015-09-29 17:58:17", "2015-09-29 22:06:31", "2015-09-29 22:52:28", "2015-09-29 23:55:22") 
MEASUREMENT <- c("Length","Length","Width","Length","Width","Height","Length","Height") 
df1 <- data.frame(ID,StartDatetime,EndDatetime,MEASUREMENT)

df2

ID <- c("A","B","A","C","C","B","B")
MStart <- c("09/29/2015 00:02:13", "09/29/2015 05:56:50", "09/30/2015 11:55:14", "09/29/2015 15:33:00",
                    "09/29/2015 17:28:12", "09/29/2015 21:30:31", "09/29/2015 22:26:22") 
MEnd <- c("09/29/2015 00:11:12", "09/29/2015 06:55:50", "09/30/2015 11:54:14", "09/29/2015 15:47:00",
                  "09/29/2015 17:44:12", "09/29/2015 22:02:31", "09/29/2015 22:44:22") 
Measurement <- c("Length","Length","Width","Length","Width","Height","Length") 
df2 <- data.frame(ID,MStart,MEnd,Measurement)

我正在尝试解决一个有趣的问题,即检查 df2 中具有 MStart 和 MEnd 的 ID 是否在每次测量的 df1 日期时间范围内。逻辑回归

TRUE if (MStart & MEnd) **is within** (StartDatetime & EndDatetime)
FALSE if (MStart & MEnd) **is not within** (StartDatetime & EndDatetime)

我想要的输出将是 df3,其中包含 df1 中的所有列,并添加一个包含 True 或 False 值的列。

df3

  ID       StartDatetime         EndDatetime MEASUREMENT True_False
1  A 2015-09-29 00:00:13 2015-09-29 00:13:56      Length       TRUE
2  B 2015-09-29 05:55:50 2015-09-29 06:13:50      Length      FALSE
3  A 2015-09-29 11:55:14 2015-09-29 12:23:14       Width      FALSE
4  C 2015-09-29 15:24:00 2015-09-29 15:58:00      Length       TRUE
5  C 2015-09-29 17:24:12 2015-09-29 17:58:17       Width       TRUE
6  B 2015-09-29 21:34:31 2015-09-29 22:06:31      Height      FALSE
7  B 2015-09-29 22:22:22 2015-09-29 22:52:28      Length       TRUE
8  A 2015-09-29 23:38:22 2015-09-29 23:55:22      Height      FALSE

我在尝试转换 df2 的日期格式时遇到此错误,无法继续前进。

**df2$MStart <- as.POSIXct(df2$MStart,"%Y-%m-%d %H:%M:%S")**

Error in as.POSIXlt.character(as.character(x), ...) : 
  character string is not in a standard unambiguous format

请指导我如何解决这个问题。我正在尝试使用 dplyr 或 data.table 来解决这个问题,但不知道使用日期时间的逻辑。

编辑 我刚刚进行了编辑并删除了 df2 的最后一行,因此它现在只有 7 行。我也想解决这种情况,因为我更大的数据集在 df1 中包含更多行,在 df2 中包含更少行,因此也希望从 df1 返回那些不匹配的行和 FALSE。

【问题讨论】:

  • 感谢您使用可重复的数据组织您的问题,解释您想要什么、您尝试过什么以及您想要的输出。是 13 号星期五还是什么?哦,是的:)
  • 大声笑是的,确实如此:D

标签: r datetime dataframe


【解决方案1】:
library(dplyr)
library(lubridate)

df1_fix = 
  df1 %>%
  mutate(StartDatetime = ymd_hms(StartDatetime),
         EndDatetime = ymd_hms(EndDatetime)) %>%
  rename(Measurement = MEASUREMENT)


df2_fix = 
  df2 %>%
  mutate(MStart  = mdy_hms(MStart),
         MEnd = mdy_hms(MEnd))

initial_join = 
  df1_fix %>%
  full_join(df2_fix)

initial_join %>%
  filter(StartDatetime < EndDatetime,
         MStart < MEnd) %>%
  mutate(test = 
           int_overlaps(
             interval(StartDatetime, EndDatetime),
               interval(MStart, MEnd) ) ) %>%
  right_join(initial_join) %>%
  mutate(test = test %in% TRUE)

【讨论】:

  • 感谢您的解决方案,但它给了我一个错误“错误:没有公共变量。请指定 by 参数。”是否缺少 by = ID?而且我还需要使用日期时间进行测量分组。你能检查一下吗?
  • left_join 应该自动获取公共变量。看起来这两个数据集都有一个“ID”和“Measurement”变量。我添加了一个重命名来减少 MEASUREMENT
  • 太棒了。现在效果很好。当我在处理更大的数据集时,我意识到我的 df1 行 > df2 行。它抛出一个错误。您的解决方案有什么办法可以解决这个问题吗?理想情况下,我希望返回 df1 中与 TRUE_FALSE 列中的 FALSE 不匹配的行。如果不清楚,请告诉我。我也修改了我的问题供您查看。
【解决方案2】:

这是我要做的,类似于 bramtayl 的解决方案:

library(dplyr)
library(lubridate)
df<-df1
df$StartDatetime <- ymd_hms(StartDatetime)
df$EndDatetime <- ymd_hms(EndDatetime)
df$MStart<- mdy_hms(MStart)
df$MEnd<- mdy_hms(MEnd)

df3 <- df%>%
  mutate(True_False = ifelse(MStart >StartDatetime & MStart <EndDatetime &MEnd >StartDatetime & MEnd <EndDatetime,TRUE,FALSE))

【讨论】:

  • 您能解释一下 df$MStart
  • df$MStart 正在 df 数据框中创建一个名为“MStart”的新列,然后使用 mdy_hms(MStart) 中的值填充这个新列。您可以使用任何您喜欢的值来执行此操作(例如 df$test
  • 但它如何从 df2 填充值?我看到您正在指定 df
  • 没问题,您的示例在添加到 df2 之前已将 MStart 作为单独的向量存在(我的代码应紧跟在您之前提供的代码之后)。您是否希望 df1 和 df2 在每一行中包含完全相同的项目?如果是这样,您可以执行 df$MStart
  • 我明白你的意思。我刚刚意识到这些行并不完全相同,这就是导致问题的原因。你能帮我克服吗?我在更大数据集中的 df1 是 614 行,而 df2 是 451 行。我们如何修改它?
【解决方案3】:
library(lubridate)
df1$interval <- interval(ymd_hms(df1$StartDatetime),ymd_hms(df1$EndDatetime))
df2$interval <- interval(mdy_hms(df2$MStart),mdy_hms(df1$MEnd))
df1$True_False <- ifelse((df1$interval > df2$interval), "TRUE", "FALSE")
df1 

【讨论】:

  • 嗨。您的逻辑似乎适用于其中的大部分内容,但第 3 行应该为 false,因为日期时间超出了 df1 的范围。请检查一下,我想知道“间隔”逻辑是否比其他方法更好
猜你喜欢
  • 2019-07-06
  • 2020-08-10
  • 2021-11-04
  • 1970-01-01
  • 2020-02-19
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多