我有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)
最佳答案
在我看来,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)
,您可以将数据帧/标题转换为data.table。 - 使用
data1[data2, on = 'date']
,您可以进行 data.table-way 连接。 - 通过将
(nms) := mget(paste0('i.',nms))
添加到连接,您可以告诉data.table
更新data1
中的列也仅在日期匹配的情况下才出现在data2
中。
作为替代方法,您还可以将两个数据集 reshape 为长格式,然后进行连接:
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)
关于用新数据替换部分数据框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47588455/