合并非键变量的所有 "occurrences"
Merge for all "occurrences" of a non-key variable
我有两个数据集,我想要的可以粗略地称为 "outer join on a non-key variable"。
这是数据集
数据集 1
oc oc2 state_id r_state
A011 A01 1808 1.00
A011 A01 1810 0.50
A012 A01 1810 0.50
A011 A01 1814 0.33
A012 A01 1814 0.33
A013 A01 1814 0.33
数据集 2
oc r_country
A011 0.62
A012 0.14
A013 0.24
我想要的输出如下:
oc oc2 state_id r_state r_country
A011 A01 1808 1.00 0.62
A012 A01 1808 NA 0.14
A013 A01 1808 NA 0.24
A011 A01 1810 0.50 0.62
A012 A01 1810 0.50 0.14
A013 A01 1810 NA 0.24
A011 A01 1814 0.33 0.62
A012 A01 1814 0.33 0.62
A013 A01 1814 0.33 0.24
请注意行号 2、3 和 6 是如何引入的 "artificially"。我的问题是如何在 R 中执行此操作。如果我按 oc
合并,merge
函数将不会创建这些行。如果我按 oc2
合并,它将创建不必要的额外行。请注意,oc2
只是 oc
的更高级别编码。下面是几行代码,用于在 data.tables 中获取上述数据集。请注意,这些是示例数据集,实际数据包含大约 50 个不同的 oc2
,每个 oc2
可以包含 1 到 9 个 oc
。此外,还有 47 个不同的州。
DT1 = data.table(oc = c('A011','A011','A012','A011','A012','A013'),
oc2 = rep('A01',6),
state_id = c(1808,1810,1810,1814,1814,1814),
r_state = c(1, 0.5,0.5,0.33,0.33,0.33)
)
DT2 = data.table(oc = c('A011','A012','A013'),
r_country = c(0.62, 0.14, 0.24)
)
虽然我使用的是 data.table
,但基础 data.frame
解决方案也可以。
使用:
library(zoo) # for the 'na.locf'-function
DT1[CJ(oc = oc, state_id = state_id, unique = TRUE), on = .(oc, state_id)
][order(state_id), oc2 := na.locf(oc2), by = 'state_id'
][DT2, on = 'oc', r_country := r_country][order(state_id)]
给出:
oc oc2 state_id r_state r_country
1: A011 A01 1808 1.00 0.62
2: A012 A01 1808 NA 0.14
3: A013 A01 1808 NA 0.24
4: A011 A01 1810 0.50 0.62
5: A012 A01 1810 0.50 0.14
6: A013 A01 1810 NA 0.24
7: A011 A01 1814 0.33 0.62
8: A012 A01 1814 0.33 0.14
9: A013 A01 1814 0.33 0.24
根据@Frank 的建议,您也可以不使用 zoo
-package 中的 na.locf
:
DT1[CJ(oc = oc, state_id = state_id, unique = TRUE), on = .(oc, state_id)
][DT2, on = .(oc), r_country := i.r_country][DT1, on = .(state_id), oc2 := i.oc2][]
这可以表示为使用将这 4 个表连接在一起的三重连接的单个 SQL 语句:
oc
由唯一的 oc
值组成,
state_id
由唯一的 state_id
值组成,
DT1
和
DT2
使用此代码:
library(sqldf)
sql <- "
with
oc as (select distinct oc from DT1),
state_id as (select distinct state_id from DT1)
select *
from oc
join state_id
left join DT1 using (oc, state_id)
left join DT2 using (oc)
order by state_id, oc"
sqldf(sql)
给出此输出:
oc state_id oc2 r_state r_country
1 A011 1808 A01 1.00 0.62
2 A012 1808 <NA> NA 0.14
3 A013 1808 <NA> NA 0.24
4 A011 1810 A01 0.50 0.62
5 A012 1810 A01 0.50 0.14
6 A013 1810 <NA> NA 0.24
7 A011 1814 A01 0.33 0.62
8 A012 1814 A01 0.33 0.14
9 A013 1814 A01 0.33 0.24
我有两个数据集,我想要的可以粗略地称为 "outer join on a non-key variable"。
这是数据集
数据集 1
oc oc2 state_id r_state
A011 A01 1808 1.00
A011 A01 1810 0.50
A012 A01 1810 0.50
A011 A01 1814 0.33
A012 A01 1814 0.33
A013 A01 1814 0.33
数据集 2
oc r_country
A011 0.62
A012 0.14
A013 0.24
我想要的输出如下:
oc oc2 state_id r_state r_country
A011 A01 1808 1.00 0.62
A012 A01 1808 NA 0.14
A013 A01 1808 NA 0.24
A011 A01 1810 0.50 0.62
A012 A01 1810 0.50 0.14
A013 A01 1810 NA 0.24
A011 A01 1814 0.33 0.62
A012 A01 1814 0.33 0.62
A013 A01 1814 0.33 0.24
请注意行号 2、3 和 6 是如何引入的 "artificially"。我的问题是如何在 R 中执行此操作。如果我按 oc
合并,merge
函数将不会创建这些行。如果我按 oc2
合并,它将创建不必要的额外行。请注意,oc2
只是 oc
的更高级别编码。下面是几行代码,用于在 data.tables 中获取上述数据集。请注意,这些是示例数据集,实际数据包含大约 50 个不同的 oc2
,每个 oc2
可以包含 1 到 9 个 oc
。此外,还有 47 个不同的州。
DT1 = data.table(oc = c('A011','A011','A012','A011','A012','A013'),
oc2 = rep('A01',6),
state_id = c(1808,1810,1810,1814,1814,1814),
r_state = c(1, 0.5,0.5,0.33,0.33,0.33)
)
DT2 = data.table(oc = c('A011','A012','A013'),
r_country = c(0.62, 0.14, 0.24)
)
虽然我使用的是 data.table
,但基础 data.frame
解决方案也可以。
使用:
library(zoo) # for the 'na.locf'-function
DT1[CJ(oc = oc, state_id = state_id, unique = TRUE), on = .(oc, state_id)
][order(state_id), oc2 := na.locf(oc2), by = 'state_id'
][DT2, on = 'oc', r_country := r_country][order(state_id)]
给出:
oc oc2 state_id r_state r_country 1: A011 A01 1808 1.00 0.62 2: A012 A01 1808 NA 0.14 3: A013 A01 1808 NA 0.24 4: A011 A01 1810 0.50 0.62 5: A012 A01 1810 0.50 0.14 6: A013 A01 1810 NA 0.24 7: A011 A01 1814 0.33 0.62 8: A012 A01 1814 0.33 0.14 9: A013 A01 1814 0.33 0.24
根据@Frank 的建议,您也可以不使用 zoo
-package 中的 na.locf
:
DT1[CJ(oc = oc, state_id = state_id, unique = TRUE), on = .(oc, state_id)
][DT2, on = .(oc), r_country := i.r_country][DT1, on = .(state_id), oc2 := i.oc2][]
这可以表示为使用将这 4 个表连接在一起的三重连接的单个 SQL 语句:
oc
由唯一的oc
值组成,state_id
由唯一的state_id
值组成,DT1
和DT2
使用此代码:
library(sqldf)
sql <- "
with
oc as (select distinct oc from DT1),
state_id as (select distinct state_id from DT1)
select *
from oc
join state_id
left join DT1 using (oc, state_id)
left join DT2 using (oc)
order by state_id, oc"
sqldf(sql)
给出此输出:
oc state_id oc2 r_state r_country
1 A011 1808 A01 1.00 0.62
2 A012 1808 <NA> NA 0.14
3 A013 1808 <NA> NA 0.24
4 A011 1810 A01 0.50 0.62
5 A012 1810 A01 0.50 0.14
6 A013 1810 <NA> NA 0.24
7 A011 1814 A01 0.33 0.62
8 A012 1814 A01 0.33 0.14
9 A013 1814 A01 0.33 0.24