【问题标题】:R: Compare two data.frames and delete data that not matchR:比较两个data.frames并删除不匹配的数据
【发布时间】:2016-11-02 21:42:15
【问题描述】:

我有两个 data.frame 时间序列。第一个是完整的,第二个仅包含具有正确变量值的时间步长。我需要保留所有其他变量,但想要 NA 出现在第二个 df 中的所有变量。这里是例子:

library(dplyr)
library(tidyverse)
library(lubridate)

#test data:
TDF <- tibble(DATE = seq( make_datetime(2007,09,23,06,00), make_datetime(2008,07,05,23,00), by = 600),
          V1 = round(runif(length(DATE)),2),
          V2 = round(runif(length(DATE)),2),
          V3 = round(runif(length(DATE)),2))
TDF2 <- TDF
TDF2 <- TDF2[TDF2$V1>0.7,]

输出:

> TDF
# A tibble: 41,287 × 4
                  DATE    V1    V2    V3
                <dttm> <dbl> <dbl> <dbl>
1  2007-09-23 06:00:00  0.89  0.21  0.03
2  2007-09-23 06:10:00  0.26  0.54  0.70
3  2007-09-23 06:20:00  0.74  0.22  0.80
4  2007-09-23 06:30:00  0.31  0.48  0.38
5  2007-09-23 06:40:00  0.93  0.26  0.21

> TDF2
# A tibble: 11,972 × 4
                  DATE    V1    V2    V3
                <dttm> <dbl> <dbl> <dbl>
1  2007-09-23 06:00:00  0.89  0.21  0.03
2  2007-09-23 06:20:00  0.74  0.22  0.80
3  2007-09-23 06:40:00  0.93  0.26  0.21
4  2007-09-23 07:20:00  0.91  0.36  0.83
5  2007-09-23 07:40:00  0.95  0.87  0.91

这就是我需要的:

> TDF_modified
# A tibble: 41,287 × 4
                  DATE    V1    V2    V3
                <dttm> <dbl> <dbl> <dbl>
1  2007-09-23 06:00:00  0.89  0.21  0.03
2  2007-09-23 06:10:00  NA    0.54  0.70
3  2007-09-23 06:20:00  0.74  0.22  0.80
4  2007-09-23 06:30:00  NA    0.48  0.38
5  2007-09-23 06:40:00  0.93  0.26  0.21

我需要一个通用的解决方案,只需使用两个 data.frame。我可以通过循环来做到这一点,但我敢打赌有一种更优雅的方式。非常感谢先进!

【问题讨论】:

    标签: r dataframe dplyr


    【解决方案1】:

    我并不完全清楚您在寻找什么,但根据您的示例输出,您似乎希望从 TDF 中保留 V2V3 的结果,并且只删除 V1阅读。

    一种方法是使用left_join,不使用TDF 中的V1 列,而仅使用TDF2 中的V1 列:

    left_join(
      select(TDF, -V1)
      , select(TDF2, DATE, V1) )
    

    给予:

                      DATE    V2    V3    V1
                    <dttm> <dbl> <dbl> <dbl>
    1  2007-09-23 06:00:00  0.14  0.62    NA
    2  2007-09-23 06:10:00  0.87  0.05  0.87
    3  2007-09-23 06:20:00  0.20  0.52    NA
    4  2007-09-23 06:30:00  0.34  0.01    NA
    5  2007-09-23 06:40:00  0.92  0.37  0.83
    6  2007-09-23 06:50:00  0.94  0.27    NA
    7  2007-09-23 07:00:00  0.98  0.49    NA
    8  2007-09-23 07:10:00  0.70  0.98    NA
    9  2007-09-23 07:20:00  0.05  0.55  0.72
    10 2007-09-23 07:30:00  0.16  0.12  0.99
    

    来自我的随机数据。

    如果您正在寻找更完整的解决方案,您可以执行full_join,这将产生重复的列,然后按照您的意愿处理它们。例如,如果缺少V1,这将返回NA,如果缺少TDF2$V1,但对于V2V3,如果缺少,它会给出TDF 值,并且仅在两个值存在时给出NA,并且不同的。由于我不确定您要使用什么,您可能需要在此处添加更复杂的检查。

    full_join(TDF, TDF2, "DATE") %>%
      mutate(V1 = ifelse(is.na(V1.y), NA, V1.x)
             , V2 = ifelse(is.na(V2.y), V2.x
                           , ifelse(V2.x == V2.y, V2.x, NA))
             , V3 = ifelse(is.na(V3.y), V3.x
                           , ifelse(V3.x == V3.y, V3.x, NA))
             )
    

    返回:

    # A tibble: 41,287 × 10
                      DATE  V1.x  V2.x  V3.x  V1.y  V2.y  V3.y    V1    V2    V3
                    <dttm> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
    1  2007-09-23 06:00:00  0.62  0.14  0.62    NA    NA    NA    NA  0.14  0.62
    2  2007-09-23 06:10:00  0.87  0.87  0.05  0.87  0.87  0.05  0.87  0.87  0.05
    3  2007-09-23 06:20:00  0.53  0.20  0.52    NA    NA    NA    NA  0.20  0.52
    4  2007-09-23 06:30:00  0.03  0.34  0.01    NA    NA    NA    NA  0.34  0.01
    5  2007-09-23 06:40:00  0.83  0.92  0.37  0.83  0.92  0.37  0.83  0.92  0.37
    6  2007-09-23 06:50:00  0.70  0.94  0.27    NA    NA    NA    NA  0.94  0.27
    7  2007-09-23 07:00:00  0.51  0.98  0.49    NA    NA    NA    NA  0.98  0.49
    8  2007-09-23 07:10:00  0.65  0.70  0.98    NA    NA    NA    NA  0.70  0.98
    9  2007-09-23 07:20:00  0.72  0.05  0.55  0.72  0.05  0.55  0.72  0.05  0.55
    10 2007-09-23 07:30:00  0.99  0.16  0.12  0.99  0.16  0.12  0.99  0.16  0.12
    # ... with 41,277 more rows
    

    (而且,要清理重复的列,只需在完成后使用select。)

    【讨论】:

      【解决方案2】:

      这是一个应该可以工作的基本 R 解决方案:

      is.na(TDF$V1[setdiff(seq_len(nrow(TDF)), match(TDF$Date, TDF2$Date))]) <- TRUE
      

      match 函数返回 TDF 中的观察位置,其中 TDF2 中存在相同的日期。 setdiff 将此输出转换为该集合的补集,即 TDF 中日期不匹配的观察集。对于这些观察,使用is.na&lt;- 方法将 TDF$V1 的值设置为 NA。

      【讨论】:

      • 也感谢基本 R 解决方案!
      猜你喜欢
      • 2021-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-14
      相关资源
      最近更新 更多