简体   繁体   中英

Writing for nested for loop where statements have multiple conditions in R

I am trying to determine field goal percentage of shots based off of certain areas of a basketball court, including the restricted area, the paint (excl the restricted area), all other 2 pointers, corner 3's, and all other 3's.

What I have are the x,y coordinates of the outcome (make or miss) or each shot. What I tried to do is write a for loop to take in the rows and row information, and check to see if multiple conditions are met using nested ifelse statements.

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))))))))))))}

I bounded all the areas on the court by geometric functions:
Restricted Area = x(-125,125), y(inf, x tan acos(x/125))

Paint, excluding restricted area = (x(-245,-125)U(125,245), y(inf, 460)) and (x(-125,125),y(x tan acos(x/125),460))

All other 2's = (x(-660,-245)U(245,660),y(inf, x[i] tan acos(x[i]/675)) and (x(-245,245),y(460,x[i] tan acos(x[i]/675))

Corner 3's = x(-750,-660)U(660,750),y(inf,x[i] tan acos(660/675)

All other 3's = (x(-750,-660)U)(660,750),y(x[i] tan acos(660/675),inf)) and (x(-660,660),y(x[i] tan acos(x[i]/675),inf)

The x values range from (-750,750) and y values from (-87,972), where (0,0) is the center of the basket, the x values range from sideline to sideline. I have a couple subsets of the data that I run this through depending on the range of x values. I run a subset where x ranges (-125,125), one where it runs (-675,-125)U(125,675), and another where its (-750,-675)U(675,750). (I did this to prevent the arccos() expressions from returning NANs as a precaution, but I don't think I actually needed to). You will also notice I used a vector for the range of i, just so I could sub out the different subsets I made. Not sure if this is the problem.

Whenever I try to run it, I get

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 "}"

I double checked and triple checked to make sure I didn't throw in a redundant parenthesis or bracket, but I can't find one. So I guess what I'm asking for is one of two things:

Is there some other problem with the code that might be creating this error?

AND/OR

Would you recommend something better? I'm sure there must be some "apply" way to do it, but I'm very iffy at apply and wouldn't know where to start.

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

You can do this much more simply by using dplyr and the case_when function. This approach accomplishes two things. First, it eliminates the for loop and thus reduces evaluation time. Second it doesn't use all of the ifelse statements.

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"))

Your output would then be:

> 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

Now, I used the actual names rather than the 1-6 numbering system, because I think that makes data visualization and explanation a lot easier for other people as well as future you. But you can easily change it back to the 1-6 system with this set up (with 6 being the "other")

Okay so I found my problem, and it is awfully silly.

In the 2nd ifelse() statement, there was the condition x[i] => -125 in which the syntax for the operator was switched, should be x[i] >= -125. The leading = messed up how everything was read, which made R think the following parenthesis and bracket were unexpected. Flipping the two back fixed the problem.

Though, I appreciate any other response giving me ideas that look cleaner. I know a big nested ifelse() statement with lots of & conditional statements within doesn't look pretty at all, and they get annoying to write. I would definitely use tbradley's dplyr solution instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM