Comportamento de <- NULL em listas versus data.frames para remover dados
Muitos usuários de R eventualmente descobrem muitas maneiras de remover elementos de seus dados. Uma maneira é usarNULL
, particularmente quando você quer fazer algo como soltar uma coluna de umdata.frame
ou soltar um elemento de umlist
.
Eventualmente, um usuário se depara com uma situação em que deseja descartar várias colunas de umdata.frame
imediatamente, e eles bateram em cima<- list(NULL)
como a solução (desde o uso<- NULL
resultará em um erro).
A data.frame
é um tipo especial delist
, então não seria tão difícil imaginar que as abordagens para remover itens de umlist
deve ser o mesmo que remover colunas de umdata.frame
. No entanto, eles produzem resultados diferentes, como pode ser visto no exemplo abaixo.
## Make some small data--two data.frames and two lists
cars1 <- cars2 <- head(mtcars)[1:4]
cars3 <- cars4 <- as.list(cars2)
## Demonstration that the `list(NULL)` approach works
cars1[c("mpg", "cyl")] <- list(NULL)
cars1
# disp hp
# Mazda RX4 160 110
# Mazda RX4 Wag 160 110
# Datsun 710 108 93
# Hornet 4 Drive 258 110
# Hornet Sportabout 360 175
# Valiant 225 105
## Demonstration that simply using `NULL` does not work
cars2[c("mpg", "cyl")] <- NULL
# Error in `[<-.data.frame`(`*tmp*`, c("mpg", "cyl"), value = NULL) :
# replacement has 0 items, need 12
Mude para aplicar o mesmo conceito a umlist
e compare a diferença de comportamento.
## Does not fully drop the items, but sets them to `NULL`
cars3[c("mpg", "cyl")] <- list(NULL)
# $mpg
# NULL
#
# $cyl
# NULL
#
# $disp
# [1] 160 160 108 258 360 225
#
# $hp
# [1] 110 110 93 110 175 105
## *Does* drop the `list` items while this would
## have produced an error with a `data.frame`
cars4[c("mpg", "cyl")] <- NULL
# $disp
# [1] 160 160 108 258 360 225
#
# $hp
# [1] 110 110 93 110 175 105
As principais questões que tenho são, se umdata.frame
é umlist
, por que se comporta de maneira tão diferente nesse cenário? Existe uma maneira infalível de saber quando um elemento será descartado, quando ele produzirá um erro, e quando ele simplesmente receberá um erro?NULL
valor? Ou dependemos de tentativa e erro para isso?