用新数据

时间:2017-12-01 07:20:55

标签: r dplyr

我有 data1 data2 ,我需要 data3 ,用<替换 data1 的某些区域EM> DATA2

我使用此方法更新数据,但实际上需要更新几个列,这将是繁琐的。

你知道更简单的方法吗?

library(tidyverse)
library(lubridate)

data1 <- tibble(date=date("2017-11-1") + c(1:10),
            a=sample(100,10),b=sample(100,10))

data2 <- tibble(date=date("2017-11-1") + c(1:8),
            a=sample(100,8))

data_bind <- left_join(data1, data2, by=("date"))
data_bind$a.x[!is.na(data_bind$a.y)] <- data_bind$a.y[!is.na(data_bind$a.y)]
data_bind %>% select(-a.y) %>% dplyr::rename(a=a.x)

1 个答案:

答案 0 :(得分:5)

在我看来,data.table - 包更适合这样的任务。使用:

# create a vector with names from 'data2' that are not used to join by
nms <- names(data2)[-1]

# load the 'data.table'-package
library(data.table)

# convert the dataframes to data,table's
setDT(data1)
setDT(data2)

# join and update the column in 'data1' with the matching values from 'data2'
data1[data2, on = 'date', (nms) := mget(paste0('i.',nms))][]

给出:

          date  a  b
 1: 2017-11-02 21 11
 2: 2017-11-03 22 12
 3: 2017-11-04 23 13
 4: 2017-11-05 24 14
 5: 2017-11-06 25 15
 6: 2017-11-07 26 16
 7: 2017-11-08 27 17
 8: 2017-11-09 28 18
 9: 2017-11-10  9 19
10: 2017-11-11 10 20

这是做什么的:

  • 使用setDT(data1)将dataframes / tibbles转换为data.table。
  • 使用data1[data2, on = 'date'],您可以加入data.table-way。
  • 通过向加入添加(nms) := mget(paste0('i.',nms)),您告诉data.table更新data1中的列,其中的列仅在日期匹配的data2中出现。

作为替代方法,您还可以将两个数据集重新整形为长格式,然后进行连接:

library(data.table)
melt(data1, id = 'date')[melt(data2, id = 'date')
                         , on = .(date, variable)
                         , value := i.value
                         ][, dcast(.SD, date ~ variable)]

将此方法转换为tidyverse

library(dplyr)
library(tidyr)

gather(data1, key, value, -1) %>% 
  left_join(., gather(data2, key, value, -1), by = c('date','key')) %>% 
  mutate(value.x = ifelse(!is.na(value.y), value.y, value.x)) %>% 
  select(date, key, value = value.x) %>% 
  spread(key, value)

两者都会给你相同的输出。

使用过的数据:

data1 <- data.frame(date = as.Date("2017-11-1") + c(1:10), a = 1:10, b = 11:20)
data2 <- data.frame(date = as.Date("2017-11-1") + c(1:8), a = 21:28)