У меня проблемы с запуском оператора tryCatch в цикле for. Я хочу просмотреть каждую строку в моем фрейме данных (x), и если есть ошибка при взятии sqrt данной строки в столбце k1, я хочу, чтобы sqrtd равнялось "NULL", а если нет, то это значение sqrt.
Ниже приведен код, который я пробовал, однако новый столбец sqr для каждой строки имеет "NULL", но только вторая строка должна быть "NULL", поскольку нельзя взять sqrt("a").
library(Jmisc)
library(dplyr)
x <- data.frame(k1 = c(3,"a",3,4,5), k2 = c(1,NA,NA,4,5), data1 = 1:5)
p <- data.frame(NULL)
for (row in 1:nrow(x)){
sqrtd <- tryCatch(sqrt(x$k1[row]),error=function(e) sqrtd = "NULL")
x <- addCol(x,value=c(sqr=sqrtd))
p <- rbind(p,x)
}
print(p)





addCol от JMisc, похоже, добавляет одно значение (в документации оно ошибочно называется «константой») в data.frame для всего столбца. В вашем коде вы заменяете существующий столбец после первой итерации новым значением.
Решение в вашем случае состоит в том, чтобы избежать цикла for — на самом деле data.frames практически никогда не должны создаваться внутри цикла. Вместо этого используйте векторизованные операции R. Такие как:
sqrt_or_null = function (x) {
tryCatch(sqrt(x), error = function (e) "NULL")
}
p = mutate(x, sqr = lapply(k1, sqrt_or_null))
Однако это оставит вас со столбцом списка, который является громоздким типом данных в data.frame. Причина в том, что данный столбец, не являющийся списком, может содержать значения только одного типа, но ваша функция возвращает типы разные в зависимости от того, успешна операция или нет: либо numeric, либо character.
Вы можете привести результаты:
p = mutate(x, sqr = as.character(lapply(k1, sqrt_or_null)))
… но я предлагаю подумать о лучшем представлении ошибочных значений (например, NA) или о том, чтобы избежать ошибок перед выполнением этой операции (например, путем filterобработки недопустимых строк).
В вашем коде есть дополнительная проблема: тип k1 — factor, а не numeric. Таким образом, это не удастся для значения каждый. Сначала вам нужно будет преобразовать значения факторов в числовые значения, что требует двух шагов: преобразование в строки символов, а затем в числовые значения:
p = x %>%
mutate(k1num = as.numeric(as.character(k1))) %>%
mutate(sqr = ifelse(is.na(k1num), "NULL", sqrt(k1num)))
@MLS Да, но причина в том, что ваш столбец на самом деле является столбцом строки символов (точнее, коэффициентов), а не чисел. (См. отредактированный ответ)
Хорошо, спасибо, это имеет смысл. Я просто пытаюсь лучше понять tryCatch, потому что это всего лишь пример, однако в моем окончательном коде я не использую sqrt, я использую функцию из пакета.
Каждый вектор может быть только одного типа (например, числовой, логический, символьный). Если вы попытаетесь включить более одного типа в назначение вектора, вектор будет приведен к самому широкому типу, который может обрабатывать входные данные. Если вы запустите x$k1, вы должны заметить, что результирующий вектор представляет собой вектор символов строк (т. Е. "3" "a" "3" "4" "5"). Это потому, что "a" — это строка, поэтому весь вектор x$k1 приводится к символу. Извлечение квадратного корня из любого элемента этого вектора приведет к ошибке, поэтому sqrtd всегда присваивается "NULL".
Итак, гипотетически, если x $ k1 имеет тот же тип и во второй строке возникает ошибка, сработает ли ответ Конрада?