为点 R 生成圆形边界

generate circular boundary for points R

我正在努力围绕图像中 4 个不同的感兴趣区域设置边界 - 图像和数据采用 0-1 归一化 space,具有四个大小相同的象限。设置方形边界很容易:

df.all$ROI <- ifelse(df.all$x_pred_normalised > 0 & df.all$x_pred_normalised <= .5 &
                     df.all$y_pred_normalised > 0 & df.all$y_pred_normalised <= .5, c("lower_left"), 
              ifelse(df.all$x_pred_normalised > 0 & df.all$x_pred_normalised <= .5 &
                     df.all$y_pred_normalised > .5 & df.all$y_pred_normalised <= 1, c("upper_left"),
              ifelse(df.all$x_pred_normalised > .5 & df.all$x_pred_normalised <= 1 &
                     df.all$y_pred_normalised > 0 & df.all$y_pred_normalised <= .5, c("lower_right"), 
              ifelse(df.all$x_pred_normalised > .5 & df.all$x_pred_normalised <= 1 &
                     df.all$y_pred_normalised > .5 & df.all$y_pred_normalised <= 1, c("upper_right"),
                     c("other")))))

但是,我想在每个象限 (.25, .25; .25, .75; .75, .25; . 75, .75) 提供相同的输出。

示例数据:

x_pred_normalized <- rnorm(1000, mean=.5, sd=.5)
y_pred_normalized <- rnorm(1000, mean=.5, sd=.5)
df.all <- as.data.frame(cbind(x_pred_normalized, y_pred_normalized))

df.all$ROI_square <- ifelse(df.all$x_pred_normalised > 0 & df.all$x_pred_normalised <= .5 &
                     df.all$y_pred_normalised > 0 & df.all$y_pred_normalised <= .5, c("lower_left"), 
              ifelse(df.all$x_pred_normalised > 0 & df.all$x_pred_normalised <= .5 &
                     df.all$y_pred_normalised > .5 & df.all$y_pred_normalised <= 1, c("upper_left"),
              ifelse(df.all$x_pred_normalised > .5 & df.all$x_pred_normalised <= 1 &
                     df.all$y_pred_normalised > 0 & df.all$y_pred_normalised <= .5, c("lower_right"), 
              ifelse(df.all$x_pred_normalised > .5 & df.all$x_pred_normalised <= 1 &
                     df.all$y_pred_normalised > .5 & df.all$y_pred_normalised <= 1, c("upper_right"),
                     c("other")))))

期望的输出:

x_pred_normalized y_pred_normalized ROI_square  ROI_circle
.99               .99               upper_right other
.51               .51               upper_right other
.25               .25               lower_left  lower_left

您的示例不会产生您描述的数据。并且你永远不应该在 data.frame 的调用中使用 cbind 除非有一个数据框对象作为参数之一。这是一个符合您描述的数据框结构(并且足够小,不会在测试时用无用的输出填满您的控制台):

df.all <- data.frame(
             x_pred_normalized = pmax( 0, pmin( rnorm(10, mean=.5, sd=.5), 0.99999)), 
             y_pred_normalized = pmax( 0, pmin( rnorm(10, mean=.5, sd=.5), 0.99999)) )
# all values between 0 and .99999

我发现深度嵌套的 ifelse 结构非常难以调试并且浪费了 space,而使用两列矩阵来 select 字符矩阵中的项目更容易理解.索引数字矩阵中的列是用 findInterval 构造的,因此它将被矢量化并且在时间和 space.

上都更加高效
 df.all$quad <- matrix(c("First", "Third","Second","Fourth"), ncol=2)[ cbind(
                    findInterval(df.all$x_pred_normalized,c(  0, .5, 1,Inf) ),
                    findInterval(df.all$y_pred_normalized,c(  0, .5,1,Inf) ) )]
#--------------
> df.all
   x_pred_normalized y_pred_normalized   quad
1         0.78886879         0.3063979  Third
2         0.48122193         0.5440334 Second
3         0.85496224         0.4849327  Third
4         0.01457113         0.5116597 Second
5         0.76936612         0.7424495 Fourth
6         0.99999000         0.4544564  Third
7         0.55473184         0.0000000  Third
8         0.99967092         0.7843946 Fourth
9         0.72561140         0.3985747  Third
10        0.17755530         0.1337408  First

对于 circle-containment 列,我将使用逻辑测试乘以索引值,该索引值可用于通过布尔运算从向量中提取值:

dist= function(x,y) 
df.all$circle <- with( df.all, c("other", "First", "Second", "Third", "Fourth")[
      1 +  # value when all subsequent tests are FALSE
      1*(sqrt( (x_pred_normalized-0.25)^2+(y_pred_normalized-0.25)^2) <=0.25) + 
       # above should be should be 1 (TRUE) for lower-rt;  else 0
      2*(sqrt( (x_pred_normalized-0.25)^2+ (y_pred_normalized-0.75)^2) <=0.25)+
      3*(sqrt( (x_pred_normalized-0.75)^2+(y_pred_normalized-0.25)^2) <=0.25)+
      4*(sqrt( (x_pred_normalized-0.75)^2+(y_pred_normalized-0.75)^2)<=0.25) ] )
#--------------
> df.all
   x_pred_normalized y_pred_normalized   quad circle
1         0.78886879         0.3063979  Third  Third
2         0.48122193         0.5440334 Second  other
3         0.85496224         0.4849327  Third  other
4         0.01457113         0.5116597 Second  other
5         0.76936612         0.7424495 Fourth Fourth
6         0.99999000         0.4544564  Third  other
7         0.55473184         0.0000000  Third  other
8         0.99967092         0.7843946 Fourth  other
9         0.72561140         0.3985747  Third  Third
10        0.17755530         0.1337408  First  First

我看到我使用了 0.25 的圆半径,而你要求的是 0.15。必要的更改应该易于实施。