带条件的样条插值 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
。然后用by
将finX
按fips
值分成单独的数据帧。对于每个小于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
我有一个非常大的数据集,其结构如下例所示。
我一直在尝试使用 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
。然后用by
将finX
按fips
值分成单独的数据帧。对于每个小于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