有什么办法可以不循环

时间:2018-09-26 20:13:42

标签: r for-loop dplyr

我有以下使用每月数据的代码:

set.seed(2)
vector <- as.data.frame(runif(120)+0.5)
b <- data.frame()

    for (j in 1:I(nrow(vector))) {
        if (is.na(vector[j, i]) || is.na(vector[j + 12, i]) || 
            is.na(vector[j + 24, i]) || is.na(vector[j + 36, i]) ||
            is.na(vector[j + 48, i]) || is.na(vector[j + 60, i])) {
            b[j, i] <- NA
        } else if (vector[j, i] < 1 && vector[j + 12, i] < 1 && 
            vector[j + 24, i] < 1 && vector[j + 36, i] < 1 && 
            vector[j + 48, i] < 1) {
            b[j, i] <- vector[j + 60, i]
        } else {
            b[j, i] <- NA
        }
    }

它首先检查是否有任何值是NA(在此示例中将不存在),然后检查一年后的值是否大于1。有没有办法例如使用dplyr获得相同的结果?问题在于这些值彼此相距十二个月,但是每个月都需要检查一次。

2 个答案:

答案 0 :(得分:2)

(对我来说)不太清楚您要在这里输出什么,但是dplyr的“ lead”功能应该可以做到这一点,并且还可以节省大量NA检查。

如果您只想获取年度价值,而没有年度价值则使用NA,则应该这样做:

vector <- data.frame(obs = runif(120)+0.5) # giving this variable a name for 
convenience
vector %>% 
  mutate(year_later = lead(obs, 12),
         two_years_later = lead(obs, 24)) # etc

我将所有内容都放在一个数据帧中,但是如果愿意,您当然可以保留b <- data.frame()

这应该复制您的原始for循环,尽管我没有得到任何符合您条件的观察结果:

vector %>% 
  mutate(final_answer = 
           ifelse(obs < 1 && lead(obs, 12) < 1 && lead(obs, 24) < 1 && lead(obs, 36) < 1 && lead(obs, 48) < 1, 
                  lead(obs, 60), NA))

答案 1 :(得分:1)

我将用一个简单的向量而不是data.frame来解决您的问题。这样比较容易推断,并且很容易适应data.frame列上的循环。

set.seed(2)
v <- runif(120) + 0.5

可以通过将向量更改为数组来表示向量的“月度”。

w <- matrix(v, nrow = 12)
w[, 1:3]
#            [,1]      [,2]      [,3]
#  [1,] 0.6848823 1.2605133 0.8472722
#  [2,] 1.2023740 0.6808201 0.9887732
#  [3,] 1.0733263 0.9052822 0.6492469
#  [4,] 0.6680519 1.3535485 0.8570626
#  [5,] 1.4438393 1.4763985 1.4626440
#  [6,] 1.4434750 0.7258255 0.6323720
#  [7,] 0.6291590 0.9448092 0.5104145
#  [8,] 1.3334488 0.5749794 0.6646422
#  [9,] 0.9680185 1.1618988 1.3101921
# [10,] 1.0499837 0.8875495 1.3688610
# [11,] 1.0526741 1.3368892 1.0142818
# [12,] 0.7388948 0.6505014 1.1271963

您需要从代码中确保5年内该月的所有值(包括原始值)都小于1。因此,我们可以比较矩阵的6个块并将结果组合起来。

total_cols <- ncol(w)
comparison <- {
  w[, 1:(total_cols - 5)] < 1 &
    w[, 2:(total_cols - 4)] < 1 &
    w[, 3:(total_cols - 3)] < 1 &
    w[, 4:(total_cols - 2)] < 1 &
    w[, 5:(total_cols - 1)] < 1 &
    w[, 6:(total_cols - 0)] < 1
}
comparison
#  [,1]  [,2]  [,3]  [,4]  [,5]
#  [1,] FALSE FALSE FALSE FALSE FALSE
#  [2,] FALSE FALSE FALSE FALSE FALSE
#  [3,] FALSE FALSE FALSE FALSE FALSE
#  [4,] FALSE FALSE FALSE FALSE FALSE
#  [5,] FALSE FALSE FALSE FALSE FALSE
#  [6,] FALSE FALSE FALSE FALSE FALSE
#  [7,]  TRUE  TRUE FALSE FALSE FALSE
#  [8,] FALSE FALSE FALSE FALSE FALSE
#  [9,] FALSE FALSE FALSE FALSE FALSE
# [10,] FALSE FALSE FALSE FALSE FALSE
# [11,] FALSE FALSE FALSE FALSE FALSE
# [12,] FALSE FALSE FALSE FALSE FALSE

然后,我们可以使用五年的提前值来创建新的向量,基于comparison的值为TRUE

new_v <- rep(NA, length(v))
new_v[which(comparison)] <- w[, -(1:5)][which(comparison)]
new_v
#   [1]        NA        NA        NA        NA        NA        NA 0.8881448
#   [8]        NA        NA        NA        NA        NA        NA        NA
#  [15]        NA        NA        NA        NA 0.9026427        NA        NA
#  [22]        NA        NA        NA        NA        NA        NA        NA
#  [29]        NA        NA        NA        NA        NA        NA        NA
#  [36]        NA        NA        NA        NA        NA        NA        NA
#  [43]        NA        NA        NA        NA        NA        NA        NA
#  [50]        NA        NA        NA        NA        NA        NA        NA
#  [57]        NA        NA        NA        NA        NA        NA        NA
#  [64]        NA        NA        NA        NA        NA        NA        NA
#  [71]        NA        NA        NA        NA        NA        NA        NA
#  [78]        NA        NA        NA        NA        NA        NA        NA
#  [85]        NA        NA        NA        NA        NA        NA        NA
#  [92]        NA        NA        NA        NA        NA        NA        NA
#  [99]        NA        NA        NA        NA        NA        NA        NA
# [106]        NA        NA        NA        NA        NA        NA        NA
# [113]        NA        NA        NA        NA        NA        NA        NA