Saurus
Saurus

Reputation: 79

Writing a median function in R

I have been tasked to write my own median function in R, without using the built-in median function. If the numbers are odd; calculate the two middle values, as is usual concerning the median value. Something i probably could do in Java, but I struggle with some of the syntax in

R Code:

list1 <- c(7, 24, 9, 42, 12, 88, 91, 131, 47, 71)

sorted=list1[order(list1)]
sorted
n = length(sorted)
n
if(n%2==0) # problem here, implementing mod() and the rest of logic.

Upvotes: 0

Views: 8187

Answers (4)

fabla
fabla

Reputation: 1816

A short function that does the trick:

my_median <- function(x){
   # Order Vector ascending
   x <- sort(x)
   # For even lenght average the value of the surrounding numbers
   if((length(x) %% 2) == 0){
    return((x[length(x)/2] + x[length(x)/2 + 1]) / 2)
   }
   # For uneven lenght just take the value thats right in the center
   else{
     return(x[(length(x)/2) + 0.5])
   }
}

Check to see if it returns desired outcomes:

my_median(list1) 
44.5
median(list1)
44.5
#
list2 <- c(1,4,5,90,18)
my_median(list2)
5
median(list2)
5

Upvotes: 1

James
James

Reputation: 66834

You don't need to test for evenness, you can just create a sequence from half the length plus one, using floor and ceiling as appriopriate:

x <- rnorm(100)
y <- rnorm(101)

my_median <- function(x)
{
mid <- seq(floor((length(x)+1)/2),ceiling((length(x)+1)/2))
mean(sort(x)[mid])
}

my_median(x)
[1] 0.1682606
median(x)
[1] 0.1682606
my_median(y)
[1] 0.2473015
median(y)
[1] 0.2473015

Upvotes: 0

ThomasIsCoding
ThomasIsCoding

Reputation: 101247

Here is a self-written function mymedian:

mymedian <- function(lst) {
  n <- length(lst)
  s <- sort(lst)
  ifelse(n%%2==1,s[(n+1)/2],mean(s[n/2+0:1]))
}

Example

list1 <- c(7, 24, 9, 42, 12, 88, 91, 131, 47, 71)
list2 <- c(7, 24, 9, 42, 12, 88, 91, 131, 47)
mymedian(list1)
mymedian(list2)

such that

> mymedian(list1)
[1] 44.5

> mymedian(list2)
[1] 42

Upvotes: 3

ErrorJordan
ErrorJordan

Reputation: 641

I believe this should get you the median you're looking for:

homemade_median <- function(vec){
  sorted <- sort(vec)
  n <- length(sorted)
  if(n %% 2 == 0){
    mid <- sorted[c(floor(n/2),floor(n/2)+1)]
    med <- sum(mid)/2
  } else {
    med <- sorted[ceiling(n/2)]
  }
  med
}

homemade_median(list1)
median(list1) # for comparison

Upvotes: 2

Related Questions