R:比较两个data.frames并删除不匹配的数据

时间:2016-11-02 13:19:22

标签: r dataframe dplyr

我有两个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.frames就需要一个通用的解决方案。我可以通过循环来做,但我打赌有一种更优雅的方式。非常感谢先进!

2 个答案:

答案 0 :(得分:1)

我并不完全清楚您要查找的内容,但根据您的示例输出,您似乎希望保留来自TDF的V2V3的结果,并且仅删除V1阅读。

一种方法是使用left_join而不使用V1的{​​{1}}列,而只使用TDF中的V1列:

TDF2

给出:

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丢失,则返回NA V1,但对于TDF2$V1V2,如果缺少则会V3值,并且如果两个值存在且不同,则仅给出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 。)

答案 1 :(得分:0)

这是一个应该有效的基础R解决方案:

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

match函数返回TDF中的观察位置,其中TDF2中存在相同的日期。 setdiff将此输出转换为此集合的补码,即TDF中日期不匹配的观察集合。使用is.na<-方法将TDF $ V1的值设置为NA以进行观察。