带条件的样条插值 R

Spline interpolation R with conditions

我有一个非常大的数据集,其结构如下例所示。

我一直在尝试使用 na.spline 函数来

1) 确定缺少产量的 "fips" 类别。

2) 如果每 fips 少于 3 个屈服值是 NA(这里是 1-3),样条函数应该启动并填充 NA。

3) 如果 "fips" 的 3 个或更多收益率不适用,则代码应删除整个 "fips" 子集,在这种情况下,应删除 fips 2。

到目前为止我的代码:

 finX <- dataset

 finxx <- transform(subset(finX, ave(na.spline(finX$Yield), fips, FUN=sum)<2))

 #or

 finxx <- transform(subset(finX, ave(is.na(finX$Yield), fips, FUN=sum)<2))

Year   fips   Max     Min   Rain  Yield
1980   1      24.7    0.0   71    37
1981   1      22.8    0.0   62    40
1982   1      22.6    0.0   47    37
1983   1      24.2    0.0   51    39
1984   1      23.8    0.0   61    47
1985   1      25.1    0.0   67    43
1980   2      24.8    0.0   72    34
1981   2      23.2    0.4   54    **NA**
1982   2      25.3    0.1   83    55
1983   2      23.0    0.0   68    **NA**
1984   2      22.4    0.7   70    **NA**
1985   2      24.6    0.0   47    31
1980   3      25.5    0.0   51    31
1981   3      25.5    0.0   51    31
1982   3      25.5    0.0   51    31
1983   3      25.5    0.0   51    **NA**
1984   3      25.5    0.0   51    31
...

目前上面的代码要么没有填写最终产品中的所有 NA,要么根本没有结果。

任何指导都会非常有用,谢谢。

Yield 需要从字符转换为数字或 NA。然后用byfinXfips值分成单独的数据帧。对于每个小于3NA's的数据框,做样条插值。大于或等于 3 的返回为 NULL。将返回的数据帧 list 合并为单个数据帧。代码看起来像:

  library(zoo)
# convert finX$Yield values from character to either numeric or NA
  finX$Yield <- sapply(finX$Yield, function(x) if(x =="**NA**") NA_real_ else as.numeric(x))

# use spline interpolation on fips sets with less than 3 NA's
   finxx <- by(finX, finX$fips, function(x) if(sum(is.na(x$Yield)) < 3) transform(x, Yield=na.spline(object=Yield, x=Year)) )    
#  combine results into a single data frame
  finxx <- do.call(rbind, finxx)

或者在转换为数值后,您可以在 Yield 列上使用 ave,其中 fips 集上的样条插值 returns 值少于 3 个 NA以及任何其他集合上的所有 NA。然后将删除最终结果中包含任何 NA 的所有行。代码如下:

finxx2 <- transform(finX, Yield=ave(Yield, fips, FUN=function(x) if(sum(is.na(x)) < 3) na.spline(object=x) else NA))
finxx2 <- na.omit(finxx2)

两个版本都给出了相同的样本数据结果,但第一个版本使用 by 允许您为每个 fips 集使用完整的数据框,而不仅仅是 Yield.在这种情况下,这允许在样条插值中为 x 值指定 Year,因此任何缺少 Year 的数据集仍会给出正确的插值。 ave 版本会得到不正确的答案。所以 by 版本似乎更健壮。

还有 dplyr 版本,它与上面的 by 版本非常相似,并且给出与基本 R 版本相同的答案。如果您愿意使用 dplyr,这可能是最直接、最可靠的方法。

library(dplyr)
finxx3 <- finX %>% group_by(fips) %>%
      filter(sum(is.na(Yield)) < 3) %>%
      mutate(Yield=na.spline(object=Yield, x=Year))

第一个版本returns

     Year fips  Max Min Rain Yield
1.1  1980    1 24.7   0   71    37
1.2  1981    1 22.8   0   62    40
1.3  1982    1 22.6   0   47    37
1.4  1983    1 24.2   0   51    39
1.5  1984    1 23.8   0   61    47
1.6  1985    1 25.1   0   67    43
3.13 1980    3 25.5   0   51    31
3.14 1981    3 25.5   0   51    31
3.15 1982    3 25.5   0   51    31
3.16 1983    3 25.5   0   51    31
3.17 1984    3 25.5   0   51    31