NULL действительно означает «ничего», а не «отсутствует», поэтому оно не может заменить фактическое значение - для отсутствующего R используется NA.
Вы можете использовать метод замены is.na для непосредственного обновления выбранных элементов, это будет работать с логическим результатом. (Использование которого для индексов будет работать только с is.na, прямое использование [вызывает доступ к списку, который является причиной вашей ошибки).
foo <- data.frame("day"= c(1, 3, 5, 7), "od" = c(0.1, "#N/A", 0.4, 0.8))
NAs <- foo == "#N/A"
## by replace method
is.na(foo)[NAs] <- TRUE
## or directly
foo[NAs] <- NA
Но вы уже имеете дело со строками (на самом деле это фактор по умолчанию) в вашем столбце od путем принудительного принуждения при его создании с помощью c (), и вам, возможно, придется обрабатывать столбцы по отдельности. Любой числовой столбец никогда не будет совпадать со строкой "# N / A", например.