【问题标题】:Create column to flag rows within a date period in R在R中创建列以标记日期期间内的行
【发布时间】:2017-02-28 18:55:47
【问题描述】:

我需要在我的主数据框中创建一个“标记”列,用于标记日期在特定时间范围内的行。该时间范围来自第二个数据帧。我想我只是停留在 ifelse(或 if)语句上,因为标志列中有 NA。也许 ifelse 不是要走的路。以下是一些示例数据:

    # main data frame
date <- seq(as.Date("2014-07-21"), as.Date("2014-09-11"), by = "day") 
group <- letters[1:4]                           
datereps <- rep(date, length(group))                  
groupreps <- rep(group, each = length(date))    
value  <- rnorm(length(datereps))
df <- data.frame(Date = datereps, Group = groupreps, Value = value)  

# flag time period data frame
flag <- data.frame(Group = c("b", "d"), 
        start = c("2014-08-01", "2014-08-26"),
        end = c("2014-08-11", "2014-09-01"))

# Merge flag dates into main data frame
df2 <- merge(df, flag, by = "Group", all.x = T)

# Execute ifelse statement on each row
df2$flag <- "something"
df2$flag <- ifelse(df2$Date >= as.Date(df2$start) & df2$Date <= as.Date(df2$end), "flag", "other")

结果是,在指定“开始”和“结束”日期的行中,“标志”和“其他”被标记,但“开始”和“结束”为 NA,我得到 @ 的 Na 值987654322@。即使我使用"something" 启动df2$flag,也会发生这种情况。对于所有未定义为"flag" 的值,我想要"other"。查看第 50:68 行。

df2[50:68,]

【问题讨论】:

  • 当您说“不起作用”时,是 R 抛出错误,还是返回的不是您想要的?

标签: r if-statement


【解决方案1】:

如果我这样做,我会跳过中间数据帧 (df2) 和合并步骤,并将 ifelse 与 | 一起使用,这意味着 OR。

date <- seq(as.Date("2014-07-21"), as.Date("2014-09-11"), by = "day") 
group <- letters[1:4]                           
datereps <- rep(date, length(group))                  
groupreps <- rep(group, each = length(date))    
value  <- rnorm(length(datereps))
df <- data.frame(DateTime = datereps, Group = groupreps, Value = value)  

这会将flag 应用于您指定的条件:

df$flag <- ifelse(df$DateTime >= as.Date("2014-08-01") & df$DateTime <= "2014-08-11" |
                    df$DateTime >= as.Date("2014-08-26") & df$DateTime <= "2014-09-01", 
                  "flag", "other")

那你可以看看:

df[df$flag=="flag",]

【讨论】:

  • 感谢 boshek 的回复。但是,此方法不考虑组。我还需要使用数据框“标志”,因为我有许多不同的开始日期和结束日期,我不想手动将这些日期输入到 ifelse 语句中。
【解决方案2】:

将最后一行更改为:

for (i in 1:nrow(df2)) {
    if (is.na(df2$start[i])) {
        df2$flag[i] = 'other'
    } else if (df2$Date[i] >= as.Date(df2$start[i]) & df2$Date[i] <= as.Date(df2$end[i])) {
        df2$flag[i] = "flag"
    } else {
        df2$flag[i] = "other"
    }
}

它很丑,但它可以完成工作。此代码未矢量化,因此适合您的情况,但对于较大的应用程序会很慢。

【讨论】:

  • 对示例中的错误表示抱歉。我刚刚更新了它,但仍然有问题。
  • 在这种情况下,您将不得不使用 ifelse() 函数以外的东西。您正在尝试比较两个日期对象,如果其中一个不是日期(如 NA),它将返回 NA。您可能需要编写一个自定义函数来执行此操作,然后使用 sapply() 或 purrr 包中的 map_chr() 将其应用于标志列。
  • 这确实有效。另一种解决方案避免了循环,也使我们使用is.na 索引:df2$flag &lt;- NA df2$flag &lt;- ifelse(df2$Date &gt;= as.Date(df2$start) &amp; df2$Date &lt;= as.Date(df2$end), "flag", "other") df2$flag[is.na(df2$flag)] &lt;- "other" # replace NA's with "other"
猜你喜欢
  • 2016-07-25
  • 2015-08-19
  • 1970-01-01
  • 2012-12-10
  • 2017-02-02
  • 1970-01-01
  • 2022-11-23
  • 2013-12-13
  • 1970-01-01
相关资源
最近更新 更多