【问题标题】:How to avoid NA columns in dcast() output?如何避免 dcast() 输出中的 NA 列?
【发布时间】:2015-10-04 08:21:46
【问题描述】:

如何避免 dcast() 输出中的NAreshape2 包?

在这个虚拟示例中,dcast() 输出将包含一个 NA 列:

require(reshape2)
data(iris)
iris[ , "Species2"] <- iris[ , "Species"]
iris[ 2:7, "Species2"] <- NA
(x <- dcast(iris, Species ~ Species2, value.var = "Sepal.Width", 
            fun.aggregate = length))
##     Species setosa versicolor virginica NA
##1     setosa     44          0         0  6
##2 versicolor      0         50         0  0
##3  virginica      0          0        50  0

对于一个有点相似的用例,table() 确实有一个选项可以避免这种情况:

table(iris[ , c(5,6)], useNA = "ifany")  ##same output as from dcast()
##            Species2
##Species      setosa versicolor virginica <NA>
##  setosa         44          0         0    6
##  versicolor      0         50         0    0
##  virginica       0          0        50    0
table(iris[ , c(5,6)], useNA = "no")  ##avoid NA columns
##            Species2
##Species      setosa versicolor virginica
##  setosa         44          0         0
##  versicolor      0         50         0
##  virginica       0          0        50

dcast() 是否有类似的选项可以删除输出中的 NA 列?如何避免获得NA 列? (这个函数有许多相当神秘的选项,这些选项被严格记录下来,我无法完全掌握......)

【问题讨论】:

  • 您可以使用dcast(na.omit(iris), Species ~ Species2, value.var = "Sepal.Width"),但如果您也对其他一些专栏感兴趣,这不是非常通用的解决方案。
  • @DavidArenburg 确实如此。我知道na.omit(iris)-like 解决方案,但我正在寻找一种不同的方法。我没有在问题中包含此要求,以避免使其过于混乱......
  • 如果我不得不猜测,我会说这是预期的行为,因此您需要有意识地删除丢失的数据(而不是意外地这样做)。我会先选择数据来解决它,所以iris[!is.na(iris$Species2),].
  • @Heroka 怎么会比na.omit更好?
  • @David 如果在某个列中只有 NA 需要删除。

标签: r na reshape2


【解决方案1】:

以下是我能够绕过它的方法:

iris[is.na(iris)] <- 'None'

x <- dcast(iris, Species ~ Species2, value.var="Sepal.Width", fun.aggregate = length)

x$None <- NULL

想法是将所有 NA 替换为“None”,以便 dcast 创建一个名为“None”而不是“NA”的列。然后,如果不需要,您可以在下一步中删除该列。

【讨论】:

  • 您能否将您的代码格式化为代码,使其更易于阅读? (缩进4个空格,或使用{}按钮。)另外,请添加说明,以便其他人更好地理解您的解决方案。
【解决方案2】:

我发现的一个解决方案是基于 cmets 中建议的降低 NA 值方法,我对此并不十分不满。它利用dcast() 中的subset 参数以及来自plyr.()

require(plyr)
(x <- dcast(iris, Species ~ Species2, value.var = "Sepal.Width",
            fun.aggregate = length, subset = .(!is.na(Species2))))
##     Species setosa versicolor virginica
##1     setosa     44          0         0
##2 versicolor      0         50         0
##3  virginica      0          0        50

对于我的特定目的(在自定义函数中),以下效果更好:

(x <- dcast(iris, Species ~ Species2, value.var = "Sepal.Width", 
            fun.aggregate = length, subset = .(!is.na(get("Species2")))))
##     Species setosa versicolor virginica
##1     setosa     44          0         0
##2 versicolor      0         50         0
##3  virginica      0          0        50

【讨论】:

    【解决方案3】:

    您可以重命名输出的 NA 列,然后将其设为 NULL。 (这对我有用)。

    require(reshape2)
    data(iris)
    iris[ , "Species2"] <- iris[ , "Species"]
    iris[ 2:7, "Species2"] <- NA
    
    (x <- dcast(iris, Species ~ Species2, value.var = "Sepal.Width", 
                fun.aggregate = length)) 
    
    setnames(x , c("setosa", "versicolor", "virginica", "newname"))
    
    x$newname <- NULL
    

    【讨论】:

      【解决方案4】:
      library(dplyr)
      library(tidyr)
      iris %>%
        filter(!is.na(Species2)) %>%
        group_by(Species, Species2) %>%
        summarize(freq = n()) %>%
        spread(Species2, freq)
      

      【讨论】:

      • 总而言之,如果可能的话,我宁愿使用基于 dcast() 的解决方案。
      • 为什么人们不赞成这个答案?
      • @MikeWise 我不知道,但我怀疑是因为它提出了一种替代方案,而不是试图在问题的限制范围内解决问题(即dcast() 函数)。我确实同意,尽管没有任何解释的否决票是 SE 周围最消极和适得其反的社区行为之一......
      • 这对我来说似乎是一个很有价值的答案,尽管如果他添加一两句话来解释它会很好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-24
      • 2021-06-23
      • 1970-01-01
      • 1970-01-01
      • 2013-12-20
      • 1970-01-01
      相关资源
      最近更新 更多