gpt4 book ai didi

r - 如何在 r 中编写函数来对记录进行计算?

转载 作者:行者123 更新时间:2023-12-02 02:33:12 24 4
gpt4 key购买 nike

在 C# 中,我习惯了数据集和当前记录的概念。对我来说,根据当前记录的条件编写复杂的计算价格函数会很容易。

我无法理解如何在 r 中执行此操作。

我尝试了以下方法

   train <- read.csv("Train.csv" )
df <- as.data.frame.matrix(train)
v = c( df$Fuel.Type ,df$No.Gears)
names(v ) <- c( "FuelType" ,"NoGears")
df$FEType = FEType( v)

我的函数定义为

FEType <- function(v    ){
ret="Low"
if (v["FuelType"]=='G') {
ret ="High"
}
return(ret)
}

这没有按我的预期工作当我检查 v 时,我发现它包含总计而不是我预期的当前行。

我哪里出错了?

在问题here中我在最后一段中看到了一些提示。

为了重现问题,表明我想要做什么,我已经

IsPretty <-function(PetalWidth){
if (PetalWidth >0.3) return("Y")
return("N")
}

df <- iris
df$Pretty = IsPretty(df$Petal.Width)

这给出了错误

the condition has length > 1 and only the first element will be used

这让我开始研究向量。但我不相信这是正确的方向。

[更新]

我习惯于思考表格和当前记录。因此我认为

df$Pretty = IsPretty(df$Petal.Width)

将具有使用计算出的 isPretty 属性向我的数据框添加一列的效果

为什么我的计算中不能包含 if 条件?

最佳答案

矢量化是您在 R 中需要习惯的最基本(也是不寻常)的事情之一。许多(大多数?)R 操作都是矢量化的。但有一些事情不是 - 并且 if(){}else{}是非矢量化的事物之一。它用于控制流(无论是否运行代码块),而不用于向量运算。 ifelse()是一个用于向量的单独函数,其中第一个参数是“测试”,第二个和第三个参数是“如果是”和“如果否”结果。测试是一个向量,返回的值是测试中每个项目的适当的是/否结果。 结果将与测试的长度相同

所以我们会写你的 IsPretty功能如下:

IsPretty <- function(PetalWidth){
return(ifelse(PetalWidth > 0.3, "Y", "N"))
}

df <- iris
df$Pretty = IsPretty(df$Petal.Width)

if(){...}else{...}对比测试条件长度为 1 的 block ,并且可以在 ... 中运行任意代码- 可能返回比测试更大的结果,或者更小的结果,或者没有结果 - 可能会修改其他对象...您可以在 if(){}else() 内执行任何操作,但测试条件的长度必须为 1。

您可以使用您的IsPretty一次运行一行 - 它对于任何一行都可以正常工作。因此,我们可以将其放入如下循环中,一次检查一行,给出 if()一次进行一项测试,一次分配一个结果。但 R 针对矢量化进行了优化,这会明显变慢,并且是一个坏习惯。

IsPrettyIf <-function(PetalWidth){
if (PetalWidth >0.3) return("Y")
return("N")
}

for(i in 1:nrow(df)) {
df$PrettyLoop[i] = IsPrettyIf(df$Petal.Width[i])
}

下面的基准测试显示矢量化版本的速度提高了 50 倍。这是一个如此简单的案例和如此小的数据,这并不重要,但对于更大的数据,或更复杂的操作,矢量化和非矢量化代码之间的差异可能是几分钟与几天。

microbenchmark::microbenchmark(
loop = {
for(i in 1:nrow(df)) {
df$PrettyLoop[i] = IsPrettyIf(df$Petal.Width[i])
}
},
vectorized = {
df$Pretty = IsPretty(df$Petal.Width)
}
)
Unit: microseconds
expr min lq mean median uq max neval
loop 3898.9 4365.6 5880.623 5442.3 7041.10 11344.6 100
vectorized 47.7 59.6 112.288 67.4 83.85 1819.4 100

对于 R 学习者来说,这是一个常见的问题 - 您可以在 Stack Overflow 上找到许多问题,人们正在使用 if(){}else{}当他们需要时ifelse()或相反亦然。 Why can't ifelse return vectors?是来自问题另一面的常见问题解答。


您的尝试发生了什么?

df <- iris

## The condition has length equal to the number of rows in the data frame
df$Petal.Width > 0.3
#> [1] FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
#> [13] FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE TRUE FALSE TRUE
## ... truncated


## R warns us that only the first value (which happens to be FALSE) is used
result = if(df$Petal.Width > 0.3) {"Y"} else {"N"}
#> Warning in if (df$Petal.Width > 0.3) {: the condition has length > 1 and only
#> the first element will be used

## So the result is a single "N"
result
#> [1] "N"

length(result)
#> [1] 1


## R "recycles" inputs that are of insufficient length
## so we get a full column of "N"
df$Pretty = result
head(df)
#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species Pretty
#> 1 5.1 3.5 1.4 0.2 setosa N
#> 2 4.9 3.0 1.4 0.2 setosa N
#> 3 4.7 3.2 1.3 0.2 setosa N
#> 4 4.6 3.1 1.5 0.2 setosa N
#> 5 5.0 3.6 1.4 0.2 setosa N
#> 6 5.4 3.9 1.7 0.4 setosa N

reprex package于2020年11月8日创建(v0.3.0)

关于r - 如何在 r 中编写函数来对记录进行计算?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64745336/

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