尝试合并具有特定条件的两个数据帧和R

时间:2017-08-17 10:31:42

标签: r join dataframe dplyr missing-data

我有两个数据框(df1df2)。我正在使用dplyr来操纵我的数据。但是,我在找到以下结果时遇到了一些麻烦:

df1包含有关idpricedate的一些信息(id并非唯一:给定id可以决定几个价格)

df2可以判断对于给定的ID是否在df1

中修改了价格和/或日期的值

我想知道是否有价格和/或日期的修改,如果是这样的话,我想把这个新值作为价格/日期

但是,df1df2都可能有点棘手,因为您可以对给定的ID进行多次修改。

更具体地说,对于给定的价格修改(如果存在,否则我采用df1中给出的价格),我想将其与日期的最后修改相关联(如果它存在,否则我采取df1)中给出的日期,只要它是<= df1$date + 30

总结一下,这是一个例子:

df1 <- data.frame(
       Id = c(1,1,2),
       price = c(1000,2000,1000),
       date = c("2016-01-01","2016-09-01","2016-01-01")
    )
df1
  Id price       date
  1  1000   2016-01-01
  1  2000   2016-09-01
  2  1000   2016-01-01

df2如下:

df2 <- data.frame(
   Id = c(1,1,1,1,1,2,2),
   price = c(1500,NA,2000,NA,3000,NA,NA),
   date = c(NA, "2016-01-03", "2016-01-05", "2016-09-02","2016-09-03","2016-01-03","2016-01-05")
)

df2
  Id price       date
  1  1500       <NA>
  1    NA   2016-01-03
  1  2000   2016-01-05
  1    NA   2016-09-02
  1  3000   2016-09-03
  2    NA   2016-01-03
  2    NA   2016-01-05

结果我希望有类似的东西:

  Id initial_price  initial_date   is_modification_price  is_modification_date true_price    true_date

  1   1000          2016-01-01          TRUE                     TRUE             2000       2016-01-05
  1   2000          2016-09-01          TRUE                     TRUE             3000       2016-09-03
  2   1000          2016-01-01          FALSE                    TRUE             1000       2016-01-05

我希望我足够清楚

有没有人知道如何实现这一点;甚至是一种完全不同的方法?

1 个答案:

答案 0 :(得分:1)

首先,准备数据帧:

# fix type
df1 <- mutate(df1, date = as.Date(date))

# fill NAs in df2
df2 <- df2 %>%
  mutate(date = as.Date(date)) %>%
  group_by(Id) %>%
  tidyr::fill(price, date) %>%
  ungroup

# fill remaining NAs with default values taken from df1
default_values <- df1 %>%
  group_by(Id) %>%
  slice(1) %>%
  rename(price0 = price, date0 = date) %>%
  ungroup

df2 <- df2 %>%
  left_join(default_values, by = "Id") %>%
  mutate(price = if_else(is.na(price), price0, price),
         date = if_else(is.na(date), date0, date)) %>%
  select(Id, price, date)

然后加入:

df1 %>%
  left_join(df2, by = "Id") %>%
  filter(date.y <= date.x + 30) %>%
  group_by(Id, price.x, date.x) %>%
  arrange(date.y) %>%
  slice(n()) %>%
  ungroup %>%
  rename(initial_price = price.x, initial_date = date.x,
         true_price = price.y, true_date = date.y) %>%
  mutate(is_modification_price = (initial_price != true_price),
         is_modification_date = (initial_date != true_date))
# # A tibble: 3 x 7
#      Id initial_price initial_date true_price  true_date is_modification_price is_modification_date
#   <dbl>         <dbl>       <date>      <dbl>     <date>                 <lgl>                <lgl>
# 1     1          1000   2016-01-01       2000 2016-01-05                  TRUE                 TRUE
# 2     1          2000   2016-09-01       3000 2016-09-03                  TRUE                 TRUE
# 3     2          1000   2016-01-01       1000 2016-01-05                 FALSE                 TRUE

请注意,最后一步中left_join后跟filter可能会占用太多内存。如果是这种情况,请改用data.table中的非等连接功能。