1989: The Midge Classification Problem (Keith)

Two species of midges, Af and Apf, have been identified by biologists Grogan and Wirth (1981) on the basis of antenna and wing length (Figure A.8). Each of nine Af midges is denoted by a circle, and each of six Apf midges is denoted by a square. It is important to be able to classify a specimen as Af or Apf, given the antenna and wing length

Midge Data

The midge data provided for each species appears as shown below:

Midge Antenna and Wing Length
Species Ant.Length Wing.Length
Af 1.38 1.64
Af 1.40 1.70
Af 1.24 1.72
Af 1.36 1.74
Af 1.38 1.82
Af 1.48 1.82
Af 1.54 1.82
Af 1.38 1.90
Af 1.56 2.08
Apf 1.14 1.78
Apf 1.20 1.86
Apf 1.18 1.96
Apf 1.30 1.96
Apf 1.26 2.00
Apf 1.28 2.00

Apf & Af Midge Scatterplot

Given a midge that you know is species Af or Apf, how would you go about classifying it?

Leverage the existence of the pointless region between the species to establish boundaries to create two lines of separation between the two midge species.

Boundaries shown below:

    ggplot(midge, aes(Wing.Length, Ant.Length, shape =  Species)) +
    geom_point(aes(colour =  Species ), size = 4) + geom_point(colour = "grey90", size = 1.5) +
    geom_segment(aes(x = 1.6, y = 1.146667, xend = 2.1, yend = 1.535556),   colour= "red") +
    geom_segment(aes(x = 1.6, y = 0.98, xend = 2.1, yend= 1.424444 ),   colour= "light blue")  +
        labs(title = "Af-Apf Midge Boundaries")

Problem Statement

Apply your method to three specimens with (antenna, wing) lengths (1.24, 1.80), (1.28, 1.84), (1.40, 2.04)

The method proposed above to use lines of separation does not adequately handle the new midges. The three specimens fall within the pointless region between the two midge borders.

Species <- rep("Unclassified", 3)
Ant.Length  <- c(1.24, 1.28, 1.40)
Wing.Length <- c(1.80,  1.84,   2.04)

unclassified <- data.frame(Species, Ant.Length, Wing.Length)


midge <- rbind(midge, unclassified)

p <- ggplot(midge, aes(Wing.Length, Ant.Length, shape = Species))
p + geom_point(aes(colour = Species), size = 4) + 
  geom_point(colour = "grey90", size = 1.5) +     
  labs(y = "Antenna Length (mm)", x = "Wing Length (mm)") +
    geom_segment(aes(x = 1.6, y = 1.146667, xend = 2.1, yend = 1.535556),   colour= "red") +
    geom_segment(aes(x = 1.6, y = 0.98, xend = 2.1, yend= 1.424444 ),   colour= "light blue")  +
        labs(title = "Midge Scatterplot with Unclassified Midge Specimens")

Assume that species Af is a valuable pollinator and that species Apf is a carrier of a debilitating disease. Would you modify your classification scheme and if so, how?

  • Yes, the classification scheme needs to be modified to classifiy the species falling in between the existing Apf and Af boundaries.

Approach

Recompute lines of separation between the two species of midges using three different classification methods:

1.) Using the ratio of midge antenna length to wing length
2.) Linear regression with predicted lower and upper ranges with an 85% confidence level
3.) Linear regression using the mid-point between the two resuling regression lines

Assumptions

  1. It is not stated in the problem description but we assume that all species of midge are of the same gender.
  2. The sample size is consistent with the midge population or is of equal proportion.
  3. Wing length and antenna length are suitable characteristics in determining the species of midge.

Classification Method 1: Antenna-Wing Ratio

  • Consider the ratio of midge antenna to wing length as a means of classification
data(midge)

midge$ratio <- with(midge, Ant.Length/Wing.Length)

ggplot(data=midge, aes(factor(Species), ratio, colour=Species)) + geom_boxplot() + 
    theme(axis.text.x = element_text(angle = 90, hjust =1)) + xlab('Midge Species') +
    labs(title = "Boxplot - Ratio of Antenna Length to Wing Length")

Using the mean ratio for each species, we arrive at the following equations:

Group.1 x
Af 0.7846034
Apf 0.6368195

Or,

\[\text{Af Midge: }Antenna.Length = 0.7846034 * Wing.Length\]

\[\text{Apf Midge:} Antenna.Length = 0.6368195 * Wing.Length\]

Superimposing on top of the midge graph:

midge$ratio_fit [midge$Species=='Af'] <- 0.7846034 * midge$Wing.Length[midge$Species=='Af']
midge$ratio_fit [midge$Species=='Apf'] <- 0.6368195 *  midge$Wing.Length[midge$Species=='Apf']

## Graph 
ggplot(midge, aes(Wing.Length, Ant.Length, shape = Species)) + 
  geom_point(aes(colour =  Species), size = 4) + geom_point(colour = "grey90", size = 1.5) +
  geom_line(aes(x = Wing.Length, y = midge$ratio_fit, colour = Species))

To establish a border between the two species, use the mean of the ratios to draw lines of separation. The mean antenna-wing ratio is 0.7107115.

We see the result below after creating the boundary and adding the unclassified midge species:

data(midge)

midge <- rbind(midge, unclassified)

midge$ratio_fit [midge$Species=='Af'] <- 0.7846034 * midge$Wing.Length[midge$Species=='Af']
midge$ratio_fit [midge$Species=='Apf'] <- 0.6368195 *  midge$Wing.Length[midge$Species=='Apf']

midge$mean_ratio_fit <- 0.7107115 * midge$Wing.Length

## Graph 2:
ggplot(midge, aes(Wing.Length, Ant.Length, shape = Species)) + 
  geom_point(aes(colour = Species), size = 4) + geom_point(colour = "grey90", size = 1.5) +
  geom_line(aes(x = Wing.Length, y = midge$ratio_fit, colour = Species)) +
  geom_line(aes(x = Wing.Length, y = midge$mean_ratio_fit)) +
  labs(title = "Ratio Approach to Establish Classification Boundary") 

Classification Method 1 - Classification Scheme:

\[\text{if Antenna.Length > 0.7107115 * Wing.Length then Af Midge}\]

\[\text{if Antenna.Length < 0.7107115 * Wing.Length then Apf Midge}\]


Classification Method 2 - LM Prediction

Create linear regression models for the Af and Apf species.

data(midge)

p <- ggplot(midge, aes(x=Wing.Length, y=Ant.Length, shape = Species))
p + geom_point(aes(colour = Species), size = 4) + geom_point(colour = "grey90", size = 1.5) +
  geom_smooth(aes(x=Wing.Length, y=Ant.Length, colour=Species), method=lm, se=FALSE)

Applying predicted values based on the model with an 85% confidence level:

Species <- rep("Unclassified", 3)
Ant.Length  <- c(1.24, 1.28, 1.40)
Wing.Length <- c(1.80,  1.84,   2.04)

unclassified <- data.frame(Species, Ant.Length, Wing.Length)


midge <- rbind(midge, unclassified)

model_apf <- lm(Ant.Length ~ Wing.Length, subset(midge, Species=="Apf"))

#summary(model_apf)

model_af <- lm(Ant.Length ~ Wing.Length, subset(midge, Species=="Af"))

#summary(model_af)

wing_length <- seq(1.6, 2.1, length.out = 18)
lvl <- .85
apf_pred <- as.data.frame(
  predict(model_apf, data.frame(Wing.Length = wing_length), interval = "prediction", level = lvl))


#View(apf_pred)

apf_pred <- cbind(wing_length, apf_pred)
#str(apf_pred)

af_pred <- as.data.frame(
  predict(model_af, data.frame(Wing.Length = wing_length), interval = "prediction", level = lvl))

#View(af_pred)

af_pred <- cbind(wing_length, af_pred)

Apf Midge Fit, Lower and Upper Values

wing_length fit lwr upr
1.600000 1.044315 0.8910843 1.197546
1.629412 1.060733 0.9170409 1.204426
1.658824 1.077152 0.9426808 1.211622
1.688235 1.093570 0.9679344 1.219205
1.717647 1.109988 0.9927142 1.227262
1.747059 1.126406 1.0169118 1.235901
1.776471 1.142824 1.0403942 1.245254
1.805882 1.159242 1.0630039 1.255481
1.835294 1.175661 1.0845628 1.266759
1.864706 1.192079 1.1048849 1.279273
1.894118 1.208497 1.1237989 1.293195
1.923529 1.224915 1.1411788 1.308652
1.952941 1.241334 1.1569723 1.325695
1.982353 1.257752 1.1712135 1.344290
2.011765 1.274170 1.1840149 1.364325
2.041177 1.290588 1.1955408 1.385636
2.070588 1.307006 1.2059762 1.408037
2.100000 1.323425 1.2155023 1.431347

Af Midge Fit, Lower and Upper Values

wing_length fit lwr upr
1.600000 1.315418 1.156812 1.474024
1.629412 1.329504 1.175582 1.483427
1.658824 1.343591 1.193739 1.493442
1.688235 1.357677 1.211234 1.504120
1.717647 1.371763 1.228019 1.515508
1.747059 1.385849 1.244053 1.527646
1.776471 1.399936 1.259305 1.540567
1.805882 1.414022 1.273755 1.554289
1.835294 1.428108 1.287398 1.568818
1.864706 1.442195 1.300241 1.584148
1.894118 1.456281 1.312305 1.600257
1.923529 1.470367 1.323622 1.617113
1.952941 1.484453 1.334232 1.634674
1.982353 1.498540 1.344185 1.652894
2.011765 1.512626 1.353531 1.671721
2.041177 1.526712 1.362323 1.691102
2.070588 1.540798 1.370612 1.710986
2.100000 1.554885 1.378447 1.731322
## Graph of predicted range ##
ggplot(midge) + geom_point(aes(x=Wing.Length, y=Ant.Length, colour = Species, shape = Species), size = 4) +
  geom_line(aes(apf_pred$wing_length, apf_pred$lwr), colour = 'green', size = 1) +
  geom_line(aes(apf_pred$wing_length, apf_pred$upr), colour = 'green', size = 1) +
  geom_line(aes(af_pred$wing_length, af_pred$lwr), colour = 'red') +
  geom_line(aes(af_pred$wing_length, af_pred$upr), colour = 'red')  +
  labs(title = "Linear Model Predicted Bands - 85% Confidence Level")

The predicted lower and upper bands for each species do not cover the unclassified midge at (1.8, 1.24). This model fails to predict one of the three unclassified midge specimens.


Classification Method 3: LM Mid-point

Given unclassified missed midge, use a similar approach using the mid-way points between the two boundaries established by the linear models:

## Apf model coefficients ##
coef(model_apf)
## (Intercept) Wing.Length 
##   0.1511644   0.5582192
## Af model coefficients ##
coef(model_af)
## (Intercept) Wing.Length 
##   0.5491244   0.4789335

\[\text{Af Midge:} Antenna.Length = 0.4789 * Wing.Length + 0.5491\] \[\text{Apf Midge:} Antenna.Length = 0.5582 * Wing.Length + 0.1512\]

avg_intercept<- mean( c(  coef(model_apf)[1], coef(model_af)[1]) )
avg_slope <- mean(c(coef(model_apf)[2], coef(model_af)[2]))

ggplot(midge) + geom_point(aes(x=Wing.Length, y=Ant.Length, colour = Species, shape = Species), size = 4) +
  geom_abline(intercept = coef(model_apf)[1], slope = coef(model_apf)[2], col='green') +
  geom_abline(intercept = coef(model_af)[1], slope = coef(model_af)[2], col='red')  +
  geom_abline(intercept = avg_intercept, slope = avg_slope, col='black')  

Classification Method 3: LM Mid-point - Classification Scheme:

\[\text{if Antenna.Length > 0.5185763 * Wing.Length + 0.3501444 then Af Midge}\]

\[\text{if Antenna.Length < 0.5185763 * Wing.Length + 0.3501444 then Apf Midge}\]


Results

Classification Method Af Midge Classification Model Apf Midge Classification Model
Antenna-Wing Ratio Antenna.Length > 0.7107115 * Wing.Length Antenna.Length > 0.7107115 * Wing.Length
LM Prediction Antenna.Length = 0.4789 * Wing.Length + 0.5491 Antenna.Length = 0.5582 * Wing.Length + 0.1512
LM Mid-point Antenna.Length > 0.5185763 * Wing.Length + 0.3501444 Antenna.Length < 0.5185763 * Wing.Length + 0.3501444
Classification Method Midge (Wing/Ant) Modeled Ant Length Predicted Species
Antenna-Wing Ratio (1.80, 1.24) 1.279281 Apf
Antenna-Wing Ratio (1.84, 1.28) 1.307709 Apf
Antenna-Wing Ratio (2.04, 1.40) 1.449851 Apf
Classification Method Midge (Wing/Ant) Modeled Ant Length (85% Confidence) Predicted Species
LM Prediction (1.80, 1.24) 1.0630039 to 1.255481 Apf
LM Prediction (1.84, 1.28) 1.0845628 to 1.266759 * Not Classified
LM Prediction (2.04, 1.40) 1.1955408 to 1.385636 Af
Classification Method Midge (Wing/Ant) Modeled Ant Length Predicted Species
LM Mid-point (1.80, 1.24) 1.283582 Apf
LM Mid-point (1.84, 1.28) 1.304325 Apf
LM Mid-point (2.04, 1.40) 1.40804 Apf

1986: The Emergency-Facilities Location Problem (Dan)

The township of Rio Rancho has hitherto not had its own emergency facilities. It has secured funds to erect two emergency facilities in 1986, each of which will combine ambulance, fire, and police services. Figure A.4 indicates the demand, or number of emergencies per square block, for 1985. The L region in th north is an obstacle, whereas the rectangle in the south is a park with a shallow pond. It takes an emergency vehicle an average of 15 seconds to go one block in the N-S direction and 20 seconds in the E-W direction. Your task is to locate the two facilities so as to minimize the total response time.

Assumptions

  • Assume that the demand is concentrated at the center of the block and that the facilities will be located on corners.

  • Assume that the demand is uniformly distributed on the streets bordering each block and that the facilities may be located anywhere on the streets.

Approach One

  • Euclidean Distance

  • Treat all points as those they can be reached by all of the other points

  • Treat the barries as blocks with no incidencies

  • Number of incidences gets multiplied by the N/S weight and E/W weight to get the total distance for traveling to that location.

  • All distances and added up acr0ss the board and the two smallest distances are where the stations should be placed.

distance <- function(matrix)
{
  final <- matrix(rep(0), nrow = NROW(matrix), ncol = NCOL(matrix))
  final.row <- 1
  final.col <- 1
  
  for (final.row in 1:NROW(matrix))
  {
    for (final.col in 1:NCOL(matrix))
    {
      temp <- 0
      for (i in 1:NROW(matrix))
      {
        for (j in 1:NCOL(matrix))
        {
          temp <- temp + matrix[i,j]*(abs(15*(final.row - i)) + abs(20*(final.col - j)))
        }
      }
      final[final.row, final.col] <- temp
    }
  }
  return(final)
}
Ranchero <- matrix(c(3,1,4,2,5,3,2,3,3,2,2,0,3,3,2,3,0,0,3,1,3,4,3,3,5,2,3,4,4,0,1,2,0,1,3,0,2,0,3,2,3,0,0,0,4,3,1,0,4,2), nrow = 10, ncol = 5, byrow = TRUE)

raw.distance <- distance(Ranchero)

#23 and 24
  • Below we can see the matrix of incidencies

  • Below that we see the distances. Block (5,3) and (5,4) have the smallest distances, so the stations should be placed there.

Ranchero
##       [,1] [,2] [,3] [,4] [,5]
##  [1,]    3    1    4    2    5
##  [2,]    3    2    3    3    2
##  [3,]    2    0    3    3    2
##  [4,]    3    0    0    3    1
##  [5,]    3    4    3    3    5
##  [6,]    2    3    4    4    0
##  [7,]    1    2    0    1    3
##  [8,]    0    2    0    3    2
##  [9,]    3    0    0    0    4
## [10,]    3    1    0    4    2
print("/n")
## [1] "/n"
raw.distance
##        [,1]  [,2]  [,3]  [,4]  [,5]
##  [1,] 11040  9820  9200  9260 10360
##  [2,]  9885  8665  8045  8105  9205
##  [3,]  9120  7900  7280  7340  8440
##  [4,]  8655  7435  6815  6875  7975
##  [5,]  8400  7180  6560  6620  7720
##  [6,]  8685  7465  6845  6905  8005
##  [7,]  9360  8140  7520  7580  8680
##  [8,] 10245  9025  8405  8465  9565
##  [9,] 11340 10120  9500  9560 10660
## [10,] 12645 11425 10805 10865 11965

Approach Two

  • Treat the matrix as a transition matrix

  • Use graphical based algorithms instead of euclidean distance, because not all points are reached by other points

  • Obstacles are left outside of the transition matrix, meaning they are not able to be reached

  • Create a digraph of all the points in the grid

  • Use Djikstras shorest path algorithm to find the shorest distances between all of the points

  • Add up all of those distance to find the total sitances between all the possible points in the model

  • The N/S and E/W distances are divided by the number of incidencies at that location. Since there are 0 incidencies on some locations, 1 was added to everything to make the math possible.

  • Transition Matrix

head(Rio.Rancho)
##      [,1] [,2] [,3]     [,4]     [,5] [,6]     [,7] [,8] [,9] [,10]
## [1,] 0.00   10    0 0.000000 0.000000 3.75 0.000000 0.00 0.00     0
## [2,] 5.00    0    4 0.000000 0.000000 0.00 5.000000 0.00 0.00     0
## [3,] 0.00   10    0 5.000000 0.000000 0.00 0.000000 3.75 0.00     0
## [4,] 0.00    0    4 0.000000 3.333333 0.00 0.000000 0.00 3.75     0
## [5,] 0.00    0    0 6.666667 0.000000 0.00 0.000000 0.00 0.00     5
## [6,] 3.75    0    0 0.000000 0.000000 0.00 6.666667 0.00 0.00     0
##         [,11] [,12] [,13] [,14] [,15] [,16] [,17] [,18] [,19] [,20] [,21]
## [1,] 0.000000     0     0     0     0     0     0     0     0     0     0
## [2,] 0.000000     0     0     0     0     0     0     0     0     0     0
## [3,] 0.000000     0     0     0     0     0     0     0     0     0     0
## [4,] 0.000000     0     0     0     0     0     0     0     0     0     0
## [5,] 0.000000     0     0     0     0     0     0     0     0     0     0
## [6,] 6.666667     0     0     0     0     0     0     0     0     0     0
##      [,22] [,23] [,24] [,25] [,26] [,27] [,28] [,29] [,30] [,31] [,32]
## [1,]     0     0     0     0     0     0     0     0     0     0     0
## [2,]     0     0     0     0     0     0     0     0     0     0     0
## [3,]     0     0     0     0     0     0     0     0     0     0     0
## [4,]     0     0     0     0     0     0     0     0     0     0     0
## [5,]     0     0     0     0     0     0     0     0     0     0     0
## [6,]     0     0     0     0     0     0     0     0     0     0     0
##      [,33] [,34] [,35] [,36] [,37] [,38] [,39] [,40] [,41] [,42] [,43]
## [1,]     0     0     0     0     0     0     0     0     0     0     0
## [2,]     0     0     0     0     0     0     0     0     0     0     0
## [3,]     0     0     0     0     0     0     0     0     0     0     0
## [4,]     0     0     0     0     0     0     0     0     0     0     0
## [5,]     0     0     0     0     0     0     0     0     0     0     0
## [6,]     0     0     0     0     0     0     0     0     0     0     0
##      [,44] [,45] [,46] [,47] [,48] [,49] [,50]
## [1,]     0     0     0     0     0     0     0
## [2,]     0     0     0     0     0     0     0
## [3,]     0     0     0     0     0     0     0
## [4,]     0     0     0     0     0     0     0
## [5,]     0     0     0     0     0     0     0
## [6,]     0     0     0     0     0     0     0

Plot

  • Digraph, showing the connection between all of the nodes

  • The nodes off to the sides are the barriers, they cannot be reached by anything

graph <- graph.adjacency(Rio.Rancho, mode = "directed", weight = TRUE)

plot.igraph(graph, layout = layout.fruchterman.reingold, vertex.label.color = "black", edge.color = "black")

Shortest Path

s.path <- shortest.paths(graph, algorithm = "dijkstra")

for (rows in 1:NROW(s.path))
{
  for (cols in 1:NCOL(s.path))
  {
    if (is.infinite(s.path[rows,cols]))
    {
      s.path[rows, cols] <- NA
    }
  }
}

final <- data.frame(Node = character(50), Distance = numeric(50), stringsAsFactors = FALSE)

for (rows in 1:NROW(s.path))
{
  final$Node[rows] <- rows
  final$Distance[rows] <- sum(s.path[rows,], na.rm = TRUE)
}

possible.outcomes <- final %>% filter(Distance > 0)
mins <- head(sort(possible.outcomes$Distance), 2)

smallest <- possible.outcomes %>% filter(Distance == mins[1])
second <- possible.outcomes %>% filter(Distance == mins[2])

#24 and 29
  • Below we see the distance matrix, shows the distacne from the nodes on the rows, to each node across the columns.
  • Below that is the two smallest distances. The translate to the points (5,4) and (6,4)
  • The stations should now be stacked, compared to being next to each other. That could be due to the boundaries getting in the way.
head(s.path)
##          [,1]     [,2]      [,3]      [,4]      [,5]     [,6]     [,7]
## [1,]  0.00000  5.00000  9.000000 13.000000 16.333333  3.75000  8.75000
## [2,]  5.00000  0.00000  4.000000  8.000000 11.333333  8.75000  5.00000
## [3,]  9.00000  4.00000  0.000000  4.000000  7.333333 12.75000  8.00000
## [4,] 13.00000  8.00000  4.000000  0.000000  3.333333 16.75000 12.00000
## [5,] 16.33333 11.33333  7.333333  3.333333  0.000000 20.08333 15.33333
## [6,]  3.75000  8.75000 12.750000 16.750000 20.083333  0.00000  5.00000
##          [,8]      [,9]     [,10]    [,11] [,12]    [,13]    [,14]
## [1,] 12.00000 16.750000 18.833333  7.50000    NA 15.75000 20.50000
## [2,]  7.00000 11.750000 13.833333 12.50000    NA 10.75000 15.50000
## [3,]  3.00000  7.750000  9.833333 16.50000    NA  6.75000 11.50000
## [4,]  7.00000  3.750000  5.833333 20.50000    NA 10.75000  7.50000
## [5,] 10.33333  7.083333  2.500000 23.83333    NA 14.08333 10.83333
## [6,] 10.00000 15.000000 20.000000  3.75000    NA 13.75000 18.75000
##         [,15]    [,16] [,17] [,18] [,19]    [,20]    [,21]    [,22]
## [1,] 23.83333 11.25000    NA    NA 24.25 28.83333 15.00000 19.00000
## [2,] 18.83333 16.25000    NA    NA 19.25 23.83333 20.00000 24.00000
## [3,] 14.83333 20.25000    NA    NA 15.25 19.83333 24.00000 28.00000
## [4,] 10.83333 24.25000    NA    NA 11.25 15.83333 28.00000 26.66667
## [5,]  7.50000 27.58333    NA    NA 11.25 12.50000 30.66667 26.66667
## [6,] 23.75000  7.50000    NA    NA 22.50 27.50000 11.25000 15.25000
##         [,23] [,24]    [,25] [,26] [,27] [,28] [,29]    [,30] [,31] [,32]
## [1,] 25.66667 28.00 31.33333 18.75 22.00 26.00 27.50 31.50000 23.75 25.75
## [2,] 28.00000 23.00 26.33333 23.75 27.00 30.00 26.00 28.83333 28.75 30.75
## [3,] 24.00000 19.00 22.33333 27.75 30.00 26.00 22.00 24.83333 32.75 33.75
## [4,] 20.00000 15.00 18.33333 31.00 26.00 22.00 18.00 20.83333 36.00 29.75
## [5,] 20.00000 15.00 15.00000 31.00 26.00 22.00 18.00 17.50000 36.00 29.75
## [6,] 21.91667 26.25 29.58333 15.00 18.25 22.25 26.25 30.25000 20.00 22.00
##      [,33] [,34]    [,35]    [,36] [,37] [,38] [,39]    [,40] [,41] [,42]
## [1,] 29.00 24.50 27.75000 31.25000 30.75    NA 20.75 24.00000 35.00 35.75
## [2,] 33.00 29.00 32.58333 36.25000 35.75    NA 25.75 29.00000 40.00 40.75
## [3,] 29.00 25.00 28.58333 40.25000 38.75    NA 28.75 32.33333 44.00 43.75
## [4,] 25.00 21.00 24.58333 41.41667 34.75    NA 24.75 28.33333 44.75 39.75
## [5,] 25.00 21.00 21.25000 41.41667 34.75    NA 24.75 25.00000 44.75 39.75
## [6,] 25.25 28.25 31.50000 27.50000 27.00    NA 24.50 27.75000 31.25 32.00
##      [,43] [,44]    [,45] [,46]    [,47]    [,48]    [,49] [,50]
## [1,]    NA 17.00 21.00000  35.0 30.00000 10.00000 14.00000 18.00
## [2,]    NA 22.00 26.00000  40.0 35.00000 15.00000 19.00000 23.00
## [3,]    NA 26.00 30.00000  44.0 39.00000 19.00000 23.00000 27.00
## [4,]    NA 28.50 31.33333  48.0 43.00000 23.00000 27.00000 31.00
## [5,]    NA 28.50 28.00000  48.5 46.33333 26.33333 30.33333 32.00
## [6,]    NA 20.75 24.75000  35.0 33.75000 13.75000 17.75000 21.75
print("/n")
## [1] "/n"
mins
## [1] 663.3333 683.6667