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.