使用`na.omit()`与`is.na()`移除NA结果为何不一致?
为什么
na.omit()和手动筛选NA的dataframe用identical()检测不一致? 核心原因是na.omit()返回的dataframe带有额外的**na.action属性**,而手动通过is.na()筛选得到的dataframe没有这个属性。identical()函数会严格比较两个对象的所有内容,包括附加属性,因此直接对比会返回FALSE;而用data.frame()包裹na.omit()的结果时,会丢弃这个额外属性,最终两个对象的结构完全一致,identical()就返回TRUE了。
验证属性差异
我们可以通过attributes()函数查看两个对象的完整属性:
# 查看na.omit结果的属性 attributes(data_omit) # 输出示例: # $names # [1] "x1" "x2" "x3" # # $row.names # [1] 1 2 4 5 6 # # $class # [1] "data.frame" # # $na.action # 3 7 # attr(,"class") # [1] "omit" # 查看手动筛选结果的属性 attributes(data_manual) # 输出示例: # $names # [1] "x1" "x2" "x3" # # $row.names # [1] 1 2 4 5 6 # # $class # [1] "data.frame"
很明显,data_omit多了一个记录被移除行位置的na.action属性,这就是identical()认为两者不同的关键。
为什么data.frame()包裹后会一致?
data.frame()函数在构造新的dataframe时,不会保留原对象的额外属性(比如na.action),只会保留dataframe的核心结构(列名、行名、数据、类)。因此data.frame(data_omit)生成的新对象,和手动筛选的data_manual的属性完全一致,identical()自然返回TRUE。
补充:用str()查看更详细结构差异
用str()函数也能直观看到两者的区别:
str(data_omit) # 'data.frame': 5 obs. of 3 variables: # $ x1: num 1 2 5 9 7 # $ x2: num 11 1 1 7 9 # $ x3: num 5 7 2 8 1 # - attr(*, "na.action")= 'omit' int 3 7 str(data_manual) # 'data.frame': 5 obs. of 3 variables: # $ x1: num 1 2 5 9 7 # $ x2: num 11 1 1 7 9 # $ x3: num 5 7 2 8 1
内容的提问来源于stack exchange,提问作者Arthur Thuy
相关产品推荐
相关产品推荐

