Как пропустить итерацию в цикле for, если условие выполнено

У меня есть код для превращения верхнего треугольника матрицы в вектор и сохранения значений из этого вектора вместе с их исходными координатами из матрицы во фрейм данных. Как пропустить цикл for, если элемент в векторе равен нулю?

Я пробовал else заявления и другие попытки.

v <- matrix(sample(0:1, 10, replace = TRUE),9,9)
t <- v[upper.tri(v,diag=T)]
tful <- t[t!=0]
df <- data.frame(FP1=rep(0,length(t)),FP2=rep(0,length(t)),tanimoto=rep(0,length(t)))
for (i in 1:length(t)){
  if (t[i]==0) next
  else {
      col_num <- floor(sqrt(2*i-7/4)+.5)
      row_num <- i-(.5*col_num^2-.5*col_num+1)+1
      df$FP1[i] <- row_num
      df$FP2[i] <- col_num
      df$tanimoto[i] <- v[row_num,col_num]
    }
}

Я не хочу, чтобы в моем фрейме данных были нули, и цикл пропускал эти значения. Я понимаю, что фрейм данных должен быть меньше в строках, но я использую это в качестве примера.


person Expectation mean first moment    schedule 25.09.2019    source источник


Ответы (1)


Ваш next работает нормально, чтобы пропустить текущую итерацию цикла.

Вы по-прежнему получаете 0 в конечном результате, потому что все значения df были инициализированы df равными 0. Когда вы пропускаете итерацию, они не изменяются, поэтому они остаются равными 0. Если вы измените инициализацию на значения NA, вы увидите, что 0 не добавляются.

df <- data.frame(FP1=rep(NA,length(t)),FP2=rep(NA,length(t)),tanimoto=rep(NA,length(t)))
for (i in 1:length(t)){
  if (t[i]==0) next
  else {
      col_num <- floor(sqrt(2*i-7/4)+.5)
      row_num <- i-(.5*col_num^2-.5*col_num+1)+1
      df$FP1[i] <- row_num
      df$FP2[i] <- col_num
      df$tanimoto[i] <- v[row_num,col_num]
    }
}
df
#    FP1 FP2 tanimoto
# 1    1   1        1
# 2    1   2        1
# 3    2   2        1
# 4    1   3        1
# 5    2   3        1
# 6    3   3        1
# 7   NA  NA       NA
# 8    2   4        1
# 9    3   4        1
# 10   4   4        1
# 11  NA  NA       NA
# ...

Простой модификацией будет фильтрация фрейма данных в качестве последнего шага: df = df[df$tanimoto != 0, ], или, если вы переключитесь на NA, df = na.omit(df).

Мы также могли бы создать решение без цикла:

v1 = v != 0 
df2 = data.frame(FP1 = row(v)[v1], FP2 = col(v)[v1], tanimoto = v[v1])
df2 = subset(df2, FP1 <= FP2)
df2
#    FP1 FP2 tanimoto
# 1    1   1        1
# 7    1   2        1
# 8    2   2        1
# 13   1   3        1
# 14   2   3        1
# 15   3   3        1
# 20   2   4        1
# 21   3   4        1
# 22   4   4        1
# 27   3   5        1
# 28   4   5        1
# 29   5   5        1
# 33   1   6        1
# 34   4   6        1
# 35   5   6        1
# ...
person Gregor Thomas    schedule 25.09.2019
comment
при преобразовании диагонали матрицы в вектор row_num и col_num дают координаты элемента вектора, которые были бы в исходной матрице. - person Expectation mean first moment; 25.09.2019
comment
Это просто кажется очень сложной формулой для чего-то простого - я бы опасался ошибок или крайних случаев. Подход без циклов мне более понятен и поэтому кажется более безопасным. (Возможно, и более эффективно.) - person Gregor Thomas; 25.09.2019
comment
Я согласен. У меня есть большая матрица, и ваш код мгновенно сделал то, что я хотел. Моя петля длилась вечность. Спасибо еще раз. - person Expectation mean first moment; 26.09.2019