Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在R中找到某一年的最接近值_R_Dplyr_Na - Fatal编程技术网

在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年的行