在R中找到某一年的最接近值
我有这类数据:在R中找到某一年的最接近值,r,dplyr,na,R,Dplyr,Na,我有这类数据: iso3 year UHC cata10 AFG 2010 0.3551409 NA AFG 2011 0.3496452 NA AFG 2012 0.3468012 NA AFG 2013 0.3567721 14.631331 AFG 2014 0.3647436 NA AFG 2015 0.3717983 NA AFG 2016 0.3855273 4.837534 AFG 2017
iso3 year UHC cata10
AFG 2010 0.3551409 NA
AFG 2011 0.3496452 NA
AFG 2012 0.3468012 NA
AFG 2013 0.3567721 14.631331
AFG 2014 0.3647436 NA
AFG 2015 0.3717983 NA
AFG 2016 0.3855273 4.837534
AFG 2017 0.3948606 NA
AGO 2011 0.3250651 12.379809
AGO 2012 0.3400455 NA
AGO 2013 0.3397722 NA
AGO 2014 0.3385741 NA
AGO 2015 0.3521086 16.902584
AGO 2016 0.3636765 NA
AGO 2017 0.3764945 NA
我想找出cata10变量最接近2012年和2017年(+ou-2年,即2012年可以是2010年、2011年、2013年或2014年数据)的值。输出应为:
iso3year_UHC UHC year_cata cata10
AFG 2012 0.3468012 2013 14.631331
AFG 2017 0.3948606 2016 4.837534
AGO 2012 0.3400455 2011 12.379809
AGO 2017 0.3764945 2015 16.902584
编辑:请注意,如果在参考年之前或之后2年没有数据,则我应该不适用
两天以来,我一直在尝试命令的音调,但未能找到解决方案。你能告诉我要尝试的命令类型吗
多谢各位
N.这里有三种方法。第一个是最清晰的,因为它表明问题实际上是一个聚合和过滤的自连接,并直接对此进行建模,并自动处理注释中提到的边缘情况,而无需额外代码。第二种方法使用
lappy
循环来获得所需的效果,但它涉及更繁琐的操作,尽管它确实具有零包依赖性的优点。最后一种方法通过执行两次左连接来绕过dplyr缺少复杂的自连接这一事实
1)sqldf使用末尾注释中重复定义的DF
执行自连接,以便年差为-2、-1、1或2,iso3代码相同,匹配实例中cata10不为NA,并且在我们使用的min(…)
查找当年绝对差值最小的行。这使用了这样一个事实:SQLite具有这样一个特性:min(…)
将导致返回满足最小化条件的整行。最后,仅以2012和2017行为例。SQL使用复杂连接直接建模约束的能力允许我们直接将需求建模为代码
library(sqldf)
sqldf("select
a.iso3year iso3year_UHC,
a.UHC,
substr(b.iso3year, 5, 8) year_cata,
b.cata10,
substr(a.iso3year, 5, 8) year,
min(abs(substr(a.iso3year, 5, 8) - substr(b.iso3year, 5, 8))) min_value
from DF a
left join DF b on year - year_cata in (-2, -1, 1, 2) and
substr(a.iso3year, 1, 3) = substr(b.iso3year, 1, 3) and
b.cata10 is not null
group by a.iso3year
having year in ('2012', '2017')")[1:4]
给予:
iso3year_UHC UHC year_cata cata10
1 AFG 2012 0.3468012 2013 14.631331
2 AFG 2017 0.3948606 2016 4.837534
3 AGO 2012 0.3400455 2011 12.379809
4 AGO 2017 0.3764945 2015 16.902584
iso3year_UHC UHC year_cata cata10
1 AFG 2012 0.3468012 2013 14.631331
2 AFG 2017 0.3948606 2016 4.837534
3 AGO 2012 0.3400455 2011 12.379809
4 AGO 2017 0.3764945 2015 16.902584
# A tibble: 4 x 4
iso3year UHC year_cata cata10
<chr> <dbl> <int> <dbl>
1 AFG 2012 0.347 2013 14.6
2 AFG 2017 0.395 2016 4.84
3 AGO 2012 0.340 2011 12.4
4 AGO 2017 0.376 2015 16.9
2)基本R此解决方案仅使用基本R。我们首先通过将iso3year
分为两部分来创建year
和iso
变量ix
是DF
的索引,给出了2012年或2017年为年份的行。对于这些行中的每一行,我们找到具有cata10值的最近年份,并创建一行输出数据帧,lappy
作为行列表返回,L
。最后,我们将这些行绑定在一起。这并不像(1)那样简单,但它的优点是没有包依赖关系
to.year <- function(x) as.numeric(substr(x, 5, 8))
year <- to.year(DF$iso3year)
iso <- substr(DF$iso3year, 1, 3)
ix <- which(year %in% c(2012, 2017))
L <- lapply(ix, function(i) {
DF0 <- na.omit(DF[iso[i] == iso & (year[i] - year) %in% c(-2, -1, 1, 2), ])
if (nrow(DF0)) {
with(DF0[which.min(abs(to.year(DF0$iso3year) - year[i])), c("iso3year", "cata10")],
data.frame(iso3year_UHC = DF$iso3year[i],
UHC = DF$UHC[i],
year_cata = as.numeric(substr(iso3year, 5, 8)),
cata10))
} else {
data.frame(iso3year_UHC = DF$iso3year[i],
UHC = DF$UHC[i],
year_cata = NA,
cata10 = NA)
}
})
do.call("rbind", L)
3)dplyr/tidyr
首先将iso3year
分为iso
和year
列,给出DF2
。然后选择2012和2017行,给出DF3
。现在使用iso
左键将DF3
连接到DF2
,并获取连接实例中cata10
的非NA行,两个连接数据帧之间的绝对年差为1或2。然后使用slice
选择几年中距离最小的行,并选择给出DF4
的所需列,最后将DF3
与DF4
左连接,这将填充不匹配的任何行
library(dplyr)
library(tidyr)
DF2 <- DF %>%
separate(iso3year, c("iso", "year"), remove = FALSE, convert = TRUE)
DF3 <- DF2 %>%
filter(year %in% c(2012, 2017))
DF4 <- DF3 %>%
left_join(DF2, "iso") %>%
drop_na(cata10.y) %>%
filter(abs(year.x - year.y) %in% 1:2) %>%
group_by(iso3year.x) %>%
slice(which.min(abs(year.x - year.y))) %>%
ungroup %>%
select(iso3year = iso3year.x, UHC = UHC.x, year_cata = year.y, cata10 = cata10.y)
DF3 %>%
select(iso3year, UHC) %>%
left_join(DF4, c("iso3year", "UHC"))
库(dplyr)
图书馆(tidyr)
DF2%
单独(iso3year,c(“iso”,“year”),删除=假,转换=真)
DF3%
过滤器(年份百分比,单位为%c(2012年、2017年))
DF4%
左联合(DF2,“iso”)%>%
下降量(cata10.y)%>%
过滤器(绝对值(x年-y年)%在%1:2中%>%
分组依据(iso3year.x)%>%
切片(哪个.min(abs(year.x-year.y)))%>%
解组%>%
选择(iso3year=iso3year.x,UHC=UHC.x,year\u cata=year.y,cata10=cata10.y)
DF3%>%
选择(ISO3年,UHC)%>%
左联合(DF4,c(“ISO3年”、“UHC”))
给予:
iso3year_UHC UHC year_cata cata10
1 AFG 2012 0.3468012 2013 14.631331
2 AFG 2017 0.3948606 2016 4.837534
3 AGO 2012 0.3400455 2011 12.379809
4 AGO 2017 0.3764945 2015 16.902584
iso3year_UHC UHC year_cata cata10
1 AFG 2012 0.3468012 2013 14.631331
2 AFG 2017 0.3948606 2016 4.837534
3 AGO 2012 0.3400455 2011 12.379809
4 AGO 2017 0.3764945 2015 16.902584
# A tibble: 4 x 4
iso3year UHC year_cata cata10
<chr> <dbl> <int> <dbl>
1 AFG 2012 0.347 2013 14.6
2 AFG 2017 0.395 2016 4.84
3 AGO 2012 0.340 2011 12.4
4 AGO 2017 0.376 2015 16.9
#一个tible:4 x 4
ISO3年UHC年第10类
1 AFG 2012 0.347 2013 14.6
2 AFG 2017 0.395 2016 4.84
3年前2012年0.340 2011年12月4日
2017年4月前0.376 2015年16.9
注
行这里有三种方法。第一个是最清晰的,因为它表明问题实际上是一个聚合和过滤的自连接,并直接对此进行建模,并自动处理注释中提到的边缘情况,而无需额外代码。第二种方法使用lappy
循环来获得所需的效果,但它涉及更繁琐的操作,尽管它确实具有零包依赖性的优点。最后一种方法通过执行两次左连接来绕过dplyr缺少复杂的自连接这一事实
1)sqldf使用末尾注释中重复定义的DF
执行自连接,以便年差为-2、-1、1或2,iso3代码相同,匹配实例中cata10不为NA,并且在我们使用的min(…)
查找当年绝对差值最小的行。这使用了这样一个事实:SQLite具有这样一个特性:min(…)
将导致返回满足最小化条件的整行。最后,仅以2012和2017行为例。SQL使用复杂连接直接建模约束的能力允许我们直接将需求建模为代码
library(sqldf)
sqldf("select
a.iso3year iso3year_UHC,
a.UHC,
substr(b.iso3year, 5, 8) year_cata,
b.cata10,
substr(a.iso3year, 5, 8) year,
min(abs(substr(a.iso3year, 5, 8) - substr(b.iso3year, 5, 8))) min_value
from DF a
left join DF b on year - year_cata in (-2, -1, 1, 2) and
substr(a.iso3year, 1, 3) = substr(b.iso3year, 1, 3) and
b.cata10 is not null
group by a.iso3year
having year in ('2012', '2017')")[1:4]
给予:
iso3year_UHC UHC year_cata cata10
1 AFG 2012 0.3468012 2013 14.631331
2 AFG 2017 0.3948606 2016 4.837534
3 AGO 2012 0.3400455 2011 12.379809
4 AGO 2017 0.3764945 2015 16.902584
iso3year_UHC UHC year_cata cata10
1 AFG 2012 0.3468012 2013 14.631331
2 AFG 2017 0.3948606 2016 4.837534
3 AGO 2012 0.3400455 2011 12.379809
4 AGO 2017 0.3764945 2015 16.902584
# A tibble: 4 x 4
iso3year UHC year_cata cata10
<chr> <dbl> <int> <dbl>
1 AFG 2012 0.347 2013 14.6
2 AFG 2017 0.395 2016 4.84
3 AGO 2012 0.340 2011 12.4
4 AGO 2017 0.376 2015 16.9
2)基本R此解决方案仅使用基本R。我们首先通过将iso3year
分为两部分来创建year
和iso
变量ix
是DF
的索引,给出了2012年或2017年为年份的行。对于这些行中的每一行,我们找到具有cata10值的最近年份,并创建一行输出数据帧,lappy
作为行列表返回,L
。最后,我们将这些行绑定在一起。这并不像(1)那样简单,但它的优点是没有包依赖关系
to.year <- function(x) as.numeric(substr(x, 5, 8))
year <- to.year(DF$iso3year)
iso <- substr(DF$iso3year, 1, 3)
ix <- which(year %in% c(2012, 2017))
L <- lapply(ix, function(i) {
DF0 <- na.omit(DF[iso[i] == iso & (year[i] - year) %in% c(-2, -1, 1, 2), ])
if (nrow(DF0)) {
with(DF0[which.min(abs(to.year(DF0$iso3year) - year[i])), c("iso3year", "cata10")],
data.frame(iso3year_UHC = DF$iso3year[i],
UHC = DF$UHC[i],
year_cata = as.numeric(substr(iso3year, 5, 8)),
cata10))
} else {
data.frame(iso3year_UHC = DF$iso3year[i],
UHC = DF$UHC[i],
year_cata = NA,
cata10 = NA)
}
})
do.call("rbind", L)
3)dplyr/tidyr
首先将iso3year
分为iso
和year
列,给出DF2
。然后选择2012年和2017年的行