r - 在 R 中的“if 语句”中计算空值的问题
问题描述
我将一些数据传递给 R 中的一个简单代码块,该代码块计算空值,然后执行 ARIMA 时间序列插补。我写了一个非常简单的“if”语句,它计算时间序列中的空值,如果它们小于一定数量,则忽略该列并转到下一个(因为 ARIMA 插补需要一定数量的非空数据才能工作,否则返回错误)。计算空值似乎可以正常工作,但是 if 语句的行为非常奇怪并且不起作用。我包含了一个打印语句来计算 if 语句内部和外部的空值,但是当 if 语句未执行时,if 语句将代码传递给循环。这是代码和输出:
stations <- c('BX1', 'BX2', 'BG3') # each station has a different data file
pollutants <- c('nox','no2','pm10','pm25') # each station contains data on a number of pollutants
for (s in stations) {
print(paste('starting imputation for station ', s, sep=" "))
s_result <- read.csv(paste("/path/to/file", s, "_rescaled.csv", sep=""))
for (p in pollutants) {
ts = c()
pcol = paste0(p,"_iqr",sep="") # find the right column
ts = s_result[[pcol]] # get the time series from the column
print(pcol) # check which pollutant we're working on
print(length(ts)) # test the length of the time series
print(sum(is.na(ts))) # test the number of nulls in the time series
if (sum(is.na(ts) != length(ts))) { # if the time series is not completely null
print(sum(is.na(ts))) # check the length of the time series again for testing
usermodel <- arima(ts, order = c(10, 1, 0))$model # calculate the arima
p_result <- na_kalman(ts, model = usermodel, maxgap = 24) # calculate the arima
s_result <- cbind(s_result,p_result) # add the computed column to the dataframe
names(s_result)[names(s_result) == "p_result"] <- paste0(p,"_imputed",sep ="")
} else { # otherwise add a null column
p_result <- c(NA, length=length(ts))
s_result <- cbind(s_result,p_result) # enter a null column
names(s_result)[names(s_result) == "p_result"] <- paste0(p,"_imputed",sep ="")
}
}
filename = paste0("/path/to/file", s, "_imputed_test.csv", sep="")
write.csv(s_result, filename, row.names = TRUE)
print(paste('completed imputation for station ', s, sep=" "))
}
问题是,这个 if 语句无法正常工作,因为它正在将数据传递给 if 语句中的 arima 插补,即使空值的数量等于时间序列的长度也是如此。这是输出:
[1] "starting imputation for station BG1"
[1] "nox_iqr"
[1] 17520
[1] 4660
[1] 4660
[1] "no2_iqr"
[1] 17520
[1] 4664
[1] 4664
[1] "pm10_iqr"
[1] 17520
[1] 17520
[1] 17520
Error in arima(ts, order = c(10, 1, 0)) : 'x' must be numeric
显然有问题,对于 pm10 污染物,有 17520 个空值,与时间序列的长度相同。因此,if 语句不应在 'if' 语句中再次运行计算空值数量的行,因为应该绕过这行代码。IE。对于与列 pm10_iqr 相关的时间序列,空值数为 17520,时间序列的长度为 17520,这将导致 arima 失败 - 因此 if 语句应跳过此行。但它不这样做。
请问我哪里错了?这应该很简单,但没有任何意义!我不写很多 R 代码,通常是 Python。谢谢你的帮助!
解决方案
sum(is.na(ts) != length(ts))
应该是
sum(is.na(ts)) != length(ts))
解释出了什么问题:在 R 中,除 0 以外的任何数字都计算为 TRUE。例如:
if (0) {print("evaluated to TRUE")} else {print("evaluated to FALSE")} and
回报:
[1] "evaluated to FALSE"
和:
if (5) {print("evaluated to TRUE")} else {print("evaluated to FALSE")}
回报:
[1] "evaluated to TRUE"
此外,R 接受布尔值 ( TRUE
, FALSE
) 作为sum
(和其他算术函数)的参数,并在这些情况下将它们视为 1 ( TRUE
) 和 0 ( FALSE
)。
is.na(ts) != length(ts)
评估某个 TRUE 和 FALSE 向量
和
sum(is.na(ts) != length(ts))
愉快地总结它们;)
这就是为什么您的代码没有引发任何错误的原因,因为它可以正常工作,只是没有按照我们的意思行事……这些是我最担心的错误;)
推荐阅读
- c++ - 如何使用 C++ 将 UTF-16 转换为 UTF-8?
- c# - 更改 url 中的查询字符串
- c++ - 如何用变量数组新建一个结构?
- arrays - 在数组中查找最小值/最大值 - 遍历循环
- docker - 使用 Check_MK 监控 Docker
- json - 如何将 json 文件读入地图
- android - 谷歌地图喜欢标记周围有地名的标记
- javascript - 如何使画布的不同部分(矩形)在给定的坐标对中淡出?
- c++ - cmake - 如何可能链接 Boost 的 sub_directory 头文件(例如:/archive/text_oarchive.hpp)?
- java - 修改现有的 JBehave 插件