I also faced a similar problem when trying to find a package that finds quartiles. That's not to say the others are wrong but to say this is how I personally would have defined quartiles. It is similar to Shikar's results with using mid-point but also works on lists that have an odd length. If the quartile position is between lengths, it will use the average of the neighbouring values. (i.e. position always treated as either the exact position or 0.5 of the position)
import math
def find_quartile_postions(size):
if size == 1:
# All quartiles are the first (only) element
return 0, 0, 0
elif size == 2:
# Lower quartile is first element, Upper quartile is second element, Median is average
# Set to 0.5, 0.5, 0.5 if you prefer all quartiles to be the mean value
return 0, 0.5, 1
else:
# Lower quartile is element at 1/4th position, median at 1/2th, upper at 3/4
# Quartiles can be between positions if size + 1 is not divisible by 4
return (size + 1) / 4 - 1, (size + 1) / 2 - 1, 3 * (size + 1) / 4 - 1
def find_quartiles(num_array):
size = len(num_array)
if size == 0:
quartiles = [0,0,0]
else:
sorted_array = sorted(num_array)
lower_pos, median_pos, upper_pos = find_quartile_postions(size)
# Floor so can work in arrays
floored_lower_pos = math.floor(lower_pos)
floored_median_pos = math.floor(median_pos)
floored_upper_pos = math.floor(upper_pos)
# If position is an integer, the quartile is the elem at position
# else the quartile is the mean of the elem & the elem one position above
lower_quartile = (sorted_array[floored_lower_pos]
if (lower_pos % 1 == 0)
else (sorted_array[floored_lower_pos] + sorted_array[floored_lower_pos + 1]) / 2
)
median = (sorted_array[floored_median_pos]
if (median_pos % 1 == 0)
else (sorted_array[floored_median_pos] + sorted_array[floored_median_pos + 1]) / 2
)
upper_quartile = (sorted_array[floored_upper_pos]
if (upper_pos % 1 == 0)
else (sorted_array[floored_upper_pos] + sorted_array[floored_upper_pos + 1]) / 2
)
quartiles = [lower_quartile, median, upper_quartile]
return quartiles