如何将Inf插入列表而不将其强制转换为字符

时间:2015-12-21 18:40:14

标签: r

我有一个列表,我想用R数值'Infinity'替换字符串Inf。我尝试了各种方法,但R不断将值Inf强制转换为字符串'Inf'。以下是我尝试过的方法:

# Doesn't work
l1 <- list('Infinity')
l1[[1]][l1[[1]] == 'Infinity'] <- Inf
l1
class(l1[[1]])

# Doesn't work
l2 <- list('Infinity')
special.values <- match(l2[[1]], c("Infinity", "-Infinity", "NaN"))
indices <- which(!is.na(special.values))
l2[[1]][indices] <- c(Inf, -Inf, NaN)[na.omit(special.values)]
l2
class(l2[[1]])

不幸的是,我有额外的限制,我不能在整个列表上进行替换,因为列表中的某些元素可能包含'Infinity'的合法字符串

# This works, but would incorrectly replace data in my use case
l3 <- list('Infinity')
l3 <- replace(l3, l3 == 'Infinity', Inf)
l3
class(l3[[1]])

关于如何使这项工作的任何想法。这是一个更完整的例子,说明我实际编写的代码是什么样的。

l4 <- list(1.0, 'Infinity', 'Infinity')
l4.types <- c('numeric', 'numeric', 'character')
for (i in which(l4.types %in% 'numeric')) {
  # insert code here
}
all.equal(l4, list(1.0, Inf, 'Infinity')) # TRUE

1 个答案:

答案 0 :(得分:0)

我相信您的代码不起作用,因为当您替换字符向量的元素时,替换将被强制转换为字符。

这在一般情况下是有道理的:

x = c("a", "b", "c")
x[2] = 1
x
# [1] "a" "1" "c"

矢量必须是一种类型,所以上面是唯一的方法。 没有意义进行特殊处理以检查向量是否长度为1,因此我们希望它以完全相同的方式工作,它确实

# this is consistent:
y1 = "infinity"
y1[1] = Inf
y1
# [1] "Inf"

如果要更改向量的类,则必须替换整个向量或明确强制它:

## replace whole vector (not just an element)
y2 = "infinity"
y2 = Inf
y2
# [1] Inf

## coerce
y3 = "infinity"
y3[1] = Inf
y3 = as.numeric(y3)
y3
# [1] Inf

由于上述两种方法都可以与较长的矢量一致地工作。

由于此处突出显示的代码中的单个括号替换为l1[[1]] [ l1[[1]] == 'Infinity' ] <- Inf,因此它属于上面的xy1示例。解决方案是相同的,要么替换整个向量,要么明确强制转换为数字。下面我采取“替换整个矢量”的方法。

l4 <- list(1.0, 'Infinity', 'Infinity')
l4.types <- c('numeric', 'numeric', 'character')
for (i in which(l4.types %in% 'numeric')) {
  if(l4[[i]] == 'Infinity') l4[[i]] = Inf
}
all.equal(l4, list(1.0, Inf, 'Infinity'))
# [1] TRUE