Neste tuturial iremos mostrar como o comportamento de NAs no R é consistente com o de NULL no PostgreSQL.
Quando você envia um dataframe do R para PostgreSQL, NAs, ou seja, valores faltantes, são convertidos para NULL. Acontece que o R diferencia NA de NULL. No R NULL é tipo de objeto e é por isso que você não consegue incluí-lo num vetor ou numa matriz, mas consegue adicioná-lo como elemento numa lista, inclusive em dataframes, já que estas também são listas. Porém, somente quando todas as colunas são NULL. NULL no R é um tanto ambíguo, pois ora se comporta como vazio, ora como elemento indefinido.
Por sua vez, NA no R é um elemento lógico para indicar dado desconhecido. Isso é concebido dentro da lógica ternária, que admite três valores: VERDADEIRO, FALSO e DESCONHECIDO. O mesmo acontece com SQL para NULL.
Neste tuturial iremos mostrar como o comportamento de NAs no R é consistente com o de NULL no PostgreSQL.
Para criar objetos com valores desconhecidos no R, você simplesmente coloca NA no vetor ou na coluna:
a <- c(1,2,3,NA)
a
[1]  1  2  3 NA
df <- data.frame(a = a)
df
   a
1  1
2  2
3  3
4 NA
No PostgreSQL, você pode fazer o mesmo, mas com NULL
a
1
2
3
(4 rows)
a
1
2
3
(4 rows)
Como ambos são valores desconhecidos, espera-se que o comportamento seja similar num e noutro, e de fato é, em muitas situações.
2 == NA
[1] NA
NA == NA
[1] NA
2 < NA
[1] NA
2 + NA
[1] NA
Em todas essas situações, o R retorna o elemento lógico NA, ou seja, desconhecido, porque o resultado da comparação é de fato desconhecido, já que NA pode equivaler a uma infinidade de valores, inclusive o valor comparado a NA.
Como NULL possui a mesma natureza, as respostas são consistentes:
?column?
(1 row)
?column?
(1 row)
?column?
(1 row)
?column?
(1 row)
Igualmente, algo que surpreende no R é o filtro negativo em colunas que contêm NAs:
subset(df,a !=2)
  a
1 1
3 3
Com dplyr ocorre o mesmo:
dplyr::filter(df,a != 2)
  a
1 1
2 3
Em ambos os casos, linhas com NAs também foram excluídas. Isso porque NA pode conter o 2 (Confesso que esse comportamento não me convence inteiramente).
Vejamos em SQL
a
1
3
(2 rows)
Para evitar surpresas, não se esqueça de explicitamente filtrar para NAs no R e para NULLs no PostgreSQL.
a
1
3
(3 rows)
Não estou absolutamente seguro de que os comportamentos de NA no R e NULL em SQL são sempre os mesmos, mas para as operações mais comuns, você pode ficar tranquila que são.