R 使用NAs按时间和变量ID合并两个数据帧

R 使用NAs按时间和变量ID合并两个数据帧,r,dataframe,merge,data.table,sqldf,R,Dataframe,Merge,Data.table,Sqldf,我目前正在使用R中的一些货币,希望合并或覆盖两个数据集以创建一个 对于所有货币,我在DF1中有1980年至2017年的数据。对于其中的16个,我在DF2中也有1970年至1975年至2017年间不同地点的数据。我想做的是将DF2中的1970-1980部分放在DF1之上。我想如果我设法将DF1合并到DF2中,对于它们都有值的单元格(因此DF1覆盖DF2),我会获得相同的结果。然而,并非所有货币的起始日期都完全相同,所以我不能只是硬编码 下面是一个示例,向您展示它的外观: Date是时间变量(每月数

我目前正在使用R中的一些货币,希望合并或覆盖两个数据集以创建一个

对于所有货币,我在
DF1
中有1980年至2017年的数据。对于其中的16个,我在
DF2
中也有1970年至1975年至2017年间不同地点的数据。我想做的是将
DF2
中的1970-1980部分放在
DF1
之上。我想如果我设法将
DF1
合并到
DF2
中,对于它们都有值的单元格(因此
DF1
覆盖
DF2
),我会获得相同的结果。然而,并非所有货币的起始日期都完全相同,所以我不能只是硬编码

下面是一个示例,向您展示它的外观:
Date
是时间变量(每月数据)
DF1
将对应于1980-2017年的数据,
DF2
将对应于1970-2017年的数据。我的目标是基于列和行ID将
DF1
中的值重写为
DF2
DF3
是所需的输出,没有来自DF1的NAs,而是来自DF2的值

set.seed(1234)
DF1=data.frame(matrix(data=c(c(4:9),rnorm(30)),6,6))
set.seed(4321)
DF2=data.frame(matrix(data=c(c(1:12),rnorm(36)),12,4))
names(DF1)=c("Date","Currency1","Currency3","Currency6","Currency7","Currency8")
names(DF2)=c("Date","Currency1","Currency2","Currency3")
DF1$Currency3[1:2]=NA
DF1$Currency1[4:5]=NA

> DF1
  Date  Currency1  Currency3   Currency6  Currency7  Currency8
1    4 -1.2070657         NA -0.77625389 -0.8371717 -0.6937202
2    5  0.2774292         NA  0.06445882  2.4158352 -1.4482049
3    6  1.0844412 -0.5644520  0.95949406  0.1340882  0.5747557
4    7         NA -0.8900378 -0.11028549 -0.4906859 -1.0236557
5    8         NA -0.4771927 -0.51100951 -0.4405479 -0.0151383
6    9  0.5060559 -0.9983864 -0.91119542  0.4595894 -0.9359486

> DF2
   Date   Currency1    Currency2   Currency3
1     1 -0.42675738 -1.260985237 -0.09920208
2     2 -0.22361182  1.139464085 -0.23803425
3     3  0.71760679 -1.221781923  0.04778266
4     4  0.84144567  1.573315888  0.29651274
5     5 -0.12835727  0.073477874 -0.83380992
6     6  1.60934721 -1.175115087 -1.37397000
7     7 -0.29716745 -1.588261899  0.14027895
8     8  0.19600465 -0.747380729  0.66212596
9     9  1.24074620  0.483521864  1.13103967
10   10 -0.71869815 -0.003025539 -0.47511202
11   11 -0.06723632 -0.008930402  0.85241411
12   12  0.34436710  0.593357619 -0.75151885
我从一个用户那里得到了这个答案,但我遇到了一个新问题,
DF1
中的一些数据包含
NA
s,该代码将其覆盖到
DF2

library(data.table)
DF3 <- copy(DF2)
nm1 <- names(DF1)[-1]
setDT(DF3)[DF1, (nm1) := mget(paste0("i.", nm1)), on = .(Date)]

    > DF3
    Date  Currency1  Currency2    Currency3   Currency6  Currency7  Currency8
 1:    1  1.1022975 -0.8553646 -0.162309524          NA         NA         NA
 2:    2 -0.4755931 -0.2806230  0.563055819          NA         NA         NA
 3:    3 -0.7094400 -0.9943401  1.647817473          NA         NA         NA
 4:    4 -1.2070657 -0.9685143           NA -0.77625389 -0.8371717 -0.6937202
 5:    5  0.2774292 -1.1073182           NA  0.06445882  2.4158352 -1.4482049
 6:    6  1.0844412 -1.2519859 -0.564451999  0.95949406  0.1340882  0.5747557
 7:    7         NA -0.5238281 -0.890037829 -0.11028549 -0.4906859 -1.0236557
 8:    8         NA -0.4968500 -0.477192700 -0.51100951 -0.4405479 -0.0151383
 9:    9  0.5060559 -1.8060313 -0.998386445 -0.91119542  0.4595894 -0.9359486
10:   10 -0.4658975 -0.5820759 -0.669633580          NA         NA         NA
11:   11  1.4494963 -1.1088896 -0.007604756          NA         NA         NA
12:   12 -1.0686427 -1.0149620  1.777084448          NA         NA         NA
库(data.table)

DF3要仅替换
DF3
中在
DF1
中没有缺失对应项的值,可以使用
ifelse

使用:

DF3 <- copy(DF2)
nm1 <- names(DF1)[-1]
nm2 <- names(DF2)
setDT(DF3)[DF1, (nm1) := {n <- seq_along(nm1);
                          lapply(n, function(i) ifelse(is.na(get(paste0("i.", nm1[i]))) & nm1[i] %in% nm2, 
                                                       get(paste0("x.", nm1[i])), 
                                                       get(paste0("i.", nm1[i]))))},
           on = .(Date)]

使用数据:

set.seed(1234)
DF1=data.frame(matrix(data=c(c(4:9),rnorm(30)),6,6))
set.seed(4321)
DF2=data.frame(matrix(data=c(c(1:12),rnorm(36)),12,4))
names(DF1)=c("Date","Currency1","Currency3","Currency6","Currency7","Currency8")
names(DF2)=c("Date","Currency1","Currency2","Currency3")
DF1$Currency3[1:2]=NA
DF1$Currency1[4:5]=NA
DF1$Currency7[nrow(DF1)]=NA
1)sqldf使用
coalesce
执行
DF1
DF2
的左连接,以在其参数中选择第一个不缺失的参数:

library(sqldf)
sqldf("select Date,
              coalesce(DF1.Currency1, DF2.Currency1) Currency1,
              DF2.Currency2,
              coalesce(DF1.Currency3, DF2.Currency3) Currency3
       from DF2 left join DF1 using (Date)")
给予:

   Date   Currency1   Currency2  Currency3
1     1  1.12493092 -0.15579551  1.1000254
2     2 -0.04493361 -1.47075238  0.7631757
3     3 -0.01619026 -0.47815006 -0.1645236
4     4 -0.83562860  0.41794156 -0.2533617
5     5  1.59528080  1.35867955  0.6969634
6     6  0.32950780 -0.10278773  1.5117812
7     7 -0.82046840  0.38767161  0.3898432
8     8  0.48742910 -0.05380504 -0.6212406
9     9  0.73832470 -1.37705956 -2.2146999
10   10 -1.98935170 -0.41499456  0.7685329
11   11  0.61982575 -0.39428995 -0.1123462
12   12 -0.05612874 -0.05931340  0.8811077
   Date   Currency1   Currency2  Currency3
1     1  1.12493092 -0.15579551  1.1000254
2     2 -0.04493361 -1.47075238  0.7631757
3     3 -0.01619026 -0.47815006 -0.1645236
4     4 -0.83562860  0.41794156 -0.2533617
5     5  1.59528080  1.35867955  0.6969634
6     6  0.32950780 -0.10278773  1.5117812
7     7 -0.82046840  0.38767161  0.3898432
8     8  0.48742910 -0.05380504 -0.6212406
9     9  0.73832470 -1.37705956 -2.2146999
10   10 -1.98935170 -0.41499456  0.7685329
11   11  0.61982575 -0.39428995 -0.1123462
12   12 -0.05612874 -0.05931340  0.8811077
这些名称可以如下参数化:

Date <- names(DF2)[1]
Currency1 <- names(DF2)[2]
Currency2 <- names(DF2)[3]
Currency3 <- names(DF2)[4]

fn$sqldf("select [$Date],
              coalesce(DF1.[$Currency1], DF2.[$Currency1]) [$Currency1],
              DF2.[$Currency2],
              coalesce(DF1.[$Currency3], DF2.[$Currency3]) [$Currency3]
       from DF2 left join DF1 using ([$Date])")
2)dplyrdplyr可以以基本相同的方式执行此操作,甚至具有
coalesce
功能:

library(dplyr)
DF2 %>% 
     left_join(DF1, by = "Date") %>%
     transmute(Date,
               Currency1 = coalesce(Currency1.y, Currency1.x),
               Currency2,
               Currency3 = coalesce(Currency3.y, Currency3.x))
给予:

   Date   Currency1   Currency2  Currency3
1     1  1.12493092 -0.15579551  1.1000254
2     2 -0.04493361 -1.47075238  0.7631757
3     3 -0.01619026 -0.47815006 -0.1645236
4     4 -0.83562860  0.41794156 -0.2533617
5     5  1.59528080  1.35867955  0.6969634
6     6  0.32950780 -0.10278773  1.5117812
7     7 -0.82046840  0.38767161  0.3898432
8     8  0.48742910 -0.05380504 -0.6212406
9     9  0.73832470 -1.37705956 -2.2146999
10   10 -1.98935170 -0.41499456  0.7685329
11   11  0.61982575 -0.39428995 -0.1123462
12   12 -0.05612874 -0.05931340  0.8811077
   Date   Currency1   Currency2  Currency3
1     1  1.12493092 -0.15579551  1.1000254
2     2 -0.04493361 -1.47075238  0.7631757
3     3 -0.01619026 -0.47815006 -0.1645236
4     4 -0.83562860  0.41794156 -0.2533617
5     5  1.59528080  1.35867955  0.6969634
6     6  0.32950780 -0.10278773  1.5117812
7     7 -0.82046840  0.38767161  0.3898432
8     8  0.48742910 -0.05380504 -0.6212406
9     9  0.73832470 -1.37705956 -2.2146999
10   10 -1.98935170 -0.41499456  0.7685329
11   11  0.61982575 -0.39428995 -0.1123462
12   12 -0.05612874 -0.05931340  0.8811077
注意:定义问题中输入的原始代码未使用
set.seed
使其不可复制,因此我们使用了与问题中最初显示的输入相对应的以下代码。(从那时起,这个问题被修正为添加
set.seed


DF1谢谢。如何用自动脚本替换手动编写的列名(currency1-2-3)?我将尝试一下!我用一个“新问题”更新了原来的帖子,主要是因为我是个笨蛋。对于sqldf,在SQL语句中定义变量Date、Currency1、Currency2、将列名作为值的货币以及使用$Date等。见第1点末尾的补充。或者,只需将列重命名为标准名称,执行计算并恢复名称即可。这种重命名方法也适用于dplyr。请看这两种方法的答案。谢谢,我看看是否有效。(你看到主帖子中的数据编辑了吗?)。请注意,您只需要在顶部设置一个
set.seed
,以使其可复制。它们是其他的
set.seed
命令,这些命令不会造成伤害,但实际上并不需要使其可复制。在实际数据上尝试时,我遇到了一个问题。在运行setDT时,它会给出一个错误,提示“get(paste0(“x.”,names1[i]):未找到对象“x.somecurrency”
”。在实际数据中,我在DF1中的货币比在DF2中的货币多,这可能是问题所在吗?@NielsJo It正在处理更新的示例数据。您使用的是data.table的最新版本吗?此外,最好为
DF2
使用另一个
set.seed()。我会再次尝试运行代码,也许我在某个地方犯了一个小错误,谢谢!这个例子工作得很好,但实际的数据却不是这样。我可以使用DF1作为副本运行相反的操作,并从DF2获取名称,但是当我交换名称时,会出现错误,这对我来说没有意义。几乎发疯了,我现在已经尝试了所有可能的迭代。@NielsJo没有重现问题的示例,很难说出确切的问题是什么……请使用
set.seed(1234)
在使用随机生成的值或
sample()
时创建可重现的数据。谢谢。如果有帮助的话,当然可以。最好对DF2使用另一个set.seed(),这样您就可以看到一种方法是否有效。请参阅我的更新答案以获取示例。感谢您的编辑。
DF1 <-
structure(list(Date = 4:9, Currency1 = c(-0.8356286, 1.5952808, 
0.3295078, -0.8204684, 0.4874291, 0.7383247), Currency3 = c(NA, 
NA, 1.5117812, 0.3898432, -0.6212406, -2.2146999)), .Names = c("Date", 
"Currency1", "Currency3"), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6"))

DF2 <-
structure(list(Date = 1:12, Currency1 = c(1.12493092, -0.04493361, 
-0.01619026, 0.94383621, 0.8212212, 0.59390132, 0.91897737, 0.7821363, 
0.07456498, -1.9893517, 0.61982575, -0.05612874), Currency2 = c(-0.15579551, 
-1.47075238, -0.47815006, 0.41794156, 1.35867955, -0.10278773, 
0.38767161, -0.05380504, -1.37705956, -0.41499456, -0.39428995, 
-0.0593134), Currency3 = c(1.1000254, 0.7631757, -0.1645236, 
-0.2533617, 0.6969634, 0.5566632, -0.6887557, -0.7074952, 0.364582, 
0.7685329, -0.1123462, 0.8811077)), .Names = c("Date", "Currency1", 
"Currency2", "Currency3"), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"))