Interquartile range

Is this the best way to go about this?

--[[
    Calculates the interquartile range of a table.
    The interquartile range is the difference between the upper and lower quartiles.
    The upper quartile is the median of the upper half of the table.
    The lower quartile is the median of the lower half of the table.
    The median is the middle value of the table.
    If the table has an even number of values, the median is the average of the two middle values.
    @param t The table.
    @return The interquartile range.
]]
function get_interquartile_range(t)
    local median = get_median(t)
    local lower_half = {}
    local upper_half = {}
    for i, v in ipairs(t) do
        if v < median then
            table.insert(lower_half, v)
        elseif v > median then
            table.insert(upper_half, v)
        end
    end
    return get_median(upper_half) - get_median(lower_half)
end

--[[
    Calculates the median of a table.
    The median is the middle value of the table.
    If the table has an even number of values, the median is the average of the two middle values.
    @param t The table.
    @return The median.
]]
function get_median(t)
    local sorted = {}
    for i, v in ipairs(t) do
        table.insert(sorted, v)
    end
    table.sort(sorted)
    local middle = math.floor(#sorted / 2)
    if #sorted % 2 == 0 then
        return (sorted[middle] + sorted[middle + 1]) / 2
    else
        return sorted[middle + 1]
    end
end

local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
print(get_interquartile_range(t))

IQR basically is Q3 - Q1 with Q3 being the 75% value of a table and Q1 being the 25% value

The way I would tackle this is like this:

function IQR(t)
	local Q1 = t[#t*0.25]
	local Q3 = t[#t*0.75]
	return Q3 - Q1
end

local newTable = {1,2,3,4,5}
print(IQR(newTable))

This could work but you run into a problem when the #t isn’t even but it’s odd

What I would do to get the Q1 and Q3 is:

function IQR(t)
	if #t % 2 == 0 then -- Checks if it's even
		local Q1 = t[#t*0.25] -- Gets the Q1th value of the table
		local Q3 = t[#t*0.75]
		return Q3 - Q1
	else -- If it isn't then we tackle it another way
		local medQ1 = (math.round(#t*.25) + (math.round(#t*.25)+1))/2 -- Since #t isn't a rounded number it would error so we round it up and get the next number to find the median of those two to then calculate what exact number to look for in our table
		local medQ3 = (math.round(#t*.75) + (math.round(#t*.75)+1))/2
		if medQ1 % 2 == 0 and medQ3 % 2 == 0 then --if the median is even then great we can just do what we did on the first part of the function
			local Q1 = t[medQ1]
			local Q3 = t[medQ3]
			return Q3 - Q1
		else 
			local Q1 = (t[math.round(medQ1)] + t[math.round(medQ1)-1])/2 -- if it isn't since medQn can either be a rounded number or a number like 1.5 and 1.5 will get rounded up to 2 so we get the number before so that we can get the median of the two and then we got Q1
			local Q3 = (t[math.round(medQ3)] + t[math.round(medQ3)-1])/2
			return Q3 - Q1
		end
	end
end

local newTable = {1,2,3,4,5}
print(IQR(newTable))

Assuming of course the table is sorted which can easily be done.

Its works with odd. Though… 20c

I updated the script, and even tested it as you can see below, I believe it doesn’t have any errors.

function IQR(t)
	if (#t % 2) == 0 then -- Checks if it's even
		local Q1 = t[math.round(#t*0.25)] -- Gets the Q1th value of the table
		local Q3 = t[math.round(#t*0.75)]
		print("passed1",Q1,Q3,#t)
		return Q3 - Q1
	else -- If it isn't then we tackle it another way
		local medQ1 = (math.round(#t*.25) + (math.round(#t*.25)+1))/2 -- Since #t isn't a rounded number it would error so we round it up and get the next number to find the median of those two to then calculate what exact number to look for in our table
		local medQ3 = (math.round(#t*.75) + (math.round(#t*.75)+1))/2
		if (medQ1 % 2 == 0) and (medQ3 % 2 == 0) then --if the median is even then great we can just do what we did on the first part of the function
			local Q1 = t[medQ1]
			local Q3 = t[medQ3]
			print("passed2",Q1,Q3)
			return Q3 - Q1
		else 
			local Q1 = (t[math.round(medQ1)] + t[math.round(medQ1)-1])/2 -- if it isn't since medQn can either be a rounded number or a number like 1.5 and 1.5 will get rounded up to 2 so we get the number before so that we can get the median of the two and then we got Q1
			local Q3 = (t[math.round(medQ3)] + t[math.round(medQ3)-1])/2
			print("passed3",Q1,Q3)
			return Q3 - Q1
		end
	end
end


function makeTable()
	local t = {}
	local tableSize = math.random(1,100)
	for i = 1, tableSize do
		table.insert(t,math.random(1,10))
		i += 1
	end
	
	table.sort(t,function(a,b)
		return a < b
	end)
	print(t)
	return t
end

local newTable = makeTable()

print(IQR(newTable))

I don’t even need to find the IQR of a table, idek why I created the script.