【问题标题】:Writing for nested for loop where statements have multiple conditions in R编写嵌套 for 循环,其中语句在 R 中有多个条件
【发布时间】:2017-08-13 08:55:22
【问题描述】:

我正在尝试根据篮球场的某些区域来确定投篮命中率,包括禁区、油漆区(不包括禁区)、所有其他 2 分球、角球 3 分和所有其他 3 分。

我所拥有的是结果(成功或失败)或每个镜头的 x、y 坐标。我试图做的是编写一个 for 循环来获取行和行信息,并使用嵌套的 ifelse 语句检查是否满足多个条件。

for (i in cs){shotarea[i] <- ifelse(x[i] >= -125 & x[i] <= 125 & y[i] < x[i]*tan(acos(x[i]/125)),1,
                  ifelse(x[i] => -125 & x[i] <= 125 & y[i] < 460 & y[i] > 460-x[i]*tan(acos(x[i]/125)),2,
                  ifelse(x[i] >= -245 & x[i] < -125 & y[i] < 460,2,
                  ifelse(x[i] <= 245 & x[i] > 125 & y[i] < 460,2,
                  ifelse(x[i] >= -660 & x[i] < -245 & y[i] < x[i]*tan(acos(x[i]/675)),3,
                  ifelse(x[i] > -245 & x[i] < 245 & y[i] < x[i]*tan(acos(x[i]/675)) & y > 460,3,
                  ifelse(x[i] > 245 & x[i] <= 660 & y[i] < x[i]*tan(acos(x[i]/675)),3,
                  ifelse(x[i] > -750 & x[i] < -660 & y[i] < x[i]*tan(acos(660/675)),4,
                  ifelse(x[i] < 750 & x[i] > 660 & y[i] < x[i]*tan(acos(660/675)),4,
                  ifelse(x[i] > -750 & x[i] < -660 & y[i] > x[i]*tan(acos(660/675)),5,
                  ifelse(x[i] < 750 & x[i] > 660 & y[i] > x[i]*tan(acos(660/675)),5,
                  ifelse(x[i] > -660 & x[i] < 660 & y[i] > x[i]*tan(acos(x[i]/675)),5,6))))))))))))}

我用几何函数界定了球场上的所有区域:
限制区域 = x(-125,125), y(inf, xtanacos(x/125))

油漆,不包括限制区域 = (x(-245,-125)U(125,245), y(inf, 460)) 和 (x(-125,125),y(xtanacos (x/125),460))

所有其他 2 = (x(-660,-245)U(245,660),y(inf, x[i]tanacos(x[i]/675)) 和 (x (-245,245),y(460,x[i]tanacos(x[i]/675))

三号角 = x(-750,-660)U(660,750),y(inf,x[i]tanacos(660/675)

所有其他 3 的 = (x(-750,-660)U)(660,750),y(x[i]tanacos(660/675),inf)) 和 (x( -660,660),y(x[i]tanacos(x[i]/675),inf)

x 值的范围是 (-750,750),y 值的范围是 (-87,972),其中 (0,0) 是篮子的中心,x 值的范围是边线到边线。我有几个数据子集,我根据 x 值的范围运行它。我运行一个子集,其中 x 范围 (-125,125),一个运行 (-675,-125)U(125,675),另一个运行 (-750,-675)U(675,750)。 (我这样做是为了防止 arccos() 表达式返回 NAN 作为预防措施,但我认为我实际上不需要这样做)。你还会注意到我使用了一个向量来表示 i 的范围,这样我就可以分出我制作的不同子集。不知道是不是这个问题。

每当我尝试运行它时,我都会得到

Error: unexpected ')' in:"ifelse((x[i] < 750 && x[i] > 660 && y[i] > x[i]*tan*acos(660/675)),5,
                  ifelse((x[i] > -660 && x[i] < 660 && y[i] > x[i]*tan*acos(x[i]/675)),5,6)))))))))))", > }Error: unexpected '}' in "}"

我仔细检查和三次检查以确保我没有输入多余的括号或括号,但我找不到。所以我想我要的是两件事之一:

可能导致此错误的代码是否存在其他问题?

与/或

你会推荐更好的东西吗?我确信必须有一些“申请”的方式来做到这一点,但我在申请时非常不确定,不知道从哪里开始。

EDIT: For sample data, you could use x <- runif(3580,min=-749,max=749); y <- runif(3580,min=-86,max=971)

EDIT: I went through and made sure the tan() functions had parenthesis, but otherwise removed what I hope are redundant parethenses

【问题讨论】:

  • 您也可以通过子集更轻松地完成此任务,但如果没有样本数据集就很难判断。
  • 谢谢,我刚刚添加了一些示例数据的编辑。
  • 其中一个问题与您的x[1]*tan*acos() 通话有关。 tan() 是一个函数,需要一个输入。否则它不知道如何处理它。你是想要x[1]*tan(acos()) 还是 x[1]*tan(x[1])*acos()`
  • 哦,好点。我想要 x[i]*tan(acos())。我想在脚本中有意外的“)”的恐慌中,我寻找任何可以删除不必要的括号的方法,并且我必须匆忙删除它们。

标签: r for-loop nested conditional


【解决方案1】:

您可以通过使用dplyrcase_when 函数更简单地做到这一点。这种方法完成了两件事。首先,它消除了 for 循环,从而减少了评估时间。其次,它没有使用所有 ifelse 语句。

library(dplyr)
x <- runif(3580,min=-749,max=749); y <- runif(3580,min=-86,max=971)
df <- data.frame(x = x, y = y)
df1 <- df %>%
  mutate(shotarea = case_when(.$x >= -125 & .$x <= 125 & .$y < .$x*tan(acos(.$x/125)) ~ "restricted",
                              .$x >= -125 & .$x <= 125 & .$y < 460 & .$y > 460-.$x*tan(acos(.$x/125)) ~ "paint",
                              ((.$x >= -245 & .$x < -125) | (.$x > 125 & .$x <= 245)) & .$y < 460 ~ "paint",
                              .$x > -245 & .$x < 245 & .$y < .$x*tan(acos(.$x/675)) & .$y > 460 ~ "other 2",
                              ((.$x >= -660 & .$x < -245) | (.$x > 245 & .$x <= 660)) & .$y < .$x*tan(acos(.$x/675)) ~ "other 2",
                              ((.$x >= -750 & .$x < -660) | (.$x > 660 & .$x <= 750)) & .$y < .$x*tan(acos(660/675)) ~ "corner 3",
                              ((.$x >= -750 & .$x < -660) | (.$x > 660 & .$x <= 750)) & .$y > .$x*tan(acos(660/675)) ~ "other 3",
                              .$x > -660 & .$x < 660 & .$y > .$x*tan(acos(.$x/675)) ~ "other 3",
                              TRUE ~ "other"))

您的输出将是:

> head(df1)
           x         y shotarea
1 -719.26311 733.67983  other 3
2  294.60845 574.06028  other 2
3  423.09931  62.15332  other 2
4  597.60403 960.28765  other 3
5 -592.23907 486.24250  other 3
6   33.58853 411.12968    paint

现在,我使用实际名称而不是 1-6 编号系统,因为我认为这让其他人以及未来的你更容易进行数据可视化和解释。但是您可以使用此设置轻松将其更改回 1-6 系统(6 是“其他”)

【讨论】:

  • 看起来不错。我以前从未真正使用过 dplyr,但我越是滚动浏览 StackExchange 和其他问题的其他答案,我发现 dplyr 和 plyr 是我可能应该了解的非常有用的软件包。我是否仍需要对数据进行子集化以避免 acos(x/125) 和 acos(x/675) 生成 NAN?
  • 我确实收到了一些警告消息,指出产生了一些 NaN。但据我所知,它不应该影响所需的结果,因为如果acos(x/125) 返回NaN,它就不会与对应的字符串匹配。如果您查看结果并且它们似乎不正确,您可以使用mutate() 之前的filter() 函数进行子集化,并且您可以以与调用mutate() 相同的方式调用它
  • 非常感谢!我看了看,你是对的,它没有影响输出,因为条件在技术上没有得到满足。
【解决方案2】:

好的,所以我发现了我的问题,这非常愚蠢。

在第二个 ifelse() 语句中,有条件 x[i] => -125 切换了运算符的语法,应该是 x[i] >= -125。前导的 = 搞砸了所有内容的读取方式,这使 R 认为以下括号和括号是出乎意料的。将两者翻转即可解决问题。

不过,我很感激任何其他回复给我看起来更清晰的想法。我知道一个包含大量 & 条件语句的大型嵌套 ifelse() 语句看起来一点也不漂亮,而且写起来很烦人。我肯定会改用 tbradley 的 dplyr 解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-05
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 2021-11-15
    • 2018-03-15
    • 2021-05-14
    相关资源
    最近更新 更多