【问题标题】:Dealing with missing factor levels in R function处理 R 函数中缺失的因子水平
【发布时间】:2020-05-22 11:13:23
【问题描述】:

我正在尝试编写一个简单的函数来调整某些几何形状的暴露表面积,具体取决于它们如何相互连接。它看起来像这样:

funct <- function(A, shape, x) {
radius <- x / 2
A <- dplyr::case_when(
  shape == "sphere" ~ A - (pi * radius^2), 
  shape == "cylinder" ~ A - 2*(pi * radius^2), 
  shape == "ellipsoid" ~ A - (0.2 * A[which(shape == "sphere")] + (2 * pi * radius[which(shape == "cylinder")]))
)
  return(A)
}

这很简单,但在实际数据集中经常缺少因子水平,这意味着简单的调整不起作用:

testdata <- 
  data.frame(ind = paste(letters[1:10]), A = rnorm(10), shape = rep(c("sphere", "ellipsoid"), each = 5), x = rnorm(10))

testdata$Aadj <- funct(A = testdata$A, shape = testdata$shape, x = testdata$x)
#Error: `shape == "ellipsoid"... must be length 10 or one, not 0 

我可以通过完成数据集手动解决这个问题:

shapes <- as.vector(c("sphere", "cylinder", "ellipsoid"))
testdata <- tidyr::complete(testdata, ind, shape = shapes, fill=list(A = 0))
testdata$Aadj <- funct(A = testdata$A, shape = testdata$shape, x = testdata$x)

为了使这更简洁,我会对如何处理实际函数中缺失的因子水平的一些输入感兴趣。我认为这可以通过首先将它们添加到数据中来解决(将“A”设置为 0 以允许计算),然后在返回数据之前再次删除它们?

我还对如何在函数中跨主题(testdata df 中的“ind”)循环的建议感兴趣(而不是例如在应用函数时在 dplyr 管道中设置它)。

非常感谢。

【问题讨论】:

  • 尝试使用shape %in% "ellipsoid" 而不是==。不确定这是否能解决您的问题,但我发现%in% 是一个更合作的运营商。
  • 你的预期输出是什么?

标签: r loops


【解决方案1】:

使用纯 R 似乎运行没有错误:

funct <- function(A, shape, x) {
  radius <- x / 2
  sph <- which(shape == "sphere")
  cyl <- which(shape == "cylinder")

  A_new <- ifelse(shape == "sphere", A - (pi * radius^2), 
                  ifelse(shape == "cylinder", A - 2*(pi * radius^2), 
                         A - (0.2 * A[sph] + (2 * pi * radius[cyl]))))
  A_new
}

testdata$Aadj <- funct(A = testdata$A, shape = testdata$shape, x = testdata$x)
testdata

#   ind           A     shape           x       Aadj
#1    a  0.92219266    sphere  1.49043259 -0.8224824
#2    b -0.43705855    sphere  0.21633097 -0.4738145
#3    c  0.66549715    sphere  1.63981414 -1.4464310
#4    d -1.56945688    sphere -1.51169390 -3.3642633
#5    e  0.06975590    sphere -1.68775240 -2.1674572
#6    f  0.02811881 ellipsoid -1.04717409         NA
#7    g  0.95586893 ellipsoid -0.24831690         NA
#8    h  0.79428218 ellipsoid  0.03230311         NA
#9    i  1.86062696 ellipsoid -0.66786452         NA
#10   j  0.53938164 ellipsoid -1.26945744         NA

【讨论】:

    【解决方案2】:

    谢谢大家,这很有帮助。我自己考虑了一些,并意识到添加一个非常简单的 NA 感知函数可以在保留其余语法的情况下完成这个技巧。这效果更好,因为即使缺少因子水平,我仍然想继续计算。因此:

    sum_ <- function(...) sum(..., na.rm=T) 
    funct <- function(A, shape, x) {
      radius <- x / 2
      A <- dplyr::case_when(
        shape == "sphere" ~ A - sum_((pi * radius[which(shape == 'cylinder')]^2)), 
        shape == "cylinder" ~ A -  sum_(2*(pi * radius^2)), 
        shape == "ellipsoid" ~ A -  sum_((0.2 * A[which(shape == "sphere")]), (2 * pi * radius[which(shape == "cylinder")]))
      )
      return(A)
    }
    

    【讨论】:

      猜你喜欢
      • 2022-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多