【问题标题】:Spline interpolation R with conditions带条件的样条插值 R
【发布时间】:2016-02-22 06:09:45
【问题描述】:

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

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

1) 确定缺少 Yield 的“fips”类别。

2) 如果少于 3 个 Yield 值是每个 fips 的 NA(此处为 1-3),则样条函数应启动并填写 NA。

3) 如果“fips”的 3 个或更多 Yields 不适用,则代码应删除整个“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,要么根本没有结果。

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

【问题讨论】:

  • 在这种情况下,可能还值得看看像 AMELIA 这样的插补包。由于 na.spline 只是在 Yield 变量上进行插值。其他变量(如 Rain、Max)中可能有有用的信息,这些信息与产量相关,可能有助于改进 NA 的估计。 AMELIA 可以使用这些变量间相关性,而 zoo 或 imputeTS 包中的单变量时间序列插补方法则不能。

标签: r conditional-statements spline


【解决方案1】:

Yield 需要从字符转换为数字或NA。然后使用byfinXfips 值划分为单独的数据帧。对于少于 3 个NA'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 集合上的值,其中 NA 少于 3 个,并且所有其他集合上的所有 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))

第一个版本返回

     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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    相关资源
    最近更新 更多