gpt4 book ai didi

r - r 中的简单函数

转载 作者:行者123 更新时间:2023-12-04 11:03:55 26 4
gpt4 key购买 nike

我一直在尝试创建一个非常简单的函数。基本上我想要 t$C 中的每个元素根据我代码中的 if then 语句更改,其他保持不变。所以这是我的代码:

set.seed(20)
x1=rnorm(100)
x2=rnorm(100)
x3=rnorm(100)
t=data.frame(a=x1,b=x1+x2,c=x1+x2+x3)
fun1=function(multi1,multi2)
{
v=t$c
s=c()
for (i in v)
{
if (i<0)
{
s[i]=i*multi1
}
else if(i>0)
{
s[i]=i*multi2
}
}

return(s)
}

fun1(multi1=0.5,multi2=2)

但它只给了我几个数字。我觉得我可能犯了一些愚蠢的错误,但我无法弄清楚。

最佳答案

tl;博士 此操作可以矢量化。您可以使用以下方法,假设您要保留 0 的值。或 NA独自的。

with(t, c * ifelse(c < 0, 0.5, ifelse(c > 0, 2, 1)))

如果您想将它们包含在一侧(例如在积极的一侧),那就更简单了。
with(t, c * ifelse(c < 0, 0.5, 2))

就您的循环而言,您在那里遇到了一些问题。

首先,您正在索引 s十进制值,这可能会导致计算错误。这也是你的结果向量如此短的原因。当您在循环中建立索引时,索引被移动到整数值,并且由于其中一些被重复, s结果很短。

实际的唯一索引长度是这样的 -
length(unique(as.integer(t$c)))
# [1] 9

结果你得到,作为一个简单的例子,
s[c(1, 2, 1, 1)] <- something

由于 1 是重复的,因此仅更改了索引 1 和 2。这就是你的循环中发生的事情。进一步说明为
x <- 1:5
x[1.2]
# [1] 1
x[1.99]
# [1] 1

接下来,注意下面我们已经分配了向量 s .我们可以这样做,因为我们知道结果向量的长度将与 v 相同。 .这是推荐的、更有效的方法,而不是在循环中构建向量。

继续前进,我改变了 for(i in v)for(i in seq_along(v))纠正这一点。现在我们正在使用 i 的序列进行索引。 .然后我们还需要索引 v以相同的方式。最后,我们可以分配 s[i] <- if(...而不是分配给 if() 内的相同索引陈述。

另请注意,您还没有考虑 0或任何其他可能出现在 v 中的值(如 NA )。我添加了最后的 else我们只是不理会这些值(value)观。根据您的需要进行更改。此外,而不是去全局环境获取 t$c ,我们可以将它作为参数传递并使这个函数更通用(归功于@ShawnMehan 的建议)。这是修改后的版本:
fun1 <- function(vec, multi1, multi2) {
s <- vector("numeric", length(vec))
for (i in seq_along(vec)) {
s[i] <- if (vec[i] < 0) {
vec[i] * multi1
} else if(vec[i] > 0) {
vec[i] * multi2
} else {
vec[i]
}
}
return(s)
}

所以现在我们有一个长度为 100 的结果
x <- fun1(t$c, 0.5, 2)
str(x)
# num [1:100] 2.657 -0.949 7.423 -0.749 5.664 ...

我写了这么长的解释,因为我认为你正在学习如何编写一个循环。不过,在 R 中,我们可以将整个操作向量化并将其放入一行代码中。以下行给出与 fun1(t$c, 0.5, 2) 相同的结果.
with(t, c * ifelse(c < 0, 0.5, ifelse(c > 0, 2, 1)))

感谢@Frank 发现我的计算疏忽。

希望这一切都有意义。有时我不擅长解释和技术术语。如果有任何问题,请发表评论。

关于r - r 中的简单函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32620557/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com