【问题标题】:Removing days before and after matching row删除匹配行前后的天数
【发布时间】:2016-01-23 22:19:18
【问题描述】:

我可以删除两个数据帧 df1 和 df2 之间匹配的行,并使用@Eric Fail 提供的一些代码:

df1[!(apply(df1[1:2], 1, toString) %in% apply(df2[1:2], 1, toString)), ]

或使用@steveb 提供的dplyr 解决方案

df1 %>% filter( ! ((date == df2$date) & (ticker == df2$ticker)) )

但是,我意识到我不仅需要像这样删除共享行:

df1 <- data.frame(ticker = c("MSFT", "MSFT", "MSFT", "MSFT"), 
date = c("2016-01-01", "2016-01-02", "2016-01-03", "2016-01-04"), stringsAsFactors=F)
df1

  ticker       date
1   MSFT 2016-01-01
2   MSFT 2016-01-02
3   MSFT 2016-01-03
4   MSFT 2016-01-04

df2 <- data.frame(ticker = c("AAPL", "GOOG", "MSFT", "FB"), 
date = c("2016-01-01", "2016-01-01", "2016-01-02", "2016-01-03"), stringsAsFactors=F)
df2

  ticker       date
1   AAPL 2016-01-01
2   GOOG 2016-01-01
3   MSFT 2016-01-02
4     FB 2016-01-03

df3 

  ticker       date
1   MSFT 2016-01-01
2   MSFT 2016-01-03
3   MSFT 2016-01-04

还有指定行的前一天和后一天。所以我的最终 df 将是:

  ticker       date
1   MSFT 2016-01-04

注意,3 MSFT 2016-01-02 是匹配项,因此需要删除该行,以及前一天和后一天,3 MSFT 2016-01-013 MSFT 2016-01-03

两个匹配的示例:

df1 <- data.frame(ticker = c("MSFT", "MSFT", "MSFT", "MSFT"),
                  date = as.Date(c("2016-01-01", "2016-01-02", "2016-01-03", "2016-01-04")),
                  stringsAsFactors=F)
df2 <- data.frame(ticker = c("AAPL", "GOOG", "MSFT", "MSFT"),
                  date = as.Date(c("2016-01-01", "2016-01-01", "2016-01-01","2016-01-02")),
                  stringsAsFactors=F)

目标输出:

ticker       date
4   MSFT 2016-01-04

【问题讨论】:

    标签: r


    【解决方案1】:

    您可以将字符串转换为日期,以便您可以添加和减去天数

    df1 <- data.frame(ticker = c("MSFT", "MSFT", "MSFT", "MSFT"),
                      date = as.Date(c("2016-01-01", "2016-01-02", "2016-01-03", "2016-01-04")),
                      stringsAsFactors=F)
    df2 <- data.frame(ticker = c("AAPL", "GOOG", "MSFT", "FB"),
                      date = as.Date(c("2016-01-01", "2016-01-01", "2016-01-02", "2016-01-03")),
                      stringsAsFactors=F)
    
    
    (m <- df2[(df2$date %in% df1$date) & (df2$ticker %in% df1$ticker), ])
    #   ticker       date
    # 3   MSFT 2016-01-02
    
    df1[!(df1$date %in% (m$date + c(-1,0,1))), ]
    
    #   ticker       date
    # 4   MSFT 2016-01-04
    

    编辑 - 对于多个匹配项,只需在每个日期应用 function(x)

    df1 <- data.frame(ticker = c("MSFT", "MSFT", "MSFT", "MSFT"),
                      date = as.Date(c("2016-01-01", "2016-01-02", "2016-01-03", "2016-01-04")),
                      stringsAsFactors=F)
    df2 <- data.frame(ticker = c("AAPL", "GOOG", "MSFT", "MSFT"),
                      date = as.Date(c("2016-01-01", "2016-01-01", "2016-01-01","2016-01-02")),
                      stringsAsFactors=F)
    
    (m <- df2[(df2$date %in% df1$date) & (df2$ticker %in% df1$ticker), ])
    #   ticker       date
    # 3   MSFT 2016-01-01
    # 4   MSFT 2016-01-02
    
    df1[!(df1$date %in% (sapply(m$date, function(x) x + c(-1,0,1)))), ]
    #   ticker       date
    # 4   MSFT 2016-01-04
    

    【讨论】:

    • 非常优雅。它工作得很好,除非有两个或更多匹配,在这种情况下我得到Warning message: In unclass(e1) + unclass(e2) : longer object length is not a multiple of shorter object length 并且只删除最后一个匹配。我试图制作一个仅在有两个以上匹配项时才运行的 for 循环,但我想有更好的方法。我在原始问题中添加了另一个包含两个匹配项而不是一个匹配项的示例。
    • @RyGuy 试试df1[!(df1$date %in% (sapply(m$date, function(x) x + c(-1,0,1)))), ]
    • 太棒了!谢谢。
    猜你喜欢
    • 2018-09-13
    • 2021-03-13
    • 1970-01-01
    • 2013-06-22
    • 2014-03-17
    • 2019-02-19
    • 2012-08-01
    • 2013-03-04
    • 1970-01-01
    相关资源
    最近更新 更多